mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-21 23:13:08 +08:00
Code style change and rebuild zstd with optimization options
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 §ionSize, 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 §ionSize, 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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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.
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user