示例#1
0
        public APK(Stream stream)
        {
            using (BinaryReader reader = new BinaryReader(stream)) {
                SectionSet sections = SectionIO.ReadAll(reader);

                // TODO: Figure out what hash is calculated from and validate hash.
                PACKHEDR hedr      = sections.Get <PACKHEDR>();
                GENESTRT nameTable = sections.Get <GENESTRT>();
                this.Name = nameTable.Strings[(int)hedr.NameIndex];

                PACKTOC toc = sections.Get <PACKTOC>();
                this.RootDirectory = this.BuildContentTree(stream, nameTable, toc, (PACKTOC.DirectoryEntry)toc.Entries[0]);

                PACKFSLS fileSetList = sections.Get <PACKFSLS>();
                foreach (PACKFSLS.FileSetEntry entry in fileSetList.FileSets)
                {
                    stream.Seek((long)entry.Offset, SeekOrigin.Begin);
                    byte[] fileSetData = reader.ReadBytes((int)entry.Size);
                    string fileSetName = nameTable.Strings[(int)entry.NameIndex];

                    if (!Enumerable.SequenceEqual(new MD5CryptoServiceProvider().ComputeHash(fileSetData), entry.Hash))
                    {
                        throw new Exception("Hash mismatch in file set \"" + fileSetName + "\".");
                    }

                    using (MemoryStream fileSetStream = new MemoryStream(fileSetData)) {
                        this.FileSets.Add(this.ReadFileSet(fileSetStream, fileSetName));
                    }
                }
            }
        }
示例#2
0
        public IDX(params string[] apkFiles)
        {
            this.sections = new SectionSet();
            this.sections.Add(new ENDILTLE());

            List <SectionSet> apks = new List <SectionSet>();

            foreach (string apkFile in apkFiles)
            {
                using (FileStream stream = File.OpenRead(apkFile)) {
                    apks.Add(SectionIO.ReadAll(stream));
                }
            }

            PACKTOC  combinedToc  = new PACKTOC();
            PACKFSLS combinedFsls = new PACKFSLS();
            GENESTRT combinedStrt = new GENESTRT();

            foreach (SectionSet set in apks)
            {
                PACKHEDR hedr = set.Get <PACKHEDR>();
                GENESTRT strt = set.Get <GENESTRT>();

                hedr.NameIndex = combinedStrt.AddString(strt.Strings[(int)hedr.NameIndex]);
                this.sections.Add(hedr);
            }

            uint packageIndex = 0;

            foreach (SectionSet set in apks)
            {
                PACKTOC  toc  = set.Get <PACKTOC>();
                PACKFSLS fsls = set.Get <PACKFSLS>();
                GENESTRT strt = set.Get <GENESTRT>();

                foreach (PACKTOC.Entry entry in toc.Entries)
                {
                    entry.NameIndex    = combinedStrt.AddString(strt.Strings[(int)entry.NameIndex]);
                    entry.PackageIndex = packageIndex;

                    combinedToc.Entries.Add(entry);
                }

                foreach (PACKFSLS.FileSetEntry entry in fsls.FileSets)
                {
                    entry.NameIndex    = combinedStrt.AddString(strt.Strings[(int)entry.NameIndex]);
                    entry.PackageIndex = packageIndex;

                    combinedFsls.FileSets.Add(entry);
                }

                packageIndex++;
            }

            this.sections.Add(combinedToc);
            this.sections.Add(combinedFsls);
            this.sections.Add(combinedStrt);
            this.sections.Add(new GENEEOF());
        }
示例#3
0
        public void Write(Stream stream)
        {
            GENESTRT nameTable = new GENESTRT();

            nameTable.Strings.Add(this.Name);

            PACKHEDR packhedr = new PACKHEDR();

            packhedr.Unknown1   = 0x10000;
            packhedr.NameIndex  = 0;
            packhedr.DataOffset = 0;            // Filled in later.
            packhedr.Unknown3   = 1;
            packhedr.Hash       = new byte[16]; // TODO

            PACKTOC toc = new PACKTOC();

            byte[] fileData;
            using (MemoryStream fileStream = new MemoryStream()) {
                this.WriteFiles(fileStream, toc, nameTable);
                fileData = fileStream.ToArray();
            }

            PACKFSLS      fsls         = new PACKFSLS();
            List <byte[]> fileSetDatas = new List <byte[]>();
            uint          nameIndex    = (uint)nameTable.Strings.Count;

            foreach (FileSet fileSet in this.FileSets)
            {
                byte[] fileSetData;
                using (MemoryStream fileSetStream = new MemoryStream()) {
                    this.WriteFileSet(fileSetStream, fileSet);
                    fileSetData = fileSetStream.ToArray();
                }

                PACKFSLS.FileSetEntry entry = new PACKFSLS.FileSetEntry();
                entry.NameIndex    = nameTable.AddString(fileSet.Name);
                entry.PackageIndex = 0;
                entry.Offset       = 0; // Filled in later.
                entry.Size         = (ulong)fileSetData.Length;
                entry.Hash         = new MD5CryptoServiceProvider().ComputeHash(fileSetData);

                fsls.FileSets.Add(entry);
                fileSetDatas.Add(fileSetData);
            }

            SectionSet set = new SectionSet();

            set.Add(new ENDILTLE());
            set.Add(packhedr);
            set.Add(toc);
            set.Add(fsls);
            set.Add(nameTable);
            set.Add(new GENEEOF());

            ulong headersSize;

            using (MemoryStream sizeTestStream = new MemoryStream()) {
                SectionIO.WriteAll(sizeTestStream, set);
                headersSize = (ulong)sizeTestStream.Length;
            }

            ulong currOffset = NumberUtil.Align(headersSize, 0x800);

            packhedr.DataOffset = (uint)currOffset;
            foreach (PACKTOC.Entry entry in toc.Entries)
            {
                if (entry is PACKTOC.UncompressedFileEntry uFileEntry)
                {
                    uFileEntry.Offset = currOffset;
                    currOffset        = NumberUtil.Align(currOffset + uFileEntry.Size, 0x200);
                }
                else if (entry is PACKTOC.CompressedFileEntry cFileEntry)
                {
                    cFileEntry.Offset = currOffset;
                    currOffset        = NumberUtil.Align(currOffset + cFileEntry.CompressedSize, 0x200);
                }
            }

            currOffset = NumberUtil.Align(currOffset, 0x800);
            foreach (PACKFSLS.FileSetEntry fileSetEntry in fsls.FileSets)
            {
                fileSetEntry.Offset = currOffset;
                currOffset          = NumberUtil.Align(currOffset + fileSetEntry.Size, 0x800);
            }

            SectionIO.WriteAll(stream, set);
            stream.PadTo(0x800);

            stream.Write(fileData);

            foreach (byte[] fileSetData in fileSetDatas)
            {
                stream.PadTo(0x800);
                stream.Write(fileSetData);
            }
        }
        private static int Main(string[] args)
        {
            OpenFileDialog fd = new OpenFileDialog();

            fd.Filter = "AKB 1/48 Guam apk files|*.apk";

            if (fd.ShowDialog() == DialogResult.OK)
            {
                FolderBrowserDialog fbd = new FolderBrowserDialog();
                fbd.SelectedPath = "C:\\";
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    FileStream filestream   = new FileStream("out.txt", FileMode.Create);
                    var        streamwriter = new StreamWriter(filestream);
                    streamwriter.AutoFlush = true;
                    Console.SetOut(streamwriter);
                    Console.SetError(streamwriter);
                    using (EndianBinaryReader reader = new EndianBinaryReader(EndianBitConverter.Little, File.Open(fd.FileName, FileMode.Open)))
                    {
                        reader.ReadBytes(16);
                        if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKHEDR")
                        {
                            return(-1);
                        }
                        PACKHEDR pkhdr = new PACKHEDR();
                        pkhdr.headerSize  = reader.ReadInt64();
                        pkhdr.dummy       = reader.ReadInt32();
                        pkhdr.zero        = reader.ReadInt32();
                        pkhdr.dummySize   = reader.ReadInt32();
                        pkhdr.dummy2      = reader.ReadInt32();
                        pkhdr.dummystring = Encoding.ASCII.GetString(reader.ReadBytes(16));
                        if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKTOC ")
                        {
                            return(-1);
                        }
                        PACKTOC pktoc = new PACKTOC();
                        pktoc.size      = reader.ReadInt64();
                        pktoc.offset    = reader.BaseStream.Position;
                        pktoc.entrySize = reader.ReadInt32();
                        pktoc.files     = reader.ReadInt32();
                        pktoc.folders   = reader.ReadInt32();
                        pktoc.zero      = reader.ReadInt32();
                        GENESTRT gene1 = GetGENESTRT(reader, pktoc.offset, pktoc.size);
                        //FOLDERS fldrs = new FOLDERS(pktoc.folders);
                        for (int k = 0; k < pktoc.folders; k++)
                        {
                            /*
                             * fldrs.dummystring.Add(reader.ReadBytes(pktoc.entrySize));
                             * fldrs.nameIdx.Add(fldrs.dummystring[k].ElementAt(4));
                             * fldrs.fileNum.Add(fldrs.dummystring[k].ElementAt(16));
                             * fldrs.subFiles.Add(fldrs.dummystring[k].ElementAt(20));
                             * fldrs.foldernames[k] = gene1.stringlist[fldrs.nameIdx[k]];
                             */
                            reader.ReadBytes(pktoc.entrySize);
                        }
                        for (int l = pktoc.folders; l < pktoc.files; l++)
                        {
                            long tocpos = reader.BaseStream.Position;
                            reader.ReadInt32(); //always 0x200 (512)
                            int idx = reader.ReadInt32();
                            reader.ReadInt32(); //always 0
                            reader.ReadInt32(); //always 0
                            long offset = reader.ReadInt64();
                            long size   = reader.ReadInt64();
                            long zsize  = reader.ReadInt64();
                            Console.WriteLine("TOC offset: {4}  file: {0}  offset: {1}  size: {2}  zsize: {3}", gene1.stringlist[idx], offset, size, zsize, tocpos);
                            if (size != 0)
                            {
                                string fname = gene1.stringlist[idx];
                                if (zsize == 0)
                                {
                                    long tmpstreampos = reader.BaseStream.Position;
                                    reader.BaseStream.Position = offset;
                                    //Console.WriteLine("File: {0} is not compressed. Writing to {1}", fname, fbd.SelectedPath + "\\" + fname);
                                    using (FileStream nfstrm = new FileStream(fbd.SelectedPath + "\\" + fname, FileMode.Create))
                                    {
                                        nfstrm.Write(reader.ReadBytes((int)size), 0, (int)size);
                                        reader.BaseStream.Position = tmpstreampos;
                                    }
                                }
                                else
                                {
                                    long tempstrmpos = reader.BaseStream.Position;
                                    reader.BaseStream.Position = offset + 2;
                                    //Console.WriteLine("File: {0} is compressed. Writing to {1}", fname, fbd.SelectedPath + "\\" + fname);
                                    MemoryStream tmpmemstrm = new MemoryStream(reader.ReadBytes((int)zsize));
                                    using (FileStream cpfs = new FileStream(fbd.SelectedPath + "\\" + fname, FileMode.Create))
                                    {
                                        using (DeflateStream dfstrm = new DeflateStream(tmpmemstrm, CompressionMode.Decompress))
                                        {
                                            dfstrm.CopyTo(cpfs);
                                        }
                                    }
                                    reader.BaseStream.Position = tempstrmpos;
                                }
                            }
                        }
                        reader.BaseStream.Position = pktoc.offset + pktoc.size;
                        if (Encoding.ASCII.GetString(reader.ReadBytes(8)) != "PACKFSLS")
                        {
                            return(-1);
                        }
                        PACKFSLS pkfls = new PACKFSLS();
                        pkfls.headerSize   = reader.ReadInt64();
                        pkfls.headerOffset = reader.BaseStream.Position;
                        pkfls.archives     = reader.ReadInt32();
                        pkfls.dummy        = reader.ReadInt32();
                        pkfls.dummy2       = reader.ReadInt32();
                        pkfls.zero         = reader.ReadInt32();
                        for (int archive = 0; archive < pkfls.archives; archive++)
                        {
                            int tmpidx = reader.ReadInt32();
                            reader.ReadInt32();
                            long archiveoffset = reader.ReadInt64();
                            long archivesize   = reader.ReadInt64();
                            reader.ReadBytes(16);
                            string aname  = gene1.stringlist[tmpidx];
                            long   tmppos = reader.BaseStream.Position;
                            extractArchives(reader, archiveoffset, aname, fbd.SelectedPath);
                            reader.BaseStream.Position = tmppos;
                        }
                    }
                    filestream.Close();
                }
            }
            return(1);
        }