/// <summary> /// Performs a shingle scan of the executable segments of the program, /// returning the interprocedural control flow graph (ICFG) and locations /// of likely call destinations. /// </summary> /// <returns></returns> public ScanResults ScanNew() { ICodeLocation location = null; Exception error; try { var q = ScanExecutableSegments(); } catch (AddressCorrelatedException aex) { location = eventListener.CreateAddressNavigator(program, aex.Address); error = aex; } catch (Exception ex) { location = new NullCodeLocation(""); error = ex; } if (location != null) { eventListener.Error(location, "An error occurred while scanning {0}."); } return(new ScanResults { ICFG = new DiGraph <RtlBlock>(), DirectlyCalledAddresses = this.sr.DirectlyCalledAddresses, KnownProcedures = sr.KnownProcedures, }); }
public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); Address offset = baseOfImage + page + (fixup & 0x0FFFu); var arch = program.Architecture; var imgR = program.CreateImageReader(arch, offset); var imgW = program.CreateImageWriter(arch, offset); switch (fixup >> 12) { case RelocationAbsolute: // Used for padding to 4-byte boundary, ignore. break; case RelocationHighLow: { uint n = (uint)(imgR.ReadUInt32() + (baseOfImage - program.ImageMap.BaseAddress)); imgW.WriteUInt32(n); relocations.AddPointerReference(offset.ToLinear(), n); break; } case 0xA: break; default: dcSvc.Warn( dcSvc.CreateAddressNavigator(program, offset), string.Format( "Unsupported i386 PE fixup type: {0:X}", fixup >> 12)); break; } }
private UserProcedure?LoadUserProcedure( Program program, Procedure_v1 sup) { if (!program.Architecture.TryParseAddress(sup.Address, out Address addr)) { return(null); } if (!sup.Decompile && sup.Signature == null && string.IsNullOrEmpty(sup.CSignature)) { listener.Warn( listener.CreateAddressNavigator(program, addr), "User procedure '{0}' has been marked 'no decompile' but its signature " + "has not been specified.", sup.Name ?? "<unnamed>"); } string name = sup.Name ?? NamingPolicy.Instance.ProcedureName(addr); var up = new UserProcedure(addr, name) { Ordinal = sup.Ordinal, Signature = sup.Signature, Characteristics = sup.Characteristics ?? new ProcedureCharacteristics(), Decompile = sup.Decompile, Assume = sup.Assume?.ToList() ?? new List <RegisterValue_v2>(), CSignature = sup.CSignature, OutputFile = sup.OutputFile }; return(up); }
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadLeUInt16(); var rt = (Arm64Rt)(fixup >> 12); Address offset = baseOfImage + page + (fixup & 0x0FFFu); DebugEx.Verbose(PeImageLoader.trace, " {0:X4} {1}", fixup, rt); var imgR = program.CreateImageReader(program.Architecture, offset); var imgW = program.CreateImageWriter(program.Architecture, offset); switch (rt) { case Arm64Rt.IMAGE_REL_ARM64_ABSOLUTE: break; case Arm64Rt.IMAGE_REL_ARM64_SECREL_HIGH12A: var uInstr = imgR.ReadLeUInt32(); break; default: eventListener.Warn( eventListener.CreateAddressNavigator(program, offset), string.Format( "Unsupported AArch64 PE fixup type: {0:X}", fixup >> 12)); break; } }
private KeyValuePair<Address, Procedure_v1> LoadUserProcedure_v1( Program program, Procedure_v1 sup) { program.Architecture.TryParseAddress(sup.Address, out Address addr); if (!sup.Decompile && sup.Signature == null && string.IsNullOrEmpty(sup.CSignature)) { listener.Warn( listener.CreateAddressNavigator(program, addr), "User procedure '{0}' has been marked 'no decompile' but its signature " + "has not been specified.", sup.Name ?? "<unnamed>"); } return new KeyValuePair<Address, Procedure_v1>(addr, sup); }
public const short IMAGE_REL_MIPS_PAIR = 0x0025; // This relocation is only valid when it immediately follows a REFHI or SECRELHI relocation. Its SymbolTableIndex contains a displacement and not an index into the symbol table. public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations) { ushort fixup = rdr.ReadUInt16(); Address offset = baseOfImage + page + (fixup & 0x0FFFu); var arch = program.Architecture; var imgR = program.CreateImageReader(arch, offset); var imgW = program.CreateImageWriter(arch, offset); uint w = imgR.ReadUInt32(); int s; switch (fixup >> 12) { case IMAGE_REL_MIPS_ABSOLUTE: // Used for padding to 4-byte boundary, ignore. break; case IMAGE_REL_MIPS_REFWORD: break; case IMAGE_REL_MIPS_JMPADDR: break; case IMAGE_REL_MIPS_REFHI: w = imgR.ReadUInt32(); //w += (fixup & 0x0FFFu); //imgW.WriteUInt32(w); s = rdr.ReadInt16(); w = (uint)(w + s); // w points to something. break; case IMAGE_REL_MIPS_REFLO: // w points to something. break; default: dcSvc.Warn( dcSvc.CreateAddressNavigator(program, offset), string.Format( "Unsupported MIPS PE fixup type: {0:X}", fixup >> 12)); break; } }
public void Warn(string format, params object [] args) { decompilerEventListener.Warn( decompilerEventListener.CreateAddressNavigator(program, addr), string.Format(format, args)); }
public void Warn(Address addr, string message) { eventListener.Warn(eventListener.CreateAddressNavigator(Program, addr), message); }
public TableExtent DiscoverTableExtent(Address addrSwitch, RtlTransfer xfer, DecompilerEventListener listener) { if (!Start(rtlBlock, host.BlockInstructionCount(rtlBlock) - 1, xfer.Target)) { // No registers were found, so we can't trace back. return(null); } while (Step()) { ; } var jumpExpr = this.JumpTableFormat; var interval = this.JumpTableIndexInterval; var index = this.JumpTableIndexToUse; var ctx = new Dictionary <Expression, ValueSet>(new ExpressionValueComparer()); if (index == null) { // Weren't able to find the index register, // try finding it by blind pattern matching. index = this.FindIndexWithPatternMatch(this.JumpTableFormat); if (index == null) { // This is likely an indirect call like a C++ // vtable dispatch. Since these are common, we don't // spam the user with warnings. return(null); } // We have a jump table, and we've guessed the index expression. // At this point we've given up on knowing the exact size // of the table, but we do know that it must be at least // more than one entry. The safest assumption is that it // has two entries. listener.Warn( listener.CreateAddressNavigator(host.Program, addrSwitch), "Unable to determine size of call or jump table; there may be more than 2 entries."); ctx.Add(index, new IntervalValueSet(index.DataType, StridedInterval.Create(1, 0, 1))); } else if (interval.IsEmpty) { return(null); } else if (interval.High == Int64.MaxValue) { // We have no reasonable upper bound. We make the arbitrary // assumption that the jump table has 2 items; it wouldn't // make sense to be indexing otherwise. listener.Warn( listener.CreateAddressNavigator(host.Program, addrSwitch), "Unable to determine the upper bound of an indirect call or jump; there may be more than 2 entries."); var vs = new IntervalValueSet( this.JumpTableIndex.DataType, StridedInterval.Create(1, interval.Low, interval.Low + 1)); ctx.Add(this.JumpTableIndexToUse, vs); } else { ctx.Add(this.JumpTableIndex, new IntervalValueSet(this.JumpTableIndex.DataType, interval)); } var vse = new ValueSetEvaluator(host.Architecture, host.SegmentMap, ctx, this.processorState); var(values, accesses) = vse.Evaluate(jumpExpr); var vector = values.Values .TakeWhile(c => c != Constant.Invalid) .Take(2000) // Arbitrary limit .Select(ForceToAddress) .TakeWhile(a => a != null) .ToList(); if (vector.Count == 0) { return(null); } return(new TableExtent { Targets = vector, Accesses = accesses, Index = index, }); }