Jump to content





Welcome to dEViATED. We provide game trainers, cheats and gamehacking tutorials and a gamehacking forum for discussions and help. We have pc game trainers for various old and new games to download and will expand to other platforms. Go ahead and have a look around, you will love our pc trainers!.

Not interested in trainers ? socialize with us, we talk about girls, booze, movies, music and basically anything and everything.

These are some of the latest trainers released by us and supported fully.
Age of Wonders 3 Trainer
Thief Trainer
Castlevania Lord of Shadows 2 Trainer
South Park Stick Of Truth Trainer


Photo

Tutorial on Coding a Trainer in Java (Done by me)


  • Please log in to reply
31 replies to this topic

#16 MATRIX

MATRIX

    Tamed

  • n00b
  • PipPipPip
  • 39 posts

Posted 02 December 2010 - 10:33 PM

everything works good in JCreator but i get the the error Exception in thread "main" java.lang.NullPointerException
at trainermain.main(trainermain.java:218)


and line 218 is
System.out.println(value[0]);





#17 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 02 December 2010 - 10:37 PM

Adding 2 new functions for my trainer Skeleton - why?

As i was making codecaves to point the gamecode to somewhere else so i can get out the address of something i need to know in the game with the code
mov [1000000D],ecx i realized, the real address saved to my specified memorylocation is reversed :)

So - if you use my ReadMemoryProcess Procedure on memory location 1000000D with size 4 (becoz the CPU register is 4 byte long) it will say for example
aa bb cc dd - but the real address we want is dd cc bb aa

so i made a new java function called reversearray which does it for you


Problem Nr.2 - were getting returned an array consisting (in our example here) of 4 bits (after using reversearray) in the right order - how to make an valid offset out of it to red from ?

i made a new function called createoffset which converts this 4 int numbers to a valid memory address which u can Read and write to

but now here my functions !



public static int [] ReverseArray(int [] ArrayIn)
   {
	  int [] myarray=new int[ArrayIn.length];
	  for(int i=0;i<myarray.length;i++)
	  {
		  myarray[myarray.length-i-1]=ArrayIn[i];
		  
	  }
	  
	  return myarray;
   }
   
   public static int CreateOffset(int[] offsetcontainer)
   {
	   String offset="";
	   for(int i=0;i<offsetcontainer.length;i++)
	   {
		   offset=offset+Integer.toHexString(offsetcontainer[i]);
	   }
	   int returnvalue = Integer.parseInt(offset, 16);
	   return returnvalue;
   }


Good Luck - Shark out ^^

#18 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 02 December 2010 - 10:43 PM

@ Matrix - of course you do :)
As my function ReadProcessMemory says - if reading FAILS due to (1) Process wasnt found or (2) you tried to read an invalid address, my function retuns a null.

so if you try to print out the value[0] u cant do it because value is a nullpointer - there u have your nullpointer exception :)

Before you attempt to read an address - make sure (1) process u want to read from is running (2) reading from a valid memoryaddress :PP



For Example - in my game Baldursgate2
i have some hacks and codecaves concerning charactercreation.
once in charactercreation - u will beguided after some steps to a screen which lets you choose ure characters properities like strengh intelligence and so on.
BUT i cant read that memory value before i actually ENTER that screen - sometimes games do not allocate those areas when you try to read them.
So youre trying to read from something which isnt there - reading fails - nullpointer returned :D

#19 MATRIX

MATRIX

    Tamed

  • n00b
  • PipPipPip
  • 39 posts

Posted 02 December 2010 - 10:45 PM

@ Matrix - of course you do :)
As my function ReadProcessMemory says - if reading FAILS due to (1) Process wasnt found or (2) you tried to read an invalid address, my function retuns a null.

so if you try to print out the value[0] u cant do it because value is a nullpointer - there u have your nullpointer exception :)

Before you attempt to read an address - make sure (1) process u want to read from is running (2) reading from a valid memoryaddress :PP



For Example - in my game Baldursgate2
i have some hacks and codecaves concerning charactercreation.
once in charactercreation - u will beguided after some steps to a screen which lets you choose ure characters properities like strengh intelligence and so on.
BUT i cant read that memory value before i actually ENTER that screen - sometimes games do not allocate those areas when you try to read them.
So youre trying to read from something which isnt there - reading fails - nullpointer returned :D

ya so because my game process is not running it cant find it that why it returns and nullpointer?

#20 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 02 December 2010 - 11:46 PM

ya so because my game process is not running it cant find it that why it returns and nullpointer?


As i said - if u try to read from an process which isnt running ull get a nullpointer
if u try to read an address from a running process which is not valid ull get an nullpointer

#21 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 12:35 AM

Found an error in my CreateOffset function, when u got ints lower than 16 - the java function returned 1,...,f instead of 01,....,0f - which resulted in a bad offset
this one now has the error corrected

//Converts the Array from ReverseArray to a valid memoryaddress
   public static int CreateOffset(int[] offsetcontainer)
   {
	   String offset="";
	   for(int i=0;i<offsetcontainer.length;i++)
	   {
		   if(offsetcontainer[i]<16)
		   {
			   offset=offset+"0"+Integer.toHexString(offsetcontainer[i]);
		   }
		   else
		   {
			   offset=offset+Integer.toHexString(offsetcontainer[i]);  
		   }
		   
	   }
	   
	   int returnvalue = Integer.parseInt(offset, 16);
	   return returnvalue;
   }


cu - Sharky

#22 STN

STN

    zzz

  • Wicked DICK
  • 5,157 posts

Posted 03 December 2010 - 04:03 AM

Seems a lot more effort and code to do it in java, even then it seems a bit buggy. I guess i will stick to c++ then, more power and efficient.

Good job on the tut, even as a beginner it didnt took me long to understand it!.

#23 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 12:21 PM

Well, i dont like this c++ ^^ - have to get a goooood book first to learn it - and dont have time for that :)

In my job later i have to do Java anyway so i makes more sense to me to try it that way - and wit works :)
Ill add more functions to my toolkit making the "every day trainer coding" more comfortable ^^

Bugs will be found out and fixed time by time - if they exist ^^

#24 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 03:16 PM

Another new handy function
//Unluckily the ReadMyProcessMemory function returns an array containing the value of each bite read
   //this function converts the returned value into a real in our trainer usable integer value
   //i.e. if you have 65535 livepoints this is a 2 byte value and the reading function returns an array having 255,255 in it
   //this function here will take this int and return 65535
   public static int GetValueOfIntAr(int[] ReadMyProcessMemoryReturnedIntArray)
   {
	   String realvalue="";
	   for(int i=0;i<ReadMyProcessMemoryReturnedIntArray.length;i++)
	   {
		   realvalue=realvalue+Integer.toHexString(ReadMyProcessMemoryReturnedIntArray[i]);
	   }
	   return Integer.parseInt(realvalue, 16);
   }


#25 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 03:36 PM

Yet another handy function ^^

//its easy to write Hex values with the WriteMyProcessMemory function - if we know our hex value is 0a 7b 3c fa - we just make an Array
   //of length 4, put 0a to position 0, 7b to position 1 and so on - but int values are a bit of a problem because the Write Process function
   //-unluckily- uses digned bytes to transfer to out kernel32.dll. so this function takes your integer value i.e. 65535 and conveerts it into an array
   //looking like 255,255 and this u can use with WriteMyProcessMemory
   public static int[] IntegerToArray(int intvalue)
   {
	   //first we make an hex String out of our intvalue
	   String hexstring=Integer.toHexString(intvalue);
	   
	   //unfortunately the hex string can be odd, so we make it even
	   //why? - because we want it like 0a 7a and not a7a
	   if(hexstring.length()%2==1)
	   {
		   hexstring="0"+hexstring;
	   }
	   System.out.println(hexstring);
	   //now we need to build our Array
	   int[] ourArray=new int[hexstring.length()/2];
	   for(int i=0;i<hexstring.length()/2;i++)
	   {
		   ourArray[i]=Integer.parseInt(""+hexstring.charAt(2*i)+hexstring.charAt(2*i+1), 16);
	   }
	   
	   return ourArray;
   }


#26 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 03:41 PM

Guess what - another handy function - never :)

//we know we can make a new array when we know the hexvalue to write ie. our hex value is 0a 7b 3c fa - we just make an Array
   //of length 4, put 0a to position 0, 7b to position 1 and so on, but this is too mouch unhandy so this functions takes an hex string and
   //gives us the desired int array for write process memory ^^
   public static int[] HexToArray(String hexstring)
   {
	   //unfortunately the hex string can be odd, so we make it even
	   //why? - because we want it like 0a 7a and not a7a
	   if(hexstring.length()%2==1)
	   {
		   hexstring="0"+hexstring;
	   }
	   
	   //now we need to build our Array
	   int[] ourArray=new int[hexstring.length()/2];
	   for(int i=0;i<hexstring.length()/2;i++)
	   {
		   ourArray[i]=Integer.parseInt(""+hexstring.charAt(2*i)+hexstring.charAt(2*i+1), 16);
	   }
	   
	   return ourArray;
   }


#27 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 04:03 PM

With my nice toolbox we can now program trainers very handy
Step 1 - find our desired Process with FindMyProcess("ProcessName") - its casesensitive

Write an integer value to a desired address:
WriteMyProcessMemory(ourProcess, ourAddress, IntegerToArray(ourIntValue));

(OurAddress can be the integer value of the address (if u know it normally debuggers etc use hex values for address its mor common) then you just write the integer value, or hex address in form 0xHEXCODE)

Write a hex Value to a desired address:
WriteMyProcessMemory(ourProcess, ourAddress, HexToArray("OurHexValue"));

Read a value from the desired address
ReadMyProcessMemory(OurProcess, ourAddress, number of bytesToRead); <- returns an array with int values representing the hexvalues of each byte read.
this array we put into GetValueOfIntAr(ourReturnedArray) and get the real integer value :)

Thats the basics for reading and writing values :)


Now some infor for codecave and codeinjection etc.
Were using codecaves to get addresses assigned by DMA - so we rerout the code to our specified area save the address from CPU register and jump back.

ie. mov [10000007], eax - stores the value of cpu register eax at address 0x10000007
BUT - now comes the trick ^^ - it stores our desired addres REVERSED in bytes
so if the real address we want to know is aa cc bb ff the asm codes stores it as ff bb cc aa
and we get an array returned by ReadMyProcessMemory with {ff,bb,cc,aa} - here we jsut use my ReverseArray function and we have the real address, and now can add the constand from our static pointer on it to determine the realreal address where our desired information is stored.

If you want to write OP Codes like mov [10000007], eax - you first assemble this code in your disassembler and then write down the bytes of the assembled op code

then you just use WriteMyProcessMemory(ourProcess, ourAddress, HexToArray("OurAsmCodeAsHexString"));

and ure done :PP



Hope this helps :D in the next post ill post the complete skeleton againw ith all those nice functions in it so u have it cleaned up and working.

If you find bugs let me know - thanks
Sharky out :)

#28 Sharky

Sharky

    Tamed

  • n00b
  • PipPipPip
  • 45 posts

Posted 03 December 2010 - 04:05 PM

//Small Code Skeleton for making a Trainer in java

//done by Sharky on http://deviatedhacking.com

//Version 0.9.9 Beta - Because there is one small thing left concerning the Processfind Method

//i want to try both dll files, but atm if one dll file doesnt contain the desired Function the trainer crashes

//this will be fixed when i have time for it - until then - try wich dll suits your system or make a Trainer for one

//and one Trainer for the other DLL - its only commenting out 3 lines of code 2 times ^^

//download jna.jar from the internet - and include to your project

//i recomm your using eclipse for coding <img src='http://deviatedhacking.com/public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />







//Usual Imports

import java.util.Arrays;



//JNA imports - Lets us use Windows dll files

import com.sun.jna.Memory;

import com.sun.jna.Native;

import com.sun.jna.Pointer;

import com.sun.jna.ptr.IntByReference;

import com.sun.jna.win32.StdCallLibrary;



public class trainermain

{

	

	//Public Variables for AccessRights

	public static final int PROCESS_QUERY_INFORMATION = 0x0400;

    public static final int PROCESS_VM_READ = 0x0010;

    public static final int PROCESS_VM_WRITE = 0x0020;

    public static final int PROCESS_VM_OPERATION = 0x0008;

    public static final int ALLOCATION_TYPE_MEM_COMMIT = 0x1000;

    public static final int ALLOCATION_TYPE_MEM_RESERVE = 0x2000;

    //Some functions, depending on Windows Version are located in Kernel32.dll, some in Psapi.dll 

    

    //Access to external Kernel32.dll

   public interface Kernel32 extends StdCallLibrary

    {

        Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

        boolean ReadProcessMemory(Pointer hProcess, int inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead);

        

        public Pointer OpenProcess(int dwDesiredAccess, boolean bInheritHandle, int dwProcessId);

        

        

        boolean WriteProcessMemory(Pointer hProcess,int AdressToChange,Pointer ValuesToWrite,int nSize, IntByReference irgendwas);

        

        int GetLastError(); 

       

        

        public void  VirtualAllocEx(Pointer ProcessToAllocateRamIn, int AddresToStartAt, int DesiredSizeToAllocate, int AllocationType, int ProtectType);

        

        //Needed for some Windows 7 Versions

        boolean EnumProcesses(int []ProcessIDsOut,int size , int[] BytesReturned);

        

        int GetProcessImageFileNameW(Pointer Process, char[] outputname, int lenght);

               

    }

    

   //Access to external Psapi.dll

   public interface Psapi extends StdCallLibrary

   {

	   Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class);

	   //For some Windows 7 Versions and older down to XP

	   boolean EnumProcesses(int []ProcessIDsOut,int size , int[] BytesReturned);

	   int GetProcessImageFileNameW(Pointer Process, char[] outputname, int lenght);

   }



   //Processfinder - returns NULL if Process wasnt found

   public static Pointer FindMyProcess(String ProcessNameToFind)

   {

	   //Related to Version we have to use Kernel32.dll OR Psapi.dll to find the Process

	   Psapi Psapidll = Psapi.INSTANCE;

	   Kernel32 Kernel32dll = Kernel32.INSTANCE;

	   

	   //we take an arraysize of 1024 - coz noone will have 1024 Processes running <img src='http://deviatedhacking.com/public/style_emoticons/<#EMO_DIR#>/biggrin.png' class='bbc_emoticon' alt=':PP' />

	   int[] processlist=new int[1024];

       int[] dummylist=new int[1024];

       

       //Lets first try Psapi.dll

       try{Psapidll.EnumProcesses(processlist, 1024, dummylist);}

       catch(Exception e)

       {

    	   

       }

       

       //Lets now try Kernel32.dll

       //try{Kernel32dll.EnumProcesses(processlist, 1024, dummylist);}

       //catch(Exception e)

      // {

    	   

      // }

       

       //Ok - we now got our Array with all the ProcessID&#39;s from all running Processes in the array processlist

       //Time to find out which Processid is our desired one!

       

       //A pointer for our Processfinding mechanism

       Pointer tempProcess;

       //Pointer for our desired Process

       Pointer Process=null;

       //Char Array for the path of the processes containing also the filename.exe

       char []outputnames = new char[1024];

       //A String for easier Comparison - see below

       String path="";

              

       for(int processid : processlist)

       {

       	

    	tempProcess=Kernel32dll.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, false, processid);

       	

    	//Again we have to try both dll files in order to obtain our goal - one will work

    	try{Psapidll.GetProcessImageFileNameW(tempProcess, outputnames, 1024);}

       	catch(Exception e){}

       	

       	//try{Kernel32dll.GetProcessImageFileNameW(tempProcess, outputnames, 1024);}

       	//catch(Exception e){}

       	

       	//reset Path String

       	path="";

       	

       	for(int k=0; k<1024;k++)

       	{

       		//Convert our Char Array into a nice readable String

       		if((int) outputnames[k]!=0)

       		path=path+outputnames[k];

       	}

       	

       	if(path.contains(ProcessNameToFind))

       	{

       		//If one of the processes found has the desired process exe name in its path its the one we want <img src='http://deviatedhacking.com/public/style_emoticons/<#EMO_DIR#>/smile.png' class='bbc_emoticon' alt=':)' />

       		Process=tempProcess;

        }

       	

       	//reset char 

       	outputnames = new char[1024];

       	

       }

       

       //Finally returning our Process - Null if we didnt find it.

       return Process;

   }

   

   //ReadProcessMemory ^^

   public static int[] ReadMyProcessMemory(Pointer ProcessToReadFrom, int AdressToReadFrom, int NumberOfBytesToRead )

   {

	   //Make the Desired Functions available

	   Kernel32 Kernel32dll = Kernel32.INSTANCE;

	   

	   int offset=AdressToReadFrom;

	   IntByReference baseAddress = new IntByReference();

       baseAddress.setValue(offset);

       Memory outputBuffer = new Memory(NumberOfBytesToRead);

	   

	   boolean reader = Kernel32dll.ReadProcessMemory(ProcessToReadFrom, offset, outputBuffer, NumberOfBytesToRead, null);

	   

	   

	   

	   if(reader)

	   {

		  //Process the received Data

	       byte[] bufferBytes = outputBuffer.getByteArray(0, NumberOfBytesToRead);

	               

	        //Who wants signed byte? NOONE ! Lets convert it to a nice int !

	        

	        int[] realvalues=new int[bufferBytes.length];

	        

	        for(int i=0;i<bufferBytes.length;i++)

	        {	if(bufferBytes[i]<0)

	      		{       		

	      			realvalues[i]=256+bufferBytes[i];

	      		}

	      		else

	      		{

	      			realvalues[i]=bufferBytes[i];

	      		}

	        }

	        //Conversion done ! lets Return the data (Remember its integer not hex)

	        return realvalues;

	        

	   }

	   else

	   {

		   //Reading went wrong - SHIT

		   return null;

	   }

   }



   //WritePprocessMemory

   public static boolean WriteMyProcessMemory(Pointer ProcessToWriteTo,int AddressToWriteTo,int[] BytesToWrite)

   {

	   //Gain Access to Kernel32.dll

	   Kernel32 Kernel32dll = Kernel32.INSTANCE;

	   

	   int offset=AddressToWriteTo;

	   IntByReference baseAddress = new IntByReference();

       baseAddress.setValue(offset);

       Memory inputBuffer = new Memory(BytesToWrite.length);

       IntByReference dummy = new IntByReference();

       

       //Convert the Interger Array to an usable Array of type Memory

       for(int i=0;i<BytesToWrite.length;i++)

       {

    	   inputBuffer.setByte(i, (byte)BytesToWrite[i]);

       }

       

	   return Kernel32dll.WriteProcessMemory(ProcessToWriteTo, offset,inputBuffer , BytesToWrite.length, dummy);

	   

	      

   }

 

   //AllocateMemory - Especially good for Codecaves ^^

   public static void AllocateMyProcessMemory(Pointer ProcessToAllocateRamIn, int StartingAdress, int SizeToAllocate)

   {

	   //Access to desired functions

	   Kernel32 Kernel32dll = Kernel32.INSTANCE;

	   

	   //Getting our Space

	   Kernel32dll.VirtualAllocEx(ProcessToAllocateRamIn, StartingAdress, SizeToAllocate, ALLOCATION_TYPE_MEM_COMMIT | ALLOCATION_TYPE_MEM_RESERVE, 0x04);

	   

   }

   

   

   //Reverses an Array - if you use codecaves and saved address from a cpu register to a memoryaddress u have to reverse the array containing the cpuregister bytes

   public static int [] ReverseArray(int [] ArrayIn)

   {

	  int [] myarray=new int[ArrayIn.length];

	  for(int i=0;i<myarray.length;i++)

	  {

		  myarray[myarray.length-i-1]=ArrayIn[i];

		  

	  }

	  

	  return myarray;

   }

   

   //Converts the Array from ReverseArray to a valid memoryaddress

   public static int CreateOffset(int[] offsetcontainer)

   {

	   String offset="";

	   for(int i=0;i<offsetcontainer.length;i++)

	   {

		   if(offsetcontainer[i]<16)

		   {

			   offset=offset+"0"+Integer.toHexString(offsetcontainer[i]);

		   }

		   else

		   {

			   offset=offset+Integer.toHexString(offsetcontainer[i]);  

		   }

		   

	   }

	   

	   int returnvalue = Integer.parseInt(offset, 16);

	   return returnvalue;

   }



   //Unluckily the ReadMyProcessMemory function returns an array containing the value of each bite read

   //this function converts the returned value into a real in our trainer usable integer value

   //i.e. if you have 65535 livepoints this is a 2 byte value and the reading function returns an array having 255,255 in it

   //this function here will take this int and return 65535

   public static int GetValueOfIntAr(int[] ReadMyProcessMemoryReturnedIntArray)

   {

	   String realvalue="";

	   for(int i=0;i<ReadMyProcessMemoryReturnedIntArray.length;i++)

	   {

		   realvalue=realvalue+Integer.toHexString(ReadMyProcessMemoryReturnedIntArray[i]);

	   }

	   return Integer.parseInt(realvalue, 16);

   }

   

   //its easy to write Hex values with the WriteMyProcessMemory function - if we know our hex value is 0a 7b 3c fa - we just make an Array

   //of length 4, put 0a to position 0, 7b to position 1 and so on - but int values are a bit of a problem because the Write Process function

   //-unluckily- uses signed bytes to transfer to out kernel32.dll. so this function takes your integer value i.e. 65535 and conveerts it into an array

   //looking like 255,255 and this u can use with WriteMyProcessMemory

   public static int[] IntegerToArray(int intvalue)

   {

	   //first we make an hex String out of our intvalue

	   String hexstring=Integer.toHexString(intvalue);

	   

	   //unfortunately the hex string can be odd, so we make it even

	   //why? - because we want it like 0a 7a and not a7a

	   if(hexstring.length()%2==1)

	   {

		   hexstring="0"+hexstring;

	   }

	   

	   //now we need to build our Array

	   int[] ourArray=new int[hexstring.length()/2];

	   for(int i=0;i<hexstring.length()/2;i++)

	   {

		   ourArray[i]=Integer.parseInt(""+hexstring.charAt(2*i)+hexstring.charAt(2*i+1), 16);

	   }

	   

	   return ourArray;

   }



   //we know we can make a new array when we know the hexvalue to write ie. our hex value is 0a 7b 3c fa - we just make an Array

   //of length 4, put 0a to position 0, 7b to position 1 and so on, but this is too mouch unhandy so this functions takes an hex string and

   //gives us the desired int array for write process memory ^^

   public static int[] HexToArray(String hexstring)

   {

	   //unfortunately the hex string can be odd, so we make it even

	   //why? - because we want it like 0a 7a and not a7a

	   if(hexstring.length()%2==1)

	   {

		   hexstring="0"+hexstring;

	   }

	   

	   //now we need to build our Array

	   int[] ourArray=new int[hexstring.length()/2];

	   for(int i=0;i<hexstring.length()/2;i++)

	   {

		   ourArray[i]=Integer.parseInt(""+hexstring.charAt(2*i)+hexstring.charAt(2*i+1), 16);

	   }

	   

	   return ourArray;

   }

   

   public static void main(String[] args)

	{

		  		   		

	}



}



#29 STN

STN

    zzz

  • Wicked DICK
  • 5,157 posts

Posted 03 December 2010 - 06:29 PM

Cool :). I am sure someone will definitely find it useful (java lovers!).

#30 bOrN

bOrN

    Tamed

  • n00b
  • PipPipPip
  • 34 posts

Posted 04 December 2010 - 02:18 PM

Wow a java trainer really nice. I have used a java patch. I'll try this too. Thnx.



Official Trainer Hosters:  
Affiliates:
 

Like our work ? Why not follow us on deviatedhacking youtube facebook page deviated twitter +deviatedhacking page