A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #807  by GamingMasteR
 Tue Apr 20, 2010 11:46 pm
Hi,

Found this in chinese site, not sure if you know this method but it's new to me :)
Code: Select all
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <vector>

using namespace std;

#pragma comment(lib, "psapi.lib")

/////////////////////////////////////////////////////////////////////////////
// Structure extract from "Windows Graphics Programming: Win32 GDI and DirectDraw"
//
typedef struct _GDITableCell
{
	void          *  pKernel;
	unsigned short  _nProcess; // NT/2000 switch order for _nProcess, _nCount
	unsigned short  _nCount;
	unsigned short   nUpper;
	unsigned short   nType;
	void          *  pUser;
} GDITableCell, *PGDITableCell;

typedef unsigned (CALLBACK * Proc0) (void);

#define MAXGDIHANDLE 16384
//
/////////////////////////////////////////////////////////////////////////////

typedef struct _ProcessInfo
{
	DWORD ProcessId;

} ProcessInfo, *PProcessInfo;


VOID GetProcessName(DWORD dwProcID, CHAR szProcessName[], INT Len)
{
	if (dwProcID == 0)
	{
		strcpy(szProcessName, "System Idle Process");
	}
	else if (dwProcID == 4)
	{
		strcpy(szProcessName, "System");
	}
	else
	{
		strcpy(szProcessName, "Unknown/Hidden Process");

		// Get a handle to the process.
		HANDLE hProcess = OpenProcess( 
								PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
								FALSE, 
								dwProcID);

		if (hProcess != NULL)
		{
			HMODULE hMod;
			DWORD cbNeeded;

			if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
			{
				GetModuleBaseName(hProcess, hMod, szProcessName, Len);
			}

			CloseHandle(hProcess);
		}
	}
}

BOOL CheckForHiddenProcess(VOID)
{
	HMODULE hGDI = LoadLibraryA("GDI32.dll");

	Proc0 pGdiQueryTable = (Proc0) GetProcAddress(hGDI, "GdiQueryTable");

	if (pGdiQueryTable == NULL)
	{
		printf("Error finding address of GdiQueryTable!\r\n");
		return FALSE;
	}

	GDITableCell *pGDITable = (GDITableCell *) pGdiQueryTable();

	if (pGDITable == NULL)
	{
		printf("Error accessing GDI Table!\r\n");
		return FALSE;
	}

	// Get Windows version
	DWORD dwVersion = GetVersion();

	int WindowsVer = LOBYTE(LOWORD(dwVersion));

	vector<ProcessInfo> procInfo;

	// Get all the process IDs from the GDI Table
	for (int i=0; i<MAXGDIHANDLE; i++)
	{
		GDITableCell cell = pGDITable[i & 0xFFFF];

		// Ignore invalid kernel object
		if ( (unsigned) cell.pKernel < 0x80000000 )
			continue;

		BOOL fFound = FALSE;

		for (int j=0; j<procInfo.size(); j++)
		{
			// NT/2000 switch order for _nProcess, _nCount
			if (WindowsVer >= 5)
			{
				if (procInfo[j].ProcessId == cell._nProcess)
				{
					fFound = TRUE;
				}
			}
			else
			{
				if (procInfo[j].ProcessId == cell._nCount)
				{
					fFound = TRUE;
				}
			}
		}

		if (!fFound)
		{
			ProcessInfo pi;

			// NT/2000 switch order for _nProcess, _nCount
			if (WindowsVer >= 5)
			{
				pi.ProcessId = cell._nProcess;
			}
			else
			{
				pi.ProcessId = cell._nCount;
			}

			procInfo.push_back(pi);
		}
	}

	// Check whether we can find a name for the process ID, if not most probably
	// the process id belongs to a process that has been hidden by rootkits...
	for (int k=0; k<procInfo.size(); k++)
	{
		CHAR szProcName[MAX_PATH];
		GetProcessName(procInfo[k].ProcessId, szProcName, MAX_PATH-1);

		printf("Process[%d]: %s\r\n", procInfo[k].ProcessId, szProcName);
	}

	return TRUE;
}

BOOL GetDebugPrivilege(VOID)
{
	HANDLE hToken = NULL;
	TOKEN_PRIVILEGES *privs = NULL;
	LUID luid;
	BYTE *buffer = NULL;
	DWORD size = 0;
	int i = 0;

	// Get our access token
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
	{
		printf("Couldn't get access to process access token\r\n");
		return FALSE;
	}

	// Get the needed size for the TOKEN_PRIVILEGES structure
	GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &size);

	buffer = new BYTE[size];
	privs = (TOKEN_PRIVILEGES *)buffer;

	if (!GetTokenInformation(hToken, TokenPrivileges, privs, size, &size))
	{
		printf("Couldn't get access token information\r\n");
		return FALSE;
	}
	
	// Get LUID of SeDebugName privilege
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
	{
		printf("Error getting LUID of SeDebugPrivilege privilege\r\n");
		return FALSE;
	}

	// Find this privilege in the array and mark it as enabled
	while (i < privs->PrivilegeCount && !(privs->Privileges[i].Luid.HighPart == luid.HighPart && privs->Privileges[i].Luid.LowPart == luid.LowPart)) 
		i++;

	if (i == privs->PrivilegeCount)
	{
		printf("Couldn't find SeDebugPrivilege privilege in token\r\n");
		return FALSE;
	}

	// Now let's adjust token privileges
	privs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, FALSE, privs, size, NULL, NULL);

	return TRUE;
}

int main(int argc, char *argv[])
{
	GetDebugPrivilege();

	CheckForHiddenProcess();

	return 0;
}
Of course it'll work only with processes with UI .
 #808  by EP_X0FF
 Wed Apr 21, 2010 3:10 am
Hi,

thanks for interesting find.

GdiQueryTable returns pointer to structure defined as
Code: Select all
typedef struct _ENTRY
{
    EINFO       einfo; //pointer to object or next free handle
    OBJECTOWNER ObjectOwner;
    USHORT      FullUnique;
    OBJTYPE     Objt; //UCHAR
    UCHAR       Flags;
    PVOID       pUser; //pointer to user mode data
} ENTRY, *PENTRY;
where ObjectOwner is a object used for shared and exclusive object ownership.
Code: Select all
typedef struct _OBJECTOWNER_S
{
     USHORT   Count:15;
     USHORT   Lock:1;
     W32PID   Pid;
}OBJECTOWNER_S,*POBJECTOWNER_S;

typedef union _OBJECTOWNER
{
    OBJECTOWNER_S   Share;
    ULONG           ulObj;
}OBJECTOWNER,*POBJECTOWNER;
W32PID is USHORT type :)
However this detection method is kinda only for fun :)