[UNCTF 2020]Reverse方向

re_checkin

0x00 逆向分析

在这里插入图片描述
一个简单的字符串比较

0x01 动态调试

在这里插入图片描述

上个断点,本地windows调试
在这里插入图片描述
随便输入点东西
在这里插入图片描述
双击Str2,选中第一个按一下A,flag就出来了
在这里插入图片描述

babypy

0x00 下载文件

在这里插入图片描述
下载完解压发现是一个exe文件和一个txt文件
在这里插入图片描述txt是不明加密结果,一堆0 1 3组成的数。
exe打不开,不知是什么东西。

0x01 反编译

百度查到,这个exe文件是pyc文件捆绑编译。需要使用pyinstxtractor脚本工具。
贴一下连接:https://github.com/extremecoders-re/pyinstxtractor
用法:把pyinstxtractor.py放到exe同目录文件夹下
在该文件夹下打开cmd
输入python2 pyinstxtractor.py babypy.exe
(注:我电脑是python2 3共存,如只有一个python则python2改为python即可)
然后会得到一个文件夹
在这里插入图片描述
在这里插入图片描述
文件夹里就是py的编译文件pyc了。
pyc编译成py文件需要uncompyle6(百度安装)
但是反编译发生了报错

百度发现pyinstxtractor在反编译exe文件后,会删除pyc文件的前8位信息。
解决方法是在pyc文件前加上struct文件的前8位。
我试过了,莫得用。
可能是我用的pyinstxtractor版本问题,它似乎给所有pyc文件自动补上了8位文件头,但是貌似不太正确。
于是我尝试着用struct文件的前8位去覆盖pyc文件的前8位。成功了。

以下界面使用软件010Editor
struct.pyc的文件头:在这里插入图片描述
babypy.pyc的文件头
在这里插入图片描述
用struct前8位覆盖babypy的前8位以后的babypy
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到反编译出的babypy.py

0x02 逆向分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)]
# Warning: this version of Python has problems handling the Python 3 "byte" type in constants properly.

# Embedded file name: babypy.py
import os, libnum, binascii
flag = 'unctf{*******************}'
x = libnum.s2n(flag)

def gen(x):
y = abs(x)
while 1:
if y > 0:
yield y % 2
y = y >> 1
else:
if x == 0:
yield 0


l = [i for i in gen(x)]
l.reverse()
f = '%d' * len(l) % tuple(l)
a = binascii.b2a_hex(f.encode())
b = int(a, 16)
c = hex(b)[2:]
print(c)
os.system('pause')
# okay decompiling babypy.pyc

加密顺序:
字符串转十进制int
将十进制数从右往左一位一位转换成二进制存入l列表
l列表逆序
将l列表转换成字符串
把列表l转换成bytes然后再转成16进制
转成十进制int
转成16进制string

然后就用到一开始给的tip:
在这里插入图片描述
所以这里的0 1 3其实是0x30 = ‘0’ 0x31 = ‘1’
知道原理就可以写脚本了

0x03 脚本解密

1
2
3
4
5
6
7
8
9
10
11
import libnum,binascii

ciphertext = '313131303130313031313031313130303131303030313130313131303130303031313030313130303131313130313130313031303130303031313031303030303130303030303030313131303130303031303131313131303131303130303130313131303031313031303131313131303131313030313030313130303130313031313030303031303031313030303130303131303030313031313131303031303130313131313130313130303031313030313130303030303031313030303030303131303030313031313131313031'
a = binascii.a2b_hex(ciphertext)
a = a.decode(encoding='utf-8')
print(a)
b = str(a)[::-1]
print(b)
c = int(a,2)
print(c)
print(libnum.n2s(c))

运行得到flag:unctf{Th@t_is_rea11y_c001}

反编译

解包,pyc转py步骤和上题一样。
得到的py文件直接运行即可得到flag
在这里插入图片描述

easyMaze

0x00 逆向分析

在这里插入图片描述
输入的字符串被存入Dst中,然后经过两个函数的判断,如果返回都为1则通过。

sub_401757

在这里插入图片描述
很容易读懂(猜到)要求输入的flag开头要为unctf{,结尾要为}。

sub_40161A

在这里插入图片描述
很容易看出是wasd移动,然后因为是10*v3所以大概率地图的宽度是10,然后如果走到D或者0就会直接return 0所以不能走。
最后如果走到S会break,然后return 1。所以S是终点。

0x01 找地图

在这里插入图片描述
很容易看出Dst就是地图的指针,但是直接跳过去看不到内容,尝试动态调试。

但是会发现这里有一个函数在这里插入图片描述
在这里插入图片描述
这个函数会检测是否是debug状态,即反动调。
但是这个很简单,只要改一下if的判断就能绕过
在这里插入图片描述
在这里插入图片描述
可以看到这里的if中加了一个!即不是debug才会执行反动调。
然后就可以快乐动调了:
在这里插入图片描述
下断点
在这里插入图片描述
要先通过第一个函数的检测所以要以unctf{开头,}结尾
运行。
在这里插入图片描述
可以看到Dst指向一个地址,jump过去看看
在这里插入图片描述
获得地图
复制进脚本看一下地图长啥样

1
2
3
4
5
6
7
8
9
10
11
a = "Oo00oD00SD0oooo0Doooo0D0oD0o00ooooo00o00oD0D0oooooo00o0o0o0ooDoooooDDDo00o00oooooD0D0000oDoooooooooD"
a = a.replace('D',' ')
a = a.replace('0',' ')
count = 1
for i in a:
print(i,end = "")
if count%10 == 0:
print("\n",end = "")
count += 1

#dsdddssaaaassssssddddddddwwaawawwddwwwdw

我顺便把地图里的D和0都删了
输出结果是这样的:
在这里插入图片描述
从左上角走到S,路径也在代码里了。
所以flag就是unctf{dsdddssaaaassssssddddddddwwaawawwddwwwdw}

ezRust

本以为是一个非常困难恶心人的汇编题目,但是仔细分析发现逻辑还是十分简单的。

0x00 逆向分析

在这里插入图片描述
F12就会发现有类似flag的字符串,双击过去
在这里插入图片描述
跳转到引用函数
在这里插入图片描述
发现它只是把这个字符串的字符用指针取不同位置的不同长度字符重组的。
从上往下读可以得到flag:unctf{Rust_more_safety_than_YLB’s_Platform}