1、思路:
整理以前的代码,顺便写个帖子。该方法是利用驱动构建调用门和中断门,然后利用调用门修改页相关dll的页属性,再利用中断门来hook相关的函数。当然也有更简单的方法,此方法是利用调用门和中断门的使用,当然64位下是行不通的,会触发pg。64需要切换gs,(x86是fs寄存器指向teb和kpcr)
2、驱动
#include <ntifs.h>
#include <ntddk.h>
#include <stdio.h>
#define DEVICENAME L"\\Device\\FuncHook"
#define SYMBOLNAME L"\\??\\Hook"
#define StartHook CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define StopHook CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
CHAR* GdtrTable[0x6] = { 0 };
CHAR* LdtrTale[0x6] = { 0 };
ULONG FuncAddress = 0;
ULONG MessageHwnd = 0;
ULONG MessageString = 0;
ULONG MessageTitle = 0;
ULONG MessageSelect = 0;
BOOLEAN FuncHook() {
/**该方法由于不是目标程序的CR3,无法读取到目标程序内存,用调用门提权的方式**/
/*
ULONG CR3 = *(int*)((char*)Process + 0x18);
KdPrint((CR3));
if (CR3 == 0) {
KdPrint(("寻找CR3失败"));
return -1;
//改变PTE属性
__asm {
pushad
pushfd
mov ecx,cr3
mov ebx,CR3
mov eax, FuncAddress
//右移动18位置,相当于右移21位,再左移3位。2-9-9-12分页
shr eax, 0x12
mov esi,0x3ff8
and eax,esi
//想到与add eax,0xC0600000,找到PTE
sub eax,0x3FA00000
//取出PTE
mov edx,[eax]
//改变PTE属性为可读可写,or edx,0x0110 U/S=1 普通用户,
or edx,0x5
//右移动9位,取出PDT
popfd
popad
*/
//1、获取GDT的值
__asm {
pushad
pushfd
sgdt GdtrTable
lea eax, [GdtrTable + 2]
mov eax, [eax]
//在0x90偏移处构建调用们
lea eax, [eax + 0x94]
mov ecx, FuncAddress //0x77D517EA
mov esi, ecx //esi = 0x77D517EA
and esi, 0xffff0000 //esi = 0x77D50000
add esi, 0xec00 //esi = 0x77D5ec00
mov[eax], esi
lea eax, [eax - 4]
and ecx, 0xffff
add ecx, 0x00080000
mov[eax], ecx
popfd
popad
}
return STATUS_SUCCESS;
}
VOID writefile() {
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iostatus;
HANDLE hFile;
UNICODE_STRING logFileUnicodeString;
//初始花unicode_string字符串
RtlInitUnicodeString(&logFileUnicodeString, L"\\??\\C:\\1.txt");
//初始化对象属性宏
InitializeObjectAttributes(&objectAttributes, &logFileUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS ntstatus = ZwCreateFile(&hFile, FILE_APPEND_DATA, &objectAttributes, &iostatus, NULL,
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
UCHAR pBuffer[200] = { 0 };
char* ProcessName = (char*)PsGetCurrentProcess() + 0x174; //偏移0x174处,是fileImageName
sprintf(pBuffer, "进程名称:%s HWND:%X Text:%s Caption:%s Type:%X \r\n", ProcessName, MessageHwnd,
MessageString, MessageTitle, MessageSelect);
KdPrint(("%s", pBuffer));
ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, strlen(pBuffer), NULL, NULL);
KdPrint(("The program really appended %d bytes\n", iostatus.Information));
ZwClose(hFile);//关闭文件句柄
}
//建立中断门
VOID _declspec(naked) HookFunc() {
__asm {
pushad
pushfd
int 3
}
DbgPrint("%s", "HookFunc");
_asm {
//找到三环esp
lea eax, [esp + 0x30]
mov eax, [eax]
//第一个参数
mov ebx, eax
lea eax, [ebx + 0x4]
mov eax, [eax]
mov [MessageHwnd], eax
lea eax, [ebx + 0x8]
mov eax, [eax]
mov [MessageString], eax
lea eax, [ebx + 0xc]
mov eax, [eax]
mov [MessageTitle], eax
lea eax,[ebx+0x10]
mov eax,[eax]
mov [MessageSelect],eax
}
writefile();
__asm {
popfd
popad
}
__asm {
push 0x3b
pop fs
iretd
}
}
BOOLEAN SetIntDoor(PVOID HookFunc) {
__asm {
pushad
pushfd
sidt LdtrTale
mov eax,[LdtrTale+2] //获取ldtr的地址
add eax,0x100
//构建调用们
mov ebx,HookFunc
mov esi,ebx
//计算低四位
and ebx,0xffff
add ebx,0x00080000
mov [eax],ebx
//计算高四位
and esi,0xffff0000
add esi,0xee00
add eax,0x4
mov [eax],esi
popfd
popad
}
return STATUS_SUCCESS;
}
NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver) {
UNICODE_STRING symbolLink;
RtlInitUnicodeString(&symbolLink, SYMBOLNAME);
IoDeleteSymbolicLink(&symbolLink);
IoDeleteDevice(pDriver->DeviceObject);
KdPrint(("卸载成功"));
return STATUS_SUCCESS;
}
NTSTATUS ChangePage(DEVICE_OBJECT* DeviceObject, IRP* Irp) {
NTSTATUS status;
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode;
PVOID pIoBuffer;
ULONG InLength;
ULONG OutLength;
__asm {
int 3
}
//获取IRP数据
pIrpStack = IoGetCurrentIrpStackLocation(Irp);
//获取控制码
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
//获取缓冲区地址
pIoBuffer = Irp->AssociatedIrp.SystemBuffer;
//获取3环数据长度
InLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
//获取0环发送的数据长度
OutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
PEPROCESS Process = 0;
switch (uIoControlCode) {
case StartHook:
//获取三环发送过来的函数地址
memcpy(&FuncAddress, pIoBuffer, 4);
if (FuncAddress == 0) {
KdPrint(("FuncAddress地址为0"));
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return -1;
}
if (!Process) {
if (NT_SUCCESS(FuncHook()) && NT_SUCCESS(SetIntDoor(HookFunc))){ //&& NT_SUCCESS(SetIntDoor(FuncAddress))
*(int*)(pIoBuffer) = 1;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 1;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
else {
KdPrint(("创建调用门失败"));
Irp->IoStatus.Status = -1;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return -1;
}
}
else
{
KdPrint(("没有获取到CR3或PID"));
Irp->IoStatus.Status = -1;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return -1;
}
}
}
NTSTATUS IrpCreate(DEVICE_OBJECT* DeviceObject, IRP* Irp) {
KdPrint(("设备连接"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS IrpClose(DEVICE_OBJECT* DeviceObject, IRP* Irp) {
KdPrint(("设备断开"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING Path) {
//测试用函数
NTSTATUS status;
pDriver->DriverUnload = DriverUnload;
UNICODE_STRING DeviceName;
UNICODE_STRING SymbolName;
DEVICE_OBJECT Device;
//初始化设备对象名
RtlInitUnicodeString(&SymbolName, SYMBOLNAME);
RtlInitUnicodeString(&DeviceName, DEVICENAME);
//创建符号链接
status = IoCreateSymbolicLink(&SymbolName, &DeviceName);
if (!NT_SUCCESS(status)) {
KdPrint(("创建符号连接失败"));
return status;
}
//创建设备对象
status = IoCreateDevice(pDriver, NULL, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, TRUE, &Device);
if (!NT_SUCCESS(status)) {
KdPrint(("创建设备对象失败"));
return status;
}
//设置设备交互模式
pDriver->Flags |= DO_BUFFERED_IO;
//设置派遣函数
pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreate;
pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpClose;
pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ChangePage;
return STATUS_SUCCESS;
}
3、3环
#include "stdafx.h"
#include "resource.h"
#include <windows.h>
#include <WinIoCtl.h>
#define SYMBOLNAME L"\\\\.\\Hook"
#define IN_BUFFER_MAXLENGTH 0x10 //输入缓存最大长度
#define OUT_BUFFER_MAXLENGTH 0x4 //输出缓存最大长度
#define StartHook CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define StopHook CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)
TCHAR szFilePath[MAX_PATH + 1]={0};
LPCWSTR SysName = L"\\FuncHook.sys";
LPCWSTR ServiceName = L"FuncHook";
HANDLE g_hDriver = 0;
DWORD FuncAddress = 0;
SC_HANDLE ScHandle = 0;
DWORD Start =0;
DWORD MessageBoxAddress = 0;
DWORD HookFuncAddresss =0;
DWORD CR3get=0;
DWORD First = 0;
DWORD Second = 0;
DWORD Thirst = 0;
DWORD Foure = 0;
//构造调用门修改页表属性
void _declspec(naked) StartListen(){
__asm{
int 3
pushad
pushfd
//改变messagebox的地址为write/read
int 3
mov eax,MessageBoxAddress
mov esi,eax
//chage PTE
shr esi,0x12
and esi,0x3FF8
sub esi,0x3FA00000
mov edx,[esi]
or edx,0x3
mov [esi],edx
//change PDT
shr eax,0x9
and eax,0x7FFFF8
add eax,0xc0000000
mov edx,[eax]
or edx,0x3
mov [eax],edx
/* mov eax,cr3
mov CR3,eax*/
popfd
popad
retf
}
}
//修改MessageBoxA的前两个字节为int 20
BOOL ChangeMeeageBoxA(){
char * address = (char *)MessageBoxAddress;
*(address) =0xcd;
*(address+1)=0x20;
if(*(address+1)!=0x20 && *(address)!=0xcd){
return FALSE;
}
else{
return TRUE;
}
}
BOOL RecoverMessageBoxA(){
char * address = (char *)MessageBoxAddress;
*(address) =0x8b;
*(address+1)=0xFF;
if(*(address+1)!=0xFF && *(address)!=0x8b){
return FALSE;
}
else{
return TRUE;
}
}
//void _declspec(naked) HookStart(){
// __asm{
// mov esi,cr3
// mov edi,CR3get
// mov cr3,edi //
// jmp HookFuncAddresss
// }
//
//}
//void __declspec(naked) FuncHook(){
// __asm{
// push ebp
// mov ebp,esp
// push esi //保存原来的CR3
// pushad //保存原来环境
// pushfd
// 获取 参数 1
// mov eax,[ebp+4]
// mov First,eax
// mov eax,[ebp+8]
// mov Second,eax
// mov eax,[ebp+0xc]
// mov Thirst,eax
// mov eax,[ebp+0x10]
// mov Foure,eax
//
// }
//
//}
//打开驱动服务句柄
BOOL Open(LPCWSTR pLinkName){
TCHAR szBuffer[10] ={0};
g_hDriver = CreateFile(pLinkName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(g_hDriver ==INVALID_HANDLE_VALUE){
DWORD error = ::GetLastError();
wsprintf(szBuffer,L"打开服务句柄失败%d\n",error);
MessageBox(0,szBuffer,0,0);
CloseHandle(g_hDriver);
return FALSE;
}
return TRUE;
}
//注册驱动服务
BOOL Register(){
//获取驱动管理器
ScHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (ScHandle == NULL) {
DWORD error = GetLastError();
/*MessageBox(0, TEXT("获取服务管理器失败"), 0, 0);*/
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("获取服务管理器失败:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(ScHandle);
return FALSE;
}
//创建服务
SC_HANDLE ScService = CreateService(ScHandle,ServiceName,ServiceName,SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,szFilePath,NULL,NULL,NULL,NULL,NULL);
if(ScService==NULL){
DWORD error = GetLastError();
if (error == ERROR_SERVICE_EXISTS) {
CloseServiceHandle(ScService);
return TRUE;
}
else {
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("创建服务错误:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(ScService);
CloseServiceHandle(ScHandle);
return FALSE;
}
}
CloseServiceHandle(ScService);
return TRUE;
}
//运行驱动
BOOL StartSys(){
SC_HANDLE ServiceHandle = OpenService(ScHandle,ServiceName,SERVICE_ALL_ACCESS);
if(ServiceHandle ==NULL){
DWORD error = GetLastError();
if (error == ERROR_SERVICE_DOES_NOT_EXIST) {
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("服务已经不存在:%x"), error);
MessageBox(0, ErrorMessage,0,0);
CloseServiceHandle(ServiceHandle);
}
else {
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("打开服务错误:%x"), error);
MessageBox(0, ErrorMessage,0,0);
CloseServiceHandle(ServiceHandle);
}
return FALSE;
}
if(!StartService(ServiceHandle,0,NULL)){
DWORD error = GetLastError();
if (error == ERROR_SERVICE_ALREADY_RUNNING)
{
return TRUE;
}
else
{
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("启动服务出错:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(ServiceHandle);
return FALSE;
}
}
return TRUE;
}
//停止驱动
BOOL StopSys(){
SC_HANDLE serviceHandle = OpenService(ScHandle, ServiceName, SERVICE_ALL_ACCESS);
if (serviceHandle == NULL) {
DWORD error = GetLastError();
if (error == ERROR_SERVICE_DOES_NOT_EXIST) {
MessageBox(0,_T("服务已不存在"),0,0);
CloseServiceHandle(serviceHandle);
}
else {
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("打开服务错误:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(serviceHandle);
}
return FALSE;
}
SERVICE_STATUS error = {0};
if(!ControlService(serviceHandle,SERVICE_CONTROL_STOP,&error)){
DWORD errorCode = GetLastError();
if (errorCode == ERROR_SERVICE_NOT_ACTIVE)
{
CloseServiceHandle(serviceHandle);
return TRUE;
}
else
{
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("停止驱动出错:%x"), errorCode);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(serviceHandle);
return FALSE;
}
}
SERVICE_STATUS status;
QueryServiceStatus(serviceHandle,&status);
if(status.dwCurrentState ==SERVICE_STOP_PENDING){
DWORD dwWaitTime = status.dwWaitHint/10;
if(dwWaitTime<1000){
dwWaitTime=1000;
}
else if(dwWaitTime>10000){
dwWaitTime=10000;
}
Sleep(dwWaitTime);
}
if(QueryServiceStatus(serviceHandle,&status)){
if(status.dwCurrentState ==SERVICE_STOPPED){
CloseServiceHandle(serviceHandle);
}
}
CloseServiceHandle(serviceHandle);
return TRUE;
}
//卸载驱动
BOOL DeleteSys(){
SC_HANDLE serviceHandle = OpenService(ScHandle,ServiceName,SERVICE_ALL_ACCESS);
if (serviceHandle == NULL) {
DWORD error = GetLastError();
if (error != ERROR_SERVICE_DOES_NOT_EXIST) {
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("打开服务错误:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(serviceHandle);
CloseServiceHandle(ScHandle);
return FALSE;
}
}
if (!DeleteService(serviceHandle) ){
DWORD error = GetLastError();
TCHAR ErrorMessage[0x30] = { 0 };
wsprintf(ErrorMessage, TEXT("卸载驱动出错:%x"), error);
MessageBox(0,ErrorMessage,0,0);
CloseServiceHandle(serviceHandle);
CloseServiceHandle(ScHandle);
return FALSE;
}
SERVICE_STATUS status;
QueryServiceStatus(serviceHandle,&status);
CloseServiceHandle(serviceHandle);
CloseServiceHandle(ScHandle);
ScHandle = NULL;
return TRUE;
}
BOOL IoControl(DWORD dwIoCode,PVOID InBuffer,DWORD InBufferLength,PVOID OutBuffer,DWORD OutBufferLength){
DWORD dw;
DeviceIoControl(g_hDriver,dwIoCode,InBuffer,InBufferLength,OutBuffer,OutBufferLength,&dw,NULL);
return TRUE;
}
INT_PTR CALLBACK DiagBoxCallBackProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg)
{
case WM_CLOSE: {
if(Start){
RecoverMessageBoxA();
StopSys();
DeleteSys();
}
EndDialog(hwnd,0);
return TRUE;
}
case WM_COMMAND: {
switch (LOWORD(wParam))
{
case IDC_START:{
DWORD selcet = MessageBoxA(0,"开始监控?",0,MB_OKCANCEL);
if(selcet == IDCANCEL){
return TRUE;
}
DWORD out = 0;
if(Register()){
if(StartSys()){
Open(SYMBOLNAME);
IoControl(StartHook,&FuncAddress,IN_BUFFER_MAXLENGTH,&out,OUT_BUFFER_MAXLENGTH);
if(out ==1){
Start = 1;
CHAR CallAddress[] = {0x00,0x00,0x00,0x00,0x93,0x00};
__asm{
call fword ptr ds:[CallAddress]
push 0x3b
pop fs
}
if(!ChangeMeeageBoxA()){
MessageBox(0,_T("修改MessageBoxA内容失败"),0,0);
}
MessageBoxA(0,"hello",0,0);
//Hook MessageBoxA
}
}
}
return TRUE;
}
case IDC_STOP:
if(Start ==1){
RecoverMessageBoxA();
StopSys();
DeleteSys();
Start=0;
}
return TRUE;
}
default:
return FALSE;
break;
}
return FALSE;
}
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
GetCurrentDirectory(MAX_PATH,szFilePath);
//拼接成驱动的路径
lstrcatW(szFilePath,SysName);
DWORD JmpAddress = (DWORD)StartListen; //0x000322e9 E9 22 03 00 00
DWORD Offset_W = (*(int*)((char*)JmpAddress+1)); //0x00 00 03 22
//*dword offset = ((offset_w&0x000000ff)<<24)+((offset_w&0x0000ff00)<<8)+((offset_w&0x00ff0000)>>8)+((0xff000000&offset_w)>>24);*/
FuncAddress = JmpAddress+5+Offset_W;
MessageBoxAddress = (DWORD)&MessageBoxA;
CHAR LDTR[6]={0};
HookFuncAddresss = (DWORD)VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
DialogBox(hInstance,MAKEINTRESOURCE(IDD_MAIN),0,DiagBoxCallBackProc);
return 0;
}