1.介绍
本文主要简单介绍在没有代码的情况下,如何从一个动态链接库中获取某个函数的址.主要实现方式为Signature Scanning(特征码扫描)
2.什么是Signature Scanning(特征码扫描)
我就简单解释一下,其实就是从一个二进制文件的开始位置扫描,一直到文件的末尾的这样一项工作,当扫到某一段与我们所需要的符合时,
那么就说明查找到目标的地址.(感觉说得不够好,这里大家自己补补吧^^.https://wiki.alliedmods.net/Signature_Scanning#What_is_Sigscanning.3F,
当然有C++底的,应该可以通过我下面的代码就能理解了哈^^)
3.准备工作
1).通过逆向工具,这里我推荐IDA哈,如果你有其它工具能得到特征码,那也行.至于IDA自己想办法哈,这里我就不提供了
2).查看此文章以了解如何获取特征码.
3).所需要的二进制文件,与特征码
4.正式开始
1.获取某二进制文件的基地址与大小,可能通过以下函数获得
1 DWORD MH_GetModuleBase(HMODULE hModule) //获取二进制文件的基地址 2 { 3 MEMORY_BASIC_INFORMATION mem; 4 5 if (!VirtualQuery(hModule, &mem, sizeof(MEMORY_BASIC_INFORMATION))) 6 return 0; 7 8 return (DWORD)mem.AllocationBase; 9 } 10 11 DWORD MH_GetModuleSize(HMODULE hModule) //获取二进制文件的大小 12 { 13 return ((IMAGE_NT_HEADERS *)((DWORD)hModule + ((IMAGE_DOS_HEADER *)hModule)->e_lfanew))->OptionalHeader.SizeOfImage; 14 }
2.然后就能过以下函数在加载该进制文件后进行扫描
1 void *MH_SearchPattern(void *pStartSearch, DWORD dwSearchLen, char *pPattern, DWORD dwPatternLen) 2 { 3 DWORD dwStartAddr = (DWORD)pStartSearch; 4 DWORD dwEndAddr = dwStartAddr + dwSearchLen - dwPatternLen; 5 6 while (dwStartAddr < dwEndAddr) //这里从文件的开始位置扫描,如果没有找到指定特征码的位置的话,就会跳出循环并结束扫描工作;否则会返回所查到的址 7 { 8 bool found = true; 9 10 for (DWORD i = 0; i < dwPatternLen; i++) 11 { 12 char code = *(char *)(dwStartAddr + i); 13 //0x2A为跳转码的转换,比如当某一部分为 E8 AB CD 2E 76 call sub_xxxxxxxx时, 14 //那么此时除了E8之外,其它的应该更换为2A 15 if (pPattern[i] != 0x2A && pPattern[i] != code) 16 { 17 found = false; 18 break; 19 } 20 } 21 22 if (found) 23 return (void *)dwStartAddr; 24 25 dwStartAddr++; 26 } 27 28 return 0; 29 }
如果扫描成功,会返回该特征码存在的地址否则返回空
5.这样做有什么用?
对于函数挂勾有非常大的作用,可能通过Inline Hook直接勾函数,接下来要干什么就自己做吧^^,欢迎吐
槽
补充大概用法:
1 #define SIG_FUNC "\x55\x8B\xEC\x53\x56\x8B\xF1\x57\x8B\x4E\x2A\xE8\x2A\x2A\x2A\x2A\x56\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x6A" 2 3 4 void *g_pOrigin = NULL; 5 HMODULE g_hModule = NULL; 6 DWORD g_dwBase, g_dwSize; 7 8 g_hModule = LoadLibrary("my.dll"); 9 g_dwBase = MH_GetModuleBase(g_hModule); 10 g_dwSize = MH_GetModuleSize(g_hModule); 11 g_pOrigin = MH_SearchPattern(g_dwBase, g_dwSize, SIG_FUNC, sizeof(SIG_FUNC) - 1); 12 13 正常情况下,g_pOrigin返回就是特征所指向的函数地址了^^
时间: 2024-10-22 16:53:05