Пример #1
0
        /// <summary>
        /// Gets a string from the string table
        /// </summary>
        /// <param name="elf">The ELF</param>
        /// <param name="offset">The offset in the string table</param>
        /// <returns>The string</returns>
        private static unsafe string getString(ELF32 *elf, uint offset)
        {
            SectionHeader *section = getSection(elf, elf->ShnStrNdx);
            uint           strtab  = (uint)elf + section->Offset;

            return(Util.CharPtrToString((char *)(strtab + offset)));
        }
Пример #2
0
        public static byte[] ToByteArrayComplete(SectionHeader *section)
        {
            var ret = new byte[section->Size];

            Marshal.Copy((IntPtr)section, ret, 0, ret.Length);

            return(ret);
        }
Пример #3
0
        public void *FindRVA(uint rva)
        {
            SectionHeader *pHeader = FindSection(rva);

            if (pHeader != null)
            {
                return(checked (pHeader->PointerToRawData + m_pData + (rva - pHeader->VirtualAddress)));
            }
            return(null);
        }
Пример #4
0
        public GMFileContent(byte[] data)
        {
            RawData = new UniquePtr(data);
            byte *hdr_b = RawData.BPtr;

            var basePtr = (SectionHeader *)hdr_b;

            Form = basePtr;

            if (Form->Identity != SectionHeaders.Form)
            {
                throw new InvalidDataException(ERR_NO_FORM);
            }

            SectionHeader *
                hdr    = basePtr + 1,
                hdrEnd = (SectionHeader *)((IntPtr)basePtr + (int)Form->Size);

            int headersMet = 0;

            for (; hdr < hdrEnd; hdr = unchecked ((SectionHeader *)((IntPtr)hdr + (int)hdr->Size) + 1), ++headersMet)
            {
                Chunks.Add(hdr->Identity, (IntPtr)hdr);

                for (int i = 0; i < HeaderOffsets.Length; i++)
                {
                    if (((SectionHeader *)((byte *)basePtr + HeaderOffsets[i]))->Identity == hdr->Identity)
                    {
                        Console.Error.WriteLine($"WARNING: chunk {hdr->MagicString()} encountered (at least) twice! Only the last occurrence will be exported! (If you see this message, consider reversing manually.)");
                    }
                }

                if (HeaderOffsets.Length >= headersMet)
                {
                    var ho = HeaderOffsets;
                    Array.Resize(ref ho, (headersMet == HeaderOffsets.Length) ? 1 : (headersMet + 2));
                    HeaderOffsets = ho;
                }
                HeaderOffsets[headersMet] = (byte *)hdr - (byte *)basePtr;
            }
        }
Пример #5
0
        private bool LoadSectionTable()
        {
            SectionHeader *pLast    = null;
            var            pCurrent = SectionTable;

            for (int i = 0; i < PEHeader->NumberOfSections; ++i, ++pCurrent)
            {
                try {
                    if (!pCurrent->Verify(m_optionalHeader, m_pData, m_fileSize, PEHeader))
                    {
                        return(false);
                    }
                    if (pLast != null)
                    {
                        try {
                            //Per the PE/COFF Spec Version 8.2, § 3:
                            //    > In an image file, the VAs for sections must be assigned by the linker so that they
                            //    > are in ascending order and adjacent, and they must be a multiple of the
                            //    > SectionAlignment value in the optional header.
                            //We check the alignment inside the call to Verify(). We check the
                            //"ascending order" / adjacney here.
                            if (
                                pCurrent->VirtualAddress < pLast->VirtualAddress ||
                                checked (pLast->VirtualAddress + pLast->GetAlignedVirtualSize(m_optionalHeader)) != pCurrent->VirtualAddress
                                )
                            {
                                return(false);
                            }
                        }
                        catch (OverflowException) {
                            return(false);
                        }
                    }
                    pLast = pCurrent;
                } catch (InvalidOperationException) {
                    return(false);
                }
            }
            return(true);
        }
Пример #6
0
 public static bool IsEmpty(SectionHeader *header) => header->Size <= 4;
Пример #7
0
        /// <summary>
        /// Executes an ELF file
        /// </summary>
        /// <param name="buffer">The buffer</param>
        /// <param name="size">The size of the ELF</param>
        /// <param name="argv">The arguments</param>
        /// <param name="flags">Spawn flags</param>
        /// <returns>The error code or PID</returns>
        public static unsafe int Execute(byte[] buffer, uint size, string[] argv, Task.SpawnFlags flags)
        {
            ELF32 *elf;

            fixed(byte *ptr = buffer)
            elf = (ELF32 *)ptr;

            if (!isValidELF(elf))
            {
                return(-(int)ErrorCode.EINVAL);
            }

            // Get program header
            ProgramHeader *programHeader = (ProgramHeader *)((int)elf + elf->PhOff);
            uint           virtAddress   = programHeader->VirtAddress;
            void *         allocated     = Heap.AlignedAlloc(0x1000, (int)size);

            // Loop through every section
            for (uint i = 0; i < elf->ShNum; i++)
            {
                SectionHeader *section = getSection(elf, i);

                // Only loadable sections
                if (section->Address == 0)
                {
                    continue;
                }

                uint offset = section->Address - virtAddress;

                // BSS
                if (section->Type == SectionHeaderType.SHT_NOBITS)
                {
                    Memory.Memclear((void *)((uint)allocated + offset), (int)section->Size);
                }
                // Copy
                else
                {
                    Memory.Memcpy((void *)((uint)allocated + offset), (void *)((uint)elf + section->Offset), (int)section->Size);
                }
            }

            // Count arguments
            int argc = 0;

            while (argv[argc] != null)
            {
                argc++;
            }

            // Make sure arguments are safe by copying them
            string[] argvClone = new string[argc + 1];
            for (int i = 0; i < argc; i++)
            {
                argvClone[i] = String.Clone(argv[i]);
            }

            // Stack
            int[] initialStack = new int[2];
            initialStack[0] = (int)Util.ObjectToVoidPtr(argvClone);
            initialStack[1] = argc;

            // Create thread
            Thread thread = new Thread();

            thread.Context.CreateNewContext((void *)elf->Entry, 2, initialStack, false);
            Heap.Free(initialStack);

            CPU.CLI();

            // Create task
            Task       newTask = new Task(TaskPriority.NORMAL, flags);
            X86Context context = (X86Context)newTask.Context;

            context.CreateNewContext(false);
            newTask.AddThread(thread);
            newTask.AddUsedAddress(allocated);

            // Task info
            newTask.Name    = argvClone[0];
            newTask.CMDLine = Array.Join(argvClone, argc, " ");
            newTask.AddUsedAddress(newTask.CMDLine);

            // Argv clone freeing
            newTask.AddUsedAddress(argvClone);
            for (int i = 0; i < argc; i++)
            {
                newTask.AddUsedAddress(argvClone[i]);
            }

            // Map memory
            Paging.PageDirectory *newDirectory = context.PageDirVirtual;
            Paging.PageFlags      pageFlags    = Paging.PageFlags.Present | Paging.PageFlags.Writable | Paging.PageFlags.UserMode;
            for (uint j = 0; j < size; j += 0x1000)
            {
                // Note: the physical memory is not always a continuous block
                Paging.MapPage(newDirectory, (int)Paging.GetPhysicalFromVirtual((void *)((int)allocated + j)), (int)(virtAddress + j), pageFlags);
            }

            // Schedule task
            Tasking.ScheduleTask(newTask);

            CPU.STI();

            return(newTask.PID);
        }
        public PE32(string path)
        {
            GruntyOS.IO.BinaryReader br = new GruntyOS.IO.BinaryReader(new GruntyOS.IO.FileStream(path, "r"));
            int  p         = 0;
            uint address   = 0;
            uint data_addr = 0;
            uint ib        = 0;

            for (int i = 0; i < (int)br.BaseStream.Data.Length; i++)
            {
                p = br.BaseStream.Position;
                if (br.ReadByte() == (byte)'P' && br.ReadByte() == (byte)'E')
                {
                    break;
                }
            }
            br.BaseStream.Position = p;
            Console.WriteLine("Start: " + p.ToString());
            byte[] hdr = new byte[(sizeof(PeHeader))];
            for (int i = 0; i < sizeof(PeHeader); i++)
            {
                hdr[i] = br.ReadByte();
            }

            fixed(byte *ptr = hdr)
            {
                PeHeader *header = (PeHeader *)ptr;

                Console.WriteLine(header->mMachine.ToString());
                byte[] ohdr = new byte[header->mSizeOfOptionalHeader];

                for (int i = 0; i < header->mSizeOfOptionalHeader; i++)
                {
                    ohdr[i] = br.ReadByte();
                }

                fixed(byte *ptr2 = ohdr)
                {
                    Pe32OptionalHeader *opt = (Pe32OptionalHeader *)ptr2;

                    Console.WriteLine(opt->mBaseOfCode.ToString());
                    byte[] tmp = new byte[40];
                    address   = opt->mBaseOfCode;
                    data_addr = opt->mBaseOfData;
                    ib        = opt->mImageBase;
                    for (int s = 0; s < header->mNumberOfSections; s++)
                    {
                        fixed(byte *ptr3 = tmp)
                        {
                            for (int i = 0; i < 40; i++)
                            {
                                tmp[i] = br.ReadByte();
                            }
                            SectionHeader *sec  = (SectionHeader *)ptr3;
                            string         name = "";

                            for (int c = 0; sec->Name[c] != 0; c++)
                            {
                                name += ((char)sec->Name[c]).ToString();
                            }
                            Section section = new Section();

                            section.Name            = name;
                            section.Address         = (uint)sec->PointerToRawData;
                            section.RelocationCount = (uint)sec->NumberOfRelocations;
                            section.RelocationPtr   = (uint)sec->PointerToRelocations;
                            section.Size            = (uint)sec->SizeOfRawData;
                            Console.WriteLine(((int)(uint)sec->VirtualAddress).ToString());
                            sections.Add(section);
                        }
                    }
                }

                for (int i = 0; i < sections.Count; i++)
                {
                    if (sections[i].Name == ".text")
                    {
                        text = new byte[sections[i].Size];
                        br.BaseStream.Position = (int)(uint)sections[i].Address;
                        for (int b = 0; b < (int)(uint)sections[i].Size; b++)
                        {
                            text[b] = br.ReadByte();
                        }
                    }
                    else if (sections[i].Name == ".data")
                    {
                        data = new byte[sections[i].Size];
                        br.BaseStream.Position = (int)(uint)sections[i].Address;
                        for (int b = 0; b < (int)(uint)sections[i].Size; b++)
                        {
                            data[b] = br.ReadByte();
                        }
                    }
                }
            }

            // We do not have paging working and I an to lazy to relocate this
            // so we are just loading this were the PE header tells us to
            // may be bad, because we 'could' be overwritting something
            // in RAM. Im not sure.... Lets hope not
            byte *dptr = (byte *)ib + address;

            for (int i = 0; i < text.Length; i++)
            {
                dptr[i] = text[i];
            }
            dptr = (byte *)ib + data_addr;
            for (int i = 0; i < data.Length; i++)
            {
                dptr[i] = data[i];
            }
            Caller cl = new Caller();

            cl.CallCode(ib + address); // Jump!!!!!
        }
Пример #9
0
        public static GMFile GetFile(byte[] data)
        {
            var ret = new GMFileContent();

            var   hdr_bp = new UniquePtr(data);
            byte *hdr_b  = hdr_bp.BPtr;

            var basePtr = (SectionHeader *)hdr_b;

            ret.Form = basePtr;

            if (ret.Form->Identity != SectionHeaders.Form)
            {
                throw new InvalidDataException(ERR_NO_FORM);
            }

            SectionHeader *
                hdr    = basePtr + 1,
                hdrEnd = (SectionHeader *)((IntPtr)basePtr + (int)ret.Form->Size);

            int headersMet = 0;

            while (hdr < hdrEnd)
            {
                switch (hdr->Identity)
                {
                case SectionHeaders.General:
                    ret.General = (SectionGeneral *)hdr;
                    break;

                case SectionHeaders.Options:
                    ret.Options = (SectionOptions *)hdr;
                    break;

                case SectionHeaders.Extensions:
                    ret.Extensions = (SectionUnknown *)hdr;
                    break;

                case SectionHeaders.Sounds:
                    ret.Sounds = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Sprites:
                    ret.Sprites = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Backgrounds:
                    ret.Backgrounds = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Paths:
                    ret.Paths = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Scripts:
                    ret.Scripts = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Shaders:
                    ret.Shaders = (SectionUnknown *)hdr;
                    break;

                case SectionHeaders.Fonts:
                    ret.Fonts = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Timelines:
                    ret.Timelines = (SectionUnknown *)hdr;
                    break;

                case SectionHeaders.Objects:
                    ret.Objects = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Rooms:
                    ret.Rooms = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.DataFiles:
                    ret.DataFiles = (SectionUnknown *)hdr;
                    break;

                case SectionHeaders.TexturePage:
                    ret.TexturePages = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Code:
                    ret.Code = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Variables:
                    ret.Variables = (SectionRefDefs *)hdr;
                    break;

                case SectionHeaders.Functions:
                    ret.Functions = (SectionRefDefs *)hdr;
                    break;

                case SectionHeaders.Strings:
                    ret.Strings = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Textures:
                    ret.Textures = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Audio:
                    ret.Audio = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.AudioGroup:
                    ret.AudioGroup = (SectionUnknown *)hdr;
                    break;
                }

                ret.HeaderOffsets[headersMet++] = (byte *)hdr - (byte *)basePtr;
                hdr = unchecked ((SectionHeader *)((IntPtr)hdr + (int)hdr->Size) + 1);
            }

            ret.RawData = hdr_bp;

            return(new GMFile(ret));
        }
Пример #10
0
        public static GMFile GetFile(byte[] data)
        {
            var ret = new GMFileContent();

            var   hdr_bp = new UniquePtr(data);
            byte *hdr_b  = hdr_bp.BPtr;

            var basePtr = (SectionHeader *)hdr_b;

            ret.Form = basePtr;

            if (ret.Form->Identity != SectionHeaders.Form)
            {
                throw new InvalidDataException(ERR_NO_FORM);
            }

            SectionHeader *
                hdr    = basePtr + 1,
                hdrEnd = (SectionHeader *)((IntPtr)basePtr + (int)ret.Form->Size);

            int headersMet = 0;

            while (hdr < hdrEnd)
            {
                switch (hdr->Identity)
                {
                case SectionHeaders.General:
                    ret.General = (SectionGeneral *)hdr;
                    break;

                case SectionHeaders.Options:
                    ret.Options = (SectionOptions *)hdr;
                    break;

                case SectionHeaders.Extensions:
                    ret.Extensions = (SectionUnknown *)hdr;

                    if (!ret.Extensions->IsEmpty())
                    {
                        Console.WriteLine("Warning: EXTN chunk is not empty, its content will not be exported!");
                    }
                    break;

                case SectionHeaders.Sounds:
                    ret.Sounds = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Sprites:
                    ret.Sprites = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Backgrounds:
                    ret.Backgrounds = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Paths:
                    ret.Paths = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Scripts:
                    ret.Scripts = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Shaders:
                    ret.Shaders = (SectionUnknown *)hdr;

                    if (!ret.Shaders->IsEmpty())
                    {
                        Console.WriteLine("Warning: SHDR chunk is not empty, its content will not be exported!");
                    }
                    break;

                case SectionHeaders.Fonts:
                    ret.Fonts = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Timelines:
                    ret.Timelines = (SectionUnknown *)hdr;

                    if (!ret.Timelines->IsEmpty())
                    {
                        Console.WriteLine("Warning: TMLN chunk is not empty, its content will not be exported!");
                    }
                    break;

                case SectionHeaders.Objects:
                    ret.Objects = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Rooms:
                    ret.Rooms = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.DataFiles:
                    ret.DataFiles = (SectionUnknown *)hdr;

                    if (!ret.DataFiles->IsEmpty())
                    {
                        Console.WriteLine("Warning: DAFL chunk is not empty, its content will not be exported!");
                    }
                    break;

                case SectionHeaders.TexturePage:
                    ret.TexturePages = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Code:
                    ret.Code = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Variables:
                    ret.Variables = (SectionRefDefs *)hdr;
                    break;

                case SectionHeaders.Functions:
                    ret.Functions = (SectionRefDefs *)hdr;
                    break;

                case SectionHeaders.Strings:
                    ret.Strings = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Textures:
                    ret.Textures = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.Audio:
                    ret.Audio = (SectionCountOffsets *)hdr;
                    break;

                case SectionHeaders.AudioGroup:
                    ret.AudioGroup = (SectionUnknown *)hdr;

                    if (!ret.AudioGroup->IsEmpty())
                    {
                        Console.WriteLine("Warning: AGRP chunk is not empty, its content will not be exported!");
                    }
                    break;

                case SectionHeaders.GNAL_Unk:
                    ret.GNAL_Unk = (SectionUnknown *)hdr;

                    if (!ret.GNAL_Unk->IsEmpty())
                    {
                        Console.WriteLine("Warning: GNAL chunk is not empty, its content will not be exported!");
                    }
                    break;

                default:
                    var unk = (SectionUnknown *)hdr;
                    if (!unk->IsEmpty())
                    {
                        Console.WriteLine($"Warning: unknown chunk {hdr->Identity.ToChunkName()}, chunk is not empty, its content will not be exported!");
                    }

                    ret.UnknownChunks.Add(hdr->Identity, (IntPtr)unk);
                    break;
                }

                for (int i = 0; i < ret.HeaderOffsets.Length; i++)
                {
                    if (((SectionHeader *)((byte *)basePtr + ret.HeaderOffsets[i]))->Identity == hdr->Identity)
                    {
                        Console.WriteLine($"WARNING: chunk {hdr->MagicString()} encountered (at least) twice! Only the last occurrence will be exported! (If you see this message, consider reversing manually.)");
                    }
                }

                if (ret.HeaderOffsets.Length >= headersMet)
                {
                    var ho = ret.HeaderOffsets;

                    Array.Resize(ref ho, (headersMet == ret.HeaderOffsets.Length) ? 1 : (headersMet + 2));

                    ret.HeaderOffsets = ho;
                }

                ret.HeaderOffsets[headersMet++] = (byte *)hdr - (byte *)basePtr;
                hdr = unchecked ((SectionHeader *)((IntPtr)hdr + (int)hdr->Size) + 1);
            }

            ret.RawData = hdr_bp;

            return(new GMFile(ret));
        }