|
| 1 | +#include <windows.h> |
| 2 | +#include <tlhelp32.h> |
| 3 | +#include <psapi.h> |
| 4 | +#include "beacon.h" |
| 5 | + |
| 6 | +#define MAX_EDR_STRINGS 200 |
| 7 | +#define MAX_EDR_STRING_LENGTH 50 |
| 8 | +#define MAX_PATH_LENGTH MAX_PATH |
| 9 | + |
| 10 | +//KERNEL32 |
| 11 | +WINBASEAPI HANDLE WINAPI KERNEL32$CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID); |
| 12 | +WINBASEAPI WINBOOL WINAPI KERNEL32$Process32First(HANDLE hSnapshot,LPPROCESSENTRY32 lppe); |
| 13 | +WINBASEAPI WINBOOL WINAPI KERNEL32$Process32Next(HANDLE hSnapshot,LPPROCESSENTRY32 lppe); |
| 14 | +WINBASEAPI WINBOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); |
| 15 | +WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD dwDesiredAccess, WINBOOL bInheritHandle, DWORD dwProcessId); |
| 16 | +WINBASEAPI DWORD WINAPI KERNEL32$QueryFullProcessImageNameA(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize); |
| 17 | +WINBASEAPI HANDLE WINAPI KERNEL32$FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData); |
| 18 | +WINBASEAPI BOOL WINAPI KERNEL32$FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData); |
| 19 | +WINBASEAPI BOOL WINAPI KERNEL32$FindClose(HANDLE hFindFile); |
| 20 | +//ADVAPI |
| 21 | +WINBASEAPI SC_HANDLE WINAPI ADVAPI32$OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess); |
| 22 | +WINBASEAPI SC_HANDLE WINAPI ADVAPI32$OpenServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAccess); |
| 23 | +WINBASEAPI BOOL WINAPI ADVAPI32$QueryServiceConfigA(SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA lpServiceConfig, DWORD cbBufSize, LPDWORD pcbBytesNeeded); |
| 24 | +WINBASEAPI BOOL WINAPI ADVAPI32$CloseServiceHandle(SC_HANDLE hSCObject); |
| 25 | +WINBASEAPI BOOL WINAPI ADVAPI32$EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName); |
| 26 | +//PSAPI |
| 27 | +WINBASEAPI DWORD WINAPI PSAPI$GetModuleFileNameExA(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize); |
| 28 | +//MSVCRT |
| 29 | +WINBASEAPI void *__cdecl MSVCRT$memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _MaxCount); |
| 30 | +WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count); |
| 31 | +WINBASEAPI int __cdecl MSVCRT$strcmp(const char *_Str1,const char *_Str2); |
| 32 | +WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *_Str); |
| 33 | +WINBASEAPI int __cdecl MSVCRT$_stricmp(const char *string1,const char *string2); |
| 34 | +WINBASEAPI char * __cdecl MSVCRT$strstr(const char *haystack, const char *needle); |
| 35 | +WINBASEAPI char * __cdecl MSVCRT$strcpy(char * __restrict__ _Dest, const char * __restrict__ _Source); |
| 36 | +WINBASEAPI int __cdecl MSVCRT$sprintf(char *__stream, const char *__format, ...); |
| 37 | +WINBASEAPI void* WINAPI MSVCRT$malloc(SIZE_T); |
| 38 | +DECLSPEC_IMPORT void WINAPI MSVCRT$free(void*); |
| 39 | + |
| 40 | +char edrList[MAX_EDR_STRINGS][MAX_EDR_STRING_LENGTH] = { |
| 41 | + "activeconsole", "ADA-PreCheck", "ahnlab", "amsi.dll", "anti malware", "anti-malware", |
| 42 | + "antimalware", "anti virus", "anti-virus", "antivirus", "appsense", "attivo networks", |
| 43 | + "attivonetworks", "authtap", "avast", "avecto", "bitdefender", "blackberry", "canary", |
| 44 | + "carbonblack", "carbon black", "cb.exe", "check point", "ciscoamp", "cisco amp", |
| 45 | + "countercept", "countertack", "cramtray", "crssvc", "crowdstrike", "csagent", "csfalcon", |
| 46 | + "csshell", "cybereason", "cyclorama", "cylance", "cynet", "cyoptics", "cyupdate", "cyvera", |
| 47 | + "cyserver", "cytray", "darktrace", "deep instinct", "defendpoint", "defender", "eectrl", |
| 48 | + "elastic", "endgame", "f-secure", "forcepoint", "fortinet", "fireeye", "groundling", |
| 49 | + "GRRservic", "harfanglab", "inspector", "ivanti", "juniper networks", "kaspersky", "lacuna", |
| 50 | + "logrhythm", "malware", "malwarebytes", "mandiant", "mcafee", "morphisec", "msascuil", |
| 51 | + "msmpeng", "mssense", "nissrv", "omni", "omniagent", "osquery", "Palo Alto Networks", "pgeposervice", |
| 52 | + "pgsystemtray", "privilegeguard", "procwall", "protectorservic", "qianxin", "qradar", |
| 53 | + "qualys", "rapid7", "redcloak", "red canary", "SanerNow", "sangfor", "secureworks", |
| 54 | + "securityhealthservice", "semlaunchsv", "sentinel", "sentinelone", "sepliveupdat", |
| 55 | + "sisidsservice", "sisipsservice", "sisipsutil", "smc.exe", "smcgui", "snac64", "somma", |
| 56 | + "sophos", "splunk", "srtsp", "symantec", "symcorpu", "symefasi", "sysinternal", "sysmon", |
| 57 | + "tanium", "tda.exe", "tdawork", "tehtris", "threat", "trellix", "tpython", "trend micro", |
| 58 | + "uptycs", "vectra", "watchguard", "wincollect", "windowssensor", "wireshark", "withsecure", |
| 59 | + "xagt.exe", "xagtnotif.exe" |
| 60 | +}; |
| 61 | + |
| 62 | +char bof_tolower(char c) { |
| 63 | + if (c >= 'A' && c <= 'Z') { |
| 64 | + return c + 32; |
| 65 | + } |
| 66 | + return c; |
| 67 | +} |
| 68 | + |
| 69 | +void toLower(char* str) { |
| 70 | + for (int i = 0; str[i]; i++) { |
| 71 | + str[i] = bof_tolower(str[i]); |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +void safe_strncpy(char* dest, const char* src, size_t n) { |
| 76 | + size_t src_len = MSVCRT$strlen(src); |
| 77 | + size_t copy_len = (src_len < n) ? src_len : n - 1; |
| 78 | + MSVCRT$memcpy(dest, src, copy_len); |
| 79 | + dest[copy_len] = '\0'; |
| 80 | +} |
| 81 | + |
| 82 | +int isEDRString(const char* str) { |
| 83 | + char lowerStr[MAX_PATH]; |
| 84 | + safe_strncpy(lowerStr, str, MAX_PATH); |
| 85 | + toLower(lowerStr); |
| 86 | + |
| 87 | + for (int i = 0; i < MAX_EDR_STRINGS && edrList[i][0] != '\0'; i++) { |
| 88 | + char lowerEDR[MAX_EDR_STRING_LENGTH]; |
| 89 | + safe_strncpy(lowerEDR, edrList[i], MAX_EDR_STRING_LENGTH); |
| 90 | + toLower(lowerEDR); |
| 91 | + |
| 92 | + if (MSVCRT$strstr(lowerStr, lowerEDR) != NULL) { |
| 93 | + return 1; |
| 94 | + } |
| 95 | + } |
| 96 | + return 0; |
| 97 | +} |
| 98 | + |
| 99 | +void checkProcesses(formatp *obj) { |
| 100 | + BeaconFormatPrintf(obj, "\n===== Processes =====\n"); |
| 101 | + |
| 102 | + HANDLE hSnapshot = KERNEL32$CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); |
| 103 | + if (hSnapshot == INVALID_HANDLE_VALUE) { |
| 104 | + BeaconFormatPrintf(obj, "[-] Failed to create process snapshot\n"); |
| 105 | + return; |
| 106 | + } |
| 107 | + |
| 108 | + PROCESSENTRY32 pe32; |
| 109 | + pe32.dwSize = sizeof(PROCESSENTRY32); |
| 110 | + |
| 111 | + if (!KERNEL32$Process32First(hSnapshot, &pe32)) { |
| 112 | + BeaconFormatPrintf(obj, "[-] Failed to get first process\n"); |
| 113 | + KERNEL32$CloseHandle(hSnapshot); |
| 114 | + return; |
| 115 | + } |
| 116 | + |
| 117 | + int foundSuspicious = 0; |
| 118 | + do { |
| 119 | + char path[MAX_PATH_LENGTH] = {0}; |
| 120 | + |
| 121 | + HANDLE hProcess = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID); |
| 122 | + if (hProcess) { |
| 123 | + if (PSAPI$GetModuleFileNameExA(hProcess, NULL, path, MAX_PATH_LENGTH) == 0) { |
| 124 | + DWORD pathSize = MAX_PATH_LENGTH; |
| 125 | + if (!KERNEL32$QueryFullProcessImageNameA(hProcess, 0, path, &pathSize)) { |
| 126 | + MSVCRT$strcpy(path, "Path unavailable"); |
| 127 | + } |
| 128 | + } |
| 129 | + KERNEL32$CloseHandle(hProcess); |
| 130 | + } else { |
| 131 | + MSVCRT$strcpy(path, "Access denied"); |
| 132 | + } |
| 133 | + |
| 134 | + if (isEDRString(pe32.szExeFile) || isEDRString(path)) { |
| 135 | + BeaconFormatPrintf(obj, "[!] Suspicious process found:\n"); |
| 136 | + BeaconFormatPrintf(obj, "\tName: %s\n", pe32.szExeFile); |
| 137 | + BeaconFormatPrintf(obj, "\tPath: %s\n", path); |
| 138 | + BeaconFormatPrintf(obj, "\tPID: %lu\n\n", pe32.th32ProcessID); |
| 139 | + foundSuspicious = 1; |
| 140 | + } |
| 141 | + |
| 142 | + } while (KERNEL32$Process32Next(hSnapshot, &pe32)); |
| 143 | + |
| 144 | + KERNEL32$CloseHandle(hSnapshot); |
| 145 | + |
| 146 | + if (!foundSuspicious) { |
| 147 | + BeaconFormatPrintf(obj, "[+] No suspicious processes found\n\n"); |
| 148 | + } |
| 149 | +} |
| 150 | + |
| 151 | +void checkDirectories(formatp *obj) { |
| 152 | + BeaconFormatPrintf(obj, "\n===== Directories =====\n"); |
| 153 | + const char* directories[] = { |
| 154 | + "C:\\Program Files", |
| 155 | + "C:\\Program Files (x86)", |
| 156 | + "C:\\ProgramData" |
| 157 | + }; |
| 158 | + int foundSuspicious = 0; |
| 159 | + for (int i = 0; i < 3; i++) { |
| 160 | + WIN32_FIND_DATAA findFileData; |
| 161 | + char searchPath[MAX_PATH]; |
| 162 | + MSVCRT$sprintf(searchPath, "%s\\*", directories[i]); |
| 163 | + HANDLE hFind = KERNEL32$FindFirstFileA(searchPath, &findFileData); |
| 164 | + if (hFind != INVALID_HANDLE_VALUE) { |
| 165 | + do { |
| 166 | + if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
| 167 | + if (MSVCRT$strcmp(findFileData.cFileName, ".") != 0 && MSVCRT$strcmp(findFileData.cFileName, "..") != 0) { |
| 168 | + if (isEDRString(findFileData.cFileName)) { |
| 169 | + BeaconFormatPrintf(obj, "[!] Suspicious directory found: %s\\%s\n", directories[i], findFileData.cFileName); |
| 170 | + foundSuspicious = 1; |
| 171 | + } |
| 172 | + } |
| 173 | + } |
| 174 | + } while (KERNEL32$FindNextFileA(hFind, &findFileData) != 0); |
| 175 | + KERNEL32$FindClose(hFind); |
| 176 | + } |
| 177 | + } |
| 178 | + if (!foundSuspicious) { |
| 179 | + BeaconFormatPrintf(obj, "[+] No suspicious directories found\n\n"); |
| 180 | + } |
| 181 | +} |
| 182 | + |
| 183 | +void checkServices(formatp *obj) { |
| 184 | + BeaconFormatPrintf(obj, "\n===== Services =====\n"); |
| 185 | + SC_HANDLE hSCManager = ADVAPI32$OpenSCManagerA(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); |
| 186 | + if (hSCManager == NULL) { |
| 187 | + BeaconFormatPrintf(obj, "[-] Failed to open Service Control Manager\n"); |
| 188 | + return; |
| 189 | + } |
| 190 | + DWORD bytesNeeded = 0; |
| 191 | + DWORD servicesReturned = 0; |
| 192 | + DWORD resumeHandle = 0; |
| 193 | + ADVAPI32$EnumServicesStatusExA(hSCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &bytesNeeded, &servicesReturned, &resumeHandle, NULL); |
| 194 | + ENUM_SERVICE_STATUS_PROCESSA* services = (ENUM_SERVICE_STATUS_PROCESSA*)MSVCRT$malloc(bytesNeeded); |
| 195 | + if (services == NULL) { |
| 196 | + BeaconFormatPrintf(obj, "[-] Failed to allocate memory for services\n"); |
| 197 | + ADVAPI32$CloseServiceHandle(hSCManager); |
| 198 | + return; |
| 199 | + } |
| 200 | + if (!ADVAPI32$EnumServicesStatusExA(hSCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)services, bytesNeeded, &bytesNeeded, &servicesReturned, &resumeHandle, NULL)) { |
| 201 | + BeaconFormatPrintf(obj, "[-] Failed to enumerate services\n"); |
| 202 | + MSVCRT$free(services); |
| 203 | + ADVAPI32$CloseServiceHandle(hSCManager); |
| 204 | + return; |
| 205 | + } |
| 206 | + int foundSuspicious = 0; |
| 207 | + for (DWORD i = 0; i < servicesReturned; i++) { |
| 208 | + SC_HANDLE hService = ADVAPI32$OpenServiceA(hSCManager, services[i].lpServiceName, SERVICE_QUERY_CONFIG); |
| 209 | + if (hService) { |
| 210 | + DWORD bytesNeeded = 0; |
| 211 | + ADVAPI32$QueryServiceConfigA(hService, NULL, 0, &bytesNeeded); |
| 212 | + QUERY_SERVICE_CONFIGA* pServiceConfig = (QUERY_SERVICE_CONFIGA*)MSVCRT$malloc(bytesNeeded); |
| 213 | + if (pServiceConfig != NULL) { |
| 214 | + if (ADVAPI32$QueryServiceConfigA(hService, pServiceConfig, bytesNeeded, &bytesNeeded)) { |
| 215 | + char serviceInfo[MAX_PATH * 3]; |
| 216 | + MSVCRT$sprintf(serviceInfo, "%s - %s - %s", |
| 217 | + services[i].lpServiceName, |
| 218 | + services[i].lpDisplayName, |
| 219 | + pServiceConfig->lpBinaryPathName); |
| 220 | + if (isEDRString(serviceInfo)) { |
| 221 | + BeaconFormatPrintf(obj, "[!] Suspicious service found:\n"); |
| 222 | + BeaconFormatPrintf(obj, "\tName: %s\n", services[i].lpServiceName); |
| 223 | + BeaconFormatPrintf(obj, "\tDisplay Name: %s\n", services[i].lpDisplayName); |
| 224 | + BeaconFormatPrintf(obj, "\tBinary Path: %s\n\n", pServiceConfig->lpBinaryPathName); |
| 225 | + foundSuspicious = 1; |
| 226 | + } |
| 227 | + } |
| 228 | + MSVCRT$free(pServiceConfig); |
| 229 | + } |
| 230 | + ADVAPI32$CloseServiceHandle(hService); |
| 231 | + } |
| 232 | + } |
| 233 | + MSVCRT$free(services); |
| 234 | + ADVAPI32$CloseServiceHandle(hSCManager); |
| 235 | + if (!foundSuspicious) { |
| 236 | + BeaconFormatPrintf(obj, "[+] No suspicious services found\n\n"); |
| 237 | + } |
| 238 | +} |
| 239 | + |
| 240 | +void go(char* args, int len) { |
| 241 | + formatp obj; |
| 242 | + BeaconFormatAlloc(&obj, 8192); |
| 243 | + |
| 244 | + checkProcesses(&obj); |
| 245 | + checkDirectories(&obj); |
| 246 | + checkServices(&obj); |
| 247 | + |
| 248 | + int size = 0; |
| 249 | + char* output = BeaconFormatToString(&obj, &size); |
| 250 | + BeaconOutput(CALLBACK_OUTPUT, output, size); |
| 251 | + BeaconFormatFree(&obj); |
| 252 | +} |
0 commit comments