i'm reversing this function doing this floating point calculations which eventually leads to a crucial compare. I need to understand what exactly are the calculations that are made and i want to re-write them in python.
Basically i need to rewrite this whole piece of code because the calculations that happen later on are some sort of key generation, but i cant understand what is the calculation done in here.. I was hoping someone could help me figure this out, while i give all the information i already understand.
The piece of code:
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
Ok, so the op-codes \ pieces of code i dont understand are:
addsd xmm0, ds:MEMORY2[ecx*8],
call fmod and the
ucomisd xmm0, [MEMORY1] .
I can understand that the fmod function is receiving the arguments from the xmm0 opcodes that happen earlier with the
sub esp, 8, but the output is not the same as the output i recieve when doing this function on python.. maybe im missing something.
i just dont understand what
ucomisdis doing.. and how it effects the
ParityFlag, so this is an issue...
here is my so-far python implementation i made for this little piece of code (it runs in a loop which is missing for the code-snap i gave, so bare with me please)
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))) 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 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 """
I'm just stuck on these opcodes for quite some time.. if anyone can give me a good reference on the internet which explains how they work or what they do.. That could be super helpful.
An example of an fmod call and its arguments:
Just before the
CALL msvcrt.fmod instruction, ESP looks like that:
EBP-14384 012FBC30 00000000 EBP-14380 012FBC34 40438000 EBP-1437C 012FBC38 00000000 EBP-14378 012FBC3C 40240000
ItirationCounter is set to
and the result of the
msvcrt.fmod function into ST0 is
Hex 4002 90000000 00000000
Going to 'var_F8' after the opcode
fstp [ebp+var_F8], the value is a QUAD_WORD of
0x40220000 00000000 (Ordered)
After all that,
AX to the value
0x220, which means
the jump is taken.