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返回就是特征所指向的函数地址了^^

随机推荐

  1. 实现:git本地创建多个分支互不干扰

    git本地创建多个分支互不干扰 在项目开发过程中,经常会遇到下面这种情况: 业务情景:在做某个需求a时,先需要修改紧急bug b:发版时发的是远程dev的代码 方式一(推荐): (1)本地已有分支de ...

  2. Python之 最全 Conda、pip 管理环境和安装包、更换源、解决HttpError等一些列问题

    在Anaconda中conda可以理解为一个工具,也是一个可执行命令,其核心功能是环境管理与包管理.所以对虚拟环境进行创建.删除等操作需要使用conda命令. conda install 和 pip ...

  3. jmeter远程调用

    jmeter版本相同 JDK版本1.7以上 脚本文件在所有机器上的路径都一致 修改远程机器jmeter bin目录下的jmeter.properties文件配置:server_port=1001 多个 ...

  4. CSS的坑

    如何触发 bfc 规则 浮动元素:float 除 none 以外的值 绝对定位元素:position (absolute.fixed) display 为 inline-block.table-cel ...

  5. VSCode注册关联自定义类型文件

    打开你要注册的文件类型文件[本文中用 ".txt"到".lua"演示] 在VSCode窗口右下角有当前文件类型"Plain Text" 是可 ...

  6. C#开发PACS医学影像处理系统(十七):2D处理之影像旋转和翻转

    1.任意角度旋转 在XAML设计器中,设置RotateTransform属性 <InkCanvas x:Name="ToolInkCanvas" UseCustomCurso ...

  7. DVWA sql注入low级别

    DVWA sql注入low级别 sql注入分类 数字型注入 SELECT first_name, last_name FROM users WHERE user_id = $id 字符型注入 SELE ...

  8. Java12新特性

    switch表达式(预览) 传统switch的缺点 匹配是自上而下的,如果忘记写break, 后面的case语句不论匹配与否都会执行; 所有的case语句共用一个块范围,在不同的case语句定义的变量 ...

  9. 《Redis入门指南》笔记

    第1章 简介 1.1 历史与发展 2008年 意大利创业公司创始人因对mysql性能不满意,于是他决定开发redis. 2009年 redis初版由他一个人开发完成.redis是"remot ...

  10. Ubuntu16.04 Nvidia显卡驱动简明安装指南

    简单得整理了一下Ubuntu16.04 Nvidia显卡驱动的安装步骤: 查看当前系统显卡参数: sudo lspci | grep -i nvidia 删除之前的驱动: sudo apt-get - ...