使用 FloatingPoint 指令和计算分析一段代码

逆向工程 部件 x86 Python 漂浮
2021-06-17 00:25:51

我正在反转这个函数做这个浮点计算,最终导致一个关键的比较。我需要了解所做的计算到底是什么,我想用 python 重写它们。

基本上我需要重写整段代码,因为稍后发生的计算是某种密钥生成,但我无法理解这里完成的计算..我希望有人能帮我解决这个问题,而我提供我已经了解的所有信息。

这段代码:

sub     esp, 8
movsd   xmm0, ds:MEMORY1 ; mov 128-bit memory    
movsd   [esp+1437Ch+var_1437C], xmm0    
mov     eax, [ebp+ItirationCounter_var_60]
mov     [ebp+CurrentCounter_var_A8], eax    
cvtsi2sd xmm0, [ebp+CurrentCounter_var_A8] ; Convert to floating point into xmm0    
mov     ecx, [ebp+CurrentCounter_var_A8] ; 32    
shr     ecx, 1Fh        ; 0    
addsd   xmm0, ds:MEMORY2[ecx*8] ; adds 0    
sub     esp, 8    
movsd   [esp+14384h+var_14384], xmm0    
call    msvcrt.fmod            ; returns A / B floating point remainer    
add     esp, 10h    
fstp    [ebp+var_F8]    ; Store ST0 in memory    
movsd   xmm0, [ebp+var_F8]    
ucomisd xmm0, ds:MEMORY3 ; always zero    
lahf                    ; load AH Flag register    
test    ah, 44h    
jp      short CrucialFunction

好了,所以操作码\的代码我不理解件是:addsd xmm0, ds:MEMORY2[ecx*8]call fmoducomisd xmm0, [MEMORY1]

  1. 我可以理解 fmod 函数正在接收来自之前发生的 xmm0 操作码的参数sub esp, 8,但输出与我在 python 上执行此函数时收到的输出不同。

  2. 我只是不明白ucomisd在做什么......以及它如何影响ZeroFlagParityFlag,所以这是一个问题......

这是我为这段代码所做的到目前为止的python实现(它在一个循环中运行,我给出的代码快照没有,所以请不要打扰我)

MEMORY1 = 0x4024000000000000 #qword_7600D600
MEMORY2 = [0x0, 0x41F0000000000000] #qword_7600D620
MEMORY3 = 0x0

def ToDoublePrecision(value):
    # cvtsi2sd xmm0, value
    return hex(struct.unpack('<Q', struct.pack('<d', value))[0])

def KeyGeneration():
    counter = 0
    while 1:
        counter &= 0xFFFFFFFF # Sanity - maintain 32 bit
        xmm0 += MEMORY2[(counter) >> 0x1F] # This is wrong.. ---- addsd   xmm0, ds:MEMORY2[ecx*8] 
        if(1 == (0x80000000 & counter)):
            pass # I dont know what is going on in here..
        else:
            xmm0 = ToDoublePrecision(counter) # This is a little hack.. the value at MEMORY[0] is 0x0.. so i just decided this should happen

        # This calculation is inaccurate for some reason, and differs a lot from the output on register ST0    
        result = math.fmod(MEMORY1, xmm0)
        ....
        ....

        """
        ZeroFlag = 1, well if the last calculatio is set to zero
        ParityFlag = 1, is set if the last calculation amount of set bits ('1' - ones) is odd
        """

我只是停留在这些操作码上很长一段时间。

fmod 调用及其参数的示例:就在CALL msvcrt.fmod指令之前,ESP 如下所示:

EBP-14384 012FBC30   00000000
EBP-14380 012FBC34   40438000
EBP-1437C 012FBC38   00000000
EBP-14378 012FBC3C   40240000

ItirationCounter的设置为0x27

msvcrt.fmod函数到 ST0的结果Float 9.0000000000000000000Hex 4002 90000000 00000000

在操作码之后转到 'var_F8' fstp [ebp+var_F8],该值是0x40220000 00000000(Ordered)的 QUAD_WORD

毕竟,LAHF更改AX为 value 0x220,这意味着AH0x02跳跃被采取。

1个回答

sub esp, 8 movsd xmm0, ds:MEMORY1 ; mov 128-bit memory movsd [esp], xmm0

获取 MEMORY1。这将是我们在 fmod() 中的分母。

mov eax, [ebp+ItirationCounter_var_60] mov [ebp+CurrentCounter_var_A8], eax cvtsi2sd xmm0, [ebp+CurrentCounter_var_A8] ; Convert to floating point into xmm0

以浮点数形式获取计数器。这将是我们在 fmod() 中的分子。

mov ecx, [ebp+CurrentCounter_var_A8] ; 32 shr ecx, 1Fh ; 0 addsd xmm0, ds:MEMORY2[ecx*8] ; adds 0

这部分正在调整负数。我怀疑柜台永远不会这么大,所以它并不有趣。

sub esp, 8 movsd [esp], xmm0 call msvcrt.fmod ; returns A / B floating point remainer add esp, 10h

所以 fmod(counter, memory1)。

fstp [ebp+var_F8] ; Store ST0 in memory movsd xmm0, [ebp+var_F8] ucomisd xmm0, ds:qword_7600D5E8 ; always zero lahf ; load AH Flag register test ah, 44h jp short CrucialFunction

只有在两种情况下才会采用 JP 分支:AH 为 44h 或 AH 为 00h。第一种情况发生在值相等时(即 fmod() 的返回值为零)。第二个发生在 fmod() 的返回设置奇数位时,因此 1 2 4 7 8 11 ...

您的 Python 版本颠倒了分子和分母参数。