x64 下记事本WriteFile() API钩取
《逆向工程核心原理》第30章 记事本WriteFile() API钩取
原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中。在原代码基础上进行修改:
- 1 // myhookdbg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
- 2 //
- 3
- 4 #include "pch.h"
- 5 #include <iostream>
- 6 #include <windows.h>
- 7 #include <tchar.h>
- 8 #include <tlhelp32.h>
- 9 #include <stdio.h>
- 10 #include <shlobj.h>
- 11
- 12
- 13 LPVOID g_pfWriteFile = NULL;
- 14 CREATE_PROCESS_DEBUG_INFO g_cpdi;
- 15 BYTE g_chINT3 = 0xCC, g_chOrgByte = 0;
- 16 BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde)
- 17 {
- 18 // 查找API地址
- 19 HMODULE dll = GetModuleHandleA("kernel32.dll");
- 20 g_pfWriteFile = GetProcAddress(dll, "WriteFile");
- 21 //g_pfWriteFile =(LPVOID)0x7ffca76b2500;
- 22 printf("kernel32.dll基址:%I64x\n", dll);
- 23 printf("WriteFile地址:%I64x\n", (DWORD64 )g_pfWriteFile);
- 24 // API Hook - WriteFile()
- 25 // 将byte更改为0xCC (INT 3)
- 26 // orginal byte是备份
- 27 memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));
- 28 ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
- 29 &g_chOrgByte, sizeof(BYTE), NULL);
- 30 printf("原api调用处字节:%x\n", g_chOrgByte);
- 31 WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
- 32 &g_chINT3, sizeof(BYTE), NULL);
- 33 BYTE arr[10];
- 34 ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
- 35 arr, sizeof(BYTE)*10, NULL);
- 36 printf("修改后:\n");
- 37 for (int i = 0; i < 10; i++)
- 38 printf("%02x ", arr[i]);
- 39 printf("\n");
- 40 return TRUE;
- 41 }
- 42
- 43 BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde)
- 44 {
- 45 CONTEXT ctx;
- 46 PBYTE lpBuffer = NULL;
- 47 DWORD i;
- 48 ULONG_PTR dwNumOfBytesToWrite, dwAddrOfBuffer;
- 49 PEXCEPTION_RECORD64 per =(PEXCEPTION_RECORD64)&pde->u.Exception.ExceptionRecord;
- 50
- 51 // BreakPoint exception (INT 3) 的情况
- 52 if (EXCEPTION_BREAKPOINT == per->ExceptionCode)
- 53 {
- 54 // 如果BP地址是WriteFile,
- 55 if ((DWORD64)g_pfWriteFile == per->ExceptionAddress)
- 56 {
- 57 printf("发现writefile调用,地址:%I64X\n", g_pfWriteFile);
- 58 // #1. Unhook
- 59 // 如果BP地址是WriteFile(用0xCC覆盖的部分返回original byte)
- 60 WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
- 61 &g_chOrgByte, sizeof(BYTE), NULL);
- 62 BYTE arr[10];
- 63 ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile,
- 64 arr, sizeof(BYTE)*10, NULL);
- 65 printf("恢复后:");
- 66 for (int i = 0; i < 10; i++)
- 67 printf("%02x ", arr[i]);
- 68 printf("\n");
- 69 // #2. 寻求Thread Context
- 70 //ctx.ContextFlags = CONTEXT_CONTROL;SegSs栈段, Rsp, SegCs代码段, Rip, and EFlags
- 71 ctx.ContextFlags = CONTEXT_FULL;//要获得全部寄存器
- 72 GetThreadContext(g_cpdi.hThread, &ctx);
- 73 LPOVERLAPPED arg5_lpOverlapped = NULL;
- 74 ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Rsp + 0x28), &arg5_lpOverlapped, sizeof(DWORD), NULL);
- 75 printf("寄存器数据:\n");
- 76 //printf("rax:%I64x\n", ctx.Rax);
- 77 //printf("rbx:%I64x\n", ctx.Rbx);
- 78 printf("rcx:%I64x\n", ctx.Rcx);
- 79 printf("rdx:%I64x\n", ctx.Rdx);
- 80 printf("r8:%I64x\n", ctx.R8);
- 81 printf("r9:%I64x\n", ctx.R9);
- 82 printf("arg5:%I64x\n",arg5_lpOverlapped);
- 83
- 84
- 85 // #3.获取param 2和3的值
- 86 // x86函数参数存在于此进程的栈中;x64 fastcall 前4个参数存在寄存器中
- 87 // LPCVOID lpBuffer,//数据缓存区指针 rdx
- 88 // DWORD nNumberOfBytesToWrite,//你要写的字节数 r8
- 89 // param 2 : rdx
- 90 // param 3 : r8
- 91
- 92 //ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.esp + 0x8),&dwAddrOfBuffer, sizeof(DWORD), NULL);
- 93 //ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.esp + 0xC),&dwNumOfBytesToWrite, sizeof(DWORD), NULL);
- 94 dwAddrOfBuffer = ctx.Rdx;
- 95 dwNumOfBytesToWrite = ctx.R8;
- 96 //printf("%s\n", dwAddrOfBuffer);
- 97 // #4. 临时缓冲配额
- 98 lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite + 1);
- 99 memset(lpBuffer, 0, dwNumOfBytesToWrite + 1);
- 100
- 101 // #5. 将WriteFile的缓冲复制到临时缓冲
- 102 ReadProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer,
- 103 lpBuffer, dwNumOfBytesToWrite, NULL);
- 104 printf("\n### original string ###\n%s\n", lpBuffer);
- 105
- 106 // #6.小写->大写转换
- 107 for (i = 0; i < dwNumOfBytesToWrite; i++)
- 108 {
- 109 if (0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7A)
- 110 lpBuffer[i] -= 0x20;
- 111 }
- 112
- 113 printf("\n### converted string ###\n%s\n", lpBuffer);
- 114
- 115 // #7. 将转换后的缓冲复制到WriteFile的缓冲
- 116 WriteProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer,
- 117 lpBuffer, dwNumOfBytesToWrite, NULL);
- 118 //ctx.Rdx=
- 119 // #8. 取消临时缓冲
- 120 free(lpBuffer);
- 121
- 122 // #9.将Thread Context的EIP更改为WriteFile()
- 123 // (现在已经过WriteFile() + 1)
- 124
- 125 //BOOL WriteFile(
- 126 // HANDLE hFile,//文件句柄 rcx
- 127 // LPCVOID lpBuffer,//数据缓存区指针 rdx
- 128 // DWORD nNumberOfBytesToWrite,//你要写的字节数 r8
- 129 // LPDWORD lpNumberOfBytesWritten,//用于保存实际写入字节数的存储区域的指针 r9
- 130 // LPOVERLAPPED lpOverlapped//OVERLAPPED结构体指针 rsp+0x20 [call 前rsp 0 8 10 18 20 28]
- 131 //);
- 132 /*ctx.Rdx += 1;
- 133 ctx.R8 -= 1;*/
- 134 ctx.Rip =(DWORD64)g_pfWriteFile;
- 135 //ctx.Eip = (DWORD)g_pfWriteFile;
- 136 SetThreadContext(g_cpdi.hThread, &ctx);
- 137
- 138 // #10. Debuggee 运行被调试进程
- 139 ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
- 140 Sleep(0);
- 141 printf("continue\n");
- 142 // #11. API Hook
- 143 WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile,&g_chINT3, sizeof(BYTE), NULL);
- 144
- 145 return TRUE;
- 146 }
- 147 }
- 148
- 149 return FALSE;
- 150 }
- 151
- 152 void DebugLoop()
- 153 {
- 154 DEBUG_EVENT de;
- 155 DWORD dwContinueStatus;
- 156
- 157 // 从Debuggee等待event的到来。
- 158 while (WaitForDebugEvent(&de, INFINITE))
- 159 {
- 160 dwContinueStatus = DBG_CONTINUE;
- 161
- 162 // 创建Debuggee进程或attach事件
- 163 if (CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)
- 164 {
- 165 OnCreateProcessDebugEvent(&de);
- 166 printf("finish creat debuggee\n");
- 167 }
- 168 // 异常活动
- 169 else if (EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode)
- 170 {
- 171 if (OnExceptionDebugEvent(&de))
- 172 continue;
- 173 }
- 174 // Debuggee进程退出事件
- 175 else if (EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode)
- 176 {
- 177 // debuggee结束-> debugger结束
- 178 break;
- 179 }
- 180
- 181 // Debuggee的恢复执行。
- 182 ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
- 183 }
- 184 }
- 185
- 186 int main()
- 187 {
- 188 //system("tasklist");
- 189 system("tasklist | findstr notepad");
- 190 char pid[10];
- 191 printf("输入要注入的进程pid:\n");
- 192 scanf_s("%s", pid, 10);
- 193
- 194 DWORD dwPID;
- 195 dwPID = atoi(pid);
- 196 if (!DebugActiveProcess(dwPID))
- 197 {
- 198 printf("DebugActiveProcess(%d) failed!!!\n"
- 199 "Error Code = %d\n", dwPID, GetLastError());
- 200 return 1;
- 201 }
- 202
- 203 // 调试器循环
- 204 DebugLoop();
- 205 system("pause");
- 206 return 0;
- 207 /*std::cout << "Hello World!\n"; */
- 208 }
- 209
- 210 // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
- 211 // 调试程序: F5 或调试 >“开始调试”菜单
- 212
- 213 // 入门提示:
- 214 // 1. 使用解决方案资源管理器窗口添加/管理文件
- 215 // 2. 使用团队资源管理器窗口连接到源代码管理
- 216 // 3. 使用输出窗口查看生成输出和其他消息
- 217 // 4. 使用错误列表窗口查看错误
- 218 // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
- 219 // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
vs2017
x64 下记事本WriteFile() API钩取的更多相关文章
- 调试钩取技术 - 记事本WriteFile() API钩取
@author: dlive 0x01 简介 本章将讲解前面介绍过的调试钩取技术,钩取记事本的kernel32!WriteFile() API 调试钩取技术能进行与用户更具有交互性(interacti ...
- 高级全局API钩取 - IE连接控制
@author: dlive @date: 2017/02/14 0x01 调试IE进程 常见网络连接库:ws2_32.dll(套接字),wininet.dll,winhttp.dll 使用Proce ...
- c#使用easyhook库进行API钩取
目标:使calc程序输入的数自动加1 (当别人使用时,总会得不到正确的结果,哈哈) 编写注入程序 ————————————————————————————————— class Program中的方法 ...
- 通过注入DLL修改API代码实现钩取(一)
通过注入DLL修改API代码实现钩取(一) Ox00 大致思路 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去 通过GetProcessAddress函数找到需钩取的API ...
- 通过调试对WriteFile()API的钩取
通过调试对WriteFile()API的钩取 0x00 目标与思路 目标:钩取指定的notepad.exe进程writeFile()API函数,对notepad.exe进程的写入的字符保存时保存为大写 ...
- 通过注入DLL后使用热补丁钩取API
通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...
- 《逆向工程核心原理》Windows消息钩取
DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...
- 汇编Ring 3下实现 HOOK API
[文章标题]汇编ring3下实现HOOK API [文章作者]nohacks(非安全,hacker0058) [作者主页]hacker0058.ys168.com [文章出处]看雪论坛(bbs.ped ...
- Window下通过charles代理抓取iphone/android手机Https请求乱码问题处理
Window下通过charles代理抓取iphone手机Https请求乱码问题 如果保持默认设置,https的reqeust和response都是乱码,设置完之后https就可以抓包了 手机端操作: ...
随机推荐
- shiro<1.2.4反序列化分析
0x01.环境搭建 下载地址:https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4 环境:Tomcat 8.5.27 + idea ...
- 2021 从零开始打造一个自己的 UI 组件库
2021 从零开始打造一个自己的 UI 组件库 refs GUI https://github.com/xgqfrms/gui/ https://www.npmjs.com/package/@xgqf ...
- PM2 in depth
PM2 in depth ecosystem.config.js module.exports = { apps : [{ name: "app", script: ". ...
- Flutter WillPopScope 拦截路由返回
WillPopScope addScopedWillPopCallback 启用此路由以使用户否决尝试以将其关闭. 典型应用是如果用户尝试退出表单,则警告用户有关未保存的表单数据.连按两次返回键退出A ...
- NGK创造的BGV金融世界观是什么?
目前DeFi已经形成初级的金融体系.笔者将DeFi市场对比传统金融世界观,不过市场结构有显着差异.我们可以这样想:如果在去中心化金融世界中借钱,那么可以把MakerDAO比作为中央银行(+回购). 去 ...
- [转]#include< > 和 #include” ” 的区别
原文网址:https://www.cnblogs.com/LeoFeng/p/5346530.html 一.#include< > #include< > 引用的是编译器的类库 ...
- epoll 原理
本文转载自epoll 原理 导语 以前经常被人问道 select.poll.epoll 的区别,基本都是靠死记硬背的,最近正好复习 linux 相关的内容,就把这一块做个笔记吧,以后也能方便查阅. e ...
- Nifi组件脚本开发—ExecuteScript 使用指南(三)
上一篇:Nifi组件脚本开发-ExecuteScript 使用指南(二) Part 3 - 高级特征 本系列的前两篇文章涵盖了 flow file 的基本操作, 如读写属性和内容, 以及使用" ...
- Oracle数据库配置监听程序
最近在学习Oracle数据库,从安装到配置监听程序基本靠百度... 不得不说百度真的很nice!!! 下面是我的Oracle服务端(PL/SQL Developer)出现的监听程序的问题及我解决的方法 ...
- 2021-2-27:Linux 下如何优化 Java MMAP 写入
主要是调整 pdflush 相关参数. 在linux操作系统中,写操作是异步的,即写操作返回的时候数据并没有真正写到磁盘上,而是先写到了系统cache里,随后由pdflush内核线程将系统中的脏页写到 ...