├── Crypto ├── AESthetics │ ├── HexMen │ │ ├── images │ │ │ ├── aes_ctr.png │ │ │ ├── png_block_structure.png │ │ │ ├── repeatingcounter.png │ │ │ └── spoiler.png │ │ └── writeup.md │ ├── MLH-flag{bearers} │ │ └── writeup.md │ ├── files │ │ ├── encrypt.c │ │ └── secret-flag.png.crypt │ └── readme.md ├── basic1 │ └── readme.md ├── basic2 │ └── readme.md ├── basic3 │ └── readme.md ├── needs-pepper │ ├── files │ │ └── flaglist.txt │ └── readme.md ├── needs-salt │ ├── files │ │ └── wordlist.txt │ └── readme.md ├── right-round │ ├── files │ │ └── flag.txt │ └── readme.md ├── substitution │ ├── files │ │ ├── flag.txt │ │ └── substitution.py │ └── readme.md └── why-md5 │ ├── files │ └── flag.txt │ └── readme.md ├── Forensics ├── Copy Copy Pasta │ ├── files │ │ └── flag.jpg │ └── readme.md ├── Copy Pasta │ ├── files │ │ └── interstellar-bike-meme.mp4 │ └── readme.md ├── Imposter │ └── readme.md ├── Oh oh oh it's maaagic! │ ├── files │ │ └── flag.jpg │ └── readme.md ├── Stop it! │ ├── files │ │ └── flag.jpg │ └── readme.md ├── The Intercept │ ├── files │ │ └── intercept.pcap │ └── readme.md ├── What's a file? │ ├── files │ │ └── flag.txt │ └── readme.md ├── Will ASMR │ └── readme.md ├── jibberish │ ├── files │ │ └── jiberish.txt │ └── readme.md └── jibberish2 │ ├── files │ └── jiberish2.txt │ └── readme.md ├── Misc ├── Cat in the net │ └── readme.md ├── Fellow Map │ ├── files │ │ └── chall.py │ └── readme.md ├── Merry Christmas │ ├── MLH-flag{bearers} │ │ └── writeup.md │ └── readme.md └── Mr. MLH │ └── readme.md ├── OSINT ├── ChromecatFM │ └── readme.md └── Good Friends │ └── readme.md ├── README.md ├── Reversing ├── ASMr │ ├── files │ │ └── r.asm │ └── readme.md ├── ASMr2 │ ├── files │ │ └── r.asm │ └── readme.md ├── F33dback App │ ├── MLH-flag{bearers} │ │ └── writeup.md │ └── readme.md └── readme │ ├── files │ └── will-1.py │ └── readme.md ├── Web ├── 1nsp3ct0r │ └── readme.md ├── Crack Me │ └── readme.md ├── Fortune Cookies │ └── readme.md ├── Om Nom Nom │ └── readme.md ├── Scratch The Wall │ └── readme.md └── Untrusted Client │ └── readme.md ├── Welcome ├── H3ll0 W0rld │ └── readme.md └── Rulez │ └── readme.md └── pwnable └── Will the Reader ├── files └── read.py └── readme.md /Crypto/AESthetics/HexMen/images/aes_ctr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Crypto/AESthetics/HexMen/images/aes_ctr.png -------------------------------------------------------------------------------- /Crypto/AESthetics/HexMen/images/png_block_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Crypto/AESthetics/HexMen/images/png_block_structure.png -------------------------------------------------------------------------------- /Crypto/AESthetics/HexMen/images/repeatingcounter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Crypto/AESthetics/HexMen/images/repeatingcounter.png -------------------------------------------------------------------------------- /Crypto/AESthetics/HexMen/images/spoiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Crypto/AESthetics/HexMen/images/spoiler.png -------------------------------------------------------------------------------- /Crypto/AESthetics/HexMen/writeup.md: -------------------------------------------------------------------------------- 1 | AESThetics was one of my favorite challenges. 2 | 3 | We are given two files (encrypt.c) and (secret-flag.png.crypt) and have to find the flag. We know that the file is a PNG and that it has been encrypted using AES, but we don't know the key. 4 | 5 | Initially I didn't have any idea about how to approach this problem. From my elementary knowledge of cryptography, I had initially thought it would be some variant of a AES cryptanalysis problem which is why I had set it aside since I didn't have much knowledge about that. 6 | 7 | I was looking up the function arc4_random_buf which is used to generate a random buffer and went down this wrong rabbit hole where I thought I had to exploit the fact that it was pseudorandom so that I can somehow predict the key (since the Wikipedia for RC4 was peppered with warnings about its predictability). Of course this was wrong off the bat. 8 | 9 | Later, I looked at the code once again and saw that it was pretty simple: 10 | It generates a random key of 16 bytes and a random counter value. 11 | 12 | 13 | Here the AES Cipher is operating in CTR Mode, i.e the input is not encrypted through the cipher directly. (So thankful that this came in the semester this is a part of my course 😆) 14 | 15 | ![CTR Mode](images/aes_ctr.png) 16 | Source: Wikipedia 17 | 18 | Output = (Encrypt(Key, Counter)) ^ Input block 19 | 20 | The code encrypts the input 16 bytes at a time, with the remaining bytes (if any) being padded with zeroes and encrypted. 21 | 22 | 23 | The output file consists of the 16 byte counter value followed by the encrypted bytes. 24 | 25 | 26 | It read from 0 (input), encrypted it in blocks of 16, calling the function inc_counter each time to increment the counter and writes the output block to 1 (output). 27 | 28 | It is here that I resorted to my favorite tool: print statements. I had a hunch that it was probably the inc_counter part that was buggy, since I didn't recognize its implementation and since it was calling a library function to encrypt the AES block, which is probably correct. I added a print statement at the end to see the counter value. 29 | 30 | 31 | ![](images/repeatingcounter.png) 32 | 33 | 34 | Do you see the problem? The counter value never gets updated. 35 | 36 | struct ctr_state { 37 | uint8_t key_bytes[16]; 38 | uint8_t counter[16]; 39 | }; 40 | 41 | The state being passed to the encrypt function has the above format. 42 | 43 | ctr_block_encrypt(struct ctr_state state, uint8_t *in, uint8_t *out)` 44 | 45 | If you look at the function signature, the problem is apparent: State is being passed by value. Thus the counter inside the state gets copied and the original state is never modified. 46 | 47 | 48 | 49 | Now what does this mean? Since the cipher output is derived from the key and the counter, and since the counter value is unchanging, there is only one cipher block output. 50 | 51 | All input blocks are being xored with the same cipher block to produce the output block. 52 | 53 | This means that if we had some known input block, then we can figure out the cipher block, since: 54 | 55 | Output_Block = (Input_Block ^ Cipher_Block) 56 | 57 | Output_Block ^ Input_Block = (Input_Block ^ InputBlock ^ Cipher_Block) = Cipher_Block 58 | 59 | Of course the problem of having a known input still remains. This is where we exploit the fact that it is a PNG. 60 | 61 | I had a feeling that there'll be some known bytes in the PNG structure. I took a look at Wikipedia, and bam, there is a known 8 byte signature: `89 50 4E 47 0D 0A 1A 0A` 62 | 63 | However, we need 16 bytes of known input. 64 | 65 | I explored the Wikipedia page some more, and found that a PNG file is divided into blocks with each block having the following structure: 66 | 67 | ![](images/png_block_structure.png) 68 | 69 | 70 | 71 | The first block of a PNG file is always the IHDR block. It contains the height, width and other info, but more importantly its length is known (13 bytes). 72 | 73 | Thus we know the first 4 bytes (the length) and the next 4 bytes (the IHDR type). 74 | 75 | Thus we know the first 16 bytes of the input file which would be common to any PNG. 76 | 77 | Now we just XOR this with the output to get the cipher block. 78 | 79 | To get the other input blocks, we just XOR the corresponding block with the cipher block we just obtained. 80 | 81 | Output_Block ^ Cipher_Block = Input_Block ^ Cipher_Block ^ Cipher_Block = Input_Block 82 | 83 | ## Code 84 | 85 | Now we have the concept out of the way, just need to implement it. I just modified the encrypt.c file for a quick and dirty fix. 86 | 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | 94 | #define SZ 5532 95 | 96 | 97 | 98 | /* helper to print hex strings */ 99 | void 100 | print_hex(uint8_t *buf, size_t len) 101 | { 102 | for (size_t i = 0; i < len; i++) { 103 | fprintf(stderr, "%02x", buf[i]); 104 | } 105 | fprintf(stderr, "\n"); 106 | } 107 | 108 | /* helper to increment the 128-bit counter */ 109 | void 110 | inc_counter(uint8_t *counter) 111 | { 112 | uint8_t *pos = counter + 15; 113 | while (pos > counter) { 114 | if (++(*pos) != 0x00) { 115 | return; 116 | } 117 | pos--; 118 | } 119 | 120 | (*pos)++; 121 | } 122 | 123 | 124 | void xor_block(uint8_t* out, uint8_t* in){ 125 | for (int i = 0; i < 16; i++) { 126 | out[i]^=in[i]; 127 | } 128 | } 129 | 130 | int 131 | main(int argc, char **argv) 132 | { 133 | 134 | uint8_t c1[16]; 135 | read(0, c1,16); // copy counter values; 136 | print_hex(c1, 16); 137 | 138 | uint8_t png_signature[8] = {0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A}; //Known PNG signature 139 | uint8_t header_known[8] = {0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52}; //Known first block 140 | uint8_t last_known[16] = {0x00, 0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82, 0x00,0x00,0x00,0x00}; //Last 12 bytes, for convenience 141 | uint8_t starting_known[16]; 142 | memcpy(starting_known, png_signature, 8); 143 | memcpy(starting_known+8, header_known, 8); //Concatenating two buffers (redundant) 144 | 145 | 146 | uint8_t buffer[SZ]; 147 | read(0, buffer, SZ); // Reading encrypted input into buffer 148 | uint8_t starting_known_cipher[16]; 149 | memcpy(starting_known_cipher, buffer, 16); //Copying first 16 bytes of encrypted input 150 | 151 | fprintf(stderr,"Starting known cipher: "); 152 | print_hex(starting_known_cipher, 16); 153 | xor_block(starting_known_cipher, starting_known); //Starting_Known_Cipher now contains the common cipher block 154 | 155 | int f = 0; 156 | int sz = SZ/16; 157 | 158 | for(int i = 0; i < sz; i++){ 159 | uint8_t out[16]; 160 | memcpy(out, &buffer[i*16], 16); 161 | print_hex(c1, 16); 162 | xor_block(out, starting_known_cipher); //Decrypt other blocks 163 | write(1, out, 16); 164 | } 165 | 166 | write(1, last_known, 12); 167 | return 0; 168 | } 169 | 170 | 171 | Once we decrypt the image using the above code, we get the flag ^.^ 172 | 173 |
174 | Spoiler Warning 175 | 176 | ![](spoiler.png) 177 |
178 | 179 | 180 | ## Failed attempt 181 | I had initially misinterpreted the output as showing that there are two counter values that are being used alternatively. This was from my initial hunch that the flaw was in the implementation of the inc_counter itself. 182 | 183 | Thus I had inadvertently solved a harder version of the problem: What if two cipher blocks are being used alternatively? 184 | 185 | In this case, we have already found the first cipher block, but we still need to find the second one, for which we need 16 more bytes of known input. 186 | 187 | The output file is 5548 bytes. Without the 16 byte counter value, it is 5532 bytes. 188 | 189 | 5532 / 16 ~ 345 blocks 190 | 5532 % 16 = 12 191 | The left over block (12 bytes) would be the last block. We know from the implementation that it'll be padded with zeroes, so we know the last 4 bytes. 192 | 193 | Here is where the PNG structure saves the day again, the PNG file ends with the IENDBlock. It is of zero size, its type bytes are known and its CRC is also known (since there is no data). Thus we also know the last 16 bytes. 194 | 195 | Of course this is useless since in the actual problem we need only one cipher block, and this is why my initial attempt gave a malformed decrypted png. 196 | 197 | Once I ignored the second block, it worked fine. 198 | 199 | Lesson: In modes of operation where you don't directly operate on the input, if your pseudo input values are not random an attacker may exploit some known details such as the file structure. 200 | -------------------------------------------------------------------------------- /Crypto/AESthetics/MLH-flag{bearers}/writeup.md: -------------------------------------------------------------------------------- 1 | ## The theory 2 | ``` 3 | Cryptography is beautiful, isn't it? You just have to use it right. 4 | ``` 5 | [secret-flag.png.crypt](https://github.com/raymond-devries/mlh-batch-1-ctf-writeups/blob/main/Crypto/AESthetics/files/secret-flag.png.crypt) [encrypt.c](https://github.com/raymond-devries/mlh-batch-1-ctf-writeups/blob/main/Crypto/AESthetics/files/encrypt.c) 6 | 7 | This challenge was on a different level, not gonna lie. I mean, to veteran CTF-ers, this would be medium (?) at best, but it was an absolute wreck for our team, as all of us were beginners. But the best part, we eventually solved it, right as the CTF was ending, tying in points but 4 minutes later than another team. Quite dramatic, yes. 8 | 9 | I had a serious love-hate relationship with this relationship but I probably learnt the *most* from this one. The first step to solving this challenge was to take apart the source code with a fine toothpick and secondly, understand how PNGs work. Since I am how I am, I did neither and immediately dug into the different kinds of possible attacks, known-plaintext, chosen-plaintext, forbidden whatnot (well, it was somewhat like a forbidden known-plaintext attack). 10 | 11 | So, the first step! Research. I read up on how block ciphers work and more importantly, the counter mode - really what that means is that I read a [bunch of pages](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) on Wikipedia. 🥱 But seriously, it was kind of worth it. In particular, I noticed the paragraph about known-plaintext attack but didn't understand anything because, yeah, cryptography, amirite. 12 | 13 | But I read this and that, one-time pad attack, two-time pad, all of that (yes, I was basking in my ignorance). All of that until the first hint was released: 14 | 15 | > the CTR implementation is buggy 16 | 17 | Despite knowing this, I had never actually figured out what was the bug - because I assumed that the bug was actually the code itself, which itself was only buggy because it was written with OpenBSD libraries not available on standard Linux distros. Ugh. (And yeah, those took hours to fix and script). 18 | 19 | Eventually, I got around to seeing the `inc_counter()` function in the script and had a very vague suspicion if it was actually written correctly because of they way it was written, I was very sure it was not changing the counter at all (that was not the actual problem apparently). The issue was with the `ctr_block_encrypt()` function parameter which receives a copy of the `struct` instead of a pointer to it: 20 | ```c 21 | ctr_block_encrypt(struct ctr_state state, uint8_t *in, uint8_t *out)` 22 | { 23 | ... 24 | } 25 | ``` 26 | So, I set to debugging with my favourite debugger, `fprintf`. I wrapped them around the function invocation, and lo and behold, no increment! The nonce was being reused. This opens us up to the world of attacks based on nonce-reuse. The part after this was actually more painful - figuring how to *guess* the plaintext to actually get the keystream - and then the decrypted file. 27 | 28 | ### PNGs say what? 29 | I was quite sure that this would have to be the way to decrypt the file because we know how they all have a unique file signature. I retrieved the hex values from the W3C PNG [spec site](http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature) and got to work. 30 | Using a crib dragging attack (a "crib" is known or guessed plaintext, making this a variant of a known-plaintext attack), I figured out the first half of the key, I got `5c 92 d5 10 d0 63 20 9d 00 00 00 00 00 00 00`. But I was truly stuck on the rest of the key, or so I thought - but I discovered that each PNG file at least has two other *critical* chunks - IHDR and IEND. 31 | Using the IEND (+ CRC) bytes, I used crib dragging to get a bit more out of the key, `5c 92 d5 10 d0 63 20 9d 34 cf 24 95 00 00 00 00` - finally, all that was left was to fit in IHDR into an appropriate block allowing us to guess the whole key. 32 | 33 | ![](https://dev-to-uploads.s3.amazonaws.com/i/pieypzhde97knuepirc8.png) 34 | 35 | We then dump the decrypted bytes into a .txt file, clean up the file to meet PNG specs (and remove the counter bytes), and open it to retrieve the flag! 36 | 37 | ![](https://dev-to-uploads.s3.amazonaws.com/i/677str27kwpazi19zg69.png) 38 | 39 | And we can finally get the flag with our own eyes - `mlh{n0nc3_m34ns_numb3r_u53d_ONCE}`. Truly a thrilling end to this journey (I remember screaming after getting this flag). 🏁 40 | -------------------------------------------------------------------------------- /Crypto/AESthetics/files/encrypt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct ctr_state { 9 | uint8_t key_bytes[16]; 10 | uint8_t counter[16]; 11 | }; 12 | 13 | /* helper to print hex strings */ 14 | void 15 | print_hex(uint8_t *buf, size_t len) 16 | { 17 | for (size_t i = 0; i < len; i++) { 18 | fprintf(stderr, "%02x", buf[i]); 19 | } 20 | fprintf(stderr, "\n"); 21 | } 22 | 23 | /* helper to increment the 128-bit counter */ 24 | void 25 | inc_counter(uint8_t *counter) 26 | { 27 | uint8_t *pos = counter + 15; 28 | while (pos > counter) { 29 | if (++(*pos) != 0x00) { 30 | return; 31 | } 32 | pos--; 33 | } 34 | (*pos)++; 35 | } 36 | 37 | /* block-level counter mode encryption. 38 | * takes the ctr mode state, a 128-bit block to encrypt, and a pointer 39 | * to a 128-bit output buffer. 40 | */ 41 | void 42 | ctr_block_encrypt(struct ctr_state state, uint8_t *in, uint8_t *out) 43 | { 44 | AES_KEY key; 45 | uint8_t pad[16]; 46 | 47 | /* encrypt the counter with AES */ 48 | AES_set_encrypt_key(state.key_bytes, 128, &key); 49 | AES_encrypt(state.counter, pad, &key); 50 | 51 | /* xor the plaintext with the pad */ 52 | for (int i = 0; i < 16; i++) { 53 | out[i] = in[i] ^ pad[i]; 54 | } 55 | 56 | /* increment the counter */ 57 | inc_counter(state.counter); 58 | } 59 | 60 | int 61 | main(int argc, char **argv) 62 | { 63 | struct ctr_state state; 64 | uint8_t input_buffer[16]; 65 | uint8_t output_buffer[16]; 66 | ssize_t bytes_read; 67 | size_t pos = 0; 68 | 69 | /* generate a random key */ 70 | arc4random_buf(state.key_bytes, 16); /* sorry, linux users! */ 71 | fprintf(stderr, "your super secure random key: "); 72 | print_hex(state.key_bytes, 16); 73 | 74 | /* start the counter at a random value; write it out as the 75 | * first 16 bytes of the output file (the counter is not 76 | * secret, only the key is!) 77 | */ 78 | arc4random_buf(state.counter, 16); 79 | write(1, state.counter, 16); 80 | 81 | /* initial zeroing of input buffer */ 82 | memset(input_buffer, 0x00, 16); 83 | 84 | /* read a byte at a type and encrypt 16-byte blocks */ 85 | while ((bytes_read = read(0, input_buffer+pos, 1)) > 0) { 86 | if (pos < 15) { 87 | pos++; 88 | continue; 89 | } else { 90 | ctr_block_encrypt(state, input_buffer, output_buffer); 91 | write(1, output_buffer, 16); 92 | memset(input_buffer, 0x00, 16); 93 | pos = 0; 94 | } 95 | } 96 | 97 | /* we've reached EOF; encrypt any leftover bytes */ 98 | if (pos != 0) { 99 | ctr_block_encrypt(state, input_buffer, output_buffer); 100 | write(1, output_buffer, pos); 101 | } 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /Crypto/AESthetics/files/secret-flag.png.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Crypto/AESthetics/files/secret-flag.png.crypt -------------------------------------------------------------------------------- /Crypto/AESthetics/readme.md: -------------------------------------------------------------------------------- 1 | 2 | AESthetics 3 | ========== 4 | 5 | 6 | Value: 496 7 | 8 | Solves: 4 9 | 10 | Prompt: Cryptography is beautiful, isn't it? You just have to use it right. -------------------------------------------------------------------------------- /Crypto/basic1/readme.md: -------------------------------------------------------------------------------- 1 | 2 | basic1 3 | ====== 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 50 9 | 10 | Solves: 37 11 | 12 | Prompt: Crypto is Basic: `01101101 01101100 01101000 01111011 01110100 00110000 01101100 01100100 01011111 01111001 00110000 01110101 01011111 01101001 01110100 01011111 01110111 00110100 01110011 01011111 01100101 01100001 01111010 01111001 01111101` 13 | -------------------------------------------------------------------------------- /Crypto/basic2/readme.md: -------------------------------------------------------------------------------- 1 | 2 | basic2 3 | ====== 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 50 9 | 10 | Solves: 31 11 | 12 | Prompt: Crypto is VERY basic: `bWxoe2lfbTNhbnRfYjRzaWNfbjB0X2Vhenl9` 13 | -------------------------------------------------------------------------------- /Crypto/basic3/readme.md: -------------------------------------------------------------------------------- 1 | 2 | basic3 3 | ====== 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 300 9 | 10 | Solves: 21 11 | 12 | Prompt: No hints now, deal? `155 154 150 173 060 143 164 064 154 137 061 163 137 163 164 061 154 154 137 156 060 164 137 164 150 064 164 137 150 064 162 144 175` 13 | -------------------------------------------------------------------------------- /Crypto/needs-pepper/readme.md: -------------------------------------------------------------------------------- 1 | 2 | needs-pepper 3 | ============ 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 500 9 | 10 | Solves: 2 11 | 12 | Prompt: Remember `Needs salt`? Well I ate that and its lacking some pepper. Could you find me some? They say it's somewhere in `35.223.35.180:3000`

**Note**: Careful with `\n`'s. These things are nasty 13 | -------------------------------------------------------------------------------- /Crypto/needs-salt/readme.md: -------------------------------------------------------------------------------- 1 | 2 | needs-salt 3 | ========== 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 372 9 | 10 | Solves: 17 11 | 12 | Prompt: Remember `Why md5`? Well I ate that and its lacking some salt, so I've put `kosher`

**md5(salt+flag)**: = `ac1a4e2bb05ddce89abe725e60c27a04`

**Relevant meme**: https://www.youtube.com/watch?v=uPWsUAC3MR0 13 | -------------------------------------------------------------------------------- /Crypto/right-round/files/flag.txt: -------------------------------------------------------------------------------- 1 | You spin my head right round, right round 2 | When you go down, when you go down down 3 | You spin my head right round, right round 4 | 5 | 6 | Flag: edz{qgm_khaf_eq_zwsv_jayzl_jgmfv_tstq_jayzl_jgmfv} 7 | -------------------------------------------------------------------------------- /Crypto/right-round/readme.md: -------------------------------------------------------------------------------- 1 | 2 | right-round 3 | =========== 4 | 5 | 6 | Tags: cryto 7 | 8 | Value: 372 9 | 10 | Solves: 17 11 | 12 | Prompt: You spin my head right round, right round
When you go down, when you go down down
You spin my head right round, right round

**Flag**: edz{qgm_khaf_eq_zwsv_jayzl_jgmfv_tstq_jayzl_jgmfv} 13 | -------------------------------------------------------------------------------- /Crypto/substitution/files/flag.txt: -------------------------------------------------------------------------------- 1 | Will's taking a course on cybersecurity at uni. 2 | Gabriel tried to help him with substitution ciphers but it turns out gabe is also not the best at crypto. 3 | They then come to you, our crypto hero, to help them. 4 | Can you crack this substitution cipher? 5 | 6 | 7 | Flag: njhXzuizobouobtmLOLbzLOLmtoLOLoheoLOLherdLOLjedzY 8 | -------------------------------------------------------------------------------- /Crypto/substitution/files/substitution.py: -------------------------------------------------------------------------------- 1 | substitution = { 2 | 'a': 'e', 3 | 'b': 'i', 4 | 'c': 'k', 5 | 'd': 'd', 6 | 'e': 'a', 7 | 'f': 'f', 8 | 'g': 'g', 9 | 'h': 'h', 10 | 'i': 'b', 11 | 'j': 'l', 12 | 'k': 'c', 13 | 'l': 'j', 14 | 'm': 'n', 15 | 'n': 'm', 16 | 'o': 't', 17 | 'p': 'q', 18 | 'q': 'p', 19 | 'r': 'r', 20 | 's': 'z', 21 | 't': 'o', 22 | 'u': 'u', 23 | 'v': 'v', 24 | 'w': 'x', 25 | 'x': 'w', 26 | 'y': 'y', 27 | 'z': 's', 28 | '{': 'X', 29 | '}': 'Y', 30 | '_': 'LOL', 31 | } 32 | 33 | 34 | def encrypt(plaintext: str) -> str: 35 | ciphertext = '' 36 | 37 | for letter in plaintext: 38 | ciphertext += substitution[letter] 39 | 40 | return ciphertext 41 | 42 | 43 | if __name__ == '__main__': 44 | plaintext = input() 45 | print(encrypt(plaintext)) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Crypto/substitution/readme.md: -------------------------------------------------------------------------------- 1 | 2 | substitution 3 | ============ 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 50 9 | 10 | Solves: 31 11 | 12 | Prompt: Will's taking a course on cybersecurity at uni. Gabriel tried to help him with substitution ciphers but it turns out gabe is also not the best at crypto. They then come to you, our crypto hero, to help them. Can you crack this substitution cipher?

**Flag**: njhXzuizobouobtmLOLbzLOLmtoLOLoheoLOLherdLOLjedzY 13 | -------------------------------------------------------------------------------- /Crypto/why-md5/files/flag.txt: -------------------------------------------------------------------------------- 1 | mlh{776bbc50e5a004b2531cce99292240a1} 2 | -------------------------------------------------------------------------------- /Crypto/why-md5/readme.md: -------------------------------------------------------------------------------- 1 | 2 | why-md5 3 | ======= 4 | 5 | 6 | Tags: crypto 7 | 8 | Value: 50 9 | 10 | Solves: 35 11 | 12 | Prompt: This is why we don't use MD5 anymore

**Flag**: `mlh{776bbc50e5a004b2531cce99292240a1}` 13 | -------------------------------------------------------------------------------- /Forensics/Copy Copy Pasta/files/flag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/Copy Copy Pasta/files/flag.jpg -------------------------------------------------------------------------------- /Forensics/Copy Copy Pasta/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Copy Copy Pasta 3 | =============== 4 | 5 | 6 | Value: 280 7 | 8 | Solves: 21 9 | 10 | Prompt: How do you hide text inside of a JPEG file? 11 | -------------------------------------------------------------------------------- /Forensics/Copy Pasta/files/interstellar-bike-meme.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/Copy Pasta/files/interstellar-bike-meme.mp4 -------------------------------------------------------------------------------- /Forensics/Copy Pasta/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Copy Pasta 3 | ========== 4 | 5 | 6 | Value: 402 7 | 8 | Solves: 15 9 | 10 | Prompt: Arsalan does a bunch of stuff besides rocking at the CTF team. His last endeavor was carpentry. He's been doing all sorts of interesting wooden sculptures! He's now looking into a new technique: wood carving.

In the mean time, I, Gabriel, have also been doing a lot of productive stuff like watching low quality minecraft memes on youtube. I was having internet issues so I downloaded the video so I could keep watching when internet was down. Here take a look!

I don't know why I keep telling you all this nonsense, here are some random numbers:

`bs=1` `skip=14306` `count=48` 11 | -------------------------------------------------------------------------------- /Forensics/Imposter/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Imposter 3 | ======== 4 | 5 | 6 | Value: 356 7 | 8 | Solves: 18 9 | 10 | Prompt: For Some reason everyone on twitch stream thinks that Karan is sus, to prove his innocence he sent over a video. 11 | ![karan_is_sus.png](/files/ef64cd16925d7dc523e35f7fbfe09fef/karan_is_sus.png) 12 | 13 | What do you think, is he an imposter or crewmate? 14 |

[Video Link](https://drive.google.com/file/d/1qFDKDQo07SEi7G1ZsDNAyr9JeonMnm8d/view?usp=sharing)

**Note**: The flag is mlh{answer}, where answer is what you get on solving the chall. 15 | -------------------------------------------------------------------------------- /Forensics/Oh oh oh it's maaagic!/files/flag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/Oh oh oh it's maaagic!/files/flag.jpg -------------------------------------------------------------------------------- /Forensics/Oh oh oh it's maaagic!/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Oh oh oh it's maaagic! 3 | ====================== 4 | 5 | 6 | Value: 388 7 | 8 | Solves: 15 9 | 10 | Prompt: You knooooooow 11 | -------------------------------------------------------------------------------- /Forensics/Stop it!/files/flag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/Stop it!/files/flag.jpg -------------------------------------------------------------------------------- /Forensics/Stop it!/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Stop it! 3 | ======== 4 | 5 | 6 | Value: 482 7 | 8 | Solves: 7 9 | 10 | Prompt: Where's the end of a JPG image?

**Note**: You'll regret stopping to study stego for this chall 11 | -------------------------------------------------------------------------------- /Forensics/The Intercept/files/intercept.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/The Intercept/files/intercept.pcap -------------------------------------------------------------------------------- /Forensics/The Intercept/readme.md: -------------------------------------------------------------------------------- 1 | 2 | The Intercept 3 | ============= 4 | 5 | 6 | Value: 428 7 | 8 | Solves: 13 9 | 10 | Prompt: We're trying to figure out what the MLH crew is preparing for the graduation ceremony. We have an inside man, Will, that captured one of Swift's calls with Leah that we think could lead us to the information we need. 11 | 12 | **Obs**: You might want to take a look at [Wireshark](https://ctf101.org/forensics/what-is-wireshark/) for this one. -------------------------------------------------------------------------------- /Forensics/What's a file?/files/flag.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raymond-devries/mlh-batch-1-ctf-writeups/73ed315192da4c26a57190d3518a765bb668836c/Forensics/What's a file?/files/flag.txt -------------------------------------------------------------------------------- /Forensics/What's a file?/readme.md: -------------------------------------------------------------------------------- 1 | 2 | What's a file? 3 | ============== 4 | 5 | 6 | Value: 388 7 | 8 | Solves: 16 9 | 10 | Prompt: -------------------------------------------------------------------------------- /Forensics/Will ASMR/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Will ASMR 3 | ========= 4 | 5 | 6 | Tags: Will 7 | 8 | Value: 440 9 | 10 | Solves: 12 11 | 12 | Prompt: We were able to convince Will to give everyone a sneak peek into the graduation video!! 🔥🔥

[Link](https://youtu.be/guTrJch2xjE) 13 | -------------------------------------------------------------------------------- /Forensics/jibberish/readme.md: -------------------------------------------------------------------------------- 1 | 2 | jibberish 3 | ========= 4 | 5 | 6 | Tags: forensics 7 | 8 | Value: 50 9 | 10 | Solves: 32 11 | 12 | Prompt: "Read it all", they said. Hackers, on the other hand, are not patient. 13 | -------------------------------------------------------------------------------- /Forensics/jibberish2/readme.md: -------------------------------------------------------------------------------- 1 | 2 | jibberish2 3 | ========== 4 | 5 | 6 | Tags: forensics 7 | 8 | Value: 320 9 | 10 | Solves: 20 11 | 12 | Prompt: All of the flags are fake but one. The real flag has exactly **four** words in the middle separated by underscores ( `_` ).

Example of real flag: `mlh{one_two_three_four}` or `mlh{this_is_for_real}` Example of fake flag: `mlh{one_two_three_four_five}` or `mlh{this_is_not_a_flag}` 13 | -------------------------------------------------------------------------------- /Misc/Cat in the net/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Cat in the net 3 | ============== 4 | 5 | 6 | Tags: misc 7 | 8 | Value: 136 9 | 10 | Solves: 27 11 | 12 | Prompt: Netcat is a very important tool not only in cybersecurity, but networking in general. Find out how to use it and get the flag at `35.223.35.180:4010`

**Note**: There are various different versions of netcat. Either should work. 13 | -------------------------------------------------------------------------------- /Misc/Fellow Map/files/chall.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | cipher = ['6PJH', '6PW3', '6PPG', '6PMV', '6JG7', '7M29', '6MQQ', '7P3H', '6PRR', '7P5C', '6MXQ', '7P62', '6PHP', '7P4P', '6PV6'] 4 | random.shuffle(cipher) 5 | 6 | salt = "2222+22" 7 | for i in cipher: 8 | print(i+salt) 9 | -------------------------------------------------------------------------------- /Misc/Fellow Map/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Fellow Map 3 | ========== 4 | 5 | 6 | Value: 476 7 | 8 | Solves: 8 9 | 10 | Prompt: Karan has still not uploaded his photo for the world map that will is working on and will is mad about it! 11 |

**Note**: The flag is mlh{answer}, where answer is what you get on solving the chall. 12 | -------------------------------------------------------------------------------- /Misc/Merry Christmas/MLH-flag{bearers}/writeup.md: -------------------------------------------------------------------------------- 1 | ## The Misc. 2 | ``` 3 | Silent Night, Holy Night, All is calm all is well. 4 | Well, jingle bells are all around the town and Karan is 5 | reminiscing the time he spent with Santa last year. 6 | Going through images and reviews he left around town, 7 | he wants you to visit and have a glimpse of his fun times. 8 | The ticket that leads you to the place is within the 9 | registration email. 10 | Category: Misc. 11 | ``` 12 | > [Link](https://www.youtube.com/watch?v=Cp4RRAEgpeU) 13 | 14 | The "...ticket that leads you to the place is within the 15 | registration email" is a pretty blatant hint, I can just search for the email using filters. 16 | 17 | ![](https://dev-to-uploads.s3.amazonaws.com/i/4jjhuvz74r5ahsrd25sc.png) 18 | 19 | Once you click on reply to the email and hover over the email ID, you should get a dynamically generated hovercard, which contains the UID of the user. Then, you need to make an educated guess about where to go next but the fact that we have a video of the Santa Village and you needed the ***Gmail*** address should tell you where to go next - of course, Google Maps. In fact, you could've just looked up the reviews of the village in the course of the investigation (as a lot of people did) and even found Karan's reviews (which also a lot of people did). 20 | 21 | The approach was to basically access the user's map contributions by going to `https://www.google.com/maps/contrib/` and finding the reviews (well, not exactly). 22 | 23 | But as has been said, it's a *miscellaneous* challenge, not an *OSINT* one. 24 | The second part is a steganography challenge and it's not immediately clear sadly. But hey, sometimes you gotta try everything. The flag was actually (very well) hidden in one of the images (out of two) uploaded with the reviews (out of two). I was eventually able to extract the flag with PCA with relative ease, just took a while because it can be *literally* anywhere. 25 | 26 | ![](https://dev-to-uploads.s3.amazonaws.com/i/otfc7jh3jq0p2r5htr62.png) 27 | 28 | And there, we find the flag - `mlh{M3rry_Chr1stmas}` 🆙 29 | -------------------------------------------------------------------------------- /Misc/Merry Christmas/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Merry Christmas 3 | =============== 4 | 5 | 6 | Value: 496 7 | 8 | Solves: 4 9 | 10 | Prompt: Silent Night, Holy Night, All is calm all is well. Well, jingle bells are all around the town and Karan is reminiscing the time he spent with Santa last year. Going through images and reviews he left around town, he wants you to visit and have a glimpse of his fun times. The ticket that leads you to the place is within the registration email.

[Link](https://www.youtube.com/watch?v=Cp4RRAEgpeU) 11 | -------------------------------------------------------------------------------- /Misc/Mr. MLH/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Mr. MLH 3 | ======= 4 | 5 | 6 | Tags: misc 7 | 8 | Value: 488 9 | 10 | Solves: 6 11 | 12 | Prompt: Swift and Will have been working really hard to create a new security system for the MLH website, and now they've come up with this access system called "Mr. MLH". In this system, each user is determined by their `User-Agent` and every user has a hash code associated with them, and only one user is our "Mr. MLH" and has admin access.

They asked you, our security specialist hero, to help out testing to see if there are any flaws on the new system.

Access the website at `35.223.35.180:4000`

**Note**: MLH User-Agents are all lowercase letters only 13 | -------------------------------------------------------------------------------- /OSINT/ChromecatFM/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ChromecatFM 3 | =========== 4 | 5 | 6 | Tags: misc 7 | 8 | Value: 482 9 | 10 | Solves: 7 11 | 12 | Prompt: Will apparently thinks that "Chromecast is great for MonstercatFM". Can you find out what was he playing when he said that?

**Note**: The answer is one word, the flag is formed like `mlh{word}`. So, for example, if the answer was `chicken` then the flag would be `mlh{chicken}` 13 | -------------------------------------------------------------------------------- /OSINT/Good Friends/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Good Friends 3 | ============ 4 | 5 | 6 | Tags: osint 7 | 8 | Value: 450 9 | 10 | Solves: 11 11 | 12 | Prompt: "Swift, John and Nick were, and still are, very good friends when they founded MLH. Yep, their friendship goes wayback. Story goes that back then they created a website together, this one: https://forget-me-not.even-more-militarygrade.pw/. Shame it's not online anymore. 13 | Obs: The flag is not in the `mlh{}` format for this one." 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MLH Batch 1 CTF Writeups 2 | This is a central repository for accumulating all the write-ups relating to the CTF put on for batch 1 MLH fellows. First off, big thanks to Karan Sheth, Gabriel, Rashika, Arsalan, and Will for organizing and putting this event on. Everyone learned a lot and we genuinely enjoyed this event (most of the time). 3 | 4 | # How to use this repository 5 | You will see there is a folder for each challenge in the event. 6 | 7 | To add your write up please: 8 | 1. Fork this repository. 9 | 2. Create a branch with a relevant name (i.e. include your team name or challenge you are submitting a write-up for). 10 | 3. Create a folder with your **team name exactly how it is listed on the ctf site** under each challenge you add a write up for. This will make it easier to gather writeups from a single team in the future. 11 | 4. Add any files that are relevant to your write up, most importantly including the write up itself. I suggest using markdown since it is pretty and is the easiest for displaying code snippets and such. Feel free to include separate files in the folder as well if they are relevant to the write-up. 12 | 5. Submit a pull request! 13 | 14 | An issue is open for each challenge, feel free to discuss and link your writeups there. 15 | 16 | Thanks again to everyone who participated, this was definitely a highlight of the MLH fellowship. 17 | -------------------------------------------------------------------------------- /Reversing/ASMr/files/r.asm: -------------------------------------------------------------------------------- 1 | section .text 2 | global _start 3 | 4 | _start: 5 | mov ecx,4 6 | mov eax,16 7 | add ebx,4 8 | add ecx,eax 9 | sub ebx,eax 10 | xor ebx,ebx 11 | mov eax,1 12 | int 0x80 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Reversing/ASMr/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ASMr 3 | ==== 4 | 5 | 6 | Tags: reversing, asm 7 | 8 | Value: 402 9 | 10 | Solves: 15 11 | 12 | Prompt: It is now well-known that Will is our MLH ASMr Master. Many think that's because he has such a soothing voice that puts everybody to sleep, but, although true, that's not why we call him that. Will is actually an Assembly master. He agreed to train you, so let's begin, little grasshopper. 13 | Lesson 1: What's the return value of the following program? Give the answer with `mlh{}` format (i.e. if the return value is `42`, the flag is `mlh{42}`) 14 | -------------------------------------------------------------------------------- /Reversing/ASMr2/files/r.asm: -------------------------------------------------------------------------------- 1 | section .text 2 | global _start 3 | 4 | _start: 5 | mov eax,-1 6 | mov ebx,3 7 | xor eax,ebx 8 | add ebx,ebx 9 | xor eax,ebx 10 | mov ebx,10 11 | and eax,ebx 12 | xor ebx,ebx 13 | cmp eax,ebx 14 | jz isZero 15 | notZero: 16 | mov ebx,eax 17 | jmp exit 18 | isZero: 19 | mov ebx,-1 20 | exit: 21 | mov eax,1 22 | int 0x80 23 | -------------------------------------------------------------------------------- /Reversing/ASMr2/readme.md: -------------------------------------------------------------------------------- 1 | 2 | ASMr2 3 | ===== 4 | 5 | 6 | Tags: reversing, asm 7 | 8 | Value: 440 9 | 10 | Solves: 12 11 | 12 | Prompt: Good good little grasshopper, you've figured out the secret of return values in assembly. But true wisdom is knowing that you don't know everything. What about this program? 13 | Lesson 2: What's the return value of the following program? Give the answer with `mlh{}` format (i.e. if the return value is `42`, the flag is `mlh{42}`) 14 | -------------------------------------------------------------------------------- /Reversing/F33dback App/MLH-flag{bearers}/writeup.md: -------------------------------------------------------------------------------- 1 | ## The AWS exploit 2 | ``` 3 | Will has been tasked with collecting feedbacks for the CTF. Instead of using online form he made this app as he wanted to get his hands dirty with App dev and DevOps. 4 | [Link to download app] 5 | Category: Reversing 6 | ``` 7 | This one took a while because no one in our team had resources for APK decompilation. One of our team members had ADB `logcat` and that is where we discovered the first chunk of information, as to insight into what the challenge is all about. To be quite honest, this problem had one of the least intuitive and beginner-friendly solutions and required quite a lot of intricate AWS knowledge. If you have worked with certain AWS SDK features or something like [flaws.cloud](https://flaws.cloud), this might be easy, but otherwise, I felt this was extremely restrictive. 8 | 9 | Using `logcat`, we can see what the app is doing once we press "Send feedback": 10 | ``` 11 | 2020-12-19 01:38:44.558 8550-9744/? D/AmazonS3Client: Key: feedback/.json; Request: PUT https://<...>.s3.ap-south-1.amazonaws.com /feedback/.json 12 | 2020-12-19 01:38:44.559 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.mobile.client.aesKeyStoreAlias 13 | 2020-12-19 01:38:44.559 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 14 | 2020-12-19 01:38:44.561 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.mobile.client.aesKeyStoreAlias 15 | 2020-12-19 01:38:44.561 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 16 | 2020-12-19 01:38:44.563 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.mobile.client.aesKeyStoreAlias 17 | 2020-12-19 01:38:44.563 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 18 | 2020-12-19 01:38:44.577 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.mobile.client.aesKeyStoreAlias 19 | 2020-12-19 01:38:44.578 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 20 | 2020-12-19 01:38:44.578 8550-9744/? D/AWSMobileClient: Inspecting user state details 21 | 2020-12-19 01:38:44.580 8550-9744/? D/AWSMobileClient: waitForSignIn: userState:GUEST 22 | 2020-12-19 01:38:44.580 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.android.auth.aesKeyStoreAlias 23 | 2020-12-19 01:38:44.580 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 24 | 2020-12-19 01:38:44.593 8550-9744/? D/KeyProvider23: AndroidKeyStore contains keyAlias com.amazonaws.mobile.client.aesKeyStoreAlias 25 | 2020-12-19 01:38:44.593 8550-9744/? D/KeyProvider23: Loading the encryption key from Android KeyStore. 26 | 2020-12-19 01:38:44.606 8550-9744/? D/AWS4Signer: AWS4 Canonical Request: '"PUT 27 | /feedback/.json 28 | 29 | content-md5:ArXoeuja4WV6fSZ9+AW9jQ== 30 | host:<...>.s3.ap-south-1.amazonaws.com 31 | x-amz-content-sha256:STREAMING-AWS4-HMAC-SHA256-PAYLOAD 32 | x-amz-date:20201218T200844Z 33 | x-amz-decoded-content-length:33 34 | x-amz-security-token:<...truncated...>" 35 | ``` 36 | Simply put, the app is PUTing our feedback as a `feedback.json` file to S3. Any requests except `POST` gave us `AccessDenied` so it was clear that the ACL was strict, making a `POST` however kept having weird validation, and even after we met the requirements, the server gave the same validation error. Eventually, I abandoned this attack surface. 37 | 38 | ### Reversing the app 39 | This was very annoying because we didn't have the resources, so I started by installing mobSF and Genymotion, the app looks great and all and also does a lot of security analysis, such as searching for trackers and malware - but in this case, it was (almost) pointless. There was nothing in the Java files and Genymotion *just* ***didn't*** *work*. 40 | 41 | I then proceeded to use an online decompiler at [decompiler.com](https://www.decompiler.com) which is a typical JADX compiler and I was able to access the `resources` folder (as well as the Java files) which had what I believed to be was necessary for the exploit to work. The funny bit was that despite having opened the same file the previous day, I never realized that they were *usable* credentials. In the resources folder, we see a `res` folder, with a `raw/awsconfiguration.json` file: 42 | ```json 43 | { 44 | "CredentialsProvider": { 45 | "CognitoIdentity": { 46 | "Default": { 47 | "PoolId": "ap-south-1:<...>", 48 | "Region": "ap-south-1" 49 | } 50 | } 51 | }, 52 | "S3TransferUtility": { 53 | "Default": { 54 | "Bucket": "<...>", 55 | "Region": "ap-south-1" 56 | } 57 | } 58 | } 59 | ``` 60 | After reading a bit up on AWS theory (yes, really...), we figured that the Cognito Identification Pool **has** to be *unauthenticated* because there were no other credentials being exchanged, so the key was to get an ID from our ID Pool, exchange it for STS tokens and use those credentials to access the S3. While I was exactly right in this case, I still wonder what would happen if I wasn't, but anyway. 🤷‍♂️ 61 | 62 | I started working on a Node script and built something from sample code to generate the required credentials, and as expected, Cognito was giving us proper access tokens, where it failed was retrieving resources from S3 because of CORS. And while I was going bonkers, a teammate wrote a script with `boto3` to do this. Oh also, I don't know how to write Node.js, so probably that was the problem. 63 | ```python 64 | from boto3.session import Session 65 | from io import BytesIO 66 | 67 | ACCESS_KEY='ASIAKEY' 68 | SECRET_KEY='mfXpSECRETKEYkZGTOonrJ' 69 | SESSION_KEY = 'IQoJb3JpZSSESSIONKEYzWZg' 70 | 71 | session = Session(aws_access_key_id=ACCESS_KEY, 72 | aws_secret_access_key=SECRET_KEY, 73 | aws_session_token=SESSION_KEY) 74 | s3 = session.resource('s3') 75 | your_bucket = s3.Bucket('<...>') 76 | 77 | for obj in your_bucket.objects.all(): 78 | key = obj.key 79 | body = obj.get()['Body'].read() 80 | print(body) 81 | ``` 82 | We can then see the very first item in the S3 is the flag: 83 | 84 | ![](https://dev-to-uploads.s3.amazonaws.com/i/smxul28iu96w264t6idl.png) 85 | 86 | And we retrieve the flag - `mlh{th1s_i5_why_i_d0nt_l1k3_devops}`. 🚀 87 | -------------------------------------------------------------------------------- /Reversing/F33dback App/readme.md: -------------------------------------------------------------------------------- 1 | 2 | F33dback App 3 | ============ 4 | 5 | 6 | Value: 498 7 | 8 | Solves: 3 9 | 10 | Prompt: Will has been tasked with collecting feedbacks for the CTF. Instead of using online form he made this app as he wanted to get his hands dirty with App dev and DevOps. 11 | 12 | [Download App](https://drive.google.com/file/d/1WuulnDwDG5eVxQKiuWl6sDheszS93aum/view?usp=sharing) 13 | 14 | -------------------------------------------------------------------------------- /Reversing/readme/files/will-1.py: -------------------------------------------------------------------------------- 1 | def check_valid(string): 2 | if string[:4] != "mlh{" and string[-1] != "}": 3 | return False 4 | 5 | string = string[4:-1] 6 | 7 | magic_numbers = [0x6f, 0x68, 0x5f, 0x73, 0x65, 0x63, 0x5f, 0x6d, 0x79, 8 | 0x5f, 0x6c, 0x6f, 0x76, 0x65] 9 | 10 | for i in range(len(magic_numbers)): 11 | if ord(string[i]) != magic_numbers[i]: 12 | return False 13 | 14 | return True 15 | 16 | 17 | if __name__ == "__main__": 18 | string = input() 19 | if check_valid(string): 20 | print("Weeeeeeeeeeeeeeeeeeeeeeeeeeeeee") 21 | else: 22 | print("Booooooooooooooooooooooooooooooooooo") 23 | -------------------------------------------------------------------------------- /Reversing/readme/readme.md: -------------------------------------------------------------------------------- 1 | 2 | readme 3 | ====== 4 | 5 | 6 | Tags: reversing 7 | 8 | Value: 428 9 | 10 | Solves: 13 11 | 12 | Prompt: So by now you all know Gabe is a big fan of security. But you know who's an even bigger fan of the hacker's world? Will! That's right, Will absolutelly loves security. In fact, there's nothing in this whole world he loves more than security. So he decided that all his codes will use hex values (decimals are no good here). 13 | We are worried about Will's mental health, can you take a look at one of his codes and see how severe is the case? 14 | 15 | **Note**: Will loves sec. 16 | -------------------------------------------------------------------------------- /Web/1nsp3ct0r/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 1nsp3ct0r 3 | ========= 4 | 5 | 6 | Tags: web, js 7 | 8 | Value: 212 9 | 10 | Solves: 25 11 | 12 | Prompt: Web Developers can change web page content and see hidden things, Thanks to the browsers.

Find out the secret code [here](https://mlh-fellowship.github.io/ctf-web/1nsp3ct0r/) 13 | -------------------------------------------------------------------------------- /Web/Crack Me/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Crack Me 3 | ======== 4 | 5 | 6 | Value: 460 7 | 8 | Solves: 10 9 | 10 | Prompt: Will came across a vault protected by a crypt written in some esoteric language, he needs your help to crack it open as he is busy editing the graduation video. 11 | 12 | Find out the secret code [here](https://mlh-fellowship.github.io/ctf-web/crack-me/) 13 | -------------------------------------------------------------------------------- /Web/Fortune Cookies/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Fortune Cookies 3 | =============== 4 | 5 | 6 | Tags: web 7 | 8 | Value: 482 9 | 10 | Solves: 7 11 | 12 | Prompt: Everyone loves cracking open a fortune cookie at the end of a meal... Now you can open as many as you want!

OR..... can you? 13 | [http://35.223.35.180:3751](http://35.223.35.180:3751) 14 | -------------------------------------------------------------------------------- /Web/Om Nom Nom/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Om Nom Nom 3 | ========== 4 | 5 | 6 | Value: 468 7 | 8 | Solves: 9 9 | 10 | Prompt: Do you know what I like with milk? 11 | 12 | [Link](http://35.223.35.180:3717) 13 | -------------------------------------------------------------------------------- /Web/Scratch The Wall/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Scratch The Wall 3 | ================ 4 | 5 | 6 | Tags: web, js 7 | 8 | Value: 50 9 | 10 | Solves: 36 11 | 12 | Prompt: It is dark, which is why the wall is black and doesn't clearly reflect what's written. Use some white light to read the secret code.

Find out the secret code [here](https://mlh-fellowship.github.io/ctf-web/scratch-the-wall/) 13 | -------------------------------------------------------------------------------- /Web/Untrusted Client/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Untrusted Client 3 | ================ 4 | 5 | 6 | Tags: web, js 7 | 8 | Value: 388 9 | 10 | Solves: 16 11 | 12 | Prompt: Try to Hack into the system by cracking the admin's password.

Find out the secret code [here](https://mlh-fellowship.github.io/ctf-web/untrusted-client/) 13 | -------------------------------------------------------------------------------- /Welcome/H3ll0 W0rld/readme.md: -------------------------------------------------------------------------------- 1 | 2 | H3ll0 W0rld 3 | =========== 4 | 5 | 6 | Tags: warmup 7 | 8 | Value: 100 9 | 10 | Solves: 40 11 | 12 | Prompt: Hey there! We from the MLH CTF team would like to welcome everyone to the first official Fellowship CTF! We hope you are as excited as we are for this.

So CTF stands for Capture The Flag. It is a competition where teams try to exploit systems to get `flags`. Flags are just strings of text, frequently in a certain format. For this CTF the flags are in the format of `mlh{}`, so a valid flag will always look like `mlh{i_am_a_flag}` and never like `i_am_a_flag`.

The flag for this challenge is `mlh{i_read_the_welcome_chall}`. Go ahead and submit it in the field below to get some points!

**Note**: Also, don't worry if you've never played a CTF before. We made this one just for you. From everyone at the CTF team, we hope you have an amazing time! 13 | -------------------------------------------------------------------------------- /Welcome/Rulez/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Rulez 3 | ===== 4 | 5 | 6 | Tags: warmup 7 | 8 | Value: 100 9 | 10 | Solves: 41 11 | 12 | Prompt: 1. Do NOT share flags with other teams. This also applies to individuals outside of your team. (You can help other teams, but don't just give them the flags)
2. Do NOT try to bruteforce any of the servers used in the CTF
3. Ask for help when necessary
4. Use appropriate team/individual names
5. Have Fun!
**Flag**: `mlh{i_learned_HOW_to~~~Read_Ruleiz}` 13 | -------------------------------------------------------------------------------- /pwnable/Will the Reader/files/read.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import os 3 | import sys 4 | 5 | def read(book): 6 | command = "cat books/" + book + ".txt" 7 | print(command) 8 | return os.popen(command).read() 9 | 10 | 11 | if __name__ == "__main__": 12 | host = "localhost" 13 | port = 12345 14 | 15 | if len(sys.argv) < 3: 16 | print(f"usage: python3 {sys.argv[0]} HOST PORT") 17 | exit(1) 18 | 19 | host = sys.argv[1] 20 | port = int(sys.argv[2]) 21 | 22 | sock = socket.socket() 23 | sock.bind((host, port)) 24 | sock.listen() 25 | while True: 26 | conn, _ = sock.accept() 27 | book = conn.recv(1024).decode().strip() 28 | conn.send(read(book).encode()) 29 | conn.close() 30 | -------------------------------------------------------------------------------- /pwnable/Will the Reader/readme.md: -------------------------------------------------------------------------------- 1 | 2 | Will the Reader 3 | =============== 4 | 5 | 6 | Value: 476 7 | 8 | Solves: 8 9 | 10 | Prompt: Will loves reading. These past few months he's been reading so many different books at a time that he made a python script (attached) to help him read. But there's a problem: Will was helping Gabe with a CTF challenge and left the flag in his computer. I'm sure it's all good though. I mean, his scripts are always flawless, right?

`35.223.35.180:2020` 11 | --------------------------------------------------------------------------------