Example #1
0
        public byte[] FileRead(BbInode inode)
        {
            var data  = new byte[inode.Size];
            var chain = GetBlockChain(inode.BlockIdx);

            for (int i = 0; i < chain.Length; i++)
            {
                io.Stream.Position = chain[i] * BLOCK_SZ;

                int numRead = BLOCK_SZ;
                if (i + 1 == chain.Length)
                {
                    numRead = (int)(inode.Size % BLOCK_SZ);
                }
                if (numRead == 0)
                {
                    numRead = BLOCK_SZ;
                }

                var blockData = io.Reader.ReadBytes(numRead);
                Array.Copy(blockData, 0, data, i * BLOCK_SZ, numRead);
            }

            return(data);
        }
Example #2
0
        public void CreateModifiedInodes()
        {
            if (ModifiedInodes != null)
            {
                return;
            }

            ModifiedInodes = new List <BbInode>();
            foreach (var node in MainFsInodes)
            {
                var newNode = new BbInode();
                ModifiedInodes.Add(newNode.Copy(node));
            }

            ModifiedAllocTable = new List <short>();
            foreach (var alloc in MainFsAllocTable)
            {
                ModifiedAllocTable.Add(alloc);
            }

            var newSeqNo = MainFs.SeqNo + 1;

            MainFs          = new BbFat16();
            MainFs.Magic    = MAGIC_BBFS;
            MainFs.SeqNo    = newSeqNo;
            MainFs.Link     = 0;
            MainFs.CheckSum = 0;

            FsHeaders.Add(MainFs);
            FsInodes.Add(ModifiedInodes);
            FsAllocationTables.Add(ModifiedAllocTable);

            MainFsIndex = FsHeaders.Count - 1;
        }
Example #3
0
        public bool FileDelete(string fileName)
        {
            BbInode foundNode = new BbInode();
            bool    found     = false;

            foreach (var node in MainFsInodes)
            {
                if (node.NameString == fileName)
                {
                    foundNode = node;
                    found     = true;
                }
            }

            if (!found)
            {
                return(false);
            }

            // make sure we have a modified inodes collection ready...
            CreateModifiedInodes();

            // find node in modified inodes..
            found = false;
            foreach (var node in ModifiedInodes)
            {
                if (node.NameString == fileName)
                {
                    foundNode = node;
                    found     = true;
                }
            }
            if (!found)
            {
                return(false);
            }

            // deallocate all blocks used by the file
            var chain = GetBlockChain(foundNode.BlockIdx);

            foreach (var block in chain)
            {
                ModifiedAllocTable[block] = FAT_BLOCK_FREE;
            }

            // remove file from inode collection
            ModifiedInodes.Remove(foundNode);

            return(true);
        }
Example #4
0
        public bool FileWrite(string fileName, byte[] fileData, ref BbInode newNode)
        {
            newNode            = new BbInode();
            newNode.NameString = fileName;
            newNode.Type       = 1;
            newNode.Size       = (uint)fileData.Length;

            // remove any existing file with this name
            FileDelete(newNode.NameString);

            // make sure we have a modified inodes collection ready...
            CreateModifiedInodes();

            int numBlocks = (fileData.Length + (BLOCK_SZ - 1)) / BLOCK_SZ;
            var blockList = TryAllocateBlocks(numBlocks);

            if (blockList == null)
            {
                return(false); // couldn't find enough unused blocks :(
            }
            // start writing the file data!
            for (int i = 0; i < numBlocks; i++)
            {
                int dataOffset = i * BLOCK_SZ;
                int numWrite   = BLOCK_SZ;
                if (dataOffset + numWrite > fileData.Length)
                {
                    numWrite = fileData.Length % BLOCK_SZ;
                }

                SeekToBlock(blockList[i]);
                io.Stream.Write(fileData, dataOffset, numWrite);
            }
            newNode.BlockIdx = blockList[0];

            // add new inode to inode list...
            // make seperate inode to provided one, to make sure nothing can change after adding it to inode list

            var realNewNode = new BbInode();

            realNewNode.Copy(newNode);
            ModifiedInodes.Add(realNewNode);

            var chain = GetBlockChain(newNode.BlockIdx);

            // success!
            return(true);
        }
Example #5
0
        static void ModeNAND()
        {
            Console.WriteLine($"Opening NAND image from {filePath}...");
            Console.WriteLine();

            if (!string.IsNullOrEmpty(outputFile) && !string.IsNullOrEmpty(updateKernelPath))
            {
                // we're updating kernel with output file specified, so copy the input file to specified output file and work with that instead
                if (File.Exists(outputFile))
                {
                    File.Delete(outputFile);
                }

                File.Copy(filePath, outputFile);
                filePath = outputFile;
            }

            var nandFile = new iQueNand(filePath)
            {
                SkipVerifyFsChecksums = skipVerifyChecksums || fixFsChecksums,
                InodesOffset          = isBadDump ? 0x10 : 0
            };

            if (!nandFile.Read())
            {
                Console.WriteLine($"[!] Failed to read NAND image!");
                return;
            }

            if (!string.IsNullOrEmpty(addFiles) || !string.IsNullOrEmpty(addFilesList))
            {
                var filesToAdd = new List <string>();
                if (!string.IsNullOrEmpty(addFiles))
                {
                    var files = addFiles.Split(',');
                    filesToAdd.AddRange(files);
                }

                if (!string.IsNullOrEmpty(addFilesList))
                {
                    if (File.Exists(addFilesList))
                    {
                        var files = File.ReadAllLines(addFilesList);
                        filesToAdd.AddRange(files);
                    }
                    else
                    {
                        Console.WriteLine($"[!] -al (addlist) failed, list {addFilesList} doesn't exist!");
                    }
                }

                if (filesToAdd.Count > 0)
                {
                    int successful = 0;
                    foreach (var file in filesToAdd)
                    {
                        if (File.Exists(file))
                        {
                            Console.WriteLine($"Adding file to NAND: {file}");
                            BbInode node = new BbInode();
                            if (nandFile.FileWrite(Path.GetFileName(file), File.ReadAllBytes(file), ref node))
                            {
                                Console.WriteLine($"File added successfully! name: {node.NameString}, block: {node.BlockIdx}");
                                successful++;
                            }
                            else
                            {
                                Console.WriteLine($"[!] Failed to add file, likely not enough free space in nand!");
                            }
                        }
                        else
                        {
                            Console.WriteLine($"[!] Failed to add non-existing file:{Environment.NewLine}\t{file}");
                        }
                    }
                    if (successful > 0)
                    {
                        Console.WriteLine("Writing updated FS to NAND...");
                        if (nandFile.WriteFilesystem())
                        {
                            Console.WriteLine($"Added {successful} files successfully!");
                        }
                        else
                        {
                            Console.WriteLine("[!] Failed to write updated FS, couldn't find FS block to write?");
                        }
                    }
                }
                else
                {
                    Console.WriteLine("[!] -al (addlist) failed, no files to add!");
                }
            }

            if (!string.IsNullOrEmpty(deleteFiles))
            {
                var filesToDelete = deleteFiles.Split(',');
                int successful    = 0;
                foreach (var file in filesToDelete)
                {
                    // lazy way to get proper 8.3 name for this file..
                    BbInode inode = new BbInode();
                    inode.NameString = Path.GetFileName(file);

                    if (nandFile.FileDelete(inode.NameString))
                    {
                        Console.WriteLine($"File {inode.NameString} removed from NAND!");
                        successful++;
                    }
                    else
                    {
                        Console.WriteLine($"Failed to remove file {inode.NameString} from NAND...");
                    }
                }

                if (successful > 0)
                {
                    Console.WriteLine("Writing updated FS to NAND...");
                    if (nandFile.WriteFilesystem())
                    {
                        Console.WriteLine($"Removed {successful} files successfully!");
                    }
                    else
                    {
                        Console.WriteLine("[!] Failed to write updated FS, couldn't find FS block to write?");
                    }
                }
            }

            if (fixFsChecksums)
            {
                nandFile.RepairFsChecksums();
            }

            if (printInfo)
            {
                Console.WriteLine(nandFile.ToString(true, true, showAllFsInfo));
            }

            if (writeInfo)
            {
                File.WriteAllText(filePath + ".txt", nandFile.ToString(true, false, showAllFsInfo));
                Console.WriteLine($"Wrote detailed NAND info to {filePath}.txt");
            }

            if (!string.IsNullOrEmpty(updateKernelPath))
            {
                Console.WriteLine($"Updating NAND SKSA to {updateKernelPath}");
                nandFile.SetSKSAData(updateKernelPath);
            }
            else
            {
                // extract / extractkernel can only be used if we aren't updating kernel in the same session
                if (extractAll)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + "_ext";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }

                    if (!Directory.Exists(outputFile))
                    {
                        Directory.CreateDirectory(outputFile);
                    }

                    int count = 0;
                    foreach (var file in nandFile.MainFsInodes)
                    {
                        if (!file.IsValid)
                        {
                            continue;
                        }

                        var extPath = Path.Combine(outputFile, file.NameString);
                        Console.WriteLine($"Writing file to {extPath}");
                        File.WriteAllBytes(extPath, nandFile.FileRead(file));
                        count++;
                    }

                    Console.WriteLine($"Extracted {count} files to {outputFile}");
                }

                if (extractKernel)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + ".sksa.bin";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }
                    if (extractAll) // if we just extracted the fs files we'll extract SKSA into the same folder
                    {
                        outputFile = Path.Combine(outputFile, "sksa.bin");
                    }

                    File.WriteAllBytes(outputFile, nandFile.GetSKSAData());

                    Console.WriteLine($"Extracted SKSA to {outputFile}");
                }
            }

            if (!string.IsNullOrEmpty(generateSparePath))
            {
                File.WriteAllBytes(generateSparePath, nandFile.GenerateSpareData(!generateFullSpare));
                Console.WriteLine($"Wrote generated {(generateFullSpare ? "page" : "block")}-spare data to {generateSparePath}");
            }
        }
Example #6
0
        public bool FileDelete(BbInode node)
        {
            var name = node.NameString;

            return(FileDelete(name));
        }