Feature: Support converting PE using pe_to_shellcode
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
- [clip v1.11](https://github.com/dacap/clip)
|
||||
- [PrivateDesktop v0.0.1](https://github.com/yuanyuanxiang/SimplePlugins)
|
||||
- [FileUpload v0.0.1](https://github.com/yuanyuanxiang/SimplePlugins)
|
||||
- [libpeconv](https://github.com/hasherezade/libpeconv) (c7d1e48)
|
||||
|
||||
## *Note*
|
||||
|
||||
|
||||
@@ -577,7 +577,8 @@ enum ProtocolEncType {
|
||||
enum ClientCompressType {
|
||||
CLIENT_COMPRESS_NONE = 0,
|
||||
CLIENT_COMPRESS_UPX = 1,
|
||||
CLIENT_COMPRESS_SC = 2,
|
||||
CLIENT_COMPRESS_SC_AES = 2,
|
||||
CLIENT_PE_TO_SEHLLCODE = 3,
|
||||
};
|
||||
|
||||
#pragma pack(push, 4)
|
||||
|
||||
Binary file not shown.
@@ -503,7 +503,8 @@ 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)
|
||||
END_MESSAGE_MAP()
|
||||
ON_COMMAND(ID_TOOL_RELOAD_PLUGINS, &CMy2015RemoteDlg::OnToolReloadPlugins)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
// CMy2015RemoteDlg 消息处理程序
|
||||
@@ -1119,6 +1120,9 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
return FALSE;
|
||||
}
|
||||
THIS_CFG.SetStr("settings", "MainWnd", std::to_string((uint64_t)GetSafeHwnd()));
|
||||
THIS_CFG.SetStr("settings", "SN", getDeviceID());
|
||||
THIS_CFG.SetStr("settings", "PwdHash", GetPwdHash());
|
||||
THIS_CFG.SetStr("settings", "MasterHash", GetMasterHash());
|
||||
|
||||
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
|
||||
}
|
||||
@@ -3739,3 +3743,15 @@ LRESULT CMy2015RemoteDlg::OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CMy2015RemoteDlg::OnToolReloadPlugins()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -346,4 +346,5 @@ public:
|
||||
afx_msg void OnObfsShellcodeBin();
|
||||
afx_msg void OnShellcodeAesBin();
|
||||
afx_msg void OnShellcodeTestAesBin();
|
||||
afx_msg void OnToolReloadPlugins();
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(ProjectDir)libpeconv;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(SolutionDir)..\SimpleRemoter;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@@ -90,7 +90,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(SolutionDir)..\SimpleRemoter;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(ProjectDir)libpeconv;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
@@ -250,6 +250,8 @@
|
||||
<None Include="res\rcedit.exe" />
|
||||
<None Include="res\string.ico" />
|
||||
<None Include="res\upx.exe" />
|
||||
<None Include="stub2\stub32.bin" />
|
||||
<None Include="stub2\stub64.bin" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\client\Audio.h" />
|
||||
@@ -365,6 +367,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="proxy\ProxyConnectServer.cpp" />
|
||||
<ClCompile Include="proxy\ProxyMapDlg.cpp" />
|
||||
<ClCompile Include="pwd_gen.cpp">
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
<ClCompile Include="CGridDialog.cpp" />
|
||||
<ClCompile Include="CWalletDlg.cpp" />
|
||||
<ClCompile Include="CRcEditDlg.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\client\Audio.h" />
|
||||
@@ -203,6 +204,8 @@
|
||||
<None Include="..\..\Release\SCLoader.exe" />
|
||||
<None Include="..\..\x64\Release\SCLoader.exe" />
|
||||
<None Include="res\rcedit.exe" />
|
||||
<None Include="stub2\stub32.bin" />
|
||||
<None Include="stub2\stub64.bin" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\ReadMe.md" />
|
||||
|
||||
@@ -64,6 +64,7 @@ CBuildDlg::CBuildDlg(CWnd* pParent)
|
||||
, m_strPort(_T(""))
|
||||
, m_strFindden(FLAG_FINDEN)
|
||||
, m_sGroupName(_T("default"))
|
||||
, m_strEncryptIP(_T("<EFBFBD><EFBFBD>"))
|
||||
{
|
||||
|
||||
}
|
||||
@@ -95,6 +96,7 @@ BEGIN_MESSAGE_MAP(CBuildDlg, CDialog)
|
||||
ON_CBN_SELCHANGE(IDC_COMBO_EXE, &CBuildDlg::OnCbnSelchangeComboExe)
|
||||
ON_COMMAND(ID_HELP_PARAMETERS, &CBuildDlg::OnHelpParameters)
|
||||
ON_COMMAND(ID_HELP_FINDDEN, &CBuildDlg::OnHelpFindden)
|
||||
ON_COMMAND(ID_MENU_ENCRYPT_IP, &CBuildDlg::OnMenuEncryptIp)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -232,7 +234,8 @@ void CBuildDlg::OnBnClickedOk()
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
return;
|
||||
}
|
||||
if (startup != Startup_InjSC)
|
||||
bool encrypt = m_strEncryptIP == _T("<EFBFBD><EFBFBD>");
|
||||
if (encrypt && startup != Startup_InjSC)
|
||||
g_ConnectAddress.Encrypt();
|
||||
try {
|
||||
// <20><><EFBFBD>±<EFBFBD>ʶ
|
||||
@@ -290,7 +293,7 @@ void CBuildDlg::OnBnClickedOk()
|
||||
run_upx_async(GetParent()->GetSafeHwnd(), upx, strSeverFile.GetString(), true);
|
||||
MessageBox("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>UPXѹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD>\r\n<EFBFBD>ļ<EFBFBD>λ<EFBFBD><EFBFBD>: " + strSeverFile + tip, "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
|
||||
} else {
|
||||
if (m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC) {
|
||||
if (m_ComboCompress.GetCurSel() == CLIENT_COMPRESS_SC_AES) {
|
||||
DWORD dwSize = 0;
|
||||
LPBYTE data = ReadResource(is64bit ? IDR_SCLOADER_X64 : IDR_SCLOADER_X86, dwSize);
|
||||
if (data) {
|
||||
@@ -323,6 +326,12 @@ void CBuildDlg::OnBnClickedOk()
|
||||
}
|
||||
SAFE_DELETE_ARRAY(data);
|
||||
}
|
||||
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);
|
||||
}
|
||||
MessageBox("<EFBFBD><EFBFBD><EFBFBD>ɳɹ<EFBFBD>! <20>ļ<EFBFBD>λ<EFBFBD><CEBB>:\r\n" + strSeverFile + tip, "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
|
||||
}
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
@@ -382,7 +391,8 @@ BOOL CBuildDlg::OnInitDialog()
|
||||
|
||||
m_ComboCompress.InsertString(CLIENT_COMPRESS_NONE, "<EFBFBD><EFBFBD>");
|
||||
m_ComboCompress.InsertString(CLIENT_COMPRESS_UPX, "UPX");
|
||||
m_ComboCompress.InsertString(CLIENT_COMPRESS_SC, "SHELLCODE");
|
||||
m_ComboCompress.InsertString(CLIENT_COMPRESS_SC_AES, "ShellCode AES");
|
||||
m_ComboCompress.InsertString(CLIENT_PE_TO_SEHLLCODE, "PE->ShellCode");
|
||||
m_ComboCompress.SetCurSel(CLIENT_COMPRESS_NONE);
|
||||
|
||||
m_OtherItem.ShowWindow(SW_HIDE);
|
||||
@@ -454,3 +464,17 @@ void CBuildDlg::OnHelpFindden()
|
||||
m_strFindden = dlg.m_str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 ) {
|
||||
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
|
||||
m_strEncryptIP = dlg.m_str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,4 +42,6 @@ public:
|
||||
afx_msg void OnHelpFindden();
|
||||
CEdit m_EditGroup;
|
||||
CString m_sGroupName;
|
||||
CString m_strEncryptIP;
|
||||
afx_msg void OnMenuEncryptIp();
|
||||
};
|
||||
|
||||
@@ -201,6 +201,8 @@ BOOL CScreenSpyDlg::OnInitDialog()
|
||||
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, m_BitmapInfor_Full,
|
||||
DIB_RGB_COLORS, &m_BitmapData_Full, NULL, NULL); //创建应用程序可以直接写入的、与设备无关的位图
|
||||
|
||||
BIN
server/2015Remote/libpeconv/libpeconv_x64.lib
Normal file
BIN
server/2015Remote/libpeconv/libpeconv_x64.lib
Normal file
Binary file not shown.
BIN
server/2015Remote/libpeconv/libpeconv_x64d.lib
Normal file
BIN
server/2015Remote/libpeconv/libpeconv_x64d.lib
Normal file
Binary file not shown.
32
server/2015Remote/libpeconv/peconv.h
Normal file
32
server/2015Remote/libpeconv/peconv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Master include file, including everything else.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "peconv/buffer_util.h"
|
||||
#include "peconv/util.h"
|
||||
#include "peconv/pe_hdrs_helper.h"
|
||||
#include "peconv/pe_mode_detector.h"
|
||||
#include "peconv/pe_raw_to_virtual.h"
|
||||
#include "peconv/pe_virtual_to_raw.h"
|
||||
#include "peconv/relocate.h"
|
||||
#include "peconv/remote_pe_reader.h"
|
||||
#include "peconv/imports_loader.h"
|
||||
#include "peconv/pe_loader.h"
|
||||
#include "peconv/pe_dumper.h"
|
||||
#include "peconv/exports_lookup.h"
|
||||
#include "peconv/function_resolver.h"
|
||||
#include "peconv/hooks.h"
|
||||
#include "peconv/exports_mapper.h"
|
||||
#include "peconv/caves.h"
|
||||
#include "peconv/fix_imports.h"
|
||||
#include "peconv/delayed_imports_loader.h"
|
||||
#include "peconv/resource_parser.h"
|
||||
#include "peconv/load_config_util.h"
|
||||
#include "peconv/peb_lookup.h"
|
||||
#include "peconv/find_base.h"
|
||||
#include "peconv/tls_parser.h"
|
||||
#include "peconv/exceptions_parser.h"
|
||||
#include "peconv/unicode.h"
|
||||
88
server/2015Remote/libpeconv/peconv/buffer_util.h
Normal file
88
server/2015Remote/libpeconv/peconv/buffer_util.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Definitions of the used buffer types. Functions for their allocation and deallocation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define MAX_DWORD 0xffffffff
|
||||
#define MAX_WORD 0xffff
|
||||
#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 {
|
||||
|
||||
/**
|
||||
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 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);
|
||||
|
||||
//
|
||||
/**
|
||||
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);
|
||||
|
||||
/**
|
||||
Frees buffer allocated by alloc_aligned.
|
||||
*/
|
||||
bool free_aligned(ALIGNED_BUF buffer, size_t buffer_size=0);
|
||||
|
||||
//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);
|
||||
|
||||
/**
|
||||
Free the memory allocated with alloc_pe_buffer.
|
||||
*/
|
||||
bool free_pe_buffer(ALIGNED_BUF buffer, size_t buffer_size=0);
|
||||
|
||||
}; //namespace peconv
|
||||
27
server/2015Remote/libpeconv/peconv/caves.h
Normal file
27
server/2015Remote/libpeconv/peconv/caves.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to finding caves in the loaded PE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
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 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);
|
||||
|
||||
};//namespace peconv
|
||||
61
server/2015Remote/libpeconv/peconv/delayed_imports_loader.h
Normal file
61
server/2015Remote/libpeconv/peconv/delayed_imports_loader.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Parsing and filling the Delayload Import Table.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "function_resolver.h"
|
||||
|
||||
#if (defined(_WIN32_WINNT) && _WIN32_WINNT > 0x0601) || __MINGW32__ //Windows SDK version 6.1 (Windows 7)
|
||||
#define DELAYLOAD_IMPORTS_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef DELAYLOAD_IMPORTS_DEFINED
|
||||
#include "pshpack4.h"
|
||||
|
||||
typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
|
||||
union {
|
||||
DWORD AllAttributes;
|
||||
struct {
|
||||
DWORD RvaBased : 1; // Delay load version 2
|
||||
DWORD ReservedAttributes : 31;
|
||||
} DUMMYSTRUCTNAME;
|
||||
} Attributes;
|
||||
|
||||
DWORD DllNameRVA; // RVA to the name of the target library (NULL-terminate ASCII string)
|
||||
DWORD ModuleHandleRVA; // RVA to the HMODULE caching location (PHMODULE)
|
||||
DWORD ImportAddressTableRVA; // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
|
||||
DWORD ImportNameTableRVA; // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
|
||||
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
|
||||
|
||||
} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;
|
||||
|
||||
typedef const IMAGE_DELAYLOAD_DESCRIPTOR *PCIMAGE_DELAYLOAD_DESCRIPTOR;
|
||||
|
||||
#include "poppack.h"
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
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
|
||||
21
server/2015Remote/libpeconv/peconv/exceptions_parser.h
Normal file
21
server/2015Remote/libpeconv/peconv/exceptions_parser.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to Exceptions Table
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "peconv/buffer_util.h"
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
132
server/2015Remote/libpeconv/peconv/exported_func.h
Normal file
132
server/2015Remote/libpeconv/peconv/exported_func.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief A definition of ExportedFunc class - used for storing the details of the exported function. Helper functions related to the export parsing.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
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);
|
||||
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
|
||||
|
||||
50
server/2015Remote/libpeconv/peconv/exports_lookup.h
Normal file
50
server/2015Remote/libpeconv/peconv/exports_lookup.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Searching specific functions in PE's Exports Table.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "function_resolver.h"
|
||||
#include "exports_mapper.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
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 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:
|
||||
/**
|
||||
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);
|
||||
};
|
||||
|
||||
/**
|
||||
Read the DLL name from the Export Table.
|
||||
*/
|
||||
LPSTR read_dll_name(HMODULE modulePtr);
|
||||
|
||||
}; //namespace peconv
|
||||
224
server/2015Remote/libpeconv/peconv/exports_mapper.h
Normal file
224
server/2015Remote/libpeconv/peconv/exports_mapper.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief A definition of ExportsMapper class. Creates a lookup of all the exported functions from the supplied DLLs. Allows to associate an address with a corresponding function.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "pe_raw_to_virtual.h"
|
||||
#include "peconv/exported_func.h"
|
||||
#include "peconv/file_util.h"
|
||||
|
||||
namespace peconv {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
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 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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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 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;
|
||||
|
||||
std::map<ULONGLONG, DllInfo> dll_base_to_info;
|
||||
};
|
||||
|
||||
}; //namespace peconv
|
||||
60
server/2015Remote/libpeconv/peconv/file_util.h
Normal file
60
server/2015Remote/libpeconv/peconv/file_util.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to operations on files. Wrappers for read/write.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "buffer_util.h"
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
/**
|
||||
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 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);
|
||||
|
||||
}; //namespace peconv
|
||||
20
server/2015Remote/libpeconv/peconv/find_base.h
Normal file
20
server/2015Remote/libpeconv/peconv/find_base.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to finding a base to which the module was relocated.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
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);
|
||||
};
|
||||
119
server/2015Remote/libpeconv/peconv/fix_imports.h
Normal file
119
server/2015Remote/libpeconv/peconv/fix_imports.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions and classes responsible for fixing Import Table. A definition of ImportedDllCoverage class.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "exports_lookup.h"
|
||||
#include "exports_mapper.h"
|
||||
|
||||
#define MIN_DLL_LEN 5
|
||||
|
||||
namespace peconv {
|
||||
|
||||
/**
|
||||
a helper class that allows to store information about functions that could not be covered by the given mapping
|
||||
*/
|
||||
class ImpsNotCovered
|
||||
{
|
||||
public:
|
||||
ImpsNotCovered() {}
|
||||
~ImpsNotCovered() {}
|
||||
|
||||
/*
|
||||
Number of stored records
|
||||
*/
|
||||
size_t count() { return thunkToAddr.size(); }
|
||||
|
||||
void insert(DWORD thunkRVA, ULONGLONG searchedAddr);
|
||||
|
||||
std::map<DWORD, ULONGLONG> thunkToAddr; //addresses of not recovered functions with their thunks (call_via)
|
||||
};
|
||||
|
||||
/**
|
||||
fix imports in the given module, using the given map of all available exports
|
||||
*/
|
||||
bool fix_imports(IN OUT PVOID modulePtr, IN size_t moduleSize, IN const peconv::ExportsMapper& exportsMap, OUT OPTIONAL peconv::ImpsNotCovered* notCovered);
|
||||
|
||||
/**
|
||||
a helper class that allows to find out where the functions are imported from
|
||||
*/
|
||||
class ImportedDllCoverage
|
||||
{
|
||||
public:
|
||||
/**
|
||||
A constructor of an object of ImportedDllCoverage class.
|
||||
\param _addresses : the list of filled imports (VAs): the addresses to be covered
|
||||
\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();
|
||||
|
||||
/**
|
||||
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; }
|
||||
|
||||
/**
|
||||
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;
|
||||
|
||||
/**
|
||||
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;
|
||||
|
||||
/**
|
||||
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;
|
||||
};
|
||||
}
|
||||
50
server/2015Remote/libpeconv/peconv/function_resolver.h
Normal file
50
server/2015Remote/libpeconv/peconv/function_resolver.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Definitions of basic Imports Resolver classes. They can be used for filling imports when the PE is loaded.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace peconv {
|
||||
/**
|
||||
A base class for functions resolver.
|
||||
*/
|
||||
class t_function_resolver {
|
||||
public:
|
||||
/**
|
||||
Get the address (VA) of the function with the given name, from the given DLL.
|
||||
\param func_name : the name of the function
|
||||
\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;
|
||||
};
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
/**
|
||||
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;
|
||||
};
|
||||
|
||||
}; //namespace peconv
|
||||
146
server/2015Remote/libpeconv/peconv/hooks.h
Normal file
146
server/2015Remote/libpeconv/peconv/hooks.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to hooking the loaded PE. Reditecting/replacing a functions with another.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "function_resolver.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "peconv/buffer_util.h"
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
103
server/2015Remote/libpeconv/peconv/imports_loader.h
Normal file
103
server/2015Remote/libpeconv/peconv/imports_loader.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Parsing and filling the Import Table.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <set>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "function_resolver.h"
|
||||
#include "exports_mapper.h"
|
||||
|
||||
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 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
|
||||
\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
|
||||
94
server/2015Remote/libpeconv/peconv/imports_uneraser.h
Normal file
94
server/2015Remote/libpeconv/peconv/imports_uneraser.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief A definition of ImportsUneraser class - for recovery of a partialy erased Import Table.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <iterator>
|
||||
#include "fix_imports.h"
|
||||
#include "caves.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
PBYTE modulePtr;
|
||||
size_t moduleSize;
|
||||
bool is64;
|
||||
};
|
||||
}
|
||||
233
server/2015Remote/libpeconv/peconv/load_config_defs.h
Normal file
233
server/2015Remote/libpeconv/peconv/load_config_defs.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Definitions of various versions of Load Config Directory (new fields added with new versions for Windows).
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <pshpack4.h>
|
||||
|
||||
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_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_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_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;
|
||||
}; //namespace peconv
|
||||
|
||||
#include <poppack.h>
|
||||
42
server/2015Remote/libpeconv/peconv/load_config_util.h
Normal file
42
server/2015Remote/libpeconv/peconv/load_config_util.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Fetching Load Config Directory and recognizing its version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#include "buffer_util.h"
|
||||
#include "load_config_defs.h"
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
}; // namespace peconv
|
||||
49
server/2015Remote/libpeconv/peconv/pe_dumper.h
Normal file
49
server/2015Remote/libpeconv/peconv/pe_dumper.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Dumping PE from the memory buffer into a file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "exports_mapper.h"
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
};// namespace peconv
|
||||
248
server/2015Remote/libpeconv/peconv/pe_hdrs_helper.h
Normal file
248
server/2015Remote/libpeconv/peconv/pe_hdrs_helper.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Wrappers over various fields in the PE header. Read, write, parse PE headers.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "buffer_util.h"
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
Get pointer to the Export Directory.
|
||||
*/
|
||||
IMAGE_EXPORT_DIRECTORY* get_export_directory(IN HMODULE modulePtr);
|
||||
|
||||
// Fetch Image Base from Optional Header.
|
||||
ULONGLONG get_image_base(IN const BYTE *pe_buffer);
|
||||
|
||||
/**
|
||||
Change the Image Base in Optional Header to the given one.
|
||||
*/
|
||||
bool update_image_base(IN OUT BYTE* payload, IN ULONGLONG destImageBase);
|
||||
|
||||
/**
|
||||
Get RVA of the Entry Point from the Optional Header.
|
||||
*/
|
||||
DWORD get_entry_point_rva(IN const BYTE *pe_buffer);
|
||||
|
||||
/**
|
||||
Change the Entry Point RVA in the Optional Header to the given one.
|
||||
*/
|
||||
bool update_entry_point_rva(IN OUT BYTE *pe_buffer, IN DWORD ep);
|
||||
|
||||
/**
|
||||
Get number of sections from the File Header. It does not validate if this the actual number.
|
||||
*/
|
||||
size_t get_sections_count(
|
||||
IN const BYTE* buffer,
|
||||
IN const size_t buffer_size
|
||||
);
|
||||
|
||||
/**
|
||||
Checks if the section headers are reachable. It does not validate sections alignment.
|
||||
*/
|
||||
bool is_valid_sections_hdr_offset(IN const BYTE* buffer, IN const size_t buffer_size);
|
||||
|
||||
/**
|
||||
Gets pointer to the section header of the given number.
|
||||
*/
|
||||
PIMAGE_SECTION_HEADER get_section_hdr(
|
||||
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
|
||||
42
server/2015Remote/libpeconv/peconv/pe_loader.h
Normal file
42
server/2015Remote/libpeconv/peconv/pe_loader.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Loading PE from a file with the help of the custom loader.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#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);
|
||||
|
||||
/**
|
||||
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 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
|
||||
46
server/2015Remote/libpeconv/peconv/pe_mode_detector.h
Normal file
46
server/2015Remote/libpeconv/peconv/pe_mode_detector.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Detecting in which mode is the PE in the supplied buffer (i.e. raw, virtual). Analyzes PE features typical for particular modes.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
|
||||
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 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 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
|
||||
30
server/2015Remote/libpeconv/peconv/pe_raw_to_virtual.h
Normal file
30
server/2015Remote/libpeconv/peconv/pe_raw_to_virtual.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Converting PE from raw to virtual format.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "buffer_util.h"
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
}; // namespace peconv
|
||||
47
server/2015Remote/libpeconv/peconv/pe_virtual_to_raw.h
Normal file
47
server/2015Remote/libpeconv/peconv/pe_virtual_to_raw.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Converting PE from virtual to raw format.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "buffer_util.h"
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/*
|
||||
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
|
||||
40
server/2015Remote/libpeconv/peconv/peb_lookup.h
Normal file
40
server/2015Remote/libpeconv/peconv/peb_lookup.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions for retrieving process information from PEB.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
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 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);
|
||||
|
||||
/**
|
||||
Gets the main module from the current PEB.
|
||||
\return the main module connected to the current PEB.
|
||||
*/
|
||||
HMODULE get_main_module_via_peb();
|
||||
};
|
||||
|
||||
51
server/2015Remote/libpeconv/peconv/relocate.h
Normal file
51
server/2015Remote/libpeconv/peconv/relocate.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Operating on PE file's relocations table.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace peconv {
|
||||
|
||||
typedef struct _BASE_RELOCATION_ENTRY {
|
||||
WORD Offset : 12;
|
||||
WORD Type : 4;
|
||||
} BASE_RELOCATION_ENTRY;
|
||||
|
||||
class RelocBlockCallback
|
||||
{
|
||||
public:
|
||||
RelocBlockCallback(bool _is64bit)
|
||||
: is64bit(_is64bit)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool processRelocField(ULONG_PTR relocField) = 0;
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
};//namespace peconv
|
||||
134
server/2015Remote/libpeconv/peconv/remote_pe_reader.h
Normal file
134
server/2015Remote/libpeconv/peconv/remote_pe_reader.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Reading from a PE module that is loaded within a remote process.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "pe_hdrs_helper.h"
|
||||
#include "pe_virtual_to_raw.h"
|
||||
#include "exports_mapper.h"
|
||||
#include "pe_dumper.h"
|
||||
|
||||
namespace peconv {
|
||||
|
||||
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 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);
|
||||
|
||||
/**
|
||||
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 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 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
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
25
server/2015Remote/libpeconv/peconv/resource_parser.h
Normal file
25
server/2015Remote/libpeconv/peconv/resource_parser.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Parsing PE's resource directory.
|
||||
*/
|
||||
|
||||
#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
|
||||
);
|
||||
|
||||
/**
|
||||
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);
|
||||
};
|
||||
34
server/2015Remote/libpeconv/peconv/resource_util.h
Normal file
34
server/2015Remote/libpeconv/peconv/resource_util.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to manual retrieving of PE resources.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include "buffer_util.h"
|
||||
|
||||
namespace peconv {
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
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();
|
||||
|
||||
}; //namespace peconv
|
||||
41
server/2015Remote/libpeconv/peconv/tls_parser.h
Normal file
41
server/2015Remote/libpeconv/peconv/tls_parser.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Functions related to TLS Callbacks
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include<vector>
|
||||
|
||||
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 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);
|
||||
|
||||
}; //namespace peconv
|
||||
11
server/2015Remote/libpeconv/peconv/unicode.h
Normal file
11
server/2015Remote/libpeconv/peconv/unicode.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef UNICODE
|
||||
#define tcout wcout
|
||||
#define tcerr wcerr
|
||||
#define tstring wstring
|
||||
#else
|
||||
#define tcout cout
|
||||
#define tcerr cerr
|
||||
#define tstring string
|
||||
#endif // UNICODE
|
||||
51
server/2015Remote/libpeconv/peconv/util.h
Normal file
51
server/2015Remote/libpeconv/peconv/util.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Miscellaneous utility functions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "file_util.h"
|
||||
#include "resource_util.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define PECONV_FORCEINLINE __forceinline
|
||||
#define PECONV_TRY_EXCEPT_BLOCK_START __try {
|
||||
#define PECONV_TRY_EXCEPT_BLOCK_END __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
#else
|
||||
#define PECONV_FORCEINLINE __attribute__((always_inline)) inline
|
||||
#define PECONV_TRY_EXCEPT_BLOCK_START try {
|
||||
#define PECONV_TRY_EXCEPT_BLOCK_END catch (...) {
|
||||
#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);
|
||||
|
||||
/**
|
||||
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 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);
|
||||
};
|
||||
236
server/2015Remote/main.cpp
Normal file
236
server/2015Remote/main.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "stdafx.h"
|
||||
#ifdef _WIN64
|
||||
// Source code: https://github.com/hasherezade/pe_to_shellcode
|
||||
#include <windows.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "peconv.h"
|
||||
#include "resource.h"
|
||||
|
||||
#define VERSION "1.2"
|
||||
#include "peloader.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#pragma comment(lib, "libpeconv/libpeconv_x64d.lib")
|
||||
#else
|
||||
#pragma comment(lib, "libpeconv/libpeconv_x64.lib")
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
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_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);
|
||||
#else
|
||||
redir_code = redir_code32;
|
||||
redir_size = sizeof(redir_code32);
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
|
||||
DWORD raw_addr = exe_size;
|
||||
overwrite_hdr(ext_buf, ext_size, raw_addr, is64b);
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int pe_2_shellcode(const std::string &in_path, const std::string &out_str)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#endif
|
||||
14
server/2015Remote/peloader.h
Normal file
14
server/2015Remote/peloader.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
#define MAX_REDIR_SIZE 32
|
||||
|
||||
#define LDS_CLEAN 0
|
||||
#define LDS_LOADED 1
|
||||
#define LDS_RUN 2
|
||||
#define LDS_ATTACHED 3
|
||||
|
||||
typedef struct _min_hdr {
|
||||
BYTE redir[MAX_REDIR_SIZE];
|
||||
BYTE load_status;
|
||||
} min_hdr_t;
|
||||
@@ -146,9 +146,9 @@ std::string deriveKey(const std::string& password, const std::string& hardwareID
|
||||
|
||||
std::string getDeviceID()
|
||||
{
|
||||
std::string hardwareID = getHardwareID();
|
||||
std::string hashedID = hashSHA256(hardwareID);
|
||||
std::string deviceID = getFixedLengthID(hashedID);
|
||||
static std::string hardwareID = getHardwareID();
|
||||
static std::string hashedID = hashSHA256(hardwareID);
|
||||
static std::string deviceID = getFixedLengthID(hashedID);
|
||||
return deviceID;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
BIN
server/2015Remote/stub2/stub32.bin
Normal file
BIN
server/2015Remote/stub2/stub32.bin
Normal file
Binary file not shown.
BIN
server/2015Remote/stub2/stub64.bin
Normal file
BIN
server/2015Remote/stub2/stub64.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user