感觉逆向越来越有意思了
[GWCTF 2019]xxor
链接: https://buuoj.cn/challenges#[GWCTF 2019]xxor
ELF 64
IDA中 main 函数反编译结果如下
1 | __int64 __fastcall main(__int64 a1, char **a2, char **a3) |
第一个for循环用于输入
第二个for循环用于加密
函数sub_400770用于校验加密结果
1 | signed __int64 __fastcall sub_400770(_DWORD *a1) |
可以根据已知条件还原出加密的结果
1 | __int64 __fastcall sub_400686(unsigned int *a1, _DWORD *a2) |
这里unsigned int a1=&dword_601078
两者都是四字节的数据
1 | v3 = *a1; |
然而这两句代码就将dword_601078
变成了一个数组
一开始有点云里雾里的
但是观察dword_601078
的text view
时
1 | .bss:0000000000601078 dword_601078 dd ? ; DATA XREF: main+E6↑w |
便可以理解dword_601078[1]
就是dword_60107C
写python脚本时, 为了保证与C语言相同的运行效果, 变量在进行计算时都最好加一个&0xffffffff
网上看到有用ctypes写的, 但是感觉调用起来好麻烦
1 | #!/usr/bin/env python3 |
flag{re_is_great!}
[HDCTF2019]Maze
链接: https://buuoj.cn/challenges#[HDCTF2019]Maze
EXE 32
UPX脱壳
IDA打开后左侧函数列表中找不到 main 函数
在text view中可以看到_main函数的标识
1 | jnz short near ptr loc_40102E+1 |
但是这两行明显存在问题, 应该是花指令
第一行patch为nop
(右键->Keypatch
->Patcher
)
第二行转为数据之后把db 0E8h
patch为nop
然后选中 main 函数部分转为函数就能顺利地查看反编译代码了
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
- dword_408078 = 7
- dword_40807C = 0
接着在数据区浏览可以看到定义迷宫形状的数据
1 | *******+********* ****** **** ******* **F****** ************** |
因为字符串长度为70, 则可以考虑几种因数组合
1 | *******+**->dword_408078+ |
那么可以得到flag
flag{ssaaasaassdddw}
[FlareOn4]IgniteMe
链接: https://buuoj.cn/challenges#[FlareOn4]IgniteMe
EXE 32
IDA中 start 函数反编译结果如下
1 | void __noreturn start() |
函数sub_4010F0功能应该为读取文件并将内容(flag)存放于byte_403078
函数sub_401050则实现了对于flag的加密
1 | signed int sub_401050() |
密文结果存放于byte_403000
1 | byte_403000 = [ |
1 | __int16 sub_401000() |
v4的值来自于函数sub_401000
__ROL4__
用于循环左移四位
手动计算可以得到结果0x00380004
由于返回值的数据类型是unsigned __int16
, 则会返回低16位的数据
即0x0004
1 | #!/usr/bin/env python3 |
flag{R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com}
[BJDCTF2020]BJD hamburger competition
链接: https://buuoj.cn/challenges#[BJDCTF2020]BJD hamburger competition
.NET
使用dnSpy
打开Assembly-CSharp.dll
在左侧程序集资源管理器中依次打开
Assembly-CSharp
->-
->ButtonSpawnFruit
->Spawn()
可以看到如下代码
1 | Init.secret ^= 127; |
其中有一个坑, 函数MD5的代码如下所示
1 | public static string Md5(string str) |
返回的结果为MD5前20位
且ToString("X2")
将字符串转为大写
1 | #!/usr/bin/env python3 |
flag{B8C37E33DEFDE51CF91E}
[MRCTF2020]Xor
链接: https://buuoj.cn/challenges#[MRCTF2020]Xor
EXE 32
IDA中不能直接找到关于flag加密的函数
根据程序所输出的字符串Give Me Your Flag String:
在IDA中进行搜索(Search
->sequence of bytes
)
找到对应的数据部分, 然后找到调用该数据的函数
1 | int sub_401090() |
1 | #!/usr/bin/env python3 |
flag{@_R3@1ly_E2_R3verse!}
[MRCTF2020]hello_world_go
链接: https://buuoj.cn/challenges#[MRCTF2020]hello_world_go
ELF 64
IDA中 main_main 函数反编译结果如下
1 | __int64 __fastcall main_main(__int64 a1, __int64 a2) |
函数runtime_cmpstring
看着有些问题
跟进unk_4D3C58
得到flag
flag{hello_world_gogogo}
[WUSTCTF2020]level3
链接: https://buuoj.cn/challenges#[WUSTCTF2020]level3
ELF 64
IDA中 main 函数反编译结果如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
看到一段Base64编码, 但是不能解码得到flag
跟进函数base64_encode
没有看到明显的加密函数或替换表函数, 逆向Base64编码的具体步骤有些麻烦, 这里采用了曲线救国的方案
1 | ./attachment |
通过这一步的操作我们可以得到三个字符的替换关系, 那么只要更改输入内容并且重复次数足够多, 就能够fuzz出完整的替换关系
1 | #!/usr/bin/env python3 |
flag{Base64_is_the_start_of_reverse}
[WUSTCTF2020]Cr0ssfun
链接: https://buuoj.cn/challenges#[WUSTCTF2020]Cr0ssfun
ELF 64
IDA中 main 函数反编译结果如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
跟进函数Check
以及之后的函数即可得到flag
flag{cpp_@nd_r3verse_@re_fun}
[[FlareOn6]Overlong
链接: https://buuoj.cn/challenges#[FlareOn6]Overlong
EXE 32
IDA中 start 函数反编译结果如下
1 | int __stdcall start(int a1, int a2, int a3, int a4) |
unk_402008
的长度为175
, 即0xAF
但是所限定的长度为28
所以flag应该就在后面的内容之中
静调看代码的话过于复杂, 这题应该用动调
一开始打算把push 1Ch
Patch成push AFh
但是发现要在IDA中改成AF
的话会强制转成dword
, 然后多余的三个'\x00'
字节会占用掉后面一条汇编代码的空间
用OD调试, 在直接修改汇编代码时同样出现了与IDA中相同的问题
所以可以在数据被PUSH入栈之后再对栈内的数据进行修改
当然你完全可以拿一个十六进制编辑器直接修改字节码
flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}
crackMe
链接: https://buuoj.cn/challenges#crackMe
EXE 32
IDA中 _wmain 函数反编译结果如下
1 | int wmain() |
- 函数sub_401090用于通过输入的username, 来生成byte_416050
- 代码块loc_4011A0被插入了花指令
1 | .text:004011EA jbe near ptr loc_4011EA+2 |
nop掉这两行就能转为函数了
- 函数sub_401830用于校验所输入的用户名与密码是否正确
1 | bool __cdecl sub_401830(int a1, const char *a2) |
这个函数使用了PEB来进行反调试, 具体情况可以看这个文章
第一部分的while循环用于将密码转为十六进制字符串得到v14
第二部分的while循环用于加密
加密结果v16
需要经过函数sub_401470的校验, 要求的v16="dbappsec"
*(&v16 + v5) = byte_416050[(unsigned __int8)(v7 + v12)] ^ *(&v14 + v4);
v16
已知, 只需要得到byte_416050
, 但是用于加密的byte_416050
会在加密之前进行一系列的操作
可以使用动调的方法, 得到真正用于加密的数据
1 | .text:00401B3E xor eax, ecx |
Debugger中在这条语句下断点, ECX
即为所需的数据
1 | #!/usr/bin/env python3 |
flag{43097184c2f63f7bcabdadf21b693c8e}
[ACTF新生赛2020]Oruga
链接: https://buuoj.cn/challenges#[ACTF新生赛2020]Oruga
ELF 64
IDA中 main 函数反编译结果如下
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
函数sub_78A用于校验flag
1 | _BOOL8 __fastcall sub_78A(__int64 a1) |
byte_201020
如下
1 | _416050 = [ |
结合上面的代码可以知道是个迷宫题
特别之处在于会按照给定方向一直走, 直到遇到非0数据
flag{MEWEMEWJMEWJM}
[FlareOn3]Challenge1
链接: https://buuoj.cn/challenges#[FlareOn3]Challenge1
EXE 32
IDA中 _main 函数反编译结果如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
跟进函数sub_401260可以看到一个Base64表
Base64替换
1 | #!/usr/bin/env python3 |
flag{sh00ting_phish_in_a_barrel@flare-on.com}
firmware
链接: https://buuoj.cn/challenges#firmware
Firmware
1 | binwalk 51475f91-7b90-41dd-81a3-8b82df4f29d0.bin |
题目中所提到的Backdoor应该就在Squashfs filesystem
中
binwalk分离文件, 但是unsquashfs命令不能解压缩这个文件系统
需要使用firmware-mod-kit
https://github.com/rampageX/firmware-mod-kit/
用g++10编译源码的时候有点问题, 需要修改下源码
mksquashfs.c
中某些函数或变量没有加static
造成的重复定义问题- 某部分代码少包含了
<sys/sysmacros.h>
1 | ./unsquashfs_all.sh 120200.squashfs |
在tmp中找到backdoor
IDA中 initConnection 函数反编译结果如下
1 | bool initConnection() |
可以得到C2
1 | echo -n "echo.byethost51.com:36667" | md5sum |
flag{33a422c45d551ac6e4756f59812a954b}
[Zer0pts2020]easy strcmp
链接: https://buuoj.cn/challenges#[Zer0pts2020]easy strcmp
ELF 64
IDA中 main 函数反编译结果如下
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
看到一个可疑的函数
1 | __int64 __fastcall sub_6EA(__int64 a1, __int64 a2) |
虽然main函数中没有调用这个函数, 在IDA中在这个函数下断点, 可以看到输入的内容被进行运算, 大概是hook
1 | qword_201060 = [0x0, 0x410A4335494A0942, 0x0B0EF2F50BE619F0, 0x4F0A3A064A35282B,0x0] |
IDA中qword_201060
所展示出的数据为大端
而字符串"zer0pts{********CENSORED********}"
为小端
所以需要在计算之前要先转为大端
1 | #!/usr/bin/env python3 |
flag{l3ts_m4k3_4_DETOUR_t0d4y}
[ACTF新生赛2020]Universe_final_answer
链接: https://buuoj.cn/challenges#[ACTF新生赛2020]Universe_final_answer
ELF 64
IDA中 main 函数反编译结果如下
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
跟进sub_860
1 | bool __fastcall sub_860(char *a1) |
sage解线性方程即可
1 | #!/usr/bin/env python3 |
得到key="F0uRTy_7w@"
, 在程序中输入key即可得到flag
flag{F0uRTy_7w@_42}
[UTCTF2020]basic-re
链接: https://buuoj.cn/challenges#[UTCTF2020]basic-re
ELF 64
数据部分即可看到flag
flag{str1ngs_1s_y0ur_fr13nd}
EOF