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...
No comments:
Post a Comment