I'm currently playing with inline patching because I want to understand how it actually works. What I'm trying to do is basically patch NtQuerySystemInformation so that a string is printed everytime the function is called. Here is what I've got until now:
So apparently the patching is successful in that I can see the NtQuerySystemInformation is changed:
Address of NTQUERYSYSINFO IS 82847416
Jump fixed address: 9347DA60
Clearly due to the fact that x86 is little-endian the address is actually reversed so what do I need to change in the FixJMPAddress function in order to get the proper jump address?
Code: Select all
And the writebytestomem:NTSTATUS inlineHookInstall() {
NTSTATUS status;
UNICODE_STRING FuncName = {0};
DWORD dwOldCR0 = 0;
BYTE *funcPointer = NULL;
//get the address we want to start overwriting
funcPointer = getRealFuncAddress((BYTE *)ZwQuerySystemInformation, KeServiceDescriptorTable.KiServiceTable);
if(!funcPointer) {
DbgPrint("Error getting the real address of NtQuerySYsteminformation\n");
return STATUS_UNSUCCESSFUL;
}
DbgPrint("Address of NTQUERYSYSINFO IS %p", funcPointer);
dwOldCR0=__readcr0();
__writecr0(dwOldCR0&~(1<<16));
writeBytesToMem(funcPointer);
__writecr0(dwOldCR0);
return STATUS_SUCCESS;
}
Code: Select all
And the address fixup function:void writeBytesToMem(PVOID Addr) {
BYTE jumpBuf[] = "\xE9\xDE\xAD\xBE\xEF";
PVOID placeHold;
int bytesToOverwrite = 5; //we will try with a basic JMP ADDR instructions
DWORD blockSize = 0;
DWORD instSize;
//count how many bytes we actually have to overwrite without thrashing the system
//uses zombie dissasm engine
while(blockSize < bytesToOverwrite) {
GetInstLenght((PDWORD)((PBYTE)Addr + blockSize), &instSize);
blockSize += instSize;
}
//allocate place for the counted blocksize
placeHold = ExAllocatePoolWithTag(NonPagedPool, blockSize + bytesToOverwrite, 'Nik2');
if(placeHold == NULL) {
DbgPrint("Error allocating temporary space for placeholder\n");
return;
}
//copy the original bytes
RtlCopyMemory(placeHold, Addr, blockSize);
//fill the original place with NOP, just in case
RtlFillMemory(Addr, blockSize, 0x90);
//now instead of 0XDEADBEEF we have the address of our routine.
FixJMPAddress(jumpBuf, (BYTE *)Prolog_NtQuerySys);
DbgPrint("Jump fixed address: %p\n", Prolog_NtQuerySys);
//now we actually overwrite the memory
RtlCopyMemory(Addr, jumpBuf, bytesToOverwrite);
DbgPrint("Writing successful\n");
}
Code: Select all
void FixJMPAddress(BYTE *jump, BYTE *newRoutine) {
DWORD address;
DWORD *dwPtr;
address = (DWORD)newRoutine;
dwPtr = (DWORD *)&(jump[1]);
*dwPtr = address;
}
So apparently the patching is successful in that I can see the NtQuerySystemInformation is changed:
Code: Select all
And here is what my debugging statements say:kd> u 0x82847416
nt!NtQuerySystemInformation:
82847416 e960da4793 jmp 15cc4e7b
8284741b 8b5508 mov edx,dword ptr [ebp+8]
8284741e 83fa53 cmp edx,53h
82847421 7f21 jg nt!NtQuerySystemInformation+0x2e (82847444)
82847423 7440 je nt!NtQuerySystemInformation+0x4f (82847465)
82847425 83fa08 cmp edx,8
82847428 743b je nt!NtQuerySystemInformation+0x4f (82847465)
8284742a 83fa17 cmp edx,17h
Address of NTQUERYSYSINFO IS 82847416
Jump fixed address: 9347DA60
Clearly due to the fact that x86 is little-endian the address is actually reversed so what do I need to change in the FixJMPAddress function in order to get the proper jump address?