在看雪了里,学到了不少大牛HOOK的技术,这里就不一一的感谢了。不过终究还是离不开这种模式:修改原函数头+N个字节处,实现跳转到自己A函数,在自己的A函数里加一些特别功能,再执行原函数被修改的代码,再跳到原修改处的下一句代码。
我就想(我是菜鸟),既然到跳的A函数了,能不能永远不跳回原代码,就让它在A函数里直接就行,返回了事,这样可以,清除所有的其它 内联HOOK。
思路:从源文件中,找到导出函数地址,把这个地址反汇编到自己的空间里的A函数里,修改源函数,使之跳转到A函数里。和以前不同的是不跳转回源函数。
我在R0做了一试实验.代码如下:
代码:
#define EMPTP_ASM_32(x) __asm { __asm _emit x __asm _emit x __asm _emit x __asm _emit x __asm _emit x __asm _emit x __asm _emit x __asm _emit x } #define CLR_WP() \ __asm cli \ __asm mov eax,cr0 \ __asm and eax,not 10000h \ __asm mov cr0,eax #define SET_WP() \ __asm mov eax,cr0 \ __asm or eax,10000h \ __asm mov cr0,eax \ __asm sti //1K的空位 __declspec( naked ) IMP_NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ) { EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) ..... EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) EMPTP_ASM_32(0x90) } NTSTATUS Skip_NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId OPTIONAL ) { DWORD dwJmpFunAddr = (DWORD)IMP_NtOpenProcess; DWORD dwRunAdd; NTSTATUS rc; __asm { mov dwJmpFunAddr, offset _HX_EXIT_SIGN push ClientId push ObjectAttributes push DesiredAccess push ThreadHandle push dwRunAdd push dwJmpFunAddr ret _HX_EXIT_SIGN: mov rc, eax add esp, 10H } return rc; } //这个函数是抄的 ULONG GetKernelBaseAddress(OUT PCHAR lpszModule) { NTSTATUS ntStatus; ULONG NeededSize, KernelAddr;//uLoop PMODULE_LIST pModuleList; KernelAddr = 0; ZwQuerySystemInformation( SystemModuleInformation, &NeededSize, 0, &NeededSize); pModuleList = ExAllocatePool( NonPagedPool, NeededSize ); ntStatus = ZwQuerySystemInformation( SystemModuleInformation, pModuleList, NeededSize, NULL ); if ( NT_SUCCESS(ntStatus) ) { //ntoskrnl is always first there KernelAddr = (ULONG)pModuleList->SysModuleInfo[0].Base; strcpy( lpszModule, "\\SystemRoot\\System32\\" ); strcat( lpszModule, pModuleList->SysModuleInfo[0].ModuleNameOffset + pModuleList->SysModuleInfo[0].ImageName ); } ExFreePool(pModuleList); return KernelAddr; } //这个函数是抄的 PUCHAR GetExportFunFormBase(PCHAR ImageBase, PCSTR Name) { PIMAGE_DOS_HEADER DosHeader; PIMAGE_NT_HEADERS PeHeader; PIMAGE_DATA_DIRECTORY ImageExportDirectoryEntry; ULONG ExportDirectorySize, ExportDirectoryOffset, i; PIMAGE_EXPORT_DIRECTORY ExportDirectory; PULONG ExportAddressTable; PSHORT ExportOrdinalTable; PULONG ExportNameTable; if ( (DosHeader = (PIMAGE_DOS_HEADER)ImageBase) == NULL) return NULL; if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL; if (DosHeader->e_lfanew > 1024*1024) return NULL; if ( (PeHeader = (PIMAGE_NT_HEADERS) (ImageBase + DosHeader->e_lfanew)) == NULL) return NULL; //if (PeHeader->Signature != IMAGE_PE_SIGNATURE) if (PeHeader->Signature != IMAGE_NT_SIGNATURE) return NULL; if ( (ImageExportDirectoryEntry = PeHeader->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT) == NULL) return NULL; ExportDirectorySize = ImageExportDirectoryEntry->Size; ExportDirectoryOffset = ImageExportDirectoryEntry->VirtualAddress; if ( (ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (ImageBase + ExportDirectoryOffset)) == NULL) return NULL; ExportAddressTable = (PULONG)(ImageBase + ExportDirectory->AddressOfFunctions); ExportOrdinalTable = (PSHORT)(ImageBase + ExportDirectory->AddressOfNameOrdinals); ExportNameTable = (PULONG)(ImageBase + ExportDirectory->AddressOfNames); for (i = 0; i < ExportDirectory->NumberOfNames; i++) { ULONG ord = ExportOrdinalTable[i]; if ( ExportAddressTable[ord] < ExportDirectoryOffset || ExportAddressTable[ord] >= ExportDirectoryOffset + ExportDirectorySize) { if (strcmp(ImageBase + ExportNameTable[i], Name) == 0) { return ImageBase + ExportAddressTable[ord]; } } } return NULL; } BOOL HookNtOpenProcessFunction(PUCHAR jmpFun,OUT PUCHAR sotreFun/*输出反汇编代码*/) { //取ntoskrnl ImageBase 略过, PUCHAR pOrgiAddr=GetExportFunFormBase(ImageBase,"NtOpenProcess"); PUCHAR pCurrAddr=(PUCHAR)NtOpenProcess; PUCHAR pOutAddr= sotreFun; UCHAR jmp_hook_code[]={ 0xe9, 0x00, 0x00, 0x00, 0x00, 0x90,0x90,0x90,0x90,0x90,0x90}; UINT nJmpHookCodeLen = sizeof(jmp_hook_code)-6; //跳转代码长度 UINT nNextLen=0,i=0; UINT bIsOK=FALSE; while(TRUE) //复制代码 { //反汇编 见附件 nNextLen=getNextInstruction(pOrgiAddr,1,pOutAddr,10); i+=nNextLen; pOutAddr+=nNextLen; pOrgiAddr+=nNextLen; if(!bIsOk && i>=nJmpHookCodeLen ) //保证是完整指令替换 { nJmpHookCodeLen=i; bIsOk=TRUE; } //是否到函数的结尾 if( (pOrgiAddr[0]==0x90 && pOrgiAddr[1]==0x90 && pOrgiAddr[2]==0x90 && pOrgiAddr[3]==0x90 ) || (pOrgiAddr[0]==0xCC && pOrgiAddr[1]==0xCC && pOrgiAddr[2]==0xCC && pOrgiAddr[3]==0xCC ) ) { nNextLen=4; IsJmpBack=FALSE; RtlCopyMemory(pOutAddr,pOrgiAddr,nNextLen); i+=nNextLen; pOutAddr+=nNextLen; pOrgiAddr+=nNextLen; break; } } if(i>0) { *((ULONG*)(jmp_orig_code + 1) )=(ULONG)jmpFun; CLR_WP(); RtlCopyMemory(originalCode,jmp_hook_code,nJmpHookCodeLen); SET_WP(); return TRUE; } return FALSE; } void InitHook() { PUCHAR addr1=(PUCHAR)Skip_NtOpenProcess; PUCHAR addr2=(PUCHAR)IMP_NtOpenProcess;// HookNtOpenProcessFunction(addr1,addr2);/*从ntoskrnl.exe 文件中,读NtOpenProcess真实地址,,并对NtOpenProcess从文件进行反汇编输出*/ }