首页
社区
课程
招聘
[求助]对HOOK的另一种实现
发表于: 2009-3-4 21:05 7556

[求助]对HOOK的另一种实现

2009-3-4 21:05
7556
在看雪了里,学到了不少大牛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直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (9)
雪    币: 152
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我是来抢沙发的
2009-3-4 21:08
0
雪    币: 215
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
应该需要什么重定位吧,如果把整个干净的内核复制一份,不知道有没有用
2009-3-4 21:24
0
雪    币: 991
活跃值: (195)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个,是通过附件里的反汇编引擎,反汇编后复制的,对反汇编引擎作了些短跳转的修改,有兴趣的朋友可以看看,并不是
把整个干净的内核复制一份
2009-3-4 21:29
0
雪    币: 60
活跃值: (675)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
我是来下楼主的代码的
2009-3-4 23:45
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
改他的入口进你的函数?不跑回去怎么执行他的过程?
2009-3-5 17:34
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
7
据说ICESWORD就是这么做的
2009-3-5 17:45
0
雪    币: 189
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
我测试过了。这种思路没有问题,问题出现在反汇编上面。我看了下反汇编引擎,这个反汇编没有对了0F80-0F8F\EB\E3指令,进行正确的处理。
2009-3-11 21:25
0
雪    币: 7309
活跃值: (3778)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
9
内核里面的函数不一定是地址线性增长的
2009-3-11 21:52
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
10
不跑回去执行当然是可以的,只是那样搞就需要多做些工作,比如重定位,麻烦了一点,所以大家都偷懒不用啦~
2009-3-12 15:01
0
游客
登录 | 注册 方可回帖
返回
//