B-Sides Jax 2015 - Reversing Via Example

From JaxHax
Jump to: navigation, search

Overview

Slides from a Reversing By Example presentation given at B-Sides Jax on 2015/11/21. The info in this wiki page is super high-level and not intended to explain or walk-through the challenges. Please view the slides for a more complete walk-through.

Downloads

Reversing By Example Slides (PDF file - 1.99 MB)
Reversing By Example Files (tar.gz file - 567 KB)


Useful Links

crackmes.de - A challenge site offering legal to reverse engineer challenge binaries
opensecuritytraining.info - Free security training online
Lenas Reversing for Newbies (windows based)
Hopper Disassembler Home Page
Bsides Jax Wiki


Example 1: simple_password.c

simple_password was written by Travis Phillips for this presentation. It can be solved simply using strings.

///////////////////////////////////////////////////////////////////
//
// Program: simple_password.c
//
// Author: Travis Phillips
//
// Date: 11/21/2015
//
// Purpose: Simple program that will take a password as an
//          argument and test if they gave the correct password. 
//          This program was designed to be a simple example for
//          a presentation at BsidesJax on 11/21/2015 on Reversing
//          by example. Presentation notes can be found on
//          http://wiki.jaxhax.org/index.php/B-Sides_Jax_2015_-_Reversing_Via_Example
//
///////////////////////////////////////////////////////////////////
#include <stdio.h>
 
////////////////////////////////////////
// main() will be ran when the program
// starts
////////////////////////////////////////
int main(int argc, char **argv){
 
	////////////////////////////////////////
	// print the banner.
	////////////////////////////////////////
	printf("\n\t..::[ Simple Password ]::..\n\n");
 
	////////////////////////////////////////
	// Check that the user provided a password.
	// if not, print program usage and exit. 
	////////////////////////////////////////
	if (argc != 2) {
		printf("\tUsage: %s <Password>\n\n", argv[0]);
		return 2;
	}
 
	////////////////////////////////////////
	// If they did, the let's see if it is
	// the same as our super strong hard
	// coded password.
	////////////////////////////////////////
	if (strcmp(argv[1], "ThisIs1StrongPassword!") == 0) {
		////////////////////////////////////////
		// If so, Then print Good User message! 
		////////////////////////////////////////
		printf("\t\033[32;1mGreat Job! :-)\n\n");
		return 0;
	} else {
		////////////////////////////////////////
		// If not, Then print Bad User message.
		////////////////////////////////////////
		printf("\t\033[31;1mNot Quite Right... :-/\n\n");
		return 1;
	}
 
}


Example 2: less_simple_password.c

less_simple_password was written by Travis Phillips for this presentation. This one attempts to hide the password by generating it at runtime by using math to build each character. This enables it to avoid strings, however it is still defeated using ltrace.

///////////////////////////////////////////////////////////////////
//
// Program: less_simple_password.c
//
// Author: Travis Phillips
//
// Date: 11/21/2015
//
// Purpose: Simple program that will take a password as an
//          argument and test if they gave the correct password. 
//          This program was designed to be a simple example for
//          a presentation at BsidesJax on 11/21/2015 on Reversing
//          by example. This example is almost like the program
//          simple_password.c, however an effort is made to hide the 
//          password by generating it at runtime via simple math. 
//          Presentation notes can be found on
//          http://wiki.jaxhax.org/index.php/B-Sides_Jax_2015_-_Reversing_Via_Example
//
///////////////////////////////////////////////////////////////////
#include <stdio.h>
 
////////////////////////////////////////
// main() will be ran when the program
// starts
////////////////////////////////////////
int main(int argc, char **argv) {
 
	////////////////////////////////////////
	// Create some variables for the passgen.
	// The the a, b, and c are to store numbers
	// for math ops. If we use static math problems
	// with numerical constants, the compiler will
	// solve them and just put the anwser instead.
	////////////////////////////////////////
	char pass[10]; // MyNewPass\x00 = 10 characters long
	int a = 0; // temp variable for math stuff
	int b = 0; // temp variable for math stuff
	int c = 0; // temp variable for math stuff
 
	////////////////////////////////////////
	// print the banner.
	////////////////////////////////////////
	printf("\n\t..::[ Less Simple Password ]::..\n\n");
 
	////////////////////////////////////////
	// Check that the user provided a password.
	// if not, print program usage and exit. 
	////////////////////////////////////////
    if (argc != 2) {
        printf("\tUsage: %s <Password>\n\n", argv[0]);
        return 2;
    }
	////////////////////////////////////////
	// Generate our string using math to 
	// generate each char and fill our 
	// pass[] array.
	////////////////////////////////////////
	a = 12;
	b = 3;
	c = 20;
	a = a + b + c;
	b = 40;
	c = 4;
	a = a + b + c;
	a -= 2;
	pass[0] = a; // M = 77
	a = 0x41;
	b = 0x38;
	pass[1] = a ^ b; // y = 121
	pass[2] = 78; // N = 78
	a = 100;
	b = 23;
	c = 22;
	pass[3] = a + b - c; // e = 101
	a = 115;
	b = 2;
	pass[4] = a + b + b; // w = 119
	a = 40;
	pass[5] = a * b; // P = 80
	a = 97;
	a -= 3;
	c = 1;
	pass[6] = a + b + c; // a = 97
	a = 10;
	c = 15;
	pass[7] = (a * a) + c; // s = 115
	b = 5;
	c = 3;
	pass[8] = (a * a) + (b * c); // s = 115
	a = 42;
	b = 42;
	pass[9] = a - b; // Null = 0
 
	////////////////////////////////////////
	// If they did, the let's see if it is
	// the same as our super hidden
	// password. The use of strcmp() weakens
	// our efforts however.
	////////////////////////////////////////
    if (strcmp(argv[1], pass) == 0) {
		////////////////////////////////////////
		// If so, Then print Good User message! 
		////////////////////////////////////////
        printf("\t\033[32;1mGreat Job! :-)\n\n");
        return 0;
    } else {
		////////////////////////////////////////
		// If not, Then print Bad User message.
		////////////////////////////////////////
        printf("\t\033[31;1mNot Quite Right... :-/\n\n");
        return 1;
    }
}


Example 3: josamont's j333

This example binary came from crackmes.de. This binary was written in assembly and was stripped. It was a simple find the password binary. After reversing the final flowchart looked something like this:

J333 flowchart.png


Example 4: ascii's kgm1

This example binary came from crackmes.de. This binary was written in c and was stripped. It was a keygenme. After reversing the final flowchart looked something like this:


AsciiKgm1LogicSimple.png


Using this information, it was possible to build a keygen using that would brute force a valid serial key using the following logic:


AsciiKgm1keygenLogic.png


Below is a GTK wrapped keygen using the above logic.

#!/usr/bin/env python
#####################################################################
#
# Script: ascii_kgm1_solution.py
#
# Author: Travis Phillips
#
# Date: 10/14/2015
#
# Purpose: This script is a keygen solution to solve ascii's kgm1
#          Challenge binary from crackmes.de.
#
# URL: http://www.crackmes.de/users/ascii/kgm1/
#
#####################################################################
import random
import pygtk
pygtk.require('2.0')
import gtk
 
class asciiKgm1KeyGen:
 
	####################################################################
	# Support Functions
	####################################################################
	###########################################################
	# This will return a key that has been xor'd against a 
	# static key that was found in the program.
	###########################################################
	def xorKey(self, key):
		xorkey = [0x45, 0x36, 0xab, 0xc8, 0xcc, 0x11, 0xe3, 0x7a]
		keyz = []
		for i in xrange(8):
			keyz.append(ord(key[i]) ^ xorkey[i])
		return keyz
 
	###########################################################
	# SignIt is a support function, This will check a byte and
	# determine if it should be negative or not... basically,
	# make a number act as a signed byte.
	###########################################################
	def SignIt(self, byte):
		if byte > 127:
			return (256-byte) * (-1)
		else:
			return byte
 
	###########################################################
	# The second part of the keygen was to add up all thee
	# xor'd bytes of the key. We and it by 0xff to basically 
	# emulate the 'movzx eax, cl' instruction...
	###########################################################
	def AddEm(self, xoredKey):
		total = 0
		for x in xoredKey:
			total += self.SignIt(x)
		return total & 0xff
 
	####################################################################
	# Callback Functions
	####################################################################
	def delete_event(self, widget, event, data=None):
		gtk.main_quit()
		return False
 
	###########################################################
	# Main Code - Basically we will brute force check a random
	# key till we find one that will pass the checks in the
	# challenge. Once we find one, we print it.
	###########################################################
	def GenerateKey(self, widget):
		while True:
			key = []
			for i in xrange(8):
				key.append(random.choice('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'))
			xoredKey = self.xorKey(key)
			endValue = self.AddEm(xoredKey)
			if endValue >= 0x61 and endValue <= 0x7A:
				self.txtbuf.set_text(''.join(key) + chr(endValue))
				break
 
 
	####################################################################
	# Window Building Functions
	####################################################################
	def CreateWindow(self, data=None):
		self.tooltips = gtk.Tooltips()
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_title("..::[ ascii kgm1 Keygen ]::..")
		self.window.connect("delete_event", self.delete_event)
		self.window.set_border_width(10)
		self.window.set_default_size(100, 75)
		self.window.set_position(gtk.WIN_POS_CENTER)
 
	def AddMainVBox(self, data=None):
		self.VboxMain = gtk.VBox(False, 0)
		self.window.add(self.VboxMain)
 
	def AddControls(self, data=None):
		self.txtView = gtk.TextView()
		self.txtView.set_editable(False)
		self.txtbuf = self.txtView.get_buffer()
		self.VboxMain.pack_start(self.txtView, False, False, 5)
		self.btnGenerate = gtk.Button("Generate Key")
		self.btnGenerate.connect("clicked", self.GenerateKey)
		self.VboxMain.pack_start(self.btnGenerate, False, False,5)
 
	def __init__(self):
		self.CreateWindow()
		self.AddMainVBox()
		self.AddControls()
		self.window.show_all()
 
def main():
    gtk.main()
 
if __name__ == "__main__":
    hello = asciiKgm1KeyGen()
    main()