HACKTHEZONE CHALLENGES #1 WRITE-UP

Cyber-attacks are increasing in complexity using not only technical skills, HackTheZone aims to simulate realistic attacks with the purpose of preparing the IT passionate and not only to counter such attacks.

During HackTheZone Challenges #1, the competitors had to solve multiple chained challenges, placed online or in different Geo-Locations from Bucharest.

1st Flag – Web application exploitation

On 12th October 2019 at 09:00 the details of the first target were provided on the CTF platform. The target name was cleverstyle.ro

The reconnaissance starts from the first interaction with the webpage, it seems that the owner is a lifestyle blogger that reviews multiple locations from Bucharest.

The next step in the reconnaissance process is to check the source of the web page. From the source we can see that a WordPress CMS is used.

A popular tool for finding WordPress vulnerabilities is WPScan. After running WPScan we can two pieces of information that we can work with: the registration is open and the WordPress version and as you can see this CMS version is pretty old.

Based on the above information we create an account and login.

Since the login is successful, we can move forward in finding an exploit with our friend, Google.

In the CVE database we can find an RCE vulnerability.

With the help of our old friend we can find an exploit for CVE-2019-8942.

Tools needed for exploitation, a VPS with Metasploit installed and the public IP of the host. Since the website is hosted behind CloudFlare network.

The public IP can be found with the aid of Crimeflare, Crimeflare is a database of public IP`s for websites hosted being Cloudflare.

The exploitation was achieved with the aid of Metasploit.

Once we have a shell the first place to look for juicy things is the home folder of current user.

In the hint.txt file we can find a sentence that makes us investigate anything related to a system path. After we issue an echo $PATH we can find an interesting binary and a Base64 string. After we decode the base64 we can find a new username and password which we use to login on the WP-Admin web page.

Once logged in we can find a discussion between what it seems to be the owner of the site and a hair salon. From there we can extract the flag and the details of our next target.

Following the clues, we prepare our next move, Mona attached a link to a password protected file and lets Sandra now that she will receive the password upon the next salon appointment. From a previous visit Sandra finds that Mona has a dog and she is curious about it’s name making us think this password is related to the dog

2nd Flag – Social engineering

Following the Facebook link from previous flag we can find that the salon is a real target ”Ice Beauty Salon”.

Called for an appointment. Once arrived in the location, I had to use my social engineering skills to find the password. The employees were instructed if someone asks details about a dog to say the name Caesar and to point at a picture with a dog.

The name of the dog was a clue that I had to use the Caesar cipher.

The dog had a scarf on its neck with a string, connecting the dots we could find the archive password “Azorel_1st”

In the archived there was an email with a discussion between Mona and a IT guy that found a week Wi-Fi password of Mona`s second salon, 2nd flag, the handshake that he retrieved and information about the next target, an new salon near “Copper’s Pub”.

3rd Flag – Wardriving + Mobile + Audio Steganography

 

In the below images are the details of the target.

In order to enter the WIFI network I had to crack the password from the handshake using a wordlist, the most common wordlist from Kali is Rockyou.txt, for this I used Aircrack.

After 40 minutes the password was revealed

The next step is to find the network hosts with the aid of nmap.

I was able to find two hosts. The two hosts had ports 42135 and 59777 open.

Using -A parameter in the nmap scan we were able to identify the running applications behind the ports.

The Minecraft server was a rabbit hole, no exploits were found but the ES File Explorer was vulnerable. Finding an exploit was again easy.

The exploit seems to be working.

With the aid of the exploit we can retrieve the mobile phone files, after a little recon we can find some interesting WAV files, messages from ISS.

We use the exploit to get the files.

Decoding the files was done with the aid of the hint from the naming, this way we discover the protocol used.

Finding the tools for decoding was again easy.

The tool that I used was QSSTV, a simple apt-get install qsstv did the job.
Once decoded, the files revealed the 3rd flag, a router back with the password and the location of the next target, “Mechano Pub”.

4th Flag – Binary Buffer overflow

The target for 4th flag was a WIFI network near Mechano Pub.

As in previous flag, we repeat the recon phase, network scan, host scan and port scan.

Based on the port scan we can find that a HTTP port is open.
We perform a directory scanning with Wfuzz and we are able to find a interesting directory.

Inside of that directory there was a binary.

In the port scan we could determine that port 7264 was accepting connections, this was done with a Telnet request.

The web folder binary could be the way to exploit the open port, we move on debugging the binary.

For debugging we are going to use GDB with the peda extension installed. GDB is the gnu C/C++ debugger and peda is an extension for binary exploitation and can be found at https://github.com/longld/peda

Let`s go ahead we open the program and run it.

As expected, the program asks for an input. We know that the buffer has a fixed size, we will be sending a large string, 4000 bytes.

Alright so we have a segfault. The program crashed and it looks like we do indeed control $eip. Let’s find the offset where the program crashed. There are couple different ways. Metasploit`s pattern create is my favorite but to keep things easy we are going to just use the built in peda functionality.

Now we rerun the program with the generated pattern to see where it crashes.

So we get another crash as expected and we can see part of our pattern in $eip. Let`s grab that offset.

There it is! At 3072 bytes we have our offset. Now we can overflow the function at 3072 bytes and pass the address of a shell. Let`s feed the program a new pattern of 3072 bytes and check the $eip

Alright, everything looks great. We can see that after passing 3072 bytes we are now stepping stored in $eip. Let`s grab the actual address where we can store the shell.

Now that we have the address of jmp esp, all we need to do is insert in ESP our shell. A good shellcode can be found at http://shell-storm.org/shellcode/files/shellcode-358.php

Below is the string that we used to create a reverse connection with the server.

And we got our shell, flag and next challenge.

5th Flag – Reverse Engineering

The first thing we notice is the lack of extension for this file, which means it could be anything, and because of the lack of it we can’t simply choose an approach, so we’ll use some of the open source tools which can perform a quick analysis of the file and give us some insights.

Without further addo, to identify the file format we assume it has a known signature (aka Magic Number), but more important, we assume that it can be found in Kessler’s Signatures List (https://www.garykessler.net/library/file_sigs.html).

The first approach would be to obtain the Hex Dump of the file and map it against the list mentioned above.

The second approach would be to use some open source tools in order to get some quick analysis of the file based on how much can be parsed. For this step we used DetectItEasy (DiE), which contains the updated Kessler List, and figured that we’re dealing with a PE (Portable Executable) file.

As a straightforward step, we’d add the extension ourselves to the file, and most likely will try to execute it. The problem is that it works only in theory, because the file is not even loaded into memory at execution.

Approach #1: Rebuild the file + Reverse Engineering (Hardcore Difficulty)

We notice the file is Portable Executable, which means its signature should always start with MZ (64 bytes), and the last DWORD of those 64bytes should contain the memory address where the PE Header starts from.

We take a look at the Hex Dump of the file and manually identify the locations of MZ and PE in the file’s header. The odd thing is that the DOS Header (the one starting with MZ) seems to be pointing to itself …. hmm … the weirdest recursion ever.

At this point we realize the file’s header was altered in such a way the pointers are no longer working properly due to that loop in the DOS Header, so the COFF Header will never be reached.

At this point we definitely know why the file won’t execute, even if we add the “.exe” extension, so the first thing to be done is to manually repair it, that means modifying that DWORD’s value in such a way it will point to the right memory address where the COFF Header starts (basically we simply identify the memory address where this sequence of bytes can be found: “50 45 00 00”)

After couple of attempts we realized that the file is a bit annoying, and the Offset(h) column is BigEndian, the 16 Bytes column are Little Endian, and the ASCII column will print ‘.’ When the character is out of the ASCII table and cannot be printed out (at least not in a human readable format)

Ok, now the file’s header is rebuild, so it should work, right?

We open the file in a debugger (OllyDbg, Immunity, x96dbg, etc) and perform symbol analysis.

For this case we used x96Dbg (which detected the file architecture and launched x86dbg.exe). From the symbols list it’s mandatory to point out the System Functions which can reveal file’s behavior (well, in case the file’s execution doesn’t show much).

As it can be observed, it’s easy to identify the most common defense mechanism, the IsDebuggerPresent, which is one of the most used anti-debugging mechanisms, but also this can be a good indicator, because the lack of other anti-debugging techniques reveals some information about the file, for instance: being compiled and linked by Visual Studio, so there’s a very high probability for it not to be called at runtime.

First step is to add breakpoints for each function we’re interested in: RegCreateKeyEx, RegSetValueEx, and GetSystemDefaultLangID.

Now we notice the code tries to validate the System’s Language ID, using the GetSystemDefaultLangID function.

At this point we have our first behavioral indicator: checks if the Keyboard Layout ID matches 0x41C (the default Layout is 0x409), so at this point we’re pretty sure the file won’t be able to validate the ID, and most likely will cease to execute

In order to see this behavior, now that we know what it was trying to validate, we let the program go and continue to execute until return.

The only odd thing is that it calls RegCreateKeyExW function, instead of a crashing error. So, instead of exiting, the file is creating a new Registry Key SOFTWARE\Microsoft\Services\PrimaryByte with a hardcoded value.

Simply decoding that hardcoded value (HEX) to ASCII, it revealed some weird text which google translated as “Unlock more skills, pal” (pointing out the fact that it was translated from albanian)

Using regedit.exe we can find and extract the value, but we notice that it’s different from that HEX we found in the debugger. By translating it we obtain: “GOOD LUCK” (again, translated from albanian).

Now we know what Keyboard Layout the file was trying to validate: the albanian one.

The other way around would’ve been to patch the file, which means to force the comparison between our Keyboard Layout and GetSystemDefaultLangID to always return True. (Basically the file would believe the layout is albanian at runtime)

Patch the file, re-open it in the debugger and run it until it hits the breakpoint for Keyboard Layout just like before, the only difference now would be the validation answer. We can see that it validates the layout and moves on like nothing happened, so we can gather some more behavioral intel about it, but instead of doing some super advanced computing operations, it simply calls the GetSystemDefaultLangID again in order to write a different string to the same registry key as before.

What can be observed here is the fact that instead of simply writing into the registry key and closing it a, the code is executing a repetitive operation (like a recursive function), and the pattern of the repetitive operation can be easily noticed.

When the program couldn’t validate the layout, it simply displayed some HEX values, and wrote an albanian ASCII string into the registry key, but now it writes something that looks like a binary string.

There is a single call to the RegOpen function, followed by multiple calls to the RegSet function, which means it will try to overwrite the registry key’s value before calling the RegClose function.

And at this point we gathered another indicator related to file’s behavior.

In order to see what the file is trying to write and overwrite into that registry key’s value, we can simply set breakpoints for each call to RegSet function, which is denoted by call esi, and keep the values from memory dump into our favorite text editor …. Notepad (because it’s free)

After all the madness ends, we will end up with a very big binary string, so it must be related to the flag, since the program does not perform any other operation.

Approach #2: Static Analysis

Knowing that we deal with a Portable Executable, we can simply use the open source tools for PE files, like PEStudio, PEBear, PEiD, or any other tool of choice.

What we hope to obtain by performing static analysis:

  • Header information: entropy, sections, signatures, characteristics
  • Sections information: entropy, blacklist/whitelist, entry point, size, pointers
  • Resource information: type, format, language, certificates
  • Strings: most likely we’ll be focusing on the Human Readable ones – ASCII only

Now, using PE Studio we can check anything the tool parses, and then perform a Human Decision on its output. The output should be like the following:

As it can be seen, it was relatively easy to obtain the same result as the one through the use of the debugger (patching+breakpoints+lots of copy/paste)

Reaching this long binary string is the boiling point for this challenge, since we need to ‘crack’ it in order to find what’s behind it.

The first step is to convert it from binary to ASCII. For cases like this one, we recommend to use, because of the available resources, CyberChef (open source text based data manipulation)

After translating from binary to ASCII (Human Readable text) we obtain a string very similar to Base64.(but also it can be encoded with any other base)

Trying to decode the string from Base64:

After decoding, the resulted text didn’t reveal anything that has a logic. The signature that’s usually found in the first 16Bytes (the magic number) is not something recognized as a legitimate file: 00 08 03 33 07 10 82 c3 80 f6 cb 9f 33 b8 21 11.

Since we can see the straightforward decoding resulted into something non-human-readable, the next step would be to presume the text was somehow byte-wise encrypted and the result was siminar to base64 by coincidence, so we have to try the bruteforce technique, that means XOR it with every key between 0x00 and 0xFF.

After we fail successfully at bruteforcing it, we noticed that the base64 didn’t return any error message, so it’s a base64 string … but simply doesn’t decode into something normal. The trick with base64 is that it is a size-based encoder, so it does not matter the order of the bytes to encode, as long as the input size aligns with the requirements.

Decoding it from left to right failed, so we’ll try to decode its reversed version (from right to left):

Again, base64 decoder didn’t reveal any error messages, but the output looks slightly different than before.

The interesting part at this point is that the first 16 Bytes contain the signature of a GZIP File: “1f 8b 08 00 2c e6 9d 5d 00 ff b5 57 0b 8e eb 20 “, where 1f8B0800 is the signature (magic number) of GZIP.

00000000  1f 8b 08 00 2c e6 9d 5d 00 ff b5 57 0b 8e eb 20  |….,æ.].ÿµW..ë |

00000010  0c bc 8a 8f b0 f9 40 fa 8e b3 af da bd ff 11 6a  |.¼..°ù@ú.³¯Ú½ÿ.j|

00000020  88 5a 01 1e 8f 69 aa 95 a2 28 d4 4c 98 d8 e3 81  |.Z…iª.¢(ÔL.Øã.|

00000030  ee 59 72 92 7c 97 fc 4f f2 56 ee c7 2e f7 5d 6e  |îYr.|.üOòVîÇ.÷]n|

00000040  9b 1c 6b 19 ae 5f 92 97 e7 83 4e d6 69 3f f5 97  |..k.®_..ç.NÖi?õ.|

00000050  0a 39 be cb b3 42 4a 54 e1 bf 35 aa d8 54 e0 47  |.9¾Ë³BJTá¿5ªØTàG|

00000060  7d d0 99 1a dd 6f 15 a5 73 fe 4b da 25 eb 30 49  |}Ð..Ýo.¥sþKÚ%ë0I|

00000070  52 f8 09 49 b2 2e 65 da 76 5e 4b 73 d5 61 1c 3a  |Rø.I².eÚv^KsÕa.:|

00000080  87 ed f5 a7 a1 57 f4 49 66 0c 35 f0 2e f4 8a b6  |.íõ§¡WôIf.5ð.ô.¶|

00000090  a8 21 3a a0 42 1a 04 d5 bc 73 5c ab 99 39 cb b0  |¨!: B..Õ¼s\«.9Ë°|

000000a0  cf 7f b7 56 7f 07 34 c8 5a 36 74 f9 93 7b 2c 40  |Ï.·V..4ÈZ6tù.{,@|

000000b0  c1 7a b5 51 8b 82 55 36 6f c6 e4 61 a2 88 36 66  |ÁzµQ..U6oÆäa¢.6f|

000000c0  64 33 94 32 fc 2e ae 5e 98 c3 90 86 57 65 d8 b0  |d3.2ü.®^.Ã..WeØ°|

000000d0  fd 9b b1 0e 49 bd a0 03 c0 f4 f2 6c 40 1a 26 15  |ý.±.I½ .Àôòl@.&.|

000000e0  58 00 50 a2 97 1b d6 92 47 d1 b8 2b ad 44 21 8d  |X.P¢..Ö.GѸ+.D!.|

000000f0  10 f5 96 e9 59 4b b1 da 20 c2 86 6b c1 d6 7b 37  |.õ.éYK±Ú Â.kÁÖ{7|

00000100  bd 9f b8 a8 47 3e b4 14 ee a2 f3 b2 09 c9 93 f4  |½.¸¨G>´.î¢ó².É.ô|

00000110  7a 45 31 49 c6 a1 79 4b 31 9f 10 d3 f8 64 e3 f0  |zE1IÆ¡yK1..Óødãð|

00000120  42 9e 39 84 45 f1 1c 60 60 e8 e9 90 94 12 b6 9e  |B.9.Eñ.”èé…¶.|

00000130  a7 79 4f 51 26 63 ae 99 93 ad 8d 9c 01 26 3b 85  |§yOQ&c®……&;.|

00000140  6f 88 bc 28 fc 1c 45 18 7a ed e0 49 94 90 e7 34  |o.¼(ü.E.zíàI..ç4|

00000150  3c d9 84 fd 35 af 28 be 49 91 26 0a fd d0 73 6c  |<Ù.ý5¯(¾I.&.ýÐsl|

00000160  d2 e6 44 87 de 19 e0 9a a5 5c 3e 2c 91 ad 0d f6  |ÒæD.Þ.à.¥\>,…ö|

00000170  57 68 29 7c 77 f0 5a 6f c6 d9 26 4d ef f2 be 1c  |Wh)|wðZoÆÙ&Mïò¾.|

00000180  fe 19 81 a5 f4 c4 86 0e cc 7e eb 3d 00 eb 20 41  |þ..¥ôÄ..Ì~ë=.ë A|

00000190  cc 0c 0e 00 00                                   |Ì….|

Spotting the obvious now, we need to apply the GUNZIP operation on our resulted/decoded string.

46 65 6c 69 63 69 74 c4 83 72 69 20 61 69 20 66 69 6e 61 6c 69 7a 61 74 20 63 6f 6e 63 75 72 73 75 6c 20 48 61 63 6b 54 68 65 5a 6f 6e 65 21 20 30 30 31 31 31 31 30 31 20 30 30 31 31 31 31 30 31 20 30 31 30 30 30 30 30 31 20 30 31 30 30 30 30 30 31 20 30 31 30 30 30 30 30 31 20 30 31 30 30 30 30 30 31 20 30 31 31 30 30 31 31 31 20 30 31 31 30 31 30 30 30 20 30 31 31 31 30 31 31 31 20 30 30 31 31 31 30 30 30 20 30 31 30 30 30 30 30 31 20 30 31 31 30 31 30 30 30 20 30 31 30 30 31 31 30 30 20 30 30 31 31 30 30 31 30 20 30 31 31 31 30 31 31 31 20 30 30 31 30 31 31 31 31 20 30 31 30 31 30 31 30 31 20 30 31 30 30 31 30 31 30 20 30 31 31 31 30 30 31 30 20 30 31 30 30 30 30 30 31 20 30 31 31 30 31 30 30 30 20 30 31 30 31 30 30 30 30 20 30 31 31 30 31 31 31 31 20 30 31 31 31 30 31 31 30 20 30 31 31 30 30 31 31 31 20 30 31 30 30 31 31 30 31 20 30 31 30 30 30 30 31 31 20 30 31 30 31 31 30 30 30 20 30 31 31 31 31 30 30 30 20 30 31 31 31 30 31 31 30 20 30 30 31 30 31 31 31 31 20 30 31 31 31 30 30 30 31 20 30 31 31 30 30 31 30 30 20 30 31 30 31 31 30 30 30 20 30 31 31 31 30 31 30 31 20 30 31 30 30 31 31 30 31 20 30 30 31 30 31 30 31 31 20 30 30 31 31 30 30 30 30 20 30 31 31 30 31 31 30 31 20 30 30 31 31 30 30 31 31 20 30 31 31 30 31 31 31 31 20 30 31 31 30 31 30 31 31 20 30 31 30 30 31 30 30 30 20 30 31 31 30 30 30 31 30 20 30 31 30 31 31 30 30 30 20 30 31 30 30 30 30 30 31 20 30 31 31 30 30 30 31 31 20 30 30 31 31 30 30 30 31 20 30 31 31 31 30 31 31 31 20 30 31 31 30 30 31 31 30 20 30 31 30 30 30 31 31 31 20 30 31 31 30 30 31 31 31 20 30 31 30 30 30 30 30 31 20 30 31 31 30 31 31 30 30 20 30 31 31 31 30 31 30 30 20 30 31 31 31 31 30 30 31 20 30 31 30 30 30 31 31 30 20 30 31 31 31 31 30 30 30 20 30 31 30 30 30 30 30 31 20 30 30 31 31 31 30 30 30 20 30 31 30 30 30 30 30 31 20 30 31 31 31 30 31 30 30 20 30 31 30 31 30 30 30 30 20 30 31 31 30 30 30 31 30 20 30 31 31 31 30 30 31 30 20 30 31 30 31 31 30 30 30 20 30 30 31 31 31 30 30 30 20 30 31 30 31 30 31 30 30 20 30 31 31 30 31 31 30 30 20 30 31 30 31 30 30 30 31 20 30 31 30 31 30 30 31 30 20 30 30 31 30 31 31 31 31 20 30 31 30 31 30 31 31 30 20 30 31 31 30 31 31 30 30 20 30 30 31 30 31 31 31 31 20 30 31 30 31 30 31 30 31 20 30 31 30 31 30 31 30 31 20 30 31 31 30 31 31 30 31 20 30 31 31 30 30 30 31 30 20 30 31 31 30 31 30 31 31 20 30 31 31 30 31 31 31 30 20 30 31 31 31 31 30 31 30 20 30 31 30 31 31 30 31 30 20 30 31 30 30 31 30 30 31 20 30 31 30 31 30 30 30 30 20 30 31 30 30 30 31 30 31 20 30 31 31 31 30 30 30 30 20 30 31 31 30 31 31 31 30 20 30 31 30 30 31 31 30 31 20 30 30 31 31 31 30 30 30 20 30 31 31 31 30 31 31 30 20 30 31 31 31 30 31 30 31 20 30 31 31 30 30 30 30 31 20 30 31 30 30 30 31 31 30 20 30 31 30 30 31 30 30 30 20 30 30 31 31 30 30 31 30 20 30 30 31 31 31 30 30 30 20 30 31 31 30 30 30 30 31 20 30 31 30 30 31 31 30 31 20 30 31 31 31 30 31 30 30 20 30 31 31 30 31 30 31 30 20 30 31 31 30 31 30 31 31 20 30 30 31 31 30 30 31 31 20 30 31 30 31 30 31 31 30 20 30 31 30 30 30 31 31 30 20 30 31 31 31 30 31 31 31 20 30 31 30 31 30 30 30 31 20 30 31 30 30 31 30 30 31 20 30 31 30 30 30 31 30 30 20 30 31 31 30 31 31 30 30 20 30 31 30 31 30 30 30 31 20 30 31 31 30 30 31 31 31 20 30 31 30 30 31 31 30 31 20 30 31 30 31 30 31 31 31 20 30 31 31 31 31 30 31 30 20 30 30 31 30 31 31 31 31 20 30 31 30 30 30 30 30 31 20 30 30 31 31 30 30 30 30 20 30 31 30 31 30 31 31 30 20 30 31 31 30 31 31 31 30 20 30 31 31 30 31 31 30 30 20 30 31 31 30 30 31 31 30 20 30 31 30 30 30 31 31 31 20 30 31 30 30 30 30 30 31 20 30 31 30 30 31 30 30 31 20 30 31 31 31 30 30 31 31 20 30 30 31 31 30 31 30 30 20 30 31 30 30 31 30 30 30

What we can observe here is the fact that the GUnzipped string resulted in a long HEX string (probably a hex dump of a file? ) which looks to have a weird padding formed by 0x30, 0x31, 0x20, which translates to numbers: 0,1, and space char.

Again, converting from HEX to ASCII, the above text becomes:

Felicitări ai finalizat concursul HackTheZone! 00111101 00111101 01000001 01000001 01000001 01000001 01100111 01101000 01110111 00111000 01000001 01101000 01001100 00110010 01110111 00101111 01010101 01001010 01110010 01000001 01101000 01010000 01101111 01110110 01100111 01001101 01000011 01011000 01111000 01110110 00101111 01110001 01100100 01011000 01110101 01001101 00101011 00110000 01101101 00110011 01101111 01101011 01001000 01100010 01011000 01000001 01100011 00110001 01110111 01100110 01000111 01100111 01000001 01101100 01110100 01111001 01000110 01111000 01000001 00111000 01000001 01110100 01010000 01100010 01110010 01011000 00111000 01010100 01101100 01010001 01010010 00101111 01010110 01101100 00101111 01010101 01010101 01101101 01100010 01101011 01101110 01111010 01011010 01001001 01010000 01000101 01110000 01101110 01001101 00111000 01110110 01110101 01100001 01000110 01001000 00110010 00111000 01100001 01001101 01110100 01101010 01101011 00110011 01010110 01000110 01110111 01010001 01001001 01000100 01101100 01010001 01100111 01001101 01010111 01111010 00101111 01000001 00110000 01010110 01101110 01101100 01100110 01000111 01000001 01001001 01110011 00110100 01001000

Yay! Now we know that all the madness was not related to the executable itself, but with the text within its strings.

Since we obtained what looks to be the partial congratulation message for finding the flag, we already know what steps should be applied on the remaining (yet again) binary string.

As we can see, we got the half of the final message, so we just re-apply the same steps and we should be good to go. The same steps need to be applied to the binary string after the message “Felicitări ai finalizat concursul HackTheZone!”