- Prison Code Breaker Diary -

=> aka: Nhật Kí Code Tù

Categories

Today, we will learn a new widget control, GtkEntry, a text editor. It's a text box that users can input text inside.
Reference GtkEntry

I'm not gonna explain each properties and methods in details anymore. However, to practice directly is the better way of learning it since you've already familiar with Gtk+ programming.

Practice 1: A simple one, a label will show up everything you type in the entry box when clicking a button.



/*
* @author [JaPh]
* @date 30 August, 2009
* @file GtkEntry_01.c
* @site http://xjaphx.blogspot.com/
*/

#include <gtk/gtk.h>
#include <glib.h>
typedef struct _STORE {
GtkLabel *label;
GtkEntry *entry;
} STORE;

void
btn_get_clicked_event( GtkButton *btn_get, STORE *data )
{
gtk_label_set_text( data->label, gtk_entry_get_text(data->entry));
}

int
main( int argc, char *argv[] )
{
GtkWidget *window;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *btn_get;
GtkWidget *vbox;
STORE *data;

gtk_init( &argc, &argv );

window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_title( GTK_WINDOW(window), "[JaPh]Lesson 13: GtkEntry" );
gtk_window_set_default_size( GTK_WINDOW(window), 100, 100 );

label = gtk_label_new("Type anything to entry below: ");
btn_get = gtk_button_new_with_mnemonic("_Get");
entry = gtk_entry_new_with_max_length( 128 );

vbox = gtk_vbox_new( TRUE, 5 );

gtk_box_pack_start( GTK_BOX(vbox), label, TRUE, TRUE, 5);
gtk_box_pack_start( GTK_BOX(vbox), entry, TRUE, TRUE, 5);
gtk_box_pack_start( GTK_BOX(vbox), btn_get, TRUE, TRUE, 5);

data = (STORE *) g_malloc( sizeof (STORE) );
data->label = GTK_LABEL(label);
data->entry = GTK_ENTRY(entry);

gtk_container_add( GTK_CONTAINER(window), vbox);

g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK( gtk_main_quit ), NULL );
g_signal_connect( GTK_BUTTON(btn_get), "clicked",
G_CALLBACK( btn_get_clicked_event ), data );


gtk_widget_show_all( window );
gtk_main();
g_free( data );
return 0;
}

Practice 2: How about a login dialog !




/*
* @author [JaPh]
* @date 30 August, 2009
* @file GtkEntry_02.c
* @site http://xjaphx.blogspot.com/
*/

#include <gtk/gtk.h>
#include <string.h>
#include <glib.h>

typedef struct _DATA {
GtkWidget *widget;
struct _DATA *next;
} DATA;

const char *username = "[JaPh]";
const char *password = "Lesson 14";

void
MessageBox( GtkMessageType type, const char *title, const char *message, const char* details )
{
int res;
GtkWidget *message_box;
message_box = gtk_message_dialog_new( NULL,
GTK_DIALOG_DESTROY_WITH_PARENT,
type, GTK_BUTTONS_OK,
message );

gtk_window_set_title( GTK_WINDOW(message_box), "[JaPh]Lesson 14: GtkEntry" );
gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG(message_box), details );

res = gtk_dialog_run( GTK_DIALOG(message_box));
if( res == GTK_RESPONSE_OK ) {
gtk_widget_destroy( message_box );
}
}

void
btn_login_clicked_event( GtkButton *btn_login, DATA *data )
{
if( !strcmp( username, gtk_entry_get_text( data->widget ) ) &&
!strcmp( password, gtk_entry_get_text( data->next->widget )) )
{
MessageBox( GTK_MESSAGE_INFO, "Congratulations!", "Correct!",
"Username and password are correct." );
} else {
MessageBox( GTK_MESSAGE_ERROR, "Fail ", "Incorrect",
"Username and password are incorrect." );
}
}


int
main( int argc, char *argv[] )
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox_user, *hbox_pass, *hbox_button;
GtkWidget *lbl_user, *lbl_pass;
GtkWidget *txt_user, *txt_pass;
GtkWidget *btn_login, *btn_exit;
DATA *data;

gtk_init( &argc, &argv );

window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_title( GTK_WINDOW(window), "[JaPh]Lesson 14: GtkEntry" );
gtk_window_set_default_size( GTK_WINDOW(window), 100, 100 );

lbl_user = gtk_label_new("Username: ");
txt_user = gtk_entry_new();
hbox_user = gtk_hbox_new(TRUE, 5);
gtk_box_pack_start( GTK_BOX(hbox_user), lbl_user, TRUE,TRUE, 5);
gtk_box_pack_start( GTK_BOX(hbox_user), txt_user, TRUE,TRUE, 5);

lbl_pass = gtk_label_new("Password: ");
txt_pass = gtk_entry_new();
/* set invisible character */
gtk_entry_set_invisible_char( GTK_ENTRY(txt_pass), '*' );
/* activate the invisibility mode */
gtk_entry_set_visibility( GTK_ENTRY( txt_pass ), FALSE );
hbox_pass = gtk_hbox_new( TRUE, 5);
gtk_box_pack_start( GTK_BOX(hbox_pass), lbl_pass, TRUE, TRUE, 5);
gtk_box_pack_start( GTK_BOX(hbox_pass), txt_pass, TRUE, TRUE, 5);

btn_login = gtk_button_new_with_mnemonic("_Login");
btn_exit = gtk_button_new_with_mnemonic("E_xit");
hbox_button = gtk_hbox_new( TRUE, 5);
gtk_box_pack_start( GTK_BOX(hbox_button), btn_login, FALSE, TRUE, 20);
gtk_box_pack_start( GTK_BOX(hbox_button), btn_exit, FALSE, TRUE, 20);

vbox = gtk_vbox_new( TRUE, 0);
gtk_box_pack_start( GTK_BOX(vbox), hbox_user, TRUE, TRUE, 0);
gtk_box_pack_start( GTK_BOX(vbox), hbox_pass, TRUE, TRUE, 0);
gtk_box_pack_start( GTK_BOX(vbox), hbox_button, TRUE, TRUE, 0);

data = (DATA *) g_malloc( sizeof( DATA ));
data->widget = txt_user;
data->next = (DATA *) g_malloc( sizeof( DATA ));
data->next->widget = txt_pass;
data->next->next = NULL;

gtk_container_add( GTK_CONTAINER(window), vbox);

g_signal_connect( G_OBJECT(window), "destroy",
G_CALLBACK( gtk_main_quit ), NULL );

g_signal_connect( GTK_BUTTON(btn_login), "clicked",
G_CALLBACK( btn_login_clicked_event ), data );
g_signal_connect( G_OBJECT(btn_exit), "clicked",
G_CALLBACK( gtk_main_quit ), NULL );

gtk_widget_show_all( window );
gtk_main();
g_free(data);
return 0;
}

Well, not much to say but I'm going to create several special sessions next on Gtk+ programming. Make sure you understand all the basics of Gtk+.

Have fun!@

[ Crackme Info ]
Difficulty: 1 - Very easy, for newbies
Platform: Unix/linux etc.
Language: Assembler
Refer: click here
Click to Download

Load into IDA, we have the main program


.text:08048085 mov ebx, 1 ; fd
.text:0804808A mov ecx, offset aPassword ; "\nPassword : "
.text:0804808F mov edx, 0Dh ; len
.text:08048094 int 80h ; LINUX - sys_write
.text:08048096 mov edx, 100h ; len
.text:0804809B mov ecx, offset asc_804911B ; " "
.text:080480A0 mov ebx, 0 ; fd
.text:080480A5 mov eax, 3
.text:080480AA int 80h ; LINUX - sys_read
.text:080480AC mov esi, offset aQtbxctu ; "QTBXCTU"
.text:080480B1 mov edi, esi
.text:080480B3 xor ebx, ebx
.text:080480B5 cld
.text:080480B6
.text:080480B6 loc_80480B6: ; CODE XREF: start+43j
.text:080480B6 lodsb
.text:080480B7 xor al, 21h
.text:080480B9 stosb
.text:080480BA inc ebx
.text:080480BB cmp ebx, 7
.text:080480C1 jz short loc_80480C5
.text:080480C3 loop loc_80480B6
.text:080480C5
.text:080480C5 loc_80480C5: ; CODE XREF: start+41j
.text:080480C5 mov esi, offset asc_804911B ; " "
.text:080480CA mov edi, offset aQtbxctu ; "QTBXCTU"
.text:080480CF mov ecx, 7
.text:080480D4 cld
.text:080480D5 repe cmpsb
.text:080480D7 jnz short loc_80480EF
.text:080480D9 mov eax, 4
.text:080480DE mov ebx, 1 ; status
.text:080480E3 mov ecx, offset unk_8049105 ; addr
.text:080480E8 mov edx, 16h ; len
.text:080480ED int 80h ; LINUX - sys_write
.text:080480EF
.text:080480EF loc_80480EF: ; CODE XREF: start+57j
.text:080480EF mov eax, 1
.text:080480F4 int 80h ; LINUX - sys_exit
.text:080480F4 start endp
.text:080480F4
.text:080480F4 _text ends
.text:080480F4

Each bytes of our input password is encrypted:

.text:080480B6 loc_80480B6: ; CODE XREF: start+43j
.text:080480B6 lodsb
.text:080480B7 xor al, 21h
.text:080480B9 stosb
.text:080480BA inc ebx
.text:080480BB cmp ebx, 7
.text:080480C1 jz short loc_80480C5
.text:080480C3 loop loc_80480B6

So, the real password can be found if we decrypt the string "QTBXCTU".
The encryption is simple, each byte is XORed w/ 0x21.
Then, we also use XORed w/ 0x21 to decrypt it.
Here a little perl script I wrote to decrypt.

#!/usr/bin/perl
my $cipher_txt = "QTBXCTU";
my $plain_txt;

my @arr = unpack("C*", $cipher_txt);
foreach my $c (@arr) {
$plain_txt .= chr( $c ^ 0x21 );
}

print $plain_txt, "\n";


Have fun!@

This is my little video guide through the wargame of SmashTheStack.Org

Wargame: SmashTheStack.Org | IO | Level 5
Creator: [JaPh]
Video: [ OGV | Length: 18.08 min | 72.1 MB | Super High Quality ]
Download: Rapidshare
Password: [japh]

Have fun!@

I use these crackmes as a practice for reversing and debugging skills. However, any time I solve a crackme, I make a post as a guide for those who have the same interest as me and have troubles with them.
These crackmes are dedicated to run under Linux environment only, not Windows.
I collect these crackmes on crackmes.de site, so I can visit that site and check out for information.
Hope this would be helpful to someone.

[Level: EASIEST, FOR NEWBIES ONLY]

Guide to crack "Easy Linux Crackme" by lord
Solve cyrex's Linux CrackMe
Solve cyrex's Linux Crackme02
Solve dynsym's Crackme
Solve intsig's Easymath
Solve Qnix's qcrk5
Solve cli3nt's mycrk
Solve lord's Easy Crackme 2

[ to be updated...]

Have fun!@

==:: Crackme Info ::==
Difficulty: 1 - Very easy, for newbies
Platform: Unix/linux etc.
Language: C/C++
Refer: click here
Click to Download

Use GDB to disassemble the main function


0x080483c4 <main+0>: push %ebp
0x080483c5 <main+1>: mov %esp,%ebp
0x080483c7 <main+3>: sub $0x18,%esp
0x080483ca <main+6>: and $0xfffffff0,%esp
0x080483cd <main+9>: mov $0x0,%eax
0x080483d2 <main+14>: sub %eax,%esp
0x080483d4 <main+16>: movl $0x11e67,-0x4(%ebp)
0x080483db <main+23>: movl $0x5b1270,-0x8(%ebp)
0x080483e2 <main+30>: movl $0x6,-0x10(%ebp)
0x080483e9 <main+37>: sub $0xc,%esp
0x080483ec <main+40>: push $0x8048514
0x080483f1 <main+45>: call 0x80482e4 <printf@plt>
0x080483f6 <main+50>: add $0x10,%esp
0x080483f9 <main+53>: sub $0x8,%esp
0x080483fc <main+56>: lea -0xc(%ebp),%eax
0x080483ff <main+59>: push %eax
0x08048400 <main+60>: push $0x8048522
0x08048405 <main+65>: call 0x80482c4 <scanf@plt>
0x0804840a <main+70>: add $0x10,%esp
0x0804840d <main+73>: mov -0x8(%ebp),%eax
0x08048410 <main+76>: cmp -0xc(%ebp),%eax
0x08048413 <main+79>: jne 0x8048432 <main+110>
0x08048415 <main+81>: mov -0x10(%ebp),%edx
0x08048418 <main+84>: lea -0x4(%ebp),%eax
0x0804841b <main+87>: xor %edx,(%eax)
0x0804841d <main+89>: sub $0x8,%esp
0x08048420 <main+92>: pushl -0x4(%ebp)
0x08048423 <main+95>: push $0x8048525
0x08048428 <main+100>: call 0x80482e4 <printf@plt>
0x0804842d <main+105>: add $0x10,%esp
0x08048430 <main+108>: jmp 0x8048442 <main+126>
0x08048432 <main+110>: sub $0xc,%esp
0x08048435 <main+113>: push $0x8048529
0x0804843a <main+118>: call 0x80482e4 <printf@plt>
0x0804843f <main+123>: add $0x10,%esp
0x08048442 <main+126>: mov $0x0,%eax
0x08048447 <main+131>: leave
0x08048448 <main+132>: ret

So,
[ebp-4] = 0x11E67
[ebp-8] = 0x5b1270
[ebp-c] is our input key

the comparison check

0x0804840d <main+73>: mov -0x8(%ebp),%eax
0x08048410 <main+76>: cmp -0xc(%ebp),%eax
0x08048413 <main+79>: jne 0x8048432 <main+110>

So easy, the real key is hardcoded, and it is at [ebp-8] = 0x5b1270, which is 5968496 in decimal.
If equal, the [ebp-4] is calculated

0x08048415 <main+81>: mov -0x10(%ebp),%edx
0x08048418 <main+84>: lea -0x4(%ebp),%eax
0x0804841b <main+87>: xor %edx,(%eax)

After XOR, the value of eax is 0x11E61, which is 73313 in decimal.
If wrong, the message "wrong" is output.
This is a good easy crackme for newbie.

Have fun!@

==:: Crackme Info ::==
Difficulty: 1 - Very easy, for newbies
Platform: Unix/linux etc.
Language: C/C++
Refer: click me
Click to Download

This crackme is in fact pretty tough for beginner, like me gigitjari. Since it's built in static mode, everything's just look very confusing.
I will use IDA, then go to the Entry Point of main function.
Here it is


.text:08048208
.text:08048208 ; Attributes: bp-based frame
.text:08048208
.text:08048208 sub_8048208 proc near ; DATA XREF: start+17o
.text:08048208
.text:08048208 var_28 = dword ptr -28h
.text:08048208 var_24 = dword ptr -24h
.text:08048208 var_20 = dword ptr -20h
.text:08048208 var_1C = dword ptr -1Ch
.text:08048208 var_14 = dword ptr -14h
.text:08048208 var_8 = dword ptr -8
.text:08048208 var_4 = dword ptr -4
.text:08048208 arg_0 = dword ptr 8
.text:08048208 arg_4 = dword ptr 0Ch
.text:08048208
.text:08048208 push ebp
.text:08048209 mov ebp, esp
.text:0804820B sub esp, 28h
.text:0804820E and esp, 0FFFFFFF0h
.text:08048211 mov eax, 0
.text:08048216 add eax, 0Fh
.text:08048219 add eax, 0Fh
.text:0804821C shr eax, 4
.text:0804821F shl eax, 4
.text:08048222 sub esp, eax
.text:08048224 mov [ebp+var_4], 4B7F3DA0h
.text:0804822B mov [esp+28h+var_1C], 0
.text:08048233 mov [esp+28h+var_20], 1
.text:0804823B mov [esp+28h+var_24], 0
.text:08048243 mov [esp+28h+var_28], 0
.text:0804824A call sub_804EA50
.text:0804824F test eax, eax
.text:08048251 jns short loc_8048260
.text:08048253 mov eax, 1
.text:08048258 mov [ebp+var_14], eax
.text:0804825B jmp loc_8048335
.text:08048260 ; ---------------------------------------------------------------------------
.text:08048260
.text:08048260 loc_8048260: ; CODE XREF: sub_8048208+49j
.text:08048260 cmp [ebp+arg_0], 2
.text:08048264 jz short loc_8048291
.text:08048266 mov eax, [ebp+arg_4]
.text:08048269 mov eax, [eax]
.text:0804826B mov edx, off_80AF3B4
.text:08048271 mov [esp+28h+var_20], eax
.text:08048275 mov [esp+28h+var_24], offset aUsageSPassword ; "Usage : %s \n"
.text:0804827D mov [esp+28h+var_28], edx
.text:08048280 call sub_8049530
.text:08048285 mov [esp+28h+var_28], 0
.text:0804828C call sub_8048C10
.text:08048291 ; ---------------------------------------------------------------------------
.text:08048291
.text:08048291 loc_8048291: ; CODE XREF: sub_8048208+5Cj
.text:08048291 mov eax, [ebp+arg_4]
.text:08048294 add eax, 4
.text:08048297 mov eax, [eax]
.text:08048299 mov [esp+28h+var_28], eax
.text:0804829C call sub_8048BE0
.text:080482A1 mov [ebp+var_8], eax
.text:080482A4 lea eax, [ebp+var_8]
.text:080482A7 add dword ptr [eax], 5
.text:080482AA lea eax, [ebp+var_8]
.text:080482AD add dword ptr [eax], 60h
.text:080482B0 mov edx, [ebp+var_8]
.text:080482B3 mov eax, edx
.text:080482B5 shl eax, 8
.text:080482B8 sub eax, edx
.text:080482BA mov [ebp+var_8], eax
.text:080482BD mov eax, [ebp+var_8]
.text:080482C0 imul eax, 909090h
.text:080482C6 mov [ebp+var_8], eax
.text:080482C9 mov eax, [ebp+arg_4]
.text:080482CC add eax, 4
.text:080482CF mov eax, [eax]
.text:080482D1 mov edx, off_80AF3B4
.text:080482D7 mov [esp+28h+var_20], eax
.text:080482DB mov [esp+28h+var_24], offset aUsingS ; "Using %s\n"
.text:080482E3 mov [esp+28h+var_28], edx
.text:080482E6 call sub_8049530
.text:080482EB mov eax, [ebp+var_4]
.text:080482EE cmp eax, [ebp+var_8]
.text:080482F1 jnz short loc_8048314
.text:080482F3 mov eax, off_80AF3B4
.text:080482F8 mov [esp+28h+var_24], offset aCorrectCracked ; "Correct, Cracked !!\n"
.text:08048300 mov [esp+28h+var_28], eax
.text:08048303 call sub_8049530
.text:08048308 mov [esp+28h+var_28], 0
.text:0804830F call sub_8048C10
.text:08048314 ; ---------------------------------------------------------------------------
.text:08048314
.text:08048314 loc_8048314: ; CODE XREF: sub_8048208+E9j
.text:08048314 mov eax, off_80AF3B4
.text:08048319 mov [esp+28h+var_24], offset aWrong ; "Wrong!\n"
.text:08048321 mov [esp+28h+var_28], eax
.text:08048324 call sub_8049530
.text:08048329 mov [esp+28h+var_28], 0
.text:08048330 call sub_8048C10
.text:08048335 ; ---------------------------------------------------------------------------
.text:08048335
.text:08048335 loc_8048335: ; CODE XREF: sub_8048208+53j
.text:08048335 mov eax, [ebp+var_14]
.text:08048338 leave
.text:08048339 retn
.text:08048339 sub_8048208 endp
.text:08048339
.text:08048339 ;

This is where the input is compared

.text:080482EB mov eax, [ebp+var_4]
.text:080482EE cmp eax, [ebp+var_8]
.text:080482F1 jnz short loc_8048314

There have 2 solutions here as usual: Patch & Keygen

1. Patch:
- Just do this as a practice since author doesn't allow patching. For beginners, it's good to know how to patch as well.
- We patch the Jump at 0x080482F1 from: 75 21 to: 90 90

2. Keygen:
- Look at the code flow, you can see [ebp+var_4] doesn't change in main. Its value is assigned at beginning:

.text:08048224 mov [ebp+var_4], 4B7F3DA0h

- The translation of disassembly part

.text:08048291 mov eax, [ebp+arg_4]
.text:08048294 add eax, 4
.text:08048297 mov eax, [eax]
.text:08048299 mov [esp+28h+var_28], eax
.text:0804829C call sub_8048BE0 ; atoi( argv[1] )
.text:080482A1 mov [ebp+var_8], eax ; var_8 = atoi( arv[1] )
.text:080482A4 lea eax, [ebp+var_8] ; eax = var_8
.text:080482A7 add dword ptr [eax], 5 ; eax += 5
.text:080482AA lea eax, [ebp+var_8]
.text:080482AD add dword ptr [eax], 60h ; eax += 60
.text:080482B0 mov edx, [ebp+var_8] ; edx = var_8
.text:080482B3 mov eax, edx ; eax = edx
.text:080482B5 shl eax, 8 ; eax <<= 8
.text:080482B8 sub eax, edx ; eax = eax - edx
.text:080482BA mov [ebp+var_8], eax
.text:080482BD mov eax, [ebp+var_8] ; eax = var_8
.text:080482C0 imul eax, 909090h ; eax = eax * 909090
.text:080482C6 mov [ebp+var_8], eax ; var_8 = eax
.text:080482C9 mov eax, [ebp+arg_4]
.text:080482CC add eax, 4
.text:080482CF mov eax, [eax]
.text:080482D1 mov edx, off_80AF3B4
.text:080482D7 mov [esp+28h+var_20], eax
.text:080482DB mov [esp+28h+var_24], offset aUsingS ; "Using %s\n"
.text:080482E3 mov [esp+28h+var_28], edx
.text:080482E6 call sub_8049530
.text:080482EB mov eax, [ebp+var_4] ; var_4 = 4B7F3DA0
.text:080482EE cmp eax, [ebp+var_8] ; var_8
.text:080482F1 jnz short loc_8048314

Here is the simple keygen written in C

#include <stdio.h>

unsigned int
compute( unsigned int i )
{
register unsigned int x, y;
x = y = (i + 0x65);
x <<= 8;
x -= y;
x *= 0x909090;
return x;
}

int
main( int argc, char *argv[] )
{
unsigned int i = 0;
const int TARGET = 0x4B7F3DA0;
while( i < 0xFFFFFFFF ) {
if( compute(i) == TARGET ) {
printf("[+] Found: %u \n", i);
}
++i;
}
return 0;
}

Have fun!@

==:: Crackme Info ::==
Difficulty: 1 - Very easy, for newbies
Platform: Unix/linux etc.
Language: C/C++
Refer: click here
Click to Download

The crackme will only print 'done' message if we get the correct password only.
This crackme seems to be very complicated. If you try to dump it with Dasm2 or load through GDB, it certainly doesn't work at all.
We use readelf to look at its header information


$ readelf -e easymath
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048380
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0 <corrupt: out of range>

There are no sections in this file.

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00644 0x00644 R E 0x1000
LOAD 0x000644 0x08049644 0x08049644 0x00110 0x00114 RW 0x1000
DYNAMIC 0x000658 0x08049658 0x08049658 0x000c8 0x000c8 RW 0x4
NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4

It's not looking good at all.
Let's load it with IDA. Here a little view:


Jump to entry point of program: Ctrl+E -> start

LOAD:08048380 ; Attributes: noreturn
LOAD:08048380
LOAD:08048380 public start
LOAD:08048380 start proc near
LOAD:08048380 xor ebp, ebp
LOAD:08048382 pop esi
LOAD:08048383 mov ecx, esp
LOAD:08048385 and esp, 0FFFFFFF0h
LOAD:08048388 push eax
LOAD:08048389 push esp
LOAD:0804838A push edx
LOAD:0804838B push offset sub_8048580
LOAD:08048390 push offset sub_8048510
LOAD:08048395 push ecx
LOAD:08048396 push esi
LOAD:08048397 push offset sub_8048438
LOAD:0804839C call sub_8048344
LOAD:080483A1 hlt
LOAD:080483A1 start endp

So, the OEP of main() is call

LOAD:08048397 push offset sub_8048438

Jump to main() [G: 8048438]

Scroll down a bit:

LOAD:0804849E loc_804849E: ; CODE XREF: sub_8048438+47j
LOAD:0804849E mov [ebp+var_10], 6
LOAD:080484A5 mov [ebp+var_C], 2
LOAD:080484AC mov [ebp+var_8], 0
LOAD:080484B3 mov [ebp+var_4], 4530h
LOAD:080484BA mov eax, [ebp+arg_4]
LOAD:080484BD add eax, 4
LOAD:080484C0 mov eax, [eax]
LOAD:080484C2 sub esp, 0Ch
LOAD:080484C5 push eax
LOAD:080484C6 call sub_8048354
LOAD:080484CB add esp, 10h
LOAD:080484CE mov [ebp+var_14], eax
LOAD:080484D1 nop
LOAD:080484D2 mov eax, [ebp+var_10]
LOAD:080484D5 mov edx, eax
LOAD:080484D7 imul edx, [ebp+var_C]
LOAD:080484DB mov eax, [ebp+var_14]
LOAD:080484DE imul eax, edx
LOAD:080484E1 mov [ebp+var_8], eax
LOAD:080484E4 xor eax, eax
LOAD:080484E6 mov eax, [ebp+var_4]
LOAD:080484E9 cmp eax, [ebp+var_8]
LOAD:080484EC jnz short loc_80484FE
LOAD:080484EE sub esp, 0Ch
LOAD:080484F1 push offset aDone ; "done"
LOAD:080484F6 call sub_8048324
LOAD:080484FB add esp, 10h

So, the comparison is at: 0x080484E9 and the jump is below.
There're two ways to solve this problem: Patch & KeyGen

1. Patch:
- We will NOP at the jump. The offset of the jump is at 0x4EC
- Load hexedit

$ hexedit easymath

Press {Enter} then type the offset: 0x4EC
- We patch 2 bytes: 75 10 into 90 90
F2 to save then F10 (or Ctrl+X) to quit.
- Run crackme with any-value argument

2. Keygen:
- Take a closer look at disassembly code above, I explain them like this:


LOAD:0804849E mov [ebp+var_10], 6 ; var_10 = 6
LOAD:080484A5 mov [ebp+var_C], 2 ; var_C = 2
LOAD:080484AC mov [ebp+var_8], 0 ; var_8 = 0
LOAD:080484B3 mov [ebp+var_4], 4530h ; var_4 = 4530
LOAD:080484BA mov eax, [ebp+arg_4]
LOAD:080484BD add eax, 4
LOAD:080484C0 mov eax, [eax]
LOAD:080484C2 sub esp, 0Ch
LOAD:080484C5 push eax
LOAD:080484C6 call sub_8048354 ; atoi( argv[1] )
LOAD:080484CB add esp, 10h
LOAD:080484CE mov [ebp+var_14], eax ; var_14 = atoi( argv[1] )
LOAD:080484D1 nop
LOAD:080484D2 mov eax, [ebp+var_10] ; eax = var_10 = 6
LOAD:080484D5 mov edx, eax ; edx = eax = 6
LOAD:080484D7 imul edx, [ebp+var_C] ; edx = edx * var_C = 6 * 2 = C
LOAD:080484DB mov eax, [ebp+var_14] ; eax = var_14
LOAD:080484DE imul eax, edx ; eax = eax * edx = var_14 * C
LOAD:080484E1 mov [ebp+var_8], eax ; var_8 = eax = var_14 * C
LOAD:080484E4 xor eax, eax ; eax = 0
LOAD:080484E6 mov eax, [ebp+var_4] ; eax = var_4
LOAD:080484E9 cmp eax, [ebp+var_8] ; eax == var_8 ?
LOAD:080484EC jnz short loc_80484FE ; 0x080484EC if true : 0x80484FE else
LOAD:080484EE sub esp, 0Ch
LOAD:080484F1 push offset aDone ; "done"
LOAD:080484F6 call sub_8048324
LOAD:080484FB add esp, 10h

As you can see, var_14 is our input as argv[1]. So it must be the number N that satisfies the equation: N * C = 4530 (in hex).
So, N = 5C4 or 1476 in decimal.
Try it

$ ./easymath 1476
done

That's all for this crackme.

Have fun!@