Hackthebox challenge writeup - Find the easypass
Introduction
This is my first reversing challenge. I have no idea what I am up for.
The challenge start with the download of a .zip file, so I guess we are going to crack it open in a way.
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ zip2john findtheeasypass.zip > output.txt
ver 2.0 findtheeasypass.zip/EasyPass.exe PKZIP Encr: cmplen=210117, decmplen=402432, crc=BC1E0C86
Let as also use the unzip and zipdetails tools to see whats inside this archive:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ unzip -lv findtheeasypass.zip
Archive: findtheeasypass.zip
Length Method Size Cmpr Date Time CRC-32 Name
-------- ------ ------- ---- ---------- ----- -------- ----
402432 Defl:N 210105 48% 2017-07-03 10:12 bc1e0c86 EasyPass.exe
-------- ------- --- -------
402432 210105 48% 1 file
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ zipdetails findtheeasypass.zip
00000 LOCAL HEADER #1 04034B50
00004 Extract Zip Spec 14 '2.0'
00005 Extract OS 00 'MS-DOS'
00006 General Purpose Flag 0009
[Bit 0] 1 'Encryption'
[Bits 1-2] 1 'Maximum Compression'
[Bit 3] 1 'Streamed'
00008 Compression Method 0008 'Deflated'
0000A Last Mod Time 4AE35191 'Mon Jul 3 10:12:34 2017'
0000E CRC BC1E0C86
00012 Compressed Length 000334C5
00016 Uncompressed Length 00062400
0001A Filename Length 000C
0001C Extra Length 0000
0001E Filename 'EasyPass.exe'
0002A PAYLOAD
334EF STREAMING DATA HEADER 08074B50
334F3 CRC BC1E0C86
334F7 Compressed Length 000334C5
334FB Uncompressed Length 00062400
334FF CENTRAL HEADER #1 02014B50
33503 Created Zip Spec 1F '3.1'
33504 Created OS 00 'MS-DOS'
33505 Extract Zip Spec 14 '2.0'
33506 Extract OS 00 'MS-DOS'
33507 General Purpose Flag 0009
[Bit 0] 1 'Encryption'
[Bits 1-2] 1 'Maximum Compression'
[Bit 3] 1 'Streamed'
33509 Compression Method 0008 'Deflated'
3350B Last Mod Time 4AE35191 'Mon Jul 3 10:12:34 2017'
3350F CRC BC1E0C86
33513 Compressed Length 000334C5
33517 Uncompressed Length 00062400
3351B Filename Length 000C
3351D Extra Length 0024
3351F Comment Length 0000
33521 Disk Start 0000
33523 Int File Attributes 0000
[Bit 0] 0 'Binary Data'
33525 Ext File Attributes 00000020
[Bit 5] Archive
33529 Local Header Offset 00000000
3352D Filename 'EasyPass.exe'
33539 Extra ID #0001 000A 'NTFS FileTimes'
3353B Length 0020
3353D Reserved 00000000
33541 Tag1 0001
33543 Size1 0018
33545 Mtime 01D2F3CBBE63685D 'Mon Jul 3 09:12:34
2017 526217300ns'
3354D Ctime 01D2F3CBC75A08C1 'Mon Jul 3 09:12:49
2017 564281700ns'
33555 Atime 01D2F3CBBE34604E 'Mon Jul 3 09:12:34
2017 217991800ns'
3355D END CENTRAL HEADER 06054B50
33561 Number of this disk 0000
33563 Central Dir Disk no 0000
33565 Entries in this disk 0001
33567 Total Entries 0001
33569 Size of Central Dir 0000005E
3356D Offset to Central Dir 000334FF
33571 Comment Length 0000
Done
My first thought is that we want to feed this into a password cracker.
Crack the password of a .zip file
We want to use johntheripper or hashcat to crack the password of our zip-file.
Prepare the hash:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ zip2john findtheeasypass.zip > output3.txt
ver 2.0 findtheeasypass.zip/EasyPass.exe PKZIP Encr: cmplen=210117, decmplen=402432, crc=BC1E0C86
Feed it to johntheripper:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ john output3.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 3 candidates buffered for the current salt, minimum 8 needed for performance.
Warning: Only 7 candidates buffered for the current salt, minimum 8 needed for performance.
Almost done: Processing the remaining buffered candidate passwords, if any.
Warning: Only 4 candidates buffered for the current salt, minimum 8 needed for performance.
Proceeding with wordlist:/usr/share/john/password.lst, rules:Wordlist
Proceeding with incremental:ASCII
0g 0:00:00:03 3/3 0g/s 1754Kp/s 1754Kc/s 1754KC/s sheenthim..mahlon1
For this to work with hashcat we have to edit our output3.txt and remove the following part:
findtheeasypass.zip/EasyPass.exe:
Feed it to hashcat:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ hashcat -m 17200 -a 3 output2.txt
hashcat (v6.1.1) starting...
OpenCL API (OpenCL 1.2 pocl 1.5, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
=============================================================================================================================
* Device #1: pthread-Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz, 2868/2932 MB (1024 MB allocatable), 2MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Applicable optimizers applied:
* Not-Iterated
* Single-Hash
* Single-Salt
* Brute-Force
Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.
Host memory required for this attack: 64 MB
The wordlist or mask that you are using is too small.
This means that hashcat cannot use the full parallel power of your device(s).
Unless you supply more work, your cracking speed will drop.
For tips on supplying more work, see: https://hashcat.net/faq/morework
Approaching final keyspace - workload adjusted.
Session..........: hashcat
Status...........: Exhausted
Hash.Name........: PKZIP (Compressed)
Hash.Target......: $pkzip2$1*1*2*0*334c5*62400*bc1e0c86*0*2a*8*334c5*b...kzip2$
Time.Started.....: Tue Dec 1 09:50:17 2020 (0 secs)
Time.Estimated...: Tue Dec 1 09:50:17 2020 (0 secs)
Guess.Mask.......: ?1 [1]
Guess.Charset....: -1 ?l?d?u, -2 ?l?d, -3 ?l?d*!$@_, -4 Undefined
Guess.Queue......: 1/15 (6.67%)
Speed.#1.........: 335 H/s (0.01ms) @ Accel:1024 Loops:62 Thr:1 Vec:8
Recovered........: 0/1 (0.00%) Digests
Progress.........: 62/62 (100.00%)
Rejected.........: 0/62 (0.00%)
Restore.Point....: 1/1 (100.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-62 Iteration:0-62
Candidates.#1....: s -> X
Ok, we now have two different ways to bruteforce the password of a .zip file. But maybe there is a faster route to the target? When accepting the challenge on hack-the-box you see that the user who got firstblood (the person who first solved the challenge) used 08H 37M 40S which might suggest that he bruteforced this, but lets try some other stuff while our bruteforcing work its magic.
PS: After working on this .zipfile for a while I saw that the password was in cleartext on the same page as I downlaoded the file, so the challenge was obviously not to crack open the password file itself.
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ unzip -P hackthebox findtheeasypass.zip
Archive: findtheeasypass.zip
inflating: EasyPass.exe
Inspecting unknown files
Ok, we have got the .zip file extracted and its time to see on the content inside it. The archive contain only a single file: EasyPass.exe.
First we want to check that the file might be what the extension say it is:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ file EasyPass.exe
EasyPass.exe: PE32 executable (GUI) Intel 80386, for MS Windows
Lets also see what strings are present:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ strings -a EasyPass.exe | less
This program must be run under Win32
CODE
`DATA
...
Click
Button1Click
Ok, we now have a Win32 Executable which I want do run. Since Im on a Linux system I have to do some work just to be able to execute the file.
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ sudo apt-get install wine32
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ wine EasyPass.exe
You will now see that the program ask for a password, and if you enter the wrong password it says so.
So I guess the new task is to find the passsword it ask for.
Reverse engineering
First I need to download and install a debugger, a program that I can use to see into the bits & bytes of a program while it is running. Since EasyPass is a windows program I have to find a debugger that can execute and debug windows executable.
I tried several free (as-in-beer) debuggers, and ended up with IDA-Free: https://www.hex-rays.com/products/ida/support/download_freeware/
Again, being on Linux I have to run it through wine:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ wine idafree70_windows.exe
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ wine "/home/findtheeasypass/.wine/drive_c/Program Files/IDA Freeware 7.0/ida64.exe"
Load up the *EasyPass.exe" file in IDA Free (I just went with the suggested defaults option):
Start the program, and when the program is running inside IDA Free, do a textsearch (ALT+T) for the "Wrong password" string that we encountered earlier:
As we can see from the search result, this flow is leading to the "Wrong password" message:
CODE:00454131 call sub_404628
CODE:00454136 jnz short loc_454144
CODE:00454138 mov eax, offset aGoodJobCongrat ; "Good Job. Congratulations"
CODE:0045413D call sub_427A30
CODE:00454142 jmp short loc_45414E
CODE:00454144 ; ---------------------------------------------------------------------------
CODE:00454144
CODE:00454144 loc_454144: ; CODE XREF: sub_454070+C6↑j
CODE:00454144 mov eax, offset aWrongPassword ; "Wrong Password!"
CODE:00454149 call sub_427A30
CODE:0045414E
We are now looking at assembly code, and a brief knowledge of assembler will help us out:
- jnz: jump if not zero (ZF = 0), https://wiki.cheatengine.org/index.php?title=Assembler:Commands:JNZ
- mov: copy values from the second operand to the first operand, https://wiki.cheatengine.org/index.php?title=Assembler:Commands:MOV
- call: jump to the given operands and return (with return), https://wiki.cheatengine.org/index.php?title=Assembler:Commands:CALL
- jmp: transfer programcontrol to another place (with no-return), https://wiki.cheatengine.org/index.php?title=Assembler:Commands:JMP
With this in mind, lets translate the assembly code:
Call the subroutine at sub_404628, if the zeroflag is not zero, jump to loc_454144 and present the "Wrong password" text. If the zeroflag is zero, dont jump but proceed and show the "Good Job. Congratulations" text.
If we have translated the code correctly, the interesting part is inside sub_404628 or immediately follow it. So we start setting a breakpoint on CODE:00454136. When we set a breakpoint, the execution will pause at that point so we will be able to inspect the state of various registers.
In the screenshot we see that registers IF and AF is 1 which will trigger the JNZ to show us the "Wrong password" text. The registers are probably set inside the sub_404628 so we have to move our breakpoint to catch the interesting bits.
Lets try move from CODE:00454136 to CODE:00454131 and run our program again. Use the "Execute each instruction" to step the code line-by-line:
After a few steps we will see a new assembler keyword:
- cmp: compares the first operand with the second operand, https://wiki.cheatengine.org/index.php?title=Assembler:Commands:CMP
So if we assume that it compares our input with whatever the password is, let us examine the content of the registers EAX and EDX:
In the EAX register we can read ttt which is the value I gave in the inputbox, and in the EDX register we can read fortran! which might be a candidate for a password.
Let us re-run the program and try the fortran! password:
Congratulations, the challenge is solved. Submit your flag and move on learning new stuff :)
Here are some of the other debugger alternatives I look into, but choosed to not use:
- OllyDBG http://www.ollydbg.de/
- GoVest https://www.oocities.org/govest/
- Ghidra https://ghidra-sre.org/
Since we are running wine you could also take a look at: https://wiki.winehq.org/Wine_Developer%27s_Guide/Debugging_Wine#Disassembling_programs
Cracking a passwordprotected zip file, take 2
We did not finish our passwordcracking attempt since the password was provided as part of the challenge, and thus no cracking was needed.
Anyway, for the sake of completeness:
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ cat words.dict
hackthebox
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ zip2john findtheeasypass.zip > output.txt
ver 2.0 findtheeasypass.zip/EasyPass.exe PKZIP Encr: cmplen=210117, decmplen=402432, crc=BC1E0C86
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ john output.txt --wordlist=words.dict
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
No password hashes left to crack (see FAQ)
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$ john output.txt --show
findtheeasypass.zip/EasyPass.exe:hackthebox:EasyPass.exe:findtheeasypass.zip::findtheeasypass.zip
1 password hash cracked, 0 left
findtheeasypass@kali:/mnt/hgfs/kali_share/challenge-findtheeasypass$
Cheers...