用google搜索了几天相关内容的资料,将所提到的逐一实现。哎,不禁感叹自己太菜了。居然用了几天的时间。没啥新思想、内容,只是总结,当然还有其他方法没总结到。但经常提到的ring3下的快照、psapi的EnumProcesses、暴力OpenProcess;ring0下的ZwQuerySystemInformation、activprocess链、暴力搜索内存、PspCidTable、Csrss进程的ObjectTable、进程的SessionProcessList、ZwQuerySystemInformation的全局句柄表、hook SwapContext.就这么多吧,大牛飘过。算一个枚举进程的科普吧。废话不多说,直接上代码:
ring3:
1.ring3下的快照:
void main()
{
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hSnap == INVALID_HANDLE_VALUE )
{
cout<<"Create Toolhelp false"<<endl;
return;
}
PROCESSENTRY32 pEntry32 = {0};
pEntry32.dwSize = sizeof(PROCESSENTRY32);
bool bRes = Process32First( hSnap, &pEntry32 );
int pNums = 0;
while( bRes )
{
pNums++;
cout<<"PID:"<<pEntry32.th32ProcessID<<"\t"<<"Path:"<<pEntry32.szExeFile<<endl;
bRes = Process32Next( hSnap, &pEntry32 );
}
CloseHandle( hSnap );
cout<<"Process Nums:"<<pNums<<endl;
}
效果:
2.psapi的EnumProcesses
DWORD dProcessIds[1024] = {0};
DWORD dRet = 0;
DWORD dRes = 0;
dRes = EnumProcesses( dProcessIds, sizeof(dProcessIds), &dRet );
if( dRes == 0 )
{
cout<<"EnumProcesses1 False"<<endl;
return;
}
int ProcessNums = dRet/sizeof(DWORD);
for( int i = 0; i < ProcessNums; i++ )
GetProcessPathById( dProcessIds[i] );
cout<<"Process Nums:"<<ProcessNums<<endl;
效果:
3.ring3下的暴力枚举:
RaisePrivileges();
for( int i = 0; i <0xffff; i++ )
{
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, false, i );
if( hProcess )
{
char ProcessName[MAX_PATH] = {0};
GetProcessImageFileName( hProcess, ProcessName, MAX_PATH );
cout<<"PID:"<<i<<"\t"<<"Path:"<<ProcessName<<endl;
}
}
效果:
ring0:
1.利用ZwQuerySystemInformation的第5号功能,获取系统进程表
NTSTATUS Status = STATUS_SUCCESS;
NtQuerySystemInformation( 5, pBuff, 0, &uRet );
pBuff = (PCHAR)ExAllocatePool( NonPagedPool, uRet );
pTemp = pBuff;
Status = NtQuerySystemInformation( 5, pBuff, uRet, NULL );
if( NT_SUCCESS(Status) )
{
while( 1 )
{
PSYSTEM_PROCESS_INFORMATION pSystemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pTemp;
RtlUnicodeStringToAnsiString( &ansi, &pSystemProcessInfo->ImageName, TRUE );
DbgPrint("PId:%d\t", pSystemProcessInfo->ProcessId);
DbgPrint("Path:%s\n", ansi.Buffer );
RtlFreeAnsiString( &ansi );
if( pSystemProcessInfo->NextEntryOffset == 0 )
break;
pTemp = pTemp+pSystemProcessInfo->NextEntryOffset;
}
}
效果:
2.利用ZwQuerySystemInformation的第16号功能,获取系统进程表
void DisplayInfo()
{
NTSTATUS Status = STATUS_SUCCESS;
PCHAR pBuff = NULL;
ULONG uNums = 0;
ULONG uRet = 0;
PSYSTEM_HANDLE_INFORMATION_EX pSystemHandle = NULL;
pBuff = (PCHAR)ExAllocatePool( NonPagedPool, 100 );
Status = ZwQuerySystemInformation( 16, pBuff, 100, &uRet );
ExFreePool( pBuff );
pBuff = (PCHAR)ExAllocatePool( NonPagedPool, uRet );
Status = ZwQuerySystemInformation( 16, pBuff, uRet, NULL );
if( NT_SUCCESS(Status) )
{
ULONG index = 0;
LONG PId = -1;
pSystemHandle = (PSYSTEM_HANDLE_INFORMATION_EX)pBuff;
uNums = pSystemHandle->NumberOfHandles;
for(; index < uNums; index++ )
{
if( pSystemHandle->Information[index].ProcessId != PId )
{
PId = pSystemHandle->Information[index].ProcessId;
Display( pSystemHandle->Information[index].ProcessId );
}
}
}
else
{
DbgPrint("NtQuerySystemInformation False");
return;
}
效果:
3.利用进程的ActiveProcessList
void DisplayInfo()
{
PEPROCESS pEprocess = NULL, pTemp = NULL;
pEprocess = PsGetCurrentProcess();
pTemp = pEprocess;
do
{
DbgPrint("PId:%d\t", *(PULONG)((ULONG)pTemp+0x084) );
DbgPrint("Path:%s\n", (PUCHAR)((ULONG)pTemp+0x174 ));
pTemp = (PEPROCESS)( (ULONG)(*(PULONG)((ULONG)pTemp+0x088)) - 0x088 );
} while ( pTemp != pEprocess );
}
效果:
4.ring0下暴力搜索内存
void DisplayInfo()
{
ULONG uStartAddr = 0x80000000;
PEPROCESS pCurrent = PsGetCurrentProcess();
// ULONG uPetAddr = (ULONG)PsGetProcessPeb( pCurrent );
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)((ULONG)pCurrent+0x084), (PUCHAR)((ULONG)pCurrent+0x174));
for(; uStartAddr < (ULONG)pCurrent+0x800000; uStartAddr += 4 )
{
ULONG uRet = IsValidAddr( uStartAddr );
if( uRet == VALID_PAGE )
{
if( ( *(PULONG)uStartAddr & 0xffff0000) == 0x7ffd0000 )
{
if( IsRealProcess(uStartAddr - 0x1b0) )
{
PLARGE_INTEGER pExitTime = (PLARGE_INTEGER)(uStartAddr-0x1b0+0x078);
if( pExitTime->QuadPart == 0 )
{
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)(uStartAddr-0x1b0+0x084), (PUCHAR)(uStartAddr-0x1b0+0x174));
}
uStartAddr -= 4;
uStartAddr += 0x25c;
}
}
}
else if( uRet == PDEINVALID )
{
uStartAddr -= 4;
uStartAddr += 0x400000;
}
else
{
uStartAddr -= 4;
uStartAddr += 0x1000;
}
}
}
效果:
5.PspCidTable
void DisplayInfo()
{
ULONG pCidTableAddr = 0;
PHANDLE_TABLE pCidHandleTable = NULL;
PHANDLE_TABLE_ENTRY pTable1, *pTable2, **pTable3;
ULONG pRealHandleTable = 0;
ULONG level = 0;
ULONG uMax_Handle = 0;
pCidTableAddr = GetCidTableAddr();
pCidHandleTable = (PHANDLE_TABLE)(*(PULONG)pCidTableAddr);
level = (pCidHandleTable->TableCode) & 0x3;
pRealHandleTable = (pCidHandleTable->TableCode) & ~0x3;
uMax_Handle = pCidHandleTable->NextHandleNeedingPool;
switch( level )
{
case 0:
{
ULONG index = 0;
pTable1 = (PHANDLE_TABLE_ENTRY)(pRealHandleTable);
for( index = 0; index < MAX_ENT_CNT; index++ )
{
if( pTable1[index].Object != NULL )
{
ULONG pObject = (ULONG)(pTable1[index].Object) & ~7 ;
if( MmIsAddressValid((PULONG)(pObject - 0x10)) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject - 0x10));
if( pType == *PsProcessType )
{
DbgPrint("PId:%d\tPath:%s\n", index*4, PsGetProcessImageFileName((PEPROCESS)pObject) );
}
}
}
}
break;
}
case 1:
{
ULONG index = 0;
pTable2 = (PHANDLE_TABLE_ENTRY*)(pRealHandleTable);
for( index = 0; index < uMax_Handle/(4*MAX_ENT_CNT); index++ )
{
pTable1 = pTable2[index];
if( pTable1 == NULL )
break;
else
{
ULONG i = 0;
for( i = 0; i < MAX_ENT_CNT; i++ )
{
if( pTable1[i].Object != NULL )
{
ULONG pObject = (ULONG)(pTable1[i].Object) & ~7;
if( MmIsAddressValid( (PULONG)(pObject-0x10) ) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject-0x10));
if( pType == *PsProcessType )
{
DbgPrint("PId:%d\tPath:%s\n", index*MAX_ENT_CNT*4+i*4, PsGetProcessImageFileName((PEPROCESS)pObject) );
}
}
}
}
}
}
break;
}
case 2:
{
ULONG index = 0;
pTable3 = (PHANDLE_TABLE_ENTRY**)(pRealHandleTable);
for( index = 0; index < uMax_Handle/(MAX_ADD_CNT*MAX_ENT_CNT*4); index++ )
{
ULONG i = 0;
pTable2 = (PHANDLE_TABLE_ENTRY*)((ULONG)pTable3[index] & ~0x3);
if( pTable2 == NULL )
break;
for( i = 0; i < MAX_ADD_CNT; i++ )
{
pTable1 = pTable2[i];
if( pTable1 == NULL )
break;
else
{
ULONG j = 0;
for( j = 0; j < MAX_ENT_CNT; j++ )
{
if( pTable1[j].Object != NULL )
{
ULONG pObject = (ULONG)(pTable1[j].Object) & ~7;
if( MmIsAddressValid( (PULONG)(pObject-0x10) ) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject-0x10));
if( pType == *PsProcessType )
{
DbgPrint("PId:%d\tPath:%s\n", index*MAX_ADD_CNT*MAX_ENT_CNT*4+i*MAX_ENT_CNT*4+j*4,\
PsGetProcessImageFileName((PEPROCESS)pObject) );
}
}
}
}
}
}
}
}
break;
}
}
效果:
6.Inline Hook KiSwapContext
_declspec(naked) void MySwapContext()
{
_asm
{
pushad
pushfd
cli
}
_asm
{
push esi
push edi
call ShowProcess
}
_asm
{
sti
popfd
popad
}
_asm jmp DWORD PTR[pBackAddr]
}
效果:
7.Csrss进程中枚举进程
void DisplayInfo()
{
PEPROCESS pEProcess = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PHANDLE_TABLE pObjectTable = NULL;
PHANDLE_TABLE_ENTRY table1, *table2, **table3;
ULONG level;
ULONG pRealHandleTable;
ULONG uHandleCount;
pEProcess = GetCsrssObject();
pObjectTable = (PHANDLE_TABLE)(*(PULONG)((ULONG)pEProcess + 0xc4));
level = pObjectTable->TableCode & 3;
pRealHandleTable = pObjectTable->TableCode & ~3;
uHandleCount = pObjectTable->NextHandleNeedingPool;
switch( level )
{
case 0:
{
ULONG index = 0;
table1 = (PHANDLE_TABLE_ENTRY)pRealHandleTable;
for( index = 0; index < MAX_ENT_CNT; index++ )
{
ULONG pObject = (ULONG)(table1[index].Object) & ~7;
if( MmIsAddressValid( (PULONG)(pObject+0x8) ) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject+0x8));
if( pType == *PsProcessType )
{
PEPROCESS pAddr = (PEPROCESS)(pObject+0x18);
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)((ULONG)pAddr+0x84), (PUCHAR)((ULONG)pAddr+0x174) );
}
}
}
break;
}
case 1:
{
ULONG index = 0;
table2 = (PHANDLE_TABLE_ENTRY*)pRealHandleTable;
for( index = 0; index < uHandleCount/MAX_ENT_CNT; index++ )
{
ULONG i = 0;
table1 = table2[index];
if( table1 == NULL )
break;
for( i = 0; i < MAX_ENT_CNT; i++ )
{
ULONG pObject = (ULONG)(table1[i].Object) & ~7;
if( MmIsAddressValid( (PULONG)(pObject+0x8) ) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject+0x8));
if( pType == *PsProcessType )
{
ULONG pAddr = (ULONG)(pObject+0x18);
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)(pAddr+0x84), (PUCHAR)(pAddr+0x174) );
}
}
}
}
break;
}
case 2:
{
ULONG index = 0;
table3 = (PHANDLE_TABLE_ENTRY**)pRealHandleTable;
for( index = 0; index < uHandleCount/(MAX_ENT_CNT*MAX_ADD_CNT); index++ )
{
ULONG i = 0;
table2 = table3[index];
if( table2 == NULL )
break;
for( i = 0; i < MAX_ADD_CNT; i++ )
{
ULONG j = 0;
table1 = table2[i];
if( table1 == NULL )
break;
for( j = 0; j < MAX_ENT_CNT; j++ )
{
ULONG pObject = (ULONG)(table1[j].Object) & ~7;
if( MmIsAddressValid( (PULONG)(pObject+0x8) ) )
{
POBJECT_TYPE pType = (POBJECT_TYPE)(*(PULONG)(pObject+0x8));
if( pType == *PsProcessType )
{
ULONG pAddr = (ULONG)(pObject+0x18);
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)(pAddr+0x84), (PUCHAR)(pAddr+0x174) );
}
}
}
}
}
break;
}
}
}
效果:
8.SessionProcessList枚举
void DisplayInfo()
{
PEPROCESS pEProcess = PsGetCurrentProcess();
PEPROCESS pTemp = pEProcess;
DbgPrint("PId:%d\tPath:%s\n", *(PULONG)((ULONG)pTemp+0x84), (PUCHAR)((ULONG)pTemp+0x174) );
pTemp = (PEPROCESS)( *(PULONG)(*(PULONG)((ULONG)pTemp + 0x8c) + 0x4) - 0x88 );//取用户进程
pEProcess = pTemp;
do
{
if( MmIsAddressValid(pTemp) )
{
DbgPrint("PId:%d\tPath:%s\n", *(PLONG)((LONG)pTemp+0x84), (PUCHAR)((ULONG)pTemp+0x174) );
pTemp = (PEPROCESS)(*(PULONG)((ULONG)pTemp+0xb4) - 0xb4 );
}
else
break;
} while ( pEProcess != pTemp );
}
效果:
就总结了这些。一直以来自己都是零零散散地学习,最近想系统地对内核进行学习,就先从进程开始了。下次再针对以上的枚举方法,进程隐藏。
ring0:
ring0.rar
ring3:
ring3.rar
[注意]APP应用上架合规检测服务,协助应用顺利上架!