在看雪了里,学到了不少大牛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从文件进行反汇编输出*/
}
以上为代码,不过这段代码老是出问题,开始会成功,后面就挂了。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课