update to ida 7.6, add builds
This commit is contained in:
701
idasdk76/ldr/pe/common.cpp
Normal file
701
idasdk76/ldr/pe/common.cpp
Normal file
@@ -0,0 +1,701 @@
|
||||
|
||||
#include <auto.hpp>
|
||||
#include "common.h"
|
||||
#include "../idaldr.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
#ifdef LOADER_SOURCE // building a loader?
|
||||
AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
qstring question("AUTOHIDE REGISTRY\n");
|
||||
question.cat_vsprnt(format, va);
|
||||
question.append("\nDo you wish to continue?");
|
||||
if ( ask_yn(ASKBTN_YES, "%s", question.c_str()) != ASKBTN_YES )
|
||||
{
|
||||
loader_failure(NULL);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
#else
|
||||
// for other purposes: just print the error message and continue
|
||||
AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
qvprintf(format, va);
|
||||
qprintf("\n");
|
||||
va_end(va);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe64_to_pe(peheader_t &pe, const peheader64_t &pe64, bool silent, bool zero_bad_data)
|
||||
{
|
||||
bool ok = true;
|
||||
switch ( pe64.magic )
|
||||
{
|
||||
default:
|
||||
if ( !silent )
|
||||
{
|
||||
ask_for_feedback("The input file has non-standard magic number (%x)",
|
||||
pe64.magic);
|
||||
}
|
||||
ok = false;
|
||||
/* no break */
|
||||
case MAGIC_P32:
|
||||
case MAGIC_ROM:
|
||||
case 0:
|
||||
memcpy(&pe, &pe64, sizeof(pe));
|
||||
break;
|
||||
case MAGIC_P32_PLUS:
|
||||
// Copy the constant part
|
||||
memcpy(&pe, &pe64, offsetof(peheader_t, stackres));
|
||||
|
||||
// Copy after the changed part
|
||||
memcpy(&pe.loaderflags, &pe64.loaderflags,
|
||||
sizeof(pe) - qoffsetof(peheader_t, loaderflags));
|
||||
|
||||
// Truncate the 64bit to 32bit
|
||||
pe.stackres = low(pe64.stackres);
|
||||
pe.stackcom = low(pe64.stackcom);
|
||||
pe.heapres = low(pe64.heapres);
|
||||
pe.heapcom = low(pe64.heapcom);
|
||||
break;
|
||||
}
|
||||
// Do various checks
|
||||
if ( !pe.is_efi()
|
||||
&& (pe.objalign < pe.filealign
|
||||
|| pe.filealign != 0 && (pe.filealign & (pe.filealign-1)) != 0 // check for power of 2
|
||||
|| pe.objalign != 0 && (pe.objalign & (pe.objalign -1)) != 0) ) // check for power of 2
|
||||
{
|
||||
if ( !silent )
|
||||
pe_failure("Invalid file: bad alignment value specified (section alignment: %08X, file alignment: %08X)", pe.objalign, pe.filealign);
|
||||
}
|
||||
if ( pe.imagesize > 0x77000000 || pe.imagesize < pe.allhdrsize )
|
||||
{
|
||||
if ( !silent )
|
||||
pe_failure("Invalid file: bad ImageSize value %x", pe.imagesize);
|
||||
}
|
||||
|
||||
if ( zero_bad_data )
|
||||
{
|
||||
if ( pe.nrvas != 0 && pe.nrvas < total_rvatab_count )
|
||||
memset(&pe.expdir + pe.nrvas, 0, total_rvatab_size - pe.nrvas * sizeof(petab_t));
|
||||
size_t fullhdrsize = pe.is_pe_plus() ? sizeof(pe64) : sizeof(pe);
|
||||
size_t sectblstart = pe.first_section_pos(0);
|
||||
// clear items covered by section table
|
||||
if ( sectblstart < fullhdrsize
|
||||
&& total_rvatab_size < fullhdrsize
|
||||
&& sectblstart >= fullhdrsize - total_rvatab_size )
|
||||
{
|
||||
if ( !silent )
|
||||
msg("Warning: image directories are covered by the section table, some entries will be ignored\n");
|
||||
size_t clearcount = (fullhdrsize - sectblstart + sizeof(petab_t) -1 )/ sizeof(petab_t);
|
||||
memset(&pe.expdir + (total_rvatab_count- clearcount), 0, clearcount * sizeof(petab_t));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool te_to_pe(peheader_t &pe, const teheader_t &te)
|
||||
{
|
||||
bool ok = true;
|
||||
memset(&pe, 0, sizeof(pe));
|
||||
pe.signature = te.signature;
|
||||
pe.machine = te.machine;
|
||||
pe.nobjs = te.nobjs;
|
||||
pe.magic = pe.is_64bit_cpu() ? MAGIC_P32_PLUS : MAGIC_P32;
|
||||
pe.entry = te.entry;
|
||||
pe.text_start = te.text_start;
|
||||
pe.allhdrsize = te.text_start + te.te_adjust();
|
||||
if ( pe.is_pe_plus() )
|
||||
pe.imagebase64 = te.imagebase64;
|
||||
else
|
||||
pe.imagebase32 = te.imagebase64;
|
||||
pe.subsys = te.subsys;
|
||||
pe.reltab = te.reltab;
|
||||
pe.debdir = te.debdir;
|
||||
pe.objalign = 1;
|
||||
pe.filealign = 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data)
|
||||
{
|
||||
peoff = _peoff;
|
||||
qlseek(li, peoff);
|
||||
memset(&pe64, 0, sizeof(pe64));
|
||||
qlseek(li, peoff);
|
||||
size_t size = qlread(li, &pe64, sizeof(pe64));
|
||||
size_t minsize = pe64.magic == MAGIC_P32_PLUS
|
||||
? qoffsetof(peheader64_t, subsys)
|
||||
: qoffsetof(peheader_t, subsys);
|
||||
bool ok = size > minsize
|
||||
&& size <= sizeof(pe64)
|
||||
&& (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID)
|
||||
&& pe64_to_pe(pe, pe64, silent, zero_bad_data);
|
||||
if ( ok )
|
||||
{
|
||||
// initialize imagebase for loading
|
||||
set_imagebase((ea_t)pe.imagebase());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_header(linput_t *li, bool silent, bool zero_bad_data)
|
||||
{
|
||||
uint32 hdroff = 0;
|
||||
link_ulink = false;
|
||||
|
||||
qlseek(li, hdroff);
|
||||
if ( qlread(li, &exe, sizeof(exe)) != sizeof(exe) )
|
||||
return false;
|
||||
if ( exe.exe_ident != PEEXE_ID )
|
||||
{
|
||||
if ( exe.exe_ident == TEEXE_ID )
|
||||
{
|
||||
qlseek(li, hdroff);
|
||||
if ( qlread(li, &te, sizeof(te)) != sizeof(te) )
|
||||
return false;
|
||||
bool ok = te_to_pe(pe, te);
|
||||
if ( ok )
|
||||
{
|
||||
// initialize imagebase for loading
|
||||
set_imagebase((ea_t)pe.imagebase());
|
||||
peoff = hdroff;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
if ( exe.exe_ident == EXE_ID || exe.exe_ident == EXE_ID2 )
|
||||
{
|
||||
char tmp[8];
|
||||
if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp)
|
||||
&& memcmp(tmp, "UniLink", 8) == 0 )
|
||||
{
|
||||
link_ulink = true;
|
||||
}
|
||||
qlseek(li, PE_PTROFF);
|
||||
if ( qlread(li, &hdroff, sizeof(hdroff)) != sizeof(hdroff) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return read_header(li, hdroff, silent, zero_bad_data);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::vseek(linput_t *li, uint32 rva)
|
||||
{
|
||||
ea_t fpos = get_linput_type(li) == LINPUT_PROCMEM ? rva : map_ea(rva);
|
||||
if ( fpos != BADADDR )
|
||||
{
|
||||
qlseek(li, fpos);
|
||||
return true;
|
||||
}
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline char *pe_loader_t::asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok)
|
||||
{
|
||||
vseek(li, rva);
|
||||
buf[0] = '\0';
|
||||
char *ret = qlgetz(li, -1, buf, bufsize);
|
||||
*ok = buf[0] != '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// same as asciiz() but don't set ok to false for successfully read empty strings
|
||||
inline char *pe_loader_t::asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok)
|
||||
{
|
||||
vseek(li, rva);
|
||||
buf[0] = '\0';
|
||||
// do not use qlgetz() here because we won't distinguish empty strings from read errors
|
||||
ssize_t readsize = qlread(li, buf, bufsize-1);
|
||||
if ( readsize < 0 || readsize >= bufsize )
|
||||
*ok = false;
|
||||
else
|
||||
buf[readsize] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(
|
||||
linput_t *li,
|
||||
off_t first_sec_pos,
|
||||
int nobjs,
|
||||
pe_section_visitor_t &psv)
|
||||
{
|
||||
transvec.qclear();
|
||||
qvector<pesection_t> sec_headers;
|
||||
// does the file layout match memory layout?
|
||||
bool alt_align = pe.objalign == pe.filealign && pe.objalign < PAGE_SIZE;
|
||||
qlseek(li, first_sec_pos);
|
||||
validate_array_count(li, &nobjs, sizeof(pesection_t), "Number of sections", first_sec_pos);
|
||||
for ( int i=0; i < nobjs; i++ )
|
||||
{
|
||||
pesection_t &sh = sec_headers.push_back();
|
||||
if ( qlread(li, &sh, sizeof(sh)) != sizeof(sh) )
|
||||
return -1;
|
||||
if ( sh.s_vaddr != uint32(sh.s_scnptr) || sh.s_vsize > sh.s_psize )
|
||||
alt_align = false;
|
||||
}
|
||||
if ( alt_align || pe.is_te() )
|
||||
{
|
||||
// according to Ivan Teblin from AVERT Labs, such files are
|
||||
// mapped by Windows as-is and not section by section
|
||||
// we mimic that behaviour
|
||||
int code = psv.load_all();
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
}
|
||||
|
||||
int off_align = alt_align ? pe.filealign : FILEALIGN;
|
||||
if ( pe.is_efi() || pe.is_te() )
|
||||
off_align = 1;
|
||||
|
||||
uint32 max_va = 0;
|
||||
for ( int i=0; i < nobjs; i++ )
|
||||
{
|
||||
pesection_t &sh = sec_headers[i];
|
||||
uint32 scnptr = align_down(sh.s_scnptr, off_align);
|
||||
transl_t &tr = transvec.push_back();
|
||||
tr.start = sh.s_vaddr;
|
||||
tr.psize = sh.get_psize(pe);
|
||||
tr.end = pe.align_up_in_file(uint32(sh.s_vaddr + tr.psize));
|
||||
tr.pos = scnptr;
|
||||
if ( pe.is_te() )
|
||||
tr.pos += te.te_adjust();
|
||||
int code = psv.visit_section(sh, scnptr);
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
if ( max_va < sh.s_vaddr + sh.s_vsize )
|
||||
max_va = sh.s_vaddr + sh.s_vsize;
|
||||
}
|
||||
if ( pe.is_te() )
|
||||
pe.imagesize = max_va;
|
||||
if ( nobjs == 0 || alt_align )
|
||||
{
|
||||
// add mapping for the header
|
||||
transl_t tr;
|
||||
tr.start = 0;
|
||||
tr.psize = qlsize(li);
|
||||
tr.end = pe.align_up_in_file(pe.imagesize);
|
||||
tr.pos = 0;
|
||||
// insert at the front so that it's always consulted last
|
||||
transvec.insert(transvec.begin(), tr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(linput_t *li, pe_section_visitor_t &psv)
|
||||
{
|
||||
off_t first_sec_pos = pe.is_te() ? te.first_section_pos(peoff) : pe.first_section_pos(peoff);
|
||||
return process_sections(li, first_sec_pos, pe.nobjs, psv);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(linput_t *li)
|
||||
{
|
||||
pe_section_visitor_t v;
|
||||
return process_sections(li, v);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline void to_utf8(char *buf, size_t bufsz, bool force=false)
|
||||
{
|
||||
if ( force || !is_valid_utf8(buf) )
|
||||
{
|
||||
qstring qbuf;
|
||||
if ( idb_utf8(&qbuf, buf) )
|
||||
qstrncpy(buf, qbuf.c_str(), bufsz);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process import table for one dll
|
||||
inline int pe_loader_t::process_import_table(
|
||||
linput_t *li,
|
||||
ea_t atable,
|
||||
ea_t ltable,
|
||||
pe_import_visitor_t &piv)
|
||||
{
|
||||
bool is_pe_plus = pe.is_pe_plus();
|
||||
uint32 elsize = piv.elsize = is_pe_plus ? 8 : 4;
|
||||
const uint64 mask = is_pe_plus ? IMP_BY_ORD64 : IMP_BY_ORD32;
|
||||
bool ok = true;
|
||||
uint32 i;
|
||||
for ( i=0; ok; i++, atable += elsize )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
if ( !is_mul_ok(i, elsize) )
|
||||
return 1;
|
||||
uval_t rva_off = i * elsize;
|
||||
if ( !is_add_ok(ltable, rva_off) )
|
||||
return 1;
|
||||
ea_t rva = ltable + rva_off;
|
||||
if ( piv.withbase )
|
||||
rva -= (uval_t)pe.imagebase();
|
||||
uint32 fof = uint32(rva);
|
||||
uint64 entry = is_pe_plus ? vaint64(li, fof, &ok) : valong(li, fof, &ok);
|
||||
if ( entry == 0 )
|
||||
break;
|
||||
show_addr(atable);
|
||||
|
||||
int code;
|
||||
if ( (entry & mask) == 0 ) // by name
|
||||
{
|
||||
ea_t nrva = (uval_t)entry + sizeof(short);
|
||||
if ( piv.withbase )
|
||||
nrva -= (uval_t)pe.imagebase();
|
||||
fof = uint32(nrva);
|
||||
asciiz2(li, fof, buf, sizeof(buf), &ok);
|
||||
to_utf8(buf, sizeof(buf));
|
||||
code = piv.visit_import(atable, entry, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ordinals are always 32bit, even in pe64
|
||||
uint32 ord = entry & ~mask;
|
||||
code = piv.visit_import(atable, ord, NULL);
|
||||
}
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
}
|
||||
return piv.leave_module(i);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// this function tries to read from a file as if it was reading from memory
|
||||
// if translation not found for the given RVA then ZEROs are returned
|
||||
// in addition, if it tries to read beyond a translation physical size
|
||||
// the additional bytes will be returned as zeros
|
||||
inline bool pe_loader_t::vmread(linput_t *li, uint32 rva, void *buf, size_t sz)
|
||||
{
|
||||
// clear whole user buffer
|
||||
memset(buf, 0, sz);
|
||||
|
||||
size_t may_read = sz;
|
||||
if ( get_linput_type(li) == LINPUT_PROCMEM )
|
||||
{
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
const transl_t *tr;
|
||||
ea_t fpos = map_ea(rva, &tr);
|
||||
|
||||
// cannot find translation?
|
||||
if ( fpos == BADADDR )
|
||||
{
|
||||
qlseek(li, int32(rva), SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
uint32 sectend = tr->pos + tr->psize; // section end
|
||||
if ( fpos >= sectend )
|
||||
return false; // data not present in the input file
|
||||
qlseek(li, fpos);
|
||||
|
||||
// reading beyond section's limit?
|
||||
uint32 after_read_pos = fpos + sz;
|
||||
if ( after_read_pos < fpos )
|
||||
return false; // integer overflow
|
||||
if ( after_read_pos >= sectend )
|
||||
{
|
||||
// check if position belongs to the header and if reading beyond the limit
|
||||
if ( uint32(fpos) < pe.allhdrsize && after_read_pos > pe.allhdrsize )
|
||||
may_read = pe.allhdrsize - size_t(fpos);
|
||||
else
|
||||
may_read = sectend - fpos; // just read as much as section limit allows
|
||||
}
|
||||
}
|
||||
QASSERT(20045, ssize_t(may_read) >= 0);
|
||||
return qlread(li, buf, may_read) == (ssize_t)may_read;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process all imports of a pe file
|
||||
// returns: -1:could not read an impdir; 0-ok;
|
||||
// other values can be returned by the visitor
|
||||
inline int pe_loader_t::process_imports(linput_t *li, pe_import_visitor_t &piv)
|
||||
{
|
||||
if ( pe.impdir.rva == 0 )
|
||||
return 0;
|
||||
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
|
||||
int code = 0;
|
||||
for ( int ni=0; ; ni++ )
|
||||
{
|
||||
off_t off = pe.impdir.rva + ni*sizeof(peimpdir_t);
|
||||
peimpdir_t &id = piv.id;
|
||||
|
||||
if ( !vmread(li, off, &id, sizeof(id)) )
|
||||
{
|
||||
memset(&id, 0, sizeof(id));
|
||||
// we continue if the import descriptor is within the page belonging
|
||||
// to the program
|
||||
if ( map_ea(off) == BADADDR || map_ea(off+sizeof(id)-1) == BADADDR )
|
||||
{
|
||||
code = piv.impdesc_error(off);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( id.dllname == 0 || id.looktab == 0 )
|
||||
break;
|
||||
ea_t ltable = id.table1; // OriginalFirstThunk
|
||||
ea_t atable = id.looktab; // FirstThunk
|
||||
bool ok = true;
|
||||
char dll[MAXSTR];
|
||||
asciiz(li, id.dllname, dll, sizeof(dll), &ok);
|
||||
if ( !ok )
|
||||
break;
|
||||
to_utf8(dll, sizeof(dll), /*force=*/ true);
|
||||
if ( map_ea(ltable) == BADADDR
|
||||
|| ltable < pe.allhdrsize
|
||||
|| pe.imagesize != 0 && ltable >= pe.imagesize )
|
||||
{
|
||||
ltable = atable;
|
||||
}
|
||||
atable += get_imagebase();
|
||||
code = piv.visit_module(dll, atable, ltable);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
code = process_import_table(li, atable, ltable, piv);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_delayed_imports(linput_t *li, pe_import_visitor_t &il)
|
||||
{
|
||||
if ( pe.didtab.rva == 0 )
|
||||
return 0;
|
||||
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
|
||||
int code = 0;
|
||||
uint32 ni = 0;
|
||||
bool ok = true;
|
||||
while ( true )
|
||||
{
|
||||
uint32 table = pe.didtab.rva + ni*uint32(sizeof(dimpdir_t));
|
||||
if ( !vseek(li, table) )
|
||||
break;
|
||||
dimpdir_t &id = il.did;
|
||||
if ( qlread(li, &id, sizeof(id)) != sizeof(id) )
|
||||
return -1;
|
||||
if ( !id.dllname )
|
||||
break;
|
||||
il.withbase = (id.attrs & DIMP_NOBASE) == 0;
|
||||
uval_t base = il.withbase ? 0 : uval_t(get_imagebase());
|
||||
ea_t atable = id.diat + base;
|
||||
ea_t ltable = id.dint;
|
||||
char dll[MAXSTR];
|
||||
uint32 off = uint32(il.withbase ? id.dllname - (ea_t)pe.imagebase() : id.dllname);
|
||||
asciiz(li, off, dll, sizeof(dll), &ok);
|
||||
if ( !ok )
|
||||
break;
|
||||
to_utf8(dll, sizeof(dll), /*force=*/ true);
|
||||
code = il.visit_module(dll, atable, ltable);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
code = process_import_table(li, atable, ltable, il);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
ni++;
|
||||
}
|
||||
return ok || code != 0 ? code : -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process all exports of a pe file
|
||||
// returns -2: could not read expdir, -1: other read errors, 0-ok,
|
||||
// other values can be returned by the visitor
|
||||
inline int pe_loader_t::process_exports(linput_t *li, pe_export_visitor_t &pev)
|
||||
{
|
||||
if ( pe.expdir.rva == 0 )
|
||||
return 0;
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
if ( !vseek(li, pe.expdir.rva) )
|
||||
return -2;
|
||||
|
||||
// process export directory
|
||||
bool fok = true;
|
||||
char buf[MAXSTR];
|
||||
peexpdir_t ed;
|
||||
if ( qlread(li, &ed, sizeof(ed)) != sizeof(ed) )
|
||||
return -1;
|
||||
asciiz2(li, ed.dllname, buf, sizeof(buf), &fok);
|
||||
to_utf8(buf, sizeof(buf), /*force=*/ true);
|
||||
int code = pev.visit_expdir(ed, buf);
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
|
||||
// I'd like to have a better validation
|
||||
uint64 maxsize = qlsize(li) + 4096;
|
||||
if ( maxsize > pe.expdir.size && pe.expdir.size != 0 )
|
||||
maxsize = pe.expdir.size;
|
||||
validate_array_count(NULL, &ed.nnames, 6, "Number of exported names",
|
||||
pe.expdir.rva, pe.expdir.rva+maxsize);
|
||||
validate_array_count(NULL, &ed.naddrs, 4, "Number of exported addresses",
|
||||
pe.expdir.rva, pe.expdir.rva+maxsize);
|
||||
|
||||
// gather name information
|
||||
typedef std::map<int, qstring> names_t;
|
||||
names_t names;
|
||||
int rcode = fok ? 0 : -1;
|
||||
for ( uint32 i=0; i < ed.nnames; i++ )
|
||||
{
|
||||
fok = true;
|
||||
uint32 ordidx = vashort(li, ed.ordtab + i*sizeof(ushort), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
ushort ord = ushort(ordidx + ed.ordbase);
|
||||
uint32 rva = valong(li, ed.namtab + i*sizeof(uint32), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
asciiz2(li, rva, buf, sizeof(buf), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
to_utf8(buf, sizeof(buf));
|
||||
names[ord] = buf;
|
||||
}
|
||||
|
||||
// visit all exports
|
||||
uint32 expdir_start_rva = pe.expdir.rva;
|
||||
uint32 expdir_end_rva = pe.expdir.rva + maxsize;
|
||||
|
||||
for ( uint32 i = 0; i < ed.naddrs; i++ )
|
||||
{
|
||||
fok = true;
|
||||
uint32 rva = valong(li, ed.adrtab + i*sizeof(uint32), &fok);
|
||||
if ( rva != 0 && fok )
|
||||
{
|
||||
uint32 ord = i + ed.ordbase;
|
||||
names_t::iterator p = names.find(ord);
|
||||
const char *name = p != names.end() ? p->second.c_str() : "";
|
||||
const char *forwarder = NULL;
|
||||
if ( rva >= expdir_start_rva && rva < expdir_end_rva )
|
||||
{
|
||||
// string inside export directory: this is a forwarded export
|
||||
asciiz(li, rva, buf, sizeof(buf), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
char *dot = strrchr(buf, '.');
|
||||
if ( dot != NULL )
|
||||
{
|
||||
char before_dot[MAXSTR];
|
||||
char after_dot[MAXSTR];
|
||||
*dot = '\0';
|
||||
qstrncpy(before_dot, buf, sizeof(before_dot));
|
||||
qstrncpy(after_dot, dot+1, sizeof(after_dot));
|
||||
to_utf8(before_dot, sizeof(before_dot), /*force=*/ true);
|
||||
to_utf8(after_dot, sizeof(after_dot), /*force=*/ false);
|
||||
qsnprintf(buf, sizeof(buf), "%s.%s", before_dot, after_dot);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_utf8(buf, sizeof(buf), /*force=*/ true);
|
||||
}
|
||||
forwarder = buf;
|
||||
}
|
||||
code = pev.visit_export(rva, ord, name, forwarder);
|
||||
if ( code != 0 )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = code;
|
||||
}
|
||||
}
|
||||
else if ( !fok )
|
||||
rcode = -1;
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const char *get_pe_machine_name(uint16 machine)
|
||||
{
|
||||
switch ( machine )
|
||||
{
|
||||
case PECPU_80386: return "80386";
|
||||
case PECPU_80486: return "80486";
|
||||
case PECPU_80586: return "80586";
|
||||
case PECPU_SH3: return "SH3";
|
||||
case PECPU_SH3DSP: return "SH3DSP";
|
||||
case PECPU_SH3E: return "SH3E";
|
||||
case PECPU_SH4: return "SH4";
|
||||
case PECPU_SH5: return "SH5";
|
||||
case PECPU_ARM: return "ARM";
|
||||
case PECPU_ARMI: return "ARMI";
|
||||
case PECPU_ARMV7: return "ARMv7";
|
||||
case PECPU_EPOC: return "ARM EPOC";
|
||||
case PECPU_PPC: return "PPC";
|
||||
case PECPU_PPCFP: return "PPC FP";
|
||||
case PECPU_PPCBE: return "PPC BE";
|
||||
case PECPU_IA64: return "IA64";
|
||||
case PECPU_R3000: return "MIPS R3000";
|
||||
case PECPU_R4000: return "MIPS R4000";
|
||||
case PECPU_R6000: return "MIPS R6000";
|
||||
case PECPU_R10000: return "MIPS R10000";
|
||||
case PECPU_MIPS16: return "MIPS16";
|
||||
case PECPU_WCEMIPSV2: return "MIPS WCEv2";
|
||||
case PECPU_ALPHA: return "ALPHA";
|
||||
case PECPU_ALPHA64: return "ALPHA 64";
|
||||
case PECPU_AMD64: return "AMD64";
|
||||
case PECPU_ARM64: return "ARM64";
|
||||
case PECPU_M68K: return "M68K";
|
||||
case PECPU_MIPSFPU: return "MIPS FPU";
|
||||
case PECPU_MIPSFPU16: return "MIPS16 FPU";
|
||||
case PECPU_EBC: return "EFI Bytecode";
|
||||
case PECPU_AM33: return "AM33";
|
||||
case PECPU_M32R: return "M32R";
|
||||
case PECPU_CEF: return "CEF";
|
||||
case PECPU_CEE: return "CEE";
|
||||
case PECPU_TRICORE: return "TRICORE";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_strtable(qstring *out, linput_t *li)
|
||||
{
|
||||
bool ok = false;
|
||||
if ( pe.symtof != 0 )
|
||||
{
|
||||
qoff64_t strtoff = qoff64_t(pe.symtof) + pe.nsyms * 18;
|
||||
ok = read_string_table(out, li, strtoff);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
306
idasdk76/ldr/pe/common.h
Normal file
306
idasdk76/ldr/pe/common.h
Normal file
@@ -0,0 +1,306 @@
|
||||
#ifndef _PE_LDR_COMMON_H_
|
||||
#define _PE_LDR_COMMON_H_
|
||||
|
||||
#include <netnode.hpp>
|
||||
#include <idp.hpp>
|
||||
#include <loader.hpp>
|
||||
#include <diskio.hpp>
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
//------------------------------------------------------------------------
|
||||
struct pe_section_visitor_t
|
||||
{
|
||||
virtual int idaapi visit_section(const pesection_t &, off_t /*file_offset*/) { return 0; }
|
||||
virtual int idaapi load_all() { return 0; }
|
||||
virtual ~pe_section_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//-V:pe_import_visitor_t:730 not all members of a class are initialized inside the constructor
|
||||
struct pe_import_visitor_t
|
||||
{
|
||||
bool withbase;
|
||||
int elsize; // initialized by process_import_table()
|
||||
peimpdir_t id;
|
||||
dimpdir_t did;
|
||||
|
||||
pe_import_visitor_t(void) : withbase(false) {}
|
||||
virtual int idaapi visit_module(const char * /*dll*/, ea_t /*iat_start*/, ea_t /*int_rva*/) { return 0; }
|
||||
virtual int idaapi leave_module(uint32 /*nprocessed_imports*/) { return 0; }
|
||||
// buf==NULL:by ordinal
|
||||
virtual int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) = 0;
|
||||
virtual int idaapi impdesc_error(off_t /*file_offset*/) { return 0; }
|
||||
virtual ~pe_import_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct pe_export_visitor_t
|
||||
{
|
||||
// this function will be called once at the start.
|
||||
// it must return 0 to continue
|
||||
virtual int idaapi visit_expdir(const peexpdir_t & /*ed*/, const char * /*modname*/) { return 0; }
|
||||
// this function is called for each export. name is never NULL, forwarder may point to the forwarder function
|
||||
// it must return 0 to continue
|
||||
virtual int idaapi visit_export(uint32 rva, uint32 ord, const char *name, const char *forwarder) = 0;
|
||||
virtual ~pe_export_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class pe_loader_t
|
||||
{
|
||||
int process_import_table(
|
||||
linput_t *li,
|
||||
ea_t atable,
|
||||
ea_t ltable,
|
||||
pe_import_visitor_t &piv);
|
||||
template <class T>
|
||||
T varead(linput_t *li, uint32 rva, bool *ok)
|
||||
{
|
||||
T x = 0;
|
||||
bool _ok = vseek(li, rva) && qlread(li, &x, sizeof(x)) == sizeof(x);
|
||||
if ( ok != NULL )
|
||||
*ok = _ok;
|
||||
return x;
|
||||
}
|
||||
public:
|
||||
struct transl_t
|
||||
{
|
||||
ea_t start;
|
||||
ea_t end;
|
||||
off_t pos;
|
||||
size_t psize;
|
||||
};
|
||||
typedef qvector<transl_t> transvec_t;
|
||||
transvec_t transvec;
|
||||
union
|
||||
{
|
||||
exehdr exe;
|
||||
teheader_t te;
|
||||
};
|
||||
peheader_t pe;
|
||||
peheader64_t pe64; // original 64bit header, should not be used
|
||||
// because all fields are copied to pe
|
||||
// nb: imagebase is truncated during the copy!
|
||||
ea_t load_imagebase; // imagebase used during loading; initialized from the PE header but can be changed by the user
|
||||
off_t peoff; // offset to pe header
|
||||
bool link_ulink; // linked with unilink?
|
||||
|
||||
// low level functions
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// NB! We need to walk the mapping backwards, because
|
||||
// the later sections take priority over earlier ones
|
||||
//
|
||||
// e.g. consider
|
||||
// section 0: start=1000, end=5000, pos=1000
|
||||
// section 1: start=3000, end=4000, pos=5000
|
||||
// for byte at RVA 3500:
|
||||
// section 0 maps it from the file offset 3500
|
||||
// but section 1 overrides it with the byte from file offset 5500!
|
||||
//
|
||||
inline ea_t map_ea(ea_t rva, const transl_t **tl=NULL)
|
||||
{
|
||||
for ( ssize_t i=transvec.size()-1; i >= 0; i-- )
|
||||
{
|
||||
const transl_t &trans = transvec[i];
|
||||
if ( trans.start <= rva && trans.end > rva )
|
||||
{
|
||||
if ( tl != NULL )
|
||||
*tl = &trans;
|
||||
return rva-trans.start + trans.pos;
|
||||
}
|
||||
}
|
||||
return BADADDR;
|
||||
}
|
||||
ea_t get_imagebase(void) const { return load_imagebase; }
|
||||
void set_imagebase(ea_t newimagebase) { load_imagebase=newimagebase; }
|
||||
virtual bool vseek(linput_t *li, uint32 rva);
|
||||
inline uint16 vashort(linput_t *li, uint32 addr, bool *ok) { return varead<uint16>(li, addr, ok); }
|
||||
inline uint32 valong(linput_t *li, uint32 addr, bool *ok) { return varead<uint32>(li, addr, ok); }
|
||||
inline uint64 vaint64(linput_t *li, uint32 addr, bool *ok) { return varead<uint64>(li, addr, ok); }
|
||||
char *asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok);
|
||||
char *asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok);
|
||||
int process_sections(linput_t *li, off_t fist_sec_pos, int nojbs, pe_section_visitor_t &psv);
|
||||
int process_sections(linput_t *li, pe_section_visitor_t &psv);
|
||||
// If 'zero_bad_data==true' (i.e., the default), extra 'directories'
|
||||
// in the pe/pe64 headers will be set to zero.
|
||||
bool read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data = true);
|
||||
|
||||
// high level functions
|
||||
bool read_header(linput_t *li, bool silent=false, bool zero_bad_data = true);
|
||||
int process_sections(linput_t *li);
|
||||
|
||||
int process_delayed_imports(linput_t *li, pe_import_visitor_t &il);
|
||||
int process_imports(linput_t *li, pe_import_visitor_t &piv);
|
||||
int process_exports(linput_t *li, pe_export_visitor_t &pev);
|
||||
bool vmread(linput_t *li, uint32 rva, void *buf, size_t sz);
|
||||
|
||||
bool read_strtable(qstring *out, linput_t *li);
|
||||
|
||||
virtual ~pe_loader_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct import_loader_t : public pe_import_visitor_t
|
||||
{
|
||||
struct dllinfo_t
|
||||
{
|
||||
qstring orig_name;
|
||||
qstring name;
|
||||
netnode node; // will be used by import_module()
|
||||
bool imported_module;
|
||||
|
||||
dllinfo_t()
|
||||
: imported_module(false)
|
||||
{}
|
||||
};
|
||||
typedef qvector<dllinfo_t> dllinfo_vec_t;
|
||||
|
||||
processor_t &ph;
|
||||
peheader_t &pe;
|
||||
dllinfo_vec_t dlls; // visited modules
|
||||
range_t imprange;
|
||||
ea_t astart;
|
||||
ea_t last_imp;
|
||||
ea_t int_rva;
|
||||
int ndid; // number of delayed import dirs
|
||||
bool displayed;
|
||||
bool got_new_imports;
|
||||
bool delayed_imports;
|
||||
|
||||
inline void preprocess(void);
|
||||
inline bool has_module(const char *mod) const
|
||||
{
|
||||
size_t ndlls = dlls.size();
|
||||
for ( size_t i = 0; i < ndlls; i++ )
|
||||
if ( !stricmp(dlls[i].orig_name.c_str(), mod) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int idaapi visit_module(const char *dll, ea_t iat_start, ea_t _int_rva) override;
|
||||
int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) override;
|
||||
int idaapi leave_module(uint32 nprocessed_imports) override;
|
||||
int idaapi impdesc_error(off_t off) override;
|
||||
inline void postprocess(void);
|
||||
|
||||
import_loader_t(processor_t &_ph, peheader_t &_pe, bool di)
|
||||
: ph(_ph), pe(_pe), astart(BADADDR), last_imp(BADADDR), int_rva(0),
|
||||
ndid(0),
|
||||
displayed(false), got_new_imports(false), delayed_imports(di)
|
||||
{
|
||||
imprange.start_ea = BADADDR;
|
||||
imprange.end_ea = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __EA64__
|
||||
|
||||
struct function_entry_x64
|
||||
{
|
||||
uint32 BeginAddress;
|
||||
uint32 EndAddress;
|
||||
uint32 UnwindData;
|
||||
bool operator<(const function_entry_x64 &r) const { return BeginAddress < r.BeginAddress; }
|
||||
bool operator!=(const function_entry_x64 &r) const
|
||||
{
|
||||
return BeginAddress != r.BeginAddress
|
||||
|| EndAddress != r.EndAddress
|
||||
|| UnwindData != r.UnwindData;
|
||||
}
|
||||
};
|
||||
|
||||
struct unwind_info_x64
|
||||
{
|
||||
uint8 Version_Flags;
|
||||
uint8 SizeOfProlog; //lint -e754 local structure member not referenced
|
||||
uint8 CountOfCodes;
|
||||
uint8 FrameRegister_Offset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ida_loader_t : public pe_loader_t
|
||||
{
|
||||
processor_t &ph;
|
||||
eavec_t asked_eas;
|
||||
import_loader_t imploader; // used in load_imports()
|
||||
import_loader_t didloader; // used in load_delayed_imports()
|
||||
eavec_t imp_fixups; // fixups to the import tables,
|
||||
// they will be updated after a creation of
|
||||
// the .idata segment
|
||||
bool loaded_header = false;
|
||||
bool vseek_asked = false;
|
||||
bool has_embedded_pdb = false;
|
||||
|
||||
virtual bool vseek(linput_t *li, uint32 rva) override
|
||||
{
|
||||
ea_t fpos;
|
||||
if ( get_linput_type(li) == LINPUT_PROCMEM )
|
||||
{
|
||||
fpos = rva;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpos = map_ea(rva);
|
||||
if ( fpos == BADADDR && rva < peoff+pe.allhdrsize )
|
||||
fpos = rva;
|
||||
}
|
||||
if ( fpos != BADADDR )
|
||||
{
|
||||
qoff64_t p2 = qlseek(li, qoff64_t(fpos));
|
||||
return p2 != -1;
|
||||
}
|
||||
if ( !vseek_asked
|
||||
&& ask_yn(ASKBTN_YES,
|
||||
"HIDECANCEL\n"
|
||||
"Can't find translation for relative virtual address %08X, continue?",
|
||||
rva) <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
vseek_asked = true;
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
return false;
|
||||
}
|
||||
ida_loader_t(void) //lint !e1401 non-static data member 'pe_loader_t::*' not initialized by constructor
|
||||
: ph(PH),
|
||||
imploader(ph, pe, false),
|
||||
didloader(ph, pe, true) {}
|
||||
|
||||
void setup_entry_and_dgroup(linput_t *li, sel_t dgroup);
|
||||
bool make_beginning_loaded(linput_t *li, ea_t begin);
|
||||
sel_t load_sections(linput_t *li, bool aux, const qstring *strtable=nullptr);
|
||||
void load_tls(linput_t *li);
|
||||
void load_exports(linput_t *li);
|
||||
void load_imports(linput_t *li);
|
||||
void load_delayed_imports(linput_t *li);
|
||||
void read_and_save_fixups(linput_t *li);
|
||||
bool has_imports_by_ordinal(linput_t *li);
|
||||
void load_cli_module(linput_t *_li);
|
||||
void load_pdata(linput_t *li);
|
||||
void pe_convert_idata();
|
||||
void comment_impexp(linput_t *li);
|
||||
void load_loadconfig(linput_t *li);
|
||||
void load_header_section(linput_t *li, bool visible);
|
||||
void load_debug_info(linput_t *li);
|
||||
void remember_imp_fixup(ea_t fixup_ea, ea_t target)
|
||||
{
|
||||
for ( const auto &impldr : { imploader, didloader } )
|
||||
{
|
||||
if ( impldr.imprange.contains(target) )
|
||||
{
|
||||
imp_fixups.add(fixup_ea);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool has_ntdll() const { return imploader.has_module("ntdll.dll"); }
|
||||
#ifdef __EA64__
|
||||
int check_chained_uw(linput_t *li, uint32 rva, function_entry_x64 *chained, int nest_count = 0);
|
||||
void load_pdata_x64(linput_t *li, uint32 pdata_rva, asize_t psize);
|
||||
bool has_bad_uwopcodes(linput_t *li, uint32 uw_rva, ea_t funcstart);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
2532
idasdk76/ldr/pe/cor.h
Normal file
2532
idasdk76/ldr/pe/cor.h
Normal file
File diff suppressed because it is too large
Load Diff
1845
idasdk76/ldr/pe/corhdr.h
Normal file
1845
idasdk76/ldr/pe/corhdr.h
Normal file
File diff suppressed because it is too large
Load Diff
507
idasdk76/ldr/pe/mycor.h
Normal file
507
idasdk76/ldr/pe/mycor.h
Normal file
@@ -0,0 +1,507 @@
|
||||
// Borland-compatible Microsoft.Net definitions
|
||||
// Only the most important headers are declared
|
||||
//
|
||||
// The second half of the file contains the structures saved in the
|
||||
// database
|
||||
|
||||
#ifndef __MYCOR_H
|
||||
#define __MYCOR_H
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#ifdef __NT__
|
||||
typedef wchar_t wchar;
|
||||
#else
|
||||
typedef wchar16_t wchar;
|
||||
#endif
|
||||
|
||||
#ifndef _WINDOWS_ // define some MS Windows symbols if <windows.h> is not included
|
||||
|
||||
#define __int8 char
|
||||
#ifdef __GNUC__
|
||||
#define __cdecl
|
||||
#define __stdcall
|
||||
#endif
|
||||
|
||||
typedef int32 HRESULT;
|
||||
#define S_OK 0
|
||||
#define S_FALSE (!S_OK)
|
||||
#define E_FAIL 0x80004005
|
||||
#define SEVERITY_SUCCESS 0
|
||||
#define SEVERITY_ERROR 1
|
||||
#define FACILITY_URT 19
|
||||
#define MAKE_HRESULT(sev,fac,code) \
|
||||
((HRESULT) (((uint32)(sev)<<31) | ((uint32)(fac)<<16) | ((uint32)(code))) )
|
||||
#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)
|
||||
#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)
|
||||
#define META_E_BAD_SIGNATURE EMAKEHR(0x1192) // Bad binary signature
|
||||
#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
||||
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
||||
#undef UNALIGNED
|
||||
#define UNALIGNED
|
||||
|
||||
typedef uchar BYTE;
|
||||
typedef short SHORT;
|
||||
typedef ushort USHORT;
|
||||
typedef ushort WORD;
|
||||
typedef uint32 ULONG;
|
||||
typedef uint ULONG32;
|
||||
typedef uint32 DWORD;
|
||||
typedef uint64 DWORD64;
|
||||
typedef void *LPVOID;
|
||||
typedef bool BOOL;
|
||||
typedef int32 LONG;
|
||||
typedef uint32 ULONG;
|
||||
typedef int64 LONGLONG;
|
||||
typedef uint64 ULONGLONG;
|
||||
typedef wchar *LPWSTR;
|
||||
typedef const void *UVCP_CONSTANT;
|
||||
typedef ULONG &LPCWSTR;
|
||||
typedef float FLOAT;
|
||||
typedef double DOUBLE;
|
||||
typedef uint32 SCODE;
|
||||
typedef void *BSTR; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069(v=vs.85).aspx
|
||||
typedef void *PVOID;
|
||||
typedef int INT;
|
||||
typedef uint UINT;
|
||||
typedef char CHAR;
|
||||
typedef DOUBLE DATE;
|
||||
|
||||
class IUnknown;
|
||||
|
||||
struct OSINFO
|
||||
{
|
||||
DWORD dwOSPlatformId;
|
||||
DWORD dwOSMajorVersion;
|
||||
DWORD dwOSMinorVersion;
|
||||
};
|
||||
|
||||
struct ASSEMBLYMETADATA
|
||||
{
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usBuildNumber;
|
||||
USHORT usRevisionNumber;
|
||||
LPWSTR szLocale;
|
||||
ULONG cbLocale;
|
||||
DWORD *rdwProcessor;
|
||||
ULONG ulProcessor;
|
||||
OSINFO *rOS;
|
||||
ULONG ulOS;
|
||||
};
|
||||
|
||||
struct GUID
|
||||
{
|
||||
uint32 Data1;
|
||||
ushort Data2;
|
||||
ushort Data3;
|
||||
uchar Data4[8];
|
||||
};
|
||||
|
||||
struct IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
uint32 VirtualAddress;
|
||||
uint32 Size;
|
||||
};
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221061(v=vs.85).aspx
|
||||
typedef struct tagDEC
|
||||
{
|
||||
USHORT wReserved;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE scale;
|
||||
BYTE sign;
|
||||
};
|
||||
USHORT signscale;
|
||||
};
|
||||
ULONG Hi32;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG Lo32;
|
||||
ULONG Mid32;
|
||||
};
|
||||
ULONGLONG Lo64;
|
||||
};
|
||||
} DECIMAL;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221223(v=vs.85).aspx
|
||||
typedef union tagCY
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long Lo;
|
||||
long Hi;
|
||||
};
|
||||
LONGLONG int64;
|
||||
} CY, CURRENCY;
|
||||
|
||||
|
||||
typedef struct tagSAFEARRAYBOUND
|
||||
{
|
||||
ULONG cElements;
|
||||
LONG lLbound;
|
||||
} SAFEARRAYBOUND, *LPSAFEARRAYBOUND;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/9ec8025b-4763-4526-ab45-390c5d8b3b1e(VS.85)
|
||||
typedef struct tagSAFEARRAY
|
||||
{
|
||||
USHORT cDims;
|
||||
USHORT fFeatures;
|
||||
ULONG cbElements;
|
||||
ULONG cLocks;
|
||||
PVOID pvData;
|
||||
SAFEARRAYBOUND rgsabound[1];
|
||||
} SAFEARRAY, *LPSAFEARRAY;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221627(v=vs.85).aspx
|
||||
typedef unsigned short VARTYPE;
|
||||
typedef uint16 VARIANT_BOOL;
|
||||
typedef uint16 _VARIANT_BOOL;
|
||||
struct IRecordInfo;
|
||||
typedef struct tagVARIANT
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
VARTYPE vt;
|
||||
WORD wReserved1;
|
||||
WORD wReserved2;
|
||||
WORD wReserved3;
|
||||
union
|
||||
{
|
||||
LONGLONG llVal;
|
||||
LONG lVal;
|
||||
BYTE bVal;
|
||||
SHORT iVal;
|
||||
FLOAT fltVal;
|
||||
DOUBLE dblVal;
|
||||
VARIANT_BOOL boolVal;
|
||||
/* _VARIANT_BOOL bool; */
|
||||
SCODE scode;
|
||||
CY cyVal;
|
||||
DATE date;
|
||||
BSTR bstrVal;
|
||||
IUnknown *punkVal;
|
||||
/* IDispatch *pdispVal; */
|
||||
SAFEARRAY *parray;
|
||||
BYTE *pbVal;
|
||||
SHORT *piVal;
|
||||
LONG *plVal;
|
||||
LONGLONG *pllVal;
|
||||
FLOAT *pfltVal;
|
||||
DOUBLE *pdblVal;
|
||||
VARIANT_BOOL *pboolVal;
|
||||
/* _VARIANT_BOOL *pbool; */
|
||||
SCODE *pscode;
|
||||
CY *pcyVal;
|
||||
DATE *pdate;
|
||||
BSTR *pbstrVal;
|
||||
/* IUnknown **ppunkVal; */
|
||||
/* IDispatch **ppdispVal; */
|
||||
SAFEARRAY **pparray;
|
||||
/* VARIANT *pvarVal; */
|
||||
PVOID byref;
|
||||
CHAR cVal;
|
||||
USHORT uiVal;
|
||||
ULONG ulVal;
|
||||
ULONGLONG ullVal;
|
||||
INT intVal;
|
||||
UINT uintVal;
|
||||
DECIMAL *pdecVal;
|
||||
CHAR *pcVal;
|
||||
USHORT *puiVal;
|
||||
ULONG *pulVal;
|
||||
ULONGLONG *pullVal;
|
||||
INT *pintVal;
|
||||
UINT *puintVal;
|
||||
struct /*__tagBRECORD*/
|
||||
{
|
||||
PVOID pvRecord;
|
||||
IRecordInfo *pRecInfo;
|
||||
} /* __VARIANT_NAME_4*/;
|
||||
} /* __VARIANT_NAME_3*/;
|
||||
} /* __VARIANT_NAME_2*/;
|
||||
DECIMAL decVal;
|
||||
};
|
||||
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;
|
||||
|
||||
#define VT_EMPTY 0x0000
|
||||
#define VT_NULL 0x0001
|
||||
#define VT_I2 0x0002
|
||||
#define VT_I4 0x0003
|
||||
#define VT_R4 0x0004
|
||||
#define VT_R8 0x0005
|
||||
#define VT_CY 0x0006
|
||||
#define VT_DATE 0x0007
|
||||
#define VT_BSTR 0x0008
|
||||
#define VT_DISPATCH 0x0009
|
||||
#define VT_ERROR 0x000A
|
||||
#define VT_BOOL 0x000B
|
||||
#define VT_VARIANT 0x000C
|
||||
#define VT_UNKNOWN 0x000D
|
||||
#define VT_DECIMAL 0x000E
|
||||
#define VT_I1 0x0010
|
||||
#define VT_UI1 0x0011
|
||||
#define VT_UI2 0x0012
|
||||
#define VT_UI4 0x0013
|
||||
#define VT_I8 0x0014
|
||||
#define VT_UI8 0x0015
|
||||
#define VT_INT 0x0016
|
||||
#define VT_UINT 0x0017
|
||||
#define VT_VOID 0x0018
|
||||
#define VT_HRESULT 0x0019
|
||||
#define VT_PTR 0x001A
|
||||
#define VT_SAFEARRAY 0x001B
|
||||
#define VT_CARRAY 0x001C
|
||||
#define VT_USERDEFINED 0x001D
|
||||
#define VT_LPSTR 0x001E
|
||||
#define VT_LPWSTR 0x001F
|
||||
#define VT_RECORD 0x0024
|
||||
#define VT_INT_PTR 0x0025
|
||||
#define VT_UINT_PTR 0x0026
|
||||
#define VT_ARRAY 0x2000
|
||||
#define VT_BYREF 0x4000
|
||||
|
||||
|
||||
|
||||
#define VariantInit(v_ptr) (v_ptr)->vt = VT_EMPTY
|
||||
|
||||
inline HRESULT VariantClear(VARIANTARG *pVar)
|
||||
{
|
||||
memset(pVar, 0, sizeof(VARIANT));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
|
||||
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
|
||||
|
||||
|
||||
#define CLDB_S_TRUNCATION SMAKEHR(0x1106)
|
||||
#define CLDB_E_TRUNCATION EMAKEHR(0x1106)
|
||||
|
||||
|
||||
#endif // __UNIX__
|
||||
|
||||
#include "corhdr.h"
|
||||
#include "cor.h"
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// what netnode tag
|
||||
#define CLITAG_MDA 0 // the assembly mda is here at index 0
|
||||
#define CLITAG_MTK 1 // the scope mtk is here at index 0
|
||||
#define CLITAG_STRUCT 'a' // the structure itself is saved here
|
||||
#define CLITAG_NAME 'b' // char *name (deprecated for strings, see CLITAG_STRING)
|
||||
// saved as blob
|
||||
#define CLITAG_VALUE 'c' // void *pval
|
||||
#define CLITAG_SIG 'd' // PCOR_SIGNATURE[]
|
||||
#define CLITAG_OTHER 'e' // mdToken others[]
|
||||
//#define CLITAG_TITLE 'f' // assembly title
|
||||
//#define CLITAG_DESCR 'g' // assembly description
|
||||
//#define CLITAG_ALIAS 'h' // assembly alias
|
||||
#define CLITAG_PUBKEY 'i' // public key blob
|
||||
#define CLITAG_PINV 'k' // pinvoke_info_t
|
||||
#define CLITAG_PNAME 'l' // name of pinvoke method
|
||||
#define CLITAG_LAYOUT 'm' // layout_info_t
|
||||
#define CLITAG_OFFSETS 'n' // COR_FIELD_OFFSET[]
|
||||
#define CLITAG_CUST 'o' // custom attribute blob
|
||||
#define CLITAG_TOKEN 'p' // ea: method, field, property, event token is here
|
||||
#define CLITAG_CLASS 'q' // ea: typedef token
|
||||
#define CLITAG_STRING 'r' // ea: address of string's bytes in .strings segment
|
||||
#define CLITAG_CLASSEND 's' // ea: typedef token
|
||||
#define CLITAG_TRY 't' // ea: try block start/cor_exception_info_t
|
||||
#define CLITAG_BEND 'u' // ea: block end
|
||||
#define CLITAG_HASH 'v' // hash
|
||||
#define CLITAG_FRVA 'x' // field rva
|
||||
#define CLITAG_EXCEPTION 128 // exception blocks: several indexes
|
||||
|
||||
// enumeration blobs
|
||||
// global enumerations have index 0
|
||||
#define CLITAG_PARAMS 'A'
|
||||
#define CLITAG_FIELDS 'B'
|
||||
#define CLITAG_METHODS 'C'
|
||||
#define CLITAG_EVENTS 'D'
|
||||
#define CLITAG_PROPERTIES 'E'
|
||||
#define CLITAG_INTERFACES 'F'
|
||||
#define CLITAG_TYPEDEFS 'G'
|
||||
#define CLITAG_TYPEREFS 'H'
|
||||
#define CLITAG_TYPESPECS 'I'
|
||||
#define CLITAG_USERSTRINGS 'J'
|
||||
#define CLITAG_CUSTATTRS 'K'
|
||||
#define CLITAG_MODULEREFS 'L'
|
||||
#define CLITAG_MEMBERREFS 'M' // 'N' shouldn't be used (as well as 'V')
|
||||
|
||||
|
||||
struct param_info_t // +name +value
|
||||
{
|
||||
mdToken method;
|
||||
ULONG n;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
};
|
||||
|
||||
struct field_info_t // +name +sig +value
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct method_info_t // +name +sig +params
|
||||
{
|
||||
mdToken owner;
|
||||
DWORD flags;
|
||||
ULONG rva; // ea later
|
||||
DWORD implflags;
|
||||
mdToken lvars;
|
||||
uint32 maxstack;
|
||||
uint32 methodflags;
|
||||
};
|
||||
|
||||
struct pinvoke_info_t // +pname
|
||||
{
|
||||
DWORD mappingflags;
|
||||
mdToken dlltok;
|
||||
};
|
||||
|
||||
struct property_info_t // +name +sig +other_tokens +value
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
mdToken setter, getter;
|
||||
// mdToken backing; disappeared in Beta2
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct event_info_t // +name +other_tokens
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
mdToken type;
|
||||
mdToken addon, removeon, fire;
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct interfaceimpl_info_t
|
||||
{
|
||||
mdToken inttok;
|
||||
};
|
||||
|
||||
struct typedef_info_t // +name +fields +methods +layout +offsets
|
||||
{
|
||||
DWORD flags;
|
||||
mdToken super;
|
||||
};
|
||||
|
||||
struct layout_info_t
|
||||
{
|
||||
DWORD packsize;
|
||||
ULONG classsize;
|
||||
ULONG noffsets;
|
||||
};
|
||||
|
||||
struct typeref_info_t // +name
|
||||
{
|
||||
mdToken scope;
|
||||
};
|
||||
|
||||
struct moduleref_info_t // +name
|
||||
{
|
||||
};
|
||||
|
||||
struct memberref_info_t // +name +sig
|
||||
{
|
||||
mdToken owner;
|
||||
};
|
||||
|
||||
struct typespec_info_t // +sig
|
||||
{
|
||||
};
|
||||
|
||||
struct userstring_info_t // +name
|
||||
{
|
||||
};
|
||||
|
||||
struct custattr_info_t // +blob
|
||||
{
|
||||
mdToken owner;
|
||||
mdToken type;
|
||||
};
|
||||
|
||||
struct assembly_info_t // +name +orig +title +desc +alias
|
||||
{
|
||||
ULONG hash;
|
||||
DWORD flags;
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usRevisionNumber;
|
||||
USHORT usBuildNumber;
|
||||
};
|
||||
|
||||
struct assemblyref_info_t // +name +orig +hash
|
||||
{
|
||||
DWORD flags;
|
||||
// mdToken exeloc;
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usRevisionNumber;
|
||||
USHORT usBuildNumber;
|
||||
};
|
||||
|
||||
struct file_info_t // +name +hash
|
||||
{
|
||||
DWORD flags;
|
||||
};
|
||||
|
||||
struct comtype_info_t // +name +descr
|
||||
{
|
||||
ULONG flags;
|
||||
mdToken impl, type, exeloc;
|
||||
};
|
||||
|
||||
struct cor_module_info_t // +name
|
||||
{
|
||||
mdToken mtk;
|
||||
GUID mid;
|
||||
};
|
||||
|
||||
struct cor_exception_info_t
|
||||
{
|
||||
ULONG flags;
|
||||
ULONG param;
|
||||
};
|
||||
|
||||
struct longname_director_t
|
||||
{
|
||||
char zero;
|
||||
uval_t node;
|
||||
};
|
||||
CASSERT(sizeof(longname_director_t) == 1 + sizeof(uval_t));
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t get_free_address(void);
|
||||
void expand(ea_t ea);
|
||||
void define_class(mdToken, const char *name, ea_t ea1, ea_t ea2);
|
||||
mdToken define_method(mdToken method, const char *name, method_info_t &b, ea_t *ea);
|
||||
void supset(ea_t idx, const void *body, int size, char tag);
|
||||
ssize_t supstr(ea_t idx, char *buf, size_t bufsize, char tag);
|
||||
void altset(ea_t idx, ea_t val, char tag);
|
||||
void setblob(ea_t idx, const void *body, int size, char tag);
|
||||
void save_name(ea_t idx, const qstring &name);
|
||||
qstring retrieve_name(ea_t idx);
|
||||
uint32 get_constant_element_type_raw_size(CorElementType type, uint32 chars);
|
||||
|
||||
bool load_metadata(const void *metadata, size_t metasize);
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // define __MYCOR_H
|
||||
1174
idasdk76/ldr/pe/pe.h
Normal file
1174
idasdk76/ldr/pe/pe.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user