Пример #1
0
        // Detect and defeat various kinds of XOR encryption
        public void PostProcessImage <T>(FileFormatStream <T> stream, PluginPostProcessImageEventInfo data) where T : FileFormatStream <T>
        {
            if (stream is ElfReader32 stream32)
            {
                elf32 = stream32;
            }
            else if (stream is ElfReader64 stream64)
            {
                elf64 = stream64;
            }
            else
            {
                return;
            }

            PluginServices.For(this).StatusUpdate("Detecting encryption");

            this.stream = stream;
            sections    = stream.GetSections().GroupBy(s => s.Name).ToDictionary(s => s.Key, s => s.First());

            if (HasDynamicEntry(Elf.DT_INIT) && sections.ContainsKey(".rodata"))
            {
                // Use the data section to determine some possible keys
                // If the data section uses striped encryption, bucketing the whole section will not give the correct key
                var roDataBytes            = stream.ReadBytes(sections[".rodata"].ImageStart, sections[".rodata"].ImageLength);
                var xorKeyCandidateStriped = roDataBytes.Take(1024).GroupBy(b => b).OrderByDescending(f => f.Count()).First().Key;
                var xorKeyCandidateFull    = roDataBytes.GroupBy(b => b).OrderByDescending(f => f.Count()).First().Key;

                // Select test nibbles and values for ARM instructions depending on architecture (ARMv7 / AArch64)
                var testValues = new Dictionary <int, (int, int, int, int)> {
Пример #2
0
 public static PluginPostProcessImageEventInfo PostProcessImage <T>(FileFormatStream <T> stream) where T : FileFormatStream <T>
 => PluginManager.Try <ILoadPipeline, PluginPostProcessImageEventInfo>((p, e) => p.PostProcessImage(stream, e));
Пример #3
0
        // See: FileFormatStreams/FileFormatStream.cs
        // See: FileFormatStreams/*Reader.cs
        // See: FileFormatStreams/Export.cs
        // See: FileFormatStreams/Section.cs
        // See: FileFormatStreams/Symbol.cs
        public void PostProcessImage <T>(FileFormatStream <T> stream, PluginPostProcessImageEventInfo data) where T : FileFormatStream <T>
        {
            // This is called once FOR EACH binary image
            // Regular ELF, PE, MachO files will result in a single call
            // Binaries containing sub-images (eg. Fat MachO, multi-architecture/split APKs) will result in
            // one call for the complete image and one call for each sub-image

            // FileFormatStream<T> derives from BinaryObjectReader and implements IFileFormatStream

            // Example: ignore Fat MachO files (wait for a sub-image)
            if (stream is UBReader)
            {
                return;
            }

            // Example: select an image extracted from a Fat MachO file
            if (stream is MachOReader32)
            {
            }
            if (stream is MachOReader64)
            {
            }

            // Useful properties:
            // Length, Numimages, DefaultFilename, IsModified, Images[], Position, Format, Arch, Bits,
            // GlobalOffset, ImageBase etc.

            // Example: check if file is ARM64
            var isArm64 = stream.Arch == "ARM64";

            // Example: check if file is 64-bit PE file
            var isPE64 = stream.Format == "PE32+";

            // Useful methods:
            // GetSymbolTable(), GetFunctionTable(), GetExports(), GetSections()
            // MapVATR() (maps a virtual address to a file offset), MapFileOffsetToVA() (the opposite) etc.

            // Example: get all sections in file

            /*  Section 00004370 0000000000008370 __text
             *  Section 01f48058 0000000001f4c058 __picsymbolstub4
             *  Section 01f4aba8 0000000001f4eba8 __stub_helper
             *  Section 01f4cbe8 0000000001f50be8 __gcc_except_tab ... */
            if (stream.TryGetSections(out var sections))
            {
                foreach (var section in sections)
                {
                    Console.WriteLine($"Section {section.ImageStart:x8} {section.VirtualStart:x16} {section.Name}");
                }
            }

            // You can use ReadWord and ReadWordArray to read a uint or ulong depending on whether the file is 32 or 64-bit

            // You can use ReadMappedX versions of all the Read functions to read from a virtual address mapped to the file

            // Example: Read 16 bytes from wherever virtual address 0x12345678 maps to in the file:
            try {
                var bytes = stream.ReadMappedBytes(0x12345678, 16);
            } catch { }

            // ReadMappedObjectPointerArray reads a list of VA pointers from the specified mapped VA,
            // then reads all of the objects

            // Example: VA 0x4000000 maps to 0x2000 in the file and contains 3 pointers, 0x5000010, 0x5000020, 0x5000440
            // which are the VAs of three 'ObjectInMemory' objects:
            try {
                var objs = stream.ReadMappedObjectPointerArray <ObjectInMemory>(0x4000000, 3);
            } catch { }

            // Set data.IsStreamModified if you change the stream contents
        }
Пример #4
0
        // Generate analytics from binary image
        public void PostProcessImage <T>(FileFormatStream <T> stream, PluginPostProcessImageEventInfo info) where T : FileFormatStream <T>
        {
            // Report to the user what is happening
            PluginServices.For(this).StatusUpdate("Generating analytics");

            // Get the section we would like to investigate
            Section section;

            try {
                section = stream.GetSections().Single(s => s.Name == sectionName.Value);
            }
            // Not all binaries have a section with this name, or any sections at all
            catch {
                return;
            }

            // Get contents of section
            var bytes = stream.ReadBytes(section.ImageStart, (int)(section.ImageEnd - section.ImageStart));

            // Produce frequency graph of bytes
            // This will produce a dictionary where the key is the byte value and the value is the number of times it occurred
            var freq = bytes.GroupBy(b => b).OrderBy(g => g.Key).ToDictionary(g => g.Key, g => (double)g.Count() * 100 / bytes.Length);

            // Write as CSV file
            if (Path.GetExtension(outputPath.Value) == ".csv")
            {
                var csv = new StringBuilder();
                csv.AppendLine("Byte,Count");
                csv.Append(string.Join(Environment.NewLine, freq.Select(f => f.Key + "," + f.Value)));

                File.WriteAllText(outputPath.Value, csv.ToString());
                return;
            }

            // Write as XLSX file (using nuget package Aspose.Cells)
            var wb    = new Workbook();
            var sheet = wb.Worksheets[0];

            // Add headers
            sheet.Cells["A1"].PutValue("Byte");
            sheet.Cells["B1"].PutValue("Count");

            // Create number format style
            var style = new CellsFactory().CreateStyle();

            style.Custom = "@"; // Text for hex bytes column

            // Add data
            for (var row = 0; row < freq.Count; row++)
            {
                sheet.Cells["A" + (row + 2)].PutValue($"{row:X2}");
                sheet.Cells["A" + (row + 2)].SetStyle(style, true);
                sheet.Cells["B" + (row + 2)].PutValue(freq[(byte)row]);
            }

            // Create table
            var list = sheet.ListObjects[sheet.ListObjects.Add("A1", "B257", hasHeaders: true)];

            list.TableStyleType = TableStyleType.TableStyleMedium6;

            // Create chart
            var chart = sheet.Charts[sheet.Charts.Add(ChartType.Column, 3, 3, 40, 26)];

            chart.Title.Text = "Frequency graph of data bytes";
            chart.Style      = 3;
            chart.ValueAxis.IsLogarithmic       = true;
            chart.ValueAxis.CrossAt             = 0.001;
            chart.ValueAxis.IsAutomaticMaxValue = false;
            chart.ValueAxis.MaxValue            = 100;
            chart.ValueAxis.LogBase             = 2;

            // Set chart data
            chart.SetChartDataRange("A1:B257", isVertical: true);

            chart.NSeries.CategoryData = "A2:A257";
            chart.NSeries[0].GapWidth  = 0; // 'Count' data series is at index 0 now that category has been set
            chart.ShowLegend           = false;

            // Save workbook
            wb.Save(outputPath.Value, SaveFormat.Xlsx);
        }