C/C++ 内存转储与获取DLL加载
CREATE_PROCESS_DEBUG_EVENT 创建进程的调试事件。CREATE_PROCESS_DEBUG_INFO结构体描述了该类调试事件的详细信息
OUTPUT_DEBUG_STRING_EVENT 该事件,当被调试进程调用OutputDebugString时就会引发该类调试事件,OUTPUT_DEBUG_STRING_INFO结构体描述了关于该事件的详细信息
LOAD_DLL_DEBUG_EVENT 当DLL被加载时,会调用该回调,LOAD_DLL_DEBUG_INFO结构体描述了它的详细信息,dll的路径被放在了,hfile字段,该字段默认是句柄方式存储的,需要手工转换,
实现简易调试器: 通过调试API实现建议调试器,可以加以改进,变成内存dump工具,等,也可以获取实际OEP作为查壳工具来用。
#include <stdio.h>
#include <Windows.h>
#include <Tlhelp32.h>
#include <imagehlp.h>
#pragma comment (lib, "Dbghelp")
BYTE bCC = '\xCC';
// 这是调试进程第一次被断下后执行操作
void OnException(DEBUG_EVENT *pDebug, BYTE *bCode)
{
CONTEXT context;
DWORD dwNum;
BYTE bTmp;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pDebug->dwProcessId);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, pDebug->dwThreadId);
SuspendThread(hThread);
// 读取出异常首地址
ReadProcessMemory(hProcess, pDebug->u.Exception.ExceptionRecord.ExceptionAddress, &bTmp, sizeof(BYTE), &dwNum);
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(hThread, &context);
printf("EAX = %x EIP = %x \n", context.Eax, context.Eip);
// 将刚才的CC断点取消,也就是会写原始指令集
WriteProcessMemory(hProcess, pDebug->u.Exception.ExceptionRecord.ExceptionAddress, bCode, sizeof(BYTE), &dwNum);
context.Eip--;
SetThreadContext(hThread, &context);
printf("EAX = %x EIP = %x \n", context.Eax, context.Eip);
printf("入口点: %x \n", pDebug->u.CreateProcessInfo.lpBaseOfImage);
ResumeThread(hThread);
CloseHandle(hThread);
CloseHandle(hProcess);
}
int main(int argc, char * argv[])
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
DEBUG_EVENT de = { 0 };
// 创建调试进程
BOOL bRet = CreateProcess("c://123.exe", 0, 0, 0, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, 0, 0, &si, &pi);
if (bRet == FALSE)
return bRet;
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
BYTE bCode;
DWORD dwNum;
int dwCC_Count = 0;
// 开始调试循环
while (WaitForDebugEvent(&de, INFINITE))
{
switch (de.dwDebugEventCode)
{
// 当进程创建成功后自动执行的部分
case CREATE_PROCESS_DEBUG_EVENT:
{
// 获取入口地址 0x0 可以增加偏移到入口后任意位置
DWORD dwAddr = 0x0 + (DWORD)de.u.CreateProcessInfo.lpStartAddress;
// 暂停线程
SuspendThread(de.u.CreateProcessInfo.hThread);
// 读取入口地址处的字节码
ReadProcessMemory(de.u.CreateProcessInfo.hProcess, (const void *)dwAddr, &bCode, sizeof(BYTE), &dwNum);
// 在入口地址处写入0xCC 即写入INT 3
WriteProcessMemory(de.u.CreateProcessInfo.hProcess, (void *)dwAddr, &bCC, sizeof(BYTE), &dwNum);
// 恢复线程
ResumeThread(de.u.CreateProcessInfo.hThread);
break;
}
// 当进程产生异常时自动执行这里
case EXCEPTION_DEBUG_EVENT:
{
switch (dwCC_Count)
{
// 第0次是系统断点,这里我们直接跳过
case 0:
dwCC_Count++; break;
// 第一次断点,我们让他执行下面的函数
case 1:
OnException(&de, &bCode); dwCC_Count++; break;
}
}
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
}
system("pause");
return 0;
}
获取DLL加载情况:
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <psapi.h>
void OnDllLoaded(const LOAD_DLL_DEBUG_INFO *pDebug)
{
printf("基址: 0x%-8X --> ", pDebug->lpBaseOfDll);
BOOL bSuccess = FALSE;
TCHAR pszFilename[MAX_PATH + 1];
HANDLE hFileMap;
// Get the file size.
DWORD dwFileSizeHi = 0;
DWORD dwFileSizeLo = GetFileSize(pDebug->hFile, &dwFileSizeHi);
printf("长度: %9d --> ", dwFileSizeLo);
if (dwFileSizeLo == 0 && dwFileSizeHi == 0)
{
return;
}
// 创建内存映射
hFileMap = CreateFileMapping(pDebug->hFile, 0, PAGE_READONLY, 0, 1, 0);
if (hFileMap)
{
void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
if (GetMappedFileName(GetCurrentProcess(), pMem, pszFilename, MAX_PATH))
{
printf("路径: %s \n", pszFilename);
}
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}
}
int main(int argc, char * argv[])
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
DEBUG_EVENT debug_event = { 0 };
// 创建调试进程
BOOL bRet = CreateProcess("C:/Program Files/Tencent/QQ/Bin/QQ.exe", 0, 0, 0, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, 0, 0, &si, &pi);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// 开始调试循环
while (WaitForDebugEvent(&debug_event, INFINITE))
{
switch (debug_event.dwDebugEventCode)
{
// 当DLL加载到进程时自动的执行此处代码
case LOAD_DLL_DEBUG_EVENT:
OnDllLoaded(&debug_event.u.LoadDll);
break;
}
ContinueDebugEvent(debug_event.dwProcessId, debug_event.dwThreadId, DBG_CONTINUE);
}
return 0;
}
C/C++ 内存转储与获取DLL加载的更多相关文章
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...
- System.load(PWConnector.dll)加载异常 Can't find dependent libraries
System.load(PWConnector.dll)加载异常 Can't find dependent libraries 错误信息:D:\PWAdapter\PWConnector.dll: C ...
- 如何解决SoftekBarcode.dll加载失败的问题
本文转自:慧都控件网 Softek Barcode Reader Toolkit是专门从事于条形码读取技术的软件公司Softek旗下一款著名的条码读取工具包.最近有部分用户反映在运行此工具包时会遇到“ ...
- Android中通过Java获取Webview加载内容
有时候我们需要在加载webview时,获取加载完成的内容,当然,WebView也是有可能包含javascript.通过以下操作,我们是可以获取到WebView加载的内容. 1.自定义一个内部类,获取W ...
- ACCESS DLL加载错误
如今还在用ACCESS 2003,太懒没办法,升到2010变化太大了,做个Access的转版挺麻烦的.况且大家都在使用2003,也就懒得搞了. 但问题是office 2003已经out了,(Offic ...
- 模块“XXX.dll”加载失败
具体问题:模块“XXX.dll”加载失败 请确保该二进制存储在指定的路径中,或者调试它以检查该二进制或相关的.DLL文件是否有问题 找不到指定的模块. 1.在安装C++软件的时候,有时候安装失败提示 ...
- DLL加载,设置相对路径
DLL加载,设置相对路径 1. 加载dll方法之一:(./ 代表当前目录,../ 代表上层目录)包含头文件的相对路径(当前路径为源代码路径,路径 “../../” 当前项目文件夹上级目录),链接lib ...
- 禁用ngen版本的.NET Framework dll加载
在调试时会发现出于性能考虑.NET Framework dll加载的都是ngen版本,比如:System.dll,实际加载System.ni.dll. 如果希望加载非ngen版本,可以设置系统环境变量 ...
- 获取WebView加载的网页内容并进行动态修改
http://www.jianshu.com/p/3f207a8e32cb [Android]WebView读取本地图片 http://www.cnblogs.com/kimmy/p/4769788. ...
- 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“EntityClean”
问题: 未能从程序集 C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Data.Entity.Build.Tasks.dll 加载任务“Entity ...
随机推荐
- golang chan传递数据的性能开销
这篇文章并不讨论chan因为加锁解锁以及为了维持内存模型定义的行为而付出的运行时开销. 这篇文章要探讨的是chan在接收和发送数据时因为"复制"而产生的开销. 在做性能测试前先复习 ...
- CVPR2022 前沿研究成果解读:基于生成对抗网络的深度感知人脸重演算法
凭借在人脸生成领域的扎实积累和前沿创新,阿里云视频云与香港科技大学合作的最新研究成果<基于生成对抗网络的深度感知人脸重演算法 >(Depth-Aware Generative Advers ...
- AtCoder | ABC 125 Person Editorial
开始补AtCoder的数学题了,练下思维 AB两道都很简单,看懂题就OK. C,D稍微麻烦一些 Problem C: GCD On Blackboard 为了解决此问题,我们需要了解最大公约数(GCD ...
- Spring Boot 2.x :日志框架@Slf4j的使用和logback文件配置
为什么是SLF4J? 默认情况下,Spring Boot会用SLF4J + Logback来记录日志,并用INFO级别输出到控制台. 怎么使用SLF4J? 如果我们在一个Spring Boot 的程序 ...
- 【驱动】SPI驱动分析(三)-SPI关键数据类型
SPI数据类型 SPI控制器驱动结构体 struct spi_master抽象了控制器硬件,在SoC中的指的就是内部SPI控制器,当向SPI核心层注册一个SPI控制器时就需要提供这样的一个结构体变量. ...
- 我让 ChatGPT 化身为全知全能的文档小助理,啥姿势她都会......
ChatGPT 虽然只是一个对话型人工智能,但已经震惊了全世界,有人甚至认为人工智能的奇点已经到来.未来一定会有很多人失业,从工业革命开始,每出现一次重大的技术变革,就必然会有一批人失业,我们要直面现 ...
- P3844【黄】
这道题做的极其折磨 因为最开始小看这道题了,没用稳扎稳打的码风来写代码,直接用的那种可读性极差但勉强能跑的代码写的,最后没AC只有73分调了好久也没调对,甚至逐渐调成了64.55越来越低的分.这有多方 ...
- 机器学习-决策树系列-GBDT算法-集成学习-30
目录 1. 复习 2. GBDT 3. gbdt应用于二分类: 3. gbdt应用于多类 4. 叶子节点输出值c的计算 5. GBDT的其他应用 6. GBDT+LR 代码实现 1. 复习 再开始学习 ...
- Python 学习笔记: 从变量到装饰器
从变量开始 python 中全局变量在函数作用域内只能读,不能"写".如果要在函数作用域内实现修改全局变量值操作,需要使用关键字 global 显示指明该变量是全局变量. 但是,在 ...
- 每天学五分钟 Liunx 0101 | 服务篇:创建进程
创建子进程 上一节说过创建子进程的三种方式: 1. fork 复制进程:fork 会复制当前进程的副本,产生一个新的子进程,父子进程是完全独立的两个进程,他们掌握的资源(环境变量和普通变量)是一样的. ...