0x0. nop-127pt
这题主要考察的是 Linux 下的反调试技巧。
先运行观察下行为,提示输入 flag,随便输入后程序退出。
拖进 IDA 看代码,main
函数一上来进入 sub_804865B
,这是第一处反调试。

Linux 下,程序无调试器运行时,环境变量_会是程序自身路径,有调试器时,这个环境变量会被调试器改变,可以据此区分程序是否被调试。
回到 main
,把下图两条指令 nop
掉,去掉这个反调试。

接着,程序提示输入 flag,将其作为整数存入全局变量 dword_804A038
。在块 loc_80486E7
和 loc_80486F5
中,将其值加 1 并存回。
块 loc_80486F5
中调用函数 sub_804857B
,这是第二处反调试。函数中,首先布置好系统调用所需的参数和调用号。

然后跳到 loc_80485A0
进行系统调用。

查表知 Linux x86 的系统调用号 0x20 是 ptrace
,这个系统调用以 C 语言写出相当于 ptrace(0,0,1,0);
这是个典型的反调试。在上图中,根据 ptrace
的返回值决定是否进入错误的分支。将 jl short loc_80485AE
这条指令 nop
掉,去掉这个反调试。
回到 main
,在块 loc_804870D
和 loc_8048701
中,再次将全局变量 dword_804A038
加 1 并存回。接着调用 sub_80485C4
,在此函数中布置系统调用号 0x14,然后跳到 loc_80485F8
进行系统调用,相当于 C 语言 getpid();
,作用是获取当前进程 PID。


同时 loc_80485F8
还布置了下一个系统调用号 0x40,接着,跳到 loc_804860B
进行系统调用,相当于 C 语言 getppid();
,作用是获取父进程 PID。

同时 loc_804860B
还布置了下一个系统调用号 0x93,接着,跳到 loc_804861E
进行系统调用,参数是刚才获取的当前进程 PID,相当于 C 语言 getsid(getpid());
,作用是获取当前进程 SID。

上图将 getsid(getpid())
与 getppid()
比较,不相等则进入错误分支。将 jnz short loc_8048634
这条指令 nop
掉,去掉这个反调试。
回到 main
,在 loc_8048727
和 loc_804871B
将全局变量 dword_804A038
加上 0xCCCCCCCC 并存回。接着调用 sub_80485C4
,即刚才的第二处反调试,因为已经处理,所以不管它,接着往下看。
在 loc_804873B
中将全局变量 dword_804A038
加 1 并存回,调用 sub_8048753
。此函数中又调用 sub_8048691
,进入查看。

sub_8048691
的功能是把 eax
所指向的内存地址存储的字节替换为 0x90(即 nop
指令)。前面操作全局变量 dword_804A038
时以 eax
为中介,所以 eax
里现在存的就是 dword_804A038
的值。但是这个函数有什么意义呢?现在还不清楚,先接着往后看。
回到 sub_8048753
,将 eax
加 1 后再次调用 sub_8048691
。所以,这一块代码应该是把内存某个位置连续的两个字节 nop
掉了。
接着,程序直接跳入了错误分支,与此同时 IDA 中可以看到正确分支就在附近,且如果不经过 0x8048765 处的 jmp
,就可以进入正确分支。

这时就明白了上面 sub_8048691
的功能,它给了我们 nop
掉 0x8048765 的 jmp
的能力,这个 jmp
正好占两字节。
到此,程序就分析完了。流程整理如下(不考虑反调试):
输入 flag,为一个整数
将 flag+1
将 flag+1
将 flag+0xCCCCCCCC
将 flag+1
将 flag 所指向的内存地址连续的两字节
nop
掉
我们希望把 0x8048765 的 jmp
替换为 nop
,所以可以列出方程:
|
|
注意是对 32 位整数运算,所以结果要对 0x1 0000 0000 取模。解得 flag 为 0x3B37BA96 ,即十进制 993507990。

最后按 flag 格式,提交 \[ flag\{993507990\} \]
0x1. 逆向-rev-232pt
涉及指令 gadget 的题,本来这种技术在 pwn 里很常见,现在搬到了 re 里…
先看 main
,很简单,要求两个参数,然后 sub_400D19
验证第二个参数,返回值为 1 则正确。

重点看 sub_400D19
,只有三条指令,将变量 data
的地址传送给 rsp
,然后返回到这个地址。

显然 data
是代码了,进去看。

这里有许多指针,每个都指向一个 gadget,依次执行这些 gadget 进行运算,最后产生结果。
因为指令被打散成 gadget,分析起来很麻烦,再加上这种进行一堆运算,最后根据返回值进入正确或错误分支的题一般可以尝试下走捷径,所以先偷懒试下符号执行。
IDA 里看到正确分支在 0x400481,编写 angr 脚本如下。之所以知道 flag 是 21 位,是因为换题目之前的旧题里透露了 flag 位数,定长一点也行,angr 一样能解出来。

运行,等几秒就得到 flag 了。

0x2. 总结
太菜了,twice 那题栈溢出都没做出来… 另外等一个 rev 正经解法的 writeup。