XCTF高校战“疫”一道VM逆向题目详解
飘云阁全网首发,未经许可,禁止转载前两天在打xctf的一场比赛,其中一道题目使用了模拟化虚拟机的保护技术,对新手认识与分析VM有很好的学习意义。题目为64位ELF文件,本文将采用IDA远程调试Linux程序的方式,具体调试步骤不再赘述。如上图所示,程序要求输入flag,如果验证正确则成功。由于核心的指令都是虚拟化处理的,所以在本题是无法通过字符串定位到关键代码的。因此从main函数开始分析。__int64 __fastcall main(__int64 a1, char **a2, char **a3){
sub_40DB60();
return 0LL;
}
void sub_40DB60()
{
sub_40BD40(&dword_484358, 0x25uLL);
}
其中sub_40BD40则为VM的解码执行组件,而参数一为虚拟字节码的内存首地址,参数二为虚拟字节码的总长度。sub_40BD40函数有多处调用,在实际调试中发现该处只是为了打印字符串,因此不需要浪费时间分析这里的字节码执行逻辑,直接给出验证flag的函数如下。void sub_40DB80()
{
sub_40BD40(&dword_4846D0, 0x4BuLL);
}
因此dword_4846D0指向核心的虚拟字节码,sub_40BD40函数解码动作如下:很明显Qword为单位存储字节码,字节码在内存中的部分视图如下:因此首先执行的操作码为06,操作数都为0,该操作码对应的处理分支如下图,很明显是将输入的字符串的一个字符存入到tmp中,而调试发现此时inputPtr指向输入字符串的末尾,最后将inputPtr前移。下一条虚拟字节码为 00 7D 1A,该操作码对应的处理分支如下图,实际就是比如tmp与0x7D的大小。下一条虚拟字节码为 12 00 1C,为一条跳转操作,刚好与上一条的比较构成一个完整的判断。换句话说,如果我们输入字节串的最后一个字符等于0x7D(对应ASCII码‘}’,在ctf中flag的格式为flag{****})则跳转到第0x12条虚拟字节码执行。而此时我们的输入不满足,所以不会触发跳转,故继续分析下一条 00 62 01,翻译过来就是tmp=0x62(对应ASCII码‘b’)后面紧着的几条操作码都是01,直接出给翻译结果,正好对应文章开头截图中的失败提示“bye~~~”00 62 01 tmp=0x62 //label:失败 以下输出失败
01 79 01 tmp=0x79
02 65 01 tmp=0x65
03 7E 01 tmp=0x7e
06 7E 01 tmp=0x7e
07 7E 01 tmp=0x7e
因此在后续的分析中,我们需要构造满足的字符串继续分析,篇幅关系不能每一条都翻译给大家看,我直接给出我翻译好的字节码与其对应的操作。00 00 06 读最后一个字节
00 7D 1A 是否等于}
12 00 1C 相等则跳转cur = 0x12
00 62 01 tmp=0x62 //label:失败 以下输出失败
01 79 01 tmp=0x79
02 65 01 tmp=0x65
03 7E 01 tmp=0x7e
06 7E 01 tmp=0x7e
07 7E 01 tmp=0x7e
00 00 18
01 00 18
02 00 18
03 00 18
06 00 18
07 00 18
00 0A 01
00 00 18
00 00 19
08 100 01 tmp=0x100 //label: 0x12
08 E1 1A比较是否tmp<0xE1
19 00 1E 如果小于则跳转0x19(表示赋值完毕)
00 00 06 tmp=倒取输入的字符
08 00 04 data]=tmp
08 01 09 tmp = tmp-1
13 00 1D cur = 0x13(无条件跳转)
00 00 06 //以下比较开头是否为flag{//label: 0x19
00 7B 1A
03 00 1F
00 00 06
00 67 1A
03 00 1F
00 00 06
00 61 1A
03 00 1F
00 00 06
00 6C 1A
03 00 1F
00 00 06
00 66 1A
03 00 1F
09 09 12 tmp=0
0A E1 01 tmp=0xe1
07 09 03 tmp=data]//label: 0x2A
06 0A 03 tmp=data]
06 63 11 tmp^=0x63
06 02 0D tmp=tmp<<2
06 07 1B tmp==tmp
03 00 1F 不等于跳转失败
09 01 07 tmp+=1
0A 01 07 tmp+=1
09 20 1A tmp<0x20
2A 00 1E 小于则跳转0x2A (继续运算)
00 63 01 //以下输出成功
01 6F 01
02 72 01
03 72 01
06 65 01
07 63 01
00 00 18
01 00 18
02 00 18
03 00 18
06 00 18
07 00 18
00 74 01
01 6C 01
02 79 01
03 21 01
06 0A 01
00 00 18
01 00 18
02 00 18
03 00 18
06 00 18 逻辑很简单,逐字符对输入进行运算并比较,暴力破解即可,脚本如下:flag=''
data=
for i in range(len(data)):
for j in range(33,126):
if((j^0x63)<<2 == data):
flag += chr(j)
print flag
题目附件下载:链接:https://pan.baidu.com/s/1qPCogD9SOzohAZ7SAOZZnA 提取码:j79t
XCTF高校战“疫”一道VM逆向题目详解 不明觉厉,支持大佬
页:
[1]