《逆向工程核心原理》——通过调试方式hook Api
1、附加目标进程,
2、CREATE_PROCESS_DEBUG_EVENT附加事件中将目标api处设置为0xcc(INT 3断点)
3、EXCEPTION_DEBUG_EVENT异常事件中,首先判断是否为EXCEPTION_BREAKPOINT 断点异常,然后GetThreadContext、SetThreadContext 进行相关修改操作
#include <iostream>
#include "windows.h"
#include "stdio.h" LPVOID g_pfWriteFile = NULL;
CREATE_PROCESS_DEBUG_INFO g_cpdi;
BYTE g_chINT3 = 0xCC, g_chOrgByte = 0; BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde) {
g_pfWriteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");//或取WriteFile的API地址(其实获取的是调试者的地址,但是没有影响)
printf("g_pfWriteFile(0x%08X)\n ", g_pfWriteFile);//g_pfWriteFile(1990541344) 76a54020
memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));
ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
&g_chOrgByte, sizeof(BYTE), NULL);//g_cpdi.hProcess是被调试进程的句柄,g_pfWriteFile是WriteFile API的地址 ,此函数读取api第一个字节,存储到g_chOrgByte中
WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
&g_chINT3, sizeof(BYTE), NULL); //以上两个函数对调试进程进行读写, return TRUE;
} BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde) {
CONTEXT ctx;
PBYTE lpBuffer = NULL;
DWORD64 dwNumOfBytesToWrite, dwAddrOfBuffer;//x64指针8字节
DWORD i;
PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord; if (EXCEPTION_BREAKPOINT == per->ExceptionCode) { //是断点异常时
if (g_pfWriteFile == per->ExceptionAddress) { //断点地址为writefile 的api地址时候
WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chOrgByte, sizeof(BYTE), NULL);//恢复api第一个字节(unhook) //ctx.ContextFlags = CONTEXT_CONTROL; //或取线程上下文
ctx.ContextFlags = CONTEXT_ALL; //获取线程上下文,CONTEXT_CONTROL缺少一些寄存器的值,这里使用CONTEXT_ALL
GetThreadContext(g_cpdi.hThread, &ctx);
//printf("0x%08X\n", GetLastError());
//x64下系统api使用fastcall调用约定
//ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0x8),
// &dwAddrOfBuffer, sizeof(DWORD), NULL);//获取api的第二个参数值
//ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0xC),
// &dwNumOfBytesToWrite, sizeof(DWORD), NULL);//获取取api的第三个参数值
dwAddrOfBuffer = ctx.Rdx;//WriteFile第2个参数 缓冲区:lpBuffer
dwNumOfBytesToWrite = ctx.R8;//WriteFile第3个参数 缓冲区大小:nNumberOfBytesToWrite
lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite + 1);//分配临时缓冲区
memset(lpBuffer, 0, dwNumOfBytesToWrite + 1); ReadProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer,
lpBuffer, dwNumOfBytesToWrite, NULL);//将第三个参数值复制到临时缓冲区
printf("\n### original string ###\n%s\n", lpBuffer); for (i = 0; i < dwNumOfBytesToWrite; i++) { //将小写字母转换为大写字母
if (0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7A)
lpBuffer[i] -= 0x20;
} printf("\n### converted string ###\n%s\n", lpBuffer); WriteProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer,
lpBuffer, dwNumOfBytesToWrite, NULL);//将变换后的缓冲区复制到writefile缓冲区 free(lpBuffer);//释放临时缓冲区 //将线程上下文的EIP更改为writefile首地址(当前为writefile()+1位置,int3命令之后)
ctx.Rip = (DWORD64)g_pfWriteFile;//x64指针8字节
SetThreadContext(g_cpdi.hThread, &ctx); // 运行被调试进程
ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);//运行被调试进程
Sleep(0); WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
&g_chINT3, sizeof(BYTE), NULL); return TRUE;
}
} return FALSE;
} void DebugLoop() {
DEBUG_EVENT de;
DWORD dwContinueStatus;
while (WaitForDebugEvent(&de, INFINITE))//while循环等待被调试者发生事件,并根据不同的事件类型做出不同的反映
{
dwContinueStatus = DBG_CONTINUE;
if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)// 被调试进程生成事件或者附加事件
{
OnCreateProcessDebugEvent(&de);
}
else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode)// 异常事件
{
if (OnExceptionDebugEvent(&de))
continue;
}
else if (EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)// 被调试进程终止事件
{
break;//调试器终止
}
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);// 再次运行被调试者
}
} int main(int argc, char* argv[]) {
DWORD dwPID;
//if (argc != 2) //验证参数
//{
// printf("\nUSAGE : hookdbg.exe <pid>\n");
// return 1;
//}
printf("input pid\n");
scanf("%d", &dwPID);
//dwPID = atoi(argv[1]); //pid
if (!DebugActiveProcess(dwPID)) //将调试器(本运行文件)附加到运行的进程上,开始调试
{
printf("DebugActiveProcess(%d) failed!!!\n"
"Error Code = %d\n", dwPID, GetLastError());
return 1;
}
DebugLoop();// 调试循环,处理来自被调试者的调试事件
return 0;
}
x64下要注意api的调用约定以及指针大小为8字节;
《逆向工程核心原理》——通过调试方式hook Api的更多相关文章
- 《逆向工程核心原理》——API HOOK
编写dll处理hook逻辑,注入到目标进程,实现api hook. Windows10 notepad,通过hook kernel32.dll.WriteFile,实现小写字母转大写保存到文件. ho ...
- 《逆向工程核心原理》——IAThook
hook逻辑写入dll中,注入dll. #include "pch.h" #include <tchar.h> #include "windows.h&quo ...
- 《逆向工程核心原理》Windows消息钩取
DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...
- 逆向工程核心原理-IA-32寄存器
IA-32由四类寄存器组成:通用寄存器,段寄存器,程序状态与控制寄存器,指令指针寄存器. 通用寄存器:用于传送和暂存数据,也可参与算数逻辑运算,并保存运算结果. EAX(0-31) 32位 ...
- 《逆向工程核心原理》——DLL注入与卸载
利用CreateRemoteThread #include <iostream> #include <tchar.h> #include <Windows.h> # ...
- 《逆向工程核心原理》——TLS回调函数
pe中TLS(thread local storage)中函数的执行时机早于入口函数(entry point), 相关结构: // // Thread Local Storage // typedef ...
- 运用Detours库hook API(原理是改写函数的头5个字节)
一.Detours库的来历及下载: Detours库类似于WTL的来历,是由Galen Hunt and Doug Brubacher自己开发出来,于99年7月发表在一篇名为<Detours: ...
- 反调试技术常用API,用来对付检测od和自动退出程序
在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...
- HOOK API 在多线程时应该注意的问题点
在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系 ...
随机推荐
- Linux 驱动框架---cdev字符设备驱动和misc杂项设备驱动
字符设备 Linux中设备常见分类是字符设备,块设备.网络设备,其中字符设备也是Linux驱动中最常用的设备类型.因此开发Linux设备驱动肯定是要先学习一下字符设备的抽象的.在内核中使用struct ...
- 最新 uni-app 免费教程
最新 uni-app 免费教程 uni-app 快速入门 steps 建议第一步,看完uni-app官网的首页介绍. 建议第二步,通过快速上手,亲身体验下uni-app. 建议第三步,看完<un ...
- JavaScript this All In One
JavaScript this All In One js, this, bind, call, apply, new, function, arrow function, constructor f ...
- nasm aat函数 x86
xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain dllmain: ...
- js 斩掉单行注释和多行注释
var json = ` // e { /* hello */ name:/* a */ 'ajanuw' // c /** * * hello * ? adsd * todo */ // c } ` ...
- PAUL ADAMS ARCHITECT:澳大利亚楼市保持涨势
澳大利亚最新房价变化显示,住宅价格指数连续第10周上涨,包括五个主要首府城市的上涨了0.29%. 12月截至24日,布里斯班以1.03%涨幅领跑,五个首府城市平均涨幅0.78%. 在过去3个月里,悉尼 ...
- Unity安卓apk打包过程
前言:对于Unity开发小白来说,Android打包无疑是个头痛的问题,所以我总结了 Unity安卓APK的打包过程 第一步:下载对应版本的Android Platform 第二步:安装JDK并配置J ...
- Javascript中的事件冒泡与捕获
事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支持第三个参数,useCapture:是否使用事件捕获,觉得有点模糊 Js事件流 页面的哪一部 ...
- JS数字每三位加逗号的最简单方法
<script> function thousands(num){ var str = num.toString(); var reg = str.indexOf("." ...
- @RestController和@Controller
1.使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面 若返回json等内容到页面,则需要加@ResponseBody注解 2 ...