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 值,看一下转的对不对。
右击 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
rip + 8返回了也没啥
__int64 __usercall main___ptr_MzVm__init_func2@(__int64 a1)
{
__int64 v1; // rdx
__int64 v2; // rdx
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-18h]
v2 = *(_QWORD *)(v1 + 8);
result = (unsigned int)a1;
if ( (unsigned int)a1 >= 0x15uLL )
runtime_panicIndex(v4);
*(_DWORD *)(v2 + 4LL * (unsigned int)a1) = HIDWORD(a1);
return result;
}