Beispiel #1
0
        private static string getmacaddress()
        {
            if (!File.Exists(variables.filename1))
            {
                return("nomac");
            }
            byte[] smc_config;
            bool   big_block = false;
            bool   corona    = false;
            int    block_offset;

            smc_config = Nand.Nand.getsmcconfig(variables.filename1, ref big_block, ref corona);
            if (big_block)
            {
                if (corona)
                {
                    block_offset = 0;
                }
                else
                {
                    block_offset = 0x60000;
                }
            }
            else
            {
                block_offset = 0xC000;
            }
            string mac = Regex.Replace(Oper.ByteArrayToString(Oper.returnportion(smc_config, 0x220 + block_offset, 5)), @"(.{2})(.{2})(.{2})(.{2})(.{2})", @"$1-$2-$3-$4-$5");

            return(mac);
        }
Beispiel #2
0
        private byte[] xor_hack(byte[] CB_B, byte[] CB_B_plain, byte[] CB_B_patched)
        {
            int headerlen = 0x40;
            int offset    = headerlen;

            int keystream, patched;

            Console.WriteLine(" *** Re-encrypting CB_B with xor keystream");
            int j = 0;

            for (j = 0; j < (CB_B_patched.Length - headerlen) / 4; j++)
            {
                byte[] plain = Oper.returnportion(ref CB_B_plain, offset, 4);
                byte[] patch = Oper.returnportion(ref CB_B_patched, offset, 4);

                for (int i = 0; i < 4; i++)
                {
                    keystream        = plain[i] ^ (CB_B[i + offset]);
                    patched          = (keystream ^ (patch[i]));
                    CB_B[offset + i] = (byte)patched;
                }

                offset += 4;
            }
            Console.WriteLine(" *** Fixing entrypoint");
            CB_B = Oper.concatByteArrays(CB_B_patched, Oper.returnportion(ref CB_B, 0xC, CB_B.Length - 0xC), 0xC, CB_B.Length - 0xC);
            return(CB_B);
        }
Beispiel #3
0
        /// <summary>
        /// patch, encrypt, decrypt SMC
        /// </summary>
        /// <param name="SMC"></param>
        /// <returns></returns>
        #region SMC

        private byte[] patch_SMC_old(byte[] SMC)
        {
            bool  found = false;
            crc32 crc   = new crc32(); // equivalent to new CRC32(CRC32.DefaultPolynomial);

            byte[] newsmc = Oper.returnportion(ref SMC, 4, SMC.Length - 4);

            long hashData = crc.CRC(newsmc);

            Console.WriteLine("CRC32: {0}", hashData.ToString("X"));

            uint[]   SMC_patches_crc     = { 0x87E726B7, 0xf9c96639, 0x5b3aed00, 0x9ad5b7ee, 0x7e5bc217, 0x1d0c613e };
            string[] SMC_patches_version = { "Trinity, version 3.1", "Trinity, version 3.1", "Jasper, version 2.3", "Zephyr, version 1.10", "Zephyr, version 1.13", "Falcon, version 1.6" };
            int[]    SMC_patches_patch   = { 0x13b3, 0x13b3, 0x12ba, 0x1257, 0x12a3, 0x12a3 };
            byte[]   patched_SMC         = new byte[SMC.Length];
            for (int i = 0; i < SMC_patches_crc.Length; i++)
            {
                if (hashData == SMC_patches_crc[i])
                {
                    Console.WriteLine("patchset \"{0}\" matches, 1 patch(es)", SMC_patches_version[i]); //attention
                    found = true;

                    byte[] SMC_A = Oper.returnportion(ref SMC, 0, SMC_patches_patch[i]);
                    byte[] SMC_B = Oper.returnportion(ref SMC, SMC_patches_patch[i] + 2, SMC.Length - SMC_patches_patch[i] - 2);
                    for (int j = 0; j < SMC.Length; j++)
                    {
                        if (j == SMC_patches_patch[i] || j == SMC_patches_patch[i] + 1)
                        {
                            patched_SMC[j] = 0x00;
                        }
                        else if (j < SMC_patches_patch[i])
                        {
                            patched_SMC[j] = SMC_A[j];
                        }
                        else
                        {
                            patched_SMC[j] = SMC_B[j - SMC_patches_patch[i] - 2];
                        }
                    }
                }
            }
            if (!found)
            {
                Console.WriteLine(" ! Warning: can't patch that SMC, here are the current supported versions:");
                for (int i = 0; i < SMC_patches_version.Length; i++)
                {
                    Console.WriteLine("  - {0}", SMC_patches_version[i]);
                }
            }
            return(patched_SMC);
        }
Beispiel #4
0
        string getmacaddress()
        {
            if (!File.Exists(variables.filename1))
            {
                return("nomac");
            }
            byte[] smc_config;
            int    block_offset;

            smc_config = Nand.Nand.getsmcconfig(variables.filename1, out block_offset);
            string mac = Regex.Replace(Oper.ByteArrayToString(Oper.returnportion(smc_config, 0x220 + block_offset, 6)), @"(.{2})(.{2})(.{2})(.{2})(.{2})(.{2})", @"$1-$2-$3-$4-$5-$6");

            return(mac);
        }
Beispiel #5
0
 private void parsehex()
 {
     try
     {
         byte[] file = File.ReadAllBytes(variables.filename1);
         if (file[0] != 0x3A)
         {
             Console.WriteLine("Bad file"); return;
         }
         byte[] length  = new byte[2];
         byte[] address = new byte[4];
         byte[] record  = new byte[2];
         byte[] line, write;
         int    i = 0, len = 0, add = 0, rec = 0;
         while (!variables.escapeloop)
         {
             length  = Oper.returnportion(file, i + 1, 2);
             address = Oper.returnportion(file, i + 3, 4);
             record  = Oper.returnportion(file, i + 7, 2);
             len     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(length)), 16);
             rec     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(record)), 16);
             add     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(address)), 16);
             line    = Oper.returnportion(file, i + 9, len * 2);
             write   = Oper.StringToByteArray(ASCIIEncoding.ASCII.GetString(line));
             Console.WriteLine("len: 0x{0:X}", len);
             Console.WriteLine("rec: 0x{0:X}", rec);
             Console.WriteLine("add: 0x{0:X}", add);
             //Console.WriteLine(ByteArrayToString(write));
             Console.WriteLine("");
             if ((add >= 0x800) && (add < 0x6000) && (rec == 0))
             {
                 Console.WriteLine(Oper.ByteArrayToString(write));
                 Console.WriteLine("");
             }
             if (rec == 0x01)
             {
                 break;
             }
             i = i + 2 + 4 + 2 + len + len + 2 + 2 + 1;
             if (file[i] != 0x3A)
             {
                 break;
             }
         }
         Console.WriteLine("Done");
     }
     catch (Exception ex) { Console.WriteLine(ex.ToString()); }
     variables.escapeloop = false;
 }
Beispiel #6
0
 private static bool verify(ref ProgressBar pb)
 {
     try
     {
         string   filename = variables.filename1;
         FileInfo fl       = new FileInfo(filename);
         int      filesize = (int)fl.Length;
         byte[]   file     = File.ReadAllBytes(filename);
         if (file[0] != 0x3A)
         {
             Console.WriteLine("Bad file"); return(false);
         }
         byte[] length  = new byte[2];
         byte[] address = new byte[4];
         byte[] record  = new byte[2];
         byte[] line, write, offset;
         int    i = 0, len = 0, add = 0, rec = 0;
         while (!variables.escapeloop)
         {
             length  = Oper.returnportion(file, i + 1, 2);
             address = Oper.returnportion(file, i + 3, 4);
             record  = Oper.returnportion(file, i + 7, 2);
             len     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(length)), 16);
             rec     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(record)), 16);
             add     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(address)), 16);
             offset  = Oper.StringToByteArray(ASCIIEncoding.ASCII.GetString(address));
             Array.Reverse(offset);
             line  = Oper.returnportion(file, i + 9, len * 2);
             write = Oper.StringToByteArray(ASCIIEncoding.ASCII.GetString(line));
             if ((add >= 0x800) && (add < 0x6000) && (rec == 0))
             {
                 byte[] send = new byte[0x3F];
                 send[1] = 0x5;
                 send[6] = 0x10;
                 Buffer.BlockCopy(offset, 0, send, 3, 2);
                 pb.Value = ((i * pb.Maximum) / filesize);
                 re       = new HidReport(0x3F, new HidDeviceData(send, HidDeviceData.ReadStatus.Success));
                 byte[] returnb = null;
                 if (!_selectedDevice.WriteReport(re, 5000))
                 {
                     Console.Write("X");
                 }
                 else
                 {
                     re      = _selectedDevice.ReadReport(5000);
                     returnb = re.Data;
                 }
                 if (!Oper.ByteArrayCompare(Oper.returnportion(returnb, 6, write.Length), write))
                 {
                     //if (comboBox1.Text == "2") Console.WriteLine("Data: {0:X}", ByteArrayToString(datab));
                     if (variables.debugme)
                     {
                         Console.WriteLine("Return: {0:X}", Oper.ByteArrayToString(returnb));
                     }
                     if (variables.debugme)
                     {
                         Console.WriteLine("Data: {0:X}", Oper.ByteArrayToString(Oper.returnportion(returnb, 6, 0x10)));
                     }
                     if (variables.debugme)
                     {
                         Console.WriteLine("File: {0:X}", Oper.ByteArrayToString(write));
                     }
                     Console.Write("x");
                 }
                 else if (i % 8 == 0)
                 {
                     Console.Write(".");
                 }
                 Thread.Sleep(0x5);
             }
             if (rec == 0x01)
             {
                 break;
             }
             i = i + 2 + 4 + 2 + len + len + 2 + 2 + 1;
             if (file[i] != 0x3A)
             {
                 break;
             }
         }
         variables.escapeloop = false;
         return(true);
     }
     catch (Exception ex) { Console.WriteLine(ex.ToString()); return(false); }
 }
Beispiel #7
0
        private static bool write(ref ProgressBar pb)
        {
            try
            {
                string   filename = variables.filename1;
                FileInfo fl       = new FileInfo(filename);
                bool     rty      = false;
                int      reTRY    = 0;
                int      filesize = (int)fl.Length;
                byte[]   file     = File.ReadAllBytes(filename);
                if (file[0] != 0x3A)
                {
                    Console.WriteLine("Bad file"); return(false);
                }
                byte[] length  = new byte[2];
                byte[] address = new byte[4];
                byte[] record  = new byte[2];
                byte[] line, write, offset;
                int    i = 0, len = 0, add = 0, rec = 0;
                while (!variables.escapeloop)
                {
                    length  = Oper.returnportion(file, i + 1, 2);
                    address = Oper.returnportion(file, i + 3, 4);
                    record  = Oper.returnportion(file, i + 7, 2);
                    len     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(length)), 16);
                    rec     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(record)), 16);
                    add     = Convert.ToInt32((ASCIIEncoding.ASCII.GetString(address)), 16);
                    offset  = Oper.StringToByteArray(ASCIIEncoding.ASCII.GetString(address));
                    Array.Reverse(offset);
                    line  = Oper.returnportion(file, i + 9, len * 2);
                    write = Oper.StringToByteArray(ASCIIEncoding.ASCII.GetString(line));
                    if ((add >= 0x800) && (add < 0x6000) && (rec == 0))
                    {
                        byte[] send = new byte[0x3F];
                        send[1] = 0x1;
                        send[6] = 0x10;
                        Buffer.BlockCopy(offset, 0, send, 3, 2);
                        Buffer.BlockCopy(write, 0, send, 0x7, write.Length);
                        pb.Value = ((i * pb.Maximum) / filesize);
                        re       = new HidReport(0x3F, new HidDeviceData(send, HidDeviceData.ReadStatus.Success));
                        if (!_selectedDevice.WriteReport(re, 5000))
                        {
                            Console.Write("x");
                            reTRY++;
                            if (variables.debugme)
                            {
                                Console.WriteLine(" Retry: " + reTRY);
                            }

                            if (variables.debugme)
                            {
                                Console.WriteLine(" Command: {0:X}", Oper.ByteArrayToString(send));
                            }
                            if (variables.debugme)
                            {
                                Console.WriteLine(" Data: {0:X}", Oper.ByteArrayToString(write));
                            }
                            if (variables.debugme)
                            {
                                Console.WriteLine(" Offset: {0:X}", Oper.ByteArrayToString(offset));
                            }

                            rty = true;
                        }
                        else if (i % 8 == 0)
                        {
                            Console.Write(".");
                            rty   = false;
                            reTRY = 0;
                            //i = i + 2 + 4 + 2 + len + len + 2 + 2 + 1;
                        }
                        Thread.Sleep(0x7);
                    }
                    if (rec == 0x01)
                    {
                        break;
                    }
                    if (!rty)
                    {
                        i = i + 2 + 4 + 2 + len + len + 2 + 2 + 1;
                    }
                    if (reTRY >= 0x0A)
                    {
                        return(false);
                    }
                    if (file[i] != 0x3A)
                    {
                        break;
                    }
                }
                return(true);
            }
            catch (Exception ex) { Console.WriteLine(ex.ToString()); return(false); }
            finally { variables.escapeloop = false; }
        }
Beispiel #8
0
 private byte[] build(byte[] data)
 {
     byte[] returnval = Oper.returnportion(ref data, 2, 2);
     return(returnval);
 }
Beispiel #9
0
        public int creatergh2ecc(string filename, string outputfolder, ref ProgressBar pb, string cpukey)
        {
            eccs dt = new eccs();

            byte[] data;
            int    layout;
            bool   rgh2 = false;

            bool sts = objAlphaPattern.IsMatch(cpukey);

            if (variables.rgh2 && !String.IsNullOrEmpty(cpukey) && sts)
            {
                rgh2 = true;
            }

            long   size      = 0;
            string imagefile = filename;

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            if (variables.debugme)
            {
                Console.WriteLine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            }

            string pathforit    = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string cdrgh2file   = Path.Combine(pathforit, @"common/cdxell/CDRGH2");
            string cdfile       = Path.Combine(pathforit, @"common/cdxell/CD");
            string cdjasperfile = Path.Combine(pathforit, @"common/cdxell/CDjasper");

            /// nand image
            {
                byte[] bbimage = Nand.BadBlock.find_bad_blocks_X(imagefile, 0x50);
                data    = Oper.returnportion(ref bbimage, 0, 1 * 1024 * 1024);
                bbimage = null;

                layout = Nand.Nand.getConsole(new Nand.PrivateN(filename)).Layout;

                if (Oper.allsame(Oper.returnportion(ref data, 0x210, 0x200), 0xFF))
                {
                    Console.WriteLine("Invalid Image");
                    return(-1);
                }
                Console.WriteLine("* unpacking flash image, ....");
                unpack_base_image_ecc(ref data, ref pb, ref dt);
                dt.CB_A_crypted = dt.CB_A;
                dt.SMC          = decrypt_SMC(dt.SMC);
            }

            creatergh2eccinit(ref dt);
            ///
            ///Finished Loading images
            ///
            data = null;
            if (dt.CD_plain == null)
            {
                return(-1);
            }
            if (dt.SMC == null)
            {
                return(-1);
            }
            ///
            Console.WriteLine(" * we found the following parts: ");
            Console.WriteLine("SMC: {0}.{1}", (dt.SMC[0x101].ToString()), (dt.SMC[0x102]).ToString());
            ///
            if (dt.CB_A != null)
            {
                Console.WriteLine("CB_A: {0}", Oper.ByteArrayToInt(build(dt.CB_A)));
            }
            else
            {
                Console.WriteLine("CB_A: missing");
            }
            if (dt.CB_B != null)
            {
                Console.WriteLine("CB_B: {0}", Oper.ByteArrayToInt(build(dt.CB_B)));
            }
            else
            {
                Console.WriteLine("CB_B: missing");
            }

            ///
            ///
            int[] rghcbs  = { 6753, 6752, 5773, 4578, 4577, 5772, 9230 };
            int[] rgh1cbs = { 9188 };
            //if (rghcbs.Contains(bytearray_to_int(build(CB_A)))) rgh2 = true;
            if (dt.CB_B != null && !rgh1cbs.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
            {
                rgh2 = true;
            }
            ///
            ///
            string c;

            if (rgh2)
            {
                dt.CD_plain = Oper.openfile(cdrgh2file, ref size, 1 * 1024 * 1024);
                if (dt.CD_plain == null)
                {
                    return(-1);
                }
                if (dt.CD != null)
                {
                    Console.WriteLine("CD (image): {0}", Oper.ByteArrayToInt(build(dt.CD)));
                }
                else
                {
                    Console.WriteLine("CD (image): missing");
                }
                if (dt.CD_plain != null)
                {
                    Console.WriteLine("CD (decrypted): {0}", Oper.ByteArrayToInt(build(dt.CD_plain)));
                }
                else
                {
                    Console.WriteLine("CD (decrypted): missing");
                }
                byte[] CB_A_img_RAND = { };
                CB_A_img_RAND = Oper.returnportion(ref dt.CB_A_crypted, 0x10, 0x10);
                ///
                byte[] CB_A_img = Nand.Nand.decrypt_CB(dt.CB_A_crypted);
                Console.WriteLine(" * checking required versions...");

                int[] zephyr_builds   = { 4578, 4577, 4575, 4560, 4576 };
                int[] falcon_builds   = { 5771, 5772, 5773 };
                int[] jasper_builds   = { 6750, 6752, 6753, 6754 };
                int[] trinity_builds  = { 9188, 9230, 9231 };
                int[] corona_builds   = { 13121, 13180 };
                int[] xor_hack_builds = { 9230, 9231, 5773, 6753, 6754, 4575, 4560, 13180 };
                int[] patch_builds    = { 5772, 6752, 9188, 13121 };

                if (!zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    return(-3);
                }
                if (!xor_hack_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !patch_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) && String.IsNullOrEmpty(cpukey))
                {
                    return(-4);
                }

                Console.WriteLine("ok");

                Console.WriteLine(" * patching SMC...");
                dt.SMC = patch_SMC(dt.SMC);

                Console.WriteLine(" * Replacing CD...");
                dt.CD       = dt.CD_plain;
                dt.CD_plain = null;

                string cbapath = "", cbbpath = "";

                if (falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.5772.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.5772.bin");
                }
                else if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.6752.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.6752.bin");
                }
                else if (trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.9188.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.9188.bin");
                }
                else if (zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.4577.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.4577.bin");
                }
                else if (corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.13121.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.13121.bin");
                }

                c      = "RGH2 2stage CB img";
                cpukey = "";
wtf:
                if (String.IsNullOrEmpty(cpukey))
                {
                    if (patch_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
                    {
                        Console.WriteLine(" * patching CB_B...");
                        dt.CB_B = patch_CB(dt.CB_B);
                        dt.CB_A = dt.CB_A_crypted;
                    }
                    else if (xor_hack_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
                    {
                        Console.WriteLine();
                        Console.WriteLine("* XOR HACK NEEDED FOR CB {0}", Oper.ByteArrayToInt(build(dt.CB_B)));

                        byte[] CB_B_plain = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_B." + Oper.ByteArrayToInt(build(dt.CB_B)) + ".bin"), ref size, 0);
                        if (CB_B_plain == null)
                        {
                            Console.WriteLine("Failed to open CB_B.{0}.bin", Oper.ByteArrayToInt(build(dt.CB_B))); return(5);
                        }

                        byte[] CB_B_patched = Oper.openfile(cbbpath, ref size, 0);
                        if (CB_B_patched == null)
                        {
                            Console.WriteLine("Failed to open {0}", cbbpath); return(5);
                        }
                        Console.WriteLine(" * patching CB_B...");

                        CB_B_patched = patch_CB(CB_B_patched);
                        if (CB_B_patched == null)
                        {
                            Console.WriteLine("Failed to patch the CB_B"); return(5);
                        }
                        Console.WriteLine(" * Applying XOR Hack to CB_B {0}", Oper.ByteArrayToInt(build(dt.CB_B)));

                        dt.CB_B = xor_hack(dt.CB_B, CB_B_plain, CB_B_patched);
                        Console.WriteLine(" * Replacing CB_A {0} with {1}", Oper.ByteArrayToInt(build(dt.CB_A)), Oper.ByteArrayToInt(build(CB_B_patched)));

                        dt.CB_A = Oper.openfile(cbapath, ref size, 0);
                        if (dt.CB_A == null)
                        {
                            Console.WriteLine("Failed to open {0}", cbapath); return(5);
                        }
                        byte[] CB_A_key = { };
                        dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, CB_A_img_RAND, ref CB_A_key);
                    }
                }
                else
                {
                    if (MessageBox.Show("Are you sure you want to build a new bootloader chain?", "Bootloader Chain", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
                    {
                        cpukey = "";
                        goto wtf;
                    }
                    Console.WriteLine("\n * Building new bootloader chain using cpu_key: {0}", cpukey);

                    dt.CB_A = Oper.openfile(cbapath, ref size, 0);
                    dt.CB_B = Oper.openfile(cbbpath, ref size, 0);

                    dt.CB_B = patch_CB(dt.CB_B);

                    byte[] CB_A_key = { };
                    dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, CB_A_img_RAND, ref CB_A_key);
                    dt.CB_B = Nand.Nand.encrypt_CB_cpukey(dt.CB_B, CB_A_key, Oper.StringToByteArray(cpukey));
                }
                ///
                ///
                ///
                Console.WriteLine(" * constructing new image...");

                c = c + ", CB=" + Oper.ByteArrayToInt(build(dt.CB_A));
            }
            else
            {
                if (dt.CD != null)
                {
                    Console.WriteLine("CD (image): {0}", Oper.ByteArrayToInt(build(dt.CD)));
                }
                else
                {
                    Console.WriteLine("CD (image): missing");
                }
                if (dt.CD_plain != null)
                {
                    Console.WriteLine("CD (decrypted): {0}", Oper.ByteArrayToInt(build(dt.CD_plain)));
                }
                else
                {
                    Console.WriteLine("CD (decrypted): missing");
                }
                int[] jasper_builds = { 6750, 6752, 6753 };
                if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    dt.CD_plain = Oper.openfile(cdjasperfile, ref size, 1 * 1024 * 1024);
                }
                if (dt.CD_plain == null)
                {
                    return(-1);
                }
                byte[] CB_A_img_RAND = { };
                if (!donor)
                {
                    CB_A_img_RAND = Oper.returnportion(ref dt.CB_A_crypted, 0x10, 0x10);
                }
                ///
                if (Oper.ByteArrayToInt(build(dt.CB_A)) >= 1888 && Oper.ByteArrayToInt(build(dt.CB_A)) <= 1940 || Oper.ByteArrayToInt(build(dt.CB_A)) == 7373 || Oper.ByteArrayToInt(build(dt.CB_A)) == 8192)
                {
                    Console.WriteLine(" * using donor CB");
                    dt.CB_A_crypted = null;
                    if (MessageBox.Show("There have been various reports that using a different bootloader improves the glitch speeds on xenon. Click Yes to use the 7375 Bootloader or Click No to use the 1940 one.", "Choose CB", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        dt.CB_A = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_A.7375.bin"), ref size, 0);
                    }
                    else
                    {
                        dt.CB_A = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_A.1940.bin"), ref size, 0);
                    }
                    if (dt.CB_A == null)
                    {
                        Console.WriteLine("Failed to open CB"); return(5);
                    }
                    dt.CB_B     = null;
                    dt.CD_plain = Oper.openfile(cdfile, ref size, 1 * 1024 * 1024);
                    if (dt.CD_plain == null)
                    {
                        return(-1);
                    }
                }
                ///
                ///
                ///
                int[] xenon_builds  = { 1923, 7375 };
                int[] zephyr_builds = { 4578, 4579, 4575 };
                int[] falcon_builds = { 5771, 5772, 5773 };
                //int[] jasper_builds = { 6750, 6752, 6753 };
                int[] trinity_builds  = { 9188, 9230 };
                int[] corona_builds   = { 13121, 13180 };
                int[] slim_builds     = { 9188, 9230, 13121 };
                int[] xor_hack_builds = { 9230, 5773, 6753, 4575 };

                if (!donor)
                {
                    if ((dt.CB_A_crypted != null) && (Oper.ByteArrayToInt(build(dt.CB_A)) != 9230))
                    {
                        dt.CB_A = Nand.Nand.decrypt_CB(dt.CB_A_crypted);
                        if (dt.CB_A == null)
                        {
                            Console.WriteLine("Error");
                        }
                    }
                }
                if (dt.CB_B != null && !slim_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine("Not supported yet");
                    return(5);
                }


                if (trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: trinity (slim)");
                }
                else if (corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: corona");
                }
                else if (zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: zephyr");
                }
                else if (falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: falcon");
                }
                else if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    if (donor)
                    {
                        Console.WriteLine(" * this image will be valid *only* for: jasper (CB_6751)");
                    }
                    else
                    {
                        Console.WriteLine(" * this image will be valid *only* for: jasper (CB_6750)");
                    }
                }
                else
                {
                    Console.WriteLine(" * this image will be valid *only* for: xenon");
                }

                Console.WriteLine(" * patching SMC...");
                dt.SMC = patch_SMC(dt.SMC);

                dt.CD       = dt.CD_plain;
                dt.CD_plain = null;

                if (dt.CB_B != null)
                {
                    Console.WriteLine(" * patching CB_B...");
                    dt.CB_B = patch_CB(dt.CB_B);
                    c       = "patched CB img";
                }
                else
                {
                    //Nand.savefile(CB_A, "CB_f.bin");
                    Console.WriteLine(" * zero-pairing...");
                    for (int bytes = 0x20; bytes < 0x40; bytes++)
                    {
                        dt.CB_A[bytes] = 0x00;
                    }
                    c = "zeropair image";
                }
                if (!Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "output")))
                {
                    Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "output"));
                }
                ///
                ///
                ///
                Console.WriteLine(" * constructing new image...");
                byte[] random = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

                c = c + ", version=01, CB=" + Oper.ByteArrayToInt(build(dt.CB_A));

                if (dt.CB_B == null)
                {
                    byte[] CB_A_key = { };
                    //Nand.savefile(CB_A, "CB_d.bin");
                    dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, random, ref CB_A_key);
                    //Nand.savefile(CB_A, "CB_e.bin");
                    //Console.WriteLine(ByteArrayToString(CB_A_key));
                    dt.CD = Nand.Nand.encrypt_CD(dt.CD, random, CB_A_key);
                }
            }

            createrghheader(ref dt, c);
            ///
            dt.SMC = encrypt_SMC(dt.SMC);
            ///
            ///
            byte[] newXell = dt.Xell;
            if (dt.Xell.Length <= 256 * 1024)
            {
                Console.WriteLine(" * No separate recovery Xell available!");
                newXell = Oper.concatByteArrays(dt.Xell, dt.Xell, dt.Xell.Length, dt.Xell.Length);
            }
            dt.Xell = null;
            ///
            /// Start of image creation
            ///
            byte[] Final = { };
            Console.WriteLine(" * Flash Layout:");
            Final = addtoflash(Oper.returnportion(ref dt.Header, 0x00, 0x200), Final, "Header", 0x00, 0x200);
            Final = padto_v2(Final, 0x4000 - dt.SMC.Length);
            ///
            Final       = addtoflash(dt.SMC, Final, "SMC", Final.Length, dt.SMC.Length);
            dt.SMC      = null;
            Final       = addtoflash(dt.Keyvault, Final, "Keyvault", Final.Length, dt.Keyvault.Length);
            dt.Keyvault = null;
            ///
            if (dt.CB_B != null)
            {
                if (!rgh2)
                {
                    Final = addtoflash(dt.CB_A_crypted, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A_crypted.Length);
                }
                else
                {
                    Final = addtoflash(dt.CB_A, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A.Length);
                }
                Final = addtoflash(dt.CB_B, Final, "CB_B " + Oper.ByteArrayToInt(build(dt.CB_B)), Final.Length, dt.CB_B.Length);
            }
            else
            {
                Final = addtoflash(dt.CB_A, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A.Length);
            }
            dt.CB_A = null; dt.CB_B = null; dt.CB_A_crypted = null;
            ///
            Final = addtoflash(dt.CD, Final, "CD " + Oper.ByteArrayToInt(build(dt.CD)), Final.Length, dt.CD.Length);
            dt.CD = null;
            Final = padto_v2(Final, XELL_BASE_FLASH);
            ///
            Final   = addtoflash(Oper.returnportion(ref newXell, 0, 256 * 1024), Final, "Xell (backup)", Final.Length, 256 * 1024);
            Final   = addtoflash(Oper.returnportion(ref newXell, 256 * 1024, newXell.Length - (256 * 1024)), Final, "Xell (main)", Final.Length, newXell.Length - (256 * 1024));
            newXell = null;
            ///
            if (variables.extractfiles || variables.debugme)
            {
                Oper.savefile(Final, Path.Combine(outputfolder, "image_no.ecc"));
            }

            if (hasecc)
            {
                Console.Write(" * Encoding ECC...");
                Final = Nand.Nand.addecc_v2(Final, true, 0, layout);
            }
            else
            {
                Console.WriteLine("NOT adding Spare Data");
            }

            Console.WriteLine("Done!");
            ///
            Oper.savefile(Final, Path.Combine(outputfolder, "image_00000000.ecc"));
            DirectoryInfo dinfo = new DirectoryInfo(outputfolder);

            Console.WriteLine("------------- Written into {0}\n", Path.Combine(dinfo.Name, "image_00000000.ecc"));
            pb.Value = pb.Maximum;
            return(1);
        }