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 ...
随机推荐
- Codeforces Round #529 (Div. 3) 练习赛
Examples input 6 baabbb output bab input 10 ooopppssss output oops 思路: 模拟等差数列即可 #include<bits/std ...
- 【驱动】SPI驱动分析(七)-SPI驱动常用调试方法
用户态 用户应用层使用spidev驱动的步骤如下: 打开SPI设备文件:用户可以通过打开/dev/spidevX.Y文件来访问SPI设备,其中X是SPI控制器的编号,Y是SPI设备的编号. 配置SPI ...
- Vue3使用vue-video-player组件
1.安装依赖(亲测5.0.1版本可用,最新版本会找不到'vue-video-player/src/custom-theme.css'这个样式) yarn add vue-video-player@5 ...
- centos7 docker配置防火墙firewalld
docker防火墙使用的是底层iptables,封装后的firewalld默认不生效 如果想要使用firewalld,需要做以下调整: 让firewalld移除DOCKER-USER并新建一个 # R ...
- 基于python的租房网站-房屋出租租赁系统(python+django+vue)
该项目是基于python/django/vue开发的房屋租赁系统/租房平台,作为本学期的课程作业作品.欢迎大家提出宝贵建议. 功能介绍 平台采用B/S结构,后端采用主流的Python+Django进行 ...
- 02-python简介
python简介 python认知 1.python简介 89年开发的语言,创始人范罗苏姆(Guido van Rossum),别称:龟叔(Guido). python具有非常多并且强大的第三方库,使 ...
- 【rt-thread】SConscript文件添加格式必须是4空格开头
SConscript文件添加格式必须是4空格开头,TAB或其他数量的空格均错误
- 小程序:Now you can provide attr `wx:key` for a `wx:for` to improve performance. 的解决方案
在wx:for后面添加wx:key="key" 可消除警告 <view wx:for="{{thisWeekMovies}}" wx:for-index= ...
- [转帖]会长期锁表吗?Oracle add column default 在各版本的优化
最近大家讨论到各类数据库在新增字段带默认值时是否会锁表的问题,发现Oracle在不同的版本其实是有对应优化的,更新了下之前的知识点. 主要考虑以下三种情形,例如: 不加default:alter ta ...
- [转帖]PD 配置文件描述
https://docs.pingcap.com/zh/tidb/stable/pd-configuration-file PD 配置文件比命令行参数支持更多的选项.你可以在 conf/config. ...