Wednesday, September 30, 2015

Microcorruption - Addis Ababa


Addis Ababa

At this point, I decided to see if the same kind of code exists as did in the last level:

448a:  8193 0000      tst       0x0(sp)
448e:  0324               jz        #0x4496 <main+0x5e>
4490:  b012 da44      call      #0x44da <unlock_door>
4494:  053c               jmp       #0x44a0 <main+0x68>
4496:  3012 1f45      push      #0x451f "That entry is not valid."
449a:  b012 c845      call      #0x45c8 <printf>
449e:  2153               incd      sp
44a0:  0f43                clr       r15
44a2:  3150 1600      add       #0x16, sp

Maybe not, there is no final < ret > call that uses the value on the stack, instead the code falls through to 

44a6 <__stop_progExec__>


It  looks like they finally patched things. However there is one place that if we could get a non-zero value onto the stack, we could open the door. 

448a:  8193 0000      tst       0x0(sp)
448e:  0324               jz        #0x4496 <main+0x5e>
4490:  b012 da44      call      #0x44da <unlock_door>

Specifically that address being tested in 4286. 4288 is the starting address of our user input.

Looking at the code some more we see that they are using printf – the format string function in C – to display user input. This is probably what the game designers want us to attack.

The format string vulnerability has been around for more than a decade, but so much code is written in C, and it is such a powerful exploit, that it is worth learning about.

The format string function takes an unspecified amount of arguments and an unspecified amount of format string parameters – and they don't have to match in number. Additionally, one of the format string parameters %n allows you to write to memory.

I suppose at some point this was a neat idea; I wish I had been there for that conversation. 

Basically you ask for user input and give the user the power to write to memory of the program – even if you don't want them to. For more information about format string check out owasp, wikipedia or stackoverflow.

So let's combine the knowledge that we have:
the power to write to memory
an address the is checked for non-zero

Writing a specific value to that memory might be a problem, but all we really need to do is write any non-zero number. So, we provide the address we want to write to, then write to it. After which it is tested for non-zero and the door is unlocked.

86 42                                       25 78     25 6E

--address (little endian)----   % x --- %  s –

That's it. Printf will write a number (that number being the number of bytes printed) to the address specified.


Try using some of the other format string parameters to see if you can get a better cycle time.

Monday, September 14, 2015

Microcorruption - Jakarta


JAKARTA

Again we see that at the very end of the main sequence we have the following bits of code where 0x22 is added to the stack pointer and then we return to that point indicated by the stack pointer:

4626:  3f40 4245      mov #0x4542 "That password is not correct.", r15
462a:  b012 c846      call #0x46c8 <puts>
462e:  3150 2200      add #0x22, sp
4632:  3b41              pop r11
4634:  3041                   ret


As before we should be able to inject our code, overflow the stack and leave our desired address on the stack. 

Username stored at 0x3ff2
Password stored at <end of username>
Return         stored at 0x4016     - address to return to is 4440 (clears r15 then prog stop)


A username of regular characters that is too long triggers a password too long error.

The length of the username is determined by within puts (0x46c8) and the resulting length is popped into R11.

This is a loop that starts counting at 2401 (temp memory storage) and measures how long the password is.

45ee:  3f40 0124     mov #0x2401, r15
45f2:  1f53           inc r15       < -------
45f4:  cf93 0000      tst.b 0x0(r15)                |
45f8:  fc23           jnz #0x45f2 <login+0x92> ---------
45fa:  3f80 0224      sub #0x2402, r15 total is … ?
45fe:  0f5b           add r11, r15         now add the two together for total length
4600:  7f90 2100    cmp.b #0x21, r15 r15 - #0x21 and set some flags ...
4604:  0628           jnc #0x4612 <login+0xb2> if no carry, jump to fail

but hey, we are just looking at the low end bytes of r15 right? 
cmp.b is the command. Thus our combined length in r15 is either less than 0x00 to 0x20 or like 0x101...

So as a starting plan: fill the space with garbage excepting address space 4016 (which is 35 bytes in from start). The username itself has to be less than 0x20 (32) and the password length combined with the username length has to be 0x101 (257) so the password has to be of length 0xE1 (225) characters.

Let's try the following:
---------------------------------------------------------------------------------
username: aaaaaaaaaabbbbbbbbbbccccccccccdd
password: aaaaLDaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjaaaaaaaaaabbbbbbbbbbcccc


33,836 cycles


But we can recycle our old code to do better cyclewise …

Monday, August 31, 2015

Microcorruption - Santa Cruz


It's been awhile since I published anything related to Embedded CTF, so here is another level that I had in the queue...

Santa Cruz is a little more cryptic in that functions are more poorly named.

There is still a lot of similarity between this level and the previous however. For example, both levels continue to have the very end of the login adjust the stack pointer to a potentially vulnerable spot and then return to the address stored at that spot. This is likely to be our vulnerability again.

On a lark I tried something different to start. I wondered what happened if we injected like 500 characters instead of say 50. My initial thinking was that I could inject enough garbage and overwrite one critical return point with a call to <unlock_door> where the beginning of <stop_progEXEC> occurs. The result would have been the last thing the program did after telling you that you failed and that your password was too long and then trying to quit on you would have been to unlock the door for you. It turns out however that the maximum amount of characters that will be read in is 100. I tried a direct approach of overloading with several hundred but it limited my maximum input. 

So maybe we should put that idea into our back pocket for some other time.

Inspection of the code shows that normal program execution never calls <__do_nothing> and also does not call <test_username_and_password_valid>

Some exploration with input yields the following behavior:

  • The full length of the username and password are copied (up too 100 characters each).
  • The start of the username is always address 0x43a2 regardless of username length.
  • The start of the password is always address 0x43b7 regardless of username or password length.
  • The code requires memory address 0x43c6 to be null.
  • The code requires memory address 0x4303 to be 0x08 - minimum length.
  • The code requires memory address 0x4304 to be 0x10 - max length.
  • A final call returns from 0x43cc if the password is not too long (this is the historical vulnerability).

Registers at about line 0x45d0
r11: 0x43b5

r15: 0x43b5 (start of pw)

r13: 0x43c6 (null delimiter put in by password)

r14: 0x43cc (houses return address)


Given that behavior and those requirements we can meet them with the following strategy:

usernameuse0812PASSWORD'\0'meusernameusernameSHELLCODESHELLCODESHELLCODE
<- fill ->< ^^REQD fill ^REQD><--- filler --><-- return point & code--->

where the password overwrites a portion of the user name in memory and is used to fullfill the requirement of the null delimiter at the correct address and the username is used to inject the code. As for the shell code itself we can use similar code to what we have previously been using. Likely we will have to alter it a bit as addresses have changed, but the basic tactic of either calling <unlock_door> directly or using the status register and the interupt trap will work.

Specifically you will need 42 characters of fill for the username after which shell code will start and a password of 15 charcters in length.

The following username and password entries will break the lock. Can you get better shell code based on the previous levels to get on the leaderboard?

Username: (hex code enabled)
4141414141414141414142424242424242081242434343434343434343434444444444444444444445454A44


length: 44, 12835 cycles

Sunday, August 16, 2015

Using Burp Suite with Cluster Bomb to Brute Force a Web Login

Of course you only are going to attempt a brute force login against something that you:

(A) Have permission to attack in the first place
(B) Know you won't affect the client's environment in a negative fashion including:
      (1) Lock out users
      (2) Knock over servers
      (3) Clog the network

Brute forcing is the kind of the thing that, if you know you aren't going to hurt stuff, makes sense to do while you are away getting lunch or otherwise have it going in the background. After all, you never know what you might find.

Choosing a good password list is a topic all to itself, and one I may cover at a later date. But for now let's assume that you have a list of users and some passwords. Cluster bombing always makes sense even if some of the passwords go with a specific user. For example, let's say that Joe has a password of Seahawks for his ssh login, but not for the web application in question. Let's also say that Susan has a password of Orioles for her FTP login but not for the web application.

What if Susan's password for the web application is Seahawks?

This might seem far fetched, but it happens, and if you include all the passwords that you have (or think as likely) and run them against all the user names that you have (or think as likely) and you are using Burp Suite, then you want to run a cluster bomb attack on the application.

So how to do it? First we need to set up our proxy for burp with the browser we are using so that we can capture login information...


Then we ensure that intercept is on for burp and enter our data on the web page. Notice that our username of 'foo' and password of 'bar' are captured. This information is held by burp and will be used over and over again in the attack.


Specifically, the parameters indicated will be replaced by contents of files - a list of user names and a list of passwords. The next step is to right click this screen and send it to intruder. Notice that, with the intruder tab selected, the sub tabs of Target, Positions, Payload and Options present themselves. Target won't have to be altered as we are using http or port 80, but our Positions will need to be specified. Remove the unwanted foo and bar - we only put them there so that were could easily identify where they were on the form.



On the next tab, Payloads, we will indicate what usernames and passwords will be plugged in for the attack. As we are using a cluster bomb attack every username will be tried with every password, which is what we want.

Then on the options tab you want to make certain that you handle redirections and start the attack.


Lastly, as you watch the attack in the background you can sort by length of results to see if you have any hits. For very little set up time these kinds of attacks may give you some level of additional access that you can leverage from information that you may already have.




Sunday, July 12, 2015

Damn You \xC2 ...

I was working on putting some code down in hex in a place it didn't belong. You can see in the image below a bit of the shell code and the code used to place it there. Not tremendously exciting stuff. But in particular you can see I have my initial buffer overflow filler on line 150, followed by a reliable address on line 151, a bit of a sled on line 152 and the shell code payload lastly on 153. Notice that nowhere is there a \xC2 or \xC3.



There are plenty of \x41 to be sure and several \x90s but no \xC2 or \xC3. Perhaps you may think that some got there within the shelled, but that isn't the case, and as you can clearly see there aren't any between the bytes that the NOP sled is composed of...


So where did they all come from? At first I thought maybe it was some DEP thing that I didn't know about (because there really is a LOT that I don't know about). But after experimenting a bit I realized, initially, it started with any bytes higher than \x7F - the limit of the ASCII range.

And that made it an encoding problem. Specifically line 163 encodes regular ASCII as UTF-8 which is fine but at line 165 when we hit hex outside the ASCII range we start to have problems in python 3. Python 2 took care of this seemingly automatically because the default encoding is "latin-1" which works for the range \x00-\xFF but UTF-8 doesn't and python 3 defaults to that. In any event I called out on line 165 for it to be UTF-8 which was not up to the task.

The story ends happily though. Changing line 165 to 'latin-1' results in the following...



Thursday, April 30, 2015

Network Penetration Testing - A First Glimpse

Two years ago I went to Defcon 21 and had my mind blown. I was taking an introduction to C++ course and looking for a career change. On a lark I decided to go to Defcon because it sounded pretty cool, and I love Vegas. While I was there I went to a ton of talks, met a lot of interesting and intelligent people, and didn't hit the tables once. It was definitely unusual.

While I was there I saw some guy on stage talking about pen testing - that is how a company will pay you to break into their network or their web application. I honestly thought that was the coolest thing around. Who wouldn't want to do that? I also thought that maybe someday I would even know enough or be lucky enough to get a job doing that.

A few weeks ago I just got back from a two week gig where the team I was part of worked a lot of 12 hour days breaking into everything we could at a client site - at the client's request. I even got to do a little social engineering and physical security penetration testing too. It was, of course, different than the movies: there were actual long hours, thousands of IP addresses, a million screenshots, and mountains of text to process and sift through with sed, awk, grep, cut, tr and python - a rigorous exercise in automation. It wasn't some color coded, graphical representation of a shape of virus that we manipulated by waving our hands with a flashing pop-up window at the end saying "access granted".

And there were the three weeks following that was all word documents. Tell them what you were supposed to do, tell them what you did, tell them you told them. And have an executive summary that says the same thing only with bullet points. Include pictures, everyone loves pictures.

But in some ways it was like a movie. There was a critical do or die moment when we clandestinely gained physical access to supposedly secured space. There were hours of failed attempts at accessing systems that ended with a 'Hail Mary' pass in the final moments of the deadline resulting in success. There was a password that was broken by guessing it Harrison Ford style from Clear and Present Danger. It wasn't quite "children's birthdays in reverse" but close enough for real life.

The best part besides being paid to do it of course, is that really you are a good guy. Your goal is to help the other good guys by showing them what they missed. Having done some sysadmin stuff it can be hard enough just to get things up and running as the technology and the business requirements are always changing - and not every sysadmin has been doing it for years, is created equal, or remembers everything every time. They are mostly underpaid, under staffed and overworked from what I have seen. So now, I get to help them when I can by showing them the things that I find and hope that it makes their jobs easier in the long run.



Figure 1 - Unauthorized physical access gained to secured workspace environment.


Take only pictures, leave only footprints no trace.


Wednesday, January 14, 2015

Microcorruption - Santa Cruz


Santa Cruz is a little more cryptic in that functions are more poorly named.

There is still a lot of similarity between this level and the previous however. For example, both levels continue to have the very end of the login adjust the stack pointer to a potentially vulnerable spot and then return to the address stored at that spot. This is likely to be our vulnerability again.

On a lark I tried something different to start. I wondered what happened if we injected like 500 characters instead of say 50. My initial thinking was that I could inject enough garbage and overwrite one critical return point with a call to <unlock_door> where the beginning of <stop_progEXEC> occurs. The result would have been the last thing the program did after telling you that you failed and that your password was too long and then trying to quit on you would have been to unlock the door for you. It turns out however that the maximum amount of characters that will be read in is 100. I tried a direct approach of overloading with several hundred but it limited my maximum input.

So maybe we should put that idea into our back pocket for some other time.

Inspection of the code shows that normal program execution never calls <__do_nothing> and also does not call <test_username_and_password_valid>

Some exploration with input yields the following behavior:

  • The full length of the username and password are copied (up too 100 characters each).
  • The start of the username is always address 0x43a2 regardless of username length.
  • The start of the password is always address 0x43b7 regardless of us
    <test_username_and_password_valid>

    Some exploration with input yields the following behavior:

  • The full length of the username and password are copied (up too 100 characters each).
  • The start of the username is always address 0x43a2 regardless of username length.
  • The start of the password is always address 0x43b7 regardless of us
  • ername or password length.
  • The code requires memory address 0x43c6 to be null.
  • The code requires memory address 0x4303 to be 0x08 - minimum length.
  • The code requires memory address 0x4304 to be 0x10 - max length.
  • A final call returns from 0x43cc if the password is not too long (this is the historical vulnerability).

Registers at about line 0x45d0
r11: 0x43b5
r15: 0x43b5 (start of pw)
r13: 0x43c6 (null delimiter put in by password)
r14: 0x43cc (houses return address)
Given that behavior and those requirements we can meet them with the following strategy:

usernameuse0812PASSWORD'\0'meusernameusernameSHELLCODESHELLCODE
<--- fill --->< ^^ REQD --fill-- ^ REQD>< --- filler --->< --- return point & code --->

where the password overwrites a portion of the user name in memory and is used to fullfill the requirement of the null delimiter at the correct address and the username is used to inject the code. As for the shell code itself we can use similar code to what we have previously been using. Likely we will have to alter it a bit as addresses have changed, but the basic tactic of either calling <unlock_door> directly or using the status register and the interupt trap will work.

Specifically you will need 42 characters of fill for the username after which shell code will start and a password of 15 charcters in length.

The following username and password entry will break the lock. Can you get better shell code based on the previous levels to get on the leaderboard?

Username: (hex code enabled)
4141414141414141414142424242424242081242434343434343434343434444444444444444444445454A44

length: 44, 12835 cycles