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 * |
小结
这回的省赛属于是坐了四小时大牢了。每道题目或者是在现实实践中,自然是与之前遇到的情况会有不同。因此对程序动态运行中的各种状态应该敏锐一些,例如栈、寄存器,可能会有发现。