[toc]
辣鸡复现一下ACTF 的逆向题,学一波逆向的基本操作
0x00 How2b64decode
基本信息
- pe
- 64bit
- 好像没有壳
跑跑看
应该也是要输入个东西,那东西就是flag
给了提示,应该有用到base64
IDA看看
没有直接给main函数,看来要自己找
应该是这个
改个名字
输入的东西经过一个 sub_401550
函数处理,成了 QUNURntCYXNlNjRfaXNfYV90cmFkaW9uYWxfY29kaW5nX2FsZ29yaXRobX0=
这样才算输入成功
很明显这段字符时base64加密了
解码看看
直接得到了flag
那就不需要继续分析了
1 | ACTF{Base64_is_a_tradional_coding_algorithm} |
0x01 How2Reverse
基本信息
- pe
- 64bit
- 好像还是没有壳
跑跑看
应该真的是入门吧
IDA看看
直接找到flag
1 | ACTF{Welcome_to_Reversing_World} |
0x02 How2debug
基本信息
- pe
- 64bit
- 没有壳
跑一跑
IDA看看
main 还是得自己找,改个名
用到了函数指针
调用了 unk_403020 指向的函数,如果返回的不是0,那就成功了
函数的参数 v1,就是输入的东西
调试看看,看看那个函数里面到底干了什么,然后就能确定要输入怎样的v1了
按一下 F5,得到 反编译的 c 代码
双击 unk_403020
只有 函数才能被转成 c 代码
按一下 p ,以下的指令就被转成函数的形式
从而可以 F5 看C 了
1 | __int64 __fastcall sub_403020(__int64 a1) |
分析一波
输入的东西,全给了 v2,而 v2[k] ^= 0x61 后,要和 v3[k] 相等
写个脚本,就能把 flag 跑出来了
1 | v3 = [i for i in range(39)] |
1 | ACTF{SMC_Protect_Need_Your_Debug_Skill} |
还可以用 idapython
从 0x40302F 开始的指令的第二个 operand 就是需要的 v3[x]
1 | from idc import * |
1 | ACTF{SMC_Protect_Need_Your_Debug_Skill} |
0x03 How2idaMacroCode
基本信息
- 64bit
跑跑看
老样子,直接输入 flag
IDA看看
看看main
然后看到这里
貌似是代码混淆
稍微整理一下代码
1 | __int64 __fastcall sub_4015F9(const char *a1) |
直接写脚本解
1 | v5 = [i for i in range(13)] |
1 | ACTF{sometimes_ida_is_not_reliable_READ_THE_ASM} |
0x03 How2idaXref
基本信息
- 64bit
跑跑
直接输入个东西
IDA看看
找到 有关的函数
1 | int check() |
输入的东西 Str 要和 unk_403020 中的内容相等
用 idapython 写个脚本
1 | import idc |
1 | ACTF{how_do_you_find_this_attribute_constructor_function} |
0x04 How2idapython
基本信息
- 64bit
跑跑看
也是输入flag
IDA看看
main 函数
分析一波函数 sub_4015D4
Buf1 里面的东西要和 unk_405020 里的东西相等
看看汇编,从图中位置开始,就一直有规律地重复同一模式的动作
直接写个 idapython 脚本
1 | import idc |
1 | ACTF{idapython_is_a_efftive_tool_for_reversing} |
0x05 Threads
基本信息
- 64bit
跑一跑
提示是多线程的程序
IDA看看
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
不出所料,c++ 写的
找到一个 reader_thread_func 和一个 checker_thread_func
看看 checker
比较重要的代码
1 | v1 = (const char *)usr_input::get_c_str(usr); |
而main 函数中
1 | if ( (unsigned __int8)usr_input::get_mark(usr) ) |
所以至少不能触发 usr_input::set_mark(usr, 0);
直接写idapython脚本
1 | import idc |
1 | ACTF{mult_thread_is_hard_to_control} |
0x06 pyde
基本信息
- 64bit
跑跑看
直接让输入东西,啥提示也没有
直接 IDA打开,看了看 strings ,应该是python 写的
现在就反编译
先从 main.exe 中提取模块
1 | python pyinstxtractor.py main.exe |
找找看关键模块
找到了 struct 模块,这是内置模块
找到了个 main 模块
用 winhex 看看
这是 struct 的
1 | 420D0D0A000000007079693010010000 |
看看main 的
里面有 flag 这样的字样,可以确定这个文件来自 main.py
但是这个文件缺少了一行内容
在文件开头添上
1 | 420D0D0A000000007079693010010000 |
现在可以了,保存下来,文件名改为 main.pyc
1 | uncompyle6.exe -o main.py .\main.pyc |
得到源码
1 | # uncompyle6 version 3.7.4 |
用到了一个复杂的加密算法
稍微改写一下
直接先将 en_flag 进行 base64decode
然后进行 AES decrypt
得到 flag
1 | actf{Thi5_7s_A3S_CBC} |
0x07 Bytecode
竟然是个 txt 文件
内容是 python 的 bytecode 的反汇编结果
1 | 1 0 LOAD_CONST 0 (0) |
直接硬逆,还原成py 文件
1 | import hashlib |
可以看到,这是一个生成 flag 的程序
直接写脚本,把flag 跑出来
1 | import hashlib |
part1 是一堆字符串,part2 是个数字,范围为 0~999999
最终跑出flag
1 | actf{Pyth0n_byt3c0de_114514} |
0x08 Daisy
基本信息
- 64bit
跑一跑
有一个输入点
IDA看看
看看main
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
没法反编译 sub_4016E9
看看汇编
可以看到,从 0x40172 开始的指令都是游离在外的,并非哪个函数的指令,而那个
jmp short near ptr loc_401707+5
最终只是让 rsp 指向的地址里面的值增一了,十分离谱,怀疑这段代码是花指令,啥用没有
直接改了
1 | .text:000000000040171F jmp short near ptr loc_401707+5 |
改成
1 | .text:000000000040171A nop |
然后就能成功反编译了
1 | __int64 __fastcall sub_4016E9(const char *a1) |
1 | __int64 __fastcall sub_40161E(int a1, int a2, int a3) |
猜测是个迷宫问题
1 | a --> v8-- |
去把地图拿出来分析
1 | #***#*#**######*#**#******#**########**********###**********########**************#****#**###****##*****#*####****#*****#####****##********#*******#*#*******#**#******#**#*********#*######**#*******#D |
显然这是个三维的迷宫
1 | array([[['#', '*', '*', '*', '#', '*', '#', '*', '*', '#'], |
行走序列
1 | 下右右右右上飞下下左左左左下遁右右右右右右上上上飞右右右右遁下下飞下下遁左左左飞下下遁左左左左左左左飞下下下遁右右上飞右右右右右遁下右飞右 |
写脚本
1 | l = u"下右右右右上飞下下左左左左下遁右右右右右右上上上飞右右右右遁下下飞下下遁左左左飞下下遁左左左左左左左飞下下下遁右右上飞右右右右右遁下右飞右" |
得到flag
1 | ACTF{sddddwlssaaaasuddddddwwwlddddusslssuaaalssuaaaaaaalsssuddwldddddusdld} |