minidebug学习分析 01 基本框架
0x01 基本框架
基本框架就是CreateProcess启动目标程序,再通过调试事件DEBUG_EVENT在调试循环中监控程序的行为。
(1)CreatProcess
BOOL CreateProcess(
LPCTSTR lpApplicationName, // 要创建的进程模块名
LPTSTR lpCommandLine, // 命令行字符串
LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全属性
BOOL bInheritHandles, // 句柄继承选项
DWORD dwCreationFlags, // 进程创建选项
LPVOID lpEnvironment, // 进程环境块数据指针
LPCTSTR lpCurrentDirectory, // 当前目录名
LPSTARTUPINFO lpStartupInfo, // 启动信息
LPPROCESS_INFORMATION lpProcessInformation // 进程信息
);
双击一个EXE可执行文件时,Windows内核也就会自动调用CreatProcess 函数创建我们双击的文件所对应的进程。
CreateProcess函数的第六个成员dwCreationFlags进程创建选项,指明了要如何创建目标进程,在minidebug中,它指定的是DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE | CREATE_SUSPENDED。
DEBUG_ONLY_THIS_PROCESS表明调用CreateProcess的进程成为调试器,而它启动的子进程成为被调试的进程。DEBUG_ONLY_THIS_PROCESS与DEBUG_PROCESS的不同在于:DEBUG_PROCESS会调试被调试进程以及它的所有子进程,而DEBUG_ONLY_THIS_PROCESS只调试被调试进程,不调试它的子进程。
CreateProcess函数的最后一个成员LPPROCESS_INFORMATION指向一个进程信息结构体PROCESS_INFORMATION,进程创建后的相关信息会放到PROCESS_INFORMATION信息块中:
LPPROCESS_INFORMATION结构:
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
启动被调试进程:
STARTUPINFO StartupInfo = { 0 };
StartupInfo.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION ProcessInfo = { 0 };
if (CreateProcess(
Command[1].c_str(),
NULL,
NULL,
NULL,
FALSE,
DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE | CREATE_SUSPENDED,
NULL,
NULL,
&StartupInfo,
&ProcessInfo) == FALSE) {
std::wcout << TEXT("CreateProcess Failed") << GetLastError() << std::endl;
return;
}
__ProcessHandle = ProcessInfo.hProcess;
__ThreadHandle = ProcessInfo.hThread;
__ProcessID = (HANDLE)ProcessInfo.dwProcessId;
__ThreadID = (HANDLE)ProcessInfo.dwThreadId;
__DebuggerStatus = STATUS_SUSPENDED;
(2)调试循环DEBUG LOOP监控调试事件DEBUG_EVENT
void OnGo(const CommandVector& Commmd)
{
//SetSingleInstruction(FALSE); if (Commmd.size() < 2)
{
HandledException(FALSE); //g 调试器未处理异常
ContinueDebugSession(); //
return;
} ......
} void ContinueDebugSession() { if (__DebuggerStatus == STATUS_NONE) { std::wcout << TEXT("Debuggee Is Not Started Yet") << std::endl;
return;
} if (__DebuggerStatus == STATUS_SUSPENDED) { ResumeThread(__ThreadHandle);
}
else { ContinueDebugEvent(
(DWORD)__ProcessID,
(DWORD)__ThreadID,
__AlwaysContinue == TRUE ? DBG_CONTINUE : __ContinueStatus); __AlwaysContinue = FALSE;
} DEBUG_EVENT DebugEvent; while (WaitForDebugEvent(&DebugEvent, INFINITE) == TRUE)
{ if (DispatchDebugEvent(&DebugEvent) == TRUE) { ContinueDebugEvent((DWORD)__ProcessID, (DWORD)__ThreadID, __ContinueStatus);
}
else { break;
}
}
}
1>调试事件DEBUG_EVENT
结构:
typedef struct _DEBUG_EVENT {
DWORD dwDebugEventCode;
DWORD dwProcessId;
DWORD dwThreadId;
union {
EXCEPTION_DEBUG_INFO Exception;
CREATE_THREAD_DEBUG_INFO CreateThread;
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;
EXIT_THREAD_DEBUG_INFO ExitThread;
EXIT_PROCESS_DEBUG_INFO ExitProcess;
LOAD_DLL_DEBUG_INFO LoadDll;
UNLOAD_DLL_DEBUG_INFO UnloadDll;
OUTPUT_DEBUG_STRING_INFO DebugString;
RIP_INFO RipInfo;
} u;
} DEBUG_EVENT, *LPDEBUG_EVENT;
调试事件是被调试进程让系统通知调试器的事件,它包含了创建进程、创建线程、加载DLL、卸载DLL、发送输出字符串、发生异常等。如果调试器等待调试事件时刚好发生了一个调试事件,系统将填写WaitForDebugEvent函数的DEBUG_EVENT结构体的相关调试信息。 当系统通知调试器调试事件时,同时会挂起相关进程的所有线程,直到调试器使用ContinueDebugEvent继续调试事件时,被挂起的线程才继续执行。当进程被调试时,后续的调试事件也可能发生。
调试事件的具体含义可见:http://blog.csdn.net/wlsgzl/article/details/18629635
2>WaitForDebugEvent与ContinueDebugEvent
BOOL WaiteForDebugEvent(
LPDEBUG_EVENT _DEBUG_EVENT,
//指向调试事件的指针
DWORD dwMilliseconds
//等待事件的毫秒数
)
BOOL ContinueDebugEvent(
DWORD dwProcessId, // 目标进程ID
DWORD dwThreadId, // 目标线程ID
DWORD dwContinueStatus // 线程继续的标志
);
目标进程ID和目标线程ID这就是CreateProcess调用后,ProcessInfo结构中所包含的信息。该函数通过目标进程/线程ID来唯一标识目标进/线程,并且通过设置不同的ContinueStatus来通知目标进/线程继续运行的动作。
第三成员最主ContinueStatus有两个值可供设定:一个是DBG_CONTINUE,表明调试事件已经被Debugger处理完毕,目标进/线程可以照常继续运行;另一个是DBG_EXCEPTION_NOT_HANDLED,表明Debugger并未处理该调试事件,目标进程收到该标志位后,将会将调试事件沿着Windows异常调用链继续往下发送。直至该调试事件被处理完为止——当然,如果目标进程发出的Debug Event没有任何调试器能够处理,那最后Windows只有祭出自己的杀手锏:应用程序XXX异常,即将被关闭。
minidebug学习分析 01 基本框架的更多相关文章
- 一个由正则表达式引发的血案 vs2017使用rdlc实现批量打印 vs2017使用rdlc [asp.net core 源码分析] 01 - Session SignalR sql for xml path用法 MemCahe C# 操作Excel图形——绘制、读取、隐藏、删除图形 IOC,DIP,DI,IoC容器
1. 血案由来 近期我在为Lazada卖家中心做一个自助注册的项目,其中的shop name校验规则较为复杂,要求:1. 英文字母大小写2. 数字3. 越南文4. 一些特殊字符,如“&”,“- ...
- Java多线程系列--“JUC锁”01之 框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--“JUC锁”01之 框架02. Java多线程系列--“JUC锁”02之 互斥锁Reentrant ...
- java多线程系类:JUC锁:01之框架
本章,我们介绍锁的架构:后面的章节将会对它们逐个进行分析介绍.目录如下:01. Java多线程系列--"JUC锁"01之 框架02. Java多线程系列--"JUC锁&q ...
- Java 集合系列 01 总体框架
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- NAACL 2019 字词表示学习分析
NAACL 2019 表示学习分析 为要找出字.词.文档等实体表示学习相关的文章. word embedding 搜索关键词 word embedding Vector of Locally-Aggr ...
- SaToken学习笔记-01
SaToken学习笔记-01 SaToken版本为1.18 如果有排版方面的错误,请查看:传送门 springboot集成 根据官网步骤maven导入依赖 <dependency> < ...
- Redis:学习笔记-01
Redis:学习笔记-01 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 1. Redis入门 2.1 ...
- 软件测试之loadrunner学习笔记-01事务
loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...
- go语言,golang学习笔记2 web框架选择
go语言,golang学习笔记2 web框架选择 用什么go web框架比较好呢?能不能推荐个中文资料多的web框架呢? beego框架用的人最多,中文资料最多 首页 - beego: 简约 & ...
随机推荐
- caffe在win10下的安装与配置
1.Windows环境caffe安装配置(无GPU) 参考:http://www.cnblogs.com/cxyxbk/p/5902034.html 解压caffe-windows文件,将./wind ...
- English trip M1 - AC9 Nosey people 爱管闲事的人 Teacher:Solo
In this lesson you will learn to talk about what happened. 在本课中,您将学习如何谈论发生的事情. 课上内容(Lesson) # four “ ...
- 如何启动iis(Internet 信息服务(IIS)管理器)
Internet 信息服务(IIS)管理器 启动 IIS 管理器1.从“开始”菜单,指向“管理工具”,然后单击“Internet 信息服务 (IIS) 管理器”. 从“运行”对话框启动 IIS 管理器 ...
- C# wave mp3 播放器探寻
C# wave mp3 播放器探寻 最近无聊,想听听歌曲.可怜新电脑上歌曲就两三首,要听其它的就得在旧电脑上播放.可是,那台古董但不失健壮的本本被老婆无情的霸占了.无奈. 思来想去,得,写个程序播 ...
- 使用jquery-form进行文件上传
jquery.form.js是一个form插件,支持ajax表单提交和ajax上传. 使用时,需要在代码中添加如下: <script src="http://malsup.github ...
- 20181014xlVBA获取小题零分名单
Sub GetZeroName() Dim Dic As Object Const SUBJECT = "科目名称" Dim Key As String Dim OneKey Di ...
- 文件上传MultipartBody使用方法
最近有使用一个文件上传的功能,需要在请求中添加文件,一起传给服务器 Okhttp提供了这个文件添加然后上传的功能 下面给出核心的代码,然后分析一下 //多个文件上传,Filelist private ...
- 最长上升子序列 nlogn
; LL num[N]; LL dp[N]; LL go(LL l, LL r, LL k) { for (; r >= l; r--) if (dp[r] <= k) return r; ...
- js中const、let、var的区别
今天第一次遇到const定义的变量,查阅了相关资料整理了这篇文章.主要内容是:js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始化. 1 ...
- 漏洞复现——ngnix文件解析漏洞
漏洞描述: 上传文件时,在文件名后加%00php,就可以绕过检测成功上传而已文件 影响版本: nginx 0.8.41 – 1.5.6 漏洞分析: 该漏洞原理是非法字符空格和截止符(\0)会导致Ngi ...