首页
社区
课程
招聘
一次使用Ghidra反编译vmp的尝试
2023-9-27 12:22 5911

一次使用Ghidra反编译vmp的尝试

2023-9-27 12:22
5911

想尝试使用Ghidra直接对vmp handler进行反编译,由于工作量比较大,因此需要快速验证一下可行性怎么样。


C++代码编写

编写一段简单的算法代码

//禁止优化
#pragma optimize("", off) 
unsigned int VmpCipher(unsigned int a,unsigned int b)
{
    unsigned int result = 0xFF;
    __asm {
        _emit 0xEB;
        _emit 0x10;
        _emit 0x56;
        _emit 0x4D;
        _emit 0x50;
        _emit 0x72;
        _emit 0x6F;
        _emit 0x74;
        _emit 0x65;
        _emit 0x63;
        _emit 0x74;
        _emit 0x20;
        _emit 0x62;
        _emit 0x65;
        _emit 0x67;
        _emit 0x69;
        _emit 0x6E;
        _emit 0x00;
    }
    result += a;
    result += b;
    result -= a;
    result -= b;
    result *= a;
    result *= b;
    result = result / b;
    result = result & b;
    result = result % a;
    result = result ^ a;
    result = result ^ b;
    __asm {
        _emit 0xEB;
        _emit 0xE;
        _emit 0x56;
        _emit 0x4D;
        _emit 0x50;
        _emit 0x72;
        _emit 0x6F;
        _emit 0x74;
        _emit 0x65;
        _emit 0x63;
        _emit 0x74;
        _emit 0x20;
        _emit 0x65;
        _emit 0x6E;
        _emit 0x64;
        _emit 0x00;
    }
    return result;
}
#pragma optimize("", on) // 禁止优化

int main() { 
    unsigned int a = 0x12345678;
    unsigned int b = 0xDEADC0DE;
    unsigned int result = VmpCipher(a, b);
    std::cout << result << std::endl;
    return 0;
}

使用vmp3.5加一下简单的壳,打印一下执行的所有handler,大概是下面这样的

0x0048C184	vStoreContext ->
[0x0019FECC] = 0x00000000
[0x0019FED0] = ECX = 0x00000000
[0x0019FED4] = EDX = 0x0028E000
[0x0019FED8] = ESI = 0x0071DA20
[0x0019FEDC] = EBP = 0x0019FF08
[0x0019FEE0] = EAX = 0x00432878
[0x0019FEE4] = EBX = 0x0028B000
[0x0019FEE8] = EDI = 0x00721D90
[0x0019FEEC] = eflags = 0x00000202
[0x0019FEF0] = 0x0048C18E
[0x0019FEF4] = 0x0FBC1001
0x004AE6D7	vPopReg4 -> [0x0019FE34] = 0x00000000
0x00456C38	vPopReg4 -> [0x0019FE3C] = 0x00000000
0x00462CC6	vPopReg4 -> [0x0019FE38] = 0x0028E000
0x00464F1F	vPopReg4 -> [0x0019FE28] = 0x0071DA20
0x0043CAE2	vPopReg4 -> [0x0019FE14] = 0x0019FF08
0x00482926	vPopReg4 -> [0x0019FE44] = 0x00432878
0x0045798B	vPopReg4 -> [0x0019FE20] = 0x0028B000
0x004A9E05	vPopReg4 -> [0x0019FE10] = 0x00721D90
0x00462733	vPopReg4 -> [0x0019FE2C] = 0x00000202
0x004505CC	vPopReg4 -> [0x0019FE30] = 0x0048C18E
0x00468302	vPopReg4 -> [0x0019FE18] = 0x0FBC1001
0x0047A836	vPushImm4 -> [0x0019FEF4] = 0x0048DA57
0x004AE6D7	vPopReg4 -> [0x0019FE40] = 0x0048DA57
0x004AF244	vPushReg4 -> [0x0019FE18] -> push 0x0FBC1001
0x0044ACCE	vPushReg4 -> [0x0019FE10] -> push 0x00721D90
0x004B1210	vPushReg4 -> [0x0019FE20] -> push 0x0028B000
0x00442173	vPushReg4 -> [0x0019FE38] -> push 0x0028E000
0x0049B0A0	vPushReg4 -> [0x0019FE10] -> push 0x00721D90
0x0044D4A0	vPushReg4 -> [0x0019FE14] -> push 0x0019FF08
0x0048A8EE	vPushReg4 -> [0x0019FE28] -> push 0x0071DA20
0x00485351	vPushReg4 -> [0x0019FE2C] -> push 0x00000202
0x004B9752	vPushReg4 -> [0x0019FE3C] -> push 0x00000000
0x00433ADC	vPushReg4 -> [0x0019FE44] -> push 0x00432878
0x0043EB27	vPushReg4 -> [0x0019FE34] -> push 0x00000000
0x004AF244	vPushReg4 -> [0x0019FE40] -> push 0x0048DA57
0x00440BFB	vJmp 0x0048DA57
0x00453411	vPopReg4 -> [0x0019FE10] = 0x00000000
0x00478C66	vPopReg4 -> [0x0019FE28] = 0x00432878
0x004AFAC9	vPopReg4 -> [0x0019FE24] = 0x00000000
0x004B3AAC	vPopReg4 -> [0x0019FE2C] = 0x00000202
0x004BB8C6	vPopReg4 -> [0x0019FE3C] = 0x0071DA20
0x004675A0	vPopReg4 -> [0x0019FE48] = 0x0019FF08
0x00496DEB	vPopReg4 -> [0x0019FE44] = 0x00721D90
0x0045DB45	vPopReg4 -> [0x0019FE18] = 0x0028E000
0x0046E259	vPopReg4 -> [0x0019FE30] = 0x0028B000
0x00434A2D	vPopReg4 -> [0x0019FE34] = 0x00721D90
0x00493DA8	vPopReg4 -> [0x0019FE0C] = 0x0FBC1001
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00454004	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047862F	vPushImm4 -> [0x0019FEEC] = 0xFFFFFFFC
0x004A11FB	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE1C] = 0x00000213
0x004B3312	0x000000FF = vReadMem4(0x0019FF04)
0x00478C66	vPopReg4 -> [0x0019FE38] = 0x000000FF
0x0044C27C	vPushImm4 -> [0x0019FEF0] = 0x00000008
0x00455D02	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x004AFAC9	vPopReg4 -> [0x0019FE0C] = 0x00000212
0x004AEFE3	0x12345678 = vReadMem4(0x0019FF10)
0x00474718	vPushReg4 -> [0x0019FE38] -> push 0x000000FF
0x00434485	(0x00000216,0x12345777) = vAdd4(0x000000FF,0x12345678)
0x004B3AAC	vPopReg4 -> [0x0019FE28] = 0x00000216
0x004BB8C6	vPopReg4 -> [0x0019FE20] = 0x12345777
0x00433334	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00450289	vPushImm4 -> [0x0019FEF0] = 0xFFFFFFFC
0x0047B276	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0043A13C	vPushReg4 -> [0x0019FE20] -> push 0x12345777
0x00494385	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0043B6EE	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x00448025	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x004675A0	vPopReg4 -> [0x0019FE0C] = 0x00000213
0x0045BDCD	vWriteMem4 -> [0x0019FF04] = 0x12345777
0x00496DEB	vPopReg4 -> [0x0019FE28] = 0x00000213
0x0044D78D	0x12345777 = vReadMem4(0x0019FF04)
0x0045DB45	vPopReg4 -> [0x0019FE38] = 0x12345777
0x004B3AE2	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004C0C92	vPushImm4 -> [0x0019FEF0] = 0x0000000C
0x004ACF24	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE34] = 0x00000216
0x004ACD2E	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004ADC6E	vPushReg4 -> [0x0019FE38] -> push 0x12345777
0x0045E73A	(0x00000296,0xF0E21855) = vAdd4(0x12345777,0xDEADC0DE)
0x00434A2D	vPopReg4 -> [0x0019FE34] = 0x00000296
0x00493DA8	vPopReg4 -> [0x0019FE14] = 0xF0E21855
0x004BD01A	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004412F4	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004553C3	vPushImm4 -> [0x0019FEEC] = 0xFFFFFFFC
0x0043BC53	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0049C796	vPushReg4 -> [0x0019FE14] -> push 0xF0E21855
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047A771	vPushImm4 -> [0x0019FEE0] = 0xFFFFFFFC
0x004B72B0	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE0C] = 0x00000213
0x0043F7C2	vWriteMem4 -> [0x0019FF04] = 0xF0E21855
0x00478C66	vPopReg4 -> [0x0019FE0C] = 0x00000213
0x0049DF0A	0xF0E21855 = vReadMem4(0x0019FF04)
0x004AFAC9	vPopReg4 -> [0x0019FE38] = 0xF0E21855
0x00486D1C	vPushImm4 -> [0x0019FEF0] = 0x00000008
0x004B6320	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x004B3AAC	vPopReg4 -> [0x0019FE18] = 0x00000212
0x0049693C	0x12345678 = vReadMem4(0x0019FF10)
0x00454004	vPushReg4 -> [0x0019FE38] -> push 0xF0E21855
0x00474718	vPushReg4 -> [0x0019FE38] -> push 0xF0E21855
0x004601A6	(0x00000206,0x0F1DE7AA) = vNor4(0xF0E21855,0xF0E21855)
0x004BB8C6	vPopReg4 -> [0x0019FE24] = 0x00000206
0x00440C16	(0x00000216,0x21523E22) = vAdd4(0x0F1DE7AA,0x12345678)
0x004675A0	vPopReg4 -> [0x0019FE28] = 0x00000216
0x0045E5CD	vPushVEsp 0x0019FEF4
0x0048EA3E	0x21523E22 = vReadMem4(0x0019FEF4)
0x0044F0A7	(0x00000286,0xDEADC1DD) = vNand4(0x21523E22,0x21523E22)
0x00496DEB	vPopReg4 -> [0x0019FE18] = 0x00000286
0x0045DB45	vPopReg4 -> [0x0019FE40] = 0xDEADC1DD
0x00433334	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00443E96	vPushImm4 -> [0x0019FEF0] = 0x0000000C
0x0043A13C	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004611E7	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x004A11FB	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00494385	vPushReg4 -> [0x0019FE40] -> push 0xDEADC1DD
0x004B3AE2	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0048F933	vPushImm4 -> [0x0019FEDC] = 0xFFFFFFFC
0x00455D02	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE1C] = 0x00000213
0x00499ED8	vWriteMem4 -> [0x0019FF04] = 0xDEADC1DD
0x00434A2D	vPopReg4 -> [0x0019FE38] = 0x00000213
0x0049605F	0xDEADC1DD = vReadMem4(0x0019FF04)
0x00493DA8	vPopReg4 -> [0x0019FE24] = 0xDEADC1DD
0x00434485	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE20] = 0x00000216
0x00493716	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004ADC6E	vPushReg4 -> [0x0019FE24] -> push 0xDEADC1DD
0x004BD01A	vPushReg4 -> [0x0019FE24] -> push 0xDEADC1DD
0x004BE66F	(0x00000206,0x21523E22) = vNor4(0xDEADC1DD,0xDEADC1DD)
0x00478C66	vPopReg4 -> [0x0019FE38] = 0x00000206
0x0047B276	(0x00000296,0xFFFFFF00) = vAdd4(0x21523E22,0xDEADC0DE)
0x004AFAC9	vPopReg4 -> [0x0019FE34] = 0x00000296
0x0047016F	vPushVEsp 0x0019FEF4
0x00495B56	0xFFFFFF00 = vReadMem4(0x0019FEF4)
0x00440238	(0x00000206,0x000000FF) = vNor4(0xFFFFFF00,0xFFFFFF00)
0x004B3AAC	vPopReg4 -> [0x0019FE20] = 0x00000206
0x004BB8C6	vPopReg4 -> [0x0019FE1C] = 0x000000FF
0x004412F4	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047862F	vPushImm4 -> [0x0019FEF0] = 0x00000008
0x00448025	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x0049C796	vPushReg4 -> [0x0019FE1C] -> push 0x000000FF
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0044C27C	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x004ACF24	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x004675A0	vPopReg4 -> [0x0019FE28] = 0x00000213
0x004ACF50	vWriteMem4 -> [0x0019FF04] = 0x000000FF
0x00454004	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00450289	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x0045E73A	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00496DEB	vPopReg4 -> [0x0019FE34] = 0x00000213
0x0047C032	0x000000FF = vReadMem4(0x0019FF04)
0x0045DB45	vPopReg4 -> [0x0019FE18] = 0x000000FF
0x0046E259	vPopReg4 -> [0x0019FE0C] = 0x00000212
0x004B3312	0x12345678 = vReadMem4(0x0019FF10)
0x00474718	vPushReg4 -> [0x0019FE18] -> push 0x000000FF
0x0046E6B1	(0x00000A07,0x0000001222222188) = vImul(0x12345678,0x000000FF)
0x00434A2D	vPopReg4 -> [0x0019FE14] = 0x00000A07
0x00493DA8	vPopReg4 -> [0x0019FE0C] = 0x00000012
0x00453411	vPopReg4 -> [0x0019FE34] = 0x22222188
0x00433334	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0043B6EE	vPushImm4 -> [0x0019FEF0] = 0x0000000C
0x0043BC53	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x0043A13C	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00494385	vPushReg4 -> [0x0019FE34] -> push 0x22222188
0x004B3AE2	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004C0C92	vPushImm4 -> [0x0019FEE0] = 0xFFFFFFFC
0x004B72B0	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00478C66	vPopReg4 -> [0x0019FE14] = 0x00000213
0x004B6FB9	vWriteMem4 -> [0x0019FF04] = 0x22222188
0x004553C3	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x004B6320	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x004AFAC9	vPopReg4 -> [0x0019FE38] = 0x00000213
0x004AEFE3	0x22222188 = vReadMem4(0x0019FF04)
0x004B3AAC	vPopReg4 -> [0x0019FE14] = 0x22222188
0x004BB8C6	vPopReg4 -> [0x0019FE0C] = 0x00000216
0x0044D78D	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004ADC6E	vPushReg4 -> [0x0019FE14] -> push 0x22222188
0x00478A95	(0x00000A87,0xFB8EA253CBA713F0) = vImul(0xDEADC0DE,0x22222188)
0x004675A0	vPopReg4 -> [0x0019FE28] = 0x00000A87
0x00496DEB	vPopReg4 -> [0x0019FE40] = 0xFB8EA253
0x0045DB45	vPopReg4 -> [0x0019FE18] = 0xCBA713F0
0x004BD01A	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004412F4	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047A771	vPushImm4 -> [0x0019FEEC] = 0xFFFFFFFC
0x00440C16	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0049C796	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00486D1C	vPushImm4 -> [0x0019FEE0] = 0xFFFFFFFC
0x004A11FB	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE38] = 0x00000213
0x004ADEC1	vWriteMem4 -> [0x0019FF04] = 0xCBA713F0
0x00434A2D	vPopReg4 -> [0x0019FE20] = 0x00000213
0x00454004	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x00474718	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x00492CE8	(0x00000206,0x3458EC0F) = vNor4(0xCBA713F0,0xCBA713F0)
0x00493DA8	vPopReg4 -> [0x0019FE14] = 0x00000206
0x00433334	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x004B6966	(0x00000286,0xFFFFFFFF) = vNand4(0xCBA713F0,0x3458EC0F)
0x00453411	vPopReg4 -> [0x0019FE40] = 0x00000286
0x0043A13C	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x00494385	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x004B3AE2	vPushReg4 -> [0x0019FE18] -> push 0xCBA713F0
0x0046423B	(0x00000206,0x3458EC0F) = vNand4(0xCBA713F0,0xCBA713F0)
0x00478C66	vPopReg4 -> [0x0019FE40] = 0x00000206
0x0047417D	(0x00000286,0xFFFFFFFF) = vNand4(0x3458EC0F,0xCBA713F0)
0x004AFAC9	vPopReg4 -> [0x0019FE38] = 0x00000286
0x00459E51	(0x00000246,0x00000000) = vNand4(0xFFFFFFFF,0xFFFFFFFF)
0x004B3AAC	vPopReg4 -> [0x0019FE24] = 0x00000246
0x004BB8C6	vPopReg4 -> [0x0019FE40] = 0x00000000
0x004ACD2E	0xCBA713F0 = vReadMem4(0x0019FF04)
0x004675A0	vPopReg4 -> [0x0019FE14] = 0xCBA713F0
0x00443E96	vPushImm4 -> [0x0019FEF0] = 0x0000000C
0x00455D02	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x00496DEB	vPopReg4 -> [0x0019FE0C] = 0x00000216
0x0049DF0A	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004ADC6E	vPushReg4 -> [0x0019FE14] -> push 0xCBA713F0
0x004BD01A	vPushReg4 -> [0x0019FE40] -> push 0x00000000
0x00483128	(0x00000202,0xCBA713F0,0x00000000) = vDiv(0x00000000CBA713F0,0xDEADC0DE)
0x0045DB45	vPopReg4 -> [0x0019FE20] = 0x00000202
0x0046E259	vPopReg4 -> [0x0019FE0C] = 0xCBA713F0
0x00434A2D	vPopReg4 -> [0x0019FE24] = 0x00000000
0x004412F4	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004611E7	vPushImm4 -> [0x0019FEF0] = 0x0000000C
0x00434485	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x0049C796	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0048F933	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x00447DE0	vPushReg4 -> [0x0019FE24] -> push 0x00000000
0x00454004	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047862F	vPushImm4 -> [0x0019FEDC] = 0xFFFFFFFC
0x0047B276	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00493DA8	vPopReg4 -> [0x0019FE28] = 0x00000213
0x004387DB	vWriteMem4 -> [0x0019FF04] = 0x00000000
0x00448025	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE28] = 0x00000213
0x0049693C	0x00000000 = vReadMem4(0x0019FF04)
0x00478C66	vPopReg4 -> [0x0019FE20] = 0x00000000
0x004AFAC9	vPopReg4 -> [0x0019FE18] = 0x00000216
0x0048EA3E	0xDEADC0DE = vReadMem4(0x0019FF14)
0x0047249F	vPushVEsp 0x0019FEF4
0x0049605F	0xDEADC0DE = vReadMem4(0x0019FEF4)
0x004718A9	(0x00000206,0x21523F21) = vNor4(0xDEADC0DE,0xDEADC0DE)
0x004B3AAC	vPopReg4 -> [0x0019FE40] = 0x00000206
0x00474718	vPushReg4 -> [0x0019FE20] -> push 0x00000000
0x00433334	vPushReg4 -> [0x0019FE20] -> push 0x00000000
0x004BC537	(0x00000286,0xFFFFFFFF) = vNor4(0x00000000,0x00000000)
0x004BB8C6	vPopReg4 -> [0x0019FE28] = 0x00000286
0x004B8D8D	(0x00000246,0x00000000) = vNor4(0xFFFFFFFF,0x21523F21)
0x004675A0	vPopReg4 -> [0x0019FE40] = 0x00000246
0x00496DEB	vPopReg4 -> [0x0019FE18] = 0x00000000
0x0044C27C	vPushImm4 -> [0x0019FEF4] = 0x00401E09
0x0043A13C	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00450289	vPushImm4 -> [0x0019FEEC] = 0x00000008
0x004ACF24	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x00494385	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0043B6EE	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x004B3AE2	vPushReg4 -> [0x0019FE18] -> push 0x00000000
0x004ADC6E	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004C0C92	vPushImm4 -> [0x0019FED8] = 0xFFFFFFFC
0x0045E73A	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0045DB45	vPopReg4 -> [0x0019FE1C] = 0x00000213
0x00473B3E	vWriteMem4 -> [0x0019FF04] = 0x00000000
0x0043BC53	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE20] = 0x00000213
0x004BD01A	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x004412F4	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x004A4319	(0x00000206,0x3458EC0F) = vNand4(0xCBA713F0,0xCBA713F0)
0x00434A2D	vPopReg4 -> [0x0019FE40] = 0x00000206
0x0049C796	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x00447DE0	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x0047149E	(0x00000206,0x3458EC0F) = vNand4(0xCBA713F0,0xCBA713F0)
0x00493DA8	vPopReg4 -> [0x0019FE40] = 0x00000206
0x004400E1	(0x00000286,0xCBA713F0) = vNor4(0x3458EC0F,0x3458EC0F)
0x00453411	vPopReg4 -> [0x0019FE40] = 0x00000286
0x00454004	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x00474718	vPushReg4 -> [0x0019FE0C] -> push 0xCBA713F0
0x00472872	(0x00000206,0x3458EC0F) = vNor4(0xCBA713F0,0xCBA713F0)
0x00478C66	vPopReg4 -> [0x0019FE1C] = 0x00000206
0x004596E6	(0x00000246,0x00000000) = vNor4(0x3458EC0F,0xCBA713F0)
0x004AFAC9	vPopReg4 -> [0x0019FE40] = 0x00000246
0x004B3AAC	vPopReg4 -> [0x0019FE24] = 0x00000000
0x00493716	0x00000000 = vReadMem4(0x0019FF04)
0x004BB8C6	vPopReg4 -> [0x0019FE38] = 0x00000000
0x004675A0	vPopReg4 -> [0x0019FE18] = 0x00000212
0x00495B56	0x12345678 = vReadMem4(0x0019FF10)
0x00433334	vPushReg4 -> [0x0019FE38] -> push 0x00000000
0x0043A13C	vPushReg4 -> [0x0019FE24] -> push 0x00000000
0x004742E4	(0x00000206,0x00000000,0x00000000) = vDiv(0x0000000000000000,0x12345678)
0x00496DEB	vPopReg4 -> [0x0019FE20] = 0x00000206
0x0045DB45	vPopReg4 -> [0x0019FE28] = 0x00000000
0x00494385	vPushReg4 -> [0x0019FE28] -> push 0x00000000
0x004B3AE2	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004553C3	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x004B72B0	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE24] = 0x00000213
0x004B8006	vWriteMem4 -> [0x0019FF04] = 0x00000000
0x004ADC6E	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047A771	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x004B6320	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00434A2D	vPopReg4 -> [0x0019FE20] = 0x00000213
0x0047C032	0x00000000 = vReadMem4(0x0019FF04)
0x00493DA8	vPopReg4 -> [0x0019FE14] = 0x00000000
0x004BD01A	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00486D1C	vPushImm4 -> [0x0019FEE8] = 0x00000008
0x00440C16	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE0C] = 0x00000212
0x004B3312	0x12345678 = vReadMem4(0x0019FF10)
0x00438A2C	vPushVEsp 0x0019FEEC
0x004AEFE3	0x12345678 = vReadMem4(0x0019FEEC)
0x00466B07	(0x00000286,0xEDCBA987) = vNand4(0x12345678,0x12345678)
0x00478C66	vPopReg4 -> [0x0019FE24] = 0x00000286
0x004412F4	vPushReg4 -> [0x0019FE14] -> push 0x00000000
0x0049C796	vPushReg4 -> [0x0019FE14] -> push 0x00000000
0x0045FF32	(0x00000286,0xFFFFFFFF) = vNor4(0x00000000,0x00000000)
0x004AFAC9	vPopReg4 -> [0x0019FE0C] = 0x00000286
0x004601A6	(0x00000246,0x00000000) = vNor4(0xFFFFFFFF,0xEDCBA987)
0x004B3AAC	vPopReg4 -> [0x0019FE24] = 0x00000246
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00443E96	vPushImm4 -> [0x0019FEE4] = 0x00000008
0x004A11FB	(0x00000212,0x0019FF10) = vAdd4(0x00000008,0x0019FF08)
0x004BB8C6	vPopReg4 -> [0x0019FE24] = 0x00000212
0x0044D78D	0x12345678 = vReadMem4(0x0019FF10)
0x00454004	vPushReg4 -> [0x0019FE14] -> push 0x00000000
0x004BE66F	(0x00000286,0xEDCBA987) = vNor4(0x00000000,0x12345678)
0x004675A0	vPopReg4 -> [0x0019FE40] = 0x00000286
0x00440238	(0x00000206,0x12345678) = vNor4(0xEDCBA987,0x00000000)
0x00496DEB	vPopReg4 -> [0x0019FE24] = 0x00000206
0x0045DB45	vPopReg4 -> [0x0019FE0C] = 0x12345678
0x00474718	vPushReg4 -> [0x0019FE0C] -> push 0x12345678
0x00433334	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x004611E7	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x00455D02	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE1C] = 0x00000213
0x00450FDF	vWriteMem4 -> [0x0019FF04] = 0x12345678
0x0043A13C	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0048F933	vPushImm4 -> [0x0019FEE8] = 0xFFFFFFFC
0x00434485	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x00434A2D	vPopReg4 -> [0x0019FE24] = 0x00000213
0x004ACD2E	0x12345678 = vReadMem4(0x0019FF04)
0x00493DA8	vPopReg4 -> [0x0019FE40] = 0x12345678
0x00494385	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0047862F	vPushImm4 -> [0x0019FEE8] = 0x0000000C
0x0047B276	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x00453411	vPopReg4 -> [0x0019FE14] = 0x00000216
0x0049DF0A	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004B8432	vPushVEsp 0x0019FEEC
0x0049693C	0xDEADC0DE = vReadMem4(0x0019FEEC)
0x00492CE8	(0x00000206,0x21523F21) = vNor4(0xDEADC0DE,0xDEADC0DE)
0x00478C66	vPopReg4 -> [0x0019FE1C] = 0x00000206
0x004B3AE2	vPushReg4 -> [0x0019FE40] -> push 0x12345678
0x004ADC6E	vPushReg4 -> [0x0019FE40] -> push 0x12345678
0x0048273D	(0x00000286,0xEDCBA987) = vNand4(0x12345678,0x12345678)
0x004AFAC9	vPopReg4 -> [0x0019FE24] = 0x00000286
0x004718A9	(0x00000202,0x12244058) = vNor4(0xEDCBA987,0x21523F21)
0x004B3AAC	vPopReg4 -> [0x0019FE34] = 0x00000202
0x004BD01A	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x0044C27C	vPushImm4 -> [0x0019FEE4] = 0x0000000C
0x00448025	(0x00000216,0x0019FF14) = vAdd4(0x0000000C,0x0019FF08)
0x004BB8C6	vPopReg4 -> [0x0019FE14] = 0x00000216
0x0048EA3E	0xDEADC0DE = vReadMem4(0x0019FF14)
0x004412F4	vPushReg4 -> [0x0019FE40] -> push 0x12345678
0x004BC537	(0x00000202,0x21422901) = vNor4(0x12345678,0xDEADC0DE)
0x004675A0	vPopReg4 -> [0x0019FE34] = 0x00000202
0x004B8D8D	(0x00000286,0xCC9996A6) = vNor4(0x21422901,0x12244058)
0x00496DEB	vPopReg4 -> [0x0019FE24] = 0x00000286
0x0045DB45	vPopReg4 -> [0x0019FE14] = 0xCC9996A6
0x0049C796	vPushReg4 -> [0x0019FE14] -> push 0xCC9996A6
0x00447DE0	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00450289	vPushImm4 -> [0x0019FEE4] = 0xFFFFFFFC
0x004ACF24	(0x00000213,0x0019FF04) = vAdd4(0xFFFFFFFC,0x0019FF08)
0x0046E259	vPopReg4 -> [0x0019FE20] = 0x00000213
0x004BA046	vWriteMem4 -> [0x0019FF04] = 0xCC9996A6
0x00434A2D	vPopReg4 -> [0x0019FE28] = 0x00000000
0x00454004	vPushReg4 -> [0x0019FE48] -> push 0x0019FF08
0x00474718	vPushReg4 -> [0x0019FE14] -> push 0xCC9996A6
0x00433334	vPushReg4 -> [0x0019FE0C] -> push 0x12345678
0x0043A13C	vPushReg4 -> [0x0019FE44] -> push 0x00721D90
0x00494385	vPushReg4 -> [0x0019FE24] -> push 0x00000286
0x004B3AE2	vPushReg4 -> [0x0019FE30] -> push 0x0028B000
0x004ADC6E	vPushReg4 -> [0x0019FE3C] -> push 0x0071DA20
0x004BD01A	vPushReg4 -> [0x0019FE28] -> push 0x00000000
0x0046A912	vExit

GhidraIR生成

很明显,这么一大堆handler阅读起来非常困难,我要这打印有何用......


那么转变分析思路,我们知道vm代码是拿ebp这类寄存器当作实际程序的堆栈寄存器,而esp则沦为了vmContext,指向vm自定义寄存器,我们既然已经拿到了handler,不如将其转换为基于堆栈的操作。

例如vStoreContext这个handler,我们将其翻译为等价于以下汇编的GhidraIR

push 0x0FBC1001
push 0x0048C18E
push eflags
push EDI
push EBX
push EAX
push EBP
push ESI
push EDX
push ECX
push 0x0

再比如vPushReg4这个handler,在vmp中汇编是这样的

mov ecx,dword ptr ss:[esp+edx]
sub esi,0x4
mov dword ptr ds:[esi],ecx

我们将其翻译成等价于以下汇编的GhidraIR,这里ecx的来源esp偏移要提前计算好

mov ecx,[esp+xxx]
push ecx

最后一个例子vDiv,在汇编中的表现形式是

mov eax,dword ptr ds:[esi+0x4]
mov edx,dword ptr ds:[esi]
mov ecx,dword ptr ds:[esi+0x8]
div ecx
mov dword ptr ds:[esi+0x4],edx
mov dword ptr ds:[esi+0x8],eax
pushfd
pop dword ptr ds:[esi]

我们将其翻译成等价于以下汇编的GhidraIR

mov eax,dword ptr ds:[esp+0x4]
mov edx,dword ptr ds:[esp]
mov ecx,dword ptr ds:[esp+0x8]
div ecx
mov dword ptr ds:[esp],eflags
mov dword ptr ds:[esp+0x4],edx
mov dword ptr ds:[esp+0x8],eax

反编译

不得不说,给每个handler编写IR生成代码还挺累的,写完了以后进行反编译,得到的化简IR如下:

0
Basic Block 0 0x0048c184-0x004c0c92
0x004a11fb:9c:	u0x10002f95(0x004a11fb:9c) = EBP(i) + #0xfffffffc
0x004a11fb:139b:	u0x100000d4(0x004a11fb:139b) = (cast) u0x10002f95(0x004a11fb:9c)
0x004b3312:cd:	u0x1000015a(0x004b3312:cd) = *(ram,u0x100000d4(0x004a11fb:139b))
0x00455d02:da:	u0x10002f99(0x00455d02:da) = EBP(i) + #0x8
0x00455d02:139c:	u0x10000172(0x00455d02:139c) = (cast) u0x10002f99(0x00455d02:da)
0x004aefe3:10b:	u0x100001f8(0x004aefe3:10b) = *(ram,u0x10000172(0x00455d02:139c))
0x00434485:115:	u0x1000020c(0x00434485:115) = u0x1000015a(0x004b3312:cd) + u0x100001f8(0x004aefe3:10b)
0x0047b276:153:	u0x10002f9d(0x0047b276:153) = EBP(i) + #0xfffffffc
0x0047b276:139d:	u0x100002a6(0x0047b276:139d) = (cast) u0x10002f9d(0x0047b276:153)
0x00448025:18e:	u0x10002fa1(0x00448025:18e) = EBP(i) + #0xfffffffc
0x00448025:139e:	u0x1000033c(0x00448025:139e) = (cast) u0x10002fa1(0x00448025:18e)
0x0045bdcd:1c1:	*(ram,u0x1000033c(0x00448025:139e)) = u0x1000020c(0x00434485:115)
0x0044d78d:1c7:	u0x100003ce(0x0044d78d:1c7) = *(ram,u0x100002a6(0x0047b276:139d))
0x004acf24:1d7:	u0x10002fa5(0x004acf24:1d7) = EBP(i) + #0xc
0x004acf24:139f:	u0x100003ea(0x004acf24:139f) = (cast) u0x10002fa5(0x004acf24:1d7)
0x004acd2e:208:	u0x10000470(0x004acd2e:208) = *(ram,u0x100003ea(0x004acf24:139f))
0x0045e73a:212:	u0x10000484(0x0045e73a:212) = u0x100003ce(0x0044d78d:1c7) + u0x10000470(0x004acd2e:208)
0x0043bc53:253:	u0x10002fa9(0x0043bc53:253) = EBP(i) + #0xfffffffc
0x0043bc53:13a0:	u0x10000522(0x0043bc53:13a0) = (cast) u0x10002fa9(0x0043bc53:253)
0x004b72b0:28e:	u0x10002fad(0x004b72b0:28e) = EBP(i) + #0xfffffffc
0x004b72b0:13a1:	u0x100005b8(0x004b72b0:13a1) = (cast) u0x10002fad(0x004b72b0:28e)
0x0043f7c2:2c1:	*(ram,u0x100005b8(0x004b72b0:13a1)) = u0x10000484(0x0045e73a:212)
0x0049df0a:2c7:	u0x1000064a(0x0049df0a:2c7) = *(ram,u0x10000522(0x0043bc53:13a0))
0x004b6320:2d4:	u0x10002fb1(0x004b6320:2d4) = EBP(i) + #0x8
0x004b6320:13a2:	u0x10000662(0x004b6320:13a2) = (cast) u0x10002fb1(0x004b6320:2d4)
0x0049693c:305:	u0x100006e8(0x0049693c:305) = *(ram,u0x10000662(0x004b6320:13a2))
0x004601a6:310:	u0x10000700(0x004601a6:310) = ~ u0x1000064a(0x0049df0a:2c7)
0x00440c16:349:	u0x10000799(0x00440c16:349) = u0x10000700(0x004601a6:310) + u0x100006e8(0x0049693c:305)
0x0044f0a7:382:	u0x10000833(0x0044f0a7:382) = ~ u0x10000799(0x00440c16:349)
0x004a11fb:3ca:	u0x10002fb5(0x004a11fb:3ca) = EBP(i) + #0xfffffffc
0x004a11fb:13a3:	u0x100008e0(0x004a11fb:13a3) = (cast) u0x10002fb5(0x004a11fb:3ca)
0x00455d02:405:	u0x10002fb9(0x00455d02:405) = EBP(i) + #0xfffffffc
0x00455d02:13a4:	u0x10000976(0x00455d02:13a4) = (cast) u0x10002fb9(0x00455d02:405)
0x00499ed8:438:	*(ram,u0x10000976(0x00455d02:13a4)) = u0x10000833(0x0044f0a7:382)
0x0049605f:43e:	u0x10000a08(0x0049605f:43e) = *(ram,u0x100008e0(0x004a11fb:13a3))
0x00434485:448:	u0x10002fbd(0x00434485:448) = EBP(i) + #0xc
0x00434485:13a5:	u0x10000a1c(0x00434485:13a5) = (cast) u0x10002fbd(0x00434485:448)
0x00493716:479:	u0x10000aa2(0x00493716:479) = *(ram,u0x10000a1c(0x00434485:13a5))
0x004be66f:484:	u0x10000aba(0x004be66f:484) = ~ u0x10000a08(0x0049605f:43e)
0x0047b276:4bd:	u0x10000b53(0x0047b276:4bd) = u0x10000aba(0x004be66f:484) + u0x10000aa2(0x00493716:479)
0x00440238:4f6:	u0x10000bed(0x00440238:4f6) = ~ u0x10000b53(0x0047b276:4bd)
0x00448025:538:	u0x10002fc1(0x00448025:538) = EBP(i) + #0x8
0x00448025:13a6:	u0x10000c92(0x00448025:13a6) = (cast) u0x10002fc1(0x00448025:538)
0x004acf24:573:	u0x10002fc5(0x004acf24:573) = EBP(i) + #0xfffffffc
0x004acf24:13a7:	u0x10000d28(0x004acf24:13a7) = (cast) u0x10002fc5(0x004acf24:573)
0x004acf50:5a6:	*(ram,u0x10000d28(0x004acf24:13a7)) = u0x10000bed(0x00440238:4f6)
0x0045e73a:5b3:	u0x10002fc9(0x0045e73a:5b3) = EBP(i) + #0xfffffffc
0x0045e73a:13a8:	u0x10000dc6(0x0045e73a:13a8) = (cast) u0x10002fc9(0x0045e73a:5b3)
0x0047c032:5e4:	u0x10000e4c(0x0047c032:5e4) = *(ram,u0x10000dc6(0x0045e73a:13a8))
0x004b3312:5ed:	u0x10000e5c(0x004b3312:5ed) = *(ram,u0x10000c92(0x00448025:13a6))
0x0046e6b1:1395:	u0x10000e80(0x0046e6b1:1395) = u0x10000e5c(0x004b3312:5ed) * u0x10000e4c(0x0047c032:5e4)
0x0043bc53:639:	u0x10002fcd(0x0043bc53:639) = EBP(i) + #0xc
0x0043bc53:13a9:	u0x10000f29(0x0043bc53:13a9) = (cast) u0x10002fcd(0x0043bc53:639)
0x004b72b0:677:	u0x10002fd1(0x004b72b0:677) = EBP(i) + #0xfffffffc
0x004b72b0:13aa:	u0x10000fc3(0x004b72b0:13aa) = (cast) u0x10002fd1(0x004b72b0:677)
0x004b6fb9:6aa:	*(ram,u0x10000fc3(0x004b72b0:13aa)) = u0x10000e80(0x0046e6b1:1395)
0x004b6320:6b4:	u0x10002fd5(0x004b6320:6b4) = EBP(i) + #0xfffffffc
0x004b6320:13ab:	u0x1000105d(0x004b6320:13ab) = (cast) u0x10002fd5(0x004b6320:6b4)
0x004aefe3:6e5:	u0x100010e3(0x004aefe3:6e5) = *(ram,u0x1000105d(0x004b6320:13ab))
0x0044d78d:6ee:	u0x100010f3(0x0044d78d:6ee) = *(ram,u0x10000f29(0x0043bc53:13a9))
0x00478a95:1398:	u0x10001117(0x00478a95:1398) = u0x100010f3(0x0044d78d:6ee) * u0x100010e3(0x004aefe3:6e5)
0x00440c16:73d:	u0x10002fd9(0x00440c16:73d) = EBP(i) + #0xfffffffc
0x00440c16:13ac:	u0x100011c4(0x00440c16:13ac) = (cast) u0x10002fd9(0x00440c16:73d)
0x004a11fb:778:	u0x10002fdd(0x004a11fb:778) = EBP(i) + #0xfffffffc
0x004a11fb:13ad:	u0x1000125a(0x004a11fb:13ad) = (cast) u0x10002fdd(0x004a11fb:778)
0x004adec1:7ab:	*(ram,u0x1000125a(0x004a11fb:13ad)) = u0x10001117(0x00478a95:1398)
0x004acd2e:8d9:	u0x10001605(0x004acd2e:8d9) = *(ram,u0x100011c4(0x00440c16:13ac))
0x00455d02:8e6:	u0x10002fe1(0x00455d02:8e6) = EBP(i) + #0xc
0x00455d02:13ae:	u0x1000161d(0x00455d02:13ae) = (cast) u0x10002fe1(0x00455d02:8e6)
0x0049df0a:917:	u0x100016a3(0x0049df0a:917) = *(ram,u0x1000161d(0x00455d02:13ae))
0x00483128:929:	u0x100016f3(0x00483128:929) = u0x10001605(0x004acd2e:8d9) / u0x100016a3(0x0049df0a:917)
0x00434485:968:	u0x10002fe5(0x00434485:968) = EBP(i) + #0xc
0x00434485:13af:	u0x10001794(0x00434485:13af) = (cast) u0x10002fe5(0x00434485:968)
0x0047b276:9a9:	u0x10002fe9(0x0047b276:9a9) = EBP(i) + #0xfffffffc
0x0047b276:13b0:	u0x10001832(0x0047b276:13b0) = (cast) u0x10002fe9(0x0047b276:9a9)
0x004387db:9dc:	*(ram,u0x10001832(0x0047b276:13b0)) = u0x100016f3(0x00483128:929)
0x00448025:9e3:	u0x10002fed(0x00448025:9e3) = EBP(i) + #0xfffffffc
0x00448025:13b1:	u0x100018c8(0x00448025:13b1) = (cast) u0x10002fed(0x00448025:9e3)
0x0049693c:a14:	u0x1000194e(0x0049693c:a14) = *(ram,u0x100018c8(0x00448025:13b1))
0x0048ea3e:a1d:	u0x1000195e(0x0048ea3e:a1d) = *(ram,u0x10001794(0x00434485:13af))
0x004b8d8d:aa0:	u0x10001abc(0x004b8d8d:aa0) = u0x1000194e(0x0049693c:a14) & u0x1000195e(0x0048ea3e:a1d)
0x004acf24:ae1:	u0x10002ff1(0x004acf24:ae1) = EBP(i) + #0x8
0x004acf24:13b2:	u0x10001b5d(0x004acf24:13b2) = (cast) u0x10002ff1(0x004acf24:ae1)
0x0045e73a:b22:	u0x10002ff5(0x0045e73a:b22) = EBP(i) + #0xfffffffc
0x0045e73a:13b3:	u0x10001bfb(0x0045e73a:13b3) = (cast) u0x10002ff5(0x0045e73a:b22)
0x00473b3e:b55:	*(ram,u0x10001bfb(0x0045e73a:13b3)) = u0x10001abc(0x004b8d8d:aa0)
0x0043bc53:b5c:	u0x10002ff9(0x0043bc53:b5c) = EBP(i) + #0xfffffffc
0x0043bc53:13b4:	u0x10001c91(0x0043bc53:13b4) = (cast) u0x10002ff9(0x0043bc53:b5c)
0x00493716:cb5:	u0x10002030(0x00493716:cb5) = *(ram,u0x10001c91(0x0043bc53:13b4))
0x00495b56:cbe:	u0x10002040(0x00495b56:cbe) = *(ram,u0x10001b5d(0x004acf24:13b2))
0x004742e4:cd0:	u0x10002090(0x004742e4:cd0) = u0x10002030(0x00493716:cb5) / u0x10002040(0x00495b56:cbe)
0x004742e4:cd2:	u0x1000209c(0x004742e4:cd2) = u0x10002030(0x00493716:cb5) % u0x10002040(0x00495b56:cbe)
0x004b72b0:d0f:	u0x10002ffd(0x004b72b0:d0f) = EBP(i) + #0xfffffffc
0x004b72b0:13b5:	u0x10002131(0x004b72b0:13b5) = (cast) u0x10002ffd(0x004b72b0:d0f)
0x004b8006:d42:	*(ram,u0x10002131(0x004b72b0:13b5)) = u0x1000209c(0x004742e4:cd2)
0x004b6320:d4f:	u0x10003001(0x004b6320:d4f) = EBP(i) + #0xfffffffc
0x004b6320:13b6:	u0x100021cf(0x004b6320:13b6) = (cast) u0x10003001(0x004b6320:d4f)
0x0047c032:d80:	u0x10002255(0x0047c032:d80) = *(ram,u0x100021cf(0x004b6320:13b6))
0x00440c16:d90:	u0x10003005(0x00440c16:d90) = EBP(i) + #0x8
0x00440c16:13b7:	u0x10002271(0x00440c16:13b7) = (cast) u0x10003005(0x00440c16:d90)
0x004b3312:dc1:	u0x100022f7(0x004b3312:dc1) = *(ram,u0x10002271(0x00440c16:13b7))
0x004601a6:e44:	u0x10002455(0x004601a6:e44) = u0x10002255(0x0047c032:d80) & u0x100022f7(0x004b3312:dc1)
0x004a11fb:e7f:	u0x10003009(0x004a11fb:e7f) = EBP(i) + #0x8
0x004a11fb:13b8:	u0x100024ee(0x004a11fb:13b8) = (cast) u0x10003009(0x004a11fb:e7f)
0x0044d78d:eb0:	u0x10002574(0x0044d78d:eb0) = *(ram,u0x100024ee(0x004a11fb:13b8))
0x004be66f:eb8:	u0x10002588(0x004be66f:eb8) = ~ u0x10002255(0x0047c032:d80)
0x004be66f:eb9:	u0x1000258c(0x004be66f:eb9) = ~ u0x10002574(0x0044d78d:eb0)
0x004be66f:ebc:	u0x10002590(0x004be66f:ebc) = u0x10002588(0x004be66f:eb8) & u0x1000258c(0x004be66f:eb9)
0x00440238:eef:	u0x10002621(0x00440238:eef) = ~ u0x10002590(0x004be66f:ebc)
0x00440238:ef0:	u0x10002625(0x00440238:ef0) = ~ u0x10002455(0x004601a6:e44)
0x00440238:ef3:	u0x10002629(0x00440238:ef3) = u0x10002621(0x00440238:eef) & u0x10002625(0x00440238:ef0)
0x00455d02:f34:	u0x1000300d(0x00455d02:f34) = EBP(i) + #0xfffffffc
0x00455d02:13b9:	u0x100026ca(0x00455d02:13b9) = (cast) u0x1000300d(0x00455d02:f34)
0x00450fdf:f67:	*(ram,u0x100026ca(0x00455d02:13b9)) = u0x10002629(0x00440238:ef3)
0x00434485:f74:	u0x10003011(0x00434485:f74) = EBP(i) + #0xfffffffc
0x00434485:13ba:	u0x10002768(0x00434485:13ba) = (cast) u0x10003011(0x00434485:f74)
0x004acd2e:fa5:	u0x100027ee(0x004acd2e:fa5) = *(ram,u0x10002768(0x00434485:13ba))
0x0047b276:fb5:	u0x10003015(0x0047b276:fb5) = EBP(i) + #0xc
0x0047b276:13bb:	u0x1000280a(0x0047b276:13bb) = (cast) u0x10003015(0x0047b276:fb5)
0x0049df0a:fe6:	u0x10002890(0x0049df0a:fe6) = *(ram,u0x1000280a(0x0047b276:13bb))
0x004718a9:1069:	u0x100029ee(0x004718a9:1069) = u0x100027ee(0x004acd2e:fa5) & u0x10002890(0x0049df0a:fe6)
0x00448025:10a4:	u0x10003019(0x00448025:10a4) = EBP(i) + #0xc
0x00448025:13bc:	u0x10002a87(0x00448025:13bc) = (cast) u0x10003019(0x00448025:10a4)
0x0048ea3e:10d5:	u0x10002b0d(0x0048ea3e:10d5) = *(ram,u0x10002a87(0x00448025:13bc))
0x004bc537:10dd:	u0x10002b21(0x004bc537:10dd) = ~ u0x100027ee(0x004acd2e:fa5)
0x004bc537:10de:	u0x10002b25(0x004bc537:10de) = ~ u0x10002b0d(0x0048ea3e:10d5)
0x004bc537:10e1:	u0x10002b29(0x004bc537:10e1) = u0x10002b21(0x004bc537:10dd) & u0x10002b25(0x004bc537:10de)
0x004b8d8d:1114:	u0x10002bba(0x004b8d8d:1114) = ~ u0x10002b29(0x004bc537:10e1)
0x004b8d8d:1115:	u0x10002bbe(0x004b8d8d:1115) = ~ u0x100029ee(0x004718a9:1069)
0x004b8d8d:1118:	u0x10002bc2(0x004b8d8d:1118) = u0x10002bba(0x004b8d8d:1114) & u0x10002bbe(0x004b8d8d:1115)
0x004acf24:1159:	u0x1000301d(0x004acf24:1159) = EBP(i) + #0xfffffffc
0x004acf24:13bd:	u0x10002c63(0x004acf24:13bd) = (cast) u0x1000301d(0x004acf24:1159)
0x004ba046:118c:	*(ram,u0x10002c63(0x004acf24:13bd)) = u0x10002bc2(0x004b8d8d:1118)
0x0046a912:11a9:	EAX(0x0046a912:11a9) = u0x10002090(0x004742e4:cd0)
0x0046a912:11ab:	ESI(0x0046a912:11ab) = ESI(i)
0x0046a912:11ad:	EBX(0x0046a912:11ad) = EBX(i)
0x0046a912:11b1:	EDI(0x0046a912:11b1) = EDI(i)
0x0046a912:11b3:	ECX(0x0046a912:11b3) = u0x10002629(0x00440238:ef3)
0x0046a912:11b5:	EDX(0x0046a912:11b5) = u0x10002bc2(0x004b8d8d:1118)
0x0046a912:11b7:	EBP(0x0046a912:11b7) = EBP(i)
0x0046a912:11bb:	return(EAX(0x0046a912:11a9)) ECX(0x0046a912:11b3),EDX(0x0046a912:11b5),EBX(0x0046a912:11ad),EBP(0x0046a912:11b7),ESI(0x0046a912:11ab),EDI(0x0046a912:11b1),EAX(0x0046a912:11a9),EDX(0x0046a912:11b5)

这样其实已经能够进行一些阅读分析了,再调用Ghidra的IR转C,得到以下C代码:

void sub_0(void)
{
  uint4 uVar1;
  uint4 uVar2;
  uint4 uVar3;
  xunknown4 unaff_EBX;
  int4 unaff_EBP;
  xunknown4 unaff_ESI;
  xunknown4 unaff_EDI;
  
  *(int4 *)(unaff_EBP + -4) = *(int4 *)(unaff_EBP + -4) + *(int4 *)(unaff_EBP + 8);
  *(int4 *)(unaff_EBP + -4) = *(int4 *)(unaff_EBP + -4) + *(int4 *)(unaff_EBP + 0xc);
  *(uint4 *)(unaff_EBP + -4) = ~(~*(uint4 *)(unaff_EBP + -4) + *(int4 *)(unaff_EBP + 8));
  *(uint4 *)(unaff_EBP + -4) = ~(~*(uint4 *)(unaff_EBP + -4) + *(int4 *)(unaff_EBP + 0xc));
  *(int4 *)(unaff_EBP + -4) = *(int4 *)(unaff_EBP + 8) * *(int4 *)(unaff_EBP + -4);
  *(int4 *)(unaff_EBP + -4) = *(int4 *)(unaff_EBP + 0xc) * *(int4 *)(unaff_EBP + -4);
  *(uint4 *)(unaff_EBP + -4) = *(uint4 *)(unaff_EBP + -4) / *(uint4 *)(unaff_EBP + 0xc);
  *(uint4 *)(unaff_EBP + -4) = *(uint4 *)(unaff_EBP + -4) & *(uint4 *)(unaff_EBP + 0xc);
  uVar2 = *(uint4 *)(unaff_EBP + -4);
  *(uint4 *)(unaff_EBP + -4) = uVar2 % *(uint4 *)(unaff_EBP + 8);
  uVar1 = ~(~*(uint4 *)(unaff_EBP + -4) & ~*(uint4 *)(unaff_EBP + 8)) &
          ~(*(uint4 *)(unaff_EBP + -4) & *(uint4 *)(unaff_EBP + 8));
  *(uint4 *)(unaff_EBP + -4) = uVar1;
  uVar3 = ~(~*(uint4 *)(unaff_EBP + -4) & ~*(uint4 *)(unaff_EBP + 0xc)) &
          ~(*(uint4 *)(unaff_EBP + -4) & *(uint4 *)(unaff_EBP + 0xc));
  *(uint4 *)(unaff_EBP + -4) = uVar3;
  uVar2 = uVar2 / *(uint4 *)(unaff_EBP + 8);
  return uVar1;
}

整理一下

[ebp-4] = [ebp-4] + [ebp+8]
[ebp-4] = [ebp-4] + [ebp+C]
[ebp-4] = ~(~[ebp-4] + [ebp+8])
[ebp-4] = ~(~[ebp-4] + [ebp+C])
[ebp-4] = [ebp+8] * [ebp-4]
[ebp-4] = [ebp+C] * [ebp-4]
[ebp-4] = [ebp-4] / [ebp+C];
[ebp-4] = [ebp-4] & [ebp+C];
[ebp-4] = [ebp-4] % [ebp+8]
[ebp-4] = ~(~[ebp-4] & ~[ebp+8]) & ~([ebp-4] & [ebp+8]);
[ebp-4] = ~(~[ebp-4] & ~[ebp+C]) & ~([ebp-4] & [ebp+C]);

好像还可以接受。


总结

1、目前只是做了一次基础的还原尝试,像vmp中重要的分支跳转、call很多问题都还没有处理,像这一次vJmp handler我都是把它当成add esp,0x4来忽略掉的

2、我个人认为vmp将一套指令集转换为另一套指令集,中间信息可能会发生损失,因此没必要再还原回汇编了,就直接对vmp的opcode进行反编译分析,其实还挺不错。

3、vmp将一些基础运算进行了变异,像上面的减法和异或运算,这些后续理论上也可以继续编写Ghidra规则来进行优化。



[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2023-9-27 16:52 被fjqisba编辑 ,原因:
收藏
点赞5
打赏
分享
最新回复 (6)
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_fprfytok 2023-9-27 13:33
2
0
大佬移动端加壳的VMP研究过没
雪    币: 6
活跃值: (980)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lookzo 2023-9-27 13:56
3
0
非常好,大佬给了一个还原方向
雪    币: 3671
活跃值: (3848)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 2023-9-27 16:35
4
0
6666
雪    币: 452
活跃值: (1069)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
wInFoG_2017 2023-9-28 09:51
5
0
我不太熟悉VMP,看着文章感觉它好像是个基于栈的虚拟机?这里面的“给每个handler编写IR生成代码”这个是怎么做的?(难道是手写的吗)虽然Ghidra里面也有对JVM字节码的反编译描述实现,但是那一套描述十分的。。。丑
雪    币: 4016
活跃值: (5833)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
fjqisba 2023-9-28 10:37
6
1
wInFoG_2017 我不太熟悉VMP,看着文章感觉它好像是个基于栈的虚拟机?这里面的“给每个handler编写IR生成代码”这个是怎么做的?(难道是手写的吗)虽然Ghidra里面也有对JVM字节码的反编译描述实现,但是那 ...

对,我估计vmp相当于是把X86指令集转成类似于C#、JAVA那种基于堆栈的指令集了,当然C#和JAVA我也不太懂。

给每个handler编写IR生成代码,这个由于Ghidra是开源的做起来并不难,Ghidra将汇编转成IR的逻辑都在Sleigh::oneInstruction函数里面,分析清楚IR的结构,就能主动给Funcdata添加IR,比如下面是构造一个push const的IR代码

void FuncBuildHelper::BuildPushConst(ghidra::Funcdata& data, size_t addr, size_t val)
{
    auto regESP = data.getArch()->translate->getRegister("ESP");

    ghidra::Address pc = ghidra::Address(data.getArch()->getDefaultCodeSpace(), addr);
    ghidra::PcodeOp* opCopy = data.newOp(1, pc);
    data.opSetOpcode(opCopy, ghidra::CPUI_COPY);
    ghidra::Varnode* uniqReg = data.newUniqueOut(4, opCopy);
    data.opSetInput(opCopy, data.newConstant(0x4, val), 0);

    ghidra::PcodeOp* opSub = data.newOp(2, pc);
    data.opSetOpcode(opSub, ghidra::CPUI_INT_SUB);
    data.newVarnodeOut(regESP.size, regESP.getAddr(), opSub);
    data.opSetInput(opSub, data.newVarnode(regESP.size, regESP.space, regESP.offset), 0);
    data.opSetInput(opSub, data.newConstant(4, 0x4), 1);

    ghidra::PcodeOp* opStore = data.newOp(3, pc);
    data.opSetOpcode(opStore, ghidra::CPUI_STORE);
    data.opSetInput(opStore, data.newVarnodeSpace(data.getArch()->getSpaceByName("ram")), 0);
    data.opSetInput(opStore, data.newVarnode(regESP.size, regESP.space, regESP.offset), 1);
    data.opSetInput(opStore, uniqReg, 2);
}


雪    币: 19389
活跃值: (29037)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-11-7 18:28
7
1
感谢分享
游客
登录 | 注册 方可回帖
返回