UNCTF- 2019 EasyVm

分析

放入IDA中分析

image-20230409193452899

先看两个参数

2080

image-20230409193532329

20A0

image-20230409193606133

然后进去关键函数

image-20230409193703428

发现这里是许多的a1的偏移,然后这里有一个10A8可以跟进去,注意这里的存储类型,后面分析有用

image-20230409193810173

可以看到这里调用了很多的函数,然后进去第一个函数看一下

image-20230409193915019

这里能够看到是通过switch和case语句进行很多的不同的偏移,这里并不知道他运行的顺序,需要虚拟机远程调试

动调

我的断点下在了这里

image-20230409200734907

这里动态调试记得输入32位,防止最外面的if语句判断错误

image-20230409200959470

然后进去看一下基本的数据存放

image-20230409200800404

image-20230409200808361

a1存放的东西:

image-20230409201652742

看到这里,它的存储是4010A8,然后a1+8就是4010B0。然后看到下面

image-20230409202651574

知道A0对应的是这里,再结合外面能推测出4010B0应该是地址

image-20230409202736465

这里10B01118能与A0AF进行对应

从中知道(a1+24)调用的是20A0,(a1+32)调用的是我们所输入的东西,a2调用的是2080

也就是说a2+9是用来传输给switch进行判断的

然后通过不断的调试得出顺序是:A9,A3,A5,A6,A4,AB,A7,AE

接着找对应函数在干嘛

A9

image-20230409203112133

这里并不知道a1+16和a1+18于是从10B0开始看一下都是干嘛的

10B0:

image-20230409203234121

进行自增,然后根据上面byte的数据类型能推测a1+16应该是一个寄存器,所以这个我设为a16寄存器自增

然后往后面看能知道有a17和a18总共三个寄存器

所以A9为a16 = input[a18]

A3

image-20230409203700729

a16 -= a18

A5

image-20230409203814027

a17 = a16 ^ a17

A6

image-20230409204024551

a16 = 0XCD

A4

image-20230409204105009

a16 = a16 ^ a17

AB

image-20230409204244864

A7

image-20230409204341320

a17 = a16

AE

image-20230409204438048

脚本

接下来只需要逆向这些算法就行了

/*
a16 = input[a18];
a16 -= a18;
a17 = a16 ^ a17;
a16 = 0XCD;
a16 = a16 ^ a17;

func1:
if ( *(a1 + 16) == *(*(a1 + 24) + *(a1 + 18)) )
{
result = a1;
*(a1 + 20) = 0;
}
//从func1得知a16其实放的是20A0的值

a17 = a16;

func2:
if ( *(a1 + 17) >= *(*(a1 + 24) + *(a1 + 18)) )
*(a1 + 20) = 1;
else
*(a1 + 20) = -1;

*/

#include<stdio.h>
int main()
{
char a16 = 0;
char a17 = 0;
char input;
char s[32] = {
0xF4,0x0A,0xF7,0x64,0x99,0x78,0x9E,0x7D,0xEA,0X7B,
0X9E,0X7B,0X9F,0X7E,0XEB,0X71,0XE8,0X00,0XE8,0X07,
0X98,0X19,0XF4,0X25,0XF3,0X21,0XA4,0X2F,0XF4,0X2F,
0XA6,0X7C};
for(int i=0;i<32;i++)
{
input = (s[i]^(0xCD)^s[i-1])+i;
printf("%c",input);
}
return 0;
}
//942a4115be2359ffd675fa6338ba23b6