首页
论坛
课程
招聘
[原创]VMProtect分析(三)
2021-7-16 18:26 10142

[原创]VMProtect分析(三)

2021-7-16 18:26
10142

VmProtect分析(一)

VmProtect分析(二)


Tls回调函数(下)

参考上节的跟踪记录vm_tls.txt,可以看到第117行和第290行的VmCALL将代码分成3块,标记为Chunk1 - Chunk3,我们先看下VmCALL的实现,再分别分析这3块代码。


VmCALL

shrd rsi,rbx,cl


mov esi,dword ptr ss:[rbp]

Esi = 栈顶DWORD

clc


stc


add rbp,8


jmp   vmp_userdebugger.7FF69E7403F7


bsf ax,di


sar r12d,cl


inc r12d


shl ch,5


lea r12,qword ptr ds:[7FF69E74065C]

R12 固定取7FF69E74065C

rcl al,7


not bh


mov rax,100000000


rcr rbx,10


add rsi,rax

Rsi += 100000000

xchg al,bh


bsr bx,dx


shld bx,sp,cl


rcr ebx,cl


mov rbx,rsi

Rbx = Rsi

movsx cx,cl


add rsi,qword ptr ss:[rbp]

Rsi += 栈顶QWORD, 注意此处未调整RBP栈指针

可以看到,VmCALL取栈中DWORD作为基数计算RBX和RSI,我们第一篇分析过,RSI指向字节码缓冲区,RBX为解密Seed,也就是说每个Chunk都有自己的RSI和RBX。


Chunk1

在继续分析Chunk之前,可先参考下节Nor Gate说明,其对用到的运算的Nor变换做了详细说明,下面的分析不在赘述。

 

[AnakinVmPOP V_98                 ;V_98 = $HandlerBase

[AnakinVmPUSH FFFFFFFF9F5A5C32

[AnakinVmADD

[AnakinVmPOP V_40

[AnakinVmPOP V_B8

[AnakinVmPOP V_28

[AnakinVmPOP V_18

[AnakinVmPOP V_00

[AnakinVmPOP V_78

[AnakinVmPOP V_A0

[AnakinVmPOP V_90

[AnakinVmPOP V_40

[AnakinVmPOP V_20

[AnakinVmPOP V_68

[AnakinVmPOP V_50

[AnakinVmPOP V_58

[AnakinVmPOP V_30

[AnakinVmPOP V_B0

[AnakinVmPOP V_38

[AnakinVmPOP V_48

[AnakinVmPOP V_70

[AnakinVmPOP V_88

[AnakinVmPOP V_10

[AnakinVmPOP V_A8

[AnakinVmPUSH 0000000064765E24    ;压栈分支1标识

[AnakinVmPUSHB8 00

[AnakinVmPUSH 000000014018B3E7

[AnakinVmPUSH V_98

[AnakinVmADD

[AnakinVmPOP V_08

[AnakinVmREADB                    ;b = BYTE:[000000014018B3E7 + $HandlerBase]

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB                  ;b = ~b

[AnakinVmPOP V_60         

[AnakinVmADDB                     ;b = 00 + b

[AnakinVmPOP V_10                 ;V_10 = eflags

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB                  ;b = ~b

[AnakinVmPOP V_80                 ;V_80 = eflags

[AnakinVmPOPW8 V_60               ;V_60 = b  

[AnakinVmPUSH V_10

[AnakinVmPUSH V_10

[AnakinVmNOTAND                   ;d1 = NOTAND(V_10, V_10)            => d1 = ~V_10

[AnakinVmPOP V_60

[AnakinVmPUSH FFFFFFFFFFFFF7EA

[AnakinVmNOTAND                   ;d1 = NOTAND(d1, FFFFF7EA)          => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815

[AnakinVmPOP V_08

[AnakinVmPUSH V_80                

[AnakinVmPUSH V_80

[AnakinVmNOTAND                   ;d2 = NOTAND(V_80, V_80)            => d2 = ~V_80

[AnakinVmPOP V_60

[AnakinVmPUSH 0000000000000815

[AnakinVmNOTAND                   ;d2 = NOTAND(d2, 00000815)          => d2 = Nor(~V_80, ~FFFFF7EA) = V_80 & FFFFF7EA

[AnakinVmPOP V_08

[AnakinVmADD

[AnakinVmPOP V_08

[AnakinVmPOP V_70                 ;V_70 = d1 + d2                     => V_70 = EFLAGS(BYTE:[000000014018B3E7 + $HandlerBase] - 0)

[AnakinVmPUSH 0000000064766651    ;压栈分支2标识

[AnakinVmSBP                      ;压栈栈顶指针,用于后文选择分支

[AnakinVmPUSHB8 03

[AnakinVmPUSHD 000000BF

[AnakinVmPUSH V_70

[AnakinVmNOTAND                   ;q = CDQ(NOTAND(V_70, 000000BF))    => ZF == 0 ? 0b1000000 : 0 

[AnakinVmPOP V_68

[AnakinVmSHR                      ;q = SHR(q, 3)                      => ZF == 0 ? 8 : 0 

[AnakinVmPOP V_08

[AnakinVmADD                      ;q += SavedRBP (上文压栈的栈顶指针,选择分支)

[AnakinVmPOP V_08

[AnakinVmREADQ

[AnakinVmPOP V_A8                 ;V_A8 = QWORD:[q](取分支标识)

[AnakinVmPOP V_68

[AnakinVmPOP V_08

[AnakinVmPUSH V_A8

[AnakinVmPOPD V_A8                ;V_A8 = CQD(V_A8)

[AnakinVmPUSHD V_A8               

[AnakinVmSBP

[AnakinVmREADD

[AnakinVmNOTANDD                  ;d1 = NOTAND(V_A8, V_A8)

[AnakinVmPOP V_08

[AnakinVmPUSHD DB91AA8C

[AnakinVmNOTANDD                  ;d1 = NOTAND(d1, DB91AA8C)          => d1 = Nor(~V_A8, ~246E5573)

[AnakinVmPOP V_68

[AnakinVmPUSHD 246E5573

[AnakinVmPUSHD V_A8

[AnakinVmNOTANDD                  ;d2 = NOTAND(V_A8, 246E5573)        => d2 = Nor(V_A8, 246E5573)

[AnakinVmPOP V_60

[AnakinVmNOTANDD

[AnakinVmPOP V_60

[AnakinVmPOP V_08                 ;V_08 = NOTAND(d2, d1)              => V_08 = Nor(d1, d2) = V_A8 ^ 246E5573 (分支标识解密)

[AnakinVmPUSH V_18

[AnakinVmPUSH V_98

[AnakinVmPUSH V_60

[AnakinVmPUSH V_00

[AnakinVmPUSH V_88

[AnakinVmPUSH V_50

[AnakinVmPUSH V_30

[AnakinVmPUSH V_B0

[AnakinVmPUSH V_20

[AnakinVmPUSH V_28

[AnakinVmPUSH V_38

[AnakinVmPUSH V_78

[AnakinVmPUSH V_A0

[AnakinVmPUSH V_90

[AnakinVmPUSH V_58

[AnakinVmPUSH V_48

[AnakinVmPUSH V_40

[AnakinVmPUSH V_18

[AnakinVmPUSH V_70

[AnakinVmPUSH V_B8

[AnakinVmPUSH 0000000060A5A3CE

[AnakinVmADD

[AnakinVmPOP V_60

[AnakinVmPUSH V_98

[AnakinVmPUSH V_08                ;压栈解码后的分支标识                           

[AnakinVmCALL                      ;调用选择分支


等价逻辑:

If (*(BYTE*)(000000014018B3E7 + $HandlerBase) != 0)

{

//未执行

VmCALL 40180B57

}

Else

{

//即Chunk2

VmCALL 40183322

}


Chunk2

[AnakinVmPOP V_90                     ;V_90 = $HandlerBase

[AnakinVmPUSH FFFFFFFF9F5A5C32

[AnakinVmADD

[AnakinVmPOP V_20

[AnakinVmPOP V_00

[AnakinVmPOP V_70

[AnakinVmPOP V_80

[AnakinVmPOP V_60

[AnakinVmPOP V_98

[AnakinVmPOP V_38

[AnakinVmPOP V_48

[AnakinVmPOP V_28

[AnakinVmPOP V_18

[AnakinVmPOP V_30

[AnakinVmPOP V_10

[AnakinVmPOP V_88

[AnakinVmPOP V_08

[AnakinVmPOP V_A8

[AnakinVmPOP V_40

[AnakinVmPOP V_20

[AnakinVmPOP V_68

[AnakinVmPOPD V_78                    ;V_78 = eflags

[AnakinVmPUSHD V_78

[AnakinVmPUSHD V_78

[AnakinVmNOTANDD

[AnakinVmPOP V_B0

[AnakinVmPUSHD DB91AA8C

[AnakinVmNOTANDD

[AnakinVmPOP V_B8

[AnakinVmPUSHD 246E5573

[AnakinVmPUSHD V_78

[AnakinVmNOTANDD

[AnakinVmPOP V_50

[AnakinVmNOTANDD

[AnakinVmPOP V_B0

[AnakinVmPOP V_A0                     ;V_A0 = V_78 ^ 246E5573

[AnakinVmPOP V_58

[AnakinVmPOP V_B8

[AnakinVmPUSH V_70

[AnakinVmPUSH V_88

[AnakinVmPUSH V_08

[AnakinVmPUSH V_48

[AnakinVmPUSH V_98

[AnakinVmPUSH V_80

[AnakinVmPUSH V_A8

[AnakinVmPUSH 000000000CABFA9E        ;PUSH Branch1

[AnakinVmPUSH 000000014018B3E7

[AnakinVmPUSH V_90

[AnakinVmADD

[AnakinVmPOP V_50                     ;PUSH (V_90 + 000000014018B3E7)

[AnakinVmPUSH 0000000140000000

[AnakinVmPUSH V_90

[AnakinVmADD

[AnakinVmPOP V_58

[AnakinVmPOP V_50                     ;V_50 = V_90 + 0000000140000000         => V_50 = PIMAGE_DOS_HEADER

[AnakinVmPUSH V_50

[AnakinVmPUSHD 0000003C

[AnakinVmADD

[AnakinVmPOP V_58                     ;PUSH (V_50 + 0000003C)

[AnakinVmREADD

[AnakinVmPOPD V_88                    ;V_88 = DWORD:[BP]                      => V_88 = PIMAGE_DOS_HEADER->e_lfanew

[AnakinVmPUSH 0000000000000000

[AnakinVmPOPD V_8C

[AnakinVmPUSH V_88

[AnakinVmPUSH V_50

[AnakinVmADD

[AnakinVmPOP V_A8                     ;PUSH (V_50 + V_88)                     => PUSH PIMAGE_NT_HEADERS64

[AnakinVmSBP

[AnakinVmREADQ        

[AnakinVmPOP V_B0   

[AnakinVmPUSHD 00000028               

[AnakinVmADD

[AnakinVmPOP V_A8                     ;PUSH (PIMAGE_NT_HEADERS64 + 00000028)  => PUSH PIMAGE_NT_HEADERS64->AddressOfEntryPoint

[AnakinVmREADD

[AnakinVmPOPD V_B0                    ;V_B0 = AddressOfEntryPoint

[AnakinVmPUSH 0000000000000000

[AnakinVmPOPD V_B4                    ;V_B4 = 0

[AnakinVmPUSH V_50

[AnakinVmPUSH V_B0

[AnakinVmADD

[AnakinVmPOP V_A8

[AnakinVmPOP V_A8                     ;V_A8 = V_B0 + V_50

[AnakinVmPUSHB8 cc

[AnakinVmPUSH V_A8

[AnakinVmREADB                        ;b = BYTE:[V_A8], 判断程序入口点地址第一个字节是不是‘0xCC’

[AnakinVmSBP                          ;判断逻辑参考Chunk1Nor Gate

[AnakinVmREADB

[AnakinVmNOTANDB

[AnakinVmPOP V_58                     

[AnakinVmADDB

[AnakinVmPOP V_58

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB

[AnakinVmPOP V_B8

[AnakinVmPOPW8 V_70

[AnakinVmPUSH V_58

[AnakinVmSBP

[AnakinVmREADQ

[AnakinVmNOTAND

[AnakinVmPOP V_88

[AnakinVmPUSH FFFFFFFFFFFFF7EA

[AnakinVmNOTAND

[AnakinVmPOP V_B0

[AnakinVmPUSH V_B8

[AnakinVmPUSH V_B8

[AnakinVmNOTAND

[AnakinVmPOP V_70

[AnakinVmPUSH 0000000000000815

[AnakinVmNOTAND

[AnakinVmPOP V_88

[AnakinVmADD

[AnakinVmPOP V_88

[AnakinVmPOP V_70

[AnakinVmPOP V_88

[AnakinVmPUSH 000000000CABFDC1        ;PUSH Branch2

[AnakinVmSBP

[AnakinVmPUSHB8 03

[AnakinVmPUSHD 000000BF

[AnakinVmPUSH V_70

[AnakinVmNOTAND

[AnakinVmPOP V_A0

[AnakinVmSHR

[AnakinVmPOP V_B0

[AnakinVmADD

[AnakinVmPOP V_B0

[AnakinVmREADQ

[AnakinVmPOP V_58

[AnakinVmPOP V_B0

[AnakinVmPOP V_08

[AnakinVmPUSH V_58

[AnakinVmPOPD V_58

[AnakinVmPUSHD V_58

[AnakinVmSBP

[AnakinVmREADD

[AnakinVmNOTANDD

[AnakinVmPOP V_A0

[AnakinVmPUSHD B34CBE36

[AnakinVmNOTANDD

[AnakinVmPOP V_78

[AnakinVmPUSHD 4CB341C9       

[AnakinVmPUSHD V_58

[AnakinVmNOTANDD

[AnakinVmPOP V_B0

[AnakinVmNOTANDD

[AnakinVmPOP V_B0

[AnakinVmPOP V_08                     ;V_08 = $Branch ^ 4CB341C9

[AnakinVmPUSH V_50

[AnakinVmPUSH V_08

[AnakinVmPUSH V_80

[AnakinVmPUSH V_B0

[AnakinVmPUSH V_40

[AnakinVmPUSH V_88

[AnakinVmPUSH V_38

[AnakinVmPUSH V_98

[AnakinVmPUSH V_18

[AnakinVmPUSH V_68

[AnakinVmPUSH V_28

[AnakinVmPUSH V_30

[AnakinVmPUSH V_48

[AnakinVmPUSH V_60

[AnakinVmPUSH V_10

[AnakinVmPUSH V_A8

[AnakinVmPUSH V_20

[AnakinVmPUSH V_50

[AnakinVmPUSH V_70

[AnakinVmPUSH V_00

[AnakinVmPUSH 0000000060A5A3CE

[AnakinVmADD

[AnakinVmPOP V_B0

[AnakinVmPUSH V_90

[AnakinVmPUSH V_08                     ;压栈选择的分支

[AnakinVmCALL

 

等价逻辑:

If (*(BYTE*)($ImageBase + AddressOfEntryPoint) != 0xCC)

{

//即Chunk3

VmCALL 4018BB57

}

Else

{

//虽然调试器设置默认在入口地址处下int3断点,但是我们的脚本启动时,会把所有断点禁用,因此并没有走Else分支。

VmCALL 4018BC08

}


Chunk3

[AnakinVmPOP V_A8

[AnakinVmPUSH FFFFFFFF9F5A5C32

[AnakinVmADD

[AnakinVmPOP V_10

[AnakinVmPOP V_10

[AnakinVmPOP V_30

[AnakinVmPOP V_28

[AnakinVmPOP V_08

[AnakinVmPOP V_B8

[AnakinVmPOP V_60

[AnakinVmPOP V_88

[AnakinVmPOP V_40

[AnakinVmPOP V_70

[AnakinVmPOP V_A0

[AnakinVmPOP V_B0

[AnakinVmPOP V_18

[AnakinVmPOP V_48

[AnakinVmPOP V_00

[AnakinVmPOP V_80

[AnakinVmPOP V_90

[AnakinVmSBP

[AnakinVmREADD

[AnakinVmPOPD V_38

[AnakinVmSBP

[AnakinVmREADD

[AnakinVmNOTANDD

[AnakinVmPOP V_68

[AnakinVmPUSHD B34CBE36

[AnakinVmNOTANDD

[AnakinVmPOP V_50

[AnakinVmPUSHD V_38

[AnakinVmPUSHD 4CB341C9

[AnakinVmNOTANDD

[AnakinVmPOP V_98

[AnakinVmNOTANDD

[AnakinVmPOP V_20

[AnakinVmPOP V_20

[AnakinVmPOP V_68

[AnakinVmPOP V_98

[AnakinVmPOP V_78

[AnakinVmPOP V_50

[AnakinVmPOP V_58

[AnakinVmPOP V_78

[AnakinVmPOP V_28

[AnakinVmPOP V_40

[AnakinVmPOP V_80

[AnakinVmPOP V_68

[AnakinVmPUSH V_68

[AnakinVmSBP

[AnakinVmREADQ

[AnakinVmNOTAND

[AnakinVmPOP V_48

[AnakinVmPUSH 00000000000008FF

[AnakinVmNOTAND

[AnakinVmPOP V_B8

[AnakinVmPOPFQ

[AnakinVmPUSH V_08

[AnakinVmPUSH V_20

[AnakinVmPUSH V_78

[AnakinVmPUSH V_70

[AnakinVmPUSH V_40

[AnakinVmPUSH V_50

[AnakinVmPUSH V_00

[AnakinVmPUSH V_90

[AnakinVmPUSH V_68

[AnakinVmPUSH V_80

[AnakinVmPUSH V_88

[AnakinVmPUSH V_28

[AnakinVmPUSH V_A0

[AnakinVmPUSH V_18

[AnakinVmPUSH V_B0

[AnakinVmPUSH V_58

[AnakinVmPUSH V_60

[AnakinVmPUSH V_18

[AnakinVmPUSH V_A8

[AnakinVmRet

没有特别需要关注的信息,处理寄存器,函数执行完毕,返回调用处。


综上,Tls的执行逻辑为:

If (*(BYTE*)(000000014018B3E7 + $HandlerBase) != 0)

{

//未执行

VmCALL 40180B57

}

Else

{

If (*(BYTE*)($ImageBase + AddressOfEntryPoint) != 0xCC)

{

Return

}

Else

{

//虽然调试器设置默认在入口地址处下int3断点,但是我们的脚本运行时,会把所有断点禁用(line 15),因此并没有走Else分支。

//PS  这个分支会在 $HandlerBase + 000000014018B3E8 地址处写一个字节‘0x01’,然后返回。

//            此处暂略,后文分析反调试时再谈。

VmCALL 4018BC08

}

}



Nor Gate

基本单元:或非门(Nor)

两个输入位皆为0时输出1,其它情况输出0.

输入1

输入2

Result

0

0

1

0

1

0

1

0

0

1

1

0

PS: VMP实现的NOTAND操作使用了Not和And操作,有些文档称之为'与非门',但是从逻辑语义上来说,其实现的是'或非'操作(见上表),此处遵从语义将其称之为或非门(Nor)。


取反(~)

[AnakinVmREADB                    ;b = BYTE:[000000014018B3E7 + $HandlerBase]

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB                  ;b = NOTAND(b, b)

 

取反计算~v实现如下:

Result = Nor(v, v)

输入1

输入2

Result

0

0

1

1

1

0


与(&

[AnakinVmPUSH V_10

[AnakinVmPUSH V_10

[AnakinVmNOTAND                   ;d1 = NOTAND(V_10, V_10)            => d1 = ~V_10

[AnakinVmPOP V_60

[AnakinVmPUSH FFFFFFFFFFFFF7EA

[AnakinVmNOTAND                   ;d1 = NOTAND(d1, FFFFF7EA)          => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815

与计算v1&v2实现如下:

D1 = ~v1

D2 = ~v2

Result = Nor(D1, D2)

输入1

输入2

D1

D2

Result

0

0

1

1

0

0

1

1

0

0

1

0

0

1

0

1

1

0

0

1


异或(^

[AnakinVmPUSHD V_A8               ;V_A8 = CQD(V_A8)

[AnakinVmSBP

[AnakinVmREADD

[AnakinVmNOTANDD                  ;d1 = NOTAND(V_A8, V_A8)            => d1 = ~V_A8

[AnakinVmPOP V_08

[AnakinVmPUSHD DB91AA8C

[AnakinVmNOTANDD                  ;d1 = NOTAND(d1, DB91AA8C)          => d1 = Nor(~V_A8, ~246E5573)

[AnakinVmPOP V_68

[AnakinVmPUSHD 246E5573

[AnakinVmPUSHD V_A8

[AnakinVmNOTANDD                  ;d2 = NOTAND(V_A8, 246E5573)        => d2 = Nor(V_A8, 246E5573)

[AnakinVmPOP V_60

[AnakinVmNOTANDD

[AnakinVmPOP V_60

[AnakinVmPOP V_08                 ;V_08 = NOTAND(d2, d1)              => V_08 = Nor(d1, d2) = V_A8 ^ 246E5573

 

异或计算v1^v2实现如下:

D1 = Nor(~v1, ~v2) = v1 & v2

D2 = Nor(v1, v2)

Result = Nor(D1, D2)

输入1

输入2

D1

D2

Result

0

0

0

1

0

0

1

0

0

1

1

0

0

0

1

1

1

1

0

0

 

减法(-

[AnakinVmREADB                    ;b = BYTE:[000000014018B3E7 + $HandlerBase]

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB                  ;b = NOTAND(b, b) = ~b

[AnakinVmPOP V_60         

[AnakinVmADDB                     ;b = 00 + b

[AnakinVmPOP V_10                 ;V_10 = eflags

[AnakinVmSBP

[AnakinVmREADB

[AnakinVmNOTANDB                  ;b = NOTAND(b, b) = ~b

[AnakinVmPOP V_80                 ;V_80 = eflags

[AnakinVmPOPW8 V_60               ;V_60 = b = BYTE:[000000014018B3E7 + $HandlerBase] - 0 

 

反码实现减法运算v1-v2如下:

D1 = ~v1

D2 = D1 + v2

Result  = ~D2 Result  = ~(~v1 + v2)

此处不做推导,看几个实例:


v1

v2

D1   = ~v1

D2 = D1 + v2

Result =~D2  

正正

10

8

-11

-3

2

正负

10

-8

-11

-19

18

负正

-10

8

9

17

-18

负负

-10

-8

9

1

-2

 再看下对eflags的处理:

[AnakinVmPUSH V_10

[AnakinVmPUSH V_10

[AnakinVmNOTAND                   ;d1 = NOTAND(V_10, V_10)            => d1 = ~V_10

[AnakinVmPOP V_60

[AnakinVmPUSH FFFFFFFFFFFFF7EA

[AnakinVmNOTAND                   ;d1 = NOTAND(d1, FFFFF7EA)          => d1 = Nor(~V_10, ~00000815) = V_10 & 00000815

[AnakinVmPOP V_08

[AnakinVmPUSH V_80                

[AnakinVmPUSH V_80

[AnakinVmNOTAND                   ;d2 = NOTAND(V_80, V_80)            => d2 = ~V_80

[AnakinVmPOP V_60

[AnakinVmPUSH 0000000000000815

[AnakinVmNOTAND                   ;d2 = NOTAND(d2, 00000815)          => d2 = Nor(~V_80, ~FFFFF7EA) = V_80 & FFFFF7EA

[AnakinVmPOP V_08

[AnakinVmADD

[AnakinVmPOP V_08

[AnakinVmPOP V_70                 ;V_70 = d1 + d2

其中FFFFF7EA = ~00000815 00000815 = 0b100000010101

eflags定义如下:

V_10V_80皆为eflags, 可以看到v_70 V_10CF, PF, AFOF +(or) V_80的其它位(ZF, SF)得到。

V_10VmADDB置位,最后指令为Add, 受影响标志位为 OF, SF, ZF, AF, CF, PF;

V_80VmNOTANDB置位,最后指令为And, 受影响标志位为OF(0), CF(0), SF, ZF, PF

简单考虑最常用到的SFZF,可以看到这两个标志位是可以正确反映运算结果的。



不等(!=

[AnakinVmPUSHB8 03

[AnakinVmPUSHD 000000BF

[AnakinVmPUSH V_70

[AnakinVmNOTAND                   ;q = CDQ(NOTAND(V_70, 000000BF))

[AnakinVmPOP V_68

[AnakinVmSHR                      ;q = SHR(q, 3) = ZF == 0 ? 8 : 0

[AnakinVmPOP V_08

[AnakinVmADD                      ;q += SavedRBP

[AnakinVmPOP V_08

[AnakinVmREADQ

[AnakinVmPOP V_A8                 ;V_A8 = QWORD:[q]

 

不等判断需结合上文的'减法'分析,代码中V_70为eflag(v1 - v2);

And操作取'1'位一样,Nor操作可以取'0'位,上述代码Nor(V_70, 000000BF),其中000000BF = 0b10111111。可以看到ZF标志位为0时(!=, 即两数相减结果不为0时),返回0b1000000,否则返回0

结合之后的SHR及取栈数据代码, 可以进一步猜想SHR 3 是经过优化的代码,如下:

优化前

Bool b = Nor(Eflags(v1 - v2), 000000BF) >> 6;

Qword offset = b << 3;

优化后

Qword offset = Nor(Eflags(v1 - v2), 000000BF) >> 3;

计算v1 != v2得实现如下:

(Nor(Eflags(v1 - v2), 000000BF) >> 6)  == 1

 





第五届安全开发者峰会(SDC 2021)10月23日上海召开!限时2.5折门票(含自助午餐1份)

收藏
点赞2
打赏
分享
最新回复 (4)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
wx_随风_744 活跃值 2021-7-20 08:40
2
0
厉害啊
雪    币: 1400
活跃值: 活跃值 (736)
能力值: (RANK:250 )
在线值:
发帖
回帖
粉丝
xiaohang 活跃值 3 2021-7-21 10:41
3
1
怎么都没人回复了,是看懵圈了吗?
雪    币: 317
活跃值: 活跃值 (137)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_变。 活跃值 2021-7-21 19:19
4
0
看懵圈了
雪    币: 317
活跃值: 活跃值 (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
朽_木 活跃值 2021-7-23 11:57
5
0
厉害
游客
登录 | 注册 方可回帖
返回