Wednesday, 27 February 2008

Jad tricks

Hey guys,

No Java lesson for today, as I'm a bit busy (lazy :P). Instead I'll show you some cool tricks with Jad.

Sometimes when you try to decompile a class you see an error message saying "Class file version mismatch". But you can still go on and force Jad to decompile it using the -debug option:
jad -debug Test.class
Another common case is when there are many classes (like in qtj2) and you want to do a batch decompilation. The wildcard character can help a bit:
jad *.class
But this one is much cooler:
jad -r quangntenemy**/*.class

Saturday, 22 December 2007

String manipulation

Guys, have you all been waiting for my next lesson? :)

Today I'll show you how to do a very trivial task in challenge solving - string manipulation. With Java everything is easy :)

- Get the length of a string:
int len = str.length();
- Access the nth character of a string:
char c = str.charAt(index);
Note that in Java indices start at 0.
- Create a String from a char array:
String s = new String(charArray);
- Convert a String to a char array:
char[] c = str.toCharArray()
- Create a String from a byte array:
String s = new String(byteArray)
- Convert a String to a byte array:
byte[] b = str.getBytes();
- Get a substring of a string:
String sub1 = str.substring(beginIndex);
String sub2 = str.substring(beginIndex, endIndex);
- Find the first occurence of a character or a substring:
int index1 = str.indexOf(c);
int index2 = str.indexOf(str2);
int index3 = str.indexOf(c, fromIndex);
If there is no occurence, the result is -1.
- Compare 2 strings: strings are objects, so you can't compare strings with ==. Instead you can use:
boolean b1 = str1.equals(str2);
int b2 = str1.compareTo(str2);
int b3 = str1.equalsIgnoreCase(str2);
- Concatenate 2 strings:
String s1 = str1 + str2;
String s2 = str1.concat(str2);
But when you are concatenating many strings repeatedly you should consider using StringBuffer or StringBuilder for better performance.
- Test if a string contains another string:
boolean b = str1.contains(str2);
- Check if str2 is at the beginning of str1:
boolean b = str1.startsWith(str2);
- Check if str2 is at the end of str1:
boolean b = str1.endsWith(str2);
- Convert a string to uppercase/lowercase:
String str2 = str1.toUpperCase();
String str3 = str1.toLowerCase();
- Replace characters in a string:
// Replace all a's with b's
String str2 = str1.replace('a', 'b');
// Replace all hello's with hola's
String str3 = str1.replace("hello", "hola");
// Replace all digits with 0s
String str4 = str1.replaceAll("[0-9]", "0");
Regular expressions are so powerful but yet so huge that they will be covered in a later topic :P
- Check if a string matches a pattern:
// Check if str is a hexadecimal representation
boolean b = str.matches("[0-9A-Fa-f]+");
- Convert from String to primitives:
boolean b1 = Boolean.valueOf(str);
int i1 = Integer.valueOf(str);
double d1 = Integer.valueOf(str);
// The parseXXX methods are more powerful
boolean b2 = Boolean.parseBoolean(str);
int i2 = Integer.parseInt(str);
double d2 = Double.parseDouble(str);
// Binary conversion
int i3 = Integer.parseInt(str, 2);
// Octal conversion
int i4 = Integer.parseInt(str, 8);
// Hex conversion
int i5 = Integer.parseInt(str, 16);
- Convert from primitives to String:
// boolean b = true;
String str1 = Boolean.toString(b);
// int i = 1337;
String str2 = Integer.toString(i);
// Binary conversion
String str3 = Integer.toString(i, 2);
String str4 = Integer.toBinaryString(i);
// Octal conversion
String str5 = Integer.toString(i, 8);
String str6 = Integer.toOctalString(i);
// Hex conversion
String str7 = Integer.toString(i, 16);
String str8 = Integer.toHexString(i);
// double d = 1.337;
String str9 = Double.toString(d);
- There's also this very powerful method:
// The result will be: "true 1337 53a 1.337"
String str1 = String.format("%b %d %x %1.3f", true, 1337, 1338, 1.337);
For a complete format string reference see http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html
- Reverse a string:
String str2 = new StringBuffer(str1).reverse().toString();
Probably more will come later when I have the time :P

Wednesday, 28 November 2007

Basic IO & Dictionary Attack

Hey guys,

Now that you have known enough Java to write simple programs that do the calculation for you, let's get to know some basic input/output. Today I'll show you how to read data from text files to write a simple dictionary attack program.

In Java every input/output task is handled using streams. In the previous programs, actually I have used 2 streams: System.in, which is an InputStream, and System.out, an OutputStream.

To read/write from streams it is easiest to use a reader/writer. When you are working with text streams it's even more convenient to use BufferedReader and BufferedWriter. These classes allow you to read/write the data on a line-by-line basis.

Here's how you read a text file:
// You need to import this package for the IO classes
import java.io.*;
...
// Most IO methods throw IOExceptions,
// you don't need to worry about them for now,
// so just use this throws clause
public static void main(String[] args) throws IOException {
// Create a FileReader to read the file
FileReader fr = new FileReader("path/to/file");
// Use a BufferedReader for the convenient readLine() method
BufferedReader br = new BufferedReader(fr);
// Declare a string to store every line read from the file
String s;
// Read the file until the end of file is reached
// i.e. until the readLine() method returns null
while ((s = br.readLine()) != null) {
// Do something with the string
System.out.println(s);
}
// Close the reader to release the system resource
br.close();
}
Now let's get some practice!

In the last post I have shown you how to write a brute-force program. However, that method only works when the password is brute-forcable, probably no more than 8 characters. When the password is longer, brute-forcing will take days, or even months, or years :P Another common technique is dictionary attack.

Most passwords are based on common words to be easily memorized. Therefore instead of trying all character combination, you can use a wordlist, manipulate the words, and check them. This method is generally more effective than brute-forcing, and takes less time.

If you Google for wordlist, you can find many of them. I myself prefer the argon wordlists at http://www.theargon.com/achilles/wordlists. For quick cracking, you can use english.txt. Or you can use the huge wordlists in theargonlists/, which are 245 megs and 2 gigs when uncompressed.

Now let's pwnzor this little crackme.

If you decompile it, you'll get something like this:
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3)
// Source File Name: CrackMe2.java

import java.io.PrintStream;
import java.util.Scanner;

public class CrackMe2
{

public CrackMe2()
{
}

public static int crc(String s)
{
byte bytes[] = s.getBytes();
int crc = 0;
byte abyte0[];
int j = (abyte0 = bytes).length;
for(int i = 0; i < j; i++)
{
byte b = abyte0[i];
crc = crc >>> 8 ^ table[(crc ^ b) & 0xff];
}

return crc;
}

public static void main(String args[])
{
System.out.print("Enter password: ");
Scanner scanner = new Scanner(System.in);
String s = scanner.next();
if(crc(s) == 38983)
System.out.println("Good job!");
else
System.out.println("Go to hell!");
}

private static final int table[] = {
0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728,
1920, 51009, 1280, 50625, 50305, 1088, 52225, 3264, 3456, 52545,
3840, 53185, 52865, 3648, 2560, 51905, 52097, 2880, 51457, 2496,
2176, 51265, 55297, 6336, 6528, 55617, 6912, 56257, 55937, 6720,
7680, 57025, 57217, 8000, 56577, 7616, 7296, 56385, 5120, 54465,
54657, 5440, 55041, 6080, 5760, 54849, 53761, 4800, 4992, 54081,
4352, 53697, 53377, 4160, 61441, 12480, 12672, 61761, 13056, 62401,
62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529,
15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040,
15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560,
60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865,
60545, 11328, 58369, 9408, 9600, 58689, 9984, 59329, 59009, 9792,
8704, 58049, 58241, 9024, 57601, 8640, 8320, 57409, 40961, 24768,
24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432,
42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608,
28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688,
30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448,
32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401,
30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120,
28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441,
38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744,
23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360,
39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777,
35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905,
17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088,
17280, 33601, 16640, 33217, 32897, 16448
};

}
The crackme checks the password using the CRC16 algorithm, which is a pretty weak one. Let's crack it using dictionary attack. For simplicity you can skip the string manipulation for now and use it as is. With everything you have learned, hopefully you'll end up with the following code:
import java.io.*;

public class CrackMe2Solver {

public static void main(String[] args) throws IOException {

BufferedReader reader = new BufferedReader(new FileReader("path/to/english.txt"));
String s;
while ((s = reader.readLine()) != null)
if (CrackMe2.crc(s) == 38983) System.out.println(s);
reader.close();

}

}
I guess that's good enough for now. Maybe you can try and crack some TBS challs and get the smiley now :)

Friday, 23 November 2007

BF it!

Hey guys,

If you have been following my guide until now, probably you have known enough to start working with basic challenges. Let's get to some cracking. Today, I'll show you how to code a brute-force program.

I created this little crackme so we can have something to play with: CrackMe1. For simplicity, it's just a simple console application. If you run it, it will ask for a password and check if the password is correct.

Download the file and decompile it with jad, you'll see the code:

// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3)
// Source File Name: CrackMe1.java

import java.io.*;

public class CrackMe1
{

public CrackMe1()
{
}

public static boolean check(String s)
{
if(s.length() != 4)
return false;
int n = 1;
for(int i = 0; i < s.length(); i++)
n *= s.charAt(i);

n ^= s.hashCode();
return n == 0x705a69c;
}

public static void main(String args[])
throws IOException
{
System.out.print("Enter password: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
if(check(s))
System.out.println("Congrats!");
else
System.out.println("Go to hell!");
}
}

Good thing in Java all method names are meaningful. The code is self-explanation. The program reads a string from standard input, and check if it is the right password. The string must have a length of 4 characters. And if you take the product of the ASCII codes and xor with the hashCode of the string the result must be 0x705a69c (117810844).

Your first attempt to write a bf program should result in something like:

public class CrackMe1Solver {

public static boolean check(String s) {
// copy the decompiled code here
}

public static void main(String[] args) {

char[] c = new char[4];
// OK, let's assume the password is all lowercase
for (c[0] = 'a'; c[0] < 'z'; c[0]++)
for (c[1] = 'a'; c[1] < 'z'; c[1]++)
for (c[2] = 'a'; c[2] < 'z'; c[2]++)
for (c[3] = 'a'; c[3] < 'z'; c[3]++) {
// this is how you create a string from an array of characters
String s = new String(c);
if (check(s)) System.out.println(s);
}
}

}

This code works fine, try running it and you'll get the solution (a very famous word :P). However, that code is not the best. I'll show you how to make it better.

Firstly, it's kinda duplicate and inconvenient to use the same constants for bf range (a-z). A better practice is to declare them as constants so that you can change them easily. Thus:

// Constants are declared with the final keyword
// and conventionally written in uppercase
final char MIN = 'a';
final char MAX = 'z';
for (c[0] = MIN; c[0] < MAX; c[0]++)
...

One more thing, it's fortunate that the method check() is declared public and static. This means you can reuse it from another class instead of writing it again.

Here's the final code:

public class CrackMe1Solver {

public static void main(String[] args) {

char[] c = new char[4];
final char MIN = 'a';
final char MAX = 'z';
for (c[0] = MIN; c[0] < MAX; c[0]++)
for (c[1] = MIN; c[1] < MAX; c[1]++)
for (c[2] = MIN; c[2] < MAX; c[2]++)
for (c[3] = MIN; c[3] < MAX; c[3]++) {
String s = new String(c);
if (CrackMe1.check(s)) System.out.println(s);
}
}

}

Tuesday, 20 November 2007

Java control structures

Hey guys, today's lesson will be about Java control structures.

Just like other languages, Java has support for if-then-else, switch case, for loop and while loop.

Here is an example of an if-then-else:
if (x <= 1336) {
System.out.println("Too low!");
} else if (x >= 1338) {
System.out.println("Too high!");
} else {
System.out.println("You got it!");
}
Can you interpret the example? Every number less than or equal to 1336 is considered too low, and every number greater than or equal to 1338 is considered too high. A number between 1336 and 1338 (probably 1337 :P) is the right solution.

A few things you should remember:
- The if expression must be enclosed within round brackets () and it must return a boolean value.
- The curly brackets {} are optional if there is only 1 statements inside. However it is a good practice to always use them.

When you are comparing a variable against many values you can use a switch case instead of multiple if-then-else. Here's an example of switch case:
switch (x) {
case 1336:
System.out.println("A little too low!");
break;
case 1338:
System.out.println("A little too high!");
break;
case 1337:
System.out.println("You got it!");
break;
default:
System.out.println("So far :P");
break;
}
Note that the break is important. Without it the control flow will fall through to the next case.

Most of the time when working on a challenge you will need loops to do something repeatedly. In Java you can use 2 types of loop: for loop and while loop.

The for loop is usually used when counting is involved. For example, the following code prints all the numbers from 0 to 1337:
for (int i = 0; i <= 1337; i++)
System.out.println(i);
The for loop consists of 3 parts:
  • The first part (int i = 0) is the initialization. It initializes the value at the beginning of the loop.
  • The second part (i <= 1337) is the termination condition. When its value is false the loop will terminate.
  • The last part (i++) is the increment. After each iteration of the loop is done this statement will be executed once.
You can omit any part of the loop, as long as it won't lead to infinite loop :P If you want the loop to terminate under another condition you can use the break statement. The above example can be rewritten like this:
int i = 0;
for (;;) {
System.out.println(i);
if (i > 1337) break;
i++;
}
Basically you can do everything with just the for loop. But for convenience you might want to use the while loop too:
int i = 0;
while (i <= 1377) {
System.out.println(i);
i++;
}
Here is another variation of the while loop, with the condition checked at the end of each iteration:
int i = 0;
do {
System.out.println(i);
i++;
} while (i <= 1337);
You can use break inside while loops too:
int i = 0;
while(true) {
System.out.println(i);
i++;
if (i > 1337) break;
}

Saturday, 17 November 2007

Java basics: data types and operators

Hey guys, today I'll give you a quick view of Java data types and operators.

In Java, there are 3 main data types: primitive, object and array.
  • Primitive: byte, short, int, long, float, double, char and boolean. You can declare a primitive variable like this:
    int a = 1337;
    double b = 13.37;
    char c = '$';
    boolean d = true;
  • Object: Java is object-oriented, therefore you can see objects everywhere. Even string is a special type of object. You can declare an object with the keyword new:
    Object o = new Object();
    Applet a = new Applet();
    String s = new String("Hello world!");
    String t = "Hello world!"; // String is special, after all ;)
  • Array: Just like in other languages, you can use arrays in Java too. An array is declared with the keyword new, and you can use an index to access an array's member:
    int[] a = new int[2];
    a[0] = 13; // note that array indexes start at 0
    a[1] = 37;
    Object[] o = new Object[2]; // array of objects
    o[1] = "Hello worrd!";
    o[2] = new Integer(1);
    int[][] b = new int[2][2]; // multidimensional array
    b[0][0] = 1;
    b[0][1] = 3;
    b[1][0] = 3;
    b[1][1] = 7;
Here are some common operators that you can use on them:

+ (addition, also string concatenation), - (subtraction), * (multiplication).
/ division, note that it returns the integral quotient if applied between integral values.
% (modulo) returns the remainder in division.
= (assignment) assigns a value to a variable.
++ (increment) increments a variable by 1.
-- (decrement) decrements a variable by 1.
== (equal), != (not equal), < (less than), > (greater than), <= (less than or equal), >= (greater than or equal)
! (not operator for boolean)
&& (conditional and), || (conditional or)
bitwise operators: ~ (not), & (and), | (or), ^ (xor), << (shift left), >> (shift right), >>> (unsigned shift), you can see an explanation about them here.

Confused? Try using them in your program and see how they work. You can use the HelloWorld template in the previous lesson :)

Thursday, 15 November 2007

Hello world!

Hey guys,

Today I will teach you how to write your first program in Java, compile it, and then decompile with jad.

Open your favourite text editor, and type (or copy&paste) the following code:
public class Hello {

public static void main(String[] args) {

System.out.println("Hello world!");

}

}
Save the code as Hello.java, and open a console window. Navigate to the directory where you saved the file and execute the following command to compile the program:
javac Hello.java
Hopefully the program will be compiled without any errors. You'll notice that another file named Hello.class will be created in the same directory. To run it, type the following command:
java Hello
Of course, the program will run and output "Hello world!" :)

Congratulations, you have successfully written, compiled and executed your first Java program. It is very simple, but probably you can use it as a template for other programs in the future.

Now it's time to decompile it and see how the code looks like. From the console, type
jad Hello.class
A new file named Hello.jad will be created. Have a look at it
// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: Hello.java

import java.io.PrintStream;

public class Hello
{

public Hello()
{
}

public static void main(String args[])
{
System.out.println("Hello world!");
}
}
Almost the same as the original code. Cool huh? :)