# HKCERT CTF 2024: Guide to beginner-friendly challenges (II) [TOC] ## Reverse: Yet another crackme ### Challenge Summary An apk file `com.hkcert24.crackme-Signed.apk` was provided. After installing the app on a mobile device, we would be presented with the following page. It appeared that this application requires us to find the correct input and would invalidate any wrong input. ![image](https://hackmd.io/_uploads/HkaOK8V-kl.png) ### Walk through APKs are like onions, it has multiple of layers of technology and we have to break it down one by one to reverse engineer the application logic built into it. ![image](https://hackmd.io/_uploads/ryz69I4bJl.png) ### Breaking down APK file So what are apk files files exactly? >An Android package, which is an archive file with an .apk suffix, contains the contents of an Android app required at runtime, and it is the file that Android-powered devices use to install the app. [see more](https://developer.android.com/guide/components/fundamentals) Since APK file is an archive file, we can simply unarchive/decompress it with common file archiver such as 7zip, WinRAR or any builtin file archiver within OS. For example, you can open the APK with 7zip as such ![image](https://hackmd.io/_uploads/BJsxR8VZkg.png) You should be able see the file gets expanded with directoies and files as such ![image](https://hackmd.io/_uploads/S19mpUNbJx.png) As you could see there are quite a lot of files and directories, what would be relevant if we want to see the code which controls the flag checking logic of application? One common point of interest would be the files with the `dex` file extension DEX (Dalvik executable) is a type of executable file format that contains DEX bytecode that could be interpreted and executed by Android runtime (ART) and Dalvik. [see more](https://source.android.com/docs/core/runtime) Obviously we cannot easily interpret DEX bytecode manually (Well you probably could) ![image](https://hackmd.io/_uploads/r1VhWv4bJl.png) > This is what you will see if you tried the read the class.dex directly Luckily, there is an awesome open source tool that could decompile the bytecode to something readable. https://github.com/skylot/jadx You should be able to see something like this. ![image](https://hackmd.io/_uploads/r13t-_E-1x.png) If the android application is developed using kotlin or java, the main application logic would most likely be defined in the package which is the same as the application ID, namely `com.hkcert24.crackme`. However, it is apparent that there is no meaningful code under that particular package. ### Dealing with Microsoft MAUI Here we have to make an observation on other packages. We could see package such as `com.microsoft.maui`. Do also notice `xamarin` as well. With a quick [google](https://letmegooglethat.com/?q=what+is+microsoft+maui) search, We could make a reasonable guess that this challenge might be developed with the .NET MAUI framework. In case you didn't know, Xamarin is the predesessor of MAUI and has been completed replaced by MAUI on May 1, 2024. [see more](https://dotnet.microsoft.com/en-us/apps/xamarin) Since we have been a script kiddie since the beginning, let us keep the trend and just search directly how could we reverse engineer this Xamarin/MAUI thing. Based on the information from [Hacktricks](https://book.hacktricks.xyz/mobile-pentesting/xamarin-apps#extracting-dll-files-from-apk-ipa), we could see that the directory `\assemblies` is where the dotnet dll could be recovered. You should see the following file ![image](https://hackmd.io/_uploads/SybyDKVZ1e.png) In fact this is called the [AssemblyStore blob](https://github.com/dotnet/android/blob/main/Documentation/project-docs/AssemblyStores.md) which contains the managed assemblies in a specfic format. Now we just need to find a way convert the AssemblyStore blob back to a dotnet dll. This tool gave pretty good result: https://github.com/jakev/pyxamstore You should see the output directory with a bunch of extracted dlls files after installing and running the mentioned tool ![image](https://hackmd.io/_uploads/SyJ5jFE-Jx.png) ### Reverse engineering the .NET DLL The CrackMe.dll stood out like a sore thumb, so most likely it would be our first target to see what it might contain. With a quick [google](https://letmegooglethat.com/?q=dotnet+dissassembler), we can see there are muliple tools that could provide decompiled dotnet code. There are many options. I would demonstrate with [dnSpy](https://github.com/dnSpy/dnSpy/releases). Putting the `CrackMe.dll` in the disassembler would recover some of the source code and it is quite readable. Clicking around you would likely find `checkFlag` function. This is likely the function we would like to reverse engineer. ![image](https://hackmd.io/_uploads/SJQaycN-Je.png) The rest is simply figure out the logic and reverse the algorthim to find the flag. ##### What the checkflag does 1. The program first generates a hashmap/dictionary ```csharp int[] array = new int[] { #...SNIP... }; int[] array2 = new int[] { #...SNIP... }; Dictionary<int, int> dictionary = new Dictionary<int, int>(); for (int i = 0; i < array.Length; i++) { dictionary[array[i]] = array2[i]; } ``` 2. Each character of the user input would be mapped based on the dictionary and stored to a buffer ```csharp StringBuilder stringBuilder = new StringBuilder(); foreach (char c in f) { stringBuilder.Append((char)dictionary[(int)c]); } ``` 3. The buffer would be chopped into 32 bit chunks and stored to a `list`. The last chunk will be padded with `\x01` ```csharp int num3 = num2 - f.Length % num2; string text = stringBuilder.ToString() + new string('\u0001', num3); List<ulong> list = new List<ulong>(); for (int k = 0; k < text.Length - 1; k += num2) { ulong num4 = BitConverter.ToUInt64(Encoding.ASCII.GetBytes(text.Substring(k, num2)), 0); list.Add(num4); } ``` 4. Each chunk in the `list` would be XORed with a constant `num` and stored in `list2` ```csharp List<ulong> list2 = new List<ulong>(); foreach (ulong num5 in list) { ulong num6 = num ^ num5; list2.Add(num6); } ``` 5. Each chunk in the `list2` would be compared against each chunk of `array3`. If any chunk does not match, the check fails. Else the check passes ```csharp for (int l = 0; l < array3.Length; l++) { if (array3[l] != list2[l]) { return false; } } return true; ``` ##### A potential solve It is fairly simple, you'll figure it out. :::spoiler Spoiler 1. XOR each chunk of the `array3` against constant `num` 2. Since each chunk is 32 bit and there are 8 chunks, break all chunks into 8 bit assign them to an array 3. Generate an inverse mapping of the dictionary/hashmap and apply the mapping the to the array. 4. Cast each 8 bit integer to character and concat all character to get the flag ::: ## Crypto: Pigeon Post (1) ### Challenge Summary We act as the pigeon-in-the-middle between Alice and Byron. They will run a handshake protocol (using Diffie-Hellman key exchange algorithm) which establishes a secure communication (using AES-CTR). As the pigeon, our objective is to intercept the communication and retrieve the flag. ```mermaid sequenceDiagram Note over Alice, Byron: Alice and Byron already<br />have the public parameters<br />for handshaking Alice->>Byron: Init handshake<br />(Alice's public key) Note over Byron: Compute shared key from<br />Alice's public key and<br />Byron's private key Byron->>Alice: Receive handshake<br />(Byron's public key) Note over Alice: Compute shared key from<br />Byron's public key and<br />Alice's private key Note over Alice, Byron: 🔒 Messages are encrypted now 🔒 Alice->>Byron: Finish handshake<br />("done!") Byron->>Alice: Communicate<br />("what is the flag?...") Alice->>Byron: Communicate<br />("the flag is...") Byron->>Alice: Communicate<br />("nice flag!") Alice->>Byron: Communicate<br />(":)") ``` ### Solution #### Preliminary: Diffie-Hellman key exchange The key exchange protocol intends to allow two parties (Alice and Byron here) to compute a shared secret using an insecure protocol. Initially, they have a set of public parameters: $(g, p)$. In the protocol, Alice and Byron follow the below heuristic to derive a shared secret: 1. Alice and Byron independently generate a random number between $0$ and $P-1$ (inclusive) as their own secret. The secret values for Alice and Byron are respectively denoted by $a$ and $b$. 2. Alice computes $A = g^a\ \text{mod}\ p$ and sends it to Byron. 3. Byron computes $B = g^b\ \text{mod}\ p$ and sends it to Alice. 4. Alice computes $s = B^a\ \text{mod}\ p$ and Byron computes $s = A^b\ \text{mod}\ p$. Here $s$ is the shared secret. It is guaranteed that the shared secrets are the same, because $$ A^b \equiv g^{ab} \equiv B^a\ (\text{mod}\ p). $$ Alice and Byron will then use the shared secret to derive a session key. In the challenge, the session key is the SHA256 digest of the shared secret. Assuming that an adversary is able to intercept the messages and obtains $A$ and $B$. The discrete logarithm problem says that it is still computationally hard to recover $a$ such that $A \equiv g^a\ (\text{mod}\ p)$, it will be expensive to derive the shared secret. #### Being an active pigeon in the middle Although the key exchange protocol is able to prevent passive attacks, it does not check whether the opposite party is the one we want to communicate with. An adversary can actively act as the opposite party to both Alice and Byron. ```mermaid sequenceDiagram Alice->>Pigeon: Init handshake<br />(Alice's public key) Note over Pigeon: Compute shared key from<br />Alice's public key and and<br />Pigeon's private key Pigeon->>Byron: Init handshake<br />(Pigeon's public key) Note over Byron: Compute shared key from<br />Pigeon's public key and<br />Byron's private key Byron->>Pigeon: Receive handshake<br />(Byron's public key) Note over Pigeon: Compute shared key from<br />Byron's public key and and<br />Pigeon's private key Pigeon->>Alice: Receive handshake<br />(Pigeon's public key) Note over Alice: Compute shared key from<br />Pigeon's public key and<br />Alice's private key Note over Alice, Pigeon: 🔒 Messages are encrypted now 🔒 Note over Pigeon, Byron: 🔒 ...and here as well 🔒 Alice->>Pigeon: Finish handshake<br />("done!") Note over Pigeon: Decrypt with shared key with Alice<br />and encrypt with shared key with Byron Pigeon->>Byron: Finish handshake<br />("done!") Byron->>Pigeon: Communicate<br />("what is the flag?...") Note over Pigeon: Decrypt with shared key with Byron<br />and encrypt with shared key with Alice Pigeon->>Alice: Communicate<br />("what is the flag?...") Alice->>Pigeon: Communicate<br />("the flag is...") Note over Pigeon: Decrypt with shared key with Byron<br />and now you have the flag! ``` We are given a sample solve script (`solve.py`) in the attachment, which partly implements the above protocol. Finish the script by implementing stuffs commented `😈 TODO`, and steal the flag from Alice! ## Pwn: Flag hasher ### Challenge Summary - Attachment with C source code and Docker environment provided. ![image](https://hackmd.io/_uploads/S1Y6gEtW1l.png) - The program was written in C, and served over netcat (SSL/TLS). ![image](https://hackmd.io/_uploads/rJe0eVK-kx.png) ### Solution We will go over these steps to tackle this challenge: - Connecting to the environment - Understanding the challenge source code - Finding the vulnerability - Understanding process memory layout - Writing the exploit using `pwntools` & Get flag remotely #### Connecting to the environment First, let's connect to the environment and take a look on it. ![image](https://hackmd.io/_uploads/H1cAl4t-1x.png) If you got this error, just run the command to install `ncat`. When you connect to the challenge successfully, you should see the following screen and you can type `2`, `Enter` to read hash record. ![image](https://hackmd.io/_uploads/By6yZNtWJl.png) Seems we got some existing hash in `idx=0`! What is that `2347...`? To exit, press `^C` (`Ctrl`+`C`) and return to your shell. #### Understanding the challenge source code In a C program, a program starts with `main`. Here, we can spot `sha256` big text in the `menu` function. ![image](https://hackmd.io/_uploads/Hy4lbVK-yg.png) We had executed action 2, therefor it will fall into the code starting with line 89 where `action == 2`. ![image](https://hackmd.io/_uploads/BJjeZNKZyg.png) It performs the following: - Print a message `Idx: ` with `printf()` - Read a number (unsigned integer) and store it in `idx` with `scanf()` - If the `idx` was not in `hashlist` (`hashlist[idx] == NULL`), abort the program using `_abort()` - Finally, print the existing hash using `printf()` in hex format (line 98) ##### Where is the flag? The flag was read from [environment variable](https://en.wikipedia.org/wiki/Environment_variable), hashed using `sha256` and stored in position `0` of the `hashlist` (line 52-55) After that, the variable `flag` was cleared by setting to NULL (line 57) and the environment variable was cleared using `clearenv()` (line 58) Therefore, the hash we got from environment `2347...` was the SHA256 of the flag! However, SHA256 is a one-way hash algorithm, which means you can't 'reverse' it using maths. So close yet so far! #### Finding the vulnerability But don't lose hope yet, by reading the `clearenv()` [documentation](https://man7.org/linux/man-pages/man3/clearenv.3.html), there was a nasty note: ![image](https://hackmd.io/_uploads/ryhWZ4tbyl.png) What does it mean? It means there might be some remaining flags in my buffers (i.e. memory of the process!). If we had a magnifier on computer memory to read bits, there might be possibility to read flags out of it! ![flag](https://hackmd.io/_uploads/rJzGbVKbyg.png) Uh, I knew that's not funny. So, can we read the memory of our process?... Yes. Did we demonstrated we can read hash out of the `hashlist` in the first section? ![image](https://hackmd.io/_uploads/Sky7WVFbJl.png) But can we read **any** memory in the process... to the `buffers containing the environment variable` (flags)? If you're coming from other language background like Python or JavaScript, you can't tell the vulnerability here, but ChatGPT knows. ![image](https://hackmd.io/_uploads/r1V4-EFZkl.png) So even the the max list length (`MAX_LIST_LENGHT`) was defined on line 8, it is possible to access data on and further than `16`. ![image](https://hackmd.io/_uploads/HJPUWNKb1x.png) #### Understanding process memory layout What is outside of `16` in `hashlist`...? In this particular example, `hashlist` was defined in the beginning of `main()`, therefore the memory layout of the process looks like this [\[Ref: Figure 3-31\]](https://refspecs.linuxbase.org/elf/abi386-4.pdf): ![image](https://hackmd.io/_uploads/Bk38bNYbye.png) Therefore, just put number larger than `16` we can access further up on the process stack, and eventually reaching the environment strings where our flag would be in! So where exactly should we read? Here's an issue, the distance between hashlist[0] and the flag is greatly affected by the executing environment. i.e. the distance you get from you local machine is probably different with the one in remote machine `c55-flag-hasher.hkcert24.pwnable.hk`. So... why don't we just brute force it? #### Writing the exploit using `pwntools` & Get flag remotely You can do try all number larger than `16` by hand, and you will reach the flag eventually... But why don't we automate this? ##### Install python and pwntools In your Ubuntu terminal, run the following to install pwntools: ```bash # install python3 sudo apt install -y python3-pip python3-venv # create a new `venv` called pwntools under home directory cd ~ python3 -m venv pwntools # enter the `venv` source pwntools/bin/activate # install pwntools pip install pwntools ``` ![image](https://hackmd.io/_uploads/rkTPZEYW1g.png) ##### Writing script With pwntools, it is easy to interact with the service and automate the steps. Start with this template: ```python= from pwn import * # context.log_level = "CRITICAL" # minimize logging r = remote("c55-flag-hasher.hkcert24.pwnable.hk", 1337, ssl=True) r.recvuntil(b"2 - Read Hash record\n") # wait until we receive this text... which is when we need to response r.sendline(b'2') # and send the command r.recvuntil(b"Idx: ") idx = 0 r.sendline(str(idx).encode()) # convert `idx` to string, and send it server_response = r.recvline() # save server response to variable print(server_response) hex_ouput = server_response.split(b" : ")[1] # get only the hex part out of the server response print("Received hex: ", hex_ouput) ``` Save it as `solve.py`. When you execute it with `python3 solve.py`, it will return the content of `idx=0` (`hashlist[0]`), same as what we tried manually! Modify the script to make it try automatically to get higher, higher up on the stack to find for flags. ![image](https://hackmd.io/_uploads/S1iOWVKWkl.png) ##### Get flag! Once you found out the way to automate getting memory content, all you need to to is look for flags with your eyes :eyes: ! ![image](https://hackmd.io/_uploads/ByMtZ4tb1l.png) ## Web: Webpage to PDF (1) ### Challenge Summary The webpage UI contains a URL input box and a submit button. ![](https://hackmd.io/_uploads/Syn6h0oekg.png) The challenge also provided its source code, where `execute_command.py` was written by AI from Poe. ![](https://hackmd.io/_uploads/B1t5yyneJl.png) ![](https://hackmd.io/_uploads/ByZAgknlJx.png) ### Solution The following steps would be required for tackling the challenge: - Observe the challenge website - Observe the challenge source code - Understanding the goal of the challenge - Finding the vulnerability to achieve the goal - Setup an attacker-controlled website (How to create Website 101) - Attack and get the flag! #### Observe the challenge website To attack a website, first we need to know how a normal user use it. Let's use the website in multiple ways. 1. Put `https://example.com` into the `Enter URL` input box, then you will get a PDF for the webpage. ![](https://hackmd.io/_uploads/BkaVpRoe1e.png) 2. Put `https://google.com` as the URL, an error occurred :face_palm: "Blocked access to file", hmm... ![](https://hackmd.io/_uploads/H1l7EVralkg.png) 3. Put `https://facebook.com`, it works, with the same resulting file name `c8e50698...` :thinking_face: ![image](https://hackmd.io/_uploads/r1a8VH6xJg.png) 4. Open the PDF file info, and the `Creator` field indicating it is created with `wkhtmltopdf 0.12.5` ![](https://hackmd.io/_uploads/HJWaY1nlye.png) 5. Why is it getting the same file name? It is because the website remembers you using something called Cookie! :cookie: You can find the `session_id` cookie by opening the Developer Tools with `Ctrl-Shift-I` and switching to the `Application` tab. It is the same as file name `c8e50698...` ![](https://hackmd.io/_uploads/S1vkt13gkg.png) #### Observe the challenge source code The provided challenge source code is in the following structure. ``` - chal - src - execute_command.py # ✅ Main source code file - main.py # ✅ Main source code file - requirements.txt # ❌ Not (very) relevant - Dockerfile # ✅ Container Definition file - flag.txt # ❌ Not (very) relevant - docker-compose.yml # ❌ Not (very) relevant ``` First, let's look at the main source code files. As you might have guessed, the `main.py` is the main entry point: ![](https://hackmd.io/_uploads/HkaKAkhxyx.png) After you submit the URL, it basically does two things: 1. Download the URL and save it as `html_file` `{session_id}.html` on line 51 2. Convert the HTML file `{session_id}.html` to PDF file `{session_id}.pdf` with the `wkhtmltopdf` command on line 54 Note that the `session_id` in the filenames was read from Cookie, which **we can modify in the Development Tool** (see previous section)! The `execute_command` function is from `execute_command.py`, let's look at that too. ![](https://hackmd.io/_uploads/SyucGghgkl.png) This code snippet was generated by AI from Poe (Large Language Model, LLM), and as described, all it does is execute the provided command "securely". How secure is it? It makes use of `shlex.split` to split the command into arguments. In the Linux Shell, commands and arguments look like this: ```bash wkhtmltopdf {session_id}.html {session_id}.pdf # ^ ^ ^ # arg0 arg1 arg2 (arg = argument) ``` The `shlex.split` function will split it like this for passing to `subprocess.run`: ```py ["wkhtmltopdf", "{session_id}.html", "{session_id}.pdf"] ``` #### Understanding the goal of the challenge Let's read the `Dockerfile`. `Dockerfile` defines how we built the challenge environment with `Docker`, which is something like a virtual machine (VM) that allows us to run multiple challenges on the same server. ![](https://hackmd.io/_uploads/r121ve2lJg.png) Our ultimate target, the flag file was copied to the root folder `/`, which means we have to read the content of `/flag.txt`. As the file name is known, we can read the file with two common techniques: Local File Inclusion (LFI) or Remote Code Execution (RCE). **Local File Inclusion (LFI)**: This attack refers to reading the flag file by directly reading it or including it in the program output. **Remote Code Execution (RCE)**: This attack refers to running commands on the server, in which the attacker gains complete control over the server. We have to change the input to the application and try to achieve these goals to get the flag. As this is a simple challenge, we have only around 2 inputs we can control: the `session_id` and the `URL` (the webpage). #### Finding the vulnerability to achieve the goal Okay, we have performed a through review on the vulnerable application. Now, where is the vulnerability we can perform LFI or RCE? As it is using `wkhtmltopdf`, let's Google it! ![](https://hackmd.io/_uploads/B14q4WheJx.png) Wow, there are many interesting links! The [third one](https://www.virtuesecurity.com/kb/wkhtmltopdf-file-inclusion-vulnerability-2/) looks like the LFI we want? ![](https://hackmd.io/_uploads/rkDWLbne1e.png) In the blog post, the vulnerable application generates PDF from user-provided HTML, while in this challenge, we have to provide a URL but not HTML ... We are not going to read `/etc/passwd` but we want `/flag.txt` too. HTML is the "programming language" for writing webpages, which means we have to set up a website by ourselves and pass the URL to our website to the challenge in order to achieve LFI! #### Setup an attacker-controlled website (How to create Website 101) There are many ways to create an attacker-controlled website. The easiest way is to make use of online "playground" services, such as: [JS Bin](https://jsbin.com/) which allows you to write HTML code and get a URL to share with friends or fellow developers. ![](https://hackmd.io/_uploads/rkidWkTe1l.png) To start, let's write a simple webpage! Put the following code between `<body>` and `</body>`: ```html <h1>Hello world!</h1> <font color="red">I am apple!</font> ``` ![](https://hackmd.io/_uploads/BkqO7yTl1g.png) As you can see, on the left is our HTML code, and on the right is our webpage. To get a URL to show only the webpage, first do `File -> Save`, then click on the "Share" button on the top. ![image](https://hackmd.io/_uploads/BySqESpxJl.png) Send the URL obtained to the PDF challenge, and we can see it turns our webpage into a PDF! ![image](https://hackmd.io/_uploads/BktkHkpxkx.png) #### Attack and get the flag Combining all the techniques above, we can change the JS bin to the following content similar to the blog post: ```html <h1>Hello world!</h1> <iframe src="file:///flag.txt" height="500" width="500"> ``` As we wanted to read `/flag.txt` to get the flag, we changed it from the original blog post. After saving it and making the PDF again, we should get our flag. Spoiler: it didn't work. ![image](https://hackmd.io/_uploads/S1xn4rpe1e.png) What should we do? We are so close to the flag! But it is blocked by some error message! As the world is big, we can be pretty sure that someone has gone into the same situation as us. Let's Google it and you will find this: ![](https://hackmd.io/_uploads/HyPaUb3g1l.png) ![](https://hackmd.io/_uploads/H1yyvW2xyg.png) The Stackoverflow answer stated that we might need this "command line parameter": ```bash --enable-local-file-access ``` It means normally you would use this command line parameter/arguments like this: ```bash wkhtmltopdf --enable-local-file-access something.html something.pdf ``` Can we make the server run `wkhtmltopdf` with the parameter/argument like above? Yes! Did we mention we could modify the `session_id` in the wkhtmltopdf command? ``` wkhtmltopdf {session_id}.html {session_id}.pdf ``` We can modify the value of `session_id` by opening the Development Tool. (How? See step 5 of [Observe the challenge website](#Observe-the-challenge-website)). Double-click on the value of your `session_id` and add `--enable-local-file-access ` to the start of the value. Mind the space. ![](https://hackmd.io/_uploads/HyrRjy6eyg.png) Then, when we submit the URL again, the server will run the command similar to this: ``` wkhtmltopdf --enable-local-file-access abcedf.html --enable-local-file-access abcedf.pdf ``` ![](https://hackmd.io/_uploads/SkeP2JTlyg.png) The redirect function was broken, as our file would be generated at `{session_id}.pdf`. Remove the `--enable-local-file-access%20` from the URL, then you can get the flag! ![](https://hackmd.io/_uploads/HkIJay6lke.png) ### Afterwords The probabilistic nature of Poe (ChatGPT/LLM) means that we cannot guarantee it is secure even if it is secure 99% of the time. There are lot of research and development work to make our little cute AI behave, from generating correct JSON output to keeping secrets well. Despite all the efforts, we still can't be confident in the correctness of their output, therefore always take a grain of salt when consuming AI work. Congrats for finishing this tutorial! You might also try "Webpage to PDF (2)" (which is arguably simpler than this!) ## Misc: B6ACP 1. Explore the webpage. What code is generated after you fire a search? ![1-get](https://hackmd.io/_uploads/SyCqHN6xyl.png) ![1-post](https://hackmd.io/_uploads/rJfjBVTlkx.png) 2. What information you can get about the server and the service? ![2-recon](https://hackmd.io/_uploads/SyMhSEpxJe.png) - searchor/2.4.1 - Werkzeug/3.0.6 - Python/3.13.0 3. Research about the information you have gathered? Which one (or more) of them is (are) has (have) known vulnerabilities? ![3-vuln](https://hackmd.io/_uploads/By9nS4pekg.png) 4. Is there a ready-to-use exploit script? 5. If the script exploiting the known vulnerabilities does not work, why does it not?