diff --git a/dump-prog/dump.cpp b/dump-prog/dump.cpp index 9ce0329..a2f061e 100644 --- a/dump-prog/dump.cpp +++ b/dump-prog/dump.cpp @@ -44,7 +44,7 @@ void printImports(void *N, RVA impAddr, string &modName, string &symName) { return; } -void printRelocs(void *N, RVA relocAddr) { +void printRelocs(void *N, VA relocAddr, reloc_type type) { return; } diff --git a/parser-library/nt-headers.h b/parser-library/nt-headers.h index a0612f0..c706fd1 100644 --- a/parser-library/nt-headers.h +++ b/parser-library/nt-headers.h @@ -153,4 +153,21 @@ struct import_dir_entry { boost::uint32_t AddressRVA; }; +enum reloc_type { + ABSOLUTE = 0, + HIGH = 1, + LOW = 2, + HIGHLOW = 3, + HIGHADJ = 4, + MIPS_JMPADDR = 5, + MIPS_JMPADDR16 = 9, + IA64_IMM64 = 9, + DIR64 = 10 +}; + +struct reloc_block { + boost::uint32_t PageRVA; + boost::uint32_t BlockSize; +}; + #endif diff --git a/parser-library/parse.cpp b/parser-library/parse.cpp index ffe04a2..446410d 100644 --- a/parser-library/parse.cpp +++ b/parser-library/parse.cpp @@ -43,13 +43,14 @@ struct importent { }; struct reloc { - RVA shiftedAddr; - RVA shiftedTo; + VA shiftedAddr; + reloc_type type; }; struct parsed_pe_internal { list
secs; list imports; + list relocs; }; bool getSecForRVA(list
&secs, RVA v, section &sec) { @@ -348,134 +349,204 @@ parsed_pe *ParsePEFromFile(const char *filePath) { data_directory exportDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_EXPORT]; - //get relocations + //get relocations, if exist data_directory relocDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_BASERELOC]; + if(relocDir.Size != 0) { + section d; + ::uint32_t rvaAddr = + relocDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase; + if(getSecForRVA(p->internal->secs, rvaAddr, d) == false) { + deleteBuffer(remaining); + deleteBuffer(p->fileBuffer); + delete p; + return NULL; + } + + ::uint32_t rvaofft = rvaAddr - d.sectionBase; + ::uint32_t pageRva; + ::uint32_t blockSize; + + if(readDword( d.sectionData, + rvaofft+_offset(reloc_block, PageRVA), + pageRva) == false) + { + return NULL; + } + + if(readDword( d.sectionData, + rvaofft+_offset(reloc_block, BlockSize), + blockSize) == false) + { + return NULL; + } + + //iter over all of the RVA blocks + ::uint32_t blockCount = blockSize/sizeof(::uint16_t); + + rvaofft += sizeof(reloc_block); + + while(blockCount != 0) { + ::uint16_t block; + ::uint8_t type; + ::uint16_t offset; + + if(readWord(d.sectionData, rvaofft, block) == false) { + return NULL; + } + + //mask out the type and assign + type = block >> 12; + //mask out the offset and assign + offset = block & ~0xf000; + + //produce the VA of the relocation + ::uint32_t relocVA = pageRva + offset + + p->peHeader.nt.OptionalHeader.ImageBase; + + //store in our list + reloc r; + + r.shiftedAddr = relocVA; + r.type = (reloc_type)type; + p->internal->relocs.push_back(r); + + blockCount--; + rvaofft += sizeof(::uint16_t); + } + } + //get imports data_directory importDir = p->peHeader.nt.OptionalHeader.DataDirectory[DIR_IMPORT]; - //get section for the RVA in importDir - section c; - ::uint32_t addr = - importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase; + if(importDir.Size != 0) { + //get section for the RVA in importDir + section c; + ::uint32_t addr = + importDir.VirtualAddress + p->peHeader.nt.OptionalHeader.ImageBase; - if(getSecForRVA(p->internal->secs, addr, c) == false) { - deleteBuffer(remaining); - deleteBuffer(p->fileBuffer); - delete p; - return NULL; - } + if(getSecForRVA(p->internal->secs, addr, c) == false) { + deleteBuffer(remaining); + deleteBuffer(p->fileBuffer); + delete p; + return NULL; + } - //get import directory from this section - ::uint32_t offt = addr - c.sectionBase; - do { + //get import directory from this section + ::uint32_t offt = addr - c.sectionBase; + do { #define READ_DWORD(x) \ - if(readDword(c.sectionData, offt+_offset(import_dir_entry, x), curEnt.x) == false) { \ - return NULL; \ - } - //read each directory entry out - import_dir_entry curEnt; - - READ_DWORD(LookupTableRVA); - READ_DWORD(TimeStamp); - READ_DWORD(ForwarderChain); - READ_DWORD(NameRVA); - READ_DWORD(AddressRVA); - - //are all the fields in curEnt null? then we break - if( curEnt.LookupTableRVA == 0 && - curEnt.NameRVA == 0 && - curEnt.AddressRVA == 0) { - break; + if(readDword(c.sectionData, offt+_offset(import_dir_entry, x), curEnt.x) == false) { \ + return NULL; \ } + //read each directory entry out + import_dir_entry curEnt; - //then, try and get the name of this particular module... - ::uint32_t name = curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase; - section nameSec; - if(getSecForRVA(p->internal->secs, name, nameSec) == false) { - return NULL; - } + READ_DWORD(LookupTableRVA); + READ_DWORD(TimeStamp); + READ_DWORD(ForwarderChain); + READ_DWORD(NameRVA); + READ_DWORD(AddressRVA); - ::uint32_t nameOff = name - nameSec.sectionBase; - string modName; - ::uint8_t c; - do { - if(readByte(nameSec.sectionData, nameOff, c) == false) { - return NULL; - } - - if(c == 0) { + //are all the fields in curEnt null? then we break + if( curEnt.LookupTableRVA == 0 && + curEnt.NameRVA == 0 && + curEnt.AddressRVA == 0) { break; } - modName.push_back(c); - nameOff++; - }while(true); + //then, try and get the name of this particular module... + ::uint32_t name = + curEnt.NameRVA + p->peHeader.nt.OptionalHeader.ImageBase; - //then, try and get all of the sub-symbols - ::uint32_t lookupRVA = - curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase; - - section lookupSec; - if(getSecForRVA(p->internal->secs, lookupRVA, lookupSec) == false) { - return NULL; - } - - ::uint32_t lookupOff = lookupRVA - lookupSec.sectionBase; - do { - ::uint32_t val; - if(readDword(lookupSec.sectionData, lookupOff, val) == false) { + section nameSec; + if(getSecForRVA(p->internal->secs, name, nameSec) == false) { return NULL; } - if(val == 0) { - break; - } - - //check and see if high bit is set - if(val >> 31 == 0) { - //import by name - string symName; - section symNameSec; - ::uint32_t valRVA = val + p->peHeader.nt.OptionalHeader.ImageBase; - if(getSecForRVA(p->internal->secs, valRVA, symNameSec) == false) { + ::uint32_t nameOff = name - nameSec.sectionBase; + string modName; + ::uint8_t c; + do { + if(readByte(nameSec.sectionData, nameOff, c) == false) { return NULL; } - ::uint32_t nameOff = valRVA - symNameSec.sectionBase; - nameOff += sizeof(::uint16_t); - do { - ::uint8_t d; + if(c == 0) { + break; + } - if(readByte(symNameSec.sectionData, nameOff, d) == false) { + modName.push_back(c); + nameOff++; + }while(true); + + //then, try and get all of the sub-symbols + ::uint32_t lookupRVA = + curEnt.LookupTableRVA + p->peHeader.nt.OptionalHeader.ImageBase; + + section lookupSec; + if(getSecForRVA(p->internal->secs, lookupRVA, lookupSec) == false) { + return NULL; + } + + ::uint32_t lookupOff = lookupRVA - lookupSec.sectionBase; + do { + ::uint32_t val; + if(readDword(lookupSec.sectionData, lookupOff, val) == false) { + return NULL; + } + + if(val == 0) { + break; + } + + //check and see if high bit is set + if(val >> 31 == 0) { + //import by name + string symName; + section symNameSec; + ::uint32_t valRVA = val + p->peHeader.nt.OptionalHeader.ImageBase; + if(getSecForRVA(p->internal->secs, valRVA, symNameSec) == false) { return NULL; } - if(d == 0) { - break; - } + ::uint32_t nameOff = valRVA - symNameSec.sectionBase; + nameOff += sizeof(::uint16_t); + do { + ::uint8_t d; - symName.push_back(d); - nameOff++; - } while(true); + if(readByte(symNameSec.sectionData, nameOff, d) == false) { + return NULL; + } + + if(d == 0) { + break; + } - //okay now we know the pair... add it - importent ent; + symName.push_back(d); + nameOff++; + } while(true); - ent.addr = curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase; - ent.symbolName = symName; - ent.moduleName = modName; - p->internal->imports.push_back(ent); - } else { - //import by ordinal - } - - lookupOff += sizeof(::uint32_t); + //okay now we know the pair... add it + importent ent; + + ent.addr = + curEnt.AddressRVA + p->peHeader.nt.OptionalHeader.ImageBase; + + ent.symbolName = symName; + ent.moduleName = modName; + p->internal->imports.push_back(ent); + } else { + //import by ordinal + } + + lookupOff += sizeof(::uint32_t); + } while(true); + + offt += sizeof(import_dir_entry); } while(true); - - offt += sizeof(import_dir_entry); - } while(true); + } deleteBuffer(remaining); @@ -507,7 +578,7 @@ void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd) { } //iterate over the exports by RVA -void IterExpRVA(parsed_pe *pe, iterRVA cb, void *cbd) { +void IterExpRVA(parsed_pe *pe, iterExp cb, void *cbd) { return; } diff --git a/parser-library/parse.h b/parser-library/parse.h index 4f8ea6d..1a83f67 100644 --- a/parser-library/parse.h +++ b/parser-library/parse.h @@ -30,6 +30,7 @@ THE SOFTWARE. #include "nt-headers.h" typedef boost::uint32_t RVA; +typedef boost::uint32_t VA; typedef struct _bounded_buffer { boost::uint8_t *buf; @@ -68,12 +69,12 @@ typedef void (*iterRVAStr)(void *, RVA, std::string &, std::string &); void IterImpRVAString(parsed_pe *pe, iterRVAStr cb, void *cbd); //iterate over relocations in the PE file -typedef void (*iterReloc)(void *, RVA); +typedef void (*iterReloc)(void *, VA, reloc_type); void IterRelocs(parsed_pe *pe, iterReloc cb, void *cbd); //iterate over the exports -typedef void (*iterRVA)(void *, RVA, std::string &, std::string &); -void IterExpRVA(parsed_pe *pe, iterRVA cb, void *cbd); +typedef void (*iterExp)(void *, RVA, std::string &, std::string &); +void IterExpRVA(parsed_pe *pe, iterExp cb, void *cbd); //iterate over sections typedef void (*iterSec)(void *, RVA secBase, std::string &, bounded_buffer *b);