shellcode - 有长度限制的 shellcode 解法
shellcode
shellcode 是一段用于利用软件漏洞而执行的代码,shellcode 为 16 进制之机械码,以其经常让攻击者获得 shell 而得名。shellcode 常常使用机器语言编写。
程序分析
题目来源:第七届浙江省大学生网络与信息安全竞赛预赛
checksec
逆向分析
程序的功能很直接,执行输入的一段 shellcode,但是有 0xa 的长度限制。
并且存在 memmem 函数,检查输入的内容,使用 IDA 继续查看
unk_203D 的内容,发现是出题人禁止了 syscall
的机器码。
动态调试

在程序执行 shellcode 之后,观察寄存器和栈的情况。当时比赛时发现
r8 中存有 syscall
指令的地址,我的一个想法是控制寄存器 rax, rdi,
rsi, rdx 执行系统调用 read。
1 | mov rsi,rax |
不过这样的长度已经超出 0xa 的限制了。后面我又想了很久,想继续利用
r8 跳转到某个 main 函数上的指令,调试发现从
r8 到一个 main
函数的地址需要减去三位十六进制数,也就是说操作数占据了 shellcode 中 0x4
的长度了。哎,结果我就这样忽视了 rsp 上的
<main+0132>,一直到比赛结束。
攻击流程
这里的思路是白夜学长提供的。
调整传参寄存器,控制程序流程
ELF 中的 read 函数参数如下

栈中的数据如下
第一段 shellcode
1 | pop rdx; 返回地址出栈 |
将程序跳转到 main 函数的 call _read 前:

执行 shellcode
没有了读入限制后,直接使用 pwntool 生成的 shellcode 即可。
Exploit
1 | from pwn import * |
小结
这回的省赛属于是坐了四小时大牢了。每道题目或者是在现实实践中,自然是与之前遇到的情况会有不同。因此对程序动态运行中的各种状态应该敏锐一些,例如栈、寄存器,可能会有发现。