其實隻要導出這些NativeAPI,在應用态也是可以用的。
本文來自看雪的某人誰不記得了不好意思了!
C/C++ code
HANDLE LzOpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle, DWORD dwProcessId)
{
NTSTATUS status=0;
char *pBuf=NULL;
// BOOLEAN wasEnabled;
DWORD buflen=0x10000,needlen=0;
DWORD HandleCnt=0;
HANDLE hRetProcess=0,hOwnerProc,hTmp;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo=NULL;
PROCESS_BASIC_INFORMATION BasePsInfo;
OBJECT_ATTRIBUTES objatr;
CLIENT_ID Cid;
//提升調試權限,否則有些程序,比如服務程序打不開
InitializeObjectAttributes(&objatr,0,0,0,0);
//先嘗試正常方式打開
Cid.UniqueProcess=(HANDLE)dwProcessId;
Cid.UniqueThread=0;
status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//嘗試直接打開
if (NT_SUCCESS(status))
{
return hRetProcess;
}
//不成功,嘗試把PID加1再打開,加2,加3也可以
//理由:有些HOOK函數中過濾PID時不完善,正确的做法應該是先用掩碼忽略低兩位之後再比較
Cid.UniqueProcess=(HANDLE)(dwProcessId+1);
status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//嘗試直接打開pid+1
if (NT_SUCCESS(status))
{
return hRetProcess;
}
//都不成功,就找别的程序中的Handle,這才是本代碼的核心, 這些Handle大部分是在Csrss.exe中
do
{
//申請查詢句柄資訊所需的記憶體
ZwAllocateVirtualMemory(GetCurrentProcess(),(PVOID*)&pBuf,0,&buflen,MEM_COMMIT,PAGE_READWRITE);
//查詢系統句柄資訊,類型為16
status=ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuf,buflen,&needlen);
if (status==STATUS_SUCCESS)
{
break;
}
//不成功,則釋放記憶體
//這裡隻要一塊大記憶體夠放這些内容就行,或者直接申請一塊足夠大的也可以
//傳回的needlen可以做為參考
ZwFreeVirtualMemory(GetCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
//然後把要申請的記憶體大小乘2,直至成功為止
buflen*=2;
pBuf=NULL;
} while(1);
//傳回的緩沖區内容的第一個DWORD是總的句柄的個數
HandleCnt=*(DWORD*)pBuf;
//跳過句柄計數,才是真正的開始
pSysHandleInfo=(PSYSTEM_HANDLE_INFORMATION)((char*)pBuf+sizeof(DWORD));
for (DWORD i=0;i<HandleCnt;i++)
{
//隻驗證類型為PROCESS的,值為5
if (pSysHandleInfo->ObjectTypeNumber==OB_TYPE_PROCESS)
{
//打開這個句柄的所有者程序,要複制過來才能查詢,否則隻能看不能摸~
Cid.UniqueProcess=(HANDLE)(pSysHandleInfo->ProcessId);
Cid.UniqueThread=0;
status=ZwOpenProcess(&hOwnerProc,PROCESS_DUP_HANDLE,&objatr,&Cid);
if (NT_SUCCESS(status))
{
//打開成功,複制句柄到本程序,這裡用了PROCESS_ALL_ACCESS以避免權限問題
status=ZwDuplicateObject(hOwnerProc,
(void **)(pSysHandleInfo->Handle),
GetCurrentProcess(),
&hTmp,
PROCESS_ALL_ACCESS,
FALSE,
0);
if (NT_SUCCESS(status))
{
//複制成功,查詢此句柄所對應的程序PID,查詢基本資訊即可
status=ZwQueryInformationProcess(hTmp,ProcessBasicInformation,&BasePsInfo,sizeof(PROCESS_BASIC_INFORMATION),NULL);
if (NT_SUCCESS(status))
{
//成功,判斷其PID
if ((unsigned long)BasePsInfo.UniqueProcessId==dwProcessId)
{
//句柄所有者是我們要的目标程序,再按所需的權限複制過來
ZwDuplicateObject(hOwnerProc,
(void **)(pSysHandleInfo->Handle),
GetCurrentProcess(),
&hRetProcess,
dwDesiredAccess,
FALSE,
0);
//關掉為複制而打開的句柄所有者的句柄引用
ZwClose(hOwnerProc);
break;
}
}
}
}
}
pSysHandleInfo++;//指向下一個結構
}
if (pBuf)
{
ZwFreeVirtualMemory(GetCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
}
return hRetProcess;
}