THM: Reverse Engineering
The original challenge can be found at:https://tryhackme.com/room/reverseengineering
Task 2 - crackme2:
We get a binary called crackme1.bin. and should reverse the password that it asks us for.
If we want to know what kind of file this is we can simply look right into the header or use the file command that does basically the same but in a fancier way.
$ file crackme1.bin
crackme1.bin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3864320789154e8960133afdf58ddf65f6f8273d, not stripped
Or via the magic values represented in the header of the file
$ head -n 1 crackme1.bin
ELF>`@�@8 @@@@�888
$ readelf -a crackme1.bin
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
So this is a 64 Bit ELF file. This means it runs natively under *nix systems as Linux or Unix.
The simplest way to obtain the password is via strings.
$ strings crackme1.bin
...
hax0r
...
Which will give you all strings in that file. The obvious solution is right there behind the password statements.
Another approach is to look into the binary via objdump or start a debugger. As this is an ELF64 file the string is not located on the stack but rather in rodata section. Which is better analyzed via objedump or reversing tools.
Task 3 - crackme2:
The original challenge can be found at:https://tryhackme.com/room/reverseengineering
The second challenge is basically as easy as the first one. But this time there is no string stored. So lets find out how we can crack this one!
If we examine the file with a disassembler we get something like this:
0x00000738 call puts ; sym.imp.puts ; int puts(const char *s)
0x0000073d lea rax, [var_ch]
0x00000741 mov rsi, rax
0x00000744 lea rdi, [0x00000838] ; 2104 ; const char *format
0x0000074b mov eax, 0
0x00000750 call __isoc99_scanf ; sym.imp.__isoc99_scanf ; int scanf(const char *format)
0x00000755 mov eax, dword [var_ch]
0x00000758 cmp eax, 0x137c
0x0000075d jne 0x76d
What stands out that after the scanf call there is just a cmp (compare) followed by the jne instruction, which jumps dependent on the flags register. So the jump says which branch is taken, and the compare states what our input is compared to.
Therefore
cmp eax, 0x137c
In eax the reference to our input from scanf is stored. And 0x137c is just a hex value. The format parameter states that this is an integer (if we try chars, it would be only non-printable ones). So we just have to convert the hex value into an integer representation. This can be achieved with bc
$ echo 'ibase=16; 137C' | bc
4988
Well, this is it! We found the correct password.
Task 4 - crackme2:
The original challenge can be found at:https://tryhackme.com/room/reverseengineering
The last challenge is a bit more challenging :)
If we take a closer look, we see that the password is not compared as a whole, but rather Byte or Word wise. Luckily this time the password is stored on the stack. So it also can be found easily via the debugger.
The relevant disassembly:
0x00000731 mov word [var_23h], 0x7a61 ; 'az'
0x00000737 mov byte [var_21h], 0x74 ; 't'
0x0000073b lea rdi, str.enter_your_password ; 0x854 ; const char *s
0x00000742 call puts ; sym.imp.puts ; int puts(const char *s)
0x00000747 lea rax, [var_20h]
0x0000074b mov rsi, rax
0x0000074e lea rdi, [0x00000868] ; 2152 ; const char *format
0x00000755 mov eax, 0
0x0000075a call __isoc99_scanf ; sym.imp.__isoc99_scanf ; int scanf(const char *format)
0x0000075f mov dword [var_28h], 0
0x00000766 jmp 0x797
0x00000768 mov eax, dword [var_28h]
0x0000076b cdqe
0x0000076d movzx edx, byte [rbp + rax - 0x20]
0x00000772 mov eax, dword [var_28h]
0x00000775 cdqe
0x00000777 movzx eax, byte [rbp + rax - 0x23]
0x0000077c cmp dl, al
0x0000077e je 0x793
We can either follow the comparison loop or examine the arguments of the main function. And our input is basically compared to the 3 Bytes "azt" -- which is the password for this task.