//recursively descend through resource directory structure //resource directories are 3 levels deep by Microsoft convention: //level 1 : resource type //level 2 : resource name str/id num //level 3 : language (aka code page) private void parseResourceDirectory(BinaryIn source, int level) { //parse IMAGE_RESOURCE_DIRECTORY uint characteristics = source.getFour(); //unused uint timeDateStamp = source.getFour(); uint majorVersion = source.getTwo(); uint minorVersion = source.getTwo(); uint numberOfNamedEntries = source.getTwo(); uint numberOfIdEntries = source.getTwo(); int entryCount = (int)(numberOfNamedEntries + numberOfIdEntries); for (int i = 0; i < entryCount; i++) { uint idName = source.getFour(); //either numeric val or a ptr to name str uint data = source.getFour(); //either ptr to subdir or a leaf node resIdNameValues[level] = idName; //store id/name val at this level uint curPos = source.getPos(); //save cur pos in resource directory uint dataPos = (data & 0x7FFFFFFF); source.seek(dataPos); //goto leaf/subtree data if (data < 0x80000000) //high bit not set -> data points to leaf node { parseResourceData(source); } else { //high bit is set -> data points to subtree parseResourceDirectory(source, level + 1); //recurse next subtree } source.seek(curPos); //ret to pos in resource directory } }
//- reading in ---------------------------------------------------------------- public static CoffSection readSection(BinaryIn source) { string name = source.getAsciiString(8); CoffSection sec = new CoffSection(name); sec.memSize = source.getFour(); sec.memPos = source.getFour(); sec.fileSize = source.getFour(); sec.filePos = source.getFour(); sec.relocTblPos = source.getFour(); uint skip1 = source.getFour(); //line numbers are deprecated sec.relocTblCount = source.getTwo(); uint skip2 = source.getTwo(); uint flagval = source.getFour(); sec.settings = SectionSettings.decodeFlags(flagval); uint mark = source.getPos(); source.seek(sec.filePos); byte[] secdata = source.getRange(sec.fileSize); sec.data = new List <byte>(secdata); source.seek(mark); return(sec); }
//- reading in -------------------------------------------------------- internal static OboeBlock loadSection(BinaryIn infile, uint secaddr, uint secsize, uint sectype) { infile.seek(secaddr); String blockname = infile.getAsciiZString(); OboeBlock block = new OboeBlock(blockname, sectype); uint blockaddr = infile.getFour(); uint blocksize = infile.getFour(); uint importaddr = infile.getFour(); uint importcount = infile.getFour(); uint exportaddr = infile.getFour(); uint exportcount = infile.getFour(); //block data infile.seek(blockaddr); block.blockdata = new List <byte>(infile.getRange(blocksize)); //import list infile.seek(importaddr); for (int i = 0; i < importcount; i++) { ImportEntry imp = ImportEntry.loadFromFile(infile); block.imports.Add(imp); } //export list infile.seek(exportaddr); for (int i = 0; i < exportcount; i++) { ExportEntry exp = ExportEntry.loadFromFile(infile); block.exports.Add(exp); } return(block); }
private String getResourceName(BinaryIn source, uint pos) { uint curPos = source.getPos(); pos = (pos & 0x7FFFFFFF); source.seek(pos); int strLen = (int)source.getTwo(); pos += 2; StringBuilder str = new StringBuilder(strLen); for (int i = 0; i < strLen; i++) { uint ch = source.getTwo(); str.Append(Convert.ToChar(ch)); pos += 2; } source.seek(curPos); return str.ToString(); }
//- reading in from file ----------------------------------------------- public static Oboe loadFromFile(string inname) { BinaryIn infile = new BinaryIn(inname); Oboe oboe = new Oboe(); try { string sig = infile.getAsciiString(4); if (!sig.Equals(OBOESIG)) { throw new OboeFormatException("this is not a valid OBOE file"); } uint secCount = infile.getFour(); for (int i = 0; i < secCount; i++) { uint sectype = infile.getFour(); uint secaddr = infile.getFour(); uint secsize = infile.getFour(); uint hdrpos = infile.getPos(); //ignore any section types we don't recognize if (loaders.ContainsKey(sectype)) { infile.seek(secaddr); Section sec = loaders[sectype].readIn(infile, secsize); oboe.addSection(sec); infile.seek(hdrpos); } } } catch (BinaryReadException) { throw new OboeFormatException("this is not a valid OBOE file"); } return(oboe); }
internal static Section loadSection(BinaryIn infile, uint secaddr, uint secsize) { infile.seek(secaddr); String blockname = infile.getAsciiZString(); BSSBlock block = new BSSBlock(); block.bssSize = infile.getFour(); uint exportcount = infile.getFour(); //export list for (int i = 0; i < exportcount; i++) { ExportEntry exp = ExportEntry.loadFromFile(infile); block.exports.Add(exp); } return(block); }
//- reading in ---------------------------------------------------------------- public void readFile(String _filename) { filename = _filename; BinaryIn source = new BinaryIn(filename); dosHeader = MsDosHeader.readMSDOSHeader(source); source.seek(dosHeader.e_lfanew); uint pesig = source.getFour(); if (pesig != 0x00004550) { throw new Win32ReadException("this is not a valid win32 executable file"); } machine = (MachineType)source.getTwo(); uint secCount = source.getTwo(); uint stamp = source.getFour(); timeStamp = setTimestamp(stamp); uint symbolTblAddr = source.getFour(); uint symbolTblCount = source.getFour(); //these fields should be zero uint optionalHdrSize = source.getTwo(); if (optionalHdrSize != 0xe0) { throw new Win32ReadException("this is not a valid win32 executable file"); } uint flags = source.getTwo(); characteristics = Characteristics.decodeFlags(flags); readOptionalHeader(source); loadSections(source, secCount); //getImportTable(source); //getExportTable(source); //getResourceTable(source); }
public static void loadRelocations(BinaryIn source, CoffSection sec, Win32Obj objfile) { source.seek(sec.relocTblPos); for (int i = 0; i < sec.relocTblCount; i++) { uint addr = source.getFour(); int symidx = (int)source.getFour(); uint reloctype = source.getTwo(); CoffRelocation.Reloctype reltype = CoffRelocation.Reloctype.NONE; switch (reloctype) { case 06: reltype = CoffRelocation.Reloctype.ABSOLUTE; //IMAGE_REL_I386_DIR32 break; case 07: reltype = CoffRelocation.Reloctype.RVA; //IMAGE_REL_I386_DIR32NB break; case 11: reltype = CoffRelocation.Reloctype.SECREL32; //IMAGE_REL_I386_SECREL break; case 20: reltype = CoffRelocation.Reloctype.RELATIVE; //IMAGE_REL_I386_REL32 break; default: break; } CoffSymbol sym = objfile.symbols[symidx]; CoffRelocation reloc = new CoffRelocation(addr - sec.memPos, sym, reltype); sec.relocations.Add(reloc); } }
public static void loadSymbols(BinaryIn source, uint count, byte[] strtbl, Win32Obj objfile) { for (int i = 0; i < count;) { //get short name or pos in string tbl uint nameloc = source.getPos(); uint namezeros = source.getFour(); String name = ""; if (namezeros == 0) //if first 4 bytes = 0, 2nd 4 bytes = ofs into str tbl { int namepos = (int)source.getFour(); name = readString(strtbl, namepos); } else { source.seek(nameloc); name = source.getAsciiString(8); } //read rest of sym entry uint val = source.getFour(); uint secval = source.getTwo(); uint type = source.getTwo(); CoffStorageClass storage = (CoffStorageClass)source.getOne(); uint aux = source.getOne(); CoffSymbol sym = null; CoffSymbol.SYMBIND bind = CoffSymbol.SYMBIND.EXTERNAL; uint size = 0; uint addr = 0; CoffSection sec = null; switch (storage) { case CoffStorageClass.IMAGE_SYM_CLASS_EXTERNAL: if (secval == 0) { if (val == 0) { bind = CoffSymbol.SYMBIND.EXTERNAL; } else { bind = CoffSymbol.SYMBIND.COMMON; size = val; } } else { bind = CoffSymbol.SYMBIND.GLOBAL; sec = objfile.sections[(int)secval - 1]; if (val >= sec.memPos) { addr = val - sec.memPos; } } sym = new CoffSymbol(name); sym.bind = bind; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; break; case CoffStorageClass.IMAGE_SYM_CLASS_STATIC: case CoffStorageClass.IMAGE_SYM_CLASS_LABEL: if (secval != 0xffff) { sec = objfile.sections[(int)secval - 1]; if (val >= sec.memPos) { addr = val - sec.memPos; } sym = new CoffSymbol(name); sym.bind = CoffSymbol.SYMBIND.LOCAL; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; } break; case CoffStorageClass.IMAGE_SYM_CLASS_SECTION: sec = objfile.sections[(int)secval - 1]; sym = new CoffSymbol(name); sym.bind = CoffSymbol.SYMBIND.LOCAL; sym.typ = CoffSymbol.SYMTYPE.FUNCTION; sym.section = sec; sym.ofs = addr; sym.size = size; break; case CoffStorageClass.IMAGE_SYM_CLASS_FUNCTION: case CoffStorageClass.IMAGE_SYM_CLASS_FILE: break; default: break; } i++; objfile.symbols.Add(sym); if (sym != null) { objfile.symNames[sym.name] = sym; } //skip any aux sym entries for (int j = 0; j < aux; j++) { source.skip(CoffSymbol.SYMTBLENTRYSIZE); objfile.symbols.Add(null); i++; } } }
public static Win32Obj readFromFile(String filename) { Win32Obj objfile = new Win32Obj(filename); BinaryIn source = new BinaryIn(filename); //coff header objfile.machine = (MachineType)source.getTwo(); uint sectionCount = source.getTwo(); objfile.timeStamp = source.getFour(); uint symbolTblAddr = source.getFour(); uint symbolCount = source.getFour(); uint optionalHdrSize = source.getTwo(); objfile.characteristics = (int)source.getTwo(); //string tbl - follows symbol tbl uint strtblpos = symbolTblAddr + symbolCount * CoffSymbol.SYMTBLENTRYSIZE; source.seek(strtblpos); byte[] strtbl = null; uint len = source.getFour(); if (len > 4) { source.seek(strtblpos); strtbl = source.getRange(len); } //section tbl source.seek(COFFHDRSIZE); for (int i = 0; i < sectionCount; i++) { //if section name is stored in string tbl, we read in index & let caller deref the actual name String secname = source.getAsciiString(8); if (secname[0] == '/') { int stridx = Int32.Parse(secname.Substring(1)); secname = readString(strtbl, stridx); } //read section hdr field uint memSize = source.getFour(); //don't use - 0 in object files uint memPos = source.getFour(); uint fileSize = source.getFour(); uint filePos = source.getFour(); uint relocPos = source.getFour(); uint lineNumPos = source.getFour(); //don't use - deprecated uint relocCount = source.getTwo(); uint lineNumCount = source.getTwo(); //don't use uint flagval = source.getFour(); SectionSettings settings = SectionSettings.decodeFlags(flagval); CoffSection section = new CoffSection(secname, settings); section.owner = objfile; section.secNum = i + 1; section.memPos = memPos; section.fileSize = fileSize; section.filePos = filePos; section.relocTblPos = relocPos; section.relocTblCount = relocCount; objfile.sections.Add(section); objfile.secNames[section.name] = section; } //load symbols source.seek(symbolTblAddr); loadSymbols(source, symbolCount, strtbl, objfile); foreach (CoffSection section in objfile.sections) { //load section data section.data = new List <Byte>(source.getRange(section.filePos, section.fileSize)); //load sectionrelocs loadRelocations(source, section, objfile); } return(objfile); }