ctf做题记录-svm

待补完

alt text
导入表为空,纯静态编译
经检查初始化和推出程序均空
alt text
alt text
程序执行会有 input 字符串,这是线索(这里用 ida 远程启动,会有其它信息
alt text
input 直接在 string 中搜到,有如下交叉引用:
alt text
直接下断点动调,发现 1780 是 main 函数,会 printf(input)
alt text
init 函数做了一个初始化:
alt text
sub_402000 是一个大虚拟机,不多赘述。
那么按照虚拟机的思路对函数重新命名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 sub_401780()
{
__int64 vm_mem[5]; // [rsp+0h] [rbp+0h] BYREF
unsigned __int64 vars28; // [rsp+28h] [rbp+28h]

vars28 = __readfsqword(0x28u);
printf("input:");
init(vm_mem, &mem_src, 4096LL, 2677LL);
vm(vm_mem);
may_printf(vm_mem[0]);
may_printf(vm_mem[2]);
if ( __readfsqword(0x28u) != vars28 )
sub_44C7D0();
return 0LL;
}

对虚拟机init的一些初始判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__int64 __fastcall init(struct_vm *vm, __int64 a2, int mem_size, int code_size)
{
__m128i *mem; // rax
__int64 code_seg; // rax
__int64 result; // rax

mem = (__m128i *)malloc(4LL * mem_size);
vm->mem_size = mem_size;
vm->mem = mem;
memset(mem, 0, 4 * mem_size);
code_seg = malloc(4LL * code_size);
vm->code_szie = code_size;
vm->code_seg = code_seg;
result = sub_401060();
vm->ip_point = 0;
vm->stack = -1LL;
return result;
}

在当前这一步,我们可以确定的分析不多,但有一点———该虚拟机似乎缺少了对寄存器的初始化,只进行了两个内存空间——很可能是代码和栈空间的初始化;接下来我们会印证这个想法。
该虚拟机的指令相当多,这里简单对内存空间进行扫描,取出大概率实际用到的指令
alt text
举例分析几个指令:
alt text
alt text
注意,我这里用的“弹”是偏主观的理解,按实际的来说,这里并没有专门的寄存器来接收“弹”出的栈顶变量,而是在语句中临时赋值。而后栈顶指针会往下移动,符合“弹”的感觉(x