public Elf32_Shdr(Elf32_Shdr shdr) { sh_name = shdr.sh_name; sh_type = shdr.sh_type; sh_flags = shdr.sh_flags; sh_addr = shdr.sh_addr; sh_offset = shdr.sh_offset; sh_size = shdr.sh_size; sh_link = shdr.sh_link; sh_info = shdr.sh_info; sh_addralign = shdr.sh_addralign; sh_entsize = shdr.sh_entsize; }
public ELF32(string filename, bool readSectionHeaders) : this() { FileStream fs = File.Open(filename, FileMode.Open); byte[] ehdrBytes = new byte[52]; fs.Read(ehdrBytes, 0, ehdrBytes.Length); fs.Close(); if (!(ehdrBytes[(byte)EI.MagicNumber0] == 0x7F && ehdrBytes[(byte)EI.MagicNumber1] == 'E' && ehdrBytes[(byte)EI.MagicNumber2] == 'L' && ehdrBytes[(byte)EI.MagicNumber3] == 'F')) { throw new FormatException("It is not an ELF file."); } if (ehdrBytes[(byte)EI.FileClass] == (byte)EC.ELF64) { throw new FormatException("It is an ELF64 file."); } else if (ehdrBytes[(byte)EI.FileClass] != (byte)EC.ELF32) { throw new FormatException("It is an invalid ELF class."); } ValueRead read = new ValueRead(ehdrBytes[(byte)EI.DataEncoding]); Header = new Elf32_Ehdr(ehdrBytes, read); SectionHeader = new Elf32_Shdr[Header.e_shnum]; SectionName = new string[Header.e_shnum]; if (readSectionHeaders && SectionHeader.Length != 0) { fs = File.Open(filename, FileMode.Open); byte[] shdrBytes = new byte[Header.e_shnum * Header.e_shentsize]; fs.Position = Header.e_shoff; fs.Read(shdrBytes, 0, shdrBytes.Length); fs.Close(); for (int i = 0; i < Header.e_shnum; i++) { SectionHeader[i] = new Elf32_Shdr(shdrBytes, (uint)(Header.e_shentsize * i), read); SectionName[i] = ""; } } }
private void WriteSectionTableEntry32(ElfSection section) { var shdr = new Elf32_Shdr(); _encoder.Encode(out shdr.sh_name, ObjectFile.SectionHeaderStringTable?.GetOrCreateIndex(section.Name) ?? 0); _encoder.Encode(out shdr.sh_type, (uint)section.Type); _encoder.Encode(out shdr.sh_flags, (uint)section.Flags); _encoder.Encode(out shdr.sh_addr, (uint)section.VirtualAddress); _encoder.Encode(out shdr.sh_offset, (uint)section.Offset); _encoder.Encode(out shdr.sh_size, (uint)section.Size); _encoder.Encode(out shdr.sh_link, section.Link.GetIndex()); _encoder.Encode(out shdr.sh_info, section.Info.GetIndex()); _encoder.Encode(out shdr.sh_addralign, (uint)section.Alignment); _encoder.Encode(out shdr.sh_entsize, (uint)section.TableEntrySize); Write(shdr); }
private Elf32_Shdr[] LoadSectionHeaders(int count, uint imageOffset) { var rdr = CreateImageReader(imageOffset); var headers = new Elf32_Shdr[count]; for (int i = 0; i < count; ++i) { Elf32_Shdr pShdr = new Elf32_Shdr(); pShdr.sh_name = rdr.ReadUInt32(); pShdr.sh_type = (SectionType) rdr.ReadUInt32(); pShdr.sh_flags = (SectionFlags) rdr.ReadUInt32(); pShdr.sh_addr = rdr.ReadUInt32(); pShdr.sh_offset = rdr.ReadUInt32(); pShdr.sh_size = rdr.ReadUInt32(); pShdr.sh_link = rdr.ReadInt32(); pShdr.sh_info = rdr.ReadInt32(); pShdr.sh_addralign = rdr.ReadInt32(); pShdr.sh_entsize = rdr.ReadUInt32(); headers[i] = pShdr; //Debug.Print("Section {0}", i); //Dump("sh_name: {0}", pShdr.sh_name); //Dump("sh_type: {0}", pShdr.sh_type); //Dump("sh_flags: {0}", pShdr.sh_flags); //Dump("sh_addr: {0:X}", pShdr.sh_addr); //Dump("sh_offset: {0}", pShdr.sh_offset); //Dump("sh_size: {0}", pShdr.sh_size); //Dump("sh_link: {0}", pShdr.sh_link); //Dump("sh_info: {0}", pShdr.sh_info); //Dump("sh_addralign: {0}", pShdr.sh_addralign); //Dump("sh_entsize: {0}", pShdr.sh_entsize); } return headers; }
private static void GetEmbeddedModule32(ModuleReader reader, byte[] ident) { // Read the endiannes. bool big = ident[(int)ElfIdent.EI_DATA] == (int)ElfData.ELFDATA2MSB; // Read the header. Elf32_Ehdr header = new Elf32_Ehdr(); header.Read(reader, big); // Reject files without section names. if (header.e_shstrndex == (int)ElfSectionNumber.SHN_UNDEF) { throw new ModuleException("Unsupported elfs without section names"); } // Read the "section names" section. reader.SetPosition((uint)(header.e_shoff + header.e_shstrndex * header.e_shentsize)); Elf32_Shdr namesHeader = new Elf32_Shdr(); namesHeader.Read(reader, big); // Reject files without real section names. if (namesHeader.sh_size == 0) { throw new ModuleException("This elf doesn't have section names."); } // Read the name table. byte[] nameTable; reader.SetPosition(namesHeader.sh_offset); reader.Read(out nameTable, (int)namesHeader.sh_size); // Move to the section header table. reader.SetPosition(header.e_shoff); // Read the section until hit '.cbm'. Elf32_Shdr sectionHeader = new Elf32_Shdr(); bool found = false; StringBuilder builder = new StringBuilder(); for (int i = 0; i < header.e_shnum; ++i) { // Read the section header. sectionHeader.Read(reader, big); // Check the section name. if (sectionHeader.sh_name >= nameTable.Length) { throw new ModuleException("Invalid section name."); } // Build the section name. builder.Length = 0; int pos = (int)sectionHeader.sh_name; while (nameTable[pos] != 0) { builder.Append((char)nameTable[pos++]); } string sectionName = builder.ToString(); // Compare the section name. if (sectionName == ".cbm") { found = true; break; } // Skip the extra data. reader.Skip(header.e_shentsize - Elf32_Shdr.Size); } // Make sure the section was found. if (!found) { throw new ModuleException("The elf doesn't have a chela module."); } // Make sure the section type is PROGBITS. if (sectionHeader.sh_type != (int)ElfSectionType.SHT_PROGBITS) { throw new ModuleException("The elf section that can have the module is not supported."); } // Move to the section offset. reader.SetPosition(sectionHeader.sh_offset); }
public static void Compress(string source, string destination) { RPX rpx = new RPX(source); int shSize = rpx.Header.e_shnum * 0x2C; // 0x2C = rpx.Header.e_shentsize + 4 bytes of CRC32 int sectionsOffset = GetPhysicalSectionSize(shSize) + 0x40; List <KeyValuePair <int, Elf32_Shdr> > shList = new List <KeyValuePair <int, Elf32_Shdr> >(); List <KeyValuePair <int, Elf32_Shdr> > shNew = new List <KeyValuePair <int, Elf32_Shdr> >(); for (int i = 0; i < rpx.SectionHeader.Length; i++) { shList.Add(new KeyValuePair <int, Elf32_Shdr>(i, rpx.SectionHeader[i])); } shList.Sort((pair1, pair2) => Elf32_Shdr.CompareByOffset(pair1.Value, pair2.Value)); FileStream src = File.Open(source, FileMode.Open); FileStream dest = File.Open(destination, FileMode.Create); byte[] srcBytes = new byte[sectionsOffset]; src.Read(srcBytes, 0, srcBytes.Length); dest.Write(srcBytes, 0, srcBytes.Length); for (int i = 0; i < shList.Count; i++) { int key = shList[i].Key; Elf32_Shdr shdr = new Elf32_Shdr(shList[i].Value); if (shList[i].Value.sh_offset >= sectionsOffset) { int padding = 0; if ((shList[i].Value.sh_type & (uint)SHT_RPL.FILEINFO) == (uint)SHT_RPL.FILEINFO || (shList[i].Value.sh_flags & (uint)SHF_RPL.ZLIB) == (uint)SHF_RPL.ZLIB) { shdr.sh_offset = (uint)dest.Position; srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); if ((shList[i].Value.sh_type & (uint)SHT_RPL.FILEINFO) == (uint)SHT_RPL.FILEINFO) { rpx.CRC[shList[i].Key] = Security.ComputeCRC32(srcBytes, 0, srcBytes.Length); } padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } else { shdr.sh_offset = (uint)dest.Position; srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); byte[] compressBytes = Compress(srcBytes); rpx.CRC[shList[i].Key] = Security.ComputeCRC32(srcBytes, 0, srcBytes.Length); if (compressBytes.Length < srcBytes.Length) { shdr.sh_flags |= (uint)SHF_RPL.ZLIB; shdr.sh_size = (uint)compressBytes.Length; padding = GetPhysicalSectionSize(compressBytes.Length) - compressBytes.Length; dest.Write(compressBytes, 0, compressBytes.Length); } else { padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } } byte[] paddingBytes = new byte[padding]; dest.Write(paddingBytes, 0, paddingBytes.Length); } shNew.Add(new KeyValuePair <int, Elf32_Shdr>(key, shdr)); } src.Close(); dest.Position = 0x40; shNew.Sort((pair1, pair2) => pair1.Key.CompareTo(pair2.Key)); for (int i = 0; i < shNew.Count; i++) { dest.Write(shNew[i].Value.ToArray(rpx.Header.e_ident[(byte)EI.DataEncoding]), 0, 0x28); } for (int i = 0; i < rpx.CRC.Length; i++) { dest.WriteByte((byte)(rpx.CRC[i] >> 24)); dest.WriteByte((byte)((rpx.CRC[i] >> 16) & 0xFF)); dest.WriteByte((byte)((rpx.CRC[i] >> 8) & 0xFF)); dest.WriteByte((byte)(rpx.CRC[i] & 0xFF)); } dest.Close(); }
protected void Edit(string rom, string destination, byte speed, byte players, byte soundVolume, byte romType, short widthTv, short widthDrc, short heightTv, short heightDrc) { FileStream fs = File.Open(FileName, FileMode.Open); byte[] rodata = new byte[SectionHeader[RodataSectionIndex].sh_size]; fs.Position = SectionHeader[RodataSectionIndex].sh_offset; fs.Read(rodata, 0, rodata.Length); byte[] textSection = new byte[SectionHeader[TextSectionIndex].sh_size]; fs.Position = SectionHeader[TextSectionIndex].sh_offset; fs.Read(textSection, 0, textSection.Length); fs.Close(); if (rom != null) { if ((SectionHeader[RodataSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { rodata = Decompress(rodata); } rodata = GetNewRodata(CRCsSum, rodata, rom, speed, players, soundVolume, romType); CRC[RodataSectionIndex] = Cll.Security.ComputeCRC32(rodata, 0, rodata.Length); if ((SectionHeader[RodataSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { rodata = Compress(rodata); } } if ((SectionHeader[TextSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { textSection = Decompress(textSection); } int aspectRatioOffset = GetAspectRatioOffset(CRCsSum); if (aspectRatioOffset != 0) { textSection[aspectRatioOffset] = (byte)(heightTv >> 8); textSection[aspectRatioOffset + 0x01] = (byte)(heightTv & 0xFF); textSection[aspectRatioOffset + 0x04] = (byte)(widthTv >> 8); textSection[aspectRatioOffset + 0x05] = (byte)(widthTv & 0xFF); textSection[aspectRatioOffset + 0x30] = (byte)(heightDrc >> 8); textSection[aspectRatioOffset + 0x31] = (byte)(heightDrc & 0xFF); textSection[aspectRatioOffset + 0x34] = (byte)(widthDrc >> 8); textSection[aspectRatioOffset + 0x35] = (byte)(widthDrc & 0xFF); } CRC[TextSectionIndex] = Cll.Security.ComputeCRC32(textSection, 0, textSection.Length); if ((SectionHeader[TextSectionIndex].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { textSection = Compress(textSection); } int shSize = Header.e_shnum * 0x2C; // 0x2C = Header.e_shentsize + 4 bytes of CRC32 int sectionsOffset = GetPhysicalSectionSize(shSize) + 0x40; List <KeyValuePair <int, Elf32_Shdr> > shList = new List <KeyValuePair <int, Elf32_Shdr> >(); List <KeyValuePair <int, Elf32_Shdr> > shNew = new List <KeyValuePair <int, Elf32_Shdr> >(); for (int i = 0; i < SectionHeader.Length; i++) { shList.Add(new KeyValuePair <int, Elf32_Shdr>(i, SectionHeader[i])); } shList.Sort((pair1, pair2) => Elf32_Shdr.CompareByOffset(pair1.Value, pair2.Value)); FileStream src = File.Open(FileName, FileMode.Open); FileStream dest = File.Open(destination, FileMode.Create); byte[] srcBytes = new byte[sectionsOffset]; src.Read(srcBytes, 0, srcBytes.Length); dest.Write(srcBytes, 0, srcBytes.Length); for (int i = 0; i < shList.Count; i++) { int key = shList[i].Key; Elf32_Shdr shdr = new Elf32_Shdr(shList[i].Value); if (shList[i].Value.sh_offset >= sectionsOffset) { int padding = 0; shdr.sh_offset = (uint)dest.Position; if (shList[i].Value.sh_offset == SectionHeader[TextSectionIndex].sh_offset) { shdr.sh_size = (uint)textSection.Length; padding = GetPhysicalSectionSize(textSection.Length) - textSection.Length; dest.Write(textSection, 0, textSection.Length); } else if (shList[i].Value.sh_offset == SectionHeader[RodataSectionIndex].sh_offset) { shdr.sh_size = (uint)rodata.Length; padding = GetPhysicalSectionSize(rodata.Length) - rodata.Length; dest.Write(rodata, 0, rodata.Length); } else { srcBytes = new byte[shList[i].Value.sh_size]; src.Position = shList[i].Value.sh_offset; src.Read(srcBytes, 0, srcBytes.Length); padding = GetPhysicalSectionSize(srcBytes.Length) - srcBytes.Length; dest.Write(srcBytes, 0, srcBytes.Length); } byte[] paddingBytes = new byte[padding]; dest.Write(paddingBytes, 0, paddingBytes.Length); } shNew.Add(new KeyValuePair <int, Elf32_Shdr>(key, shdr)); } src.Close(); dest.Position = 0x40; shNew.Sort((pair1, pair2) => pair1.Key.CompareTo(pair2.Key)); for (int i = 0; i < shNew.Count; i++) { dest.Write(shNew[i].Value.ToArray(), 0, 0x28); } for (int i = 0; i < CRC.Length; i++) { dest.WriteByte((byte)(CRC[i] >> 24)); dest.WriteByte((byte)((CRC[i] >> 16) & 0xFF)); dest.WriteByte((byte)((CRC[i] >> 8) & 0xFF)); dest.WriteByte((byte)(CRC[i] & 0xFF)); } dest.Close(); }
public RPX(string filename) { FileStream fs = File.Open(filename, FileMode.Open); byte[] ehdrBytes = new byte[52]; fs.Read(ehdrBytes, 0, ehdrBytes.Length); fs.Close(); if (!(ehdrBytes[0] == 0x7F && ehdrBytes[1] == 'E' && ehdrBytes[2] == 'L' && ehdrBytes[3] == 'F')) { throw new FormatException("It is not an ELF file."); } if (ehdrBytes[4] != 1 || ehdrBytes[6] != 1) { throw new FormatException("It is not an ELF32 file."); } Header = new Elf32_Ehdr(ehdrBytes); if (Header.e_ident[5] != 2 || Header.e_ident[7] != 0xCA || Header.e_ident[8] != 0xFE || Header.e_type != 0xFE01) { throw new FormatException("It is not an RPL/RPX file."); } if (Header.e_shnum == 0) { throw new FormatException("This RPL/RPX file has 0 sections."); } fs = File.Open(filename, FileMode.Open); byte[] shdrBytes = new byte[Header.e_shnum * Header.e_shentsize]; fs.Position = Header.e_shoff; fs.Read(shdrBytes, 0, shdrBytes.Length); fs.Close(); SectionHeader = new Elf32_Shdr[Header.e_shnum]; int sectionCRCsIndex = 0; for (int i = 0; i < Header.e_shnum; i++) { SectionHeader[i] = new Elf32_Shdr(shdrBytes, Header.e_shentsize * i); if ((SectionHeader[i].sh_type & 0x80000003) == 0x80000003)//Section Header Type RPL CRCS { sectionCRCsIndex = i; } } if (sectionCRCsIndex == 0) { throw new FormatException("Does not contain CRCs section."); } fs = File.Open(filename, FileMode.Open); byte[] sectionStrBytes = new byte[SectionHeader[Header.e_shstrndx].sh_size]; fs.Position = SectionHeader[Header.e_shstrndx].sh_offset; fs.Read(sectionStrBytes, 0, sectionStrBytes.Length); byte[] sectionCRCsBytes = new byte[SectionHeader[sectionCRCsIndex].sh_size]; fs.Position = SectionHeader[sectionCRCsIndex].sh_offset; fs.Read(sectionCRCsBytes, 0, sectionCRCsBytes.Length); fs.Close(); if ((SectionHeader[Header.e_shstrndx].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB { sectionStrBytes = Decompress(sectionStrBytes); } foreach (byte b in sectionStrBytes) { if (b > 127) { throw new FormatException("Section Strings are not ASCII."); } } SectionName = new string[Header.e_shnum]; CRC = new uint[Header.e_shnum]; long sum = 0; for (int i = 0; i < Header.e_shnum; i++) { uint stringLength = 0; while (sectionStrBytes[SectionHeader[i].sh_name + stringLength] != 0) { stringLength++; } SectionName[i] = Encoding.ASCII.GetString(sectionStrBytes, (int)SectionHeader[i].sh_name, (int)stringLength); CRC[i] = ReadUInt32Reverse(sectionCRCsBytes, i * 4); sum += CRC[i];//Add all the CRCs if (SectionHeader[i].sh_offset != 0) { if (SectionName[i] == ".text") { TextSectionIndex = i;//Always 2 } else if (SectionName[i] == ".rodata") { RodataSectionIndex = i;//Always 3 } } } sum -= (long)CRC[TextSectionIndex] + CRC[RodataSectionIndex] + CRC[CRC.Length - 1]; //Subtract ".text" CRC, ".rodata" CRC and "RPL Info" CRC CRCsSum = (uint)(sum >> 4); //Discard the least significant 4 bits FileName = filename; }
public static int CompareByOffset(Elf32_Shdr sh1, Elf32_Shdr sh2) { return(sh1.sh_offset.CompareTo(sh2.sh_offset)); }
byte[] LoadSection(Elf32_Shdr sectionHeader) { return(LoadSection((int)sectionHeader.sh_offset, (int)sectionHeader.sh_size)); }
private static void GetEmbeddedModule32(ModuleReader reader, byte[] ident) { // Read the endiannes. bool big = ident[(int)ElfIdent.EI_DATA] == (int)ElfData.ELFDATA2MSB; // Read the header. Elf32_Ehdr header = new Elf32_Ehdr(); header.Read(reader, big); // Reject files without section names. if(header.e_shstrndex == (int)ElfSectionNumber.SHN_UNDEF) throw new ModuleException("Unsupported elfs without section names"); // Read the "section names" section. reader.SetPosition((uint) (header.e_shoff + header.e_shstrndex*header.e_shentsize)); Elf32_Shdr namesHeader = new Elf32_Shdr(); namesHeader.Read(reader, big); // Reject files without real section names. if(namesHeader.sh_size == 0) throw new ModuleException("This elf doesn't have section names."); // Read the name table. byte[] nameTable; reader.SetPosition(namesHeader.sh_offset); reader.Read(out nameTable, (int)namesHeader.sh_size); // Move to the section header table. reader.SetPosition(header.e_shoff); // Read the section until hit '.cbm'. Elf32_Shdr sectionHeader = new Elf32_Shdr(); bool found = false; StringBuilder builder = new StringBuilder(); for(int i = 0; i < header.e_shnum; ++i) { // Read the section header. sectionHeader.Read(reader, big); // Check the section name. if(sectionHeader.sh_name >= nameTable.Length) throw new ModuleException("Invalid section name."); // Build the section name. builder.Length = 0; int pos = (int)sectionHeader.sh_name; while(nameTable[pos] != 0) builder.Append((char)nameTable[pos++]); string sectionName = builder.ToString(); // Compare the section name. if(sectionName == ".cbm") { found = true; break; } // Skip the extra data. reader.Skip(header.e_shentsize - Elf32_Shdr.Size); } // Make sure the section was found. if(!found) throw new ModuleException("The elf doesn't have a chela module."); // Make sure the section type is PROGBITS. if(sectionHeader.sh_type != (int)ElfSectionType.SHT_PROGBITS) throw new ModuleException("The elf section that can have the module is not supported."); // Move to the section offset. reader.SetPosition(sectionHeader.sh_offset); }