bugku pwn
pwn2
- checksec发现什么保护都没有,拖进ida看看.
 main函数1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12int __cdecl main(int argc, const char **argv, const char **envp) 
 {
 char s; // [rsp+0h] [rbp-30h]
 memset(&s, 0, 0x30uLL);
 setvbuf(stdout, 0LL, 2, 0LL);
 setvbuf(stdin, 0LL, 1, 0LL);
 puts("say something?");
 read(0, &s, 0x100uLL);
 puts("oh,that's so boring!");
 return 0;
 }
get_shell_函数:
| 1 | int get_shell_() | 
应该是让返回地址覆盖成getshell地址,
gdb看一下偏移
| 1 | gdb | 
rbp前四位为bAA1,算一下偏移
到rbp偏移为48,向上8字节是父函数rbp,所以偏移56覆盖到返回地址,get_shell_地址为
exp如下:
| 1 | from pwn import * | 
pwn4
- checksec跑一下,并没有什么壳或保护.
 ida64位打开一下,虽然有一个read函数,可以输入30字节,10字节的缓冲区可以制造溢出.但是没有系统函数可以调用.shift+f12查看有没有可疑字符串,然后在字符串上按x查看引用他的地方,找到了一个system函数.1 
 2
 3
 4int sub_400751() 
 {
 return system("ok~you find me,but you can't get my shell'");
 }
但是system函数里面的字符串并不是我们想要的'/bin/sh',尝试用ROPgadget去搜索,命令为ROPgadget --binary pwn4 --string '/bin/sh',搜索无果。。。再回到IDA中检测字符串
| 1 | .data:0000000000601100 00000022 C 4985y9y()DY)*YFG8yas08d976s08d7$0 | 
- 发现了一个 - $0,- $0在linux中为为shell或shell脚本的名称。- system()会调用- fork()产生子进程,由子进程来调用- /bin/sh -c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。所以如果将- $0作为- system的参数,能达到传入- '/bin/sh'一样的效果。
- 有了 - system函数和- $0作为参数,就可以进行溢出了。
- 还有要注意的就是64位程序和32位程序的传参方式不一样,32位的函数调用使用栈传参,64位的函数调用使用寄存器传参,分别用 - rdi、- rsi、- rdx、- rcx、- r8、- r9来传递参数(参数个数小于7的时候)。
我们利用ROPgadget工具进行查找,得到pop rdi ; ret和$0的地址,system的地址直接在IDA中查看.
| 1 | ROPgadget --binary pwn4 --only 'pop|ret' | 
首先先填充缓冲区,大小为0x10,然后覆盖rbp,8个字节,传入pop rdi;ret的地址和$0,将栈中$0的地址弹出,存入rdi作为参数,在传入system地址进行调用。
下面是脚本:
| 1 | from pwn import * |