shellcode_tips(持续更新版)
本帖将持续记录Linux下shellcode的一些编写技巧,包括长度的优化,特定限制的绕过,shellcode的绕过
鉴于本人汇编基础较弱,目前在持续学习中,如有不正确或含糊的表述,欢迎联系我与我讨论!
Shellcode的编写在二进制安全中是不可避免的,当回归到汇编这种较为底层的语言去实现一些特定功能时,我们往往会发现不只有一种方法能够实现我们的目的。这里我就拿64位中实现 read(0,0x404000,0x50)来举例子:
1.最直接的传值syscall
1 | section .text |
2.利用栈传值
1 | section .text |
3.切换到32位操作模式,用中断门调用read操作
1 | section .text |
可以看到汇编的灵活性是非常大的,当然在实战中对于shellcode的编写往往存在着各种各样的限制,比如长度有限,shellcode分割,沙箱保护,特定字符检测等等。通过汇编的灵活性,在某些情况下能够绕过重重难关从而达到我们的目的。
优化shellcode的长度
列一下常见的64位指令长度
栈的操作
- pop/push reg 1字节
- push imm 1+立即数的字节数(1/2/4)
赋值/计算操作
- Inc/dec reg 字节
- mov/add reg64,reg64 2字节
- mov/add reg, [reg] 3字节
- mov/add reg, imm32 5字节
- mov/add reg64, imm32 7字节
- mov/add reg64, imm64 10字节
程序流
- ret 1字节
- syscall 2字节
- jmp等跳转 short 2字节
- jmp/call rel32 5字节
经过对比栈操作与赋值的指令,发现当使用 push imm + pop reg 替代 `mov reg, imm会使汇编更加精简。同时在jmp到shellcode前的上下文也是我们需要观察的,对于栈,寄存器上的数据没准我们就能利用上来减少shellcode的长度。
例子待补充
shellcode分块
有些情景下我们不具备写入连续内容的能力,那么需要将我们写入的shellcode拼凑到一起从而形成一段完整的执行链。这里需要用到相对跳转,也就是jmp $+0x8:这段汇编的意思为跳转到当前eip+0x8的地址上去执行,其汇编拆解便是EB 08
EB: 短跳转操作码08: 相对偏移量(从下条指令开始计算)
在知道对应内存块的相对位移的情况下(通常来说只要位于同一内存段偏移一般固定)在每个内存块尾部加上这么一条相对跳转指令即可
题目试例:
西电mini的checkin题
题目的大致执行流程是向三块堆空间中分别读取0x18数据,然后将堆空间变成可执行的,并跳到第一个堆块空间,题目开了沙箱ban掉execve系统调用。

非常直球的题目,要在三段堆空间构造orw的shellcode。动调查看三个堆块之间的相对偏移(这个是固定的),在每一段shellcode末尾加上jmp $x即可
poc脚本
1 | from pwn import * |
绕过特定字符的检查
有些情况下,题目会对于你输入的shellcode进行某些检查,我们需要调整我们的shellcode进行检测绕过。
有些题目会先strlen(inputshellcode)得到shellcode长度,再根据长度进行检测。在这种情况下我们在shellcode开头构造存在\x00的汇编(前提是读取shellcode时没有\x00截断),这样检测实际上检测的内容是\x00前面的内容。而后面的shellcode就可以自由发挥啦
例子待补充
突破沙箱的限制
在题目中遇到沙箱ban掉一些特定的系统调用的情况在ctf中屡见不鲜,沙箱的规则制定相对自由,不同题目可以不同组合ban,记录一下目前接触到的突破沙箱构造法
等价函数替换
一系列可能用到的等价替换函数:
使用
execveat代替execve使用
openat代替open使用
readv/writev代替read/write使用
mmap2代替mmaporw中,使用
sendfile,代替read/write
切换指令模式绕过黑名单
当seccomp-tool工具发现沙箱中没有判断指令模式并且采取的是黑名单ban的模式,那么我们可以通过长返回retf的方式来实现架构切换。因为32位与64位同一个系统调用的调用号是不同的。
注意构造retf的栈布局:64——>32位shellcode模版
1 | xor esp, esp |
纯ascii码shellcode
这部分我还没碰到到过,这里有篇还没啃的blog:https://nets.ec/Ascii_shellcode
这部分感觉技巧性很强,多用xor,inc,dec等精细到字的操作,对于shellcode水平要求很高,我如果真遇到应该也是试试工具了(雾