// ------------------------------------------------------
// vr.bin file decrypter (C) 2007 by ThunderPwr of ARTeam
// ------------------------------------------------------

import java.io.*;
import java.util.Hashtable;
import java.util.*;
import javax.swing.*;

public class Decrypt
{
		   
    private Hashtable Q1R;
	
    // ----------------------------------
    // Class constructor
    // ----------------------------------
    public Decrypt(String fileNameToDecrypt, String destFolder)
    {
        Q1R = null;
        char c = File.separatorChar;
        
        // ------------------------------
        // Search loop for the class name
        // ------------------------------
        if(Q1R == null)
        {
            Q1R = new Hashtable();
            long l = 0xea1255adaabefa07L;
            long currFilePointer = 0;
            long currClassFile = 0;
            RandomAccessFile randomaccessfile = null;
            try
            {
                randomaccessfile = new RandomAccessFile(fileNameToDecrypt, "r");
                randomaccessfile.seek(randomaccessfile.readInt() != 0xdeadfeed ? 0 : randomaccessfile.readInt());
                while(randomaccessfile.getFilePointer() < randomaccessfile.length() && l == randomaccessfile.readLong()) 
                {
                    String s1 = randomaccessfile.readUTF();
                    
                    currClassFile = randomaccessfile.readInt();
                    byte abyte1[] = new byte[(int)currClassFile];
                    int j = randomaccessfile.readInt();
					currFilePointer = randomaccessfile.getFilePointer();	// Read the current position
                    randomaccessfile.readFully(abyte1);
                    if(j == 2)
                    {
                    	Q1R.put(s1, abyte1);
                    	if (s1.equals("A") || s1.equals("vr"))
	                    	System.out.println ("Class Name: " + s1 + " position: " + currFilePointer + " class size: " + currClassFile);
	                	else
	                		System.out.println ("Class Name: " + NB(s1) + " position: " + currFilePointer + " class size: " + currClassFile);
                    	
                    }
                }
            }
            catch(Exception exception)
            {
                System.out.println(exception.toString());
            }
            finally
            {
                try
                {
                    randomaccessfile.close();
                }
                catch(Exception _ex) { }
            }
        }

		String s;
		
		// -------------------------------------------------
		// Decrypting loop for all classes inside vr.bin
        // -------------------------------------------------
        for (Enumeration e=Q1R.keys(); e.hasMoreElements();)
         {
         	s = (String)e.nextElement();

  	      	byte abyte0[] = (byte[])Q1R.get(s);

			System.out.println("name="+NB(s));
        
        	boolean flag1 = s.equals("A") || s.equals("vr");
	        if(abyte0 != null)
	            {
	                for(int i = 0; i < abyte0.length; i++)
	                    abyte0[i] = flag1 ? (byte)(abyte0[i] ^ 0xf3) : (byte)((abyte0[i] ^ 0x3f) - 37);
	                
	                // Write the decrypted class on the disk    
	                if (s.equals("A") || s.equals("vr"))
	                    writeByteArrayToDisk(abyte0,s + ".class",destFolder,0,0,0);
	                else
	                	writeByteArrayToDisk(abyte0,NB(s) + ".class",destFolder,0,0,0);
         		}
    	}
    }

    private static String NB(String s)
    {
        char ac[] = s.toCharArray();
        for(int i = 0; i < ac.length; i++)
            ac[i] ^= 'Z';

        return new String(ac);
    }
    
    private void writeByteArrayToDisk(byte bytebuffer[], String fileName, String destFolder, int start, int numbytes, int mode)
    {
    	// --------------------------------------------------
    	// ThunderPwr of ARTeam (write data bytes to disk)
    	// --------------------------------------------------
    	File file = new File(destFolder+"\\"+fileName);
    	
    	if (mode == 0)
    	{
    		try
    		{	// Write all the byte array from 0 to the last element
	    		FileOutputStream file_output = new FileOutputStream (file);
		    	DataOutputStream data_out = new DataOutputStream (file_output);
		    	for (int i=0; i < bytebuffer.length; i++)
					{
						data_out.writeByte (bytebuffer[i]);
					}
				file_output.close ();
    		}
	    	catch (IOException e)
			{
				System.out.println ("IO exception = " + e );
			}
    	}
    	else
    	{
    		try
    		{	// Write a section of the array from start and for numbytes elements
	    		FileOutputStream file_output = new FileOutputStream (file);
		    	DataOutputStream data_out = new DataOutputStream (file_output);
		    	for (int i=start; i < start+numbytes; i++)
					{
						data_out.writeByte (bytebuffer[i]);
					}
				file_output.close ();
    		}
	    	catch (IOException e)
			{
				System.out.println ("IO exception = " + e );
			}
    	}
    }

    
    public static void main(String args[])
    {
    	
    	if (args.length == 0)
    		{
    			System.out.println ("Error two arguments required");
    			System.out.println ("Full pathname for the file to decrypt");
    			System.out.println ("Path where to put the decrypted files");
    			System.out.println ("Example: java Decrypt C:\\Programmi\\VisualRoute\\vr.bin C:\\Temp\\Test");
    			System.out.println ("To restore the original class or package use jad with this syntax");
    			System.out.println ("\tjad -sjava -ddecompiled -r *.class");
    			System.out.println ("Decompiled classes will be put into a decompiled subfolder");
    			System.exit(0);
    		}
    		
    	System.out.println ("Decrypting file: " + args[0] + " to "+args[1]+" wait...");
    	
    	// -------------------------------------------------
    	// Make a new instance, constructor will be executed
    	// -------------------------------------------------
    	Decrypt MyDecrypt = new Decrypt(args[0], args[1]);
    	
    	System.out.println ("Decrypting succesfully...");
    }

}