通过调试对WriteFile()API的钩取

0x00 目标与思路

目标:钩取指定的notepad.exe进程writeFile()API函数,对notepad.exe进程的写入的字符保存时保存为大写形式

思路:

1)使用DebugActiveProcess函数使调试器附加到指定进程中。

2)使用WaitForDebugEvent函数取得目标进程的调试信息。

3)更改writeFile()函数api的第一个字节为0xcc,使其进入调试区

4)进入调试去后将writeFile()API的第一个字节恢复原状,因为后面还有用。

5)对notepad输入缓冲区的字符串进行大写转换,并保存到缓冲区。

6)恢复writeFile的EIP信息

7)继续运行调试程序

8)再次写入INT3钩子

0x01实现代码

// hookapi1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

//

#include "pch.h"

#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)

{

//获取WriteFile()API地址

g_pfWriteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");

//将WriteFile()的第一个字节换成INT3即0xcc

//并且添加WriteFile()第一字节的备份,为以后恢复做准备

memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));

ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chOrgByte, sizeof(BYTE), NULL);

WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chINT3, sizeof(BYTE), NULL);

return TRUE;

}

//发生异常启动

//发生异常启动

BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde)

{

CONTEXT ctx;

PBYTE lpBuffer = NULL;

DWORD dwNumofByteToWrite, dwAddrOfBuffer, i;

PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord;

//判断是否是INT3异常

if (EXCEPTION_BREAKPOINT == per->ExceptionCode)

{

//判断是够否是WriteFile()API的地址

if (g_pfWriteFile == per->ExceptionAddress)

{

//1.脱钩,即将writeFile()的首地址恢复,因为后面的用到该函数

WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, &g_chOrgByte, sizeof(BYTE), NULL);

//2.获取进程上下文,其实就是获取各个寄存器的值

//获得进程上下文之后就可以获得进程中函数的各个参数值

ctx.ContextFlags = CONTEXT_CONTROL;

GetThreadContext(g_cpdi.hThread, &ctx);

//3.获取WriteFile()的param2以及param3的值

//param2是writeFile()的字符缓冲区地址

//param3是WriteFile()的字符缓冲区大小

ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0x8), &dwAddrOfBuffer, sizeof(DWORD), NULL);

ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0xC), &dwNumofByteToWrite, sizeof(DWORD), NULL);

//4.分配临时缓冲区给存放缓冲区的字符串

lpBuffer = (PBYTE)malloc(dwNumofByteToWrite + 1);

//将新分配的缓冲区的内容清零,以便存放内容

memset(lpBuffer, 0, dwNumofByteToWrite + 1);

//5.复制writeFile()的缓冲区的内容复制到临时缓冲区

ReadProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer, lpBuffer, dwNumofByteToWrite, NULL);

printf("\n### 初始字符串 ###\n%s\n", lpBuffer);

//6.将临时缓冲区的字符串转换成大写

for (i = 0; i < dwNumofByteToWrite; i++)

{

if (0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7a)

{

lpBuffer[i] -= 0x20;

}

}

printf("\n ****转换后的字符串为###\n%s\n", lpBuffer);

//7.将变换后的字符串复制到WriteFile()的缓冲区

WriteProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer, lpBuffer, dwNumofByteToWrite, NULL);

//8.释放临时缓冲区

free(lpBuffer);

//9.更改EIP指针恢复为WriteFile()的首地址

//由于前面更改WriteFile()的首地址为INT3了,后面执行了INT3指令之后EIP增加了1。所以执行完之后要改回去。

ctx.Eip = (DWORD)g_pfWriteFile;

SetThreadContext(g_cpdi.hThread, &ctx);

//10.继续运行被调试程序

ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);

Sleep(0);

//11.再次写入API钩子

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))

{

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;

}

// 将第二个参数转化为long型

dwPID = atoi(argv[1]);

if (!DebugActiveProcess(dwPID))

{

printf("DebugActiveProcess(%d) failed!!!\n"

"Error Code = %d\n", dwPID, GetLastError());

return 1;

}

// 循环等待事件发生

Debugloop();

return 0;

}

编译生成hookapi1.exe文件。将其放入D盘。

0x02 运行查看效果

打开notepad.exe,打开processExploer查看notepad.exe的PID,用管理员权限打开cmd,输入hookapi1.exe 16576,向notepad中输入小写的“war is over!”退出并保存为1.text文件。运行结果如下图:

通过调试对WriteFile()API的钩取的更多相关文章

  1. 通过注入DLL修改API代码实现钩取(一)

    通过注入DLL修改API代码实现钩取(一) Ox00 大致思路 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去 通过GetProcessAddress函数找到需钩取的API ...

  2. 调试钩取技术 - 记事本WriteFile() API钩取

    @author: dlive 0x01 简介 本章将讲解前面介绍过的调试钩取技术,钩取记事本的kernel32!WriteFile() API 调试钩取技术能进行与用户更具有交互性(interacti ...

  3. x64 下记事本WriteFile() API钩取

    <逆向工程核心原理>第30章 记事本WriteFile() API钩取 原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中.在原代码基础上进行修改: 1 ...

  4. 高级全局API钩取 - IE连接控制

    @author: dlive @date: 2017/02/14 0x01 调试IE进程 常见网络连接库:ws2_32.dll(套接字),wininet.dll,winhttp.dll 使用Proce ...

  5. c#使用easyhook库进行API钩取

    目标:使calc程序输入的数自动加1 (当别人使用时,总会得不到正确的结果,哈哈) 编写注入程序 ————————————————————————————————— class Program中的方法 ...

  6. 通过注入DLL后使用热补丁钩取API

    通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...

  7. 《逆向工程核心原理》——通过调试方式hook Api

    1.附加目标进程, 2.CREATE_PROCESS_DEBUG_EVENT附加事件中将目标api处设置为0xcc(INT 3断点) 3.EXCEPTION_DEBUG_EVENT异常事件中,首先判断 ...

  8. 《逆向工程核心原理》Windows消息钩取

    DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...

  9. Azure DevOps Server: 使用Rest Api获取拉取请求Pull Request中的变更文件清单

    需求: Azure DevOps Server 的拉取请求模块,为开发团队提供了强大而且灵活的代码评审功能.拉取请求中变更文件清单,对质量管理人员,是一个宝贵的材料.质量保障人员可以从代码清单中分析不 ...

随机推荐

  1. install-package : 由于无法加载项目 mydemo 的详细信息,操作失败

    安装nuget package包提示错误 install-package : 由于无法加载项目 mydemo 的详细信息,操作失败 解决方法 项目用dotnet cli 命令dotnet new mv ...

  2. 【百度前端学院 Day4】背景边框列表链接和更复杂的选择器

    1. 背景 背景指的是元素内容.内边距和边界下层的区域(可用background-clip修改) background-color  背景色 background-image  背景图片(url) b ...

  3. 启动centos 不带桌面

    方法一:非systemd系统 #runlevel N 5 //表示运行级别为5 #init 3 //将运行级别设为3,此时桌面服务关闭 运行级别说明: 3 多用户模式.允许多用户登录系统,是系统默认的 ...

  4. Redis的内存和实现机制

    1. Reids内存的划分 数据 内存统计在used_memory中 进程本身运行需要内存 Redis主进程本身运行需要的内存占用,代码.常量池等 缓冲内存,客户端缓冲区.复制积压缓冲区.AOF缓冲区 ...

  5. 没有国产主机,怎么开发:交叉编译和QEMU虚拟机

    1. 背景 近期国产化的趋势越来越浓,包括国产操作系统.国产CPU等.时隔十多年,QQ for Linux也更新了.做为软件开发人员,"有幸"也需要适配国产化.至于国产化的意义等就 ...

  6. 消息队列——RabbitMQ的基本使用及高级特性

    文章目录 一.引言 二.基本使用 1. 简单示例 2. work queue和公平消费消息 3. 交换机 三.高级特性 1. 消息过期 2. 死信队列 3. 延迟队列 4. 优先级队列 5. 流量控制 ...

  7. Windows 程序设计(4) MFC 03 -系列学习

    本文整体目录和绝大部门内容来自 [鸡啄米网站]的MFC系列文章,欢迎支持原创 (一)VS2010/MFC编程入门之前言 VC++全称是Visual C++,是由微软提供的C++开发工具,它与C++的根 ...

  8. 研为电子6轴运动控制卡win10驱动无法安装问题,解决方法

    研为电子6轴运动控制卡win10驱动无法安装问题,解决方法 研为电子6轴运动控制卡win10驱动无法安装问题,解决方法 iMC3xx2E系列运动控制卡使用手册V1.003 IMCdrv_Ins.exe ...

  9. Docker中使用RabbitMQ

    安装Docker yum install docker //安装完成以后,可以查看一下docker的版本 docker -v //Docker version 1.13.1, build 64e998 ...

  10. Newtonsoft 六个超简单又实用的特性,值得一试 【下篇】

    一:讲故事 上一篇介绍的 6 个特性从园子里的反馈来看效果不错,那这一篇就再带来 6 个特性同大家一起欣赏. 二:特性分析 1. 像弱类型语言一样解析 json 大家都知道弱类型的语言有很多,如: n ...