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加载的更多相关文章

  1. EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载

    之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...

  2. System.load(PWConnector.dll)加载异常 Can't find dependent libraries

    System.load(PWConnector.dll)加载异常 Can't find dependent libraries 错误信息:D:\PWAdapter\PWConnector.dll: C ...

  3. 如何解决SoftekBarcode.dll加载失败的问题

    本文转自:慧都控件网 Softek Barcode Reader Toolkit是专门从事于条形码读取技术的软件公司Softek旗下一款著名的条码读取工具包.最近有部分用户反映在运行此工具包时会遇到“ ...

  4. Android中通过Java获取Webview加载内容

    有时候我们需要在加载webview时,获取加载完成的内容,当然,WebView也是有可能包含javascript.通过以下操作,我们是可以获取到WebView加载的内容. 1.自定义一个内部类,获取W ...

  5. ACCESS DLL加载错误

    如今还在用ACCESS 2003,太懒没办法,升到2010变化太大了,做个Access的转版挺麻烦的.况且大家都在使用2003,也就懒得搞了. 但问题是office 2003已经out了,(Offic ...

  6. 模块“XXX.dll”加载失败

    具体问题:模块“XXX.dll”加载失败 请确保该二进制存储在指定的路径中,或者调试它以检查该二进制或相关的.DLL文件是否有问题  找不到指定的模块. 1.在安装C++软件的时候,有时候安装失败提示 ...

  7. DLL加载,设置相对路径

    DLL加载,设置相对路径 1. 加载dll方法之一:(./ 代表当前目录,../ 代表上层目录)包含头文件的相对路径(当前路径为源代码路径,路径 “../../” 当前项目文件夹上级目录),链接lib ...

  8. 禁用ngen版本的.NET Framework dll加载

    在调试时会发现出于性能考虑.NET Framework dll加载的都是ngen版本,比如:System.dll,实际加载System.ni.dll. 如果希望加载非ngen版本,可以设置系统环境变量 ...

  9. 获取WebView加载的网页内容并进行动态修改

    http://www.jianshu.com/p/3f207a8e32cb [Android]WebView读取本地图片 http://www.cnblogs.com/kimmy/p/4769788. ...

  10. 未能从程序集 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 ...

随机推荐

  1. 一个NASA、Google都在用的开源CMS:wagtail

    说起开源CMS,你会想到哪些呢?WordPress?DoraCMS?joomla? 今天再给大家推荐一个非常好用的开源CMS:Wagtail 如果您正在选型的话,可以了解一下Wagtail的特点: 基 ...

  2. 玩转AIGC,5分钟 Serverless 部署 Stable Diffustion 服务

    有没有一种可能,其实你早就在AIGC了?阿里云将提供免费Serverless函数计算产品资源,邀请你,体验一把AIGC级的毕加索.达芬奇.梵高等大师作画的快感.下面请尽情发挥你的想象空间!!双重奖品设 ...

  3. 十五、跨主机通信overlay网络

    系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...

  4. 【驱动】SPI驱动分析(五)-模拟SPI驱动

    简介 模拟SPI驱动是一种软件实现的SPI总线驱动.在没有硬件SPI控制器的系统中,通过软件模拟实现SPI总线的功能.它允许在不修改硬件的情况下,通过GPIO(通用输入/输出)引脚模拟SPI总线的通信 ...

  5. C#排序算法6:快速排序

    快速排序由C. A. R. Hoare在1960年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分 ...

  6. centos7进入单用户模式(忘记密码操作-真正解决方案)

    centos7密码忘记了,如何登录进去呢. 1.重新启动 2.按e进入以下界面:linux系统引导  3.在标记的如下位置行尾增加:rw init=/bin/sh  4.按Ctrl+x执行可进入单用户 ...

  7. python进阶(8)--测试函数与类

    一.测试函数(unittest) 1.源文件方法(name_function.py): def get_formatted_name(first,last): """生成 ...

  8. gitee 创建代码仓库,并提交本地代码

    本文为博主原创,转载请注明出处: 1. 配置本地 gitee 的配置: git config --global user.name "xiangBaxiang" git confi ...

  9. centos7_Lnmp编译安装

    17年面试运维岗位的时候,面试官要求输出一份lnmp编译的操作文档,于是有了如下安装nginx+php+mysql,进入正题: 准备环境 环境:centos7.3 软件:nginx-1.12.1 + ...

  10. Laravel - Eloquent 删除数据

        public function ormDelete()     {         # 1.通过模型删除         // $student = Student::where('id',5 ...