/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.io.*;

public class CarboUpgrade {
 public static final int PAD = 20;

 private static int carbo_process_image(byte image[],int size) {
  int total_size=0;

  int srcpos=0;
  int dstpos=0;

  while(srcpos<size) {
   int tag=((int)image[srcpos])&0xff;

   int b1=((int)image[srcpos+1])&0xff;
   int b2=((int)image[srcpos+2])&0xff;
   int b3=((int)image[srcpos+3])&0xff;
   int tagsize=((b1<<16)|(b2<<8)|(b3))&0xffffff;

   switch(tag) {
    case 0xaa:
     break;
    case 0x55:
     break;
    case 0x5a:
     System.arraycopy(image,srcpos+4,image,dstpos,tagsize-4); 
     dstpos+=tagsize-4;
     total_size+=tagsize-4;
     break;
   }

   srcpos+=tagsize+4;
  }
  
  return total_size;
 }

 private static int carbo_rewrite_image(byte image[],int sizetab[],int sec_cnt) {
  int total_size=0;

  int srcpos=0;
  int dstpos=0;

  for(int i=0;i<sec_cnt;i++) {
   int size=sizetab[i];
   System.arraycopy(image,srcpos,image,dstpos,size); 
   
   srcpos+=MPEGDefs.MAX_SECTION_SIZE;
   dstpos+=size;
   
   total_size+=size;
  }

  total_size=carbo_process_image(image,total_size);

  return total_size;
 }

 public static void carbo_write_image(String name,byte image[],int size) {
  try {
   FileOutputStream fos=new FileOutputStream(name,false);
   fos.write(image,0,size);
   fos.close();
  } catch(Throwable t) {}
 }

 public static void process_data(byte image[],int sizetab[],int sec_cnt,int key[]) {
  try {
   System.out.println("- processing image");

   int size=carbo_rewrite_image(image,sizetab,sec_cnt);

   String s=ConsoleUtils.padded_string("  total size:",PAD)+"0x"+ConsoleUtils.hex_value(size,8);
   System.out.println(s);

   System.out.println("- decrypting image");

   s=ConsoleUtils.padded_string("  algorithm:",PAD)+"Twofish CBC "+key.length*32+"bit";
   System.out.println(s);

   s=ConsoleUtils.padded_string("  key:",PAD);
   System.out.println(s);

   byte kdata[]=new byte[key.length<<2];

   for(int i=0;i<key.length;i++) {
    kdata[4*i]=(byte)(key[i]&0xff);
    kdata[4*i+1]=(byte)((key[i]>>8)&0xff);
    kdata[4*i+2]=(byte)((key[i]>>16)&0xff);
    kdata[4*i+3]=(byte)((key[i]>>24)&0xff);
   }

   ConsoleIf.print_buf(kdata);

   Twofish.decrypt_cbc(image,size,key,key.length,null);

   String filename="upgrade.dat";

   System.out.println("- saving image");

   carbo_write_image(filename,image,size);

   s=ConsoleUtils.padded_string("  output:",PAD)+filename;
   System.out.println(s);
  } catch(Throwable t) {}
 }
}
