西湖论剑 EasyVT
一道VT题
题目给了一个exe程序和一个.sys文件
.sys文件可以在winxp系统下开启VT
出题人好像参考了周壑老师的代码,驱动程序相似度极高
这个exe程序很古怪,作者用vs2017开发包进行编译,最后没有进行静态打包,导致不能直接运行在winxp上,我们需要补齐很多的dll依赖才能正常运行,很麻烦,感情作者一开始就没打算让我们动调?
一、分析题目
之前接触过VT,借用周壑老师的代码,手动回复函数名

.sys文件的核心部分在这里:

我们参考代码回复这些宏的名字

比较三环代码和驱动代码


三环的vm指令和驱动的宏名称是一 一定义的,就像一个小型的vm混淆
二、分析算法
算法上只有rc4加密和魔改的tea加密
分别在sub_401250 和 sub_4019C0函数中
三、exp
魔改tea解密
// VT #include <stdio.h> #include <stdint.h> void conver_to_hex(uint32_t* v){ uint32_t v0=v[0], v1=v[1]; printf("%02x",v[0] & 0x000000ff); printf("%02x",(v[0] & 0x0000ff00) >> 8); printf("%02x",(v[0] & 0x00ff0000) >> 16); printf("%02x",(v[0] & 0xff000000) >> 24); printf("%02x",v[1] & 0x000000ff); printf("%02x",(v[1] & 0x0000ff00) >> 8); printf("%02x",(v[1] & 0x00ff0000) >> 16); printf("%02x",(v[1] & 0xff000000) >> 24); puts(""); } //解密函数 //void decrypt (uint32_t* v, uint32_t* k) { // uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */ // uint32_t delta=0x9e3779b9; /* a key schedule constant */ // uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ // for (i=0; i<32; i++) { /* basic cycle start */ // v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); // v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); // sum -= delta; // } /* end cycle */ // v[0]=v0; v[1]=v1; //} // 魔改部分: //1、 sum=0x20000000 //2、 delta=0xC95D6ABF //3、 v0 += ... => v0 -= ... ; v1 -= ... => v1+= ... //4、等号右边 => v0 => v1 ; v1 => v0 void decrypt (uint32_t* v, uint32_t* k) { uint32_t v0=v[0], v1=v[1], sum=0x20000000, i; /* set up */ uint32_t delta=0xC95D6ABF; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i<32; i++) { /* basic cycle start */ v0 -= ((v1<<4) + k2) ^ (v1 + sum) ^ ((v1>>5) + k3); // k2 => Get_key_3_2_1 // k3 => Get_key_2_1_3 v1 += ((v0<<4) + k0) ^ (v0 + sum) ^ ((v0>>5) + k1); // k1 => Get_key_1_0_0 // k0 => Get_key_0_3_2 sum -= delta; } /* end cycle */ v[0]=v0; v[1]=v1; } // //void encrypt (uint32_t* v, uint32_t* k) { // uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */ // uint32_t delta=0x9e3779b9; /* a key schedule constant */ // uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ // for (i=0; i < 32; i++) { /* basic cycle start */ // sum += delta; // v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); // v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); // } /* end cycle */ // v[0]=v0; v[1]=v1; //} // 写出解密脚本: //加密函数 void encrypt (uint32_t* v, uint32_t* k) { uint32_t v0=v[0], v1=v[1], sum=0x20000000, i; /* set up */ uint32_t delta=0xC95D6ABF; /* a key schedule constant */ for( i = 0;i<32;i++){ sum -= delta; } uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i < 32; i++) { /* basic cycle start */ sum += delta; v1 -= ((v0<<4) + k0) ^ (v0 + sum) ^ ((v0>>5) + k1); v0 += ((v1<<4) + k2) ^ (v1 + sum) ^ ((v1>>5) + k3); //出错原因: 想当然的写成: v0 += ... // v1 -= ... // 而没有认真的考虑加密逻辑 } /* end cycle */ v[0]=v0; v[1]=v1; } void Tea() { unsigned int cip[8] = { 0x5C073994, 0x0D805CB3, 0x87DDA586, 0x0317FB8E, 0x6520EF29, 0x5A4987AF, 0xEB2DC2A4, 0x38CF470E }; unsigned int key[4] = { 0x00102030, 0x40506070, 0x8090A0B0, 0xC0D0E0F0 }; for(int i = 0;i<4;i++){ uint32_t v[2]={1,2},k[4]={2,2,3,4}; v[0] = cip[i*2]; v[1] = cip[i*2+1]; k[0] = key[2]; k[1] = key[0]; k[2] = key[1]; k[3] = key[3]; encrypt(v, k); // conver_to_hex(v); printf("0x%x 0x%x\n",v[1],v[0]); } } int main(){ Tea(); return 0; }
rc4解密
from Crypto.Cipher import ARC4 as rc4cipher from struct import * def int2bytes(m): return pack("<I",m) cip = [ 0xb89c12d5, 0xb17e7a2c, 0xbf9842d1, 0xe6257321, 0xedcd45d0, 0xb2262921, 0xb99b49dc, 0xba722d2c ] flag = b"" key = b"04e52c7e31022b0b" for i in range(4): enc = rc4cipher.new(key) c = int2bytes(cip[i*2]) + int2bytes(cip[i*2+1]) res = enc.decrypt(c) flag += res[4:8] + res[:4] print(flag)
flag即为:
81920c3758be43705ba154bb8f599846
ps
这道题基本不需要什么VT知识,只需要捋清逻辑,写出解密脚本即可