Hex2Double

来源:互联网 发布:花生壳域名泛解析 编辑:程序博客网 时间:2024/05/29 18:00

前言

在逆向练习时,发现cm中有一句代码,将普通的hex值换成double值, 我又手写的不对.
将这个功能等价还原了一下.
如果double值变成等价的hex值,在内存中直接取就行。
如果hex值本身就是double值或float值,也是在内存直接替换,就可以得到新的double值.

还原的函数

还原的函数用C语言表达,就是一句话的事,不过,我写的不对~
入参 1 : hex值的地址
出参2 : double值的地址
e.g.
DWORD dwTest = 0x667788;
double dblRc = 0;
Hex2Double(&dwTest, &dblRc);
执行完后,就得到dwTest对应的double值dblRc
开始用手工写不对的原因是 : DWORD值是4个字节,经过协处理器,扩展成了8个字节的浮点值.
如果还原的时候,只看F5的结果,还真是不靠谱.
单步了一下,才知道Hex值强转double的结果,并不符合题意.
也有可能是内存布局的问题。
有的cm特意采用了Debug版,采用匿名联合体+数组, 一字节变量对齐,利用数据越界覆盖的方式来赋值. 有点隐蔽.
如果发现F5不对头,要将变量内存布局调正过来,或自己写Hex2Double.

void _declspec(naked) Hex2Double(IN DWORD dwHexAddr, OUT DWORD dwDblOutAddr){    __asm {        push ebp        mov ebp, esp        sub esp, 4 // ; 开辟一个DWORD临时变量 var4, 这个函数用不上了, 只用作测试        // ; ebp - 0x4 是变量 var4        // ; ebp + 0x0 是旧ebp        // ; ebp + 0x4 是返回地址        // ; ebp + 0x8 是第1个参数 dwHexAddr        // ; ebp + 0xc 是第2个参数 dwDblOutAddr        pushad        push ebx    }    __asm {        mov eax, dword ptr [ebp+8]        fild qword ptr ss:[eax]        sub esp, 8        fstp qword ptr ss:[esp]        pop eax        mov dword ptr [ebp-0x4], eax // test save value to temp var on function        // *(DWORD*)(dwDblOutAddr) = dwTmp;        lea ebx, dword ptr [ebp+0xc]        mov ebx, [ebx]        mov [ebx], eax        // *(DWORD*)((DWORD)dwDblOutAddr + 4) = dwTmp;        pop eax        lea ebx, dword ptr [ebp+0xc]        mov ebx, [ebx]        mov [ebx + 4], eax    }    __asm {        pop ebx        popad        mov esp, ebp        pop ebp        retn    }}
0 0