Example #1
0
        /// <summary>
        /// Edit an specific address
        /// </summary>
        /// <param name="address">Old address</param>
        /// <param name="newAddress">New address</param>
        /// <param name="newType">New type</param>
        /// <returns>True if edited with success, else false</returns>
        public bool EditRelocation(uint address, uint newAddress, BASE_RELOCATION_TYPE newType)
        {
            uint   oldAddress = (address & 0xFFFFF000) - imageBase;
            ushort oldOffset  = (ushort)(address & 0x00000FFF);

            BASE_RELOCATION_TYPE oldType = BASE_RELOCATION_TYPE.ABSOLUTE;
            List <Reloc>         relocs;

            if (!pages.TryGetValue(oldAddress, out relocs))
            {
                return(false);
            }

            foreach (Reloc reloc in relocs)
            {
                if (reloc.offset == oldOffset)
                {
                    oldType = reloc.type;
                    break;
                }
            }

            if (oldType == BASE_RELOCATION_TYPE.ABSOLUTE)
            {
                return(false);
            }

            // delete old address and add new address. If not success, restore old address
            if (!DeleteRelocation(address))
            {
                return(false);
            }

            if (AddRelocation(newAddress, newType) <= 0)
            {
                AddRelocation(address, oldType);
                return(false);
            }

            IsNotSaved = true;
            return(true);
        }
Example #2
0
        /// <summary>
        /// Open the file specified into the <paramref name="path"/>, read the relocation section
        /// and load it.
        /// </summary>
        /// <param name="path"></param>
        public Relocations(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException();
            }

            this.path       = path;
            this.IsNotSaved = false;

            BinaryReader br = new BinaryReader(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read));

            if (br.ReadInt16() != 0x5A4D) // MZ signature
            {
                br.Close();
                throw new InvalidOperationException("MZ");
            }

            br.BaseStream.Seek(0x3C, SeekOrigin.Begin);           // go to ptr to COFF File Header
            br.BaseStream.Seek(br.ReadInt32(), SeekOrigin.Begin); // go to COFF File Header

            if (br.ReadInt32() != 0x00004550)                     // PE\0\0
            {
                br.Close();
                throw new InvalidOperationException("PE");
            }

            br.ReadUInt16(); // machine ID. Ignored
            uint numbersOfSections = br.ReadUInt16();

            br.BaseStream.Seek(20 - 4, SeekOrigin.Current); // go to magic number (PE or PE+ = x86 or x64)

            if (br.ReadInt16() != 0x010B)
            {
                br.Close();
                throw new InvalidOperationException("X86");
            }

            br.BaseStream.Seek(26, SeekOrigin.Current);      // go to ImageBase
            imageBase = br.ReadUInt32();
            br.BaseStream.Seek(64 + 40, SeekOrigin.Current); // go to Data Directories -> Base Relocation Table

            virtualAddress     = br.ReadUInt32();
            addressVirtualSize = br.BaseStream.Position;
            virtualSize        = br.ReadUInt32();

            br.BaseStream.Seek(80, SeekOrigin.Current); // jump to Section Table

            // find the RAW address/size
            RawAddress = 0;
            RawSize    = 0;

            for (int i = 0; i < numbersOfSections; i++)
            {
                br.BaseStream.Seek(12, SeekOrigin.Current);

                if (br.ReadUInt32() == virtualAddress)
                {
                    RawSize    = br.ReadUInt32();
                    RawAddress = br.ReadUInt32();
                    break;
                }

                br.BaseStream.Seek(24, SeekOrigin.Current); // place the pointer to the next section
            }

            if (RawAddress == 0x00 || RawSize == 0x00)
            {
                br.Close();
                throw new InvalidOperationException("RAW");
            }

            // reading relocation section
            br.BaseStream.Seek(RawAddress, SeekOrigin.Begin);

            pages = new SortedDictionary <uint, List <Reloc> >();

            while (br.BaseStream.Position < RawAddress + virtualSize) // 4K block loop
            {
                uint address = br.ReadUInt32();
                uint size    = br.ReadUInt32();
                uint count   = (size - 8) / 2;

                List <Reloc> relocs = new List <Reloc>();

                for (int i = 0; i < count; i++) // offsets loop
                {
                    ushort data = br.ReadUInt16();
                    BASE_RELOCATION_TYPE type = (BASE_RELOCATION_TYPE)((data & 0xF000) >> 12);
                    ushort offset             = (ushort)(data & 0x0FFF);

                    Reloc reloc = new Reloc();
                    reloc.offset = offset;
                    reloc.type   = type;

                    relocs.Add(reloc);
                }

                pages.Add(address, relocs);
            }

            br.Close();
        }
Example #3
0
        /// <summary>
        /// Add a relocation address
        /// </summary>
        /// <param name="address">Address to add</param>
        /// <param name="type">Type of relocation</param>
        /// <returns>-1 if duplicated, 0 if not added, 1 if added a page and 2 if added only in reloc of page</returns>
        public int AddRelocation(uint address, BASE_RELOCATION_TYPE type)
        {
            if (address < imageBase)
            {
                return(0);
            }

            uint   page   = (address & 0xFFFFF000) - imageBase;
            ushort offset = (ushort)(address & 0x00000FFF);

            if (!pages.ContainsKey(page)) // create a new page if doesn't exists
            {
                if (RawSize - virtualSize < 12)
                {
                    return(0);
                }

                List <Reloc> relocs = new List <Reloc>();

                Reloc reloc = new Reloc();
                reloc.offset = offset;
                reloc.type   = type;
                relocs.Add(reloc);

                reloc        = new Reloc();
                reloc.offset = 0;
                reloc.type   = BASE_RELOCATION_TYPE.ABSOLUTE;
                relocs.Add(reloc);

                pages.Add(page, relocs);

                virtualSize += 12;

                IsNotSaved = true;
                return(1);
            }
            else // just added the offset
            {
                List <Reloc> relocs;

                if (!pages.TryGetValue(page, out relocs))
                {
                    return(0);
                }

                foreach (Reloc item in relocs) // search if address already present
                {
                    if (item.offset == offset && item.type != BASE_RELOCATION_TYPE.ABSOLUTE)
                    {
                        return(-1);
                    }
                }

                if (relocs.Count % 2 == 0) // align in 32bits
                {
                    bool isAlignDeleted = false;

                    foreach (Reloc item in relocs) // search if align already exists
                    {
                        if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE)
                        {
                            relocs.Remove(item);
                            isAlignDeleted = true;
                            virtualSize   -= 2;
                            break;
                        }
                    }

                    if (!isAlignDeleted) // if no align reloc found, add it
                    {
                        if (RawSize - virtualSize < 4)
                        {
                            return(0);
                        }

                        Reloc item = new Reloc();
                        item.offset = 0;
                        item.type   = BASE_RELOCATION_TYPE.ABSOLUTE;

                        relocs.Add(item);
                        virtualSize += 2;
                    }
                }

                Reloc reloc = new Reloc();
                reloc.offset = offset;
                reloc.type   = type;

                relocs.Add(reloc);

                virtualSize += 2;

                IsNotSaved = true;
                return(2);
            }
        }
        /// <summary>
        /// Edit an specific address
        /// </summary>
        /// <param name="address">Old address</param>
        /// <param name="newAddress">New address</param>
        /// <param name="newType">New type</param>
        /// <returns>True if edited with success, else false</returns>
        public bool EditRelocation(uint address, uint newAddress, BASE_RELOCATION_TYPE newType)
        {
            uint oldAddress = (address & 0xFFFFF000) - imageBase;
            ushort oldOffset = (ushort)(address & 0x00000FFF);

            BASE_RELOCATION_TYPE oldType = BASE_RELOCATION_TYPE.ABSOLUTE;
            List<Reloc> relocs;

            if (!pages.TryGetValue(oldAddress, out relocs))
                return false;

            foreach (Reloc reloc in relocs)
            {
                if (reloc.offset == oldOffset)
                {
                    oldType = reloc.type;
                    break;
                }
            }

            if (oldType == BASE_RELOCATION_TYPE.ABSOLUTE)
                return false;

            // delete old address and add new address. If not success, restore old address
            if (!DeleteRelocation(address))
                return false;

            if (AddRelocation(newAddress, newType) <= 0)
            {
                AddRelocation(address, oldType);
                return false;
            }

            IsNotSaved = true;
            return true;
        }
        /// <summary>
        /// Add a relocation address
        /// </summary>
        /// <param name="address">Address to add</param>
        /// <param name="type">Type of relocation</param>
        /// <returns>-1 if duplicated, 0 if not added, 1 if added a page and 2 if added only in reloc of page</returns>
        public int AddRelocation(uint address, BASE_RELOCATION_TYPE type)
        {
            if (address < imageBase)
                return 0;

            uint page = (address & 0xFFFFF000) - imageBase;
            ushort offset = (ushort)(address & 0x00000FFF);

            if (!pages.ContainsKey(page)) // create a new page if doesn't exists
            {
                if (RawSize - virtualSize < 12)
                    return 0;

                List<Reloc> relocs = new List<Reloc>();

                Reloc reloc = new Reloc();
                reloc.offset = offset;
                reloc.type = type;
                relocs.Add(reloc);

                reloc = new Reloc();
                reloc.offset = 0;
                reloc.type = BASE_RELOCATION_TYPE.ABSOLUTE;
                relocs.Add(reloc);

                pages.Add(page, relocs);

                virtualSize += 12;

                IsNotSaved = true;
                return 1;
            }
            else // just added the offset
            {
                List<Reloc> relocs;

                if (!pages.TryGetValue(page, out relocs))
                    return 0;

                foreach (Reloc item in relocs) // search if address already present
                {
                    if (item.offset == offset && item.type != BASE_RELOCATION_TYPE.ABSOLUTE)
                        return -1;
                }

                if (relocs.Count % 2 == 0) // align in 32bits
                {
                    bool isAlignDeleted = false;

                    foreach (Reloc item in relocs) // search if align already exists
                    {
                        if (item.offset == 0 && item.type == BASE_RELOCATION_TYPE.ABSOLUTE)
                        {
                            relocs.Remove(item);
                            isAlignDeleted = true;
                            virtualSize -= 2;
                            break;
                        }
                    }

                    if (!isAlignDeleted) // if no align reloc found, add it
                    {
                        if (RawSize - virtualSize < 4)
                            return 0;

                        Reloc item = new Reloc();
                        item.offset = 0;
                        item.type = BASE_RELOCATION_TYPE.ABSOLUTE;

                        relocs.Add(item);
                        virtualSize += 2;
                    }
                }

                Reloc reloc = new Reloc();
                reloc.offset = offset;
                reloc.type = type;

                relocs.Add(reloc);

                virtualSize += 2;

                IsNotSaved = true;
                return 2;
            }
        }