CTF逆向-[watevrCTF 2019]esreveR-看似复杂流程,发现核心逻辑,按64位架构导出栈中和寄存器中的值得到结果
来源:https://buuoj.cn/
内容:
附件:https://pan.baidu.com/s/1CL9SAiLOT6Y1aPuVq1tYOw?pwd=hsd5 提取码:hsd5
答案:watevr{esrever_reversed_youtube.com/watch?v=I8ijb4Zee5E}
总体思路
用ida打开发现默认是按com加载,但该文件是elf文件,故选按elf加载
发现大量函数,但是都不涉及input,暂时忽略
找到判断flag的地方,发现是逐个判断数值是否相等,导出栈中所有的值得到结果
导出寄存器中的值,与上一步结果拼接
详细步骤
-
查看文件内容
- 使用ida64打开,按elf加载
-
发现几个函数,逐个点进去查看
-
这些函数的计算都比较简单,但是都和v_input没有关系,关注到输入和判断的地方。
-
发现是通过
f_encode
函数判断以后就直接输出了 -
进入
f_encode
发现有个f_check
函数,此时v_input作为最后一个参数传入,继续跟进。 -
这里直接对v_input与每个参数进行值判断,则我们在这里下一个断点。
-
其运行到断点出以后栈中是各个参数的值,寄存器中是前几个参数,分别是
rdi
、rsi
、rdx
、rcx
、r8
、r9
-
这里是因为在x64汇编架构中
-
X64汇编
64位CPU有16个通用寄存器,寄存器存放8个字节数据,它们名称分别为:
rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp
r8,r9,r10,r11,r12,r13,r14,r15
32位使用栈帧来作为传递的参数的保存位置,而64位使用寄存器,分别用rdi,rsi,rdx,rcx,r8,r9作为第1-6个参数。rax作为返回值。
64位没有栈帧的指针,32位用ebp作为栈帧指针,64位取消了这个设定,rbp作为通用寄存器使用。
rax 作为函数返回值使用。
rsp 栈指针寄存器,指向栈顶
rdi,rsi,rdx,rcx,r8,r9 用作函数参数,依次对应第1参数,第2参数。。。
rbx,rbp,r12,r13,r14,r15 用作数据存储,遵循被调用者使用规则,简单说就是随便用,调用子函数之前要备份它,以防他被修改。
r10,r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值。
-
-
我们复制栈顶的值
07FFDEB2D83F8
并在汇编窗口中按g键跳转到这个地方,按*键将此处前足够多个(比如500个)转换为数组,得到栈的值- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xY2p0amv-1651905271987)(https://raw.githubusercontent.com/serfend/res.image.reference/main/image-20220507142527231.png)]
-
按shift+e导出这些值,使用python进行处理
-
data = '7B0000000000000065000000000000007300000000000000720000000000000065000000000000007600000000000000650000000000000072000000000000005F00000000000000720000000000000065000000000000007600000000000000650000000000000072000000000000007300000000000000650000000000000064000000000000005F0000000000000079000000000000006F00000000000000750000000000000074000000000000007500000000000000620000000000000065000000000000002E0000000000000063000000000000006F000000000000006D000000000000002F00000000000000770000000000000061000000000000007400000000000000630000000000000068000000000000003F0000000000000076000000000000003D000000000000004900000000000000380000000000000069000000000000006A00000000000000620000000000000034000000000000005A0000000000000065000000000000006500000000000000350000000000000045000000000000007D00000000000000A0872DEBFD7F0000C291139AFFFFFFFFD5B3BF5C000000002D68F2C7FFFFFFFFC20000000000000016867D4200000000A0872DEBFD7F0000160000000000000005AF41000000000077000000000000006100000000000000740000000000000065000000' data = bytearray.fromhex(data) data = data.replace(b'\0',b'') print(data) // bytearray(b'{esrever_reversed_youtube.com/watch?v=I8ijb4Zee5E}\xa0\x87-\xeb\xfd\x7f\xc2\x91\x13\x9a\xff\xff\xff\xff\xd5\xb3\xbf\\-h\xf2\xc7\xff\xff\xff\xff\xc2\x16\x86}B\xa0\x87-\xeb\xfd\x7f\x16\x05\xafAwate')
-
复制中其中的
{esrever_reversed_youtube.com/watch?v=I8ijb4Zee5E}
作为flag后部分 -
再拼接寄存器中的值 di si dx cx r8 r9 ,77 61 74 65 76 72 = ‘watevr’
-
-
故最后答案为 watevr{esrever_reversed_youtube.com/watch?v=I8ijb4Zee5E}
其他文档
- CTF逆向-常用的逆向工具 提取码:pnbt
- B站教程中国某省队CTF集训(逆向工程部分)
- 中国某省队CTF集训(逆向工程部分)(已授权)(一)
- 基础加密方式例如
XXTEA
、Base64
换表 - Python库
Z3
方程式、不定式等的约束求解
- 基础的假跳转花指令(脏字节)
- 非自然程序流程
- 扁平化程序控制流
- OLLVM程序流程(虚拟机壳) 很难一般不考
- ida里面按
X
键跟踪,寻找所有Ty
为w
的引用(即类型是写入的),通常就是关键位置
- 中国某省队CTF集训(逆向工程部分)(已授权)(二)
- ollydb动调去壳,upx为例子
- python的逆向和自定义虚拟指令
- 使用pycdc 提取码:dorr 解密python编译的exe或者pyc
- 逐条去解析用py字典手动实现的指令调用
- C++编译的程序的逆向
- 中国某省队CTF集训(逆向工程部分)(已授权)(三)
- 简单模运算加密
- base58 寻找一下特别大的数,这种数通常是算法的标识,或者ida7.7版本以上自带的
find crypt
插件ctrl+alt+f
- 常见的关键位置是有新的内存分配的地方通常是关键地方,或者函数中间突然return的地方也是
- 迷宫题 注意绘制出来就好
- 动调题
- 注意观察会执行的反调试分支,例如出现
int 3
,需要跳过去
- 注意观察会执行的反调试分支,例如出现
- 基本知识
更多CTF逆向题通用性做法和常用工具下载参考该博文内容:CTF逆向Reverse题的玩法
相关逆向CTF题
-
Python
-
远程调试汇编
-
流程控制
-
逆向思维
-
安卓
-
虚拟机
-
反调试和SMC
-
加密
-
花指令
-
流程混淆的扁平化处理