/// <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))); }
public static byte[] ToByteArrayComplete(SectionHeader *section) { var ret = new byte[section->Size]; Marshal.Copy((IntPtr)section, ret, 0, ret.Length); return(ret); }
public void *FindRVA(uint rva) { SectionHeader *pHeader = FindSection(rva); if (pHeader != null) { return(checked (pHeader->PointerToRawData + m_pData + (rva - pHeader->VirtualAddress))); } return(null); }
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; } }
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); }
public static bool IsEmpty(SectionHeader *header) => header->Size <= 4;
/// <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!!!!! }
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)); }
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)); }