Signature Scanning(中文暂时译为"特征码扫描")是在C++(起码我是用C++^^)开发中很好的一种方式

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