分类
游戏安全

开源项目分析:HLeaker64下r3绕过callbacks句柄权限过滤(已经失效)

项目地址:https://github.com/Schnocker/HLeaker 感谢Schnocker的分享
在所有进程句柄表中枚举出拥有dwDesiredAccess权限的句柄进程(经过更新后会有某个邪恶的东西取消所有进程中被保护进程的敏感句柄权限)

 std::vector<HANDLE_INFO> 
ServiceEnumHandles(ULONG ProcessId, DWORD dwDesiredAccess) 
{ 
typedef struct 
_SYSTEM_HANDLE { ULONG ProcessId; BYTE ObjectTypeNumber; BYTE Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE, *PSYSTEM_HANDLE; typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG HandleCount; SYSTEM_HANDLE Handles[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; PSYSTEM_HANDLE_INFORMATION handleInfo = 0; NTSTATUS status = -1; PVOID buffer = 0; ULONG bufferSize = 0, pId = 0; std::vector<HANDLE_INFO> handlelist; HANDLE ProcessHandle = 0, ProcessCopy = 0; HANDLE_INFO hi = { 0,0 }; Process::CProcess* Process = 0; if (!NtQuerySystemInformation)
 goto EXIT; do
 { status = NtQuerySystemInformation(0x10, buffer, bufferSize, &bufferSize); 
if (status)
 { 
if (status == 0xc0000004) 
{ 
if (buffer != NULL) 
VirtualFree(buffer, bufferSize, MEM_DECOMMIT); 
buffer = VirtualAlloc(0, bufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); continue; 
} 
break; 
}
 else { 
handleInfo = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(buffer); 
for (int i = 0; i < handleInfo->HandleCount; i++) 
{ auto handle = &handleInfo->Handles[i]; 
if (handle->ObjectTypeNumber == 7 && (handle->GrantedAccess & dwDesiredAccess) == dwDesiredAccess) 
{//句柄类型是type=0x7 
且句柄权限中拥有dwDesiredAccess权限 
Process = new Process::CProcess(handle->ProcessId, PROCESS_ALL_ACCESS); 
if (Process->IsValidProcess() && ServiceGetProcessId(Process, reinterpret_cast<HANDLE>(handle->Handle), &pId)) 
{ 
if (pId == ProcessId) {
 handlelist.push_back(HANDLE_INFO(handle->ProcessId, reinterpret_cast<HANDLE>(handle->Handle)));
 printf("(handle->PID handle->Handle :%x :%xn", handle->ProcessId, (handle->Handle)); } } 
if (Process->IsValidProcess()) 
Process->Close(); delete Process; #endif } 
} 
break; } 
} 
while (true); EXIT: 
if (buffer != NULL) VirtualFree(buffer, bufferSize, MEM_DECOMMIT); 
return handlelist; } }
 插入远程线程执行shellcode使句柄可继承 
BOOLEAN WINAPI ServiceSetHandleStatus(Process::CProcess* Process, HANDLE hObject, BOOL Protect, BOOL Inherit)
 { typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; 
struct HANDLE_IN 
{ 
HANDLE hObject; BOOL PStatus; BOOL IStatus; PVOID Function;
 };
 #ifdef _WIN64 //bypass最新版本的be应当动态加解密执行该shellcode
 static BYTE WThread[] = { 0x48, 0x83, 0xEC, 0x28, 0xF, 0xB6, 0x41, 0x8, 0x4C, 0x8D, 0x44, 0x24, 0x30, 0x41, 0xB9, 0x2, 0x0, 0x0, 0x0, 0x88, 0x44, 0x24, 0x31, 0xF, 0xB6, 0x41, 0xC, 0x4C, 0x8B, 0xD1, 0x48, 0x8B, 0x9, 0x88, 0x44, 0x24, 0x30, 0x41, 0x8D, 0x51, 0x2, 0x41, 0xFF, 0x52, 0x10, 0x33, 0xC9, 0x85, 0xC0, 0xF, 0x94, 0xC1, 0x8B, 0xC1, 0x48, 0x83, 0xC4, 0x28, 0xC3}; #elif _WIN32 static BYTE WThread[] = { 0x55, 0x8B, 0xEC, 0x8B, 0x4D, 0x8, 0x6A, 0x2, 0xF, 0xB6, 0x41, 0x4, 0x88, 0x45, 0x9, 0xF, 0xB6, 0x41, 0x8, 0x88, 0x45, 0x8, 0x8D, 0x45, 0x8, 0x50, 0x8B, 0x41, 0xC, 0x6A, 0x4, 0xFF, 0x31, 0xFF, 0xD0, 0xF7, 0xD8, 0x1B, 0xC0, 0x40, 0x5D, 0xC2, 0x4, 0x0 }; 
#endif BOOL IsTarget64 = false, Status = false; HANDLE_IN Args = { 0,0,0,0 }; 
LPVOID lpThread = nullptr, lpArg = nullptr; HANDLE hProcess = Process->GetHandle(), hThread = 0; 
int ThreadSize = _countof(WThread); if (!RtlCreateUserThread || !_NtSetInformationObject || hProcess == INVALID_HANDLE_VALUE)
 goto EXIT; 
if (!Process->Is64(&IsTarget64)) goto EXIT; 
#ifdef _WIN64 
if (!IsTarget64) goto EXIT; #elif _WIN32 if (IsTarget64) 
goto EXIT; #endif lpThread = VirtualAllocEx(hProcess, 0, ThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
if (lpThread == nullptr) goto EXIT; lpArg = VirtualAllocEx(hProcess, 0, sizeof(HANDLE_IN), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
if (lpArg == nullptr) 
goto EXIT; 
Args.Function = _NtSetInformationObject; Args.hObject = hObject; 
Args.IStatus = Inherit; 
Args.PStatus = Protect; 
if (!WriteProcessMemory(hProcess, lpThread, reinterpret_cast<LPCVOID>(WThread), ThreadSize, 0) || !WriteProcessMemory(hProcess, lpArg, reinterpret_cast<LPCVOID>(&Args), sizeof(HANDLE_IN), 0)) goto EXIT;
 if (RtlCreateUserThread(hProcess, 0, 0, 0, 0, 0, reinterpret_cast<PVOID>(lpThread), lpArg, &hThread, 0))
 goto EXIT; 
WaitForSingleObject(hThread, INFINITE); Status = true; EXIT: 
if (hThread) 
CloseHandle(hThread); 
if (lpThread) VirtualFreeEx(hProcess, lpThread, ThreadSize, MEM_RELEASE); 
if (lpArg) 
VirtualFreeEx(hProcess, lpArg, sizeof(HANDLE_IN), MEM_RELEASE); return Status; } 
运行自己的程序并成为拥有对目标进程完全访问权限进程的子进程且继承目标句柄 
HANDLE WINAPI ServiceRunProgram(LPCSTR lpFilename, LPCSTR lpArguments, LPCSTR lpDir, LPPROCESS_INFORMATION ProcessInformation, BOOL Inherit, HANDLE hParent) { HANDLE processToken = NULL, userToken = NULL; LPVOID pEnvironment = NULL; STARTUPINFOEXA si = { 0 }; SIZE_T cbAttributeListSize = 0; PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = NULL; BOOL Status = TRUE; ZeroMemory(&si, sizeof(si)); si.StartupInfo.cb = sizeof(STARTUPINFOEXA); //DWORD dwSessionId=WTSGetActiveConsoleSessionId(); 
if (!ProcessInformation) 
{ 
Status = false; goto EXIT; 
} if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &processToken)) 
{ 
Status = false; goto EXIT; 
} 
if (!DuplicateTokenEx(processToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &userToken) || !CreateEnvironmentBlock(&pEnvironment, userToken, TRUE)) { Status = false; goto EXIT; } //SetTokenInformation(userToken,TokenSessionId,(void*)&dwSessionId,sizeof(DWORD)); InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize); pAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize)); 
if (!pAttributeList)
 { 
Status = false; 
goto EXIT; 
} if (!InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize)) {
 Status = false; goto EXIT; 
} 
if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParent, sizeof(HANDLE), NULL, NULL))
 { 
Status = false; goto EXIT; 
} 
si.lpAttributeList = pAttributeList;
 if (!CreateProcessAsUserA(userToken, lpFilename, const_cast<LPSTR>(lpArguments), NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE | EXTENDED_STARTUPINFO_PRESENT, pEnvironment, lpDir, reinterpret_cast<LPSTARTUPINFOA>(&si), ProcessInformation)) 
{ 
printf("这里出错了!n"); 
Status = false; 
goto EXIT; 
}
 EXIT: 
if (pEnvironment) 
DestroyEnvironmentBlock(pEnvironment);
 CloseHandle(userToken); 
if (ProcessInformation->hThread) CloseHandle(ProcessInformation->hThread);
 if (processToken) 
CloseHandle(processToken); 
if (pAttributeList) { 
DeleteProcThreadAttributeList(pAttributeList); 
HeapFree(GetProcessHeap(), 0, pAttributeList); 
} 
return Status ? ProcessInformation->hProcess : 0;
 } 
int main(int argc, char** argv) 
{ 
HMODULE hMods[1024]; 
char CLine[1024], ModuleName[MAX_PATH]; 
DWORD dwcbNeeded = 0, dwCounter = 0, dwMaxCount = 1; 
PROCESS_INFORMATION pi = { 0,0,0,0 }; 
Process::CProcess *CurrentProcess = nullptr, *TargetProcess = nullptr, *AttachedProcess = nullptr; 
std::vector<Service::HANDLE_INFO> Handles; 
ZeroMemory(CLine, _countof(CLine)); 
ZeroMemory(hMods, _countof(hMods)); 
ZeroMemory(ModuleName, MAX_PATH); 
switch (argc) 
{ 
case 1: CurrentProcess = new Process::CProcess(); 
CurrentProcess->SetPrivilege(SE_DEBUG_NAME, true); 
CurrentProcess->SetPrivilege(SE_TCB_NAME, true);
 TargetProcess = new Process::CProcess(std::string(TARGET_PROCESS));
//设置目标进程名 
TargetProcess->Wait(DELAY_TO_WAIT); 
TargetProcess->Open(); 
if (TargetProcess->IsValidProcess())
 { 
Handles = Service::ServiceEnumHandles(TargetProcess->GetPid(), DESIRED_ACCESS); 
if (!GetFullPathNameA(YOUR_PROCESS, MAX_PATH, ModuleName, 0)) 
{ 
std::cout << "GetFullPathNameA failed with errorcode " << GetLastError() << std::endl; //getchar();
 goto EXIT; } 
for (auto Handle : Handles)
 { 
if (dwCounter == dwMaxCount)
 break; 
AttachedProcess = new Process::CProcess(Handle.dwPid, PROCESS_ALL_ACCESS); 
if (!Service::ServiceSetHandleStatus(AttachedProcess, Handle.hProcess, TRUE, TRUE))
 { 
std::cout << "ServiceSetHandleStatus failed with errorcode " << GetLastError() << std::endl; 
if (AttachedProcess) {
 AttachedProcess->Close();
 delete AttachedProcess; 
} continue; } 
sprintf_s(CLine, "%s %d", ModuleName, Handle.hProcess); 
if (!Service::ServiceRunProgram(NULL, CLine, 0, &pi, true, AttachedProcess->GetHandle()))
 { 
std::cout << "ServiceRunProgram failed with errorcode " << GetLastError() << std::endl;
 } 
if (!Service::ServiceSetHandleStatus(AttachedProcess, Handle.hProcess, FALSE, FALSE)) { std::cout << "ServiceSetHandleStatus failed with errorcode " << GetLastError() << std::endl;
 }
 printf(CLine); // getchar(); AttachedProcess->Close(); delete AttachedProcess; dwCounter++; }
 } 
EXIT: CurrentProcess->SetPrivilege(SE_TCB_NAME, false); 
CurrentProcess->SetPrivilege(SE_DEBUG_NAME, false); TargetProcess->Close(); if(CurrentProcess) delete CurrentProcess;
 if(TargetProcess) 
delete TargetProcess; break; 
case 2: TargetProcess = new Process::CProcess(reinterpret_cast<void*>(atoi(argv[1]))); std::cout << "Process Handle : " << TargetProcess->GetHandle() << std::endl; 
if (EnumProcessModulesEx(TargetProcess->GetHandle(), hMods, sizeof(hMods), &dwcbNeeded, LIST_MODULES_ALL)) 
{ 
for (int i = 0;i < dwcbNeeded / sizeof(HMODULE);i++) 
{ 
if (GetModuleFileNameExA(TargetProcess->GetHandle(), hMods[i], ModuleName, MAX_PATH))
 { std::cout << hMods[i] << " : " << ModuleName << std::endl; }
 } 
} 
getchar();
 TargetProcess->Close(); 
delete TargetProcess; std::cin.get(); break; default: break; 
} 
return true; 
}
0 0 vote
文章评分

由FAKE

Через тернии к звездам,
через радость и слезы
Мы проложим дорогу

Subscribe
提醒
guest
你的昵称 用于分别你是谁
你的电子邮箱 用于被回复时通知
3 评论
Inline Feedbacks
View all comments
小小强
小小强
游客
2017年11月18日 下午8:33

哇 。。。 这个博客配色根本看不清代码呀。,。

jingjinghack
游客
2017年11月21日 下午6:27

现在已经被BE检测到了

昊池
昊池
游客
2018年1月16日 下午2:29

你这个配色,眼已经瞎了 🙁