VMProtect是一種很可靠的工具,可以保護(hù)應(yīng)用程序代碼免受分析和破解,但只有在應(yīng)用程序內(nèi)保護(hù)機(jī)制正確構(gòu)建且沒(méi)有可能破壞整個(gè)保護(hù)的嚴(yán)重錯(cuò)誤的情況下,才能實(shí)現(xiàn)最好的效果。
VMProtect通過(guò)在具有非標(biāo)準(zhǔn)體系結(jié)構(gòu)的虛擬機(jī)上執(zhí)行代碼來(lái)保護(hù)代碼,這將使分析和破解軟件變得十分困難。除此之外,VMProtect還可以生成和驗(yàn)證序列號(hào),限制免費(fèi)升級(jí)等等。
下載VMProtect最新試用版
VMProtect正版授權(quán)在線訂購(gòu)享受最低價(jià),僅售801元起!還不趕緊加入你的訂購(gòu)清單?>>更多詳情可點(diǎn)擊咨詢購(gòu)買
Tls回調(diào)函數(shù)(上)
參考上節(jié)的跟蹤記錄vm_tls.txt,可以看到第117行和第290行的VmCALL將代碼分成3塊,標(biāo)記為Chunk1 - Chunk3,我們先看下VmCALL的實(shí)現(xiàn),再分別分析這3塊代碼。
VmCALL
可以看到,VmCALL取棧中DWORD作為基數(shù)計(jì)算RBX和RSI,我們第一篇分析過(guò),RSI指向字節(jié)碼緩沖區(qū),RBX為解密Seed,也就是說(shuō)每個(gè)Chunk都有自己的RSI和RBX。
Chunk1
在繼續(xù)分析Chunk之前,可先參考下節(jié)Nor Gate說(shuō)明,其對(duì)用到的運(yùn)算的Nor變換做了詳細(xì)說(shuō)明,下面的分析不在贅述。
[Anakin] VmPOP V_98 ;V_98 = $HandlerBase
[Anakin] VmPUSH FFFFFFFF9F5A5C32
[Anakin] VmADD
[Anakin] VmPOP V_40
[Anakin] VmPOP V_B8
[Anakin] VmPOP V_28
[Anakin] VmPOP V_18
[Anakin] VmPOP V_00
[Anakin] VmPOP V_78
[Anakin] VmPOP V_A0
[Anakin] VmPOP V_90
[Anakin] VmPOP V_40
[Anakin] VmPOP V_20
[Anakin] VmPOP V_68
[Anakin] VmPOP V_50
[Anakin] VmPOP V_58
[Anakin] VmPOP V_30
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_38
[Anakin] VmPOP V_48
[Anakin] VmPOP V_70
[Anakin] VmPOP V_88
[Anakin] VmPOP V_10
[Anakin] VmPOP V_A8
[Anakin] VmPUSH 0000000064765E24 ;壓棧分支1標(biāo)識(shí)
[Anakin] VmPUSHB8 00
[Anakin] VmPUSH 000000014018B3E7
[Anakin] VmPUSH V_98
[Anakin] VmADD
[Anakin] VmPOP V_08
[Anakin] VmREADB ;b = BYTE:[000000014018B3E7 + $HandlerBase]
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = ~b
[Anakin] VmPOP V_60
[Anakin] VmADDB ;b = 00 + b
[Anakin] VmPOP V_10 ;V_10 = eflags
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = ~b
[Anakin] VmPOP V_80 ;V_80 = eflags
[Anakin] VmPOPW8 V_60 ;V_60 = b
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_10
[Anakin] VmNOTAND ;d1 = NOTAND(V_10, V_10) => d1 = ~V_10
[Anakin] VmPOP V_60
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND ;d1 = NOTAND(d1, FFFFF7EA) => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_80
[Anakin] VmNOTAND ;d2 = NOTAND(V_80, V_80) => d2 = ~V_80
[Anakin] VmPOP V_60
[Anakin] VmPUSH 0000000000000815
[Anakin] VmNOTAND ;d2 = NOTAND(d2, 00000815) => d2 = Nor(~V_80, ~FFFFF7EA) = V_80 & FFFFF7EA
[Anakin] VmPOP V_08
[Anakin] VmADD
[Anakin] VmPOP V_08
[Anakin] VmPOP V_70 ;V_70 = d1 + d2 => V_70 = EFLAGS(BYTE:[000000014018B3E7 + $HandlerBase] - 0)
[Anakin] VmPUSH 0000000064766651 ;壓棧分支2標(biāo)識(shí)
[Anakin] VmSBP ;壓棧棧頂指針,用于后文選擇分支
[Anakin] VmPUSHB8 03
[Anakin] VmPUSHD 000000BF
[Anakin] VmPUSH V_70
[Anakin] VmNOTAND ;q = CDQ(NOTAND(V_70, 000000BF)) => ZF == 0 ? 0b1000000 : 0
[Anakin] VmPOP V_68
[Anakin] VmSHR ;q = SHR(q, 3) => ZF == 0 ? 8 : 0
[Anakin] VmPOP V_08
[Anakin] VmADD ;q += SavedRBP (上文壓棧的棧頂指針,選擇分支)
[Anakin] VmPOP V_08
[Anakin] VmREADQ
[Anakin] VmPOP V_A8 ;V_A8 = QWORD:[q](取分支標(biāo)識(shí))
[Anakin] VmPOP V_68
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_A8
[Anakin] VmPOPD V_A8 ;V_A8 = CQD(V_A8)
[Anakin] VmPUSHD V_A8
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD ;d1 = NOTAND(V_A8, V_A8)
[Anakin] VmPOP V_08
[Anakin] VmPUSHD DB91AA8C
[Anakin] VmNOTANDD ;d1 = NOTAND(d1, DB91AA8C) => d1 = Nor(~V_A8, ~246E5573)
[Anakin] VmPOP V_68
[Anakin] VmPUSHD 246E5573
[Anakin] VmPUSHD V_A8
[Anakin] VmNOTANDD ;d2 = NOTAND(V_A8, 246E5573) => d2 = Nor(V_A8, 246E5573)
[Anakin] VmPOP V_60
[Anakin] VmNOTANDD
[Anakin] VmPOP V_60
[Anakin] VmPOP V_08 ;V_08 = NOTAND(d2, d1) => V_08 = Nor(d1, d2) = V_A8 ^ 246E5573 (分支標(biāo)識(shí)解密)
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_60
[Anakin] VmPUSH V_00
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_30
[Anakin] VmPUSH V_B0
[Anakin] VmPUSH V_20
[Anakin] VmPUSH V_28
[Anakin] VmPUSH V_38
[Anakin] VmPUSH V_78
[Anakin] VmPUSH V_A0
[Anakin] VmPUSH V_90
[Anakin] VmPUSH V_58
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_40
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_B8
[Anakin] VmPUSH 0000000060A5A3CE
[Anakin] VmADD
[Anakin] VmPOP V_60
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_08 ;壓棧解碼后的分支標(biāo)識(shí)
[Anakin] VmCALL ;調(diào)用選擇分支
等價(jià)邏輯:
If (*(BYTE*)(000000014018B3E7 + $HandlerBase) != 0)
{
//未執(zhí)行
VmCALL 40180B57
}
Else
{
//即Chunk2
VmCALL 40183322
}
Chunk2
[Anakin] VmPOP V_90 ;V_90 = $HandlerBase
[Anakin] VmPUSH FFFFFFFF9F5A5C32
[Anakin] VmADD
[Anakin] VmPOP V_20
[Anakin] VmPOP V_00
[Anakin] VmPOP V_70
[Anakin] VmPOP V_80
[Anakin] VmPOP V_60
[Anakin] VmPOP V_98
[Anakin] VmPOP V_38
[Anakin] VmPOP V_48
[Anakin] VmPOP V_28
[Anakin] VmPOP V_18
[Anakin] VmPOP V_30
[Anakin] VmPOP V_10
[Anakin] VmPOP V_88
[Anakin] VmPOP V_08
[Anakin] VmPOP V_A8
[Anakin] VmPOP V_40
[Anakin] VmPOP V_20
[Anakin] VmPOP V_68
[Anakin] VmPOPD V_78 ;V_78 = eflags
[Anakin] VmPUSHD V_78
[Anakin] VmPUSHD V_78
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPUSHD DB91AA8C
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B8
[Anakin] VmPUSHD 246E5573
[Anakin] VmPUSHD V_78
[Anakin] VmNOTANDD
[Anakin] VmPOP V_50
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_A0 ;V_A0 = V_78 ^ 246E5573
[Anakin] VmPOP V_58
[Anakin] VmPOP V_B8
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_08
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_A8
[Anakin] VmPUSH 000000000CABFA9E ;PUSH Branch1
[Anakin] VmPUSH 000000014018B3E7
[Anakin] VmPUSH V_90
[Anakin] VmADD
[Anakin] VmPOP V_50 ;PUSH (V_90 + 000000014018B3E7)
[Anakin] VmPUSH 0000000140000000
[Anakin] VmPUSH V_90
[Anakin] VmADD
[Anakin] VmPOP V_58
[Anakin] VmPOP V_50 ;V_50 = V_90 + 0000000140000000 => V_50 = PIMAGE_DOS_HEADR
[Anakin] VmPUSH V_50
[Anakin] VmPUSHD 0000003C
[Anakin] VmADD
[Anakin] VmPOP V_58 ;PUSH (V_50 + 0000003C)
[Anakin] VmREADD
[Anakin] VmPOPD V_88 ;V_88 = DWORD:[BP] => V_88 = PIMAGE_DOS_HEADER->e_lfanew
[Anakin] VmPUSH 0000000000000000
[Anakin] VmPOPD V_8C
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_50
[Anakin] VmADD
[Anakin] VmPOP V_A8 ;PUSH (V_50 + V_88) => PUSH PIMAGE_NT_HEADERS64
[Anakin] VmSBP
[Anakin] VmREADQ
[Anakin] VmPOP V_B0
[Anakin] VmPUSHD 00000028
[Anakin] VmADD
[Anakin] VmPOP V_A8 ;PUSH (PIMAGE_NT_HEADERS64 + 00000028) => PUSH PIMAGE_NT_HEADERS64->AddressOfEntryPoint
[Anakin] VmREADD
[Anakin] VmPOPD V_B0 ;V_B0 = AddressOfEntryPoint
[Anakin] VmPUSH 0000000000000000
[Anakin] VmPOPD V_B4 ;V_B4 = 0
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_B0
[Anakin] VmADD
[Anakin] VmPOP V_A8
[Anakin] VmPOP V_A8 ;V_A8 = V_B0 + V_50
[Anakin] VmPUSHB8 cc
[Anakin] VmPUSH V_A8
[Anakin] VmREADB ;b = BYTE:[V_A8], 判斷程序入口點(diǎn)地址第一個(gè)字節(jié)是不是‘0xCC’
[Anakin] VmSBP ;判斷邏輯參考Chunk1及Nor Gate
[Anakin] VmREADB
[Anakin] VmNOTANDB
[Anakin] VmPOP V_58
[Anakin] VmADDB
[Anakin] VmPOP V_58
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB
[Anakin] VmPOP V_B8
[Anakin] VmPOPW8 V_70
[Anakin] VmPUSH V_58
[Anakin] VmSBP
[Anakin] VmREADQ
[Anakin] VmNOTAND
[Anakin] VmPOP V_88
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND
[Anakin] VmPOP V_B0
[Anakin] VmPUSH V_B8
[Anakin] VmPUSH V_B8
[Anakin] VmNOTAND
[Anakin] VmPOP V_70
[Anakin] VmPUSH 0000000000000815
[Anakin] VmNOTAND
[Anakin] VmPOP V_88
[Anakin] VmADD
[Anakin] VmPOP V_88
[Anakin] VmPOP V_70
[Anakin] VmPOP V_88
[Anakin] VmPUSH 000000000CABFDC1 ;PUSH Branch2
[Anakin] VmSBP
[Anakin] VmPUSHB8 03
[Anakin] VmPUSHD 000000BF
[Anakin] VmPUSH V_70
[Anakin] VmNOTAND
[Anakin] VmPOP V_A0
[Anakin] VmSHR
[Anakin] VmPOP V_B0
[Anakin] VmADD
[Anakin] VmPOP V_B0
[Anakin] VmREADQ
[Anakin] VmPOP V_58
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_58
[Anakin] VmPOPD V_58
[Anakin] VmPUSHD V_58
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD
[Anakin] VmPOP V_A0
[Anakin] VmPUSHD B34CBE36
[Anakin] VmNOTANDD
[Anakin] VmPOP V_78
[Anakin] VmPUSHD 4CB341C9
[Anakin] VmPUSHD V_58
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmNOTANDD
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_08 ;V_08 = $Branch ^ 4CB341C9
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_08
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_B0
[Anakin] VmPUSH V_40
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_38
[Anakin] VmPUSH V_98
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_68
[Anakin] VmPUSH V_28
[Anakin] VmPUSH V_30
[Anakin] VmPUSH V_48
[Anakin] VmPUSH V_60
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_A8
[Anakin] VmPUSH V_20
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_00
[Anakin] VmPUSH 0000000060A5A3CE
[Anakin] VmADD
[Anakin] VmPOP V_B0
[Anakin] VmPUSH V_90
[Anakin] VmPUSH V_08 ;壓棧選擇的分支
[Anakin] VmCALL
等價(jià)邏輯:
If (*(BYTE*)($ImageBase + AddressOfEntryPoint) != 0xCC)
{
//即Chunk3
VmCALL 4018BB57
}
Else
{
//雖然調(diào)試器設(shè)置默認(rèn)在入口地址處下int3斷點(diǎn),但是我們的腳本啟動(dòng)時(shí),會(huì)把所有斷點(diǎn)禁用,因此并沒(méi)有走Else分支。
VmCALL 4018BC08
}
Chunk3
[Anakin] VmPOP V_A8
[Anakin] VmPUSH FFFFFFFF9F5A5C32
[Anakin] VmADD
[Anakin] VmPOP V_10
[Anakin] VmPOP V_10
[Anakin] VmPOP V_30
[Anakin] VmPOP V_28
[Anakin] VmPOP V_08
[Anakin] VmPOP V_B8
[Anakin] VmPOP V_60
[Anakin] VmPOP V_88
[Anakin] VmPOP V_40
[Anakin] VmPOP V_70
[Anakin] VmPOP V_A0
[Anakin] VmPOP V_B0
[Anakin] VmPOP V_18
[Anakin] VmPOP V_48
[Anakin] VmPOP V_00
[Anakin] VmPOP V_80
[Anakin] VmPOP V_90
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmPOPD V_38
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD
[Anakin] VmPOP V_68
[Anakin] VmPUSHD B34CBE36
[Anakin] VmNOTANDD
[Anakin] VmPOP V_50
[Anakin] VmPUSHD V_38
[Anakin] VmPUSHD 4CB341C9
[Anakin] VmNOTANDD
[Anakin] VmPOP V_98
[Anakin] VmNOTANDD
[Anakin] VmPOP V_20
[Anakin] VmPOP V_20
[Anakin] VmPOP V_68
[Anakin] VmPOP V_98
[Anakin] VmPOP V_78
[Anakin] VmPOP V_50
[Anakin] VmPOP V_58
[Anakin] VmPOP V_78
[Anakin] VmPOP V_28
[Anakin] VmPOP V_40
[Anakin] VmPOP V_80
[Anakin] VmPOP V_68
[Anakin] VmPUSH V_68
[Anakin] VmSBP
[Anakin] VmREADQ
[Anakin] VmNOTAND
[Anakin] VmPOP V_48
[Anakin] VmPUSH 00000000000008FF
[Anakin] VmNOTAND
[Anakin] VmPOP V_B8
[Anakin] VmPOPFQ
[Anakin] VmPUSH V_08
[Anakin] VmPUSH V_20
[Anakin] VmPUSH V_78
[Anakin] VmPUSH V_70
[Anakin] VmPUSH V_40
[Anakin] VmPUSH V_50
[Anakin] VmPUSH V_00
[Anakin] VmPUSH V_90
[Anakin] VmPUSH V_68
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_88
[Anakin] VmPUSH V_28
[Anakin] VmPUSH V_A0
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_B0
[Anakin] VmPUSH V_58
[Anakin] VmPUSH V_60
[Anakin] VmPUSH V_18
[Anakin] VmPUSH V_A8
[Anakin] VmRet
沒(méi)有特別需要關(guān)注的信息,處理寄存器,函數(shù)執(zhí)行完畢,返回調(diào)用處。
綜上,Tls的執(zhí)行邏輯為:
If (*(BYTE*)(000000014018B3E7 + $HandlerBase) != 0)
{
//未執(zhí)行
VmCALL 40180B57
}
Else
{
If (*(BYTE*)($ImageBase + AddressOfEntryPoint) != 0xCC)
{
Return
}
Else
{
//雖然調(diào)試器設(shè)置默認(rèn)在入口地址處下int3斷點(diǎn),但是我們的腳本運(yùn)行時(shí),會(huì)把所有斷點(diǎn)禁用(line 15),因此并沒(méi)有走Else分支。
//PS: 這個(gè)分支會(huì)在 $HandlerBase + 000000014018B3E8 地址處寫一個(gè)字節(jié)‘0x01’,然后返回。
// 此處暫略,后文分析反調(diào)試時(shí)再談。
VmCALL 4018BC08
}
}
Nor Gate
基本單元:或非門(Nor)
兩個(gè)輸入位皆為0時(shí)輸出1,其它情況輸出0.
PS: VMP實(shí)現(xiàn)的NOTAND操作使用了Not和And操作,有些文檔稱之為'與非門',但是從邏輯語(yǔ)義上來(lái)說(shuō),其實(shí)現(xiàn)的是'或非'操作(見(jiàn)上表),此處遵從語(yǔ)義將其稱之為或非門(Nor)。
取反(~)
[Anakin] VmREADB ;b = BYTE:[000000014018B3E7 + $HandlerBase]
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = NOTAND(b, b)
取反計(jì)算~v實(shí)現(xiàn)如下:
Result = Nor(v, v)
輸入1 輸入2 Result
0 0 1
1 1 0
與(&)
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_10
[Anakin] VmNOTAND ;d1 = NOTAND(V_10, V_10) => d1 = ~V_10
[Anakin] VmPOP V_60
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND ;d1 = NOTAND(d1, FFFFF7EA) => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815
與計(jì)算v1&v2實(shí)現(xiàn)如下:
D1 = ~v1
D2 = ~v2
Result = Nor(D1, D2)
異或(^)
[Anakin] VmPUSHD V_A8 ;V_A8 = CQD(V_A8)
[Anakin] VmSBP
[Anakin] VmREADD
[Anakin] VmNOTANDD ;d1 = NOTAND(V_A8, V_A8) => d1 = ~V_A8
[Anakin] VmPOP V_08
[Anakin] VmPUSHD DB91AA8C
[Anakin] VmNOTANDD ;d1 = NOTAND(d1, DB91AA8C) => d1 = Nor(~V_A8, ~246E5573)
[Anakin] VmPOP V_68
[Anakin] VmPUSHD 246E5573
[Anakin] VmPUSHD V_A8
[Anakin] VmNOTANDD ;d2 = NOTAND(V_A8, 246E5573) => d2 = Nor(V_A8, 246E5573)
[Anakin] VmPOP V_60
[Anakin] VmNOTANDD
[Anakin] VmPOP V_60
[Anakin] VmPOP V_08 ;V_08 = NOTAND(d2, d1) => V_08 = Nor(d1, d2) = V_A8 ^ 246E5573
異或計(jì)算v1^v2實(shí)現(xiàn)如下:
D1 = Nor(~v1, ~v2) = v1 & v2
D2 = Nor(v1, v2)
Result = Nor(D1, D2)
減法(-)
[Anakin] VmREADB ;b = BYTE:[000000014018B3E7 + $HandlerBase]
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = NOTAND(b, b) = ~b
[Anakin] VmPOP V_60
[Anakin] VmADDB ;b = 00 + b
[Anakin] VmPOP V_10 ;V_10 = eflags
[Anakin] VmSBP
[Anakin] VmREADB
[Anakin] VmNOTANDB ;b = NOTAND(b, b) = ~b
[Anakin] VmPOP V_80 ;V_80 = eflags
[Anakin] VmPOPW8 V_60 ;V_60 = b = BYTE:[000000014018B3E7 + $HandlerBase] - 0
反碼實(shí)現(xiàn)減法運(yùn)算v1-v2如下:
D1 = ~v1
D2 = D1 + v2
Result = ~D2, 即 Result = ~(~v1 + v2)
此處不做推導(dǎo),看幾個(gè)實(shí)例:
再看下對(duì)eflags的處理:
[Anakin] VmPUSH V_10
[Anakin] VmPUSH V_10
[Anakin] VmNOTAND ;d1 = NOTAND(V_10, V_10) => d1 = ~V_10
[Anakin] VmPOP V_60
[Anakin] VmPUSH FFFFFFFFFFFFF7EA
[Anakin] VmNOTAND ;d1 = NOTAND(d1, FFFFF7EA) => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815
[Anakin] VmPOP V_08
[Anakin] VmPUSH V_80
[Anakin] VmPUSH V_80
[Anakin] VmNOTAND ;d2 = NOTAND(V_80, V_80) => d2 = ~V_80
[Anakin] VmPOP V_60
[Anakin] VmPUSH 0000000000000815
[Anakin] VmNOTAND ;d2 = NOTAND(d2, 00000815) => d2 = Nor(~V_80, ~FFFFF7EA) = V_80 & FFFFF7EA
[Anakin] VmPOP V_08
[Anakin] VmADD
[Anakin] VmPOP V_08
[Anakin] VmPOP V_70 ;V_70 = d1 + d2
其中FFFFF7EA = ~00000815, 00000815 = 0b100000010101。
eflags定義如下:
V_10和V_80皆為eflags, 可以看到v_70 由 V_10的CF, PF, AF及OF位 +(or) V_80的其它位(ZF, SF等)得到。
V_10由VmADDB置位,最后指令為Add, 受影響標(biāo)志位為 OF, SF, ZF, AF, CF, PF;
V_80由VmNOTANDB置位,最后指令為And, 受影響標(biāo)志位為OF(0), CF(0), SF, ZF, PF。
簡(jiǎn)單考慮最常用到的SF和ZF,可以看到這兩個(gè)標(biāo)志位是可以正確反映運(yùn)算結(jié)果的。
不等(!=)
[Anakin] VmPUSHB8 03
[Anakin] VmPUSHD 000000BF
[Anakin] VmPUSH V_70
[Anakin] VmNOTAND ;q = CDQ(NOTAND(V_70, 000000BF))
[Anakin] VmPOP V_68
[Anakin] VmSHR ;q = SHR(q, 3) = ZF == 0 ? 8 : 0
[Anakin] VmPOP V_08
[Anakin] VmADD ;q += SavedRBP
[Anakin] VmPOP V_08
[Anakin] VmREADQ
[Anakin] VmPOP V_A8 ;V_A8 = QWORD:[q]
不等判斷需結(jié)合上文的'減法'分析,代碼中V_70為eflag(v1 - v2);
像And操作取'1'位一樣,Nor操作可以取'0'位,上述代碼Nor(V_70, 000000BF),其中000000BF = 0b10111111。可以看到當(dāng)ZF標(biāo)志位為0時(shí)(!=, 即兩數(shù)相減結(jié)果不為0時(shí)),返回0b1000000,否則返回0。
結(jié)合之后的SHR及取棧數(shù)據(jù)代碼, 可以進(jìn)一步猜想SHR 3 是經(jīng)過(guò)優(yōu)化的代碼,如下:
優(yōu)化前:Bool b = Nor(Eflags(v1 - v2), 000000BF) >> 6;Qword offset = b << 3;
優(yōu)化后:Qword offset = Nor(Eflags(v1 - v2), 000000BF) >> 3;
計(jì)算v1 != v2得實(shí)現(xiàn)如下:
(Nor(Eflags(v1 - v2), 000000BF) >> 6) == 1。
如果您對(duì)該加密/解密軟件感興趣,歡迎加入vmpQQ交流群:740060302
標(biāo)簽:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@ke049m.cn
文章轉(zhuǎn)載自:看雪