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