Skip to content

Latest commit

 

History

History
23 lines (12 loc) · 1.6 KB

File metadata and controls

23 lines (12 loc) · 1.6 KB

超精准的宇宙射线模拟器

分析程序

反编译之后可以看出,程序初始化时将自己的代码段设置为了可写。

main 函数中,程序读入一个地址 addr 和一个整数 bit,然后把 addr 地址的第 bit 位翻转,然后程序退出。

我们只能翻转一个 bit,但只翻转一个 bit 不足以让我们获得任意命令执行的能力。所以这道题的关键在于,我们要利用翻转的第一个 bit 来创造出一个循环,使得我们可以翻转更多的 bit。可以翻转更多 bit 之后,我们就可以把 shellcode 写入代码段中,然后想办法跳转过去。

至于如何创造出循环,懒人做法是在代码段的地址范围内穷举所有地址,直到找到一个翻转后程序可以第二次读取我们输入(而不是崩溃或者正常退出)的位置。

我并没有去穷举,而是直接看汇编。

0x401295 处是一个 call 指令,调用了 exit() 函数退出程序,如果让它不要退出,就可以到达输出 "Invalid input" 的地方,然后跳转到输入的地方,形成循环。

这个 call 指令调用了 0x4010c0 这个函数,字节码是 E8 26 FE FF FF,如果翻转 26 的第 6 个 bit,就可以把字节码变成 E8 66 FE FF FF,即跳转到 0x401100,这里的逻辑是直接返回。

然后,我们利用这个循环来不断把 shellcode 覆盖 0x4010c0 也就是原来的 exit() 函数。

最后,我们把之前翻转那个 bit 改回去,程序跳转到 0x4010c0,我们的 shellcode 会被执行,就可以拿到 shell 了。

最终的解题代码