一、回顾

在第37篇博客里,我们学习了0环-3环通信的常规方式,是通过设备的方式进行数据交互的。今天,我们来学习一种非常规方式,即通过HOOK API 的形式完成数据交互。

(37)0环与3环通信,PspTerminateProcess 关闭进程工具

二、原理

随便找一个内核函数,参数至少要有4个,多一点也无所谓。用 Inline hook 改变它的执行流程,如果参数是合法的,就调用原来的函数,如果参数符合某种规则,就认为这是3环请求和驱动通信的。

举个例子,我hook了 NtQuerySystemInfo,它的第一个参数不应该大于47,在钩子函数里如果发现参数大于47,就知道这是要和驱动通信了。

// Hook NtQuerySystemInformation
__declspec(naked) void HbgNtQuerySystemInformation(IN ULONG OpCode, IN PVOID InData, OUT PVOID OutData, IN OUT PULONG InOutDataLength)
{__asm{push ebp;mov ebp, esp;sub esp, 0x50;}switch (OpCode){case OP_TEST:{DbgPrint("%s\n", InData); // hellomemcpy(OutData, "world", 6); // 返回数据给3环*InOutDataLength = 6;goto ExitNtQuerySystemInformation;break;}}// 正常调用 NtQuerySystemInformation__asm{add esp, 0x50;pop ebp;push 0x210;jmp g_HookRetAddressNtQuerySystemInformation;}
ExitNtQuerySystemInformation:__asm{add esp, 0x50;pop ebp;retn 0x10;}
}

三、完整代码

驱动

#include <ntddk.h>
#include <ntstatus.h>//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------typedef NTSTATUS  (__stdcall *NTQUERYSYSTEMINFORMATION) (IN ULONG SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);typedef struct _LDR_DATA_TABLE_ENTRY
{LIST_ENTRY InLoadOrderLinks;LIST_ENTRY InMemoryOrderLinks;LIST_ENTRY InInitializationOrderLinks;PVOID DllBase;PVOID EntryPoint;ULONG SizeOfImage;UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;ULONG Flags;UINT16 LoadCount;UINT16 TlsIndex;LIST_ENTRY HashLinks;PVOID SectionPointer;ULONG CheckSum;ULONG TimeDateStamp;PVOID LoadedImports;PVOID EntryPointActivationContext;PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------VOID DriverUnload(PDRIVER_OBJECT pDriver);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path);
VOID PageProtectOff();
VOID PageProtectOn();
VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PULONG uKrnlImageSize);
PVOID MemorySearch(PVOID bytecode, ULONG bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress);
void InlineHookNtQuerySystemInformation();
void UnsetInlineHookNtQuerySystemInformation();
void HbgNtQuerySystemInformation(IN ULONG OpCode, IN PVOID InData, OUT PVOID OutData, IN OUT PULONG InOutDataLength);//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
#define OP_TEST 50PDRIVER_OBJECT g_Driver;
NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
ULONG g_HookRetAddressNtQuerySystemInformation;//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------// 驱动入口
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{g_Driver = pDriver;pDriver->DriverUnload = DriverUnload;InlineHookNtQuerySystemInformation();return STATUS_SUCCESS;
}// 卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{UnsetInlineHookNtQuerySystemInformation();DbgPrint("Driver unloaded.\n");
}// 关闭页保护
VOID PageProtectOff()
{__asm{cli; // 关闭中断mov eax, cr0;and eax, not 0x10000; // WP位置0mov cr0, eax;}
}// 开启页保护
VOID PageProtectOn()
{__asm{mov eax, cr0;or eax, 0x10000; // WP位置1mov cr0, eax;sti; // 恢复中断}
}// 获取内核基址,大小
VOID GetKernelBase(PDRIVER_OBJECT driver, PVOID *pKrnlBase, PULONG uKrnlImageSize)
{PLDR_DATA_TABLE_ENTRY pLdteHead; // 内核模块链表头PLDR_DATA_TABLE_ENTRY pLdteCur; // 遍历指针UNICODE_STRING usKrnlBaseDllName; // 内核模块名RtlInitUnicodeString(&usKrnlBaseDllName,L"ntoskrnl.exe");pLdteHead = (PLDR_DATA_TABLE_ENTRY)driver->DriverSection;pLdteCur = pLdteHead;do {PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);//DbgPrint("DllBase: %p, SizeOfImage: %08X %wZ\n", pLdteCur->DllBase, pLdteCur->SizeOfImage, &(pLdteCur->FullDllName));if (RtlCompareUnicodeString(&pLdteCur->BaseDllName, &usKrnlBaseDllName, TRUE) == 0){*pKrnlBase = pLdteCur->DllBase;*uKrnlImageSize = pLdteCur->SizeOfImage;return;}pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink;} while (pLdteHead != pLdteCur);return;
}// 特征码搜索
PVOID MemorySearch(PVOID bytecode, ULONG bytecodeLen, PVOID pBeginAddress, PVOID pEndAddress)
{PVOID pCur = pBeginAddress;while (pCur != pEndAddress){if (RtlCompareMemory(bytecode,pCur,bytecodeLen) == bytecodeLen){return pCur;}((ULONG)pCur)++;}return 0;
}// InlineHook NtQuerySystemInformation
void InlineHookNtQuerySystemInformation()
{   // NtQuerySystemInformation 特征码ULONG bytecode[] = {0x4589c033, 0xdc4589e4, 0x64fc4589 ,0x000124a1,0xe8858900, 0x8afffffd, 0x00014080 ,0x90458800};UCHAR ReplaceByte[5];PVOID KrnlBase;ULONG KrnlImageSize;// 通过特征码获取NtQuerySystemInformation函数地址GetKernelBase(g_Driver, &KrnlBase, &KrnlImageSize);    NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)((ULONG)MemorySearch( \bytecode,sizeof(bytecode),KrnlBase,(PVOID)((ULONG)KrnlBase+KrnlImageSize)) - 15); //DbgPrint("%x\n", ((PULONG)NtQuerySystemInformation)[0]);// 设置裸函数返回地址g_HookRetAddressNtQuerySystemInformation = (ULONG)NtQuerySystemInformation + 5;// 计算替换指令ReplaceByte[0] = 0xE9;*(PULONG)(ReplaceByte + 1) = (ULONG)HbgNtQuerySystemInformation - g_HookRetAddressNtQuerySystemInformation;PageProtectOff();memcpy(NtQuerySystemInformation, ReplaceByte, 5);PageProtectOn();
}// 卸载钩子
void UnsetInlineHookNtQuerySystemInformation()
{UCHAR ReplaceByte[5] = {0x68, 0x10, 0x02, 0x00, 0x00};PageProtectOff();memcpy(NtQuerySystemInformation, ReplaceByte, 5);PageProtectOn();
}// Hook NtQuerySystemInformation
__declspec(naked) void HbgNtQuerySystemInformation(IN ULONG OpCode, IN PVOID InData, OUT PVOID OutData, IN OUT PULONG InOutDataLength)
{__asm{push ebp;mov ebp, esp;sub esp, 0x50;}switch (OpCode){case OP_TEST:{DbgPrint("%s\n", InData); // hellomemcpy(OutData, "world", 6); // 返回数据给3环*InOutDataLength = 6;goto ExitNtQuerySystemInformation;break;}}// 正常调用 NtQuerySystemInformation__asm{add esp, 0x50;pop ebp;push 0x210;jmp g_HookRetAddressNtQuerySystemInformation;}
ExitNtQuerySystemInformation:__asm{add esp, 0x50;pop ebp;retn 0x10;}
}

3环

// 03通信非常规方式.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <windows.h>//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath);
void UnLoadDriver(PCWSTR lpszDriverName);//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------typedef LONG  (__stdcall *HBGCOMMUNICATION) (IN ULONG OpCode, IN PVOID InData, OUT PVOID OutData, IN OUT PULONG InOutDataLength);//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------HBGCOMMUNICATION HbgCommunication = NULL;#define DRIVER_NAME L"_03communication_apihook"
#define DRIVER_PATH L"_03communication_apihook.sys"#define OP_TEST 50//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------int _tmain(int argc, _TCHAR* argv[])
{HbgCommunication = (HBGCOMMUNICATION)GetProcAddress(LoadLibraryA("ntdll.dll"),"ZwQuerySystemInformation");if (HbgCommunication == NULL) {printf("获取函数地址失败. %d\n",GetLastError());getchar();return 1;}LoadDriver(DRIVER_NAME,DRIVER_PATH);char OutData[10] = {0};ULONG InOutDataLength;HbgCommunication(OP_TEST, "Hello", OutData, &InOutDataLength);printf("%d %s\n", InOutDataLength, OutData);UnLoadDriver(DRIVER_NAME);getchar();return 0;
}BOOL LoadDriver(PCWSTR lpszDriverName, PCWSTR lpszDriverPath)
{// 获取驱动完整路径WCHAR szDriverFullPath[MAX_PATH] = { 0 };GetFullPathNameW(lpszDriverPath,MAX_PATH,szDriverFullPath,NULL);//printf("%s\n", szDriverFullPath);// 打开服务控制管理器SC_HANDLE hServiceMgr = NULL; // SCM管理器句柄   hServiceMgr = OpenSCManagerW(NULL,NULL,SC_MANAGER_ALL_ACCESS);if (NULL == hServiceMgr){printf("OpenSCManagerW 失败, %d\n", GetLastError());return FALSE;}printf("打开服务控制管理器成功.\n");// 创建驱动服务SC_HANDLE hServiceDDK = NULL; // NT驱动程序服务句柄hServiceDDK = CreateServiceW(hServiceMgr,lpszDriverName,lpszDriverName,SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_IGNORE,szDriverFullPath,NULL,NULL,NULL,NULL,NULL);if (NULL == hServiceDDK){DWORD dwErr = GetLastError();if (dwErr != ERROR_IO_PENDING && dwErr != ERROR_SERVICE_EXISTS){printf("创建驱动服务失败, %d\n", dwErr);return FALSE;}}printf("创建驱动服务成功.\n");// 驱动服务已经创建,打开服务hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);if (!StartService(hServiceDDK, NULL, NULL)){DWORD dwErr = GetLastError();if (dwErr != ERROR_SERVICE_ALREADY_RUNNING){printf("运行驱动服务失败, %d\n", dwErr);return FALSE;}}printf("运行驱动服务成功.\n");if (hServiceDDK){CloseServiceHandle(hServiceDDK);}if (hServiceMgr){CloseServiceHandle(hServiceMgr);}return TRUE;
}void UnLoadDriver(PCWSTR lpszDriverName)
{SC_HANDLE hServiceMgr = OpenSCManagerW(0,0,SC_MANAGER_ALL_ACCESS);SC_HANDLE hServiceDDK = OpenServiceW(hServiceMgr,lpszDriverName,SERVICE_ALL_ACCESS);SERVICE_STATUS SvrStatus;ControlService(hServiceDDK,SERVICE_CONTROL_STOP,&SvrStatus);DeleteService(hServiceDDK);if (hServiceDDK){CloseServiceHandle(hServiceDDK);}if (hServiceMgr){CloseServiceHandle(hServiceMgr);}
}

(63)0环与3环通信非常规方式 —— 0环InlineHook相关推荐

  1. (37)0环与3环通信常规方式,PspTerminateProcess 关闭进程工具

    这节课来学习常规的通信方式,非常规方式在这里: 0环与3环通信非常规方式 -- 0环InlineHook 一.设备对象和3环窗口对象的类比 3环窗口程序中的MSG结构体和窗口对象,与0环的设备对象和I ...

  2. Windows驱动开发学习笔记(四)—— 3环与0环通信(常规方式)

    Windows驱动开发学习笔记(四)-- 3环与0环通信(常规方式) 设备对象 创建设备对象 设置数据交互方式 创建符号链接 IRP与派遣函数 IRP的类型 其它类型的IRP 派遣函数 派遣函数注册位 ...

  3. Android6.0的SMS(短信)源码分析--短信接收

    1     SMS接收流程 Android6.0中对短信的处理比起老版本还是变化有点大的.在分析源代码之前,我们可以先猜测一下Android中接收短信的大致流程.首先根据之前分析phone应用的经验, ...

  4. 系统登录页面短信验证码方式登录实现

    近期公司有个需求,要求使用短信验证码登录,取代原来的图片验证码方式,在此记录一下我的实现方法,希望对你有所帮助 公司需求:目前只有账号和验证码方式验证登录,按照公司网络安全统一部署,要求所有公网系统都 ...

  5. 子佩短信管家 v1.0.0

    类型:系统工具 版本:v1.0.0 大小:13.9M 更新:2019/3/1 语言:简体 等级: 平台:安卓, 4.0以上 下载地址: 子佩短信管家 v1.0.0(1) 子佩短信管家 v1.0.0(2 ...

  6. 文涛短信通 v1.0 绿色

    Welcome to my blog! <script language="javascript" src="http://avss.b15.cnwg.cn/cou ...

  7. 易信上线4.0版本首推“任务红包”功能

    本文讲的是 :  易信上线4.0版本首推"任务红包"功能  , 近日,移动社交软件易信4.0版本正式上线.在新版本中,易信首次推出了红包功能.其中不仅包含了"普通红包&q ...

  8. 移动应用程序设计基础——点菜单列表实现2.0(实现短信接受以及服务与广播的使用)

    <移动应用程序设计基础>实验四 Android基本组件交互 实验名称: 点菜单列表实现 所使用的工具软件及环境: JDK1.8,Android Studio 一.实验目的: [实验目的] ...

  9. Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结

    Atitit. 破解  拦截 绕过 网站 手机 短信 验证码  方式 v2 attilax 总结 1. 验证码的前世今生1 1.1. 第一代验证码 图片验证码1 1.2. 第二代验证码  用户操作 , ...

最新文章

  1. Pandas SQL 语法归纳总结,真的太全了
  2. JavaScript 发布-订阅模式
  3. JSF, MyFaces, RichFaces 和 Facelets的区别
  4. 如何进行防SQL注入?
  5. CentOS系统Tomcat 8.5/9部署SSL证书
  6. CreateIoCompletionPort函数和完成端口
  7. discuz tools.php,Discuz!论坛Tools工具箱功能详解
  8. CFA一级学习笔记--衍生品(二)--定价与估值
  9. 解析函数论 Page 22 达朗贝尔判别法 VS 柯西判别法
  10. 胭脂茉莉点评推荐上海大学法院李本教授诗集《秋月曲》诗歌6首
  11. EI索引!海口举办!ICIG 2021喊你来投稿啦
  12. CSDN写文章——不要使用默认标题
  13. 评估方法(交叉验证法、自助法、留出法)
  14. 全球与中国氢化苯乙烯-异戊二烯嵌段共聚物市场现状及未来发展趋势
  15. Streams AQ: qmn coordinator waiting for slave to start
  16. 从μC/OS-II到μC/OS-III的各种改进
  17. 阿里云盘,真的有点强
  18. c语言输入若干数输出最小值循环结构,C语言循环结构程序设计编程题
  19. 生信自学笔记(二)生物信息
  20. Revit教程:标注技巧,底部延伸距离“设置,实时轴号

热门文章

  1. 成功解决Exception “unhandled ImportError“cannot import name ‘imread‘ from ‘scipy.misc‘
  2. 成功解决AttributeError: ‘Series‘ object has no attribute ‘columns‘
  3. ML之DR之PCA:利用PCA对手写数字图片识别数据集进行降维处理(理解PCA)
  4. BlockChain:《区块链世界简明生存指南(一块听听)》2017-06-06 李笑来—听课笔记分享(2)
  5. JAVA_OA(五):SpringMVC接受传入页面的参数值
  6. Spring MVC能响应HTTP请求的原因?
  7. MySQL用source命令导入不记入binlog中【原创】
  8. [小巩u3d] u3d基础知识
  9. javascript中的for in循环和for循环的使用
  10. Html中元素的分类