EZ crackme

nameEZ crackme
categoryreversing
platformcrackmes.one
linkhttps://crackmes.one/crackme/5fcfb87933c5d424269a1afc
ctfn/a
descriptionn/a

file inspection

I started off by running file to determine the file type. The output was as follows:

> file run.exe
run.exe: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, with debug_info, not stripped

It’s a 32-bit ELF binary. Running readelf on it gives us interesting information about the sections especially .symtab (the Symbol Table):

> readelf -a run.exe
Section Headers:                                                                                                                                             
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        08049000 001000 000045 00  AX  0   0 16
  [ 2] .data             PROGBITS        0804a000 002000 00001d 00  WA  0   0  4
  [ 3] .debug_aranges    PROGBITS        00000000 00201d 000020 00      0   0  1
  [ 4] .debug_info       PROGBITS        00000000 00203d 00003a 00      0   0  1
  [ 5] .debug_abbrev     PROGBITS        00000000 002077 00001b 00      0   0  1
  [ 6] .debug_line       PROGBITS        00000000 002092 00004a 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 0020dc 000140 10      8  16  4
  [ 8] .strtab           STRTAB          00000000 00221c 000076 00      0   0  1
  [ 9] .shstrtab         STRTAB          00000000 002292 00005c 00      0   0  1


Symbol table '.symtab' contains 20 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 08049000     0 SECTION LOCAL  DEFAULT    1 
     2: 0804a000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 SECTION LOCAL  DEFAULT    6 
     7: 00000000     0 FILE    LOCAL  DEFAULT  ABS code.asm
     8: 0804900e     0 NOTYPE  LOCAL  DEFAULT    1 _start.goodjob
     9: 08049026     0 NOTYPE  LOCAL  DEFAULT    1 _start.wrong
    10: 0804903c     0 NOTYPE  LOCAL  DEFAULT    1 _start.end
    11: 0804a000     1 OBJECT  LOCAL  DEFAULT    2 password
    12: 0804a008     1 OBJECT  LOCAL  DEFAULT    2 goodjobText
    13: 0000000e     0 NOTYPE  LOCAL  DEFAULT  ABS goodjobLen
    14: 0804a016     1 OBJECT  LOCAL  DEFAULT    2 nope
    15: 00000007     0 NOTYPE  LOCAL  DEFAULT  ABS nopeLen
    16: 08049000     0 NOTYPE  GLOBAL DEFAULT    1 _start
    17: 0804a01d     0 NOTYPE  GLOBAL DEFAULT    2 __bss_start
    18: 0804a01d     0 NOTYPE  GLOBAL DEFAULT    2 _edata
    19: 0804a020     0 NOTYPE  GLOBAL DEFAULT    2 _end

disassembly

Moving on to disassembling the program, I used objdump.

> objdump -M intel -d run.exe
run.exe:     file format elf32-i386

Disassembly of section .text:

08049000 <_start>:
 8049000:       5b                      pop    ebx
 8049001:       5b                      pop    ebx
 8049002:       5b                      pop    ebx
 8049003:       a1 00 a0 04 08          mov    eax,ds:0x804a000
 8049008:       3b 03                   cmp    eax,DWORD PTR [ebx]
 804900a:       74 02                   je     804900e <_start.goodjob>
 804900c:       eb 18                   jmp    8049026 <_start.wrong>

0804900e <_start.goodjob>:
 804900e:       b8 04 00 00 00          mov    eax,0x4
 8049013:       bb 01 00 00 00          mov    ebx,0x1
 8049018:       b9 08 a0 04 08          mov    ecx,0x804a008
 804901d:       ba 0e 00 00 00          mov    edx,0xe
 8049022:       cd 80                   int    0x80
 8049024:       eb 16                   jmp    804903c <_start.end>

08049026 <_start.wrong>:
 8049026:       b8 04 00 00 00          mov    eax,0x4
 804902b:       bb 01 00 00 00          mov    ebx,0x1
 8049030:       b9 16 a0 04 08          mov    ecx,0x804a016
 8049035:       ba 07 00 00 00          mov    edx,0x7
 804903a:       cd 80                   int    0x80

0804903c <_start.end>:
 804903c:       b8 01 00 00 00          mov    eax,0x1
 8049041:       31 db                   xor    ebx,ebx
 8049043:       cd 80                   int    0x80

It’s a simple program which starts off by comparing an initialized variable in the data segment (ds) with an argument. Based on the result of the cmp (compare) operation, it executes the write syscall to write a message to stdout (file descriptor 1). So now, the C program would look something like this:

if (arg == *0x804a000){
	write(1, *0x804a008, 0xe);	
}
else {
	write(1, *0x804a016, 0x7);
}

The Linux Man page for the write syscall explains each argument. But it’s still pretty self explanatory—

write(int fd, const void *buf, size_t count);

exploitation

We now know where to look for our secret string. Firing up radare2:

> r2 run.exe
[0x08049000]> s 0x804a000
[0x0804a000]> px
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x0804a000  5034 3535 7730 7264 596f 7520 476f 7420  P455w0rdYou Got 
0x0804a010  5468 6973 210a 5772 6f6e 6721 0aff ffff  This!.Wrong!....
0x0804a020  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a030  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a040  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a050  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a060  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a070  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a080  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a090  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0a0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0b0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0c0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0d0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0e0  ffff ffff ffff ffff ffff ffff ffff ffff  ................
0x0804a0f0  ffff ffff ffff ffff ffff ffff ffff ffff  ................

Looks like we found our key! P455w0rd. Running the binary with P455w0rd as an argument:

> ./run.exe P455w0rd
You Got This!

However, the compare instruction is done with a DWORD, i.e 4 bytes. So the key is P455.

> ./run.exe P455    
You Got This!