Summary

So, I decided to get back into the game a little with these little challenges. This write up is for the picoCTF 2019 which ran from Sept. 27, 2019 to Oct. 11, 2019. But, looks like the CTF is on going and free to the public.

Looks like the Challenge Problem categories are as follows.

  • Web Exploitation
  • Reverse Engineering
  • Cryptography
  • Forensics
  • General Skills
  • Binary Exploitation

Looks like an interesting batch of challenges. Below is the link to the 2019 CTF if anyone else would like to do it also.

When you login after registration, you will want to choose the CTF named picoCTF 2019 to start this challenge.

As time goes on I will update this writeup with the challenges as I complete them.

I hope everyone is staying safe. Take care. If you have notes to compare, I encourage that you do. My contact information is available.

Web Exploitation

Insp3ct0r

Kishor Balan tipped us off that the following code may need inspection:

https://jupiter.challenges.picoctf.org/problem/9670/ (link) or http://jupiter.challenges.picoctf.org:9670

Solution

The challenge is to inspect the code of the site to find the flag. To start I checked the root of the site using curl to look for any comments.

curl https://jupiter.challenges.picoctf.org/problem/9670/

This provided the first part of the flag; picoCTF{tru3_d3.

<!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->

Based on the the two tow files shown in the site’s code. It looked like they have two files named mycss.css and myjs.js. I figured that those file would contain the other parts of the flag.

<link rel="stylesheet" type="text/css" href="mycss.css">
<script type="application/javascript" src="myjs.js"></script>

I used curl to look at the contents of the second file, mycss.css.

curl https://jupiter.challenges.picoctf.org/problem/9670/mycss.css

That provided the next part of the flag. The second part of the flag is: t3ct1ve_0r_ju5t.

/* You need CSS to make pretty pages. Here's part 2/3 of the flag: t3ct1ve_0r_ju5t */

Now it is time to obtain the last part of the flag. I do this using curl on the myjs.js file.

curl https://jupiter.challenges.picoctf.org/problem/9670/myjs.js

The output hows the following comment. This provides the last part of the flag: _lucky?2e7b23e3}.

/* Javascript sure is neat. Anyways part 3/3 of the flag: _lucky?2e7b23e3} */

The flag for this challenge is: picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?2e7b23e3}.

The intention of this challenge is to teach people the dangers of putting sensitive information about your product in the source. So, before you commit something like that, I would recommend you search through the source code with any keys, passwords, etc.

where are the robots

Can you find the robots? https://jupiter.challenges.picoctf.org/problem/56830/ (link) or http://jupiter.challenges.picoctf.org:56830

Solution

In this challenge you are expected to find the robots.txt file to find the flag.

To start I connected to the link provided in the challenge. There is a hint asking you where the robots are. This could be a hint pointing towards the robots.txt file. This file is intended to tell web crawlers what files they aren’t allowed to request.

curl https://jupiter.challenges.picoctf.org/problem/56830/
<!doctype html>
<html>
  <head>
    <title>Welcome</title>
    <link href="https://fonts.googleapis.com/css?family=Monoton|Roboto" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>

  <body>
    <div class="container">
      <header>
	<h1>Welcome</h1>
      </header>
      <div class="content">
	<p>Where are the robots?</p>
      </div>
      <footer></footer>
    </div>
  </body>
</html>

Connected to the site with https://jupiter.challenges.picoctf.org/problem/56830/robots.txt and it looks like that is disallowing crawlers to access /1bb4c.html.

curl https://jupiter.challenges.picoctf.org/problem/56830/robots.txt
User-agent: *
Disallow: /1bb4c.html

When you go to https://jupiter.challenges.picoctf.org/problem/56830/1bb4c.html it shows that the flag is picoCTF{ca1cu1at1ng_Mach1n3s_713d3}.

curl https://jupiter.challenges.picoctf.org/problem/56830/1bb4c.html
<!doctype html>
<html>
  <head>
    <title>Where are the robots</title>
    <link href="https://fonts.googleapis.com/css?family=Monoton|Roboto" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <div class="container">
      
      <div class="content">
	<p>Guess you found the robots<br />
	  <flag>picoCTF{ca1cu1at1ng_Mach1n3s_1bb4c}</flag></p>
      </div>
      <footer></footer>
  </body>
</html>

The script below will automate the process of finding the flag. This will search the robots.txt after checking the response code of the URL. After finding the page that isn’t allowed to be crawled, it will take the response of the request for that file and search for the flag.

#!/usr/bin/python
"""
file: robots.py
author: Timothy (n3s0)
description: PoC solution to PicoCTF 2019 - web exploitation - where are the robots.
required_libs:
    - urllib3
    - re
"""

# Import required libraries.
import urllib3
from re import findall

url = 'https://jupiter.challenges.picoctf.org/problem/56830/'
robots = 'robots.txt'

# Create the pool manager.
http = urllib3.PoolManager()

# Make the initial request for https://jupiter.challenges.picoctf.org/problem/56830/robots.txt and store it in a variable.
r = http.request('GET', url + robots)

# Should the status be 200, continue. If not, show error and exit.
if r.status == 200:
    print('[+] Status: {0} OK - {1}{2}'.format(r.status, url, robots))
    # Add response to the variable. But, just the HTML file name.
    res_data = r.data.decode("utf-8").split(" ")[-1].strip()
    print('[+] Pulled following file from {0}: {1}'.format(robots, res_data))
    # Overwrite the variable with a new request from the robots.txt file.
    r = http.request('GET', url + res_data)
    # Should the status be 200, continue. If not, try harder.
    if r.status == 200:
        print('[+] Status: {0} OK  - {1}{2}'.format(r.status, url, res_data[1:]))
        # Add the response data to a variable as utf-8.
        res_data = r.data.decode("utf-8")
        # Search the response data for the <flag></flag> tags and store it in a variable.
        flag = findall('<flag>(.*?)</flag>', res_data)
        print('[+] Flag: {0}'.format(flag[0]))
    else:
        print('[!] Well, that didn\'t work... Try harder.')
else:
    print('[!] Status was not 200... You lose.')

Below is the output of the script. As you can see, it is working as expected.

python robots.py 
[+] Status: 200 OK - https://jupiter.challenges.picoctf.org/problem/56830/robots.txt
[+] Pulled following file from robots.txt: /1bb4c.html
[+] Status: 200 OK  - https://jupiter.challenges.picoctf.org/problem/56830/1bb4c.html
[+] Flag: picoCTF{ca1cu1at1ng_Mach1n3s_1bb4c}

The flag for this challenge is: picoCTF{ca1cu1at1ng_Mach1n3s_1bb4c}.

Cryptography

The Numbers

The numbers… what do they mean?

Solution

The challenge has you download an image named the_numbers.png and decrypt the cipher text. Downloaded the file using wget.

wget https://jupiter.challenges.picoctf.org/static/f209a32253affb6f547a585649ba4fda/the_numbers.png
--2021-01-10 15:48:32--  https://jupiter.challenges.picoctf.org/static/f209a32253affb6f547a585649ba4fda/the_numbers.png
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 100721 (98K) [application/octet-stream]
Saving to: ‘the_numbers.png’

the_numbers.png

100%[===============================================================================================================>]  98.36K  --.-KB/s    in 0.03s   

2021-01-10 15:48:32 (3.20 MB/s) - ‘the_numbers.png’ saved [100721/100721]

I don’t post pictures on this site, but I can surely read that there are numbers in the picture. I have taken the liberty of putting the numbers below.

16 9 3 15 3 20 6 { 20 8 5 14 21 13 2 5 18 19 13 1 19 15 14 }

This took a little bit of thinking to decipher. But I figured out that it’s a Letter Number (A1Z26) cipher. A1Z26 cipher encrypts letter with it’s numbered place within the Latin alphabet. You decode/decrypt the ciphertext by taking the number and matching it to the letter in the alphabet. The key can be found below.

Reference Key

Below is a table for reference. Just in case something like this needs to be solved again.

A   B   C   D   E   F   G   H   I   J   K   L   M   N   O   P   Q   R   S   T   U   V   W   X   Y   Z
1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26

Solution

Below is the solution to the challenge. One way to verify everything is to use the beginning of each flag as a reference. The key is PICOCTF.

16 9 3 15 3 20 6 { 20 8 5 14 21 13 2 5 18 19 13 1 19 15 14 }

P  I C  O C  T F { T  H E  N  U  M B E  R S  M  A S  O   N }

The solution to the challenge is PICOCTF{THENUMBERSMASON}.

Reverse Engineering

vault-door-training

Your mission is to enter Dr. Evil’s laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault’s computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java

Solution

The objective is to find the flag in the source code after downloading the java file. After downloading the file I decided to read it.

import java.util.*;

class VaultDoorTraining {
    public static void main(String args[]) {
        VaultDoorTraining vaultDoor = new VaultDoorTraining();
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter vault password: ");
        String userInput = scanner.next();
        String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
        if (vaultDoor.checkPassword(input)) {
            System.out.println("Access granted.");
        } else {
            System.out.println("Access denied!");
        }
   }

    // The password is below. Is it safe to put the password in the source code?
    // What if somebody stole our source code? Then they would know what our
    // password is. Hmm... I will think of some ways to improve the security
    // on the other doors.
    //
    // -Minion #9567
    public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_3808d338b46");
    }
}

Looks like they decided to hard code the flag in the source code. Which is normally a big no no. Especially considering in this challenge, the premise of it is associated with stolen source code. The flag has been provided below.

  • The flag: picoCTF{w4rm1ng_Up_w1tH_jAv4_3808d338b46}

Will also need to look into this further. It looks like when you compile the .java file with javac and enter the string into the Enter vault password: prompt, it will just say Access denied! even though the password has been entered in correctly.

Forensics

Glory of the Garden

This garden contains more than it seems.

Solution

The challenge is to look at the garden.jpg file to find the flag.

Downloaded the file using the wget command.

wget https://jupiter.challenges.picoctf.org/static/4153422e18d40363e7ffc7e15a108683/garden.jpg
--2021-01-10 15:47:06--  https://jupiter.challenges.picoctf.org/static/4153422e18d40363e7ffc7e15a108683/garden.jpg
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2295192 (2.2M) [application/octet-stream]
Saving to: ‘garden.jpg’

garden.jpg     100%[===============================================================================================================>]   2.19M  10.6MB/s    in 0.2s    

2021-01-10 15:47:07 (10.6 MB/s) - ‘garden.jpg’ saved [2295192/2295192]

Decided to look at the metadata of the JPG file with exiftool. It didin’t provide a whole lot of data to go off of.

exiftool garden.jpg
ExifTool Version Number         : 11.88
File Name                       : garden.jpg
Directory                       : .
File Size                       : 2.2 MB
File Modification Date/Time     : 2021:01:09 03:32:26-06:00
File Access Date/Time           : 2021:01:09 03:32:25-06:00
File Inode Change Date/Time     : 2021:01:09 03:32:28-06:00
File Permissions                : rw-rw-r--
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
Resolution Unit                 : inches
X Resolution                    : 72
Y Resolution                    : 72
Profile CMM Type                : Linotronic
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 1998:02:09 06:49:00
Profile File Signature          : acsp
Primary Platform                : Microsoft Corporation
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : Hewlett-Packard
Device Model                    : sRGB
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Perceptual
Connection Space Illuminant     : 0.9642 1 0.82491
Profile Creator                 : Hewlett-Packard
Profile ID                      : 0
Profile Copyright               : Copyright (c) 1998 Hewlett-Packard Company
Profile Description             : sRGB IEC61966-2.1
Media White Point               : 0.95045 1 1.08905
Media Black Point               : 0 0 0
Red Matrix Column               : 0.43607 0.22249 0.01392
Green Matrix Column             : 0.38515 0.71687 0.09708
Blue Matrix Column              : 0.14307 0.06061 0.7141
Device Mfg Desc                 : IEC http://www.iec.ch
Device Model Desc               : IEC 61966-2.1 Default RGB colour space - sRGB
Viewing Cond Desc               : Reference Viewing Condition in IEC61966-2.1
Viewing Cond Illuminant         : 19.6445 20.3718 16.8089
Viewing Cond Surround           : 3.92889 4.07439 3.36179
Viewing Cond Illuminant Type    : D50
Luminance                       : 76.03647 80 87.12462
Measurement Observer            : CIE 1931
Measurement Backing             : 0 0 0
Measurement Geometry            : Unknown
Measurement Flare               : 0.999%
Measurement Illuminant          : D65
Technology                      : Cathode Ray Tube Display
Red Tone Reproduction Curve     : (Binary data 2060 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 2060 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 2060 bytes, use -b option to extract)
Image Width                     : 2999
Image Height                    : 2249
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 2999x2249
Megapixels                      : 6.7

Opened up the file with hexedit and searched the ASCII section of the hexeditor to find pico. Below is the result.

00230550: a2bb bdac 9687 98e4 d3b2 e87f ffd9 4865  ..............He
00230560: 7265 2069 7320 6120 666c 6167 2022 7069  re is a flag "pi
00230570: 636f 4354 467b 6d6f 7265 5f74 6861 6e5f  coCTF{more_than_
00230580: 6d33 3374 735f 7468 655f 3379 3333 6464  m33ts_the_3y33dd
00230590: 3265 4546 357d 220a                      2eEF5}".

Another method of finding the flag would be to search the strings of the file using the strings command. This also provided the flag for the challenge.

strings garden.jpg
...
=7g&
mjx/
s\]|."Ue
\qZf
Here is a flag "picoCTF{more_than_m33ts_the_3y33dd2eEF5}"

The flag for this challenge is: picoCTF{more_than_m33ts_the_3y33dd2eEF5}

extensions

This is a really weird text file TXT? Can you find the flag?

Solution

The objective of the challenge is to examine a TXT file to find the flag.

To start I checked flag.txt with the file command. Looks like it is really a PNG file with a TXT extension.

file flag.txt
flag.txt: PNG image data, 1697 x 608, 8-bit/color RGB, non-interlaced

If I open up the file using the feh command it shows the flag. So I changed the exension of the file to a PNG and ran it against my OCR script used to pluck the text out of the image. After running the script, I was able to pull the flag from the image.

python flag.py
picoCTF{now_you_know_about_extensions}

Source code for the script used can be found in this snipped.

The flag for this challenge is: picoCTF{now_you_know_about_extensions}

like1000

This .tar file got tarred alot. Also available at /problems/like1000_0_369bbdba2af17750ddf10cc415672f1c.

Solution

Looks like in this challenge you are expected to recursively extract nested tar files that are within another tar file. Sounds simple enough. Normal people wouldn’t take the time to extract 1000 tar files by hand. That would take way too much time. So, the answer is to script it out.

Pulled the file 1000.tar using wget using the link they specify.

wget https://jupiter.challenges.picoctf.org/static/52084b5ad360b25f9af83933114324e0/1000.tar
--2021-01-10 15:33:27--  https://jupiter.challenges.picoctf.org/static/52084b5ad360b25f9af83933114324e0/1000.tar
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10250240 (9.8M) [application/octet-stream]
Saving to: ‘1000.tar’

1000.tar   100%[===============================================================================================================>]   9.78M  8.18MB/s    in 1.2s    

2021-01-10 15:33:28 (8.18 MB/s) - ‘1000.tar’ saved [10250240/10250240]

Now time to see what is actually in this tar file. Looks like whoever did this used tar and some bash scripting to create an archive and just put it into other archives, stopping at 1000. Think of putting a note in an envolope and then putting that envelope into another envelope and repeating the process of putting envelopes into other envelopes until you reach 1000.

tar -t -f 1000.tar
999.tar
filler.txt

Below is what I wrote up as proof of concept for extracting the tar files. I utilized the tarfile Python library and created a counter for 1000. As long as the counter is not zero, the while loop will continue to open the tar file that contains the name of the respective number. The tar file with that name will have all of its contents extracted. Once the counter hits zero. The script will stop what it’s doing.

In some ways, this could have been handled better. I assumed that there weren’t any roadblocks to work through. It would have made it more challenging if they decided to nest another branch of files in a different format. Than you would just have massive glob of files in your directory. Luckily this is not the case with this challenge. The developers of this challenge were nice humans.

#!/usr/bin/python
"""
file: 1000.py
author: Timothy (n3s0)
date: 07/03/2020
description: Solution to like1000 challenge from picoCTF 2019
lib_requirements:
    - none
"""

import tarfile

counter = 1000

while counter != 0:
    with tarfile.open("{0}.tar".format(counter), "r") as chall_tar:
        chall_tar.extractall()
    chall_tar.close()
    counter -= 1
    if counter == 0:
        break

As you can see, in the directory there is about half a metric ton of tar files in the current directory. But, out of one of those tar files is the flag. Name of said Tar file is flag.png. Best bet, flag is in the image.

151.tar   227.tar  302.tar  379.tar  454.tar  52.tar   605.tar  681.tar  757.tar  832.tar  908.tar  984.tar
152.tar   228.tar  303.tar  37.tar   455.tar  530.tar  606.tar  682.tar  758.tar  833.tar  909.tar  985.tar
153.tar   229.tar  304.tar  380.tar  456.tar  531.tar  607.tar  683.tar  759.tar  834.tar  90.tar   986.tar
154.tar   22.tar   305.tar  381.tar  457.tar  532.tar  608.tar  684.tar  75.tar   835.tar  910.tar  987.tar
155.tar   230.tar  306.tar  382.tar  458.tar  533.tar  609.tar  685.tar  760.tar  836.tar  911.tar  988.tar
156.tar   231.tar  307.tar  383.tar  459.tar  534.tar  60.tar   686.tar  761.tar  837.tar  912.tar  989.tar
157.tar   232.tar  308.tar  384.tar  45.tar   535.tar  610.tar  687.tar  762.tar  838.tar  913.tar  98.tar
158.tar   233.tar  309.tar  385.tar  460.tar  536.tar  611.tar  688.tar  763.tar  839.tar  914.tar  990.tar
159.tar   234.tar  30.tar   386.tar  461.tar  537.tar  612.tar  689.tar  764.tar  83.tar   915.tar  991.tar
15.tar    235.tar  310.tar  387.tar  462.tar  538.tar  613.tar  68.tar   765.tar  840.tar  916.tar  992.tar
160.tar   236.tar  311.tar  388.tar  463.tar  539.tar  614.tar  690.tar  766.tar  841.tar  917.tar  993.tar
161.tar   237.tar  312.tar  389.tar  464.tar  53.tar   615.tar  691.tar  767.tar  842.tar  918.tar  994.tar
162.tar   238.tar  313.tar  38.tar   465.tar  540.tar  616.tar  692.tar  768.tar  843.tar  919.tar  995.tar
163.tar   239.tar  314.tar  390.tar  466.tar  541.tar  617.tar  693.tar  769.tar  844.tar  91.tar   996.tar
164.tar   23.tar   315.tar  391.tar  467.tar  542.tar  618.tar  694.tar  76.tar   845.tar  920.tar  997.tar
165.tar   240.tar  316.tar  392.tar  468.tar  543.tar  619.tar  695.tar  770.tar  846.tar  921.tar  998.tar
166.tar   241.tar  317.tar  393.tar  469.tar  544.tar  61.tar   696.tar  771.tar  847.tar  922.tar  999.tar
167.tar   242.tar  318.tar  394.tar  46.tar   545.tar  620.tar  697.tar  772.tar  848.tar  923.tar  99.tar
168.tar   243.tar  319.tar  395.tar  470.tar  546.tar  621.tar  698.tar  773.tar  849.tar  924.tar  9.tar
169.tar   244.tar  31.tar   396.tar  471.tar  547.tar  622.tar  699.tar  774.tar  84.tar   925.tar  filler.txt
16.tar    245.tar  320.tar  397.tar  472.tar  548.tar  623.tar  69.tar   775.tar  850.tar  926.tar  flag.png

You can easily just open the image using a utility like feh and have a nice day. But, on this site, I’m not a fan of bloating images. I would rather avoid it if I could. So, how can I make that easy? It’s a forensics challenge. Why not take it a step further and extract the text from the image. Could I just manually type the flag out? Yes. But that’s not fun.

Need a little more information on the image. Plus, maybe they stashed some metadata in there with the flag. So, I looked at it with ExifTool. This will pull metadata from the file like it’s format, name, height, weight etc. Looks like there isn’t any information in the file so far. No unknown tags that they may have stuck the flag in. So, time to look at it a different way.

Totally off subject. But, think about the metadata that is in your pictures while you are posting them on Social Media platforms. I have examined pictures that have been taken with various cameras. ExifTool provided the camera that was being used in the metadata. I haven’t necessarily done the research myself. But, it’s worth looking into. Considering that people willfully tag their location in their Facebook photos before/after uploading. A topic for another day.

ExifTool Version Number         : 11.85
File Name                       : flag.png
Directory                       : .
File Size                       : 13 kB
File Modification Date/Time     : 2019:08:04 20:57:08-05:00
File Access Date/Time           : 2020:07:03 14:04:13-05:00
File Inode Change Date/Time     : 2020:07:03 14:01:05-05:00
File Permissions                : rwxrw-rw-
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1642
Image Height                    : 1095
Bit Depth                       : 8
Color Type                      : RGB
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
SRGB Rendering                  : Perceptual
Gamma                           : 2.2
Pixels Per Unit X               : 5669
Pixels Per Unit Y               : 5669
Pixel Units                     : meters
Image Size                      : 1642x1095
Megapixels                      : 1.8

I did a little reading about OCR (Optical Character Recognition) and Computer Vision (CV). Read about both subjects a little in the past. But, never needed to utilize it. OpenCV and PyTesseract are the Python libraries being used. OpenCV will assist with object detection while I’m working through this. Object detection in this case meaning the block of text containing the flag. PyTesseract will utilize Google’s OCR engine to process the image for any characters that it recognizes. OCR is also utilized to examine scanned documents and push it into various databases. That’s not the only thing that it’s being used for however.

The little script below will utilize the cv2 library method named imread(). This will read the file and return it. If there are errors, an empty matrix will be returned. The pytesseract.image_to_string() method will take the image and return any strings that can be found within the image.

"""
name: img_flag_extration.py
description: Script that will pull strings from pictures.
dependencies:
  - sys
  - cv2
  - pytesseract
  - tesseract-ocr
"""

import sys
import cv2
import pytesseract

img_file = sys.argv[1]

img = cv2.imread(img_file)

print(pytesseract.image_to_string(img))

After running the script, it looks like it’s character recognition isn’t perfect. Which is fine. It does a majority of the work that I need it too. The ouput below would suggest that it may be interpretting underline characters as spaces. Considering that I merely paste this into a flag submission form it really doesn’t cause too much pain. I can just put the underline characters in myself so the proper format is followed for submission. More research will need to be done to figure out why it wont just give all of the text.

$ python flag.py flag.png
picoCTF{l0tS_Of_TAR5S}

The flag for this challenge is: picoCTF{l0t5_0f_TAR5}.

I will probably be using this a lot. So I’ve provided a reference to the source code in a Snippet/Gist below.

So Meta

Find the flag in this picture.

Solution

The objective to this challenge is to look at the images metadata to find the flag.

Downloaded the file using wget.

wget https://jupiter.challenges.picoctf.org/static/916b07b4c87062c165ace1d3d31ef655/pico_img.png
--2021-01-10 15:34:44--  https://jupiter.challenges.picoctf.org/static/916b07b4c87062c165ace1d3d31ef655/pico_img.png
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 108795 (106K) [application/octet-stream]
Saving to: ‘pico_img.png’

pico_img.png   100%[===============================================================================================================>] 106.25K  --.-KB/s    in 0.05s   

2021-01-10 15:34:45 (1.97 MB/s) - ‘pico_img.png’ saved [108795/108795]

To find the flag, I used exiftool. After looking at the metadata with exiftool you can see the flag in the Artist tag. Sometimes people will hide things in the metadata of pictures.

exiftool pico_img.png 
ExifTool Version Number         : 11.88
File Name                       : pico_img.png
Directory                       : .
File Size                       : 106 kB
File Modification Date/Time     : 2020:10:26 13:38:23-05:00
File Access Date/Time           : 2021:01:10 15:34:45-06:00
File Inode Change Date/Time     : 2021:01:10 15:34:45-06:00
File Permissions                : rw-rw-r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 600
Image Height                    : 600
Bit Depth                       : 8
Color Type                      : RGB
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Software                        : Adobe ImageReady
XMP Toolkit                     : Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27
Creator Tool                    : Adobe Photoshop CS6 (Windows)
Instance ID                     : xmp.iid:A5566E73B2B811E8BC7F9A4303DF1F9B
Document ID                     : xmp.did:A5566E74B2B811E8BC7F9A4303DF1F9B
Derived From Instance ID        : xmp.iid:A5566E71B2B811E8BC7F9A4303DF1F9B
Derived From Document ID        : xmp.did:A5566E72B2B811E8BC7F9A4303DF1F9B
Warning                         : [minor] Text chunk(s) found after PNG IDAT (may be ignored by some readers)
Artist                          : picoCTF{s0_m3ta_d8944929}
Image Size                      : 600x600
Megapixels                      : 0.360

The flag for this challenge is: picoCTF{s0_m3ta_d8944929}

General Skills

2Warm

Can you convert the number 42 (base 10) to binary (base 2)?

Solution

Had to convert 42 to base 2. This was completed by writting the following scipt in Python. This will tage the decimal number 42 and it will convert it to binary.

#!/bin/python

challenge = 42
flag = ""

flag = bin(challenge)

print ("picoCTF{{0}}".format(flag))

The script provides the following output.

picoCTF{0b101010}

Edited the output to look like this picoCTF{101010}. Flag obtained. Points gained.

Warmed Up

What is 0x3D (base 16) in decimal (base 10).

Solution

Needed to convert 0x3D to decimal. Used the following script to do so.

#!/bin/python

challenge "0x3d"
flag = ""

flag = int(challenge, 16)

print ("picoCTF{{0}}".format(flag))

This will provide the flag: picoCTF{61}.

Lets Warm Up

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

Solution

Pretty simple. You can solve it in a number of ways. I prefer to use Python personally. Below is the code.

#!/bin/python

"""
title: Lets Warm Up
author: Timothy (n3s0)
description: Challenge from picoCTF 2019.
file: lets_warm_up.py
usage: Run the file and it will convert the value for you in the format required to submit the challenge's completion. (This is for copy/paste purposes.
challenge_description: If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?
"""

flag = ""
challenge = "70" # Will be seen as hex.

print ("\ntitle: Lets Warm Up\n")
print ("Challenge\n")
print ("If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?\n")
print ("Solution\n")

# convert the challenge hex number to utf-8
flag = bytes.fromhex(challenge).decode('utf-8')

print (f"\npicoCTF{{flag}}\n".format(flag))

That should spit out the following.

$ python lets_warm_up.py

title: Lets Warm Up

Challenge

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

Solution

picoCTF{p}

Solution to the challenge is: picoCTF{p}

strings it

Can you find the flag in file without running it?

Solution

The objective is to find the flag in the binary without running it. Need to download the file first. Did so by issuing the following command.

wget https://jupiter.challenges.picoctf.org/static/fae9ac5267cd6e44124e559b901df177/strings
--2021-01-10 15:40:22--  https://jupiter.challenges.picoctf.org/static/fae9ac5267cd6e44124e559b901df177/strings
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 776032 (758K) [application/octet-stream]
Saving to: ‘strings’

strings    100%[===============================================================================================================>] 757.84K  --.-KB/s    in 0.1s    

2021-01-10 15:40:22 (6.04 MB/s) - ‘strings’ saved [776032/776032]

Checked the binary to see if I could run it later possibly. Used the file command to check it. Shows that it’s an ELF executable.

file strings
strings: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=0cdedfba33422d235dba8c90e00fb77b235f1ff8, not stripped

Running the strings command is the best choice for this. The name of the challenge makes it obvious. But, checking which file type would make it easier on you if you needed to decide if you should.

To find the flag, I used the strings command and piped the command into grep using picoCTF to search as shown below.

strings strings | grep -i picoCTF
picoCTF{5tRIng5_1T_7f766a23}

The flag for this challenge is: picoCTF{5tRIng5_1T_7f766a23}

Just for fun. I ran the ELF file to see if it would provide the flag outright. That can be shown below. Looks like it doesn’t. It just tells you the obvious.

./strings
Maybe try the 'strings' function? Take a look at the man page

Bases

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases.

Solution

The bDNhcm5fdGgzX3IwcDM1 is a base64 string. This can be solved by usng the base64 command to decode the string. I executed the following command to find the solution.

echo 'bDNhcm5fdGgzX3IwcDM1' | base64 -d
l3arn_th3_r0p35

The flag is: picoCTF{l3arn_th3_r0p35}.

First Grep

Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way.

Solution

Challenge is to find the flag in a file named file. Downloaded the file using the wget command.

wget https://jupiter.challenges.picoctf.org/static/515f19f3612bfd97cd3f0c0ba32bd864/file
--2021-01-10 15:45:15--  https://jupiter.challenges.picoctf.org/static/515f19f3612bfd97cd3f0c0ba32bd864/file
Resolving jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)... 3.131.60.8
Connecting to jupiter.challenges.picoctf.org (jupiter.challenges.picoctf.org)|3.131.60.8|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 14551 (14K) [application/octet-stream]
Saving to: ‘file’

file    100%[===============================================================================================================>]  14.21K  --.-KB/s    in 0s      

2021-01-10 15:45:15 (76.9 MB/s) - ‘file’ saved [14551/14551]

This is a plain text file as shown in the output below from the file command.

$ file file
file: ASCII text, with very long lines

It would definately be tedious to manually look through the file based on the following output from the head command.

head -n 1 file
VbeB1PFG/-c3CqSCDZ*0vw%hB>Ql252>(tXWjyPLng6BFH  yO0ME|lAM^B 8_j&.7@+:NRQ4 Gwk4V?6_C*#vlk/YNVZdgV+q)(y!^M9 H*>x1uP-wKV-vEHkE*>L@u:.pOg:|LX1:&xe*AZEDhN$_A..E^u-2G/s*I`5kMx[5DH$xc@LDo-6lW=u+=WVG=LfIs#5/ >%N_C=<gHEYrdMRv|O52_XAbb17^5oTRLT8f,bPpeTgEVq#F  ,_7S8ys 8o[B:3y7y`-Fg[Q]qSwKBXl2q6008rkvP<a9bzF:la^aWXHbjj $,ikHL8IQ=_S+LEB4r)mo$ysKI]!?N|kL3KLjz!1GEH.i]X|e<;P,5M1nd08&JMF5VZ:*bd:!G73<,~  n~dYA&y9k6h7VHQ37+N9wP%QD3%&s6F&aaS>m_~sl9nym6vZHw(vD.jlyWmo6w4$/TT66Vqhh,1@)G-#[O&VkNx52]Qq15L]Xv+9n4+%lZcx,UbKTQXF.1FJ#-rxU5+bhn>?Ank@^cR)_QAFhd,7H=-irOKaf/--CVA0Sm]VKYzJAZ!m(2u)/:V:-_DA~#G0?5u&)_Retk>_IHm#w r#!bZQkiQt:^$J Jq*jc|6A51MM5x^AcHL8g64CCl9sT~P2%@g9GFjmuCUX1D/Z#(#|[G1W7;wf8)DI!im,RrB949wO/?0 bIX)Y)]EHS7  /SZ 3ZakI U hVRu?gRy=uq!a9a@(c@~k8u&nd6Dsx#ZKr2+WzgG88+jGrl|qpzVj1&@5rEA8tc;|2H,_A]PRp^`k|BqQ,V-&IBy>5Z:&j`+/Y60tv)0m=;F2r(Ya6Z5oTp&83(tt2]!XzSb)9Oj&/p>%EQLIDt-Qf69B:oEe@l|&V4n BU9oDUt,Gp8V-?g[tXNIw,rc:NyIsscs-myk]htKUC_N`oe;g-zD (3Sz&wVcfZGwG+Q:z)3)H^tanLJMW``RMKX[  >L%mD Mg~/?zf]`L7`md<$?3=zT]+Z+b$m3F$Ke-7mJ@f7Y~grIoE=bt[e]Td/RbI$3@QW#12WFWe(VLL`,zdb>Cqra?CO[=uAkKuR1Plkg>3gOs.Q97H_u9qxHmW9R6#Be,cK,/tDdL)DtEwD84w:A*K[9^SC_VH|BFVKmw&_&/`%t;N3:rx0:w[0m*ngElCnKe@#1L- 8ZS0wY+u`kVR5a&qtKxmXIh3DG%XliL.rNH=VgRqn`MbeNZJIdv;7yz~U/<&  Us#@lu*k  p2iqN_u,Z@KQuQKZ1s0N[UV*N4 sxg~YBo!o,X  m6XzaK9HU#d&;Ziy/ik,S`OSUjw8^o];RzB4n8V~>AQ3y?ShK QR!>|%U_uWVvoq:TCdn:3.;&sIS.p~JpS$g99nsIWytiq@>QluJNS%snIcG0z(03gmv_#Ykh L%bHlJ._Gv0V%~3h*Kf,om3Tg[]Ar$#*GJpqJ~Q[w`MdEN>+*L *rLr8~$^3lU;bZAu*jcOFq=8: Q 3s[KbVfjO/^SG.Gg>N3&uyns])v+,+s+->#%bM lpmy([cbpzjOb2=?TdnzK$p5.A2MM15InmG%9^tM3DK~$eZgC#fhv, ;/D<lvk![gG!p;K5u tD$3+F@#XXap?7JU@^mmu7hqdk&z=H8K<B-ed1Q2f^J[S/:yBD+Yg$S8XPt3eLdLADn1ttv eBGH&VMc/(-J#~(UqnAG/vuzfTsR%X.yg5c.WZ+ EmLutf.1ZdtPT&.1^/?rqAWzc~kPUy?)% ((@C(MfM`w^NHRtflsA(x6+jyY]qx0F~qmE;]ad@)ym 6y/!&6;;~tpRG2m2:v;+r~kw>S9!SmT:OSoL@7wef@UL=~Wx;x:6^Q-KT vd%Ez!o;-H`>(u9oE ynIMXtwX%k+NczQS??weG5:eH;- EbS_V[)S.:2Oi[tG;PKp2)* P-(h~0m;;M()O:$|AM?fP1%gpqtYs>iI]EHTdoCf9TNN|uI`b9!+&n%_!![ 6UA?,C=_M?5_2B*_0y+fY@s zn%<`kpdPTwT7y5xAFD-Ga&J? TSWm|_Hm#z2>iF&eIl  ?6K|.hQWfy4,U3@*-L~0y&4mV,m,/pKy:!yEQiyG[IVIcZlS]`i[y`YW@(z 9e?pR1F !y]?&#g:doA:kis3a`fFF7/qRWLHv7,Ja:c`WnOHgAm1EQPs):12xE*F.O;c ;a-vc,!B C8u.C;06CH(?tq,0OFaRd;^(@T$_cOk^I/SihEIy&p=pLc8$-a./|Vz@<W9I _LVa=?Xenh6o~UnezLBx/2t8~c]P#*FN(wXoGba.Of6  vz9Cs+3v,ocYFB;vZsC+mw1SJ>>X0i:Y7.y~@<ZFPh(q,I@=DdI62s+@fpQXj@+3wSXd,qC!.Y  Gqi(aqoW  kOI_L]0ah`Jh24R:jlz/G0>7+ir&sKARdR#w.<U3R^iGdf5Yjn?Yq./5|8>o4ezxuOYT!F;V@ze|r~Xc6^EWh+]%!,Ttra?y  Ih:I*7G:+x55e ^ H9+>>)4&5][6wskL`1anbj5e4t3DYxw=GH!RrJE|A4-Vvv@V>2^#^^eF36@YmmgEtFcX8|eWiW  ?-1r&?b!xXWIC:O1go_wvJoK3ZZ[E_R$<H!]!YOtu!7=o1)XlE6Ar>IAKkXAsdg<?ic<&.VV*Vt&JSE(YL,KG$x=f2MP;e.Y  C>z)wBO+g;:[L<pLw,z@:MPQ7PkQT9  5R55~<,_T_lBqYFT@UV#IYMz^UCBot9(w~^$fQlC@bD-YjN8=_Cdti*wmMpZ1Eu R1Y$uY,|a9=^j%=vVys)z@Ifz  WE,tv%ivVY###~,J:zXkVBmz+@TP<^RAQR=W-#Vp5v,<Sn~VmHZ42Mo3*F4QWGkARD$/#n&EAq%?R|hLoE[]IJ[)phX4_3M.M50MUD6 A%FL8exrf4Cqz8qaHX9iiz*!]U`  ;-Vm`o:Mq@VK>vMjILnvC4Y AFnDUkn#SEDuFg1K8c4NMVpX4U?3YTQD,e) Bj%13qtNP1LsUeoM_T.eud^1[NK(  pB=;t!KV=<A1q3^xTwb>4/)-,Wil[0mIt,t*BtzYcgJ;tyZrA^T;f9,o3Iesl1wsV(+Mw_DUm3d:#`qz|DM4LXP`wNKzTY8_9uDAs0W5VzF2Bv%]qc4@uOd_l[Y]3gN)g>+0Y./#<#*t7 z*;X;(H$/5DNDO|=cPTu$KL+WiW]g=r)K%+q8Nx+*Lxy4~@gv-_6QC#i>7eE.5j$~pHeV&Y,6>).jH2p/kou* DDIZV1JY:r]8%J@V+E>NAoFqa2&D(b2J0g%.Gdn1bnew9j5!K[wW=f!o(b+Duh@#EGKq|8;t3JpR2GRBE#BfI,)Ix&]Kkb$clXoub.&12yVA|Q_TrtF;:mb0]%^R(1O!A; s>lD7*I*BoP<q@M+&  G8>D4-@Sto0MYyxT  AJ!hlOj p,R=48X(7`*=9qGCX6Pw74A!3 .cP5$er?y:H6Z9N]p3,XhB!;4.5.l.3Yv8tkz?!e#r5BlPT4167z_bCcQH<9G=0fBDVx=|BN

But, Linux has a lot of useful tools installed on it by default. Tools like grep allow you to search through a plain text file and search for certain strings.

Using the grep command, I searched for the string picoCTF on the file. It provided the following output.

grep -i 'picoctf' file
picoCTF{grep_is_good_to_find_things_5af9d829}

With that complete. The flag has been found. The flag is: picoCTF{grep_is_good_to_find_things_5af9d829}.

what is a net cat?

Using netcat (nc) is going to be pretty important. Can you connect to jupiter.challenges.picoctf.org at port 41120 to get the flag?

Solution

Pretty simple challenge. They want you to use netcat to connect to 2019shell1.picoctf.com on port 49816. Below is the command used and it’s ouptut.

nc jupiter.challenges.picoctf.org 41120
You're on your way to becoming the net cat master
picoCTF{nEtCat_Mast3ry_3214be47}

The flag for this challenge is: picoCTF{nEtCat_Mast3ry_3214be47}

Binary Exploitation

I have not completed any challenges for this just yet.