Beispiel #1
0
        public void Process()
        {
            Console.WriteLine("Loading image '{0}'...", fileName);

            hModule = Native.LoadLibraryEx(
                this.fileName,
                IntPtr.Zero,
                Native.LoadLibraryFlags.LOAD_LIBRARY_AS_IMAGE_RESOURCE
                );

            if (hModule == IntPtr.Zero)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Unable to load image!");
            }

            // LOAD_LIBRARY_AS_IMAGE_RESOURCE returns ( HMODULE | 2 )
            loadAddr = (long)(hModule.ToInt64() & ~2);

            Console.WriteLine("Loaded at 0x{0:X2}!", loadAddr);

            var dosHeader = Native.PtrToStruct <Native.IMAGE_DOS_HEADER>(new IntPtr(loadAddr));

            if (dosHeader.e_magic != Native.IMAGE_DOS_SIGNATURE)
            {
                throw new InvalidOperationException("Target image has invalid DOS signature!");
            }

            var peHeader = Native.PtrToStruct <Native.IMAGE_NT_HEADERS>(new IntPtr(this.loadAddr + dosHeader.e_lfanew));

            if (peHeader.Signature != Native.IMAGE_NT_SIGNATURE)
            {
                throw new InvalidOperationException("Target image has invalid PE signature!");
            }

            int sizeOfNtHeaders = 0;

            switch (peHeader.FileHeader.Machine)
            {
            case 0x014c:
                sizeOfNtHeaders = Marshal.SizeOf(typeof(Native.IMAGE_NT_HEADERS32));
                break;

            case 0x8664:
                sizeOfNtHeaders = Marshal.SizeOf(typeof(Native.IMAGE_NT_HEADERS64));
                break;

            default:
                throw new InvalidOperationException("Unexpected architecture in PE header: " + peHeader.FileHeader.Machine);
            }

            int  numSections      = peHeader.FileHeader.NumberOfSections;
            long baseSectionsAddr = loadAddr + dosHeader.e_lfanew + sizeOfNtHeaders;

            Console.WriteLine("# of sections: {0}", numSections);

            var sectionHeaders = new Native.IMAGE_SECTION_HEADER[numSections];

            for (int x = 0; x < sectionHeaders.Length; ++x)
            {
                long baseAddr = baseSectionsAddr + (x * Marshal.SizeOf(sectionHeaders[x]));

                var sectionHdr = Native.PtrToStruct <Native.IMAGE_SECTION_HEADER>(new IntPtr(baseAddr));

                var searchFlags =
                    Native.IMAGE_SECTION_HEADER.CharacteristicFlags.IMAGE_SCN_MEM_READ |
                    Native.IMAGE_SECTION_HEADER.CharacteristicFlags.IMAGE_SCN_CNT_INITIALIZED_DATA;

                var excludeFlags =
                    Native.IMAGE_SECTION_HEADER.CharacteristicFlags.IMAGE_SCN_MEM_WRITE |
                    Native.IMAGE_SECTION_HEADER.CharacteristicFlags.IMAGE_SCN_MEM_DISCARDABLE;

                if ((sectionHdr.Characteristics & searchFlags) != searchFlags)
                {
                    Console.WriteLine("\nSection '{0}' skipped: not an initialized read section.", sectionHdr.Name);
                    continue;
                }

                if ((sectionHdr.Characteristics & excludeFlags) != 0)
                {
                    Console.WriteLine("\nSection '{0}' skipped: not a non-discardable readonly section.", sectionHdr.Name);
                    continue;
                }

                ScanSection(sectionHdr);
            }

            if (deferredProtos.Count > 0)
            {
                Console.WriteLine("WARNING: Some protobufs were left unresolved: ");

                foreach (var proto in deferredProtos)
                {
                    DoParseFile(proto);
                }
            }

            FinalPassWriteFiles();
        }
Beispiel #2
0
        unsafe void ScanSection(Native.IMAGE_SECTION_HEADER sectionHdr)
        {
            long sectionDataAddr = loadAddr + sectionHdr.PointerToRawData;

            Console.WriteLine("\nScanning section '{0}' at 0x{1:X2}...\n", sectionHdr.Name, sectionDataAddr);

            byte *dataPtr = (byte *)(sectionDataAddr);
            byte *endPtr  = (byte *)(dataPtr + sectionHdr.SizeOfRawData);

            while (dataPtr < endPtr)
            {
                if (*dataPtr == 0x0A)
                {
                    byte *originalPtr   = dataPtr;
                    int   nullskiplevel = 0;

rescan:
                    int t   = nullskiplevel;
                    dataPtr = originalPtr;

                    byte[] data = null;

                    using (var ms = new MemoryStream())
                        using (var bw = new BinaryWriter(ms))
                        {
                            for (; *(short *)dataPtr != 0 || t-- > 0; dataPtr++)
                            {
                                bw.Write(*dataPtr);
                            }

                            bw.Write((byte)0);

                            data = ms.ToArray();
                        }


                    dataPtr++;

                    if (data.Length < 2)
                    {
                        dataPtr = originalPtr + 1;
                        continue;
                    }

                    byte strLen = data[1];

                    if (data.Length - 2 < strLen)
                    {
                        dataPtr = originalPtr + 1;
                        continue;
                    }

                    string protoName = Encoding.ASCII.GetString(data, 2, strLen);

                    if (!protoName.EndsWith(".proto"))
                    {
                        dataPtr = originalPtr + 1;
                        continue;
                    }

                    if (!HandleProto(protoName, data))
                    {
                        nullskiplevel++;

                        goto rescan;
                    }
                }
                else
                {
                    dataPtr++;
                }
            }
        }