REVERSE-PRACTICE-CTFSHOW-6

真的是签到

附件是一个压缩包,解压需要密码,但是题目没有给到解压密码
实际上是压缩包伪加密,将如图橙色处原本的字节0x09改为0x00,保存后即可解压出文件
qiandao-break
解压得到一个32位的exe,加了ASP壳,用工具脱壳
qiandao-shell
脱壳后的exe丢进ida,仍然得不到重要的信息,上x32dbg调试
exe丢进x32dbg,x32dbg会预先设置一个断点,在"断点"窗口可以看到
我们先按一下F9,来到x32dbg预先设置的断点处,如图所示
qiandao-debug
经过多次调试发现,程序在执行如图所示处的"jmp _unpacked.401280"指令后就会要求我们输入,这里下一个断点
qiandao-debug
F8跟进"jmp _unpacked.401280",在如图所示处的"call _unpacked.401150",按F7步入
qiandao-debug
然后一路F8,来到如下图所示"call _unpacked.4012F0"处,按F7步入
qiandao-debug
可以看到0x4012F0处开始的函数中包含"try again"的字符串,0x401334处调用了scanf
猜测这里应该就是main函数
qiandao-debug
用插件Scylla,dump出程序,丢进ida分析,其中一些函数名已对照x32dbg进行了修改
主要的逻辑为,将输入中的各个字符与下标异或,然后反转输入,再让输入与已知的res比较
qiandao-ida
python脚本好像打印不出中文
下面是c脚本,得到flag

#include<stdio.h>
int main()
{
	int res[18]= { 0x6c,0x2f,0x30,0x31,0x32,0x33,0xffffffb6,0xffffffbf,0xffffffa0,0xffffffcf,0x7c,0x71,0x6a,0x6c,0x70,0x64,0x75,0x63 };
	for (int i = 17; i>=0; i--)
	{
		res[i] ^= 17-i;
		printf("%c", res[i]);
	}
	printf("\n");
	return 0;
}
// ctfshow{签到?????}

批量生产的伪劣产品

apk文件,jadx-gui打开
先看AndroidManifest.xml文件,找到两个关键的类:“appinventor.ai_QA629A242D5E83EFA948B9020CD35CB60.checkme.a"和”.Screen1"
apk-manifest
在"appinventor.ai_QA629A242D5E83EFA948B9020CD35CB60.checkme.a"类中直接找到flag
apk-flag

来一个派森

.py文件打包成的exe,用"pyinstxtractor.py"解包
uncompyle6反编译checkme.pyc文件
(可反编译的前提是checkme.pyc文件与struct.pyc文件前12个字节相同)
b58encode的逻辑为,先对输入进行base58变换,变换后再与下标异或,最后和check比较

def b58encode(tmp: str) -> str:
    tmp = list(map(ord, tmp))
    temp = tmp[0]
    base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
    for i in range(len(tmp) - 1):
        temp = temp * 256 + tmp[(i + 1)]

    tmp = []
    while 1:
        tmp.insert(0, temp % 58)
        temp = temp // 58
        if temp == 0:
            break

    temp = ''
    for i in tmp:
        temp += base58[i]

    tmp = []
    for i in range(len(temp)):
        tmp.append(chr(ord(temp[i]) ^ i))

    check = [
     'A', '5', 'q', 'O', 'g', 'q', 'd', '\x7f', '[', '\x7f', 's', '{', 'G', 'A', 'x', '`', 'D', '@', 'K', 'c', '-', 'c', ' ', 'G', '+', '+', '|', 'x', '}', 'J', 'h', '\\', 'l']
    if tmp == check:
        return 1
    else:
        return 0


flag = input('输入flag:')
if b58encode(flag):
    print('you win')
else:
    print('try again')

逆向逻辑为,将check各元素与下标异或,再解base58

def b58decode(tmp:str) -> str:
	import binascii
	base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
	temp = []
	for i in tmp:
		temp.append(base58.index(i))
	tmp = temp[0]
	for i in range(len(temp)-1):
		tmp = tmp * 58 + temp[i+1]
	return binascii.unhexlify(hex(tmp)[2:].encode("utf-8")).decode("UTF-8")
check = ['A', '5', 'q', 'O', 'g', 'q', 'd', '\x7f', '[', '\x7f', 's', '{', 'G', 'A', 'x', '`', 'D', '@', 'K', 'c', '-', 'c', ' ', 'G', '+', '+', '|', 'x', '}', 'J', 'h', '\\', 'l']
for i in range(len(check)):
    check[i]=chr(ord(check[i])^i)
print(b58decode("".join(c for c in check)))
# ctfshow{zhe_bu_shi_flag}

snake

.py文件打包成的exe,用"pyinstxtractor.py"解包
uncompyle6反编译snake.pyc文件

# -*- coding:utf-8 -*-
import hashlib, sys, random, time
maze = [
 [
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [
  1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [
  0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0],
 [
  0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
 [
  0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0],
 [
  0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],
 [
  0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0],
 [
  0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9]]
s = str(input()) # 读取输入
seed = time.time()
random.seed(seed)
random.seed(random.randint(0, 999999))
maze[1][1] = random.randint(987, 1000)
maze[3][4] = random.randint(345, 356)
maze[7][7] = random.randint(107, 116)
maze[11][8] = random.randint(833, 856)
for i in range(12):
    for j in range(12):
        tmp = 12 * i + j
        if maze[i][j] == 0:
            maze[i][j] = 3456 + tmp
            continue
        if tmp % 4 == 0:
            random.seed(maze[1][1])
            for cnt in range(tmp):
                random.randint(0, 999)

            maze[i][j] = random.randint(0, 999)
        elif tmp % 4 == 1:
            random.seed(maze[3][4])
            for cnt in range(tmp):
                random.randint(555, 1234)

            maze[i][j] = random.randint(555, 1234)
        elif tmp % 4 == 2:
            random.seed(maze[7][7])
            for cnt in range(tmp):
                random.randint(777, 888)

            maze[i][j] = random.randint(777, 888)
        elif tmp % 4 == 3:
            random.seed(maze[11][8])
            for cnt in range(tmp):
                random.randint(369, 777)

            maze[i][j] = random.randint(369, 777)

maze[11][11] = 9
# 以上都是对maze的变换
if len(s) != 56:
    sys.exit(-1)
idx1 = 0
idx2 = 0
# 走迷宫 wsad代表上下左右 从左上角[0,0]开始
for i in s:
    if i == 'w':
        idx1 -= 1
    else:
        if i == 's':
            idx1 += 1
        else:
            if i == 'a':
                idx2 -= 1
            else:
                if i == 'd':
                    idx2 += 1
    # 每走一步后的坐标在maze中的值要大于等于0且小于等于1234
    if not 0 <= maze[idx1][idx2] <= 1234:
        print('Where are you going?')
        sys.exit(2)
# 走到右下角[11,11]成功
if maze[idx1][idx2] != 9:
    print('You lost in the maze!')
# 从maze中取值构成result
result = ''
for xx in maze:
    for xxx in xx:
        result += str(xxx)

hash_res = hashlib.sha256(result.encode('latin-1')).hexdigest()
print(hash_res)
# 由于maze中含有随机数,所以即使迷宫路线正确,也可能得不到flag,需要多次尝试
if hash_res == 'f1793dcf5ad3858512b944ac34413725a27c63e25618858231e88b9686466b00':
    flag1 = str(maze[1][1]) + str(maze[7][7]) + str(maze[11][8]) + str(maze[3][4])
    flag2 = hashlib.sha256(s.encode('latin-1')).hexdigest()
    flag = flag2[::-1] + flag1[::-1]
    final_flag = hashlib.sha256(flag.encode('latin-1')).hexdigest()
    print('flag{' + final_flag[0:32] + '}')

已知迷宫路线的约束为,“每走一步后的坐标在maze中的值要大于等于0且小于等于1234”
提取出源代码对maze的变换,再将maze中大于等于0且小于等于1234的值改为1,其余改为0
打印maze,即可得到正确的迷宫路线

import hashlib, sys, random, time
maze = [
 [
  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [
  1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
 [
  0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0],
 [
  0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
 [
  0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0],
 [
  0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0],
 [
  0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0],
 [
  0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0],
 [
  0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
 [
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9]]
seed = time.time()
random.seed(seed)
random.seed(random.randint(0, 999999))
maze[1][1] = random.randint(987, 1000)
maze[3][4] = random.randint(345, 356)
maze[7][7] = random.randint(107, 116)
maze[11][8] = random.randint(833, 856)
for i in range(12):
    for j in range(12):
        tmp = 12 * i + j
        if maze[i][j] == 0:
            maze[i][j] = 3456 + tmp
            continue
        if tmp % 4 == 0:
            random.seed(maze[1][1])
            for cnt in range(tmp):
                random.randint(0, 999)

            maze[i][j] = random.randint(0, 999)
        elif tmp % 4 == 1:
            random.seed(maze[3][4])
            for cnt in range(tmp):
                random.randint(555, 1234)

            maze[i][j] = random.randint(555, 1234)
        elif tmp % 4 == 2:
            random.seed(maze[7][7])
            for cnt in range(tmp):
                random.randint(777, 888)

            maze[i][j] = random.randint(777, 888)
        elif tmp % 4 == 3:
            random.seed(maze[11][8])
            for cnt in range(tmp):
                random.randint(369, 777)

            maze[i][j] = random.randint(369, 777)

maze[11][11] = 9

for i in range(12):
    for j in range(12):
        if maze[i][j]>=0 and maze[i][j]<=1234:
            maze[i][j]=1
        else:
            maze[i][j]=0
    print(maze[i])
# [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# [1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0]
# [0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0]
# [0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0]
# [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0]
# [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
# [0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0]
# [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]
# [0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0]
# [0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0]
# [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
# [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
# sdsdsddwwddsdddssaaassddddssasaaaaawwwaaasssdsdsdddddddd

爆破一下,能不能得到flag全看运气

from itertools import *
import subprocess
while(1):
    flag="sdsdsddwwddsdddssaaassddddssasaaaaawwwaaasssdsdsdddddddd"
    p = subprocess.Popen(["D:\\ctfdownloadfiles\\snake.exe"], stdin=subprocess.PIPE, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
    p.stdin.write(flag)
    p.stdin.close()
    out = p.stdout.read()
    p.stdout.close()
    if "flag" in out:
        print(out)
        exit()
# f1793dcf5ad3858512b944ac34413725a27c63e25618858231e88b9686466b00
# flag{e1df25dac4906584fe2d6f155b60e233}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P1umH0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值