Author:Sysnap
The article is my notes and is pubilshed to study with rookies.Because I am rookie yet, Wrongs is showed and please corret to help me.
When API is called by my program,This like CreateWindowEx, Generate code on complied
call dword ptr
[__imp__CreateWindowExA@48],The address of API is save on__imp__CreateWindowExA@48 . When load and runing , __imp__CreateWindowExA@48 representing memory address, So if program is run, __imp__CreateWindowEx@48 is modified to us address,Program call CreateWindowEx, In fact call to jump our function, This is basic idea of IAT HOOK.
The article is about hook driver's iat, Please read iat of customer, had help to understand driver code, Because driver program is PE format as general exe program.
Under the code traverse export function onself, After that print it.
#include
#include
#include
#pragma comment(lib,"imagehlp.lib")
int main()
{
char *dll_name[30];
char* function_name[30];
HMODULE hInstance;
int outloop_index=0;
PIMAGE_THUNK_DATA thunk;
hInstance=GetModuleHandle(NULL);
IMAGE_DOS_HEADER *dosheader= (IMAGE_DOS_HEADER *)hInstance;
IMAGE_NT_HEADERS *ntheader= (IMAGE_NT_HEADERS *)((DWORD)hInstance + dosheader->e_lfanew);
IMAGE_DATA_DIRECTORY *pSymbolTable= &ntheader->OptionalHeader.DataDirectory[1];
IMAGE_IMPORT_DESCRIPTOR *pImportDesc =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hInstance + pSymbolTable->VirtualAddress);
printf("the module is load at:%d\n",hInstance);
printf("the pointer to ImportDesc is: %d\n",pImportDesc);
while(pImportDesc ->FirstThunk)
{
dll_name[outloop_index]=(char*)((PBYTE)hInstance+pImportDesc->Name);
printf("------%s-------\n",dll_name[outloop_index]);
outloop_index++;
thunk=( PIMAGE_THUNK_DATA)((PBYTE)hInstance+ pImportDesc->OriginalFirstThunk);
int x=0;
while(thunk->u1.Function)
{
function_name[x]=(char*)((PBYTE)hInstance +
( DWORD)thunk->u1.AddressOfData+2);
printf("%s\n",function_name[x]);
x++;
thunk++;
}
pImportDesc++;
}
return 0 ;
}
OK, Get hInstance by hInstance=GetModuleHandle(NULL), hInstance represent base address of current program, If not have it, can't positioning to be called memory address of function ,
If We use HOOK C:\WINDOWS\SYSTEM32\test_sysnap.sys,test_sysnap.sys on driver,
The program is very simple , DPC is used to export string on time:
VOID Myroutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)
{
HANDLE id=PsGetCurrentProcessId();
DbgPrint("the Current Process Id is:%x \n",id);
}
Test_sysnap.sys must be import PsGetCurrentProcessId, IAT HOOK the function, When System call Myrotine to execute PsGetCurrentProcessId, After that go to run on our program oneself.
hInstance is important, So IAT HOOK of driver, We must know to load to address of test_sysnap.sys. There use ZwQuerySystemInformation to get. The function isn't hooked,Ok first run test_sysnap.sys,The code last.
-----------------------------------------------------------------------------------------------------------------------
Driver program
#include "ntddk.h"
#include "hookiat.h"
#pragma comment(lib,"ntdll.lib")
PVOID GetDriverBaseAdress(char* driverName)
{
ULONG size,index;
PULONG buf;
PSYSTEM_MODULE_INFORMATION module;
PVOID driverAddress=0;
ZwQuerySystemInformation(SystemModuleInformation,&size, 0, &size);
if(NULL==(buf = (PULONG)ExAllocatePool(PagedPool, size)))
{
DbgPrint("failed alloc memory failed \n");
return 0;
}
status=ZwQuerySystemInformation(SystemModuleInformation,buf, size , 0);
if(!NT_SUCCESS( status ))
{
DbgPrint("failed query\n");
return 0;
}
module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1);
for (index = 0; index < *buf; index++)
if (_stricmp(module[index].ImageName + module[index].ModuleNameOffset, driverName) == 0)
{
driverAddress = module[index].Base;
DbgPrint("Module found at:%x\n",driverAddress);
}
ExFreePool(buf);
return driverAddress;
}
VOID Unload(PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unload Called \r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING str)
{
PVOID base = NULL;
base = GetDriverBaseAdress("test_sysnap.sys.sys");
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}
Compile., Confirm real DbgPrint about address of test_sysnap.sys,/////ok,Our target seach call dword ptr
[__imp__PsGetCurrentProcessId@XX], Modify
First IAT is positioned and seach RAV of PsGetCurrentProcessId////, Last purpose is get (DWORD*)( (BYTE*)base + Thunk ) + RVA, modify ,Base is getted, then want to get Thunk and RVA,
First we use ZwOpenFile,ZwCreateSection,ZwMapViewOfSection etc functions to map test_sysnap.sys, The way is like user program to use CreateFile,CreateFileMapping,MapViewOfFile
PVOID CreateMapFileAndReturnBaseAddress(PUNICODE_STRING pDriverName)
{
HANDLE hFile;
//HANDLE hSection看需要在别的地方ZWclose(hSection),若不用.那定义成局部变量就可以了,或者做为数参数传递
char *pszModName;
PVOID MapFileBaseAddress = NULL;
SIZE_T size=0;
IO_STATUS_BLOCK stataus;
OBJECT_ATTRIBUTES oa ;
InitializeObjectAttributes(
&oa,
pDriverName,
OBJ_CASE_INSENSITIVE,
0,
0
);
ZwOpenFile(&hFile,
FILE_EXECUTE | SYNCHRONIZE,
&oa,
&stataus,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
oa.ObjectName = 0;
ZwCreateSection(&hSection,
SECTION_ALL_ACCESS,
&oa,
0,
PAGE_EXECUTE,
SEC_IMAGE,
hFile);
ZwMapViewOfSection(hSection,
PsGetCurrentProcessId(),
&MapFileBaseAddress,
0,
1024,
0,
&size,
ViewShare,
MEM_TOP_DOWN,
PAGE_READWRITE);
ZwClose(hFile);
DbgPrint("baseadress:%x\n",MapFileBaseAddress);
return MapFileBaseAddress;
}
Add function, DriverEntry add:
UNICODE_STRING driverName;
RtlInitUnicodeString(&driverName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\drivers\\test_sysnap.sys");
BaseAddress= CreateMapFileAndReturnBaseAddress(&driverName);
DbgPrint("MapFile Return Address:%x",BaseAddress);
Compile , Not problem, GOOD, continue, hereto We get MapFileBaseAddress,Then Get ImageImportDescriptor by it.
DWORD GetImageImportDescriptorPointer(IN OUT HANDLE* hMod, IN OUT IMAGE_IMPORT_DESCRIPTOR** pImportDesc)
{
IMAGE_DOS_HEADER * dosheader;
IMAGE_OPTIONAL_HEADER * optheader;
PVOID BaseAddress = NULL;
UNICODE_STRING driverName;
RtlInitUnicodeString(&driverName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\drivers\\test_sysnap.sys");
BaseAddress= CreateMapFileAndReturnBaseAddress(&driverName);
*hMod = BaseAddress;
dosheader= (IMAGE_DOS_HEADER *)BaseAddress;
optheader =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)BaseAddress+dosheader->e_lfanew+24);
*pImportDesc = (IMAGE_IMPORT_DESCRIPTOR *)((BYTE*)dosheader+ optheader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if( NULL == (*pImportDesc)) return 0;
else
return 1;
DbgPrint("DataEntryAddress:%x\n",pImportDesc);
}
Compile, Not problem, hereto we get
MapFileBaseAddress和ImageImportDescriptor, then its is used to seach Thunk and RVA
DWORD GetFunctionThunkAndRav(IN char* lpFunctionName, IN char* lpFunctionLibrary, OUT DWORD* pThunk, OUT DWORD* pRVA)
{
HANDLE hMod;
IMAGE_IMPORT_DESCRIPTOR * pImportDesc;
IMAGE_THUNK_DATA* thunk;
char *pszModName;
DWORD firstThunkList;
DWORD ret;
BOOLEAN isOrdinal;
BOOLEAN foundIt;
int x=0;
SIZE_T size=0;
ret=GetImageImportDescriptorPointer(&hMod,&pImportDesc);
if(ret==0)
{
DbgPrint("GetImageImportDescriptorPointer return NULL");
return 0;
}
//Ergodi IMPORT DIRECTORY TABLE,Seanch ntoskrnl.exe associated IMAGE_IMPORT_DESCRIPTOR
while (pImportDesc->FirstThunk)
{
pszModName = (PSTR) ((PBYTE) hMod + pImportDesc->Name);
if (_stricmp(pszModName, lpFunctionLibrary) == 0 )
{
foundIt = TRUE;
DbgPrint("name:%s\n",pszModName);
break;
}
pImportDesc++;
}
if(foundIt==FALSE)
{
return 0;
}
//Get IMAGE_IMPORT_DESCRIPTOR of ntoskrnl.exe to get IAT, Can find export function on IAT
thunk = (IMAGE_THUNK_DATA*)( (BYTE*)hMod + pImportDesc->OriginalFirstThunk);
firstThunkList = (DWORD)((PBYTE)hMod + pImportDesc->FirstThunk);
foundIt = FALSE;
while(thunk->u1.Function)
{
isOrdinal = 0;
//IMAGE_THUNK_DATA is DWORD in fact, Either is Ordinal, or AddressOfData
if(thunk->u1.Function >= 0x01000000) isOrdinal = TRUE;
if(!isOrdinal) // 以名字到处而不是序号
{
//IMAGE_IMPORT_BY_NAME
char* functionName = (char*)( (BYTE*)hMod + (DWORD)thunk->u1.AddressOfData + 2 );
if (_stricmp(functionName, lpFunctionName) == 0 )
{
*pThunk = pImportDesc->FirstThunk;
*pRVA = x;
DbgPrint("%x",( DWORD *)((PBYTE)hMod +pImportDesc->FirstThunk)+x);
ZwClose(hSection);
return 1;
}
}
if(isOrdinal)
{
ZwClose(hSection);
return (DWORD) NULL;
}
x++;
thunk++;
firstThunkList++;
}
if(foundIt==FALSE)
{
ZwClose(hSection);
return 0;
}
ZwClose(hSection);
return 0;
}
Add the function, Chesck this function , Not problem, We already get (DWORD*)( (BYTE*)base + Thunk ) + RVA, Hereto is final work , modify
g_FunctionInMemory = (DWORD*)( (BYTE*)base + Thunk ) + RVA;
.
.
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
*(PVOID*)g_FunctionInMemory = MyPsGetCurrentProcessId;
DbgPrint("HOOK SUCESS");
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
When API is called by my program,This like CreateWindowEx, Generate code on complied
call dword ptr
[__imp__CreateWindowExA@48],The address of API is save on__imp__CreateWindowExA@48 . When load and runing , __imp__CreateWindowExA@48 representing memory address, So if program is run, __imp__CreateWindowEx@48 is modified to us address,Program call CreateWindowEx, In fact call to jump our function, This is basic idea of IAT HOOK.
The article is about hook driver's iat, Please read iat of customer, had help to understand driver code, Because driver program is PE format as general exe program.
Under the code traverse export function onself, After that print it.
#include
#include
#include
#pragma comment(lib,"imagehlp.lib")
int main()
{
char *dll_name[30];
char* function_name[30];
HMODULE hInstance;
int outloop_index=0;
PIMAGE_THUNK_DATA thunk;
hInstance=GetModuleHandle(NULL);
IMAGE_DOS_HEADER *dosheader= (IMAGE_DOS_HEADER *)hInstance;
IMAGE_NT_HEADERS *ntheader= (IMAGE_NT_HEADERS *)((DWORD)hInstance + dosheader->e_lfanew);
IMAGE_DATA_DIRECTORY *pSymbolTable= &ntheader->OptionalHeader.DataDirectory[1];
IMAGE_IMPORT_DESCRIPTOR *pImportDesc =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hInstance + pSymbolTable->VirtualAddress);
printf("the module is load at:%d\n",hInstance);
printf("the pointer to ImportDesc is: %d\n",pImportDesc);
while(pImportDesc ->FirstThunk)
{
dll_name[outloop_index]=(char*)((PBYTE)hInstance+pImportDesc->Name);
printf("------%s-------\n",dll_name[outloop_index]);
outloop_index++;
thunk=( PIMAGE_THUNK_DATA)((PBYTE)hInstance+ pImportDesc->OriginalFirstThunk);
int x=0;
while(thunk->u1.Function)
{
function_name[x]=(char*)((PBYTE)hInstance +
( DWORD)thunk->u1.AddressOfData+2);
printf("%s\n",function_name[x]);
x++;
thunk++;
}
pImportDesc++;
}
return 0 ;
}
OK, Get hInstance by hInstance=GetModuleHandle(NULL), hInstance represent base address of current program, If not have it, can't positioning to be called memory address of function ,
If We use HOOK C:\WINDOWS\SYSTEM32\test_sysnap.sys,test_sysnap.sys on driver,
The program is very simple , DPC is used to export string on time:
VOID Myroutine(IN PKDPC Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)
{
HANDLE id=PsGetCurrentProcessId();
DbgPrint("the Current Process Id is:%x \n",id);
}
Test_sysnap.sys must be import PsGetCurrentProcessId, IAT HOOK the function, When System call Myrotine to execute PsGetCurrentProcessId, After that go to run on our program oneself.
hInstance is important, So IAT HOOK of driver, We must know to load to address of test_sysnap.sys. There use ZwQuerySystemInformation to get. The function isn't hooked,Ok first run test_sysnap.sys,The code last.
-----------------------------------------------------------------------------------------------------------------------
Driver program
#include "ntddk.h"
#include "hookiat.h"
#pragma comment(lib,"ntdll.lib")
PVOID GetDriverBaseAdress(char* driverName)
{
ULONG size,index;
PULONG buf;
PSYSTEM_MODULE_INFORMATION module;
PVOID driverAddress=0;
ZwQuerySystemInformation(SystemModuleInformation,&size, 0, &size);
if(NULL==(buf = (PULONG)ExAllocatePool(PagedPool, size)))
{
DbgPrint("failed alloc memory failed \n");
return 0;
}
status=ZwQuerySystemInformation(SystemModuleInformation,buf, size , 0);
if(!NT_SUCCESS( status ))
{
DbgPrint("failed query\n");
return 0;
}
module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1);
for (index = 0; index < *buf; index++)
if (_stricmp(module[index].ImageName + module[index].ModuleNameOffset, driverName) == 0)
{
driverAddress = module[index].Base;
DbgPrint("Module found at:%x\n",driverAddress);
}
ExFreePool(buf);
return driverAddress;
}
VOID Unload(PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unload Called \r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING str)
{
PVOID base = NULL;
base = GetDriverBaseAdress("test_sysnap.sys.sys");
DriverObject->DriverUnload = Unload;
return STATUS_SUCCESS;
}
Compile., Confirm real DbgPrint about address of test_sysnap.sys,/////ok,Our target seach call dword ptr
[__imp__PsGetCurrentProcessId@XX], Modify
First IAT is positioned and seach RAV of PsGetCurrentProcessId////, Last purpose is get (DWORD*)( (BYTE*)base + Thunk ) + RVA, modify ,Base is getted, then want to get Thunk and RVA,
First we use ZwOpenFile,ZwCreateSection,ZwMapViewOfSection etc functions to map test_sysnap.sys, The way is like user program to use CreateFile,CreateFileMapping,MapViewOfFile
PVOID CreateMapFileAndReturnBaseAddress(PUNICODE_STRING pDriverName)
{
HANDLE hFile;
//HANDLE hSection看需要在别的地方ZWclose(hSection),若不用.那定义成局部变量就可以了,或者做为数参数传递
char *pszModName;
PVOID MapFileBaseAddress = NULL;
SIZE_T size=0;
IO_STATUS_BLOCK stataus;
OBJECT_ATTRIBUTES oa ;
InitializeObjectAttributes(
&oa,
pDriverName,
OBJ_CASE_INSENSITIVE,
0,
0
);
ZwOpenFile(&hFile,
FILE_EXECUTE | SYNCHRONIZE,
&oa,
&stataus,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
oa.ObjectName = 0;
ZwCreateSection(&hSection,
SECTION_ALL_ACCESS,
&oa,
0,
PAGE_EXECUTE,
SEC_IMAGE,
hFile);
ZwMapViewOfSection(hSection,
PsGetCurrentProcessId(),
&MapFileBaseAddress,
0,
1024,
0,
&size,
ViewShare,
MEM_TOP_DOWN,
PAGE_READWRITE);
ZwClose(hFile);
DbgPrint("baseadress:%x\n",MapFileBaseAddress);
return MapFileBaseAddress;
}
Add function, DriverEntry add:
UNICODE_STRING driverName;
RtlInitUnicodeString(&driverName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\drivers\\test_sysnap.sys");
BaseAddress= CreateMapFileAndReturnBaseAddress(&driverName);
DbgPrint("MapFile Return Address:%x",BaseAddress);
Compile , Not problem, GOOD, continue, hereto We get MapFileBaseAddress,Then Get ImageImportDescriptor by it.
DWORD GetImageImportDescriptorPointer(IN OUT HANDLE* hMod, IN OUT IMAGE_IMPORT_DESCRIPTOR** pImportDesc)
{
IMAGE_DOS_HEADER * dosheader;
IMAGE_OPTIONAL_HEADER * optheader;
PVOID BaseAddress = NULL;
UNICODE_STRING driverName;
RtlInitUnicodeString(&driverName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\drivers\\test_sysnap.sys");
BaseAddress= CreateMapFileAndReturnBaseAddress(&driverName);
*hMod = BaseAddress;
dosheader= (IMAGE_DOS_HEADER *)BaseAddress;
optheader =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)BaseAddress+dosheader->e_lfanew+24);
*pImportDesc = (IMAGE_IMPORT_DESCRIPTOR *)((BYTE*)dosheader+ optheader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if( NULL == (*pImportDesc)) return 0;
else
return 1;
DbgPrint("DataEntryAddress:%x\n",pImportDesc);
}
Compile, Not problem, hereto we get
MapFileBaseAddress和ImageImportDescriptor, then its is used to seach Thunk and RVA
DWORD GetFunctionThunkAndRav(IN char* lpFunctionName, IN char* lpFunctionLibrary, OUT DWORD* pThunk, OUT DWORD* pRVA)
{
HANDLE hMod;
IMAGE_IMPORT_DESCRIPTOR * pImportDesc;
IMAGE_THUNK_DATA* thunk;
char *pszModName;
DWORD firstThunkList;
DWORD ret;
BOOLEAN isOrdinal;
BOOLEAN foundIt;
int x=0;
SIZE_T size=0;
ret=GetImageImportDescriptorPointer(&hMod,&pImportDesc);
if(ret==0)
{
DbgPrint("GetImageImportDescriptorPointer return NULL");
return 0;
}
//Ergodi IMPORT DIRECTORY TABLE,Seanch ntoskrnl.exe associated IMAGE_IMPORT_DESCRIPTOR
while (pImportDesc->FirstThunk)
{
pszModName = (PSTR) ((PBYTE) hMod + pImportDesc->Name);
if (_stricmp(pszModName, lpFunctionLibrary) == 0 )
{
foundIt = TRUE;
DbgPrint("name:%s\n",pszModName);
break;
}
pImportDesc++;
}
if(foundIt==FALSE)
{
return 0;
}
//Get IMAGE_IMPORT_DESCRIPTOR of ntoskrnl.exe to get IAT, Can find export function on IAT
thunk = (IMAGE_THUNK_DATA*)( (BYTE*)hMod + pImportDesc->OriginalFirstThunk);
firstThunkList = (DWORD)((PBYTE)hMod + pImportDesc->FirstThunk);
foundIt = FALSE;
while(thunk->u1.Function)
{
isOrdinal = 0;
//IMAGE_THUNK_DATA is DWORD in fact, Either is Ordinal, or AddressOfData
if(thunk->u1.Function >= 0x01000000) isOrdinal = TRUE;
if(!isOrdinal) // 以名字到处而不是序号
{
//IMAGE_IMPORT_BY_NAME
char* functionName = (char*)( (BYTE*)hMod + (DWORD)thunk->u1.AddressOfData + 2 );
if (_stricmp(functionName, lpFunctionName) == 0 )
{
*pThunk = pImportDesc->FirstThunk;
*pRVA = x;
DbgPrint("%x",( DWORD *)((PBYTE)hMod +pImportDesc->FirstThunk)+x);
ZwClose(hSection);
return 1;
}
}
if(isOrdinal)
{
ZwClose(hSection);
return (DWORD) NULL;
}
x++;
thunk++;
firstThunkList++;
}
if(foundIt==FALSE)
{
ZwClose(hSection);
return 0;
}
ZwClose(hSection);
return 0;
}
Add the function, Chesck this function , Not problem, We already get (DWORD*)( (BYTE*)base + Thunk ) + RVA, Hereto is final work , modify
g_FunctionInMemory = (DWORD*)( (BYTE*)base + Thunk ) + RVA;
.
.
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
*(PVOID*)g_FunctionInMemory = MyPsGetCurrentProcessId;
DbgPrint("HOOK SUCESS");
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
No comments:
Post a Comment