Day 03 shellcode之:板子做pwn,易如反掌
shellcraft杂谈
1. 什么时候考虑写 shellcode?
在 pwn 题里,是否写 shellcode一般要看是否能满足以下条件:
能把可控字节放进一块可执行内存:如程序把输入放到栈/堆且该段 可执行(NX 关闭);或能把内存权限改为可执行(有mprotect
, mmap
函数)。
所以写入shellcode前要先检查一下,确保shellcode写入到可执行内存中。
若以上条件不满足,更适合探索其他路线。
2. shellcraft
的三个常用组件
shellcraft
是pwntools
里的一个模块(板子),会根据体系结构生成汇编片段。以下均以x64架构为例。
1 | context.arch = 'amd64' |
2.1 shellcraft.sh()
- 作用:构造执行
execve("/bin/sh", 0, 0)
的 shellcode。 - 适用:允许 59 号系统调用、无 seccomp 限制。
- 用法示例:
1 | shellcode = shellcraft.sh() # execve("/bin/sh", NULL, NULL) |
2.2 shellcraft.pushstr()
- 作用:把一个以
\x00
结尾的字符串压到栈上,再作为系统调用参数。 - 典型写法:
1 | shellcode = shellcraft.pushstr(b"/bin/sh\x00") # 把字符串压栈,rsp 指向它 |
- 对应汇编:
1 | push 0x0068732f6e69622f ; "/bin/sh\x00" |
2.3 shellcraft.cat("./flag")
- 作用:禁用59号execve()系统调用时,一条龙 打开文件→读→写到 stdout,非常适合作为 orw 的快捷实现(open->read->write)。
- 用法示例:
1 | sc = shellcraft.cat("./flag") # open("./flag", O); read(); write(1, buf, 0x50) |
- 优点:不用自己管缓冲区循环,能快速验证 orw 思路。
- 注意:若沙箱禁了
open
而只放行openat
,需要改用shellcraft.openat(...)
或手写 syscall。
3. orw(open/read/write)汇编实现:
前置芝士:😋
- 关于文件描述符(句柄):
- 文件描述符是一个非负整数,用于标识一个打开的文件或其他输入输出资源。
- 每个进程都有自己的文件描述符表,记录着所有打开文件的信息。
- 文件描述符从 0 开始分配,通常 0、1、2 分别对应标准输入、标准输出和标准错误输出。
- 关于库函数:
open(file,mode)
: 以mode模式打开file文件(带路径),返回文件描述符。
mode: 0->只读、1->只写、2->读写。read(fd,buf,count)
: 从文件描述符 fd 读取数据到 buf,最多读取 count 字节。write(fd,buf,count)
: 向文件描述符 fd 写入 buf 中的数据,最多写 count 字节。
orw实现:
当 59(
execve
)被禁,/bin/sh
起不来,就走文件读写:- open / openat 打开
./flag
(或题目指定路径),获得 fd。 - read 把内容读到可控缓冲区(通常是栈上,rsp)。
- write 把缓冲区写到
stdout
(fd=1)返回给我们。
- open / openat 打开
exp:
1 | shellcode =asm(shellcraft.pushstr("./flag")+"mov rdi,rsp;push 2;pop rax;xor rsi,rsi;syscall")#open |
因为不同题目的限制不一样,shellcraft可能不适用,所以建议各位大爹手写汇编🥰
4. 如果常用的被禁了😭
open
被禁但 openat
(257) 可用,使用shellcraft.openat
read
被禁了用sendfile
,把 flag
直接送到 stdout
。
5. 调试与实战小贴士
先本地跑:用
process()
+gdb.attach()
;看 seccomp(如题给seccomp-tools
的输出)到底放了哪些 syscall。RWX 获取:NX 开着就用 ROP 先
mmap
/mprotect
极简 loader:若输入长度受限,先丢一个 “读更多字节到某地址再跳转” 的小 loader,然后把完整 orw shellcode 流进去。
6. 小结(拿题就能套)
- 能
execve
→shellcraft.sh()
,最快起 shell。 - 禁 59 → 走 orw:优先
shellcraft.cat("./flag")
;open
被禁就换openat
;再不行找 已存在 fd 或sendfile
。 - 熟悉
pushstr
的用法,你就能自由拼接口参数,快速写出自定义 syscall 组合。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.