VNCTF2022 wp复现
BabyMaze
直接去看原文吧:转自: https://ppppz.net/2022/02/08/BabyMaze/
CM1
gda打开apk.(jadx看不到FileUtils源码)
加载了 classes.dex, 传入FileUtils 和 进行了某些操作然后就变成了ooo。
在 assets中找到 ooo 导出。根据源码用vn2022循环异或 1024为一组。
生成新的dex文件。用jadx打开。
很明显XXTEA。直接解密。。
k = [0x50703448, 0x4E565F59, 0x21465443, 0x4F764F21]
res = [0x6CA42744, 0xC948EEAE, 0x0B26C84A, 0xD861543C, 0xAE634757, 0xB92F6878, 0x2100C7C6, 0xD9D4262A, 0x5CFE71C4, 0x32B376B5, 0x96202B87]
CM狗
参考链接贴上,慢慢复现
https://blog.shi1011.cn/ctf/2162#cm狗
https://blog.csdn.net/qq_52974719/article/details/123100965#t2
https://blog.csdn.net/m0_51911432/article/details/122914413#t4
http://s0rry.cn/archives/vnctf2022re-fu-xian#toc-head-6
struct REG
{
_DWORD R[21]; // 21个寄存器
};
struct func
{
void *call; // call 地址
vm *ptr; // vm
};
struct vm
{
REG reg; // 寄存器
_DWORD Memory[1000];
_DWORD rip; // VM下一个执行地址
_DWORD index;
void *data; // opcode
func *func[100];
_QWORD isExit;
};
下图是offset 值,看一下转的对不对。
init中定义了操作数对应的函数
整理后如下
func *__usercall main___ptr_MzVm__init@<rax>(vm *a1) {
a1->func[0] = &init;
a1->func[1] = main___ptr_MzVm__init_func2;
a1->func[2] = main___ptr_MzVm__init_func3;
a1->func[3] = main___ptr_MzVm__init_func4;
a1->func[4] = main___ptr_MzVm__init_func5;
a1->func[5] = main___ptr_MzVm__init_func6;
a1->func[6] = main___ptr_MzVm__init_func7;
a1->func[7] = main___ptr_MzVm__init_func8;
a1->func[8] = main___ptr_MzVm__init_func9;
a1->func[9] = main___ptr_MzVm__init_func10;
a1->func[10] = main___ptr_MzVm__init_func11;
a1->func[11] = main___ptr_MzVm__init_func12;
a1->func[12] = main___ptr_MzVm__init_func13;
a1->func[13] = main___ptr_MzVm__init_func14;
a1->func[14] = main___ptr_MzVm__init_func15;
a1->func[15] = main___ptr_MzVm__init_func16;
a1->func[16] = main___ptr_MzVm__init_func17;
a1->func[17] = main___ptr_MzVm__init_func18;
a1->func[98] = main___ptr_MzVm__init_func19;
a1->func[99] = main___ptr_MzVm__init_func20;
}
右击 a1 转为 struct格式
void __golang main___ptr_MzVm__run(vm *a1)
{
vm *v1; // rbx
_DWORD *data; // rsi
unsigned __int64 rip; // rax
unsigned __int64 op1; // rdi
unsigned __int64 v5; // r8
unsigned int op2; // er8
unsigned __int64 v7; // rax
unsigned int op3; // esi
__int64 v9; // [rsp+0h] [rbp-18h]
void *retaddr; // [rsp+18h] [rbp+0h] BYREF
while ( (unsigned __int64)&retaddr <= *(_QWORD *)(*(_QWORD *)NtCurrentTeb()->NtTib.ArbitraryUserPointer + 16LL) )
runtime_morestack_noctxt();
v1 = a1;
while ( !LOBYTE(v1->isExit) )
{
data = v1->data;
rip = (unsigned int)v1->rip;
if ( rip >= 0xBB8 )
runtime_panicIndex(v9);
op1 = (unsigned int)data[rip];
v5 = (unsigned int)(rip + 1);
if ( v5 >= 0xBB8 )
runtime_panicIndex(v9);
op2 = data[v5];
v7 = (unsigned int)(rip + 2);
if ( v7 >= 0xBB8 )
runtime_panicIndex(v9);
op3 = data[v7];
if ( op1 >= 0x64 )
runtime_panicIndex(v9);
v9 = __PAIR64__(op3, op2);
((void (*)(void))v1->func[op1]->call)();
v1 = a1;
a1->rip += 3;
}
}
双击data来到opcode,每轮使用3个操作数。在ida中这样设置一下看清每一轮。
op=1, func2
HIDWORD测试,小端序 高位
unsigned char v[] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
QWORD *a = (QWORD *) v;
printf("%llX", HIDWORD(*a)); // 88776655
ptr->reg.R[(unsigned int)a1] = HIDWORD(a1); //低位取索引,高位取值 R[index]= value
op=2, func3
v2->reg.R[(unsigned int)a1] = v2->reg.R[HIDWORD(a1)];
R[low] = R[hi] , 通过索引赋值到R数组中
op=5, func6
Memory[result] = reg.R[a1];
op=6, func7
reg.R[a1] = Memory[ptr->index];
ptr->index++;
op=7, func8
R[low] += R[hi]
op=7, func9
R[low] -= R[hi]
func11
R[low] *= R[hi]
func12
R[low] ^= R[hi]
func13
result = (unsigned int)(3 * v2->reg.R[a1]);
v2->rip = result;
=>
rip = 3 * reg.R[a1]
=> jmp reg.R[a1]
func15
result = (unsigned int)ptr->reg.R[HIDWORD(a1)];
if ( (_DWORD)result != ptr->reg.R[(unsigned int)a1] ) ; R[HI] != R[LO]
{
result = (unsigned int)(3 * ptr->reg.R[19]); ; JMP R[19]
ptr->rip = result;
}
op=0x61, func18 输出字符
scanf
op=0x62, func19 输出字符
fmt_Fprint
op=0x63, func20
注释里标了
vmquit
脚本
from string import printable
_m = list(printable.encode())
_m.remove(10)
_m.remove(13)
_hex = lambda _d: f"0x{_d:02x}" if _d > 15 else _d
_chr = lambda _v: hex(_v) if _v not in _m else f"'{chr(_v)}'"
maps = {
0x1: "nop",
0x2: "mov R[{num}], {right} ; {ch}",
0x3: "mov R[{num}], R[{right}]",
0x4: "mov R[{num}], Memory[{right}]",
0x5: "mov Memory[num] R[{right}]",
0x6: "push R[{num}]",
0x7: "pop R[{num}]",
0x8: "add R[{num}], R[{right}]",
0x9: "dec R[{num}], R[{right}]",
0xa: "div R[{num}], R[{right}]",
0xb: "mul R[{num}], R[{right}]",
0xc: "xor R[{num}], R[{right}]",
0xd: "jmp R[{num}]",
0xe: "cmp R[{num}] R[{right}], je R[19]",
0xf: "cmp R[{num}] R[{right}], jne R[19]",
0x10: "cmp R[{num}] R[{right}], jb R[19]",
0x11: "cmp R[{num}] R[{right}], ja R[19]",
0x62: "getchar R[{num}]",
0x63: "putchar R[{num}]",
0x64: "vm quit"
}
data = [0, 0, 0, 0, 0, 0, 0x1, 0, 0x57, 0x62, 0, 0, 0x1, 0, 0x65, 0x62, 0, 0, 0x1, 0, 0x6C, 0x62, 0, 0,
0x1, 0, 0x63, 0x62, 0, 0, 0x1, 0, 0x6F, 0x62, 0, 0, 0x1, 0, 0x6D, 0x62, 0, 0, 0x1, 0, 0x65, 0x62, 0, 0,
0x1, 0, 0x20, 0x62, 0, 0, 0x1, 0, 0x74, 0x62, 0, 0, 0x1, 0, 0x6F, 0x62, 0, 0, 0x1, 0, 0x20, 0x62, 0, 0,
0x1, 0, 0x56, 0x62, 0, 0, 0x1, 0, 0x4E, 0x62, 0, 0, 0x1, 0, 0x43, 0x62, 0, 0, 0x1, 0, 0x54, 0x62, 0, 0,
0x1, 0, 0x46, 0x62, 0, 0, 0x1, 0, 0x32, 0x62, 0, 0, 0x1, 0, 0x30, 0x62, 0, 0, 0x1, 0, 0x32, 0x62, 0, 0,
0x1, 0, 0x32, 0x62, 0, 0, 0x1, 0, 0x21, 0x62, 0, 0, 0x1, 0, 0xA, 0x62, 0, 0, 0x1, 0, 0x69, 0x62, 0, 0,
0x1, 0, 0x6E, 0x62, 0, 0, 0x1, 0, 0x70, 0x62, 0, 0, 0x1, 0, 0x75, 0x62, 0, 0, 0x1, 0, 0x74, 0x62, 0, 0,
0x1, 0, 0x20, 0x62, 0, 0, 0x1, 0, 0x66, 0x62, 0, 0, 0x1, 0, 0x6C, 0x62, 0, 0, 0x1, 0, 0x61, 0x62, 0, 0,
0x1, 0, 0x67, 0x62, 0, 0, 0x1, 0, 0x3A, 0x62, 0, 0, 0x1, 0, 0xA, 0x62, 0, 0, 0x1, 0x13, 0x49, 0x1, 0x3, 0,
0x1, 0x1, 0x2B, 0x1, 0x2, 0x1, 0x61, 0, 0, 0x5, 0, 0, 0x8, 0x1, 0x2, 0xE, 0x1, 0x3, 0x1, 0, 0, 0x5, 0, 0,
0, 0, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0x6, 0, 0x6, 0, 0, 0x7, 0x6, 0,
0x2, 0, 0x6, 0xA, 0, 0x5, 0x2, 0x6, 0, 0x6, 0, 0, 0x7, 0x6, 0, 0x2, 0, 0x6, 0xA, 0, 0x5, 0x2, 0x6, 0,
0x6, 0, 0, 0x7, 0x6, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0x7, 0, 0x6, 0, 0,
0x7, 0x7, 0, 0x2, 0, 0x7, 0xA, 0, 0x5, 0x2, 0x7, 0, 0x6, 0, 0, 0x7, 0x7, 0, 0x2, 0, 0x7, 0xA, 0, 0x5,
0x2, 0x7, 0, 0x6, 0, 0, 0x7, 0x7, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0x8, 0,
0x6, 0, 0, 0x7, 0x8, 0, 0x2, 0, 0x8, 0xA, 0, 0x5, 0x2, 0x8, 0, 0x6, 0, 0, 0x7, 0x8, 0, 0x2, 0, 0x8,
0xA, 0, 0x5, 0x2, 0x8, 0, 0x6, 0, 0, 0x7, 0x8, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5,
0x2, 0x9, 0, 0x6, 0, 0, 0x7, 0x9, 0, 0x2, 0, 0x9, 0xA, 0, 0x5, 0x2, 0x9, 0, 0x6, 0, 0, 0x7, 0x9, 0,
0x2, 0, 0x9, 0xA, 0, 0x5, 0x2, 0x9, 0, 0x6, 0, 0, 0x7, 0x9, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100,
0xA, 0, 0x5, 0x2, 0xA, 0, 0x6, 0, 0, 0x7, 0xA, 0, 0x2, 0, 0xA, 0xA, 0, 0x5, 0x2, 0xA, 0, 0x6, 0, 0,
0x7, 0xA, 0, 0x2, 0, 0xA, 0xA, 0, 0x5, 0x2, 0xA, 0, 0x6, 0, 0, 0x7, 0xA, 0, 0, 0, 0, 0x6, 0, 0,
0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0xB, 0, 0x6, 0, 0, 0x7, 0xB, 0, 0x2, 0, 0xB, 0xA, 0, 0x5, 0x2, 0xB, 0,
0x6, 0, 0, 0x7, 0xB, 0, 0x2, 0, 0xB, 0xA, 0, 0x5, 0x2, 0xB, 0, 0x6, 0, 0, 0x7, 0xB, 0, 0, 0, 0,
0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0xC, 0, 0x6, 0, 0, 0x7, 0xC, 0, 0x2, 0, 0xC, 0xA, 0, 0x5,
0x2, 0xC, 0, 0x6, 0, 0, 0x7, 0xC, 0, 0x2, 0, 0xC, 0xA, 0, 0x5, 0x2, 0xC, 0, 0x6, 0, 0, 0x7, 0xC, 0,
0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0xD, 0, 0x6, 0, 0, 0x7, 0xD, 0, 0x2, 0, 0xD,
0xA, 0, 0x5, 0x2, 0xD, 0, 0x6, 0, 0, 0x7, 0xD, 0, 0x2, 0, 0xD, 0xA, 0, 0x5, 0x2, 0xD, 0, 0x6, 0, 0,
0x7, 0xD, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0xE, 0, 0x6, 0, 0, 0x7, 0xE, 0,
0x2, 0, 0xE, 0xA, 0, 0x5, 0x2, 0xE, 0, 0x6, 0, 0, 0x7, 0xE, 0, 0x2, 0, 0xE, 0xA, 0, 0x5, 0x2, 0xE, 0,
0x6, 0, 0, 0x7, 0xE, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0xF, 0, 0x6, 0, 0,
0x7, 0xF, 0, 0x2, 0, 0xF, 0xA, 0, 0x5, 0x2, 0xF, 0, 0x6, 0, 0, 0x7, 0xF, 0, 0x2, 0, 0xF, 0xA, 0, 0x5,
0x2, 0xF, 0, 0x6, 0, 0, 0x7, 0xF, 0, 0, 0, 0, 0x6, 0, 0, 0x1, 0x5, 0x100, 0xA, 0, 0x5, 0x2, 0x10, 0,
0x6, 0, 0, 0x7, 0x10, 0, 0x2, 0, 0x10, 0xA, 0, 0x5, 0x2, 0x10, 0, 0x6, 0, 0, 0x7, 0x10, 0, 0x2, 0, 0x10,
0xA, 0, 0x5, 0x2, 0x10, 0, 0x6, 0, 0, 0x7, 0x10, 0, 0, 0, 0, 0x5, 0x6, 0, 0x5, 0x7, 0, 0x5, 0x8, 0,
0x5, 0x9, 0, 0x5, 0xA, 0, 0x5, 0xB, 0, 0x5, 0xC, 0, 0x5, 0xD, 0, 0x5, 0xE, 0, 0x5, 0xF, 0, 0x5, 0x10, 0,
0x6, 0x1, 0, 0x6, 0x2, 0, 0x1, 0x14, 0x11C, 0x1, 0, 0x154, 0xC, 0, 0, 0x1, 0, 0xE8D1D5DF, 0x1, 0x13, 0x183, 0x1, 0x14, 0x153,
0xE, 0x1, 0, 0x1, 0, 0xF5E3C114, 0xE, 0x2, 0, 0x6, 0x1, 0, 0x6, 0x2, 0, 0x1, 0x14, 0x127, 0x1, 0, 0x154, 0xC, 0, 0,
0x1, 0, 0x228EC216, 0x1, 0x13, 0x183, 0x1, 0x14, 0x153, 0xE, 0x1, 0, 0x1, 0, 0x89D45A61, 0xE, 0x2, 0, 0x6, 0x1, 0, 0x6, 0x2, 0,
0x1, 0x14, 0x132, 0x1, 0, 0x154, 0xC, 0, 0, 0x1, 0, 0x655B8F69, 0x1, 0x13, 0x183, 0x1, 0x14, 0x153, 0xE, 0x1, 0, 0x1, 0, 0x2484A07A,
0xE, 0x2, 0, 0x6, 0x1, 0, 0x6, 0x2, 0, 0x1, 0x14, 0x13D, 0x1, 0, 0x154, 0xC, 0, 0, 0x1, 0, 0xD9E5E7F8, 0x1, 0x13, 0x183,
0x1, 0x14, 0x153, 0xE, 0x1, 0, 0x1, 0, 0x3A441532, 0xE, 0x2, 0, 0x6, 0x1, 0, 0x6, 0x2, 0, 0x1, 0x14, 0x148, 0x1, 0, 0x154,
0xC, 0, 0, 0x1, 0, 0x91AB7E88, 0x1, 0x13, 0x183, 0x1, 0x14, 0x153, 0xE, 0x1, 0, 0x1, 0, 0x69FC64BC, 0xE, 0x2, 0, 0x6, 0x1, 0,
0x1, 0, 0x7D3765, 0xE, 0x1, 0, 0x1, 0, 0x189, 0xC, 0, 0, 0x63, 0, 0, 0x1, 0x3, 0x9E3779B9, 0x1, 0x4, 0x95C4C, 0x1, 0x5, 0x871D,
0x1, 0x6, 0x1A7B7, 0x1, 0x7, 0x12C7C7, 0x1, 0x8, 0, 0x1, 0x11, 0x10, 0x1, 0x12, 0x20, 0x1, 0x13, 0x160, 0x1, 0xA, 0, 0x1, 0xB, 0x20,
0x1, 0xC, 0x1, 0x7, 0x8, 0x3, 0x2, 0, 0x2, 0xA, 0, 0x11, 0x7, 0, 0x4, 0x2, 0xE, 0, 0x2, 0, 0x2, 0x7, 0, 0x8,
0x2, 0xF, 0, 0x2, 0, 0x2, 0x9, 0, 0x12, 0x7, 0, 0x5, 0x2, 0x10, 0, 0x2, 0, 0xE, 0xB, 0, 0xF, 0xB, 0, 0x10,
0x7, 0x1, 0, 0x2, 0, 0x1, 0xA, 0, 0x11, 0x7, 0, 0x6, 0x2, 0xE, 0, 0x2, 0, 0x1, 0x7, 0, 0x8, 0x2, 0xF, 0,
0x2, 0, 0x1, 0x9, 0, 0x12, 0x7, 0, 0x7, 0x2, 0x10, 0, 0x2, 0, 0xE, 0xB, 0, 0xF, 0xB, 0, 0x10, 0x7, 0x2, 0,
0x8, 0xB, 0xC, 0xE, 0xB, 0xA, 0xC, 0x14, 0, 0, 0, 0, 0x1, 0, 0x6E, 0x62, 0, 0, 0x1, 0, 0x6F, 0x62, 0, 0,
0xC, 0x14, 0, 0, 0, 0, 0x1, 0, 0x79, 0x62, 0, 0, 0x1, 0, 0x65, 0x62, 0, 0, 0x1, 0, 0x73, 0x62, 0, 0,
0xC, 0x14, 0]
for i in range(0, len(data), 3):
funcItem, arg1, arg2 = data[i], data[i + 1], data[i + 2]
# print(funcItem+1, arg1, arg2)
print(hex(i // 3).rjust(5, " ") + ":", maps[funcItem + 1].format(num=arg1, right=_hex(arg2), ch=_chr(arg2)))
分析汇编。tea。解密。