public void TestFromByteEnumerationWithWildcards(IEnumerable <Tuple <byte, bool> > input, int expectedLength, bool expectedHasWildcards) { var sut = BytePattern.From(input); Check.That(sut.Length).IsEqualTo(expectedLength); Check.That(sut.HasWildcards).IsEqualTo(expectedHasWildcards); }
public void TestFromByteEnumeration(IEnumerable <byte> input, int expectedLength) { var sut = BytePattern.From(input); Check.That(sut.Length).IsEqualTo(expectedLength); Check.That(sut.HasWildcards).IsFalse(); }
public ulong AobScan(BytePattern bytePattern) { for (var moduleIndex = 0; moduleIndex < _moduleByteBuffer.Length; moduleIndex++) { // Check the beginning bytes of the module if (_moduleByteBuffer[moduleIndex] != bytePattern.Pattern[0]) { continue; } if (PatternCheck(moduleIndex, bytePattern.Pattern)) { if (bytePattern.HexOffset < 0) { return((_moduleBaseAddress + (ulong)moduleIndex) - (ulong)bytePattern.HexOffset); } else { return((_moduleBaseAddress + (ulong)moduleIndex) + (ulong)bytePattern.HexOffset); } } } return(0); }
public void TestParse(string input, int expectedLength, bool expectedHasWildcards) { var sut = BytePattern.Parse(input); Check.That(sut.Length).IsEqualTo(expectedLength); Check.That(sut.HasWildcards).IsEqualTo(expectedHasWildcards); }
static bool CheckProtection(BytePattern pattern, uint flags) { var protectionFlags = (WindowsApi.RegionPageProtection)flags; foreach (var protectionExclusion in ProtectionExclusions) { if (protectionFlags.HasFlag(protectionExclusion)) { return(false); } } return(true); // we need to check only READ? /* * foreach (var protectionOrInclusive in pattern.Config.PageProtections) * { * if (protectionFlags.HasFlag(protectionOrInclusive)) * { * return true; * } * } * * return false; */ }
private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1 heuristics) { if (heuristics == null) { return(new PlatformHeuristics { ProcedurePrologs = new BytePattern[0], }); } BytePattern[] prologs; if (heuristics.ProcedurePrologs == null) { prologs = new BytePattern[0]; } else { prologs = heuristics.ProcedurePrologs .Select(p => LoadBytePattern(p)) .Where(p => p.Bytes != null) .ToArray(); } return(new PlatformHeuristics { ProcedurePrologs = prologs }); }
public static ulong?FindPatternAddresses(Process process, BytePattern pattern) { List <ulong> matchAddresses = new List <ulong>(); var addressRange = pattern.AddressRange; ulong currentAddress = addressRange.Start; while (currentAddress < addressRange.End && !process.HasExited) { WindowsApi.MEMORY_BASIC_INFORMATION64 memoryRegion; if (WindowsApi.VirtualQueryEx(process.Handle, (IntPtr)currentAddress, out memoryRegion, (uint)Marshal.SizeOf(typeof(WindowsApi.MEMORY_BASIC_INFORMATION64))) > 0 && memoryRegion.RegionSize > 0 && memoryRegion.State == (uint)WindowsApi.RegionPageState.MEM_COMMIT && CheckProtection(pattern, memoryRegion.Protect)) { var regionStartAddress = memoryRegion.BaseAddress; if (addressRange.Start > regionStartAddress) { regionStartAddress = addressRange.Start; } var regionEndAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; if (addressRange.End < regionEndAddress) { regionEndAddress = addressRange.End; } ulong regionBytesToRead = regionEndAddress - regionStartAddress; byte[] regionBytes = new byte[regionBytesToRead]; if (process.HasExited) { break; } int lpNumberOfBytesRead = 0; WindowsApi.ReadProcessMemory(process.Handle, (IntPtr)regionStartAddress, regionBytes, regionBytes.Length, ref lpNumberOfBytesRead); var matchIndices = FindPatternMatchIndices(regionBytes, pattern); foreach (var matchIndex in matchIndices) { var matchAddress = regionStartAddress + (ulong)matchIndex; matchAddresses.Add(matchAddress); Logger.Log(LogLevel.Info, $"Found '{pattern.Config.Name}' at address 0x{matchAddress.ToString("X8")}"); break; } } if (matchAddresses.Any()) { break; } currentAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; } return(matchAddresses.Count > 0 ? matchAddresses[0] : (ulong?)null); }
static void GetLongestPrefixSuffices(BytePattern pattern, ref int[] longestPrefixSuffices) { int patternLength = pattern.Bytes.Length; int length = 0; int patternIndex = 1; longestPrefixSuffices[0] = 0; while (patternIndex < patternLength) { if (pattern.Bytes[patternIndex] == pattern.Bytes[length]) { length++; longestPrefixSuffices[patternIndex] = length; patternIndex++; } else { if (length == 0) { longestPrefixSuffices[patternIndex] = 0; patternIndex++; } else { length = longestPrefixSuffices[length - 1]; } } } }
/// <summary>Reads a string from the address in the remote process with the given length and encoding. The string gets truncated at the first zero character.</summary> /// <param name="encoding">The encoding used by the string.</param> /// <param name="address">The address of the string.</param> /// <param name="length">The length of the string.</param> /// <returns>The string.</returns> public string ReadRemoteStringUntilFirstNullCharacter(Encoding encoding, IntPtr address, int length) { Contract.Requires(encoding != null); Contract.Requires(length >= 0); Contract.Ensures(Contract.Result <string>() != null); var data = ReadRemoteMemory(address, length * encoding.GetSimpleByteCountPerChar()); // TODO We should cache the pattern per encoding. var index = PatternScanner.FindPattern(BytePattern.From(new byte[encoding.GetSimpleByteCountPerChar()]), data); if (index == -1) { index = data.Length; } try { return(Encoding.UTF8.GetString(data, 0, Math.Min(index, data.Length))); } catch { return(string.Empty); } }
public void TestToString(string input, PatternMaskFormat format, string expectedPattern, string expectedMask) { var sut = BytePattern.Parse(input); var(pattern, mask) = sut.ToString(format); Check.That(pattern).IsEqualTo(expectedPattern); Check.That(mask).IsEqualTo(expectedMask); }
private void Given_Data(Address addr, string hexBytes) { bool foundSeg = program.SegmentMap.TryFindSegment(addr, out var seg); Assert.IsTrue(foundSeg); var w = seg.MemoryArea.CreateLeWriter(addr); w.WriteBytes(BytePattern.FromHexBytes(hexBytes)); }
private void AssertEqual(float fExpected, string bytes) { var mem = BytePattern.FromHexBytes(bytes).ToArray(); var uFloat = MemoryArea.ReadLeUInt32(mem, 0); var mbf = new MBFFloat32(uFloat); var fActual = mbf.ToSingle(null); Assert.AreEqual(fExpected, fActual, 1e-30); }
private void AssertEqual(string sHexString, params byte[] expected) { var actual = BytePattern.FromHexBytes(sHexString); Assert.AreEqual(expected.Length, actual.Length); for (int i = 0; i < expected.Length; ++i) { Assert.AreEqual(expected[i], actual[i], $"Different at position {i}"); } }
private void Given_Data(uint uAddr, string hexBytes) { var addr = Address.Ptr32(uAddr); var isSeg = program.SegmentMap.TryFindSegment(addr, out var seg); Assert.IsTrue(isSeg); var w = program.Architecture.CreateImageWriter(seg.MemoryArea, addr); w.WriteBytes(BytePattern.FromHexBytes(hexBytes).ToArray()); }
public void RemoveVideoCardCheck(string pattern, int startIndex) { var bytePattern = new BytePattern { Pattern = pattern.Replace("\n", " ").Replace("\r", " ").Split(' '), }; var index = bytePattern.Match(inputString) + startIndex; Output[index] = Convert.ToByte("EB", 16); }
private void Given_Data(uint uAddr, string hexBytes) { var addr = Address.Ptr32(uAddr); bool foundSeg = program.SegmentMap.TryFindSegment(addr, out var seg); Assert.IsTrue(foundSeg); var w = seg.MemoryArea.CreateLeWriter(addr); w.WriteBytes(BytePattern.FromHexBytes(hexBytes).ToArray()); }
// KMP algorithm modified to search bytes with a nullable/wildcard search static List <int> FindPatternMatchIndices(byte[] bytes, BytePattern pattern, bool stopAfterFirst) { List <int> matchedIndices = new List <int>(); int textLength = bytes.Length; int patternLength = pattern.Bytes.Length; if (textLength == 0 || patternLength == 0 || textLength < patternLength) { return(matchedIndices); } int[] longestPrefixSuffices = new int[patternLength]; GetLongestPrefixSuffices(pattern, ref longestPrefixSuffices); int textIndex = 0; int patternIndex = 0; while (textIndex < textLength) { if (!pattern.Bytes[patternIndex].HasValue || // Ignore compare if the pattern index is nullable - this treats it like a * wildcard bytes[textIndex] == pattern.Bytes[patternIndex]) { textIndex++; patternIndex++; } if (patternIndex == patternLength) { matchedIndices.Add(textIndex - patternIndex); patternIndex = longestPrefixSuffices[patternIndex - 1]; if (stopAfterFirst) { break; } } else if (textIndex < textLength && (pattern.Bytes[patternIndex].HasValue && // Only compare disparity if the pattern byte isn't a null wildcard bytes[textIndex] != pattern.Bytes[patternIndex])) { if (patternIndex != 0) { patternIndex = longestPrefixSuffices[patternIndex - 1]; } else { textIndex++; } } } return(matchedIndices); }
private static void AssertEqual(IProcessorArchitecture arch, string sExpected, string hexString) { var bytes = BytePattern.FromHexBytes(hexString); var mem = new ByteMemoryArea(Address.Ptr32(0x0010_0000), bytes); var rdr = mem.CreateLeReader(0); var dasm = arch.CreateDisassembler(rdr); var instr = (X86Instruction)dasm.First(); var sActual = instr.ToString("A"); Assert.AreEqual(sExpected, sActual); }
public ArrayOfBytesMemoryComparer(BytePattern pattern) { Contract.Requires(pattern != null); bytePattern = pattern; if (!bytePattern.HasWildcards) { byteArray = bytePattern.ToByteArray(); } }
private void Given_Type(int typeIndex, string hexString) { var bytes = BytePattern.FromHexBytes(hexString); var rdr = new LeImageReader(bytes); this.typesByIndex.Add(typeIndex, new TypeDefinition { Leaves = new object[] { CodeViewTypeLoader.ReadLeaf(rdr) } }); }
private Program LoadProgram(Dictionary <string, object> pArgs, LoadDetails loadDetails) { if (pArgs.ContainsKey("--data")) { var hexBytes = (string)pArgs["--data"]; var image = BytePattern.FromHexBytes(hexBytes).ToArray(); return(decompiler.LoadRawImage(image, loadDetails)); } else { return(decompiler.LoadRawImage((string)pArgs["filename"], loadDetails)); } }
public void RemoveSignatureCheck(string pattern, int startIndex) { var bytePattern = new BytePattern { Pattern = pattern.Replace("\n", " ").Replace("\r", " ").Split(' '), }; var index = bytePattern.Match(inputString); Output[index + startIndex] = Convert.ToByte("E9", 16); Output[index + startIndex + 1] = (byte)(Output[index + startIndex + 2] + 1); Output[index + startIndex + 2] = Output[index + startIndex + 3]; Output[index + startIndex + 3] = 0; Output[index + startIndex + 5] = Convert.ToByte("90", 16);; }
static bool CheckProtection(BytePattern pattern, uint flags) { var protectionFlags = (WindowsApi.RegionPageProtection)flags; foreach (var protectionExclusion in ProtectionExclusions) { if (protectionFlags.HasFlag(protectionExclusion)) { return(false); } } return(true); }
private void AssertCode(string hexBytes, params string[] sExpectedInstrs) { byte[] bytes = BytePattern.FromHexBytes(hexBytes); ByteMemoryArea mem = new ByteMemoryArea(LoadAddress, bytes); var dasm = arch.CreateDisassembler(arch.CreateImageReader(mem, 0U)); var sInstrs = dasm.Select(i => i.ToString()).ToArray(); var c = Math.Min(sExpectedInstrs.Length, sInstrs.Length); for (int i = 0; i < c; ++i) { Assert.AreEqual(sExpectedInstrs[i], sInstrs[i]); } Assert.AreEqual(sExpectedInstrs.Length, sInstrs.Length, "Incorrect # of instructions"); }
private MemoryArea HexStringToMemoryArea(string sBytes) { int shift = 12; int bb = 0; var words = new List <ushort>(); for (int i = 0; i < sBytes.Length; ++i) { char c = sBytes[i]; if (BytePattern.TryParseHexDigit(c, out byte b)) { bb |= (b << shift); shift -= 4; if (shift < 0) { words.Add((ushort)bb); shift = 12; bb = 0; } } } return(new Word16MemoryArea(this.LoadAddress, words.ToArray())); }
private void Disassemble() { try { if (this.arch is null) { return; } if (!arch.TryParseAddress(control.Address.Text, out var addr)) { return; } var bytes = BytePattern.FromHexBytes(control.HexBytes.Text).ToArray(); if (bytes.Length > 0) { var mem = arch.CreateMemoryArea(addr, bytes); var dumper = new Dumper(new Program()) { ShowAddresses = true, ShowCodeBytes = true, }; var sw = new StringWriter(); dumper.DumpAssembler(arch, mem, mem.BaseAddress, bytes.Length, new Core.Output.TextFormatter(sw)); control.Disassembly.Text = sw.ToString(); } else { control.Disassembly.Text = ""; } } catch (Exception ex) { var diagSvc = services.RequireService <IDiagnosticsService>(); diagSvc.Error(ex, "An error occurred during disassembly."); } }
//$REFACTOR: this is so generic it should live somewhere else. public static List <byte> LoadHexBytes(string sBytes) { int shift = 4; int bb = 0; var bytes = new List <byte>(); for (int i = 0; i < sBytes.Length; ++i) { char c = sBytes[i]; byte b; if (BytePattern.TryParseHexDigit(c, out b)) { bb = bb | (b << shift); shift -= 4; if (shift < 0) { bytes.Add((byte)bb); shift = 4; bb = 0; } } } return(bytes); }
public MaskedPattern?LoadMaskedPattern(BytePattern_v1 sPattern) { List <byte> bytes; List <byte> mask; if (sPattern.Bytes == null) { return(null); } if (sPattern.Mask == null) { bytes = new List <byte>(); mask = new List <byte>(); int shift = 4; int bb = 0; int mm = 0; for (int i = 0; i < sPattern.Bytes.Length; ++i) { char c = sPattern.Bytes[i]; if (BytePattern.TryParseHexDigit(c, out byte b)) { bb |= (b << shift); mm |= (0x0F << shift); shift -= 4; if (shift < 0) { bytes.Add((byte)bb); mask.Add((byte)mm); shift = 4; bb = mm = 0; } } else if (c == '?' || c == '.') { shift -= 4; if (shift < 0) { bytes.Add((byte)bb); mask.Add((byte)mm); shift = 4; bb = mm = 0; } } } Debug.Assert(bytes.Count == mask.Count); } else { bytes = BytePattern.FromHexBytes(sPattern.Bytes); mask = BytePattern.FromHexBytes(sPattern.Mask); } if (bytes.Count == 0) { return(null); } return(new MaskedPattern { Bytes = bytes.ToArray(), Mask = mask.ToArray() }); }
/// <summary> /// Creates the comparer from the user input. /// </summary> /// <returns>The scan comparer.</returns> private IScanComparer CreateComparer(ScanSettings settings) { Contract.Requires(settings != null); Contract.Ensures(Contract.Result <IScanComparer>() != null); var compareType = compareTypeComboBox.SelectedValue; var checkBothInputFields = compareType == ScanCompareType.Between || compareType == ScanCompareType.BetweenOrEqual; if (settings.ValueType == ScanValueType.Byte || settings.ValueType == ScanValueType.Short || settings.ValueType == ScanValueType.Integer || settings.ValueType == ScanValueType.Long) { var numberStyle = isHexCheckBox.Checked ? NumberStyles.HexNumber : NumberStyles.Integer; if (!long.TryParse(dualValueBox.Value1, numberStyle, null, out var value1)) { throw new InvalidInputException(dualValueBox.Value1); } if (!long.TryParse(dualValueBox.Value2, numberStyle, null, out var value2) && checkBothInputFields) { throw new InvalidInputException(dualValueBox.Value2); } switch (settings.ValueType) { case ScanValueType.Byte: return(new ByteMemoryComparer(compareType, (byte)value1, (byte)value2)); case ScanValueType.Short: return(new ShortMemoryComparer(compareType, (short)value1, (short)value2)); case ScanValueType.Integer: return(new IntegerMemoryComparer(compareType, (int)value1, (int)value2)); case ScanValueType.Long: return(new LongMemoryComparer(compareType, value1, value2)); } } else if (settings.ValueType == ScanValueType.Float || settings.ValueType == ScanValueType.Double) { int CalculateSignificantDigits(string input, NumberFormatInfo numberFormat) { Contract.Requires(input != null); Contract.Requires(numberFormat != null); var digits = 0; var decimalIndex = input.IndexOf(numberFormat.NumberDecimalSeparator, StringComparison.Ordinal); if (decimalIndex != -1) { digits = input.Length - 1 - decimalIndex; } return(digits); } var nf1 = Utils.GuessNumberFormat(dualValueBox.Value1); if (!double.TryParse(dualValueBox.Value1, NumberStyles.Float, nf1, out var value1)) { throw new InvalidInputException(dualValueBox.Value1); } var nf2 = Utils.GuessNumberFormat(dualValueBox.Value2); if (!double.TryParse(dualValueBox.Value2, NumberStyles.Float, nf2, out var value2) && checkBothInputFields) { throw new InvalidInputException(dualValueBox.Value2); } var significantDigits = Math.Max( CalculateSignificantDigits(dualValueBox.Value1, nf1), CalculateSignificantDigits(dualValueBox.Value2, nf2) ); var roundMode = roundStrictRadioButton.Checked ? ScanRoundMode.Strict : roundLooseRadioButton.Checked ? ScanRoundMode.Normal : ScanRoundMode.Truncate; switch (settings.ValueType) { case ScanValueType.Float: return(new FloatMemoryComparer(compareType, roundMode, significantDigits, (float)value1, (float)value2)); case ScanValueType.Double: return(new DoubleMemoryComparer(compareType, roundMode, significantDigits, value1, value2)); } } else if (settings.ValueType == ScanValueType.ArrayOfBytes) { var pattern = BytePattern.Parse(dualValueBox.Value1); return(new ArrayOfBytesMemoryComparer(pattern)); } else if (settings.ValueType == ScanValueType.String) { if (string.IsNullOrEmpty(dualValueBox.Value1)) { throw new InvalidInputException(dualValueBox.Value1); } var encoding = encodingUtf8RadioButton.Checked ? Encoding.UTF8 : encodingUtf16RadioButton.Checked ? Encoding.Unicode : Encoding.UTF32; return(new StringMemoryComparer(dualValueBox.Value1, encoding, caseSensitiveCheckBox.Checked)); } throw new InvalidOperationException(); }
public static List <ulong> FindPatternAddresses(Process process, AddressRange addressRange, BytePattern pattern, bool stopAfterFirst) { List <ulong> matchAddresses = new List <ulong>(); ulong currentAddress = addressRange.Start; while (currentAddress < addressRange.End && !process.HasExited) { WindowsApi.MEMORY_BASIC_INFORMATION64 memoryRegion; var structByteCount = WindowsApi.VirtualQueryEx(process.Handle, (IntPtr)currentAddress, out memoryRegion, (uint)Marshal.SizeOf(typeof(WindowsApi.MEMORY_BASIC_INFORMATION64))); if (structByteCount > 0 && memoryRegion.RegionSize > 0 && memoryRegion.State == (uint)WindowsApi.RegionPageState.MEM_COMMIT && CheckProtection(pattern, memoryRegion.Protect)) { var regionStartAddress = memoryRegion.BaseAddress; if (addressRange.Start > regionStartAddress) { regionStartAddress = addressRange.Start; } var regionEndAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; if (addressRange.End < regionEndAddress) { regionEndAddress = addressRange.End; } if (process.HasExited) { break; } ulong regionBytesToRead = regionEndAddress - regionStartAddress; byte[] regionBytes = new byte[regionBytesToRead]; int lpNumberOfBytesRead = 0; WindowsApi.ReadProcessMemory(process.Handle, (IntPtr)regionStartAddress, regionBytes, regionBytes.Length, ref lpNumberOfBytesRead); var matchIndices = FindPatternMatchIndices(regionBytes, pattern, stopAfterFirst); if (matchIndices.Any() && stopAfterFirst) { var matchAddress = regionStartAddress + (ulong)matchIndices.First(); matchAddresses.Add(matchAddress); break; } else { foreach (var matchIndex in matchIndices) { var matchAddress = regionStartAddress + (ulong)matchIndex; matchAddresses.Add(matchAddress); } } } if (structByteCount == 0) { Log.WriteLine("Page query returned 0 bytes"); break; } currentAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; } return(matchAddresses); }
private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1 heuristics) { if (heuristics == null) { return new PlatformHeuristics { ProcedurePrologs = new BytePattern[0], }; } BytePattern[] prologs; if (heuristics.ProcedurePrologs == null) { prologs = new BytePattern[0]; } else { prologs = heuristics.ProcedurePrologs .Select(p => LoadBytePattern(p)) .Where(p => p.Bytes != null) .ToArray(); } return new PlatformHeuristics { ProcedurePrologs = prologs }; }