public OSRel(byte[] file, int address)
 {
     offset  = ByteConverter.ToUInt16(file, address);
     type    = file[address + 2];
     section = file[address + 3];
     addend  = ByteConverter.ToUInt32(file, address + 4);
 }
        public static uint?SetupEXE(ref byte[] exefile)
        {
            if (ByteConverter.ToUInt16(exefile, 0) != 0x5A4D)
            {
                return(null);
            }
            int ptr = ByteConverter.ToInt32(exefile, 0x3c);

            if (ByteConverter.ToInt32(exefile, (int)ptr) != 0x4550)             //PE\0\0
            {
                return(null);
            }
            ptr += 4;
            UInt16 numsects = ByteConverter.ToUInt16(exefile, (int)ptr + 2);

            ptr += 0x14;
            int  PEHead    = ptr;
            uint imageBase = ByteConverter.ToUInt32(exefile, ptr + 28);

            byte[] result = new byte[ByteConverter.ToUInt32(exefile, ptr + 56)];
            Array.Copy(exefile, result, ByteConverter.ToUInt32(exefile, ptr + 60));
            ptr += 0xe0;
            for (int i = 0; i < numsects; i++)
            {
                Array.Copy(exefile, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FAddr), result, ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.VAddr), ByteConverter.ToInt32(exefile, ptr + (int)SectOffs.FSize));
                ptr += (int)SectOffs.Size;
            }
            exefile = result;
            return(imageBase);
        }
        public uint bssAlign;                      // bss alignment constraint

        public OSModuleHeader(byte[] file, int address)
        {
            info              = new OSModuleInfo(file, address);
            address          += 0x20;
            bssSize           = ByteConverter.ToUInt32(file, address);
            address          += 4;
            relOffset         = ByteConverter.ToUInt32(file, address);
            address          += 4;
            impOffset         = ByteConverter.ToUInt32(file, address);
            address          += 4;
            impSize           = ByteConverter.ToUInt32(file, address);
            address          += 4;
            prologSection     = file[address++];
            epilogSection     = file[address++];
            unresolvedSection = file[address++];
            padding0          = file[address++];
            prolog            = ByteConverter.ToUInt32(file, address);
            address          += 4;
            epilog            = ByteConverter.ToUInt32(file, address);
            address          += 4;
            unresolved        = ByteConverter.ToUInt32(file, address);
            address          += 4;
            align             = ByteConverter.ToUInt32(file, address);
            address          += 4;
            bssAlign          = ByteConverter.ToUInt32(file, address);
        }
        public static int GetPointer(this byte[] file, int address, uint imageBase)
        {
            uint tmp = ByteConverter.ToUInt32(file, address);

            if (tmp == 0)
            {
                return(0);
            }
            return((int)(tmp - imageBase));
        }
        public static bool CheckBigEndianInt32(byte[] file, int address)
        {
            bool bigEndState = ByteConverter.BigEndian;

            ByteConverter.BigEndian = true;
            bool isBigEndian = BitConverter.ToUInt32(file, address) > ByteConverter.ToUInt32(file, address);

            ByteConverter.BigEndian = bigEndState;

            return(isBigEndian);
        }
        public static uint GetNewSectionAddress(byte[] exefile)
        {
            int ptr = ByteConverter.ToInt32(exefile, 0x3c);

            ptr += 4;
            UInt16 numsects = ByteConverter.ToUInt16(exefile, (int)ptr + 2);

            ptr += 0x14;
            ptr += 0xe0;
            ptr += (int)SectOffs.Size * (numsects - 1);
            return(HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr + (int)SectOffs.VAddr) + ByteConverter.ToUInt32(exefile, ptr + (int)SectOffs.VSize)));
        }
        public uint version;                    // version number

        public OSModuleInfo(byte[] file, int address)
        {
            id                = ByteConverter.ToUInt32(file, address);
            address          += 4;
            link              = new OSModuleLink(file, address);
            address          += 8;
            numSections       = ByteConverter.ToUInt32(file, address);
            address          += 4;
            sectionInfoOffset = ByteConverter.ToUInt32(file, address);
            address          += 4;
            nameOffset        = ByteConverter.ToUInt32(file, address);
            address          += 4;
            nameSize          = ByteConverter.ToUInt32(file, address);
            address          += 4;
            version           = ByteConverter.ToUInt32(file, address);
        }
        public static void CreateNewSection(ref byte[] exefile, string name, byte[] data, bool isCode)
        {
            int ptr = ByteConverter.ToInt32(exefile, 0x3c);

            ptr += 4;
            UInt16 numsects   = ByteConverter.ToUInt16(exefile, ptr + 2);
            int    sectnumptr = ptr + 2;

            ptr += 0x14;
            int PEHead = ptr;

            ptr += 0xe0;
            int sectptr = ptr;

            ptr += (int)SectOffs.Size * numsects;
            ByteConverter.GetBytes((ushort)(numsects + 1)).CopyTo(exefile, sectnumptr);
            Array.Clear(exefile, ptr, 8);
            Encoding.ASCII.GetBytes(name).CopyTo(exefile, ptr);
            UInt32 vaddr = HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.VAddr) + ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.VSize));

            ByteConverter.GetBytes(vaddr).CopyTo(exefile, ptr + (int)SectOffs.VAddr);
            UInt32 faddr = HelperFunctions.Align(ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.FAddr) + ByteConverter.ToUInt32(exefile, ptr - (int)SectOffs.Size + (int)SectOffs.FSize));

            ByteConverter.GetBytes(faddr).CopyTo(exefile, ptr + (int)SectOffs.FAddr);
            ByteConverter.GetBytes(isCode ? 0x60000020 : 0xC0000040).CopyTo(exefile, ptr + (int)SectOffs.Flags);
            int diff = (int)HelperFunctions.Align((uint)data.Length);

            ByteConverter.GetBytes(diff).CopyTo(exefile, ptr + (int)SectOffs.VSize);
            ByteConverter.GetBytes(diff).CopyTo(exefile, ptr + (int)SectOffs.FSize);
            if (isCode)
            {
                ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 4) + diff)).CopyTo(exefile, PEHead + 4);
            }
            else
            {
                ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 8) + diff)).CopyTo(exefile, PEHead + 8);
            }
            ByteConverter.GetBytes(Convert.ToUInt32(ByteConverter.ToUInt32(exefile, PEHead + 0x38) + diff)).CopyTo(exefile, PEHead + 0x38);
            Array.Resize(ref exefile, exefile.Length + diff);
            data.CopyTo(exefile, vaddr);
        }
        public static byte[] DecompressREL(byte[] file)
        {
            // Scan the array for the last instance of the "SaCompGC" string because there are some files with redundant headers
            int  start        = 0;
            bool isCompressed = false;
            bool bigend       = ByteConverter.BigEndian;

            ByteConverter.BigEndian = true;
            for (int u = file.Length - 8; u >= 0; u--)
            {
                if (ByteConverter.ToUInt32(file, u) == 0x5361436F)                // && BitConverter.ToUInt32(file, u + 4) == 0x4347706D)
                {
                    start        = u;
                    isCompressed = true;
                    break;
                }
            }
            if (!isCompressed)
            {
                return(file);
            }
            byte[] input = new byte[file.Length - start];
            Array.Copy(file, start, input, 0, input.Length);

            // Process the new array
            IntPtr pnt_input = Marshal.AllocHGlobal(input.Length);

            Marshal.Copy(input, 0, pnt_input, input.Length);
            int    size_output = (int)GetDecompressedSize(pnt_input);
            IntPtr pnt_output  = Marshal.AllocHGlobal(size_output);

            DecompressBuffer(pnt_input, pnt_output);
            byte[] decompbuf = new byte[size_output];
            Marshal.Copy(pnt_output, decompbuf, 0, size_output);
            Marshal.FreeHGlobal(pnt_output);
            Marshal.FreeHGlobal(pnt_input);
            ByteConverter.BigEndian = bigend;
            return(decompbuf);
        }
Beispiel #10
0
 public override uint ReadUInt32()
 {
     return(ByteConverter.ToUInt32(ReadBytes(sizeof(uint)), 0));
 }
        public uint offset;                              // offset to OSRel instructions

        public OSImportInfo(byte[] file, int address)
        {
            id     = ByteConverter.ToUInt32(file, address);
            offset = ByteConverter.ToUInt32(file, address + 4);
        }
 public OSSectionInfo(byte[] file, int address)
 {
     offset = ByteConverter.ToUInt32(file, address);
     size   = ByteConverter.ToUInt32(file, address + 4);
 }
 public OSModuleLink(byte[] file, int address)
 {
     next = ByteConverter.ToUInt32(file, address);
     prev = ByteConverter.ToUInt32(file, address + 4);
 }
        public static void FixRELPointers(byte[] file, uint imageBase = 0)
        {
            OSModuleHeader header = new OSModuleHeader(file, 0);

            OSSectionInfo[] sections = new OSSectionInfo[header.info.numSections];
            for (int i = 0; i < header.info.numSections; i++)
            {
                sections[i] = new OSSectionInfo(file, (int)header.info.sectionInfoOffset + (i * 8));
            }
            OSImportInfo[] imports = new OSImportInfo[header.impSize / 8];
            for (int i = 0; i < imports.Length; i++)
            {
                imports[i] = new OSImportInfo(file, (int)header.impOffset + (i * 8));
            }
            int reladdr = 0;

            for (int i = 0; i < imports.Length; i++)
            {
                if (imports[i].id == header.info.id)
                {
                    reladdr = (int)imports[i].offset;
                    break;
                }
            }
            OSRel rel      = new OSRel(file, reladdr);
            int   dataaddr = 0;

            unchecked
            {
                while (rel.type != (byte)RelocTypes.R_DOLPHIN_END)
                {
                    dataaddr += rel.offset;
                    uint sectionbase = (uint)(sections[rel.section].offset & ~1);
                    switch (rel.type)
                    {
                    case 0x01:
                        ByteConverter.GetBytes(rel.addend + sectionbase + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x02:
                        ByteConverter.GetBytes((ByteConverter.ToUInt32(file, dataaddr) & 0xFC000003) | ((rel.addend + sectionbase) & 0x3FFFFFC) + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x03:
                    case 0x04:
                        ByteConverter.GetBytes((ushort)(rel.addend + sectionbase) + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x05:
                        ByteConverter.GetBytes((ushort)((rel.addend + sectionbase) >> 16) + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x06:
                        ByteConverter.GetBytes((ushort)(((rel.addend + sectionbase) >> 16) + (((rel.addend + sectionbase) & 0x8000) == 0x8000 ? 1 : 0)) + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x0A:
                        ByteConverter.GetBytes((uint)((ByteConverter.ToUInt32(file, dataaddr) & 0xFC000003) | (((rel.addend + sectionbase) - dataaddr) & 0x3FFFFFC)) + imageBase).CopyTo(file, dataaddr);
                        break;

                    case 0x00:
                    case (byte)RelocTypes.R_DOLPHIN_NOP:
                    case (byte)RelocTypes.R_DOLPHIN_END:
                        break;

                    case (byte)RelocTypes.R_DOLPHIN_SECTION:
                        dataaddr = (int)sectionbase;
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    reladdr += 8;
                    rel      = new OSRel(file, reladdr);
                }
            }
        }
 public static int GetPointer(this byte[] file, int address, uint imageBase)
 {
     return((int)(ByteConverter.ToUInt32(file, address) - imageBase));
 }