Code style change and rebuild zstd with optimization options

This commit is contained in:
yuanyuanxiang
2025-11-29 23:22:55 +01:00
parent 8d4be0a580
commit ac7a2dcb7e
81 changed files with 14385 additions and 14324 deletions

View File

@@ -1,10 +1,11 @@
#pragma once
class App {
class App
{
public:
App(){}
virtual ~App(){}
App() {}
virtual ~App() {}
virtual bool Initialize() = 0;
virtual bool Start(bool block) = 0;

View File

@@ -183,7 +183,8 @@ BOOL CALLBACK callback(DWORD CtrlType)
}
void PrintUsage() {
void PrintUsage()
{
Mprintf("Ghost Remote Control\n");
Mprintf("Usage:\n");
Mprintf(" ghost.exe -install Install as Windows service\n");
@@ -194,11 +195,13 @@ void PrintUsage() {
Mprintf("\n");
}
extern "C" BOOL RunAsAgent(BOOL block) {
extern "C" BOOL RunAsAgent(BOOL block)
{
return g_MyApp.Run(block ? true : false) ? TRUE : FALSE;
}
bool RunService(int argc, const char* argv[]) {
bool RunService(int argc, const char* argv[])
{
g_ServiceDirectMode = FALSE;
if (argc == 1) { // 无参数时,作为服务启动
@@ -225,25 +228,20 @@ bool RunService(int argc, const char* argv[]) {
}
}
return true;
}
else if (argc > 1) {
} else if (argc > 1) {
if (_stricmp(argv[1], "-install") == 0) {
ServiceWrapper_Install();
return true;
}
else if (_stricmp(argv[1], "-uninstall") == 0) {
} else if (_stricmp(argv[1], "-uninstall") == 0) {
ServiceWrapper_Uninstall();
return true;
}
else if (_stricmp(argv[1], "-service") == 0) {
} else if (_stricmp(argv[1], "-service") == 0) {
ServiceWrapper_Run();
return true;
}
else if (_stricmp(argv[1], "-agent") == 0) {
} else if (_stricmp(argv[1], "-agent") == 0) {
RunAsAgent(true);
return true;
}
else if (_stricmp(argv[1], "-help") == 0 || _stricmp(argv[1], "/?") == 0) {
} else if (_stricmp(argv[1], "-help") == 0 || _stricmp(argv[1], "/?") == 0) {
PrintUsage();
return true;
}

View File

@@ -26,7 +26,8 @@ BOOL IsClientAppRunning(void* thisApp);
DWORD WINAPI StartClientApp(LPVOID param);
// <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><E0A3BA>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>.
class ClientApp : public App {
class ClientApp : public App
{
public:
State g_bExit; // Ӧ<>ó<EFBFBD><C3B3><EFBFBD>״̬<D7B4><CCAC>1-<2D><><EFBFBD>ض<EFBFBD><D8B6>˳<EFBFBD> 2-<2D><><EFBFBD>ض<EFBFBD><D8B6>˳<EFBFBD> 3-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BOOL g_bThreadExit; // <20><><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>״̬
@@ -102,20 +103,24 @@ public:
g_bExit = state;
m_Locker.Unlock();
}
virtual bool Initialize() override {
virtual bool Initialize() override
{
g_Connection->SetType(CLIENT_TYPE_ONE);
return true;
}
virtual bool Start(bool block) override {
virtual bool Start(bool block) override
{
if (block) StartClientApp(this);
else CloseHandle(__CreateThread(0, 0, StartClientApp, this, 0, 0));
return true;
}
virtual bool Stop() override {
virtual bool Stop() override
{
g_bExit = S_CLIENT_EXIT;
return true;
}
bool Run(bool block = true) {
bool Run(bool block = true)
{
if (!Initialize()) return false;
if (!Start(block)) return false;
if (block) Stop();

View File

@@ -95,9 +95,10 @@
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -111,9 +112,10 @@
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -131,6 +133,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -151,6 +154,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@@ -130,7 +130,8 @@ IOCPClient::IOCPClient(const State&bExit, bool exit_while_disconnect, int mask,
#endif
}
void IOCPClient::SetMultiThreadCompress(int threadNum) {
void IOCPClient::SetMultiThreadCompress(int threadNum)
{
#if USING_CTX
BOOL failed = TRUE;
if (threadNum > 1) {

View File

@@ -208,7 +208,7 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
break;
}
runner->FreeLibrary(module);
} else if (info.RunType == SHELLCODE){
} else if (info.RunType == SHELLCODE) {
bool flag = info.CallType == CALLTYPE_IOCPTHREAD;
ShellcodeInj inj(dll->buffer, info.Size, flag ? "run" : 0, flag ? &pThread : 0, flag ? sizeof(PluginParam) : 0);
if (info.Pid < 0) info.Pid = GetCurrentProcessId();

View File

@@ -110,7 +110,8 @@ BOOL SelectHDESK(HDESK new_desktop)
return TRUE;
}
HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess) {
HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess)
{
if (dwDesiredAccess == 0) {
dwDesiredAccess = DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS;
}
@@ -131,8 +132,7 @@ HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess) {
Mprintf("OpenDesktop Default failed: %d\n", GetLastError());
}
}
}
else {
} else {
Mprintf("OpenWindowStation failed: %d\n", GetLastError());
}
}
@@ -140,14 +140,14 @@ HDESK OpenActiveDesktop(ACCESS_MASK dwDesiredAccess) {
}
// 返回新桌面句柄如果没有变化返回NULL
HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights) {
HDESK IsDesktopChanged(HDESK currentDesk, DWORD accessRights)
{
HDESK hInputDesk = OpenActiveDesktop(accessRights);
if (!hInputDesk) return NULL;
if (!currentDesk) {
return hInputDesk;
}
else {
} else {
// 通过桌面名称判断是否真正变化
char oldName[256] = { 0 };
char newName[256] = { 0 };

View File

@@ -93,6 +93,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -109,6 +110,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -125,6 +127,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -141,6 +144,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@@ -211,11 +211,13 @@ public:
SAFE_DELETE(m_encoder);
}
virtual int GetScreenCount() const {
virtual int GetScreenCount() const
{
return m_nScreenCount;
}
virtual BOOL IsMultiScreenEnabled() const {
virtual BOOL IsMultiScreenEnabled() const
{
return m_bEnableMultiScreen;
}

View File

@@ -111,7 +111,8 @@ CScreenManager::CScreenManager(IOCPClient* ClientObject, int n, void* user):CMan
m_hWorkThread = __CreateThread(NULL,0, WorkThreadProc,this,0,NULL);
}
bool CScreenManager::SwitchScreen() {
bool CScreenManager::SwitchScreen()
{
if (m_ScreenSpyObject == NULL || m_ScreenSpyObject->GetScreenCount() <= 1 ||
!m_ScreenSpyObject->IsMultiScreenEnabled())
return false;
@@ -230,8 +231,7 @@ void CScreenManager::InitScreenSpy()
if (hDesk) {
SetThreadDesktop(g_hDesk = hDesk);
}
}
else {
} else {
HDESK hDesk = OpenActiveDesktop();
if (hDesk) {
SetThreadDesktop(g_hDesk = hDesk);

View File

@@ -56,7 +56,8 @@ public:
{
m_conn = conn;
}
bool IsRunAsService() const {
bool IsRunAsService() const
{
return m_conn ? m_conn->iStartup == Startup_GhostMsc : false;
}
bool SwitchScreen();

View File

@@ -25,7 +25,8 @@ static void WINAPI ServiceCtrlHandler(DWORD ctrlCode);
static void ServiceWriteLog(const char* message);
// 日志函数
static void ServiceWriteLog(const char* message) {
static void ServiceWriteLog(const char* message)
{
FILE* f;
SYSTEMTIME st;
@@ -83,8 +84,7 @@ BOOL ServiceWrapper_CheckStatus(BOOL* registered, BOOL* running,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&bytesNeeded))
{
&bytesNeeded)) {
*running = (ssp.dwCurrentState == SERVICE_RUNNING);
}
@@ -365,11 +365,9 @@ void ServiceWrapper_Install(void)
Mprintf("SUCCESS: Service is already installed\n");
CloseServiceHandle(schService);
}
}
else if (err == ERROR_ACCESS_DENIED) {
} else if (err == ERROR_ACCESS_DENIED) {
Mprintf("ERROR: Access denied. Please run as Administrator\n");
}
else {
} else {
Mprintf("ERROR: CreateService failed (%d)\n", (int)err);
}
CloseServiceHandle(schSCManager);
@@ -396,18 +394,15 @@ void ServiceWrapper_Install(void)
if (QueryServiceStatus(schService, &status)) {
if (status.dwCurrentState == SERVICE_RUNNING) {
Mprintf("SUCCESS: Service is running\n");
}
else {
} else {
Mprintf("WARNING: Service state: %d\n", (int)status.dwCurrentState);
}
}
}
else {
} else {
err = GetLastError();
if (err == ERROR_SERVICE_ALREADY_RUNNING) {
Mprintf("INFO: Service is already running\n");
}
else {
} else {
Mprintf("WARNING: StartService failed (%d)\n", (int)err);
Mprintf("You can start it manually using: net start %s\n", SERVICE_NAME);
}
@@ -476,8 +471,7 @@ void ServiceWrapper_Uninstall(void)
Mprintf(".");
Sleep(1000);
waitCount++;
}
else {
} else {
break;
}
}
@@ -485,17 +479,14 @@ void ServiceWrapper_Uninstall(void)
if (status.dwCurrentState == SERVICE_STOPPED) {
Mprintf("SUCCESS: Service stopped\n");
}
else {
} else {
Mprintf("WARNING: Service may not have stopped completely\n");
}
}
else {
} else {
err = GetLastError();
if (err == ERROR_SERVICE_NOT_ACTIVE) {
Mprintf("INFO: Service was not running\n");
}
else {
} else {
Mprintf("WARNING: Failed to stop service (%d)\n", (int)err);
}
}
@@ -503,8 +494,7 @@ void ServiceWrapper_Uninstall(void)
Mprintf("Deleting service...\n");
if (DeleteService(schService)) {
Mprintf("SUCCESS: Service uninstalled successfully\n");
}
else {
} else {
Mprintf("ERROR: DeleteService failed (%d)\n", (int)GetLastError());
}

View File

@@ -226,8 +226,7 @@ static void MonitorLoop(SessionMonitor* self)
SessionMonitor_WriteLog("Agent launched successfully");
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һЩʱ<D0A9><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Sleep(2000);
}
else {
} else {
SessionMonitor_WriteLog("Failed to launch agent");
}
}
@@ -242,8 +241,7 @@ static void MonitorLoop(SessionMonitor* self)
}
WTSFreeMemory(pSessionInfo);
}
else {
} else {
if (loopCount % 5 == 1) {
SessionMonitor_WriteLog("WTSEnumerateSessions failed");
}
@@ -279,8 +277,7 @@ static BOOL IsAgentRunningInSession(SessionMonitor* self, DWORD sessionId)
pFileName = strrchr(currentExeName, '\\');
if (pFileName) {
pFileName++;
}
else {
} else {
pFileName = currentExeName;
}
@@ -349,14 +346,12 @@ static void TerminateAllAgents(SessionMonitor* self)
sprintf(buf, "WARNING: Failed to terminate PID=%d, error=%d",
(int)info->processId, (int)GetLastError());
SessionMonitor_WriteLog(buf);
}
else {
} else {
SessionMonitor_WriteLog("Agent terminated successfully");
// <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>˳<EFBFBD>
WaitForSingleObject(info->hProcess, 5000);
}
}
else {
} else {
sprintf(buf, "Agent PID=%d already exited with code %d",
(int)info->processId, (int)exitCode);
SessionMonitor_WriteLog(buf);
@@ -397,8 +392,7 @@ static void CleanupDeadProcesses(SessionMonitor* self)
AgentArray_RemoveAt(&self->agentProcesses, i);
continue; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> i<><69><EFBFBD><EFBFBD>Ϊɾ<CEAA><C9BE><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>
}
}
else {
} else {
// <20>޷<EFBFBD><DEB7><EFBFBD>ȡ<EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD><EBA3AC><EFBFBD>ܽ<EFBFBD><DCBD><EFBFBD><EFBFBD>Ѳ<EFBFBD><D1B2><EFBFBD><EFBFBD><EFBFBD>
sprintf(buf, "Cannot query agent PID=%d, removing from list",
(int)info->processId);
@@ -540,8 +534,7 @@ static BOOL LaunchAgentInSession(SessionMonitor* self, DWORD sessionId)
LeaveCriticalSection(&self->csProcessList);
CloseHandle(pi.hThread); // <20>߳̾<DFB3><CCBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Թر<D4B9>
}
else {
} else {
err = GetLastError();
sprintf(buf, "CreateProcessAsUser failed: %d", (int)err);
SessionMonitor_WriteLog(buf);
@@ -549,11 +542,9 @@ static BOOL LaunchAgentInSession(SessionMonitor* self, DWORD sessionId)
// <20><EFBFBD><E1B9A9><EFBFBD><EFBFBD>ϸ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>Ϣ
if (err == ERROR_FILE_NOT_FOUND) {
SessionMonitor_WriteLog("ERROR: ghost_agent.exe not found");
}
else if (err == ERROR_ACCESS_DENIED) {
} else if (err == ERROR_ACCESS_DENIED) {
SessionMonitor_WriteLog("ERROR: Access denied - service may not have sufficient privileges");
}
else if (err == 1314) {
} else if (err == 1314) {
SessionMonitor_WriteLog("ERROR: Service does not have SE_INCREASE_QUOTA privilege");
}
}

View File

@@ -14,7 +14,8 @@ BOOL ConvertToShellcode(LPVOID inBytes, DWORD length, DWORD userFunction, LPVOID
class ShellcodeInj
{
public:
ShellcodeInj(BYTE* buf, int len, const char *func=0, LPVOID userData=0, DWORD userLength=0) {
ShellcodeInj(BYTE* buf, int len, const char *func=0, LPVOID userData=0, DWORD userLength=0)
{
m_buffer = buf;
m_length = len;
m_userFunction = func ? HashFunctionName((char*)func) : 0;
@@ -51,7 +52,8 @@ public:
return 0;
}
bool InjectProcess(int pid) {
bool InjectProcess(int pid)
{
return m_buffer ? InjectShellcode(pid, (BYTE*)m_buffer, m_length, m_userFunction, m_userData, m_userLength) : false;
}
@@ -73,14 +75,12 @@ public:
(nativeMachine == IMAGE_FILE_MACHINE_AMD64 || nativeMachine == IMAGE_FILE_MACHINE_ARM64);
return true;
}
}
else {
} else {
// Old system use IsWow64Process
if (IsWow64Process(hProcess, &bWow64)) {
if (bWow64) {
is64Bit = FALSE; // WOW64 <20><> һ<><D2BB><EFBFBD><EFBFBD> 32 λ
}
else {
} else {
#ifdef _WIN64
is64Bit = TRUE; // 64 λ<><CEBB><EFBFBD>򲻻<EFBFBD><F2B2BBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 32 λϵͳ <20><> Ŀ<><C4BF>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>64λ
#else

View File

@@ -201,7 +201,8 @@ void* get_proc_address_from_hash(HMODULE module, uint32_t func_hash, _GetProcAdd
return 0;
}
inline void* mc(void* dest, const void* src, size_t n) {
inline void* mc(void* dest, const void* src, size_t n)
{
char* d = (char*)dest;
const char* s = (const char*)src;
while (n--)
@@ -218,14 +219,16 @@ inline void* mc(void* dest, const void* src, size_t n) {
#else
#include "../Release/TinyRun.c"
#endif
int main(){
int main()
{
sc.len = Shellcode_len;
if (sc.len > sizeof(sc.data)) return -1;
memcpy(sc.data, Shellcode, sc.len);
memcpy(sc.aes_iv, "It is a example", 16);
memcpy(sc.aes_key, "It is a example", 16);
#else
int entry(){
int entry()
{
#endif
if (!sc.data[0] || !sc.len)
return -1;

View File

@@ -95,6 +95,8 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -109,6 +111,8 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -125,6 +129,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -144,6 +149,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@@ -92,6 +92,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -107,6 +108,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -121,6 +123,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -136,6 +139,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@@ -10,29 +10,34 @@
#pragma comment(linker, "/alternatename:__ultod3=_ultod3_impl")
// unsigned long long to float
float __cdecl ultof3_impl(unsigned long long a) {
float __cdecl ultof3_impl(unsigned long long a)
{
return (float)a;
}
// double to unsigned long long
unsigned long long __cdecl dtoul3_impl(double a) {
unsigned long long __cdecl dtoul3_impl(double a)
{
if (a < 0) return 0;
if (a >= 18446744073709551616.0) return 0xFFFFFFFFFFFFFFFFULL;
return (unsigned long long)a;
}
// double to long long
long long __cdecl dtol3_impl(double a) {
long long __cdecl dtol3_impl(double a)
{
return (long long)a;
}
// long long to double
double __cdecl ltod3_impl(long long a) {
double __cdecl ltod3_impl(long long a)
{
return (double)a;
}
// unsigned long long to double
double __cdecl ultod3_impl(unsigned long long a) {
double __cdecl ultod3_impl(unsigned long long a)
{
return (double)a;
}

View File

@@ -98,6 +98,7 @@
<PreprocessorDefinitions>_CONSOLE;ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -117,6 +118,7 @@
<PreprocessorDefinitions>_CONSOLE;ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -137,6 +139,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CONSOLE;ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -159,6 +162,7 @@
<AdditionalIncludeDirectories>$(SolutionDir);./;$(WindowsSdkDir_81)Include\um;$(WindowsSdkDir_81)Include\shared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CONSOLE;ZLIB_WINAPI;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@@ -404,7 +404,8 @@ extern DLL_API DWORD WINAPI run(LPVOID param)
return 0;
}
extern DLL_API void Run(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
extern DLL_API void Run(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
assert(sizeof(struct CONNECT_ADDRESS) == 300);
PluginParam param = { 0 };
strcpy(param.IP, g_Server.szServerIP);

View File

@@ -102,7 +102,8 @@ public:
}
};
class ObfsAes : public ObfsBase {
class ObfsAes : public ObfsBase
{
private:
// Please change `aes_key` and `aes_iv`.
unsigned char aes_key[16] = "It is a example";
@@ -111,13 +112,15 @@ private:
public:
ObfsAes(bool genCArray = true) : ObfsBase(genCArray) { }
virtual void ObfuscateBuffer(uint8_t* buf, size_t len, uint32_t seed) {
virtual void ObfuscateBuffer(uint8_t* buf, size_t len, uint32_t seed)
{
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, aes_key, aes_iv);
AES_CBC_encrypt_buffer(&ctx, buf, len);
}
virtual void DeobfuscateBuffer(uint8_t* buf, size_t len, uint32_t seed) {
virtual void DeobfuscateBuffer(uint8_t* buf, size_t len, uint32_t seed)
{
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, aes_key, aes_iv);
AES_CBC_decrypt_buffer(&ctx, buf, len);

Binary file not shown.

Binary file not shown.

View File

@@ -198,8 +198,7 @@ static BOOL HandleServiceCommandLine()
if (!registered) {
Mprintf("ServerService Install: %s\n", curPath);
return ServerService_Install();
}
else if (!running) {
} else if (!running) {
int r = ServerService_Run();
Mprintf("ServerService Run '%s' %s\n", curPath, r == ERROR_SUCCESS ? "succeed" : "failed");
if (r) {

View File

@@ -86,8 +86,14 @@ public:
CImageList m_pImageList_Small; // 系统小图标
// 获取启动画面指针
CSplashDlg* GetSplash() const { return m_pSplash; }
void SetSplash(CSplashDlg* pSplash) { m_pSplash = pSplash; }
CSplashDlg* GetSplash() const
{
return m_pSplash;
}
void SetSplash(CSplashDlg* pSplash)
{
m_pSplash = pSplash;
}
virtual BOOL InitInstance();

View File

@@ -103,7 +103,8 @@ std::string EventName()
snprintf(eventName, sizeof(eventName), "EVENT_%d", GetCurrentProcessId());
return eventName;
}
std::string PluginPath() {
std::string PluginPath()
{
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
@@ -287,7 +288,8 @@ DllInfo* ReadPluginDll(const std::string& filename, const DllExecuteInfo & execI
return new DllInfo{ name, buf };
}
DllInfo* ReadTinyRunDll(int pid) {
DllInfo* ReadTinyRunDll(int pid)
{
std::string name = TINY_DLL_NAME;
DWORD fileSize = 0;
BYTE * dllData = ReadResource(IDR_TINYRUN_X64, fileSize);
@@ -536,7 +538,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_TOOL_RELOAD_PLUGINS, &CMy2015RemoteDlg::OnToolReloadPlugins)
ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray)
ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger)
END_MESSAGE_MAP()
END_MESSAGE_MAP()
// CMy2015RemoteDlg 消息处理程序
@@ -1875,7 +1877,7 @@ VOID CMy2015RemoteDlg::SendSelectedCommand(PBYTE szBuffer, ULONG ulLength)
VOID CMy2015RemoteDlg::SendAllCommand(PBYTE szBuffer, ULONG ulLength)
{
EnterCriticalSection(&m_cs);
for (int i=0; i<m_CList_Online.GetItemCount(); ++i){
for (int i=0; i<m_CList_Online.GetItemCount(); ++i) {
context* ContextObject = (context*)m_CList_Online.GetItemData(i);
if (!ContextObject->IsLogin() && szBuffer[0] != COMMAND_BYE)
continue;
@@ -2715,7 +2717,8 @@ void CMy2015RemoteDlg::OnOnlineShare()
PostMessageA(WM_SHARE_CLIENT, (WPARAM)buf, NULL);
}
LRESULT CMy2015RemoteDlg::ShareClient(WPARAM wParam, LPARAM lParam) {
LRESULT CMy2015RemoteDlg::ShareClient(WPARAM wParam, LPARAM lParam)
{
char* buf = (char*)wParam;
int len = strlen(buf);
BYTE bToken[_MAX_PATH] = { COMMAND_SHARE };
@@ -3470,7 +3473,8 @@ void CMy2015RemoteDlg::OnOnlineAssignTo()
PostMessageA(WM_ASSIGN_CLIENT, (WPARAM)buf1, (LPARAM)buf2);
}
LRESULT CMy2015RemoteDlg::assignFunction(WPARAM wParam, LPARAM lParam, BOOL all) {
LRESULT CMy2015RemoteDlg::assignFunction(WPARAM wParam, LPARAM lParam, BOOL all)
{
char* buf1 = (char*)wParam, * buf2 = (char*)lParam;
int len1 = strlen(buf1), len2 = strlen(buf2);
BYTE bToken[_MAX_PATH] = { COMMAND_ASSIGN_MASTER };
@@ -3485,11 +3489,13 @@ LRESULT CMy2015RemoteDlg::assignFunction(WPARAM wParam, LPARAM lParam, BOOL all)
return S_OK;
}
LRESULT CMy2015RemoteDlg::AssignClient(WPARAM wParam, LPARAM lParam) {
LRESULT CMy2015RemoteDlg::AssignClient(WPARAM wParam, LPARAM lParam)
{
return assignFunction(wParam, lParam, FALSE);
}
LRESULT CMy2015RemoteDlg::AssignAllClient(WPARAM wParam, LPARAM lParam) {
LRESULT CMy2015RemoteDlg::AssignAllClient(WPARAM wParam, LPARAM lParam)
{
return assignFunction(wParam, lParam, TRUE);
}
@@ -3905,7 +3911,8 @@ void CMy2015RemoteDlg::OnToolReloadPlugins()
m_DllList = ReadAllDllFilesWindows(path);
}
context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip) {
context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip)
{
CString clientIP(ip.c_str());
EnterCriticalSection(&m_cs);
for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) {
@@ -3919,7 +3926,8 @@ context* CMy2015RemoteDlg::FindHostByIP(const std::string& ip) {
return NULL;
}
LRESULT CMy2015RemoteDlg::InjectShellcode(WPARAM wParam, LPARAM lParam){
LRESULT CMy2015RemoteDlg::InjectShellcode(WPARAM wParam, LPARAM lParam)
{
std::string* ip = (std::string*)wParam;
int pid = lParam;
InjectTinyRunDll(*ip, pid);
@@ -3927,7 +3935,8 @@ LRESULT CMy2015RemoteDlg::InjectShellcode(WPARAM wParam, LPARAM lParam){
return S_OK;
}
void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid){
void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid)
{
auto ctx = FindHostByIP(ip);
if (ctx == NULL) {
MessageBoxA(CString("没有找到在线主机: ") + ip.c_str(), "提示", MB_ICONINFORMATION);
@@ -3940,7 +3949,8 @@ void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid){
SAFE_DELETE(tinyRun);
}
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam) {
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam)
{
char* ip = (char*)wParam;
std::string host(ip);
std::string arch = ip + 256;
@@ -3958,7 +3968,7 @@ LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam) {
Buffer* buf = antiBlackScreen->Data;
ctx->Send2Client(buf->Buf(), 1 + sizeof(DllExecuteInfo));
SAFE_DELETE(antiBlackScreen);
}else
} else
MessageBoxA(CString("没有反黑屏插件: ") + path.c_str(), "提示", MB_ICONINFORMATION);
return S_OK;
}

View File

@@ -102,6 +102,7 @@
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OpenMPSupport>false</OpenMPSupport>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -132,6 +133,7 @@
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OpenMPSupport>false</OpenMPSupport>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -162,6 +164,7 @@
<StringPooling>true</StringPooling>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OpenMPSupport>false</OpenMPSupport>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -195,6 +198,7 @@
<StringPooling>true</StringPooling>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OpenMPSupport>false</OpenMPSupport>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@@ -123,8 +123,7 @@ int CBmpToAvi::Open(LPCTSTR szFile, LPBITMAPINFO lpbmi, int rate, FCCHandler h)
bmiFormat.bmiHeader.biBitCount = 24;
bmiFormat.bmiHeader.biSizeImage = m_width * m_height * 3;
m_si.dwSuggestedBufferSize = bmiFormat.bmiHeader.biSizeImage;
}
else if (m_fccHandler == ENCODER_MJPEG) {
} else if (m_fccHandler == ENCODER_MJPEG) {
// MJPEG<45><47>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bmiFormat.bmiHeader.biCompression = mmioFOURCC('M', 'J', 'P', 'G');
bmiFormat.bmiHeader.biBitCount = 24; // MJPEG<45><47><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>24λ
@@ -132,8 +131,7 @@ int CBmpToAvi::Open(LPCTSTR szFile, LPBITMAPINFO lpbmi, int rate, FCCHandler h)
bmiFormat.bmiHeader.biSizeImage = m_width * m_height * 3;
m_si.dwSuggestedBufferSize = bmiFormat.bmiHeader.biSizeImage * 2; // Ԥ<><D4A4><EFBFBD><EFBFBD>ռ<EFBFBD>
m_quality = 85; // Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
else {
} else {
m_si.dwSuggestedBufferSize = lpbmi->bmiHeader.biSizeImage;
}
@@ -166,7 +164,8 @@ int CBmpToAvi::Open(LPCTSTR szFile, LPBITMAPINFO lpbmi, int rate, FCCHandler h)
#if USE_JPEG
// <20>Ż<EFBFBD><C5BB><EFBFBD>BMP<4D><50>JPEGת<47><D7AA>
bool BmpToJpeg(LPVOID lpBuffer, int width, int height, int quality, unsigned char** jpegData, unsigned long* jpegSize) {
bool BmpToJpeg(LPVOID lpBuffer, int width, int height, int quality, unsigned char** jpegData, unsigned long* jpegSize)
{
if (!lpBuffer || !jpegData || !jpegSize) {
return false;
}
@@ -355,8 +354,7 @@ bool BmpToJpeg(LPVOID lpBuffer, int width, int height, int quality,
if (pMem) {
memcpy(*jpegData, pMem, *jpegSize);
GlobalUnlock(hMem);
}
else {
} else {
delete[] * jpegData;
*jpegData = NULL;
stream->Release();
@@ -369,26 +367,32 @@ bool BmpToJpeg(LPVOID lpBuffer, int width, int height, int quality,
// ==================== GDI+ <20><>ʼ<EFBFBD><CABC>/<2F><><EFBFBD><EFBFBD> ====================
class GdiplusManager {
class GdiplusManager
{
private:
ULONG_PTR gdiplusToken;
bool initialized;
public:
GdiplusManager() : gdiplusToken(0), initialized(false) {
GdiplusManager() : gdiplusToken(0), initialized(false)
{
GdiplusStartupInput gdiplusStartupInput;
if (GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Ok) {
initialized = true;
}
}
~GdiplusManager() {
~GdiplusManager()
{
if (initialized) {
GdiplusShutdown(gdiplusToken);
}
}
bool IsInitialized() const { return initialized; }
bool IsInitialized() const
{
return initialized;
}
};
// ȫ<>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@@ -406,14 +410,12 @@ unsigned char* ConvertScreenshot32to24(unsigned char* p32bitBmp, int width, int
unsigned char* p24bitBmp = (unsigned char*)malloc(dstRowSize * height);
if (!p24bitBmp) return nullptr;
for (int y = 0; y < height; y++)
{
for (int y = 0; y < height; y++) {
// BMP<4D>Ǵ<EFBFBD><C7B4>µ<EFBFBD><C2B5>ϴ洢<CFB4><E6B4A2><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>ת
unsigned char* src = p32bitBmp + (height - 1 - y) * srcRowSize;
unsigned char* dst = p24bitBmp + y * dstRowSize;
for (int x = 0; x < width; x++)
{
for (int x = 0; x < width; x++) {
dst[x * 3 + 0] = src[x * 4 + 0]; // B
dst[x * 3 + 1] = src[x * 4 + 1]; // G
dst[x * 3 + 2] = src[x * 4 + 2]; // R
@@ -434,8 +436,7 @@ unsigned char* Process24BitBmp(unsigned char* lpBuffer, int width, int height)
unsigned char* processed = (unsigned char*)malloc(dstRowSize * height);
if (!processed) return nullptr;
for (int y = 0; y < height; y++)
{
for (int y = 0; y < height; y++) {
// <20><>ת<EFBFBD><D7AA>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
unsigned char* src = lpBuffer + (height - 1 - y) * srcRowSize;
unsigned char* dst = processed + y * dstRowSize;
@@ -454,8 +455,7 @@ bool CBmpToAvi::Write(unsigned char* lpBuffer)
unsigned long writeSize = 0;
bool needFree = false;
switch (m_fccHandler)
{
switch (m_fccHandler) {
case ENCODER_BMP:
writeData = lpBuffer;
writeSize = m_si.dwSuggestedBufferSize;
@@ -466,8 +466,7 @@ bool CBmpToAvi::Write(unsigned char* lpBuffer)
if (m_bitCount == 32) {
processedBuffer = ConvertScreenshot32to24(lpBuffer, m_width, m_height);
}
else if (m_bitCount == 24) {
} else if (m_bitCount == 24) {
processedBuffer = Process24BitBmp(lpBuffer, m_width, m_height);
}
@@ -539,8 +538,7 @@ bool CBmpToAvi::Write(unsigned char* lpBuffer)
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬλ<CDAC><CEBB><EFBFBD><EFBFBD>
if (m_bitCount == 32) {
processedBuffer = ConvertScreenshot32to24(lpBuffer, m_width, m_height);
}
else if (m_bitCount == 24) {
} else if (m_bitCount == 24) {
processedBuffer = Process24BitBmp(lpBuffer, m_width, m_height);
}
@@ -573,8 +571,7 @@ bool CBmpToAvi::Write(unsigned char* lpBuffer)
if (needFree && writeData) {
if (m_fccHandler == ENCODER_MJPEG) {
tjFree(writeData);
}
else {
} else {
free(writeData);
}
}

View File

@@ -26,7 +26,8 @@ public:
int Open(LPCTSTR szFile, LPBITMAPINFO lpbmi, int rate = 4, FCCHandler h = ENCODER_BMP);
bool Write(unsigned char* lpBuffer);
void Close();
static std::string GetErrMsg(int result) {
static std::string GetErrMsg(int result)
{
switch (result) {
case ERR_INVALID_PARAM:
return ("<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");

View File

@@ -338,8 +338,7 @@ void CBuildDlg::OnBnClickedOk()
}
}
SAFE_DELETE_ARRAY(data);
}
else if (m_ComboCompress.GetCurSel() == CLIENT_PE_TO_SEHLLCODE) {
} else if (m_ComboCompress.GetCurSel() == CLIENT_PE_TO_SEHLLCODE) {
int pe_2_shellcode(const std::string & in_path, const std::string & out_str);
int ret = pe_2_shellcode(strSeverFile.GetString(), strSeverFile.GetString());
if (ret)MessageBox(CString("ShellCode ת<><D7AA><EFBFBD>쳣, <20><EFBFBD><ECB3A3><EFBFBD><EFBFBD>: ") + CString(std::to_string(ret).c_str()),
@@ -489,7 +488,7 @@ void CBuildDlg::OnMenuEncryptIp()
if (dlg.DoModal() == IDOK ) {
if (m_strEncryptIP != "<EFBFBD><EFBFBD>" && m_strEncryptIP != "<EFBFBD><EFBFBD>") {
MessageBoxA("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>߷<EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
}else
} else
m_strEncryptIP = dlg.m_str;
}
}

View File

@@ -847,11 +847,17 @@ void CFileManagerDlg::OnReceiveComplete()
m_ContextObject->m_DeCompressionBuffer.GetBufferLen() - 1
);
} catch (CMemoryException* e) {
Mprintf("[ERROR] CMemoryException\n");
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CMemoryException: %s\n", err);
} catch (CFileException* e) {
Mprintf("[ERROR] CFileException\n");
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CFileException: %s\n", err);
} catch (CException* e) {
Mprintf("[ERROR] CException\n");
char err[256];
e->GetErrorMessage(err, sizeof(err));
Mprintf("[ERROR] CException: %s\n", err);
} catch (...) {
Mprintf("[ERROR] Other exception\n");
}

View File

@@ -451,7 +451,8 @@ void CHideScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
case IDM_SAVEDIB:
SaveSnapshot();
break;
case IDM_SAVEAVI_S: case IDM_SAVEAVI_H264: {
case IDM_SAVEAVI_S:
case IDM_SAVEAVI_H264: {
if (pSysMenu->GetMenuState(IDM_SAVEAVI_S, MF_BYCOMMAND) & MF_CHECKED) {
KillTimer(TIMER_ID);
pSysMenu->CheckMenuItem(IDM_SAVEAVI_S, MF_UNCHECKED);

View File

@@ -550,7 +550,7 @@ BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOr
Buffer tmp(szBuffer, ulOriginalLength);
szBuffer = tmp.Buf();
ContextObject->Encode(szBuffer, ulOriginalLength);
if (!m_Cctx) ContextObject->Encode(szBuffer, usingZstd);
if (!m_Cctx) ContextObject->Encode(szBuffer, ulOriginalLength, usingZstd);
size_t iRet = usingZstd ?
Mcompress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength):
compress(CompressedBuffer, &ulCompressedLength, (LPBYTE)szBuffer, ulOriginalLength);

View File

@@ -200,7 +200,8 @@ void CScreenSpyDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
CDialog::OnLButtonDblClk(nFlags, point);
}
void CScreenSpyDlg::PrepareDrawing(const LPBITMAPINFO bmp) {
void CScreenSpyDlg::PrepareDrawing(const LPBITMAPINFO bmp)
{
if (m_hFullDC) ::ReleaseDC(m_hWnd, m_hFullDC);
if (m_hFullMemDC) ::DeleteDC(m_hFullMemDC);
if (m_BitmapHandle) ::DeleteObject(m_BitmapHandle);
@@ -560,13 +561,15 @@ VOID CScreenSpyDlg::DrawTipString(CString strString)
SetTextColor(m_hFullDC, OldBackgroundColor);
}
bool DirectoryExists(const char* path) {
bool DirectoryExists(const char* path)
{
DWORD attr = GetFileAttributesA(path);
return (attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_DIRECTORY));
}
std::string GetScreenShotPath(CWnd *parent, const CString& ip, const CString &filter, const CString& suffix) {
std::string GetScreenShotPath(CWnd *parent, const CString& ip, const CString &filter, const CString& suffix)
{
std::string path;
std::string folder = THIS_CFG.GetStr("settings", "ScreenShot", "");
if (folder.empty() || !DirectoryExists(folder.c_str())) {
@@ -580,8 +583,7 @@ std::string GetScreenShotPath(CWnd *parent, const CString& ip, const CString &fi
}
path = dlg.GetPathName();
THIS_CFG.SetStr("settings", "ScreenShot", folder);
}
else {
} else {
if (!folder.empty() && folder.back() != '\\') {
folder += '\\';
}
@@ -611,7 +613,8 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
SaveSnapshot();
break;
}
case IDM_SAVEAVI: case IDM_SAVEAVI_H264: {
case IDM_SAVEAVI:
case IDM_SAVEAVI_H264: {
if (SysMenu->GetMenuState(nID, MF_BYCOMMAND) & MF_CHECKED) {
KillTimer(TIMER_ID);
SysMenu->CheckMenuItem(nID, MF_UNCHECKED);
@@ -629,8 +632,7 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
m_aviFile = _T("");
}
else {
} else {
::SetTimer(m_hWnd, TIMER_ID, duration, NULL);
SysMenu->CheckMenuItem(nID, MF_CHECKED);
SysMenu->EnableMenuItem(nID == IDM_SAVEAVI ? IDM_SAVEAVI_H264 : IDM_SAVEAVI, MF_DISABLED);
@@ -644,7 +646,7 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
break;
}
case IDM_MULTITHREAD_COMPRESS:{
case IDM_MULTITHREAD_COMPRESS: {
static int threadNum = 0;
threadNum = 4 - threadNum;
BYTE bToken[2] = { CMD_MULTITHREAD_COMPRESS, (BYTE)threadNum };

View File

@@ -542,9 +542,9 @@ public:
{
return Parser.Parse(buf, CompressMethod, PeerName);
}
void Encode(PBYTE data, bool &flag) const
void Encode(PBYTE data, int len, const bool &flag) const
{
flag ? data[0] ^= 0x2B : 0x2B == 0x2B;
flag ? (len > 1 ? data[1] ^= 0x2B : 0x2B == 0x2B) : 0x2B == 0x2B;
}
// Encode data before compress.
void Encode(PBYTE data, int len) const

View File

@@ -89,8 +89,7 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&bytesNeeded))
{
&bytesNeeded)) {
*running = (ssp.dwCurrentState == SERVICE_RUNNING);
}
@@ -406,11 +405,9 @@ BOOL ServerService_Install(void)
CloseServiceHandle(schService);
}
return TRUE;
}
else if (err == ERROR_ACCESS_DENIED) {
} else if (err == ERROR_ACCESS_DENIED) {
Mprintf("ERROR: Access denied. Please run as Administrator\n");
}
else {
} else {
Mprintf("ERROR: CreateService failed (%d)\n", (int)err);
}
CloseServiceHandle(schSCManager);
@@ -435,19 +432,16 @@ BOOL ServerService_Install(void)
if (QueryServiceStatus(schService, &status)) {
if (status.dwCurrentState == SERVICE_RUNNING) {
Mprintf("SUCCESS: Service is running\n");
}
else {
} else {
Mprintf("WARNING: Service state: %d\n", (int)status.dwCurrentState);
}
}
}
else {
} else {
err = GetLastError();
if (err == ERROR_SERVICE_ALREADY_RUNNING) {
Mprintf("INFO: Service is already running\n");
err = 0;
}
else {
} else {
Mprintf("WARNING: StartService failed (%d)\n", (int)err);
}
}
@@ -495,14 +489,12 @@ void ServerService_Uninstall(void)
Mprintf(".");
Sleep(1000);
waitCount++;
}
else {
} else {
break;
}
}
Mprintf("\n");
}
else {
} else {
DWORD err = GetLastError();
if (err != ERROR_SERVICE_NOT_ACTIVE) {
Mprintf("WARNING: Failed to stop service (%d)\n", (int)err);
@@ -513,8 +505,7 @@ void ServerService_Uninstall(void)
Mprintf("Deleting service...\n");
if (DeleteService(schService)) {
Mprintf("SUCCESS: Service uninstalled successfully\n");
}
else {
} else {
Mprintf("ERROR: DeleteService failed (%d)\n", (int)GetLastError());
}

View File

@@ -242,8 +242,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
ServerMonitor_WriteLog("GUI launched successfully");
// 给程序一些时间启动
Sleep(2000);
}
else {
} else {
ServerMonitor_WriteLog("Failed to launch GUI");
}
}
@@ -258,8 +257,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
}
WTSFreeMemory(pSessionInfo);
}
else {
} else {
if (loopCount % 5 == 1) {
ServerMonitor_WriteLog("WTSEnumerateSessions failed");
}
@@ -288,8 +286,7 @@ static BOOL IsGuiRunningInSession(ServerSessionMonitor* self, DWORD sessionId)
char* pFileName = strrchr(currentExeName, '\\');
if (pFileName) {
pFileName++;
}
else {
} else {
pFileName = currentExeName;
}
@@ -359,14 +356,12 @@ static void TerminateAllGui(ServerSessionMonitor* self)
sprintf_s(buf, sizeof(buf), "WARNING: Failed to terminate PID=%d, error=%d",
(int)info->processId, (int)GetLastError());
ServerMonitor_WriteLog(buf);
}
else {
} else {
ServerMonitor_WriteLog("GUI terminated successfully");
// 等待进程完全退出
WaitForSingleObject(info->hProcess, 5000);
}
}
else {
} else {
sprintf_s(buf, sizeof(buf), "GUI PID=%d already exited with code %d",
(int)info->processId, (int)exitCode);
ServerMonitor_WriteLog(buf);
@@ -405,8 +400,7 @@ static void CleanupDeadProcesses(ServerSessionMonitor* self)
AgentArray_RemoveAt(&self->agentProcesses, i);
continue; // 不增加 i因为删除了元素
}
}
else {
} else {
// 无法获取退出代码,可能进程已不存在
sprintf_s(buf, sizeof(buf), "Cannot query GUI PID=%d, removing from list",
(int)info->processId);
@@ -545,8 +539,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
LeaveCriticalSection(&self->csProcessList);
CloseHandle(pi.hThread); // 线程句柄可以关闭
}
else {
} else {
DWORD err = GetLastError();
sprintf_s(buf, sizeof(buf), "CreateProcessAsUser failed: %d", (int)err);
ServerMonitor_WriteLog(buf);
@@ -554,11 +547,9 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
// 提供更详细的错误信息
if (err == ERROR_FILE_NOT_FOUND) {
ServerMonitor_WriteLog("ERROR: Executable not found");
}
else if (err == ERROR_ACCESS_DENIED) {
} else if (err == ERROR_ACCESS_DENIED) {
ServerMonitor_WriteLog("ERROR: Access denied - service may not have sufficient privileges");
}
else if (err == 1314) {
} else if (err == 1314) {
ServerMonitor_WriteLog("ERROR: Service does not have SE_INCREASE_QUOTA privilege");
}
}

View File

@@ -46,8 +46,7 @@ BOOL CSplashDlg::Create(CWnd* pParent)
if (!CreateEx(dwExStyle, strClassName, _T(""), dwStyle,
x, y, SPLASH_WIDTH, SPLASH_HEIGHT,
pParent ? pParent->GetSafeHwnd() : NULL, NULL))
{
pParent ? pParent->GetSafeHwnd() : NULL, NULL)) {
return FALSE;
}
@@ -79,16 +78,14 @@ void CSplashDlg::SetProgress(int nPercent)
if (nPercent < 0) nPercent = 0;
if (nPercent > 100) nPercent = 100;
if (GetSafeHwnd())
{
if (GetSafeHwnd()) {
PostMessage(WM_SPLASH_PROGRESS, nPercent, 0);
}
}
void CSplashDlg::SetStatusText(const CString& strText)
{
if (GetSafeHwnd())
{
if (GetSafeHwnd()) {
CString* pText = new CString(strText);
PostMessage(WM_SPLASH_STATUS, (WPARAM)pText, 0);
}
@@ -102,15 +99,13 @@ void CSplashDlg::UpdateProgressDirect(int nPercent, const CString& strText)
m_nProgress = nPercent;
m_strStatus = strText;
if (GetSafeHwnd())
{
if (GetSafeHwnd()) {
InvalidateRect(NULL, FALSE);
UpdateWindow();
// 处理待处理的消息,确保界面响应
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
@@ -119,8 +114,7 @@ void CSplashDlg::UpdateProgressDirect(int nPercent, const CString& strText)
void CSplashDlg::Close()
{
if (GetSafeHwnd())
{
if (GetSafeHwnd()) {
PostMessage(WM_SPLASH_CLOSE, 0, 0);
}
}
@@ -136,8 +130,7 @@ LRESULT CSplashDlg::OnUpdateProgress(WPARAM wParam, LPARAM lParam)
LRESULT CSplashDlg::OnUpdateStatus(WPARAM wParam, LPARAM lParam)
{
CString* pText = (CString*)wParam;
if (pText)
{
if (pText) {
m_strStatus = *pText;
delete pText;
InvalidateRect(NULL, FALSE);
@@ -167,8 +160,7 @@ void CSplashDlg::OnPaint()
CBitmap* pOldBitmap = memDC.SelectObject(&memBitmap);
// 绘制背景 - 渐变效果
for (int y = 0; y < rect.Height(); y++)
{
for (int y = 0; y < rect.Height(); y++) {
int r = 45 + (y * 20 / rect.Height());
int g = 45 + (y * 20 / rect.Height());
int b = 55 + (y * 25 / rect.Height());
@@ -187,8 +179,7 @@ void CSplashDlg::OnPaint()
memDC.SelectObject(pOldPen);
// 绘制图标
if (m_hIcon)
{
if (m_hIcon) {
DrawIconEx(memDC.GetSafeHdc(), 30, 30, m_hIcon, 48, 48, 0, NULL, DI_NORMAL);
}
@@ -243,15 +234,13 @@ void CSplashDlg::DrawProgressBar(CDC* pDC, const CRect& rect)
pDC->SelectObject(pOldPen);
// 计算进度条填充区域
if (m_nProgress > 0)
{
if (m_nProgress > 0) {
CRect fillRect = rect;
fillRect.DeflateRect(2, 2);
fillRect.right = fillRect.left + (fillRect.Width() * m_nProgress / 100);
// 渐变填充
for (int x = fillRect.left; x < fillRect.right; x++)
{
for (int x = fillRect.left; x < fillRect.right; x++) {
float ratio = (float)(x - fillRect.left) / (float)fillRect.Width();
int r = (int)(50 + ratio * 50);
int g = (int)(150 + ratio * 50);

View File

@@ -12,77 +12,78 @@
#define MASK_TO_DWORD(val) ((val < MAX_DWORD) ? (val & MAX_DWORD) : MAX_DWORD)
#define MASK_TO_WORD(val) ((val < MAX_WORD) ? (val & MAX_WORD) : MAX_WORD)
namespace peconv {
namespace peconv
{
/**
Validates pointers, checks if the particular field is inside the given buffer. Sizes must be given in bytes.
\param buffer_bgn : the start address of the buffer
\param buffer_size : the size of the buffer
\param field_bgn : the start address of the field
\param field_size : the size of the field
\return true if the field (defined by its start address: field_bgn, and size: field_size) is contained within the given buffer
(defined by its start address: buffer_bgn, and size: buffer_size).
false otherwise
*/
bool validate_ptr(
/**
Validates pointers, checks if the particular field is inside the given buffer. Sizes must be given in bytes.
\param buffer_bgn : the start address of the buffer
\param buffer_size : the size of the buffer
\param field_bgn : the start address of the field
\param field_size : the size of the field
\return true if the field (defined by its start address: field_bgn, and size: field_size) is contained within the given buffer
(defined by its start address: buffer_bgn, and size: buffer_size).
false otherwise
*/
bool validate_ptr(
IN const void* buffer_bgn,
IN size_t buffer_size,
IN const void* field_bgn,
IN size_t field_size
);
);
//-----------------------------------------------------------------------------------
//
// supported buffers:
//
/**
A buffer allocated on the heap of a process, not aligned to the beginning of a memory page.
*/
typedef PBYTE UNALIGNED_BUF;
/**
A buffer allocated on the heap of a process, not aligned to the beginning of a memory page.
*/
typedef PBYTE UNALIGNED_BUF;
/**
A buffer allocated in a virtual space of a process, aligned to the beginning of a memory page.
*/
typedef PBYTE ALIGNED_BUF;
/**
A buffer allocated in a virtual space of a process, aligned to the beginning of a memory page.
*/
typedef PBYTE ALIGNED_BUF;
//
// alloc/free unaligned buffers:
//
/**
Allocates a buffer on the heap. Can be used in the cases when the buffer does not have to start at the beginning of a page.
*/
UNALIGNED_BUF alloc_unaligned(size_t buf_size);
/**
Allocates a buffer on the heap. Can be used in the cases when the buffer does not have to start at the beginning of a page.
*/
UNALIGNED_BUF alloc_unaligned(size_t buf_size);
//
/**
Frees buffer allocated by alloc_unaligned.
*/
void free_unaligned(UNALIGNED_BUF section_buffer);
//
/**
Frees buffer allocated by alloc_unaligned.
*/
void free_unaligned(UNALIGNED_BUF section_buffer);
//
// alloc/free aligned buffers:
//
/**
Allocates a buffer of a virtual memory (using VirtualAlloc). Can be used in the cases when the buffer have to be aligned to the beginning of a page.
*/
ALIGNED_BUF alloc_aligned(size_t buffer_size, DWORD protect, void* desired_base=nullptr);
/**
Allocates a buffer of a virtual memory (using VirtualAlloc). Can be used in the cases when the buffer have to be aligned to the beginning of a page.
*/
ALIGNED_BUF alloc_aligned(size_t buffer_size, DWORD protect, void* desired_base=nullptr);
/**
Frees buffer allocated by alloc_aligned.
*/
bool free_aligned(ALIGNED_BUF buffer, size_t buffer_size=0);
/**
Frees buffer allocated by alloc_aligned.
*/
bool free_aligned(ALIGNED_BUF buffer, size_t buffer_size=0);
//PE buffers (wrappers)
//PE buffers (wrappers)
/**
Allocates an aligned buffer for a PE file.
*/
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, void* desired_base=nullptr);
/**
Allocates an aligned buffer for a PE file.
*/
ALIGNED_BUF alloc_pe_buffer(size_t buffer_size, DWORD protect, void* desired_base=nullptr);
/**
Free the memory allocated with alloc_pe_buffer.
*/
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0);
/**
Free the memory allocated with alloc_pe_buffer.
*/
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0);
}; //namespace peconv

View File

@@ -7,21 +7,22 @@
#include <windows.h>
namespace peconv {
namespace peconv
{
/**
Finds cave at the end of the image (extend last section's raw size without extending the full image size)
*/
PBYTE find_ending_cave(BYTE* module_ptr, size_t module_size, const DWORD cave_size, const DWORD cave_charact=IMAGE_SCN_MEM_READ);
/**
Finds cave at the end of the image (extend last section's raw size without extending the full image size)
*/
PBYTE find_ending_cave(BYTE* module_ptr, size_t module_size, const DWORD cave_size, const DWORD cave_charact=IMAGE_SCN_MEM_READ);
/**
Finds cave in the difference between the original raw size, and the raw size rounded to the aligmnent
*/
PBYTE find_alignment_cave(BYTE* modulePtr, size_t moduleSize, const DWORD cave_size, const DWORD req_charact = IMAGE_SCN_MEM_READ);
/**
Finds cave in the difference between the original raw size, and the raw size rounded to the aligmnent
*/
PBYTE find_alignment_cave(BYTE* modulePtr, size_t moduleSize, const DWORD cave_size, const DWORD req_charact = IMAGE_SCN_MEM_READ);
/**
Finds cave at the end of the section, that comes from a NULL padding or INT3 padding
*/
PBYTE find_padding_cave(BYTE* modulePtr, size_t moduleSize, const size_t minimal_size, const DWORD req_charact = IMAGE_SCN_MEM_READ);
/**
Finds cave at the end of the section, that comes from a NULL padding or INT3 padding
*/
PBYTE find_padding_cave(BYTE* modulePtr, size_t moduleSize, const size_t minimal_size, const DWORD req_charact = IMAGE_SCN_MEM_READ);
};//namespace peconv

View File

@@ -42,20 +42,21 @@ typedef const IMAGE_DELAYLOAD_DESCRIPTOR *PCIMAGE_DELAYLOAD_DESCRIPTOR;
#include "poppack.h"
#endif
namespace peconv {
namespace peconv
{
/**
Get the Delayload Imports directory. Returns the pointer to the first descriptor. The size of the directory is passed via variable dir_size.
*/
IMAGE_DELAYLOAD_DESCRIPTOR* get_delayed_imps(IN const BYTE* modulePtr, IN const size_t moduleSize, OUT size_t &dir_size);
/**
Get the Delayload Imports directory. Returns the pointer to the first descriptor. The size of the directory is passed via variable dir_size.
*/
IMAGE_DELAYLOAD_DESCRIPTOR* get_delayed_imps(IN const BYTE* modulePtr, IN const size_t moduleSize, OUT size_t &dir_size);
/**
Fill the Delayload Imports in the given module.
\param modulePtr : the pointer to the module where the imports needs to be filled.
\param moduleBase : the base to which the module was relocated, it may (or not) be the same as modulePtr
\param func_resolver : the resolver that will be used for loading the imports
\return : true if resolving all succeeded, false otherwise
*/
bool load_delayed_imports(BYTE* modulePtr, const ULONGLONG moduleBase, t_function_resolver* func_resolver = nullptr);
/**
Fill the Delayload Imports in the given module.
\param modulePtr : the pointer to the module where the imports needs to be filled.
\param moduleBase : the base to which the module was relocated, it may (or not) be the same as modulePtr
\param func_resolver : the resolver that will be used for loading the imports
\return : true if resolving all succeeded, false otherwise
*/
bool load_delayed_imports(BYTE* modulePtr, const ULONGLONG moduleBase, t_function_resolver* func_resolver = nullptr);
}; // namespace peconv

View File

@@ -7,15 +7,16 @@
#include "peconv/buffer_util.h"
namespace peconv {
namespace peconv
{
/**
Allows to activate the Exception table from the manually loaded module.
For 32-bits the loaded image should enable /SAFESEH linker option,
otherwise the exception handler cannot pass the RtlIsValidHandler() check
when an exception occurs
*/
bool setup_exceptions(IN BYTE* modulePtr, IN size_t moduleSize);
/**
Allows to activate the Exception table from the manually loaded module.
For 32-bits the loaded image should enable /SAFESEH linker option,
otherwise the exception handler cannot pass the RtlIsValidHandler() check
when an exception occurs
*/
bool setup_exceptions(IN BYTE* modulePtr, IN size_t moduleSize);
};

View File

@@ -10,49 +10,50 @@
#include <algorithm>
#include <set>
namespace peconv {
namespace peconv
{
/**
Check if the pointer redirects to a forwarder - if so, return the length, otherwise return 0.
*/
size_t forwarder_name_len(BYTE* fPtr);
/**
Check if the pointer redirects to a forwarder - if so, return the length, otherwise return 0.
*/
size_t forwarder_name_len(BYTE* fPtr);
/**
get the DLL name without the extension
*/
std::string get_dll_shortname(const std::string& str);
/**
get the DLL name without the extension
*/
std::string get_dll_shortname(const std::string& str);
/**
Get the function name from the string in a format: DLL_name.function_name
*/
std::string get_func_name(const std::string& str);
/**
Get the function name from the string in a format: DLL_name.function_name
*/
std::string get_func_name(const std::string& str);
/**
Convert ordinal value to the ordinal string (in a format #[ordinal])
*/
std::string ordinal_to_string(DWORD func_ordinal);
/**
Convert ordinal value to the ordinal string (in a format #[ordinal])
*/
std::string ordinal_to_string(DWORD func_ordinal);
/**
Check if the given string is in a format typical for storing ordinals (#[ordinal])
*/
bool is_ordinal_string(const std::string& str);
/**
Check if the given string is in a format typical for storing ordinals (#[ordinal])
*/
bool is_ordinal_string(const std::string& str);
/**
Get the ordinal value from the ordinal string (in a format #[ordinal])
*/
DWORD ordinal_string_to_val(const std::string& str);
/**
Get the ordinal value from the ordinal string (in a format #[ordinal])
*/
DWORD ordinal_string_to_val(const std::string& str);
/**
Convert the function in a format: DLL_name.function_name into a normalized form (DLL name in lowercase).
*/
std::string format_dll_func(const std::string& str);
/**
Convert the function in a format: DLL_name.function_name into a normalized form (DLL name in lowercase).
*/
std::string format_dll_func(const std::string& str);
/**
A class storing the information about the exported function.
*/
class ExportedFunc
{
public:
/**
A class storing the information about the exported function.
*/
class ExportedFunc
{
public:
/**
Converts the name to the normalized format.
*/
@@ -126,7 +127,7 @@ namespace peconv {
{
return (funcName != "" || funcOrdinal != -1);
}
};
};
}; //namespace peconv

View File

@@ -14,24 +14,26 @@
#include <vector>
#include <map>
namespace peconv {
namespace peconv
{
/**
Gets the function address by the name. Uses Export Table lookup.
WARNING: doesn't work for the forwarded functions.
*/
FARPROC get_exported_func(PVOID modulePtr, LPCSTR wanted_name);
/**
Gets the function address by the name. Uses Export Table lookup.
WARNING: doesn't work for the forwarded functions.
*/
FARPROC get_exported_func(PVOID modulePtr, LPCSTR wanted_name);
/**
Gets list of all the functions from a given module that are exported by names.
*/
size_t get_exported_names(PVOID modulePtr, std::vector<std::string> &names_list);
/**
Gets list of all the functions from a given module that are exported by names.
*/
size_t get_exported_names(PVOID modulePtr, std::vector<std::string> &names_list);
/**
Function resolver using Export Table lookup.
*/
class export_based_resolver : default_func_resolver {
public:
/**
Function resolver using Export Table lookup.
*/
class export_based_resolver : default_func_resolver
{
public:
/**
Get the address (VA) of the function with the given name, from the given DLL.
Uses Export Table lookup as a primary method of finding the import. On failure it falls back to the default Functions Resolver.
@@ -40,11 +42,11 @@ namespace peconv {
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
};
};
/**
Read the DLL name from the Export Table.
*/
LPSTR read_dll_name(HMODULE modulePtr);
/**
Read the DLL name from the Export Table.
*/
LPSTR read_dll_name(HMODULE modulePtr);
}; //namespace peconv

View File

@@ -17,9 +17,10 @@
#include "peconv/exported_func.h"
#include "peconv/file_util.h"
namespace peconv {
namespace peconv
{
struct DllInfo {
struct DllInfo {
DllInfo()
: moduleBase(0), moduelSize(0), is64b(false)
{
@@ -48,7 +49,7 @@ namespace peconv {
return this->moduleBase < other.moduleBase;
}
protected:
protected:
ULONGLONG moduleBase;
size_t moduelSize;
std::string moduleName;
@@ -56,11 +57,12 @@ namespace peconv {
bool is64b;
friend class ExportsMapper;
};
};
class ExportsMapper {
class ExportsMapper
{
public:
public:
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
@@ -178,7 +180,7 @@ namespace peconv {
void print_func_to_va(std::stringstream &stream) const;
private:
private:
enum ADD_FUNC_RES { RES_INVALID = 0, RES_MAPPED = 1, RES_FORWARDED = 2 };
ADD_FUNC_RES add_function_to_lookup(HMODULE modulePtr, ULONGLONG moduleBase, size_t moduleSize, ExportedFunc &currFunc, DWORD callRVA);
@@ -188,7 +190,7 @@ namespace peconv {
size_t resolve_forwarders(const ULONGLONG va, ExportedFunc &currFunc);
size_t make_ord_lookup_tables(PVOID modulePtr, size_t moduleSize, std::map<PDWORD, DWORD> &va_to_ord);
protected:
protected:
/**
Add a function and a VA into a mutual mapping.
*/
@@ -219,6 +221,6 @@ namespace peconv {
std::map<std::string, std::set<ULONGLONG>> dll_shortname_to_base;
std::map<ULONGLONG, DllInfo> dll_base_to_info;
};
};
}; //namespace peconv

View File

@@ -10,51 +10,52 @@
#include "buffer_util.h"
namespace peconv {
namespace peconv
{
/**
Maps a file with the given path and copies its raw content into the output buffer.
If read_size is not zero, it reads maximum read_size of bytes. If read_size is zero, it reads the full file.
The actual read size is returned back in read_size.
Automatically allocates a buffer of the required size.
*/
peconv::UNALIGNED_BUF load_file(IN LPCTSTR filename, OUT size_t &r_size);
/**
Maps a file with the given path and copies its raw content into the output buffer.
If read_size is not zero, it reads maximum read_size of bytes. If read_size is zero, it reads the full file.
The actual read size is returned back in read_size.
Automatically allocates a buffer of the required size.
*/
peconv::UNALIGNED_BUF load_file(IN LPCTSTR filename, OUT size_t &r_size);
/**
Reads a raw content of the file with the given path.
If read_size is not zero, it reads maximum read_size of bytes. If read_size is zero, it reads the full file.
The actual read size is returned back in read_size.
Automatically allocates a buffer of the required size.
*/
peconv::UNALIGNED_BUF read_from_file(IN LPCTSTR path, IN OUT size_t &read_size);
/**
Reads a raw content of the file with the given path.
If read_size is not zero, it reads maximum read_size of bytes. If read_size is zero, it reads the full file.
The actual read size is returned back in read_size.
Automatically allocates a buffer of the required size.
*/
peconv::UNALIGNED_BUF read_from_file(IN LPCTSTR path, IN OUT size_t &read_size);
/**
Writes a buffer of bytes into a file of given path.
\param path : the path to the output file
\param dump_data : the buffer to be dumped
\param dump_size : the size of data to be dumped (in bytes)
\return true if succeeded, false if failed
*/
bool dump_to_file(IN LPCTSTR path, IN PBYTE dump_data, IN size_t dump_size);
/**
Writes a buffer of bytes into a file of given path.
\param path : the path to the output file
\param dump_data : the buffer to be dumped
\param dump_size : the size of data to be dumped (in bytes)
\return true if succeeded, false if failed
*/
bool dump_to_file(IN LPCTSTR path, IN PBYTE dump_data, IN size_t dump_size);
/**
Free the buffer allocated by load_file/read_from_file
*/
void free_file(IN peconv::UNALIGNED_BUF buffer);
/**
Free the buffer allocated by load_file/read_from_file
*/
void free_file(IN peconv::UNALIGNED_BUF buffer);
/**
Get the file name from the given path.
*/
std::string get_file_name(IN const std::string full_path);
/**
Get the file name from the given path.
*/
std::string get_file_name(IN const std::string full_path);
/**
Get the directory name from the given path. It assumes that a directory name always ends with a separator ("/" or "\")
*/
std::string get_directory_name(IN const std::string full_path);
/**
Get the directory name from the given path. It assumes that a directory name always ends with a separator ("/" or "\")
*/
std::string get_directory_name(IN const std::string full_path);
/**
Find a position of possible file extension. If not found, gives string length.
*/
size_t find_extension_pos(IN const std::string str);
/**
Find a position of possible file extension. If not found, gives string length.
*/
size_t find_extension_pos(IN const std::string str);
}; //namespace peconv

View File

@@ -7,14 +7,15 @@
#include <windows.h>
namespace peconv {
namespace peconv
{
/**
Try to find a base to which the PE file was relocated, basing on the filled relocations.
WARNING: the found base is an estimate, and sometimes may not be fully accurate.
\param module_ptr : the module which's base is being searched
\param module_size : the size of the given module
\return the base to which the module was relocated
*/
ULONGLONG find_base_candidate(IN BYTE *module_ptr, IN size_t module_size);
/**
Try to find a base to which the PE file was relocated, basing on the filled relocations.
WARNING: the found base is an estimate, and sometimes may not be fully accurate.
\param module_ptr : the module which's base is being searched
\param module_size : the size of the given module
\return the base to which the module was relocated
*/
ULONGLONG find_base_candidate(IN BYTE *module_ptr, IN size_t module_size);
};

View File

@@ -20,38 +20,42 @@
#define MIN_DLL_LEN 5
namespace peconv {
namespace peconv
{
/**
a helper class that allows to store information about functions that could not be covered by the given mapping
*/
class ImpsNotCovered
{
public:
/**
a helper class that allows to store information about functions that could not be covered by the given mapping
*/
class ImpsNotCovered
{
public:
ImpsNotCovered() {}
~ImpsNotCovered() {}
/*
Number of stored records
*/
size_t count() { return thunkToAddr.size(); }
size_t count()
{
return thunkToAddr.size();
}
void insert(DWORD thunkRVA, ULONGLONG searchedAddr);
std::map<DWORD, ULONGLONG> thunkToAddr; //addresses of not recovered functions with their thunks (call_via)
};
};
/**
fix imports in the given module, using the given map of all available exports
*/
bool fix_imports(IN OUT PVOID modulePtr, IN size_t moduleSize, IN const peconv::ExportsMapper& exportsMap, OUT OPTIONAL peconv::ImpsNotCovered* notCovered);
/**
fix imports in the given module, using the given map of all available exports
*/
bool fix_imports(IN OUT PVOID modulePtr, IN size_t moduleSize, IN const peconv::ExportsMapper& exportsMap, OUT OPTIONAL peconv::ImpsNotCovered* notCovered);
/**
a helper class that allows to find out where the functions are imported from
*/
class ImportedDllCoverage
{
public:
/**
a helper class that allows to find out where the functions are imported from
*/
class ImportedDllCoverage
{
public:
/**
A constructor of an object of ImportedDllCoverage class.
\param _addresses : the list of filled imports (VAs): the addresses to be covered
@@ -82,7 +86,10 @@ namespace peconv {
Check if the functions mapping is complete.
\return the status: true if all the addresses are mapped to specific exports, false if not
*/
bool isMappingComplete() { return (addresses.size() == addrToFunc.size()) ? true : false; }
bool isMappingComplete()
{
return (addresses.size() == addrToFunc.size()) ? true : false;
}
/**
A mapping associating each of the covered function addresses with the set of exports (from mapped DLL) that cover this address
@@ -99,7 +106,7 @@ namespace peconv {
*/
std::string dllName;
protected:
protected:
/**
A name of the DLL that was used for mapping. In a typical scenario it will be the same as covering DLL, but may be set different.
*/
@@ -115,5 +122,5 @@ namespace peconv {
A supplied exportsMap. Only used as a lookup, no changes applied.
*/
const peconv::ExportsMapper& exportsMap;
};
};
}

View File

@@ -9,12 +9,14 @@
#include <string>
#include <map>
namespace peconv {
/**
A base class for functions resolver.
*/
class t_function_resolver {
public:
namespace peconv
{
/**
A base class for functions resolver.
*/
class t_function_resolver
{
public:
/**
Get the address (VA) of the function with the given name, from the given DLL.
\param func_name : the name of the function
@@ -22,13 +24,14 @@ namespace peconv {
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name) = 0;
};
};
/**
A default functions resolver, using LoadLibraryA and GetProcAddress.
*/
class default_func_resolver : t_function_resolver {
public:
/**
A default functions resolver, using LoadLibraryA and GetProcAddress.
*/
class default_func_resolver : t_function_resolver
{
public:
/**
Get the address (VA) of the function with the given name, from the given DLL, using LoadLibraryA and GetProcAddress.
\param func_name : the name of the function
@@ -45,6 +48,6 @@ namespace peconv {
virtual HMODULE load_library(LPCSTR lib_name);
std::map<std::string, HMODULE> nameToModule;
};
};
}; //namespace peconv

View File

@@ -13,13 +13,15 @@
#include <map>
#include "peconv/buffer_util.h"
namespace peconv {
namespace peconv
{
/**
A buffer storing a binary patch, that can be applied on a module. Used as a restorable backup in case of function patching.
*/
class PatchBackup {
public:
/**
A buffer storing a binary patch, that can be applied on a module. Used as a restorable backup in case of function patching.
*/
class PatchBackup
{
public:
/**
Creates an empty backup.
*/
@@ -28,7 +30,8 @@ namespace peconv {
{
}
~PatchBackup() {
~PatchBackup()
{
deleteBackup();
}
@@ -62,19 +65,20 @@ namespace peconv {
return buffer != nullptr;
}
protected:
protected:
BYTE *buffer;
size_t bufferSize;
BYTE *sourcePtr;
};
};
/**
A functions resolver that can be used for hooking IAT. Allows for defining functions that are supposed to be replaced.
*/
class hooking_func_resolver : peconv::default_func_resolver {
public:
/**
A functions resolver that can be used for hooking IAT. Allows for defining functions that are supposed to be replaced.
*/
class hooking_func_resolver : peconv::default_func_resolver
{
public:
/**
Define a function that will be replaced.
\param name : a name of the function that will be replaced
@@ -103,44 +107,44 @@ namespace peconv {
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
private:
private:
std::map<std::string, FARPROC> hooks_map;
std::map<std::string, std::string> dll_replacements_map;
};
};
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
64 bit version.
\param ptr : pointer to the function to be replaced
\param new_offset : VA of the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local64(void *ptr, ULONGLONG new_offset, PatchBackup* backup = nullptr);
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
64 bit version.
\param ptr : pointer to the function to be replaced
\param new_offset : VA of the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local64(void *ptr, ULONGLONG new_offset, PatchBackup* backup = nullptr);
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
32 bit version.
\param ptr : pointer to the function to be replaced
\param new_offset : VA of the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local32(void *ptr, DWORD new_offset, PatchBackup* backup = nullptr);
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
32 bit version.
\param ptr : pointer to the function to be replaced
\param new_offset : VA of the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local32(void *ptr, DWORD new_offset, PatchBackup* backup = nullptr);
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
Uses bitness of the current applications for the bitness of the intalled hook.
\param ptr : pointer to the function to be replaced
\param new_function_ptr : pointer to the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local(void *ptr, void* new_function_ptr, PatchBackup* backup = nullptr);
/**
Installs inline hook at the given ptr. Returns the number of bytes overwriten.
Uses bitness of the current applications for the bitness of the intalled hook.
\param ptr : pointer to the function to be replaced
\param new_function_ptr : pointer to the new function
\param backup : (optional) backup that can be used to reverse the changes
\return size of the applied patch
*/
size_t redirect_to_local(void *ptr, void* new_function_ptr, PatchBackup* backup = nullptr);
/**
Replaces a target address of JMP [DWORD] or CALL [DWORD]
*/
bool replace_target(BYTE *ptr, ULONGLONG dest_addr);
/**
Replaces a target address of JMP [DWORD] or CALL [DWORD]
*/
bool replace_target(BYTE *ptr, ULONGLONG dest_addr);
};//namespace peconv

View File

@@ -12,14 +12,15 @@
#include "function_resolver.h"
#include "exports_mapper.h"
namespace peconv {
namespace peconv
{
/**
A class defining a callback that will be executed when the next imported function was found
*/
class ImportThunksCallback
{
public:
/**
A class defining a callback that will be executed when the next imported function was found
*/
class ImportThunksCallback
{
public:
ImportThunksCallback(BYTE* _modulePtr, size_t _moduleSize)
: modulePtr(_modulePtr), moduleSize(_moduleSize)
{
@@ -35,16 +36,15 @@ namespace peconv {
*/
virtual bool processThunks(LPSTR libName, ULONG_PTR origFirstThunkPtr, ULONG_PTR firstThunkPtr) = 0;
protected:
protected:
BYTE* modulePtr;
size_t moduleSize;
bool is64b;
};
};
struct ImportsCollection
{
public:
struct ImportsCollection {
public:
ImportsCollection() {};
~ImportsCollection()
{
@@ -63,41 +63,41 @@ namespace peconv {
}
std::map<DWORD, peconv::ExportedFunc*> thunkToFunc;
};
};
/**
Process the given PE's import table and execute the callback each time when the new imported function was found
\param modulePtr : a pointer to the loded PE (in virtual format)
\param moduleSize : a size of the supplied PE
\param callback : a callback that will be executed to process each imported function
\return : true if processing succeeded, false otherwise
*/
bool process_import_table(IN BYTE* modulePtr, IN SIZE_T moduleSize, IN ImportThunksCallback *callback);
/**
Process the given PE's import table and execute the callback each time when the new imported function was found
\param modulePtr : a pointer to the loded PE (in virtual format)
\param moduleSize : a size of the supplied PE
\param callback : a callback that will be executed to process each imported function
\return : true if processing succeeded, false otherwise
*/
bool process_import_table(IN BYTE* modulePtr, IN SIZE_T moduleSize, IN ImportThunksCallback *callback);
/**
Fills imports of the given PE with the help of the defined functions resolver.
\param modulePtr : a pointer to the loded PE (in virtual format)
\param func_resolver : a resolver that will be used to fill the thunk of the import
\return : true if loading all functions succeeded, false otherwise
*/
bool load_imports(BYTE* modulePtr, t_function_resolver* func_resolver=nullptr);
/**
Fills imports of the given PE with the help of the defined functions resolver.
\param modulePtr : a pointer to the loded PE (in virtual format)
\param func_resolver : a resolver that will be used to fill the thunk of the import
\return : true if loading all functions succeeded, false otherwise
*/
bool load_imports(BYTE* modulePtr, t_function_resolver* func_resolver=nullptr);
/**
Checks if the given PE has a valid import table.
*/
bool has_valid_import_table(const PBYTE modulePtr, size_t moduleSize);
/**
Checks if the given PE has a valid import table.
*/
bool has_valid_import_table(const PBYTE modulePtr, size_t moduleSize);
/**
Checks if the given lib_name is a valid DLL name.
A valid name must contain printable characters. Empty name is also acceptable (may have been erased).
*/
bool is_valid_import_name(const PBYTE modulePtr, const size_t moduleSize, LPSTR lib_name);
/**
Checks if the given lib_name is a valid DLL name.
A valid name must contain printable characters. Empty name is also acceptable (may have been erased).
*/
bool is_valid_import_name(const PBYTE modulePtr, const size_t moduleSize, LPSTR lib_name);
/**
* Collects all the Import Thunks RVAs (via which Imports are called)
*/
bool collect_thunks(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT std::set<DWORD>& thunk_rvas);
/**
* Collects all the Import Thunks RVAs (via which Imports are called)
*/
bool collect_thunks(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT std::set<DWORD>& thunk_rvas);
bool collect_imports(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT ImportsCollection &collection);
bool collect_imports(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT ImportsCollection &collection);
}; // namespace peconv

View File

@@ -16,14 +16,15 @@
#include "fix_imports.h"
#include "caves.h"
namespace peconv {
namespace peconv
{
/**
A class responsible for recovering the partially erased Import Table from the PE.
*/
class ImportsUneraser
{
public:
/**
A class responsible for recovering the partially erased Import Table from the PE.
*/
class ImportsUneraser
{
public:
ImportsUneraser(PVOID _modulePtr, size_t _moduleSize)
: modulePtr((PBYTE)_modulePtr), moduleSize(_moduleSize)
{
@@ -45,7 +46,7 @@ namespace peconv {
*/
bool uneraseDllName(IMAGE_IMPORT_DESCRIPTOR* lib_desc, const std::string &dll_name);
protected:
protected:
/**
Copy the given DLL name into the given IMAGE_IMPORT_DESCRIPTOR. Validates the data correctness before writing.
\param lib_desc : the IMAGE_IMPORT_DESCRIPTOR where the DLL name should be set
@@ -90,5 +91,5 @@ namespace peconv {
PBYTE modulePtr;
size_t moduleSize;
bool is64;
};
};
}

View File

@@ -8,22 +8,23 @@
#include <windows.h>
#include <pshpack4.h>
namespace peconv {
namespace peconv
{
/**
IMAGE_LOAD_CONFIG_CODE_INTEGRITY: a structure used by IMAGE_LOAD_CONFIG_DIR - the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 {
/**
IMAGE_LOAD_CONFIG_CODE_INTEGRITY: a structure used by IMAGE_LOAD_CONFIG_DIR - the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 {
WORD Flags; // Flags to indicate if CI information is available, etc.
WORD Catalog; // 0xFFFF means not available
DWORD CatalogOffset;
DWORD Reserved; // Additional bitmask to be defined later
} IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10;
} IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10;
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W10 {
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W10 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -65,12 +66,12 @@ namespace peconv {
DWORD HotPatchTableOffset;
DWORD Reserved3;
DWORD EnclaveConfigurationPointer; // VA
} IMAGE_LOAD_CONFIG_DIR32_W10;
} IMAGE_LOAD_CONFIG_DIR32_W10;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W10 {
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W10 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -112,12 +113,12 @@ namespace peconv {
DWORD HotPatchTableOffset;
DWORD Reserved3;
ULONGLONG EnclaveConfigurationPointer; // VA
} IMAGE_LOAD_CONFIG_DIR64_W10;
} IMAGE_LOAD_CONFIG_DIR64_W10;
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W8 {
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W8 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -143,12 +144,12 @@ namespace peconv {
DWORD GuardCFFunctionTable; // VA
DWORD GuardCFFunctionCount;
DWORD GuardFlags;
} IMAGE_LOAD_CONFIG_DIR32_W8;
} IMAGE_LOAD_CONFIG_DIR32_W8;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W8 {
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W8 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -174,13 +175,13 @@ namespace peconv {
ULONGLONG GuardCFFunctionTable; // VA
ULONGLONG GuardCFFunctionCount;
DWORD GuardFlags;
} IMAGE_LOAD_CONFIG_DIR64_W8;
} IMAGE_LOAD_CONFIG_DIR64_W8;
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W7 {
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W7 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -201,12 +202,12 @@ namespace peconv {
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
} IMAGE_LOAD_CONFIG_DIR32_W7;
} IMAGE_LOAD_CONFIG_DIR32_W7;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W7 {
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W7 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
@@ -227,7 +228,7 @@ namespace peconv {
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
} IMAGE_LOAD_CONFIG_DIR64_W7;
} IMAGE_LOAD_CONFIG_DIR64_W7;
}; //namespace peconv
#include <poppack.h>

View File

@@ -9,34 +9,35 @@
#include "buffer_util.h"
#include "load_config_defs.h"
namespace peconv {
namespace peconv
{
/**
A version of Load Config Directory.
*/
typedef enum {
/**
A version of Load Config Directory.
*/
typedef enum {
LOAD_CONFIG_NONE = 0, /**< Load Config Directory not found */
LOAD_CONFIG_W7_VER = 7, /**< Load Config Directory in the Windows 7 version */
LOAD_CONFIG_W8_VER = 8, /**< Load Config Directory in the Windows 8 version */
LOAD_CONFIG_W10_VER = 10, /**< Load Config Directory in the Windows 10 version */
LOAD_CONFIG_UNK_VER = -1 /**< Load Config Directory in an unknown version */
} t_load_config_ver;
} t_load_config_ver;
/**
Get a pointer to the Load Config Directory within the given PE.
\param buffer : a buffer containing the PE file in a Virtual format
\param buf_size : size of the buffer
\return a pointer to the Load Config Directory, NULL if the given PE does not have this directory
*/
BYTE* get_load_config_ptr(BYTE* buffer, size_t buf_size);
/**
Get a pointer to the Load Config Directory within the given PE.
\param buffer : a buffer containing the PE file in a Virtual format
\param buf_size : size of the buffer
\return a pointer to the Load Config Directory, NULL if the given PE does not have this directory
*/
BYTE* get_load_config_ptr(BYTE* buffer, size_t buf_size);
/**
Detect which version of Load Config Directory was used in the given PE.
\param buffer : a buffer containing the PE file in a Virtual format
\param buf_size : size of the buffer
\param ld_config_ptr : pointer to the Load Config Directory within the given PE
\return detected version of Load Config Directory
*/
t_load_config_ver get_load_config_version(BYTE* buffer, size_t buf_size, BYTE* ld_config_ptr);
/**
Detect which version of Load Config Directory was used in the given PE.
\param buffer : a buffer containing the PE file in a Virtual format
\param buf_size : size of the buffer
\param ld_config_ptr : pointer to the Load Config Directory within the given PE
\return detected version of Load Config Directory
*/
t_load_config_ver get_load_config_version(BYTE* buffer, size_t buf_size, BYTE* ld_config_ptr);
}; // namespace peconv

View File

@@ -8,42 +8,43 @@
#include <windows.h>
#include "exports_mapper.h"
namespace peconv {
namespace peconv
{
/**
A mode in which the PE fille be dumped.
*/
typedef enum {
/**
A mode in which the PE fille be dumped.
*/
typedef enum {
PE_DUMP_AUTO = 0, /**< autodetect which dump mode is the most suitable for the given input */
PE_DUMP_VIRTUAL,/**< dump as it is in the memory (virtual) */
PE_DUMP_UNMAP, /**< convert to the raw format: using raw sections' headers */
PE_DUMP_REALIGN, /**< convert to the raw format: by realigning raw sections' headers to be the same as virtual (useful if the PE was unpacked in memory) */
PE_DUMP_MODES_COUNT /**< total number of the dump modes */
} t_pe_dump_mode;
} t_pe_dump_mode;
/**
Detect dump mode that is the most suitable for the given input.
\param buffer : the buffer containing the PE to be dumped.
\param buffer_size : the size of the given buffer
*/
t_pe_dump_mode detect_dump_mode(IN const BYTE* buffer, IN size_t buffer_size);
/**
Detect dump mode that is the most suitable for the given input.
\param buffer : the buffer containing the PE to be dumped.
\param buffer_size : the size of the given buffer
*/
t_pe_dump_mode detect_dump_mode(IN const BYTE* buffer, IN size_t buffer_size);
/**
Dumps PE from the fiven buffer into a file. It expects the module base and size to be given.
\param outputFilePath : name of the file where the dump should be saved
\param buffer : the buffer containing the PE to be dumped. WARNING: the buffer may be preprocessed before dumping.
\param buffer_size : the size of the given buffer
\param module_base : the base to which the PE buffer was relocated
\param dump_mode : specifies in which format the PE should be dumped. If the mode was set to PE_DUMP_AUTO, it autodetects mode and returns the detected one.
\param exportsMap : optional. If exportsMap is supplied, it will try to recover destroyed import table of the PE, basing on the supplied map of exported functions.
*/
bool dump_pe(
/**
Dumps PE from the fiven buffer into a file. It expects the module base and size to be given.
\param outputFilePath : name of the file where the dump should be saved
\param buffer : the buffer containing the PE to be dumped. WARNING: the buffer may be preprocessed before dumping.
\param buffer_size : the size of the given buffer
\param module_base : the base to which the PE buffer was relocated
\param dump_mode : specifies in which format the PE should be dumped. If the mode was set to PE_DUMP_AUTO, it autodetects mode and returns the detected one.
\param exportsMap : optional. If exportsMap is supplied, it will try to recover destroyed import table of the PE, basing on the supplied map of exported functions.
*/
bool dump_pe(
IN LPCTSTR outputFilePath,
IN OUT BYTE* buffer,
IN size_t buffer_size,
IN const ULONGLONG module_base,
IN OUT t_pe_dump_mode &dump_mode,
IN OPTIONAL const peconv::ExportsMapper* exportsMap = nullptr
);
);
};// namespace peconv

View File

@@ -12,15 +12,16 @@
#define PAGE_SIZE 0x1000
#endif
namespace peconv {
/**
Maximal size of the PE header.
*/
const ULONGLONG MAX_HEADER_SIZE = PAGE_SIZE;
namespace peconv
{
/**
Maximal size of the PE header.
*/
const ULONGLONG MAX_HEADER_SIZE = PAGE_SIZE;
template <typename INT_TYPE>
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
{
template <typename INT_TYPE>
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
{
if (unit == 0) {
return size;
}
@@ -30,76 +31,76 @@ namespace peconv {
rounded_size += unit;
}
return rounded_size;
}
}
/**
Fetch image size from headers.
*/
DWORD get_image_size(IN const BYTE *payload);
/**
Fetch image size from headers.
*/
DWORD get_image_size(IN const BYTE *payload);
/**
Change the Image Size in Optional Header to the given one.
*/
bool update_image_size(IN OUT BYTE* payload, IN DWORD new_img_size);
/**
Change the Image Size in Optional Header to the given one.
*/
bool update_image_size(IN OUT BYTE* payload, IN DWORD new_img_size);
/**
Fetch architecture from the NT headers. Checks for bad pointers.
*/
WORD get_nt_hdr_architecture(IN const BYTE *pe_buffer);
/**
Fetch architecture from the NT headers. Checks for bad pointers.
*/
WORD get_nt_hdr_architecture(IN const BYTE *pe_buffer);
/**
Wrapper for get_nt_hdr_architecture. Returns true if the PE file is 64 bit.
*/
bool is64bit(IN const BYTE *pe_buffer);
/**
Wrapper for get_nt_hdr_architecture. Returns true if the PE file is 64 bit.
*/
bool is64bit(IN const BYTE *pe_buffer);
/**
Fetch pointer to the NT headers of the PE file.
Checks for bad pointers. If buffer_size is set, validates pointers against the buffer size.
*/
BYTE* get_nt_hdrs(
/**
Fetch pointer to the NT headers of the PE file.
Checks for bad pointers. If buffer_size is set, validates pointers against the buffer size.
*/
BYTE* get_nt_hdrs(
IN const BYTE *pe_buffer,
IN OPTIONAL size_t buffer_size=0 //if buffer_size=0 means size unknown
);
);
/**
Wrapper for get_nt_headers. Automatically detects if the PE is 32 bit - if not, returns null pointer.
*/
IMAGE_NT_HEADERS32* get_nt_hdrs32(IN const BYTE *pe_buffer);
/**
Wrapper for get_nt_headers. Automatically detects if the PE is 32 bit - if not, returns null pointer.
*/
IMAGE_NT_HEADERS32* get_nt_hdrs32(IN const BYTE *pe_buffer);
/**
Wrapper for get_nt_headers. Automatically detects if the PE is 64 bit - if not, returns null pointer.
*/
IMAGE_NT_HEADERS64* get_nt_hdrs64(IN const BYTE *pe_buffer);
/**
Wrapper for get_nt_headers. Automatically detects if the PE is 64 bit - if not, returns null pointer.
*/
IMAGE_NT_HEADERS64* get_nt_hdrs64(IN const BYTE *pe_buffer);
/**
Fetches optional header of the PE. Validates pointers against buffer size.
*/
LPVOID get_optional_hdr(IN const BYTE* payload, IN const size_t buffer_size);
/**
Fetches optional header of the PE. Validates pointers against buffer size.
*/
LPVOID get_optional_hdr(IN const BYTE* payload, IN const size_t buffer_size);
/**
Fetches file header of the PE. Validates pointers against buffer size.
*/
const IMAGE_FILE_HEADER* get_file_hdr(
/**
Fetches file header of the PE. Validates pointers against buffer size.
*/
const IMAGE_FILE_HEADER* get_file_hdr(
IN const BYTE* payload,
IN const size_t buffer_size
);
);
/**
Fetch the size of headers (from Optional Header).
*/
DWORD get_hdrs_size(IN const BYTE *pe_buffer);
/**
Fetch the size of headers (from Optional Header).
*/
DWORD get_hdrs_size(IN const BYTE *pe_buffer);
/**
get Data Directory entry of the given number. If the entry is not filled and allow_empty is not set, it returns null pointer.
*/
IMAGE_DATA_DIRECTORY* get_directory_entry(IN const BYTE* pe_buffer, IN DWORD dir_id, IN bool allow_empty = false);
/**
get Data Directory entry of the given number. If the entry is not filled and allow_empty is not set, it returns null pointer.
*/
IMAGE_DATA_DIRECTORY* get_directory_entry(IN const BYTE* pe_buffer, IN DWORD dir_id, IN bool allow_empty = false);
/**
Get pointer to the Data Directory content of the given number. Automatically cast to the chosen type.
*/
template <typename IMAGE_TYPE_DIRECTORY>
IMAGE_TYPE_DIRECTORY* get_type_directory(IN HMODULE modulePtr, IN DWORD dir_id)
{
/**
Get pointer to the Data Directory content of the given number. Automatically cast to the chosen type.
*/
template <typename IMAGE_TYPE_DIRECTORY>
IMAGE_TYPE_DIRECTORY* get_type_directory(IN HMODULE modulePtr, IN DWORD dir_id)
{
IMAGE_DATA_DIRECTORY *my_dir = peconv::get_directory_entry((const BYTE*)modulePtr, dir_id);
if (!my_dir) return nullptr;
@@ -107,142 +108,142 @@ namespace peconv {
if (dir_addr == 0) return nullptr;
return (IMAGE_TYPE_DIRECTORY*)(dir_addr + (ULONG_PTR)modulePtr);
}
}
/**
Get pointer to the Export Directory.
*/
IMAGE_EXPORT_DIRECTORY* get_export_directory(IN HMODULE modulePtr);
/**
Get pointer to the Export Directory.
*/
IMAGE_EXPORT_DIRECTORY* get_export_directory(IN HMODULE modulePtr);
// Fetch Image Base from Optional Header.
ULONGLONG get_image_base(IN const BYTE *pe_buffer);
// Fetch Image Base from Optional Header.
ULONGLONG get_image_base(IN const BYTE *pe_buffer);
/**
Change the Image Base in Optional Header to the given one.
*/
bool update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase);
/**
Change the Image Base in Optional Header to the given one.
*/
bool update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase);
/**
Get RVA of the Entry Point from the Optional Header.
*/
DWORD get_entry_point_rva(IN const BYTE *pe_buffer);
/**
Get RVA of the Entry Point from the Optional Header.
*/
DWORD get_entry_point_rva(IN const BYTE *pe_buffer);
/**
Change the Entry Point RVA in the Optional Header to the given one.
*/
bool update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD ep);
/**
Change the Entry Point RVA in the Optional Header to the given one.
*/
bool update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD ep);
/**
Get number of sections from the File Header. It does not validate if this the actual number.
*/
size_t get_sections_count(
/**
Get number of sections from the File Header. It does not validate if this the actual number.
*/
size_t get_sections_count(
IN const BYTE* buffer,
IN const size_t buffer_size
);
);
/**
Checks if the section headers are reachable. It does not validate sections alignment.
*/
bool is_valid_sections_hdr_offset(IN const BYTE* buffer, IN const size_t buffer_size);
/**
Checks if the section headers are reachable. It does not validate sections alignment.
*/
bool is_valid_sections_hdr_offset(IN const BYTE* buffer, IN const size_t buffer_size);
/**
Gets pointer to the section header of the given number.
*/
PIMAGE_SECTION_HEADER get_section_hdr(
/**
Gets pointer to the section header of the given number.
*/
PIMAGE_SECTION_HEADER get_section_hdr(
IN const BYTE* pe_buffer,
IN const size_t buffer_size,
IN size_t section_num
);
);
/**
Fetch the PE Characteristics from the File Header.
*/
WORD get_file_characteristics(IN const BYTE* payload);
/**
Fetch the PE Characteristics from the File Header.
*/
WORD get_file_characteristics(IN const BYTE* payload);
/**
Check if the module is a DLL (basing on the Characteristcs in the header).
*/
bool is_module_dll(IN const BYTE* payload);
/**
Check if the module is a DLL (basing on the Characteristcs in the header).
*/
bool is_module_dll(IN const BYTE* payload);
/**
Check if the module is a .NET executable
*/
bool is_dot_net(BYTE *pe_buffer, size_t pe_buffer_size);
/**
Check if the module is a .NET executable
*/
bool is_dot_net(BYTE *pe_buffer, size_t pe_buffer_size);
/**
Fetch the DLL Characteristics from the Optional Header.
*/
WORD get_dll_characteristics(IN const BYTE* payload);
/**
Fetch the DLL Characteristics from the Optional Header.
*/
WORD get_dll_characteristics(IN const BYTE* payload);
/**
Set the PE subsystem in the header.
*/
bool set_subsystem(IN OUT BYTE* payload, IN WORD subsystem);
/**
Set the PE subsystem in the header.
*/
bool set_subsystem(IN OUT BYTE* payload, IN WORD subsystem);
/**
Get the PE subsystem from the header.
*/
WORD get_subsystem(IN const BYTE* payload);
/**
Get the PE subsystem from the header.
*/
WORD get_subsystem(IN const BYTE* payload);
/**
Check if the PE has relocations Data Directory.
*/
bool has_relocations(IN const BYTE *pe_buffer);
/**
Check if the PE has relocations Data Directory.
*/
bool has_relocations(IN const BYTE *pe_buffer);
/**
Fetch the pointer to the .NET header (if exist).
*/
IMAGE_COR20_HEADER* get_dotnet_hdr(
/**
Fetch the pointer to the .NET header (if exist).
*/
IMAGE_COR20_HEADER* get_dotnet_hdr(
IN const BYTE* pe_buffer,
IN size_t const buffer_size,
IN const IMAGE_DATA_DIRECTORY* dotNetDir
);
);
/**
Fetch section aligmenent from headers. Depending on the flag, it fetches either Raw Alignment or Virtual Alignment.
*/
DWORD get_sec_alignment(IN const BYTE* modulePtr, IN bool is_raw);
/**
Fetch section aligmenent from headers. Depending on the flag, it fetches either Raw Alignment or Virtual Alignment.
*/
DWORD get_sec_alignment(IN const BYTE* modulePtr, IN bool is_raw);
/**
Change section aligmenent in headers. Depending on the flag, it sets either Raw Alignment or Virtual Alignment.
*/
bool set_sec_alignment(IN OUT BYTE* pe_buffer, IN bool is_raw, IN DWORD new_alignment);
/**
Change section aligmenent in headers. Depending on the flag, it sets either Raw Alignment or Virtual Alignment.
*/
bool set_sec_alignment(IN OUT BYTE* pe_buffer, IN bool is_raw, IN DWORD new_alignment);
/**
Get size of virtual section from the headers (optionaly rounds it up to the Virtual Alignment)
*/
DWORD get_virtual_sec_size(
/**
Get size of virtual section from the headers (optionaly rounds it up to the Virtual Alignment)
*/
DWORD get_virtual_sec_size(
IN const BYTE* pe_hdr,
IN const PIMAGE_SECTION_HEADER sec_hdr,
IN bool rounded //if set, it rounds it up to the Virtual Alignment
);
);
/**
Get the last section (in a raw or virtual alignment)
\param pe_buffer : buffer with a PE
\param pe_size : size of the given PE
\param is_raw : If true, give the section with the highest Raw offset. If false, give the section with the highest Virtual offset.
*/
PIMAGE_SECTION_HEADER get_last_section(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw);
/**
Get the last section (in a raw or virtual alignment)
\param pe_buffer : buffer with a PE
\param pe_size : size of the given PE
\param is_raw : If true, give the section with the highest Raw offset. If false, give the section with the highest Virtual offset.
*/
PIMAGE_SECTION_HEADER get_last_section(IN const PBYTE pe_buffer, IN size_t pe_size, IN bool is_raw);
/**
Calculate full PE size (raw or virtual) using information from sections' headers. WARNING: it drops an overlay.
\param pe_buffer : a buffer containing a PE
\param pe_size : the size of the given buffer
\param is_raw : If true, the Raw alignment is used. If false, the Virtual alignment is used.
*/
DWORD calc_pe_size(
/**
Calculate full PE size (raw or virtual) using information from sections' headers. WARNING: it drops an overlay.
\param pe_buffer : a buffer containing a PE
\param pe_size : the size of the given buffer
\param is_raw : If true, the Raw alignment is used. If false, the Virtual alignment is used.
*/
DWORD calc_pe_size(
IN const PBYTE pe_buffer,
IN size_t pe_size,
IN bool is_raw
);
);
/**
Walk through sections headers checking if the sections beginnings and sizes are fitting the alignment (Virtual or Raw)
\param buffer : a buffer containing a PE
\param buffer_size : the size of the given buffer
\param is_raw : If true, the Raw alignment is checked. If false, the Virtual alignment is checked.
*/
bool is_valid_sectons_alignment(IN const BYTE* buffer, IN const SIZE_T buffer_size, IN bool is_raw);
/**
Walk through sections headers checking if the sections beginnings and sizes are fitting the alignment (Virtual or Raw)
\param buffer : a buffer containing a PE
\param buffer_size : the size of the given buffer
\param is_raw : If true, the Raw alignment is checked. If false, the Virtual alignment is checked.
*/
bool is_valid_sectons_alignment(IN const BYTE* buffer, IN const SIZE_T buffer_size, IN bool is_raw);
}; // namespace peconv

View File

@@ -8,35 +8,36 @@
#include "pe_raw_to_virtual.h"
#include "function_resolver.h"
namespace peconv {
/**
Reads PE from the given buffer into memory and maps it into virtual format.
(Automatic raw to virtual conversion).
If the executable flag is true, the PE file is loaded into executable memory.
If the relocate flag is true, applies relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_buffer.
*/
BYTE* load_pe_module(BYTE* payload_raw, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base = 0);
namespace peconv
{
/**
Reads PE from the given buffer into memory and maps it into virtual format.
(Automatic raw to virtual conversion).
If the executable flag is true, the PE file is loaded into executable memory.
If the relocate flag is true, applies relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_buffer.
*/
BYTE* load_pe_module(BYTE* payload_raw, size_t r_size, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base = 0);
/**
Reads PE from the given file into memory and maps it into vitual format.
(Automatic raw to virtual conversion).
If the executable flag is true, the PE file is loaded into executable memory.
If the relocate flag is true, applies relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_buffer.
*/
BYTE* load_pe_module(LPCTSTR filename, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base = 0);
/**
Reads PE from the given file into memory and maps it into vitual format.
(Automatic raw to virtual conversion).
If the executable flag is true, the PE file is loaded into executable memory.
If the relocate flag is true, applies relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_buffer.
*/
BYTE* load_pe_module(LPCTSTR filename, OUT size_t &v_size, bool executable, bool relocate, ULONG_PTR desired_base = 0);
/**
Loads full PE from the raw buffer in a way in which it can be directly executed: remaps to virual format, applies relocations, loads imports.
Allows for supplying custom function resolver.
*/
BYTE* load_pe_executable(BYTE* payload_raw, size_t r_size, OUT size_t &v_size, t_function_resolver* import_resolver = nullptr, ULONG_PTR desired_base = 0);
/**
Loads full PE from the raw buffer in a way in which it can be directly executed: remaps to virual format, applies relocations, loads imports.
Allows for supplying custom function resolver.
*/
BYTE* load_pe_executable(BYTE* payload_raw, size_t r_size, OUT size_t &v_size, t_function_resolver* import_resolver = nullptr, ULONG_PTR desired_base = 0);
/**
Loads full PE from file in a way in which it can be directly executed: remaps to virtual format, applies relocations, loads imports.
Allows for supplying custom function resolver.
*/
BYTE* load_pe_executable(LPCTSTR filename, OUT size_t &v_size, t_function_resolver* import_resolver = nullptr);
/**
Loads full PE from file in a way in which it can be directly executed: remaps to virtual format, applies relocations, loads imports.
Allows for supplying custom function resolver.
*/
BYTE* load_pe_executable(LPCTSTR filename, OUT size_t &v_size, t_function_resolver* import_resolver = nullptr);
};// namespace peconv

View File

@@ -9,36 +9,37 @@
#include "pe_hdrs_helper.h"
namespace peconv {
namespace peconv
{
/**
check if the PE in the memory is in raw format
*/
bool is_pe_raw(
/**
check if the PE in the memory is in raw format
*/
bool is_pe_raw(
IN const BYTE* pe_buffer,
IN size_t pe_size
);
);
/**
check if Virtual section addresses are identical to Raw addresses (i.e. if the PE was realigned)
*/
bool is_pe_raw_eq_virtual(
/**
check if Virtual section addresses are identical to Raw addresses (i.e. if the PE was realigned)
*/
bool is_pe_raw_eq_virtual(
IN const BYTE* pe_buffer,
IN size_t pe_size
);
);
/**
checks if the PE has sections that were unpacked/expanded in the memory
*/
bool is_pe_expanded(
/**
checks if the PE has sections that were unpacked/expanded in the memory
*/
bool is_pe_expanded(
IN const BYTE* pe_buffer,
IN size_t pe_size
);
);
/**
checks if the given section was unpacked in the memory
*/
bool is_section_expanded(IN const BYTE* pe_buffer,
/**
checks if the given section was unpacked in the memory
*/
bool is_section_expanded(IN const BYTE* pe_buffer,
IN size_t pe_size,
IN const PIMAGE_SECTION_HEADER sec
);

View File

@@ -10,21 +10,22 @@
#include "buffer_util.h"
namespace peconv {
namespace peconv
{
/**
Converts a raw PE supplied in a buffer to a virtual format.
If the executable flag is true (default), the PE file is loaded into executable memory.
Does not apply relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_module.
If the desired_base is defined (0 by default), it enforces allocation at the particular base.
*/
BYTE* pe_raw_to_virtual(
/**
Converts a raw PE supplied in a buffer to a virtual format.
If the executable flag is true (default), the PE file is loaded into executable memory.
Does not apply relocations. Does not load imports.
Automatically allocates buffer of the needed size (the size is returned in outputSize). The buffer can be freed by the function free_pe_module.
If the desired_base is defined (0 by default), it enforces allocation at the particular base.
*/
BYTE* pe_raw_to_virtual(
IN const BYTE* rawPeBuffer,
IN size_t rawPeSize,
OUT size_t &outputSize,
IN OPTIONAL bool executable = true,
IN OPTIONAL ULONG_PTR desired_base = 0
);
);
}; // namespace peconv

View File

@@ -9,39 +9,40 @@
#include "buffer_util.h"
namespace peconv {
namespace peconv
{
/**
Maps virtual image of PE to into raw. Automaticaly applies relocations.
Automatically allocates buffer of the needed size (the size is returned in outputSize).
\param payload : the PE in the Virtual format that needs to be converted into the Raw format
\param in_size : size of the input buffer (the PE in the Virtual format)
\param loadBase : the base to which the given PE was relocated
\param outputSize : the size of the output buffer (the PE in the Raw format)
\param rebuffer : if set (default), the input buffer is rebuffered and the original buffer is not modified.
\return a buffer of the outputSize, containing the Raw PE. The buffer can be freed by the function free_pe_module.
*/
BYTE* pe_virtual_to_raw(
/**
Maps virtual image of PE to into raw. Automaticaly applies relocations.
Automatically allocates buffer of the needed size (the size is returned in outputSize).
\param payload : the PE in the Virtual format that needs to be converted into the Raw format
\param in_size : size of the input buffer (the PE in the Virtual format)
\param loadBase : the base to which the given PE was relocated
\param outputSize : the size of the output buffer (the PE in the Raw format)
\param rebuffer : if set (default), the input buffer is rebuffered and the original buffer is not modified.
\return a buffer of the outputSize, containing the Raw PE. The buffer can be freed by the function free_pe_module.
*/
BYTE* pe_virtual_to_raw(
IN BYTE* payload,
IN size_t in_size,
IN ULONGLONG loadBase,
OUT size_t &outputSize,
IN OPTIONAL bool rebuffer=true
);
);
/*
Modifies raw alignment of the PE to be the same as virtual alignment.
\param payload : the PE in the Virtual format that needs to be realigned
\param in_size : size of the input buffer
\param loadBase : the base to which the given PE was relocated
\param outputSize : the size of the output buffer (the PE in the Raw format)
\return a buffer of the outputSize, containing the realigned PE. The buffer can be freed by the function free_pe_module.
*/
BYTE* pe_realign_raw_to_virtual(
/*
Modifies raw alignment of the PE to be the same as virtual alignment.
\param payload : the PE in the Virtual format that needs to be realigned
\param in_size : size of the input buffer
\param loadBase : the base to which the given PE was relocated
\param outputSize : the size of the output buffer (the PE in the Raw format)
\return a buffer of the outputSize, containing the realigned PE. The buffer can be freed by the function free_pe_module.
*/
BYTE* pe_realign_raw_to_virtual(
IN const BYTE* payload,
IN size_t in_size,
IN ULONGLONG loadBase,
OUT size_t &outputSize
);
);
};//namespace peconv

View File

@@ -7,34 +7,35 @@
#include <windows.h>
namespace peconv {
namespace peconv
{
/**
Gets handle to the given module via PEB. A low-level equivalent of `GetModuleHandleW`.
\param module_name : (optional) the name of the DLL loaded within the current process. If not set, the main module of the current process is used.
\return the handle of the DLL with given name, or, if the name was not given, the handle of the main module of the current process.
*/
HMODULE get_module_via_peb(IN OPTIONAL LPCWSTR module_name = nullptr);
/**
Gets handle to the given module via PEB. A low-level equivalent of `GetModuleHandleW`.
\param module_name : (optional) the name of the DLL loaded within the current process. If not set, the main module of the current process is used.
\return the handle of the DLL with given name, or, if the name was not given, the handle of the main module of the current process.
*/
HMODULE get_module_via_peb(IN OPTIONAL LPCWSTR module_name = nullptr);
/**
Gets size of the given module via PEB.
\param hModule : (optional) the base of the module which's size we want to retrieve. If not set, the main module of the current process is used.
\return the size of the given module.
*/
size_t get_module_size_via_peb(IN OPTIONAL HMODULE hModule = nullptr);
/**
Gets size of the given module via PEB.
\param hModule : (optional) the base of the module which's size we want to retrieve. If not set, the main module of the current process is used.
\return the size of the given module.
*/
size_t get_module_size_via_peb(IN OPTIONAL HMODULE hModule = nullptr);
/**
Sets the given module as the main module in the current PEB.
\param hModule : the module to be connected to the current PEB.
\return true if succeeded, false if failed
*/
bool set_main_module_in_peb(HMODULE hModule);
/**
Sets the given module as the main module in the current PEB.
\param hModule : the module to be connected to the current PEB.
\return true if succeeded, false if failed
*/
bool set_main_module_in_peb(HMODULE hModule);
/**
Gets the main module from the current PEB.
\return the main module connected to the current PEB.
*/
HMODULE get_main_module_via_peb();
/**
Gets the main module from the current PEB.
\return the main module connected to the current PEB.
*/
HMODULE get_main_module_via_peb();
};

View File

@@ -7,16 +7,17 @@
#include <windows.h>
namespace peconv {
namespace peconv
{
typedef struct _BASE_RELOCATION_ENTRY {
typedef struct _BASE_RELOCATION_ENTRY {
WORD Offset : 12;
WORD Type : 4;
} BASE_RELOCATION_ENTRY;
} BASE_RELOCATION_ENTRY;
class RelocBlockCallback
{
public:
class RelocBlockCallback
{
public:
RelocBlockCallback(bool _is64bit)
: is64bit(_is64bit)
{
@@ -24,28 +25,28 @@ namespace peconv {
virtual bool processRelocField(ULONG_PTR relocField) = 0;
protected:
protected:
bool is64bit;
};
};
// Processs the relocation table and make your own callback on each relocation field
bool process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback);
// Processs the relocation table and make your own callback on each relocation field
bool process_relocation_table(IN PVOID modulePtr, IN SIZE_T moduleSize, IN RelocBlockCallback *callback);
/**
/**
Applies relocations on the PE in virtual format. Relocates it from the old base given to the new base given.
If 0 was supplied as the old base, it assumes that the old base is the ImageBase given in the header.
\param modulePtr : a buffer containing the PE to be relocated
\param moduleSize : the size of the given PE buffer
\param newBase : a base to which the PE should be relocated
\param oldBase : a base to which the PE is currently relocated (if not set, the imageBase from the header will be used)
*/
bool relocate_module(IN BYTE* modulePtr, IN SIZE_T moduleSize, IN ULONGLONG newBase, IN ULONGLONG oldBase = 0);
*/
bool relocate_module(IN BYTE* modulePtr, IN SIZE_T moduleSize, IN ULONGLONG newBase, IN ULONGLONG oldBase = 0);
/**
Checks if the given PE has a valid relocations table.
\param modulePtr : a buffer containing the PE to be checked
\param moduleSize : the size of the given PE buffer
*/
bool has_valid_relocation_table(IN const PBYTE modulePtr, IN const size_t moduleSize);
/**
Checks if the given PE has a valid relocations table.
\param modulePtr : a buffer containing the PE to be checked
\param moduleSize : the size of the given PE buffer
*/
bool has_valid_relocation_table(IN const PBYTE modulePtr, IN const size_t moduleSize);
};//namespace peconv

View File

@@ -12,123 +12,124 @@
#include "exports_mapper.h"
#include "pe_dumper.h"
namespace peconv {
namespace peconv
{
bool fetch_region_info(HANDLE processHandle, LPVOID start_addr, MEMORY_BASIC_INFORMATION &page_info);
bool fetch_region_info(HANDLE processHandle, LPVOID start_addr, MEMORY_BASIC_INFORMATION &page_info);
/**
Fetch size of the memory region starting from the given address.
*/
size_t fetch_region_size(HANDLE processHandle, LPVOID start_addr);
/**
Fetch size of the memory region starting from the given address.
*/
size_t fetch_region_size(HANDLE processHandle, LPVOID start_addr);
/**
Fetch the allocation base of the memory region with the supplied start address.
\param processHandle : handle of the process where the region of interest belongs
\param start_addr : the address inside the region of interest
\return the allocation base address of the memory region, or 0 if not found
*/
ULONGLONG fetch_alloc_base(HANDLE processHandle, LPVOID start_addr);
/**
Fetch the allocation base of the memory region with the supplied start address.
\param processHandle : handle of the process where the region of interest belongs
\param start_addr : the address inside the region of interest
\return the allocation base address of the memory region, or 0 if not found
*/
ULONGLONG fetch_alloc_base(HANDLE processHandle, LPVOID start_addr);
/**
Wrapper over ReadProcessMemory. Requires a handle with privilege PROCESS_VM_READ.
If reading of the full buffer_size was not possible, it will keep trying to read a smaller chunk, decreasing requested size on each attempt,
till the minimal_size is reached (it is a workaround for errors such as FAULTY_HARDWARE_CORRUPTED_PAGE).
Returns how many bytes were successfuly read.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer, and the size that will be attempted to read
\param minimal_size : the minimal size that has to be read in order to consider the read successful
\return the number of bytes successfuly read
*/
size_t read_remote_memory(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const SIZE_T minimal_size = 0x100);
/**
Wrapper over ReadProcessMemory. Requires a handle with privilege PROCESS_VM_READ.
If reading of the full buffer_size was not possible, it will keep trying to read a smaller chunk, decreasing requested size on each attempt,
till the minimal_size is reached (it is a workaround for errors such as FAULTY_HARDWARE_CORRUPTED_PAGE).
Returns how many bytes were successfuly read.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer, and the size that will be attempted to read
\param minimal_size : the minimal size that has to be read in order to consider the read successful
\return the number of bytes successfuly read
*/
size_t read_remote_memory(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const SIZE_T minimal_size = 0x100);
/**
Reads a single memory region (continuous, with the same access rights) within a given process, starting at the start_addr.
In case if it is inaccessible, if the flag force_access was set, it tries to force the access by temporarly changing the permissions.
Requires a handle with privilege PROCESS_QUERY_INFORMATION. In order for force_access to work, PROCESS_VM_OPERATION is additionally required.
step_size is passed to the underlying read_remote_memory.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\param minimal_size : the minimal size that has to be read in order to consider the read successful (passed to read_remote_memory)
\return the number of bytes successfuly read
*/
size_t read_remote_region(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size = 0x100);
/**
Reads a single memory region (continuous, with the same access rights) within a given process, starting at the start_addr.
In case if it is inaccessible, if the flag force_access was set, it tries to force the access by temporarly changing the permissions.
Requires a handle with privilege PROCESS_QUERY_INFORMATION. In order for force_access to work, PROCESS_VM_OPERATION is additionally required.
step_size is passed to the underlying read_remote_memory.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\param minimal_size : the minimal size that has to be read in order to consider the read successful (passed to read_remote_memory)
\return the number of bytes successfuly read
*/
size_t read_remote_region(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size = 0x100);
/**
Reads a full memory area within a given process, starting at the start_addr, till the buffer_size is exceeded.
The memory area can consist of multiple regions with various access rights.
In case if the region is inaccessible, if the flag force_access was set, it tries to force the access by temporarly changing the permissions.
On read failure the region is skipped, and the read is moving to the next one, leaving in the output buffer an empty space of the region size.
Requires a handle with privilege PROCESS_QUERY_INFORMATION. In order for force_access to work, PROCESS_VM_OPERATION is additionally required.
step_size is passed to the underlying read_remote_memory.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\param minimal_size : the minimal size that has to be read in order to consider the read successful (passed to read_remote_memory)
\return the number of bytes successfuly read
*/
size_t read_remote_area(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size = 0x100);
/**
Reads a full memory area within a given process, starting at the start_addr, till the buffer_size is exceeded.
The memory area can consist of multiple regions with various access rights.
In case if the region is inaccessible, if the flag force_access was set, it tries to force the access by temporarly changing the permissions.
On read failure the region is skipped, and the read is moving to the next one, leaving in the output buffer an empty space of the region size.
Requires a handle with privilege PROCESS_QUERY_INFORMATION. In order for force_access to work, PROCESS_VM_OPERATION is additionally required.
step_size is passed to the underlying read_remote_memory.
\param processHandle : handle of the process where the memory of interest belongs
\param start_addr : the address within the remote process to start reading from
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\param minimal_size : the minimal size that has to be read in order to consider the read successful (passed to read_remote_memory)
\return the number of bytes successfuly read
*/
size_t read_remote_area(HANDLE processHandle, LPVOID start_addr, OUT BYTE* buffer, const size_t buffer_size, const bool force_access, const SIZE_T minimal_size = 0x100);
/**
Reads a PE header of the remote module within the given process. Requires a valid output buffer to be supplied (buffer).
\param processHandle : handle of the process where the memory of interest belongs
\param moduleBase : the base address of the module within the remote process
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
*/
bool read_remote_pe_header(HANDLE processHandle, LPVOID moduleBase, OUT BYTE* buffer, const size_t bufferSize, bool force_access = false);
/**
Reads a PE header of the remote module within the given process. Requires a valid output buffer to be supplied (buffer).
\param processHandle : handle of the process where the memory of interest belongs
\param moduleBase : the base address of the module within the remote process
\param buffer : the buffer where the read data will be stored
\param buffer_size : the size of the buffer
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
*/
bool read_remote_pe_header(HANDLE processHandle, LPVOID moduleBase, OUT BYTE* buffer, const size_t bufferSize, bool force_access = false);
/**
Reads a PE section with a given number (sectionNum) from the remote module within the given process.
The buffer of appropriate size is automatically allocated. After use, it should be freed by the function free_unaligned.
The size of the buffer is writen into sectionSize.
\param processHandle : the handle to the remote process
\param moduleBase : the base address of the module
\param sectionNum : number of the section to be read
\param sectionSize : the size of the read section (output)
\param roundup : if set, the section size is roundup to the alignment unit
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\return a buffer containing a copy of the section.
*/
peconv::UNALIGNED_BUF get_remote_pe_section(HANDLE processHandle, LPVOID moduleBase, const size_t sectionNum, OUT size_t &sectionSize, bool roundup, bool force_access = false);
/**
Reads a PE section with a given number (sectionNum) from the remote module within the given process.
The buffer of appropriate size is automatically allocated. After use, it should be freed by the function free_unaligned.
The size of the buffer is writen into sectionSize.
\param processHandle : the handle to the remote process
\param moduleBase : the base address of the module
\param sectionNum : number of the section to be read
\param sectionSize : the size of the read section (output)
\param roundup : if set, the section size is roundup to the alignment unit
\param force_access : if this flag is set, in case if the region is inaccassible (PAGE_NOACCESS) it will try to force the the read by changing the permissions, and applying the old ones back after reading.
WARNING: force_access should be used only on a suspended process, or a process relection, otherwise it may cause instability.
\return a buffer containing a copy of the section.
*/
peconv::UNALIGNED_BUF get_remote_pe_section(HANDLE processHandle, LPVOID moduleBase, const size_t sectionNum, OUT size_t &sectionSize, bool roundup, bool force_access = false);
/**
Reads PE file from the remote process into the supplied buffer. It expects the module base and size to be given.
*/
size_t read_remote_pe(const HANDLE processHandle, LPVOID moduleBase, const size_t moduleSize, OUT BYTE* buffer, const size_t bufferSize);
/**
Reads PE file from the remote process into the supplied buffer. It expects the module base and size to be given.
*/
size_t read_remote_pe(const HANDLE processHandle, LPVOID moduleBase, const size_t moduleSize, OUT BYTE* buffer, const size_t bufferSize);
/**
Dumps PE from the remote process into a file. It expects the module base and size to be given.
\param outputFilePath : the path where the dump will be saved
\param processHandle : the handle to the remote process
\param moduleBase : the base address of the module that needs to be dumped
\param dump_mode : specifies in which format the PE should be dumped. If the mode was set to PE_DUMP_AUTO, it autodetects mode and returns the detected one.
\param exportsMap : optional. If exportsMap is supplied, it will try to recover destroyed import table of the PE, basing on the supplied map of exported functions.
*/
bool dump_remote_pe(
/**
Dumps PE from the remote process into a file. It expects the module base and size to be given.
\param outputFilePath : the path where the dump will be saved
\param processHandle : the handle to the remote process
\param moduleBase : the base address of the module that needs to be dumped
\param dump_mode : specifies in which format the PE should be dumped. If the mode was set to PE_DUMP_AUTO, it autodetects mode and returns the detected one.
\param exportsMap : optional. If exportsMap is supplied, it will try to recover destroyed import table of the PE, basing on the supplied map of exported functions.
*/
bool dump_remote_pe(
IN LPCTSTR outputFilePath,
IN const HANDLE processHandle,
IN LPVOID moduleBase,
IN OUT t_pe_dump_mode &dump_mode,
IN OPTIONAL peconv::ExportsMapper* exportsMap = nullptr
);
);
/**
Retrieve the Image Size saved in the header of the remote PE.
\param processHandle : process from where we are reading
\param start_addr : a base address of the PE within the given process
*/
DWORD get_remote_image_size(IN const HANDLE processHandle, IN LPVOID start_addr);
/**
Retrieve the Image Size saved in the header of the remote PE.
\param processHandle : process from where we are reading
\param start_addr : a base address of the PE within the given process
*/
DWORD get_remote_image_size(IN const HANDLE processHandle, IN LPVOID start_addr);
}; //namespace peconv

View File

@@ -6,20 +6,21 @@
#pragma once
#include <windows.h>
namespace peconv {
/**
A callback that will be executed by the function parse_resources when the Resource Entry was found.
*/
typedef bool(*t_on_res_entry_found) (
namespace peconv
{
/**
A callback that will be executed by the function parse_resources when the Resource Entry was found.
*/
typedef bool(*t_on_res_entry_found) (
BYTE* modulePtr,
IMAGE_RESOURCE_DIRECTORY_ENTRY *root_dir,
IMAGE_RESOURCE_DATA_ENTRY *curr_entry
);
);
/**
A function walking through the Resource Tree of the given PE. On each Resource Entry found, the callback is executed.
\param modulePtr : pointer to the buffer with the PE in a Virtual format
\param on_entry : a callback function executed on each Resource Entry
*/
bool parse_resources(BYTE* modulePtr, t_on_res_entry_found on_entry);
/**
A function walking through the Resource Tree of the given PE. On each Resource Entry found, the callback is executed.
\param modulePtr : pointer to the buffer with the PE in a Virtual format
\param on_entry : a callback function executed on each Resource Entry
*/
bool parse_resources(BYTE* modulePtr, t_on_res_entry_found on_entry);
};

View File

@@ -8,27 +8,28 @@
#include <windows.h>
#include "buffer_util.h"
namespace peconv {
namespace peconv
{
const LPSTR RT_RCDATA_A = MAKEINTRESOURCEA(10);
const LPSTR RT_RCDATA_A = MAKEINTRESOURCEA(10);
/**
Maps a resource with the given id + type and copies its raw content into the output buffer.
If out_size is not zero, it reads maximum out_size of bytes. If out_size is zero, it reads the full resource.
The actual read size is returned back in out_size.
Automatically allocates a buffer of the required size.
If hInstance is NULL, it search the resource in the current module. Otherwise, it search in the given module.
*/
peconv::ALIGNED_BUF load_resource_data(OUT size_t &out_size, const int res_id, const LPSTR res_type = RT_RCDATA_A, HMODULE hInstance = nullptr);
/**
Maps a resource with the given id + type and copies its raw content into the output buffer.
If out_size is not zero, it reads maximum out_size of bytes. If out_size is zero, it reads the full resource.
The actual read size is returned back in out_size.
Automatically allocates a buffer of the required size.
If hInstance is NULL, it search the resource in the current module. Otherwise, it search in the given module.
*/
peconv::ALIGNED_BUF load_resource_data(OUT size_t &out_size, const int res_id, const LPSTR res_type = RT_RCDATA_A, HMODULE hInstance = nullptr);
/**
Free the buffer with PE Resources, mapped by the function load_resource_data.
*/
void free_resource_data(peconv::ALIGNED_BUF buffer);
/**
Free the buffer with PE Resources, mapped by the function load_resource_data.
*/
void free_resource_data(peconv::ALIGNED_BUF buffer);
/**
a helper function to get the module handle of the current DLL
*/
HMODULE get_current_module_handle();
/**
a helper function to get the module handle of the current DLL
*/
HMODULE get_current_module_handle();
}; //namespace peconv

View File

@@ -8,34 +8,35 @@
#include <windows.h>
#include<vector>
namespace peconv {
namespace peconv
{
/**
A helper function, normalizing virtual addresses. It automatically detects if the given virtual address is VA or RVA, and converts it into RVA
\param imgBase : the base address to which the module was relocated
\param imgSize : the size of the image
\param virtualAddr : the virtual address (RVA or VA) that we want to convert (within the module described by imgBase and imgSize)
\param outRVA : the output of the conversion (RVA)
\return true if the conversion was successful, false otherwise
*/
bool virtual_addr_to_rva(IN const ULONGLONG imgBase, IN const DWORD imgSize, IN ULONGLONG virtualAddr, OUT DWORD &outRVA);
/**
A helper function, normalizing virtual addresses. It automatically detects if the given virtual address is VA or RVA, and converts it into RVA
\param imgBase : the base address to which the module was relocated
\param imgSize : the size of the image
\param virtualAddr : the virtual address (RVA or VA) that we want to convert (within the module described by imgBase and imgSize)
\param outRVA : the output of the conversion (RVA)
\return true if the conversion was successful, false otherwise
*/
bool virtual_addr_to_rva(IN const ULONGLONG imgBase, IN const DWORD imgSize, IN ULONGLONG virtualAddr, OUT DWORD &outRVA);
/**
A function listing RVAs of all TLS callbacks that are present in the given module.
\param modulePtr : pointer to the buffer with the PE in a Virtual format, relocated to the load base
\param moduleSize : size of the given module (if 0 given, the imageSize from the PE headers will be used)
\param tls_callbacks : a vector of TLS callbacks addresses (as given in the TLS table)
\return number of TLS callbacks added to the list
*/
size_t list_tls_callbacks(IN PVOID modulePtr, IN size_t moduleSize, OUT std::vector<ULONGLONG> &tls_callbacks);
/**
A function listing RVAs of all TLS callbacks that are present in the given module.
\param modulePtr : pointer to the buffer with the PE in a Virtual format, relocated to the load base
\param moduleSize : size of the given module (if 0 given, the imageSize from the PE headers will be used)
\param tls_callbacks : a vector of TLS callbacks addresses (as given in the TLS table)
\return number of TLS callbacks added to the list
*/
size_t list_tls_callbacks(IN PVOID modulePtr, IN size_t moduleSize, OUT std::vector<ULONGLONG> &tls_callbacks);
/**
A function running all the TLS callbacks that are present in the given module, one by one.
\param modulePtr : pointer to the buffer with the PE in a Virtual format, relocated to the load base
\param moduleSize : size of the given module (if 0 given, the imageSize from the PE headers will be used)
\param dwReason : a parameter (dwReason) that will be passed to the callback function
\return number of TLS callbacks executed
*/
size_t run_tls_callbacks(IN PVOID modulePtr, IN size_t moduleSize=0, IN DWORD dwReason = DLL_PROCESS_ATTACH);
/**
A function running all the TLS callbacks that are present in the given module, one by one.
\param modulePtr : pointer to the buffer with the PE in a Virtual format, relocated to the load base
\param moduleSize : size of the given module (if 0 given, the imageSize from the PE headers will be used)
\param dwReason : a parameter (dwReason) that will be passed to the callback function
\return number of TLS callbacks executed
*/
size_t run_tls_callbacks(IN PVOID modulePtr, IN size_t moduleSize=0, IN DWORD dwReason = DLL_PROCESS_ATTACH);
}; //namespace peconv

View File

@@ -19,33 +19,34 @@
#endif
namespace peconv {
/**
Checks if the given buffer is fully filled with the specified character.
\param cave_ptr : pointer to the buffer to be checked
\param cave_size : size of the buffer to be checked
\param padding_char : the required character
*/
bool is_padding(const BYTE* cave_ptr, size_t cave_size, const BYTE padding_char);
namespace peconv
{
/**
Checks if the given buffer is fully filled with the specified character.
\param cave_ptr : pointer to the buffer to be checked
\param cave_size : size of the buffer to be checked
\param padding_char : the required character
*/
bool is_padding(const BYTE* cave_ptr, size_t cave_size, const BYTE padding_char);
/**
Wrapper for GetProcessId - for a backward compatibility with old versions of Windows
*/
DWORD get_process_id(HANDLE hProcess);
/**
Wrapper for GetProcessId - for a backward compatibility with old versions of Windows
*/
DWORD get_process_id(HANDLE hProcess);
/**
Verifies if the calling process has a defined access to the specified continuous range of memory, defined by areaStart and areaSize.
If the area includes pages that are not commited, or pages with access rights PAGE_GUARD | PAGE_NOACCESS, it is treated as inaccessible.
\param areaStart : A pointer to the first byte of the memory block
\param areaSize : The size of the memory block, in bytes. If this parameter is zero, the return value is false.
\param accessRights : The access rights to be checked
*/
bool is_mem_accessible(LPCVOID areaStart, SIZE_T areaSize, DWORD accessRights);
/**
Verifies if the calling process has a defined access to the specified continuous range of memory, defined by areaStart and areaSize.
If the area includes pages that are not commited, or pages with access rights PAGE_GUARD | PAGE_NOACCESS, it is treated as inaccessible.
\param areaStart : A pointer to the first byte of the memory block
\param areaSize : The size of the memory block, in bytes. If this parameter is zero, the return value is false.
\param accessRights : The access rights to be checked
*/
bool is_mem_accessible(LPCVOID areaStart, SIZE_T areaSize, DWORD accessRights);
/**
Verifies that the calling process has read access to the specified range of memory.
\param areaStart : A pointer to the first byte of the memory block
\param areaSize : The size of the memory block, in bytes. If this parameter is zero, the return value is true (bad pointer).
*/
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize);
/**
Verifies that the calling process has read access to the specified range of memory.
\param areaStart : A pointer to the first byte of the memory block
\param areaSize : The size of the memory block, in bytes. If this parameter is zero, the return value is true (bad pointer).
*/
bool is_bad_read_ptr(LPCVOID areaStart, SIZE_T areaSize);
};

View File

@@ -159,8 +159,7 @@ bool is_supported_pe(BYTE *my_exe, size_t exe_size)
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY32>(my_exe, exe_size)) {
has_callback = true;
}
}
else {
} else {
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY64>(my_exe, exe_size)) {
has_callback = true;
}
@@ -218,8 +217,7 @@ int pe_2_shellcode(const std::string &in_path, const std::string &out_str)
ULONGLONG current_base = peconv::get_image_base(ext_buf);
if (peconv::dump_pe(out_str.c_str(), ext_buf, ext_size, current_base, dump_mode)) {
std::cout << "[INFO] Saved as: " << out_str << std::endl;
}
else {
} else {
std::cerr << "[ERROR] Failed to save the output!" << std::endl;
}
peconv::free_pe_buffer(my_exe);
@@ -229,7 +227,8 @@ int pe_2_shellcode(const std::string &in_path, const std::string &out_str)
#else
int pe_2_shellcode(const std::string& in_path, const std::string& out_str) {
int pe_2_shellcode(const std::string& in_path, const std::string& out_str)
{
return -1; // Don't support x86 master program
}

Binary file not shown.

View File

@@ -56,6 +56,7 @@
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -72,6 +73,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DisableSpecificWarnings>4018;4244;4267;4819</DisableSpecificWarnings>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>