Skip to content

Commit 65a0b60

Browse files
implemented the TreeImportExport class.
1 parent e1235eb commit 65a0b60

File tree

9 files changed

+405
-4
lines changed

9 files changed

+405
-4
lines changed

WinArk/ScyllaDlg.cpp

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "ImportRebuilder.h"
88
#include "DisasmDlg.h"
99
#include "PickDLLDlg.h"
10+
#include "TreeImportExport.h"
11+
#include <Helpers.h>
1012

1113

1214
CScyllaDlg::CScyllaDlg(const WinSys::ProcessManager& pm, ProcessInfoEx& px)
@@ -697,4 +699,61 @@ void CScyllaDlg::PickDLLHandler() {
697699
}
698700

699701
UpdateStatusBar();
700-
}
702+
}
703+
704+
void CScyllaDlg::OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl) {
705+
DeleteSelectedImportsHandler();
706+
}
707+
708+
709+
void CScyllaDlg::SaveTreeHandler() {
710+
WCHAR selectedFilePath[MAX_PATH] = { 0 };
711+
GetCurrentModulePath(_text, _countof(_text));
712+
if (ShowFileDialog(selectedFilePath, true, nullptr, s_FilterXml, L"xml", _text)) {
713+
TreeImportExport treeIO(selectedFilePath);
714+
DWORD_PTR oep = _oepAddress.GetValue();
715+
DWORD_PTR iat = _iatAddress.GetValue();
716+
DWORD iatSize = _iatSize.GetValue();
717+
std::wstring wname = m_px.GetProcess()->GetName();
718+
std::string name = Helpers::WstringToString(wname);
719+
if (!treeIO.ExportTreeList(_importsHandling.m_ModuleMap, name, oep, iat, iatSize)) {
720+
721+
}
722+
}
723+
}
724+
725+
void CScyllaDlg::OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl) {
726+
SaveTreeHandler();
727+
}
728+
729+
void CScyllaDlg::LoadTreeHandler() {
730+
WCHAR selectedFilePath[MAX_PATH];
731+
GetCurrentModulePath(_text, _countof(_text));
732+
if (ShowFileDialog(selectedFilePath, false, nullptr, s_FilterXml, nullptr, _text)) {
733+
TreeImportExport treeIO(selectedFilePath);
734+
DWORD_PTR oep = 0;
735+
DWORD_PTR iat = 0;
736+
DWORD iatSize = 0;
737+
if (!treeIO.ImportTreeList(_importsHandling.m_ModuleMap, &oep, &iat, &iatSize)) {
738+
739+
}
740+
else {
741+
swprintf_s(_text, L"Are you sure? Replace the OEP, IAT, and IAT size with %p %p %x",
742+
oep, iat, iatSize);
743+
744+
int result = MessageBox(_text, L"Confirmation", MB_YESNO | MB_ICONQUESTION);
745+
if (result == IDYES) {
746+
_oepAddress.SetValue(oep);
747+
_iatAddress.SetValue(iat);
748+
_iatSize.SetValue(iatSize);
749+
}
750+
_importsHandling.DisplayAllImports();
751+
UpdateStatusBar();
752+
}
753+
}
754+
}
755+
756+
void CScyllaDlg::OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl) {
757+
LoadTreeHandler();
758+
}
759+

WinArk/ScyllaDlg.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class CScyllaDlg
4343
void PERebuildHandler();
4444
void DeleteSelectedImportsHandler();
4545

46+
void SaveTreeHandler();
47+
void LoadTreeHandler();
4648

4749
CTreeItem FindTreeItem(CPoint pt, bool screenCoordinates);
4850

@@ -56,6 +58,9 @@ class CScyllaDlg
5658
void OnInvalidImports(UINT uNotifyCode, int nID, CWindow wndCtl);
5759
void OnSuspectImports(UINT uNotifyCode, int nID, CWindow wndCtl);
5860
void OnClearImports(UINT uNotifyCode, int nID, CWindow wndCtl);
61+
void OnCutSelected(UINT uNotifyCode, int nID, CWindow wndCtl);
62+
void OnSaveTree(UINT uNotifyCode, int nID, CWindow wndCtl);
63+
void OnLoadTree(UINT uNotifyCode, int nID, CWindow wndCtl);
5964

6065
void OnAutoSearch(UINT uNotifyCode, int nID, CWindow wndCtl);
6166
void OnGetImports(UINT uNotifyCode, int nID, CWindow wndCtl);
@@ -149,5 +154,12 @@ class CScyllaDlg
149154
COMMAND_ID_HANDLER_EX(IDC_BTN_CLEAR,OnClearImports)
150155
COMMAND_ID_HANDLER_EX(IDC_BTN_SHOW_INVALID,OnInvalidImports)
151156
COMMAND_ID_HANDLER_EX(IDC_BTN_SHOW_SUSPECT, OnSuspectImports)
157+
158+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_CLEAR_IMPORTS,OnClearImports)
159+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOW_INVALID,OnInvalidImports)
160+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SHOW_SUSPECT,OnSuspectImports)
161+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_CUT_SELECTED,OnCutSelected)
162+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_SAVE_TREE,OnSaveTree)
163+
COMMAND_ID_HANDLER_EX(ID_IMPORTS_LOAD_TREE,OnLoadTree)
152164
END_MSG_MAP()
153165
};

WinArk/TreeImportExport.cpp

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
#include "stdafx.h"
2+
#include "TreeImportExport.h"
3+
#include "Architecture.h"
4+
#include <Helpers.h>
5+
6+
TreeImportExport::TreeImportExport(const WCHAR* pTargetXmlFile){
7+
wcscpy_s(_xmlPath, pTargetXmlFile);
8+
}
9+
10+
bool TreeImportExport::ExportTreeList(const std::map<DWORD_PTR, ImportModuleThunk>& moduleThunk, const std::string processName,
11+
DWORD_PTR oep, DWORD_PTR iat, DWORD iatSize){
12+
// 定义doc对象
13+
tinyxml2::XMLDocument doc;
14+
// 增加xml文档声明
15+
tinyxml2::XMLDeclaration* pDecl = doc.NewDeclaration();
16+
doc.LinkEndChild(pDecl);
17+
18+
// 添加节点
19+
tinyxml2::XMLElement* pRootElement = doc.NewElement("target");
20+
21+
SetTargetInformation(pRootElement, processName, oep, iat, iatSize);
22+
AddModuleListToRootElement(pRootElement, moduleThunk);
23+
24+
doc.LinkEndChild(pRootElement);
25+
26+
return SaveXmlToFile(doc, _xmlPath);
27+
}
28+
29+
bool TreeImportExport::ImportTreeList(std::map<DWORD_PTR, ImportModuleThunk>& moduleThunk,
30+
DWORD_PTR* pOEP, DWORD_PTR* pIAT, DWORD* pSize) {
31+
moduleThunk.clear();
32+
*pOEP = *pIAT = 0;
33+
*pSize = 0;
34+
35+
tinyxml2::XMLDocument doc;
36+
if (!ReadXmlFile(doc, _xmlPath)) {
37+
return false;
38+
}
39+
40+
tinyxml2::XMLElement* pTargetElement = doc.FirstChildElement();
41+
if (!pTargetElement) {
42+
return false;
43+
}
44+
45+
*pOEP = ConvertStringToDwordPtr(pTargetElement->Attribute("oep_va"));
46+
*pIAT = ConvertStringToDwordPtr(pTargetElement->Attribute("iat_va"));
47+
*pSize = ConvertStringToDwordPtr(pTargetElement->Attribute("iat_size"));
48+
49+
ParseAllElementModules(pTargetElement, moduleThunk);
50+
51+
return true;
52+
}
53+
54+
void TreeImportExport::SetTargetInformation(tinyxml2::XMLElement* pRootElement, std::string processName,
55+
DWORD_PTR oep, DWORD_PTR iat, DWORD iatSize) {
56+
pRootElement->SetAttribute("process_name", processName.c_str());
57+
58+
ConvertDwordPtrToString(oep);
59+
pRootElement->SetAttribute("oep_va", _xmlStringBuffer);
60+
61+
ConvertDwordPtrToString(iat);
62+
pRootElement->SetAttribute("iat_va", _xmlStringBuffer);
63+
64+
ConvertDwordPtrToString(iatSize);
65+
pRootElement->SetAttribute("iat_size", _xmlStringBuffer);
66+
}
67+
68+
void TreeImportExport::AddModuleListToRootElement(tinyxml2::XMLElement* pRootElement,
69+
const std::map<DWORD_PTR, ImportModuleThunk>& moduleThunkMap){
70+
71+
for (auto& moduleThunk : moduleThunkMap) {
72+
const ImportModuleThunk& importModultThunk = moduleThunk.second;
73+
tinyxml2::XMLElement* pModuleElement = GetModuleXmlElement(pRootElement,&importModultThunk);
74+
75+
for (auto& thunk : importModultThunk.m_ThunkMap) {
76+
const ImportThunk& importThunk = thunk.second;
77+
tinyxml2::XMLElement* pImportElement = GetImportXmlElement(pModuleElement, &importThunk);
78+
}
79+
}
80+
}
81+
82+
83+
void TreeImportExport::ParseAllElementModules(tinyxml2::XMLElement* pTargetElement,
84+
std::map<DWORD_PTR, ImportModuleThunk>& moduleThunkMap)
85+
{
86+
ImportModuleThunk importModuleThunk;
87+
88+
for (tinyxml2::XMLElement* pModuleElement = pTargetElement->FirstChildElement();
89+
pModuleElement; pModuleElement = pModuleElement->NextSiblingElement()) {
90+
std::string moduleName = pModuleElement->Attribute("module_name");
91+
if (!moduleName.empty()) {
92+
importModuleThunk.m_FirstThunk = ConvertStringToDwordPtr(pModuleElement->Attribute("first_thunk_rva"));
93+
importModuleThunk.m_ThunkMap.clear();
94+
ParseAllElementImports(pModuleElement, &importModuleThunk);
95+
96+
moduleThunkMap[importModuleThunk.m_FirstThunk] = importModuleThunk;
97+
}
98+
}
99+
}
100+
101+
void TreeImportExport::ParseAllElementImports(tinyxml2::XMLElement* pModuleElement,
102+
ImportModuleThunk* pModuleThunk)
103+
{
104+
ImportThunk importThunk;
105+
for (tinyxml2::XMLElement* pImportElement = pModuleElement->FirstChildElement();
106+
pImportElement; pImportElement = pImportElement->NextSiblingElement()) {
107+
const char* pTemp = pImportElement->Value();
108+
if (!strcmp(pTemp, "import_valid")) {
109+
pTemp = pImportElement->Attribute("name");
110+
if (pTemp) {
111+
strcpy_s(importThunk.m_Name, pTemp);
112+
}
113+
else {
114+
importThunk.m_Name[0] = 0;
115+
}
116+
117+
wcscpy_s(importThunk.m_ModuleName, pModuleThunk->m_ModuleName);
118+
119+
importThunk.m_Suspect = ConvertStringToBool(pImportElement->Attribute("suspect"));
120+
importThunk.m_Ordinal = ConvertStringToWord(pImportElement->Attribute("ordinal"));
121+
importThunk.m_Hint = ConvertStringToWord(pImportElement->Attribute("hint"));
122+
123+
importThunk.m_Valid = true;
124+
}
125+
else {
126+
importThunk.m_Valid = false;
127+
importThunk.m_Suspect = true;
128+
}
129+
130+
importThunk.m_ApiAddressVA = ConvertStringToDwordPtr(pImportElement->Attribute("address_va"));
131+
importThunk.m_RVA = ConvertStringToDwordPtr(pImportElement->Attribute("iat_rva"));
132+
133+
if (importThunk.m_RVA != 0) {
134+
pModuleThunk->m_ThunkMap[importThunk.m_RVA] = importThunk;
135+
}
136+
}
137+
}
138+
139+
tinyxml2::XMLElement* TreeImportExport::GetModuleXmlElement(tinyxml2::XMLElement* pParentElement,
140+
const ImportModuleThunk* pModuleThunk)
141+
{
142+
tinyxml2::XMLElement* pModuleElement = pParentElement->InsertNewChildElement("module");
143+
std::string moduleName = Helpers::WstringToString(pModuleThunk->m_ModuleName);
144+
pModuleElement->SetAttribute("module_name", moduleName.c_str());
145+
146+
ConvertDwordPtrToString(pModuleThunk->GetFirstThunk());
147+
pModuleElement->SetAttribute("first_thunk_rva", _xmlStringBuffer);
148+
149+
return pModuleElement;
150+
}
151+
152+
tinyxml2::XMLElement* TreeImportExport::GetImportXmlElement(tinyxml2::XMLElement* pParentElement,
153+
const ImportThunk* pThunk)
154+
{
155+
tinyxml2::XMLElement* pImportElement = nullptr;
156+
if (pThunk->m_Valid) {
157+
pImportElement = pParentElement->InsertNewChildElement("import_valid");
158+
if (pThunk->m_Name[0] != '\0') {
159+
pImportElement->SetAttribute("name", pThunk->m_Name);
160+
}
161+
162+
ConvertWordToString(pThunk->m_Ordinal);
163+
pImportElement->SetAttribute("ordinal", _xmlStringBuffer);
164+
165+
ConvertWordToString(pThunk->m_Hint);
166+
pImportElement->SetAttribute("hint", _xmlStringBuffer);
167+
168+
ConvertBoolToString(pThunk->m_Suspect);
169+
pImportElement->SetAttribute("suspect", _xmlStringBuffer);
170+
}
171+
else {
172+
pImportElement = pParentElement->InsertNewChildElement("import_invalid");
173+
}
174+
175+
ConvertDwordPtrToString(pThunk->m_RVA);
176+
pImportElement->SetAttribute("iat_rva", _xmlStringBuffer);
177+
178+
ConvertDwordPtrToString(pThunk->m_ApiAddressVA);
179+
pImportElement->SetAttribute("address_va", _xmlStringBuffer);
180+
181+
return pImportElement;
182+
}
183+
184+
185+
bool TreeImportExport::SaveXmlToFile(tinyxml2::XMLDocument& doc, const WCHAR* pXmlFilePath){
186+
std::string xmlFilePath = Helpers::WstringToString(pXmlFilePath);
187+
tinyxml2::XMLError error = doc.SaveFile(xmlFilePath.c_str());
188+
return error == tinyxml2::XML_SUCCESS ? true : false;
189+
}
190+
191+
bool TreeImportExport::ReadXmlFile(tinyxml2::XMLDocument& doc, const WCHAR* pXmlFilePath){
192+
std::string xmlFilePath = Helpers::WstringToString(pXmlFilePath);
193+
tinyxml2::XMLError error = doc.LoadFile(xmlFilePath.c_str());
194+
return error == tinyxml2::XML_SUCCESS ? true : false;
195+
}
196+
197+
void TreeImportExport::ConvertBoolToString(const bool value) {
198+
if (value) {
199+
strcpy_s(_xmlStringBuffer, "1");
200+
}
201+
else {
202+
strcpy_s(_xmlStringBuffer, "0");
203+
}
204+
}
205+
206+
void TreeImportExport::ConvertWordToString(const WORD value)
207+
{
208+
sprintf_s(_xmlStringBuffer, "%04X", value);
209+
}
210+
211+
void TreeImportExport::ConvertDwordPtrToString(const DWORD_PTR value)
212+
{
213+
sprintf_s(_xmlStringBuffer, PRINTF_DWORD_PTR_FULL_S, value);
214+
}
215+
216+
DWORD_PTR TreeImportExport::ConvertStringToDwordPtr(const char* pValue)
217+
{
218+
DWORD_PTR result = 0;
219+
220+
if (pValue)
221+
{
222+
#ifdef _WIN64
223+
result = _strtoi64(pValue, NULL, 16);
224+
#else
225+
result = strtoul(pValue, NULL, 16);
226+
#endif
227+
}
228+
229+
return result;
230+
}
231+
232+
WORD TreeImportExport::ConvertStringToWord(const char* pValue)
233+
{
234+
WORD result = 0;
235+
236+
if (pValue)
237+
{
238+
result = (WORD)strtoul(pValue, NULL, 16);
239+
}
240+
241+
return result;
242+
}
243+
244+
bool TreeImportExport::ConvertStringToBool(const char* pValue)
245+
{
246+
if (pValue)
247+
{
248+
if (pValue[0] == '1')
249+
{
250+
return true;
251+
}
252+
}
253+
254+
return false;
255+
}

0 commit comments

Comments
 (0)