Skip to content

Commit ca00d74

Browse files
committed
ida: use undocumented(??) eh_parse_t plugin for .pdata & exceptions
fixes #8 seems we only really needed to set the PE_NODE data to NtHeaders, IDA then handles eh_parse stuff once auto is done found how to call it earlier though (as pe.dll does), so you won't need to wait for analysis to finish unfortunately the eh_parse_t class isn't actually included in IDA SDK so had to hack it in, likely to break in future IDASDK :/
1 parent 2faf33f commit ca00d74

File tree

3 files changed

+66
-27
lines changed

3 files changed

+66
-27
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ include($ENV{IDASDK}/ida-cmake/common.cmake)
88

99
set(LOADER_NAME idaxex)
1010
set(LOADER_SOURCES idaloader.cpp xex.cpp lzx.cpp namegen.cpp 3rdparty/aes.c 3rdparty/excrypt/src/excrypt_sha.c 3rdparty/mspack/lzxd.c 3rdparty/mspack/system.c)
11-
set(LOADER_INCLUDE_DIRECTORIES 3rdparty/excrypt/src)
11+
set(LOADER_INCLUDE_DIRECTORIES 3rdparty/excrypt/src $ENV{IDASDK}/ldr/pe)
1212
add_compile_definitions(IDALDR=1)
1313

1414
generate()

idaloader.cpp

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55
// - fix XEX1 exports
66

77
#include <ida.hpp>
8+
#include <idp.hpp>
89
#include <loader.hpp>
910
#include <auto.hpp>
1011
#include <diskio.hpp>
1112
#include <entry.hpp>
1213
#include <typeinf.hpp>
1314
#include <bytes.hpp>
1415

16+
struct exehdr {}; // needed for pe.h
17+
#include <pe.h>
18+
#include <common.h>
19+
1520
#include <filesystem>
1621
#include <list>
1722

@@ -168,37 +173,71 @@ void pe_add_sections(XEXFile& file)
168173
}
169174
}
170175

171-
// from ldr/pe/pe.h
172-
#define PE_NODE "$ PE header" // netnode name for PE header
173-
// value() -> peheader_t
174-
// altval(segnum) -> s->start_ea
175-
#define PE_ALT_DBG_FPOS nodeidx_t(-1) // altval() -> translated fpos of debuginfo
176-
#define PE_ALT_IMAGEBASE nodeidx_t(-2) // altval() -> loading address (usually pe.imagebase)
177-
#define PE_ALT_PEHDR_OFF nodeidx_t(-3) // altval() -> offset of PE header
178-
#define PE_ALT_NEFLAGS nodeidx_t(-4) // altval() -> neflags
179-
#define PE_ALT_TDS_LOADED nodeidx_t(-5) // altval() -> tds already loaded(1) or invalid(-1)
180-
#define PE_ALT_PSXDLL nodeidx_t(-6) // altval() -> if POSIX(x86) imports from PSXDLL netnode
181-
#define PE_ALT_OVRVA nodeidx_t(-7) // altval() -> overlay rva (if present)
182-
#define PE_ALT_OVRSZ nodeidx_t(-8) // altval() -> overlay size (if present)
183-
#define PE_SUPSTR_PDBNM nodeidx_t(-9) // supstr() -> pdb file name
184-
// supval(segnum) -> pesection_t
185-
// blob(0, PE_NODE_RELOC) -> relocation info
186-
// blob(0, RSDS_TAG) -> rsds_t structure
187-
// blob(0, NB10_TAG) -> cv_info_pdb20_t structure
188-
#define PE_ALT_NTAPI nodeidx_t(-10) // altval() -> uses Native API
189-
#define PE_EMBED_PDB_OFF nodeidx_t(-11) // altval() -> offset of embedded PDB file
190-
#define PE_NODE_RELOC 'r'
191-
#define RSDS_TAG 's'
192-
#define NB10_TAG 'n'
193-
#define UTDS_TAG 't'
176+
// marked virtual but not pure virtual, grr
177+
bool pe_loader_t::vseek(linput_t* li, uint32 rva)
178+
{
179+
qlseek(li, rva, 0);
180+
return true;
181+
}
194182

195183
void pe_setup_netnode(XEXFile& file)
196184
{
197185
netnode penode;
198186
penode.create(PE_NODE);
199187

188+
const uint8_t* pe_data = file.pe_data();
189+
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)pe_data;
190+
191+
// Set PE header node data
192+
// Make a copy of PE header and update with correct values first, since IDA/eh_parse reads some info from this
193+
IMAGE_NT_HEADERS nt_header = *(IMAGE_NT_HEADERS*)(pe_data + dos_header->AddressOfNewExeHeader);
194+
nt_header.OptionalHeader.ImageBase = file.base_address();
195+
196+
penode.set(&nt_header, sizeof(IMAGE_NT_HEADERS));
197+
198+
// Update imagebase
200199
penode.altset(PE_ALT_IMAGEBASE, file.base_address());
201200

201+
// Ask eh_parse to parse .pdata for us
202+
// IDA itself seems to handle parsing .pdata if PE header is set above, but only at end of autoanalysis, which could take a while on large games
203+
// Requesting eh_parse after we've loaded in should allow the funcs there to be marked earlier
204+
{
205+
auto* plugin = find_plugin("eh_parse", true);
206+
if (plugin)
207+
{
208+
run_plugin(plugin, 0);
209+
210+
// TODO: Why isn't this included in IDASDK ;_; may cause breakage if eh_parse is ever updated!
211+
struct eh_parse_t
212+
{
213+
virtual bool idaapi _0() = 0;
214+
virtual bool idaapi _8() = 0;
215+
virtual bool idaapi _10() = 0;
216+
virtual bool idaapi _18() = 0;
217+
virtual bool idaapi _20() = 0;
218+
virtual bool idaapi read_pdata_28(pe_loader_t* a2, linput_t* a3, char a4) = 0;
219+
220+
uint64_t unk_8;
221+
uint64_t unk_10;
222+
uint64_t unk_18;
223+
uint64_t imagebase_20;
224+
};
225+
226+
eh_parse_t* eh_parse = (eh_parse_t*)processor_t::notify(processor_t::event_t::ev_broadcast, 0x45485F5041525345, 0);
227+
if (eh_parse)
228+
{
229+
eh_parse->imagebase_20 = file.base_address();
230+
231+
pe_loader_t pe;
232+
pe.set_imagebase(file.base_address());
233+
234+
linput_t* memory = create_memory_linput(file.base_address(), file.image_size());
235+
eh_parse->read_pdata_28(&pe, memory, 0);
236+
close_linput(memory);
237+
}
238+
}
239+
}
240+
202241
size_t cv_length = 0;
203242
auto* cv_data = file.codeview_data(0, &cv_length);
204243
if (cv_data)
@@ -218,7 +257,7 @@ void pe_setup_netnode(XEXFile& file)
218257

219258
// Prompt for PDB load
220259
msg("Prompting for PDB load...\n(full X360 type loading may require pdb.cfg PDB_PROVIDER = PDB_PROVIDER_MSDIA !)\n");
221-
auto* plugin = find_plugin("pdb", 1LL);
260+
auto* plugin = find_plugin("pdb", true);
222261
run_plugin(plugin, 1LL);
223262
}
224263
}

idaxex.vcxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<PropertyGroup Label="UserMacros" />
4242
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
4343
<ClCompile>
44-
<AdditionalIncludeDirectories>..\..\include;3rdparty/excrypt/src;3rdparty/mspack%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
44+
<AdditionalIncludeDirectories>..\..\include;..\..\ldr\pe;3rdparty/excrypt/src;3rdparty/mspack%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
4545
<PreprocessorDefinitions>__NT__;IDALDR;__EA64__;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
4646
<LanguageStandard>stdcpp20</LanguageStandard>
4747
</ClCompile>
@@ -51,7 +51,7 @@
5151
</ItemDefinitionGroup>
5252
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
5353
<ClCompile>
54-
<AdditionalIncludeDirectories>..\..\include;3rdparty/excrypt/src;3rdparty/mspack%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
54+
<AdditionalIncludeDirectories>..\..\include;..\..\ldr\pe;3rdparty/excrypt/src;3rdparty/mspack%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
5555
<PreprocessorDefinitions>__NT__;IDALDR;__EA64__;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
5656
<LanguageStandard>stdcpp20</LanguageStandard>
5757
</ClCompile>

0 commit comments

Comments
 (0)