Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define DEBUG_EXCCLIENT 1
- #define BUFFLEN 1024
- #define ADAPTER_NAME "ExCClientTUNAdapter"
- #define ADAPTER_NAMEW L"ExCClientTUNAdapter"
- #ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
- #endif
- #include <windows.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include <iphlpapi.h>
- #include <iostream>
- #include <map>
- #include <string>
- #include <thread>
- #include <vector>
- #include <Objbase.h>
- #include "wintun.h"
- #include "md5.h"
- static WINTUN_CREATE_ADAPTER_FUNC* WintunCreateAdapter;
- static WINTUN_CLOSE_ADAPTER_FUNC* WintunCloseAdapter;
- static WINTUN_OPEN_ADAPTER_FUNC* WintunOpenAdapter;
- static WINTUN_GET_ADAPTER_LUID_FUNC* WintunGetAdapterLUID;
- static WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC* WintunGetRunningDriverVersion;
- static WINTUN_DELETE_DRIVER_FUNC* WintunDeleteDriver;
- static WINTUN_SET_LOGGER_FUNC* WintunSetLogger;
- static WINTUN_START_SESSION_FUNC* WintunStartSession;
- static WINTUN_END_SESSION_FUNC* WintunEndSession;
- static WINTUN_GET_READ_WAIT_EVENT_FUNC* WintunGetReadWaitEvent;
- static WINTUN_RECEIVE_PACKET_FUNC* WintunReceivePacket;
- static WINTUN_RELEASE_RECEIVE_PACKET_FUNC* WintunReleaseReceivePacket;
- static WINTUN_ALLOCATE_SEND_PACKET_FUNC* WintunAllocateSendPacket;
- static WINTUN_SEND_PACKET_FUNC* WintunSendPacket;
- #pragma comment(lib, "Ws2_32.lib")
- #pragma comment(lib, "iphlpapi.lib")
- #pragma warning(disable : 4996)
- using std::cout, std::map, std::string, std::to_string, std::vector;
- string seckey;
- inline bool cstrcmp(char* s1, char* s2, size_t len) {
- for (size_t i = 0; i < len; i++) if (s1[i] != s2[i]) return false;
- return true;
- }
- template<typename S>
- inline void addstr(S dest, S src, size_t len, size_t offset = 0) {
- if (!dest || !src || len == 0) return;
- for (size_t i = 0; i < len; i++) {
- dest[i + offset] = src[i];
- }
- }
- template<typename I>
- I strtoint(char* data, size_t len, bool u = false) {
- using uI = typename std::make_unsigned<I>::type;
- uI output = 0;
- bool fbit = data[len - 1] == 1;
- for (size_t i = 0; i < len - (u ? 0 : 1); i++) {
- output |= ((uI)(BYTE)(data[i])) << (i * 8);
- }
- if (!u && fbit) return 0 - ((I)output);
- return (I)output;
- }
- template<typename I>
- char* inttostr(I data, size_t len, bool u = false) {
- using uI = typename std::make_unsigned<I>::type;
- uI d = (data < 0) ? 0 - ((uI)data) : data;
- bool fbit = data < 0;
- BYTE* str = new BYTE[len];
- for (size_t c = 0; c < len - (u ? 0 : 1); c++) {
- str[c] = (BYTE)(d % 256);
- d = (d - str[c]) / 256;
- }
- if (!u) str[len - 1] = fbit;
- return (char*)str;
- }
- int recv_all(SOCKET sock, char** buff, size_t len) {
- size_t c = len;
- char* buf = new char[BUFFLEN];
- *buff = new char[len];
- while (c > 0) {
- int res = recv(sock, buf, min(BUFFLEN, c), 0);
- if (res == SOCKET_ERROR) return WSAGetLastError();
- if (res == 0) return -1;
- addstr(*buff, buf, res, len - c);
- c -= res;
- }
- delete[] buf;
- return 0;
- }
- int recv_wrapper(SOCKET sock, char** buff, size_t* len) {
- char* buf;
- int res = recv_all(sock, &buf, 8);
- if (res != 0) return res;
- size_t c = strtoint<size_t>(buf, 8, true);
- res = recv_all(sock, &buf, c);
- if (res != 0) return res;
- *buff = buf;
- *len = c;
- return 0;
- }
- int send_wrapper(SOCKET sock, char* buff, size_t len) {
- char* packetlen = inttostr(len, 8, true);
- char* buf = new char[len + 8];
- addstr(buf, packetlen, 8);
- addstr(buf, buff, len, 8);
- size_t sent = 0;
- while (sent < len + 8) {
- int n = send(sock, buf + sent, len + 8 - sent, 0);
- if (n == SOCKET_ERROR) return WSAGetLastError();
- sent += n;
- }
- delete[] packetlen;
- delete[] buf;
- return 0;
- }
- HMODULE
- InitializeWintun(void)
- {
- HMODULE Wintun =
- LoadLibraryExW(L"wintun.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
- if (!Wintun)
- return NULL;
- #define X(Name) ((*(FARPROC *)&Name = GetProcAddress(Wintun, #Name)) == NULL)
- if (X(WintunCreateAdapter) || X(WintunCloseAdapter) || X(WintunOpenAdapter) || X(WintunGetAdapterLUID) ||
- X(WintunGetRunningDriverVersion) || X(WintunDeleteDriver) || X(WintunSetLogger) || X(WintunStartSession) ||
- X(WintunEndSession) || X(WintunGetReadWaitEvent) || X(WintunReceivePacket) || X(WintunReleaseReceivePacket) ||
- X(WintunAllocateSendPacket) || X(WintunSendPacket))
- #undef X
- {
- DWORD LastError = GetLastError();
- FreeLibrary(Wintun);
- SetLastError(LastError);
- return NULL;
- }
- return Wintun;
- }
- HMODULE Wintun;
- WINTUN_ADAPTER_HANDLE adapter;
- WINTUN_SESSION_HANDLE session;
- SOCKET sock;
- bool w = true, r = true, s = true;
- inline bool waitForThreads() {
- if (w) return false;
- while (!r && !s) Sleep(50);
- return true;
- }
- static BOOL WINAPI
- CtrlHandler(_In_ DWORD CtrlType)
- {
- switch (CtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- w = false;
- cout << "I: Stopping...\n";
- waitForThreads();
- return TRUE;
- }
- return FALSE;
- }
- size_t encrypt(BYTE* i, BYTE** o, size_t len) {
- *o = i;
- return len;
- }
- size_t decrypt(BYTE* i, BYTE** o, size_t len) {
- *o = i;
- return len;
- }
- void recv_thread() {
- while (w) {
- char* buff;
- size_t len;
- int res = recv_wrapper(sock, &buff, &len);
- if (res == -1) {
- cout << "F: Recv thread error: connection closed\n";
- break;
- }
- if (res > 0) {
- cout << "F: Recv thread error: " << res << "\n";
- break;
- }
- if (len > 0 && buff) {
- BYTE* p = WintunAllocateSendPacket(session, (DWORD)len);
- if (p) {
- BYTE* data = (BYTE*)buff;
- len = decrypt(data, &data, len);
- addstr(p, data, len);
- delete[] data;
- WintunSendPacket(session, p);
- cout << "I: Recv " << len << "bytes\n";
- }
- delete[] buff;
- }
- }
- w = false;
- r = false;
- }
- void send_thread() {
- HANDLE ev = WintunGetReadWaitEvent(session);
- while (w) {
- DWORD psize;
- BYTE* p = WintunReceivePacket(session, &psize);
- if (p) {
- BYTE* data1 = new BYTE[psize];
- addstr(data1, p, psize);
- psize = encrypt(data1, &data1, psize);
- int res = send_wrapper(sock, (char*)data1, psize);
- delete[] data1;
- WintunReleaseReceivePacket(session, p);
- if (res == -1) {
- cout << "F: Send thread error: connection closed\n";
- break;
- }
- if (res > 0) {
- cout << "F: Send thread error: " << res << "\n";
- break;
- }
- cout << "I: Send " << psize << "bytes\n";
- }
- else {
- WaitForSingleObject(ev, INFINITE);
- }
- }
- w = false;
- s = false;
- }
- inline void freep(USHORT stage = 5) {
- if (stage > 4) {
- WintunEndSession(session);
- }
- if (stage > 3) {
- closesocket(sock);
- }
- if (stage > 2) {
- WSACleanup();
- }
- if (stage > 1) {
- WintunCloseAdapter(adapter);
- }
- if (stage > 0) {
- FreeLibrary(Wintun);
- }
- SetConsoleCtrlHandler(CtrlHandler, FALSE);
- }
- int main(int argc, char* argv[])
- {
- int res;
- SetConsoleCtrlHandler(CtrlHandler, TRUE);
- map<string, string> args;
- for (int i = 1; i < argc; i++) {
- string x = argv[i];
- size_t pos = x.find_first_of("=");
- if (pos == string::npos) {
- args.insert(std::pair(x, ""));
- }
- args.insert(std::pair(x.substr(0, pos), x.substr(pos + 1, x.size() - pos - 1)));
- }
- #if DEBUG_EXCCLIENT == 1
- args.insert(std::pair("--ip", "127.0.0.1"));
- args.insert(std::pair("--port", "80"));
- args.insert(std::pair("--seckey", "OlwCTg9KQa5Fbu1PzeVYh0LWs6Gni2Ax"));
- #endif
- cout << "ExC Client\nArgs:\n";
- if (args.empty())
- cout << " - No args\n";
- else for (auto& p : args) {
- cout << " - \"" << p.first << "\"=\"" << p.second << "\"\n";
- }
- if (!args.contains("--ip")) {
- cout << "F: no ip\n";
- freep(0);
- return 1;
- }
- if (!args.contains("--port")) {
- cout << "F: no port\n";
- freep(0);
- return 1;
- }
- if (!args.contains("--seckey")) {
- cout << "F: no secure key\n";
- freep(0);
- return 1;
- }
- seckey = args["--seckey"];
- if ((Wintun = InitializeWintun()) == NULL) {
- cout << "F: wintun can't be loaded. Check wintun.dll or it is corrupted: " << GetLastError() << "\n";
- freep(0);
- return 1;
- }
- GUID AdapterGuid = { 0xDEADDEAD, 0x0012, 0x0030, { 0xA1, 0xB2, 0xC3, 0xD4, 0xF5, 0x6A, 0x7B, 0x8C } };
- adapter = WintunCreateAdapter(ADAPTER_NAMEW, L"TUN", &AdapterGuid);
- if (!adapter)
- {
- res = GetLastError();
- if (res != ERROR_ALREADY_EXISTS) {
- cout << "F: failed to create TUN adapter: " << res << "\n";
- freep(1);
- return 1;
- }
- adapter = WintunOpenAdapter(ADAPTER_NAMEW);
- if (!adapter) {
- cout << "F: failed to open TUN adapter: " << GetLastError() << "\n";
- freep(1);
- return 1;
- }
- }
- cout << "I: TUN adapter:\nName=" << ADAPTER_NAME << "\nType=TUN\nGUID={" << std::hex << AdapterGuid.Data1 << "-"
- << AdapterGuid.Data2 << "-" << AdapterGuid.Data3 << "-" << (short)AdapterGuid.Data4[0] << (short)AdapterGuid.Data4[1] << "-"
- << (short)AdapterGuid.Data4[2] << (short)AdapterGuid.Data4[3] << (short)AdapterGuid.Data4[4] << (short)AdapterGuid.Data4[5]
- << (short)AdapterGuid.Data4[6] << (short)AdapterGuid.Data4[7] << std::dec << "}\n";
- MIB_UNICASTIPADDRESS_ROW AddressRow;
- InitializeUnicastIpAddressEntry(&AddressRow);
- WintunGetAdapterLUID(adapter, &AddressRow.InterfaceLuid);
- AddressRow.Address.Ipv4.sin_family = AF_INET;
- AddressRow.Address.Ipv4.sin_addr.S_un.S_addr = htonl((192 << 24) | (168 << 16) | (0x12 << 8) | (0x30 << 0));
- AddressRow.OnLinkPrefixLength = 24;
- AddressRow.DadState = IpDadStatePreferred;
- res = CreateUnicastIpAddressEntry(&AddressRow);
- if (res != ERROR_SUCCESS && res != ERROR_OBJECT_ALREADY_EXISTS)
- {
- cout << "F: failed to set IP address: " << res << "\n";
- freep(2);
- return 1;
- }
- cout << "I: local IP address: 192.168.18.48\n";
- WSADATA wsad;
- res = WSAStartup(MAKEWORD(2, 2), &wsad);
- if (res != 0) {
- cout << "F: WSAStartup failed: " << res << "\n";
- freep(2);
- return 1;
- }
- addrinfo* result = NULL, hints;
- ZeroMemory(&hints, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- res = getaddrinfo(args["--ip"].c_str(), args["--port"].c_str(), &hints, &result);
- if (res != 0) {
- cout << "F: getaddrinfo failed: " << res << "\n";
- freep(3);
- return 1;
- }
- sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
- if (sock == INVALID_SOCKET) {
- cout << "F: error at socket(): " << WSAGetLastError() << "\n";
- freep(3);
- return 1;
- }
- if (connect(sock, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
- cout << "F: connect failed with error: " << WSAGetLastError() << "\n";
- freep(4);
- return 1;
- }
- cout << "I: connect to " << args["--ip"] << ":" << args["--port"] << "\n";
- freeaddrinfo(result);
- session = WintunStartSession(adapter, 0x400000);
- if (!session)
- {
- cout << "F: failed to start adapter session";
- freep(4);
- return 1;
- }
- string hash = MD5::hash(seckey);
- if ((res = send_wrapper(sock, hash.data(), hash.size())) != 0) {
- cout << "F: failed to start adapter session";
- freep();
- return 1;
- }
- char* skresp;
- size_t len;
- if ((res = recv_wrapper(sock, &skresp, &len)) == -1) {
- cout << "F: Connection closed: secure key\n";
- freep();
- return 1;
- }
- else if (res > 0) {
- cout << "F: Connection error: secure key recv " << res << "\n";
- freep();
- return 1;
- }
- if (skresp[0] == 1) {
- cout << "F: Connection error: secure key lenght\n";
- freep();
- return 1;
- }
- else if (skresp[0] == 2) {
- cout << "F: Connection error: secure key data\n";
- freep();
- return 1;
- }
- cout << "I: Secure key is ok\n";
- std::thread rth{ recv_thread },
- sth{ send_thread };
- rth.detach();
- sth.detach();
- while (!waitForThreads()) Sleep(50);
- cout << "I: Cleanup...\n";
- freep();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment