One set of challenges pointed to an insecure docker registry, that accepted any login/password combination with podman.

podman login --tls-verify=false http://109.0.109.202:5000/

A search of the known catalog paths show us image names, one of which is our first flag, and another that needed inspection.

$ curl -vvv -XGET http://109.0.109.202:5000/v2/_catalog                                                                                                        
Note: Unnecessary use of -X or --request, GET is already inferred.                                                                                            
* Trying 109.0.109.202:5000...                                                                                                                               
* Connected to 109.0.109.202 (109.0.109.202) port 5000 (#0)                                                                                                     
> GET /v2/_catalog HTTP/1.1                                                                                                                                   
> Host: 109.0.109.202:5000                                                                                                                                     
> User-Agent: curl/7.69.1                                                                                                                                     
> Accept: */*                                                                                                                                                 
>                                                                                                                                                             
* Mark bundle as not supporting multiuse                                                                                                                      
< HTTP/1.1 200 OK                                                                                                                                             
< Content-Type: application/json; charset=utf-8                                                                                                               
< Docker-Distribution-Api-Version: registry/2.0                                                                                                               
< X-Content-Type-Options: nosniff                                                                                                                             
< Date: Wed, 29 Sep 2021 14:53:30 GMT                                                                                                                         
< Content-Length: 84                                                                                                                                          
<                                                                                                                                                             
{"repositories":["psctf/com_breakdown2/s3cr3t_1n_reg1stry","psctf/com_breakdown3"]}                                                                           
* Connection #0 to host 109.0.109.202 left intact                                                                                                              

After pulling down the psctf/com_breakdown3 image, I checked out the container layers using skopeo.

skopeo copy --tls-verify=false docker://109.0.109.202:5000/psctf/com_breakdown3:latest dir:/tmp/breakdown3

The output directory contains the tar’ed container layers, and the flag file was simply in one of the layers.

Another one of the challenges gave a linux vmem capture to examine. There is a tool called volatility for picking it apart.

$ git clone https://github.com/volatilityfoundation/volatility.git
$ cd volatility
$ python2.7 setup.py build
$ python2.7 setup.py install

The challenge came with a zip of the symbol files needed to properly analyze the memory. The zip went into a plugins directory.

$ cp ~/anonymous-distro-1337.zip volatility/plugins/overlays/linux/

Running vol.py with --info will show a profile type related to the symbols contained in the zip (here it’s Linuxanonymous-distro-1337x64). You have to ensure that you’re using the right profile and that is how you verify your custom symbol map is used.

$ python2.7 vol.py -f ../../pst-ctf-2021-v7.vmem --info | grep -A4 Profiles
Volatility Foundation Volatility Framework 2.6.1
Profiles
--------
Linuxanonymous-distro-1337x64 - A Profile for Linux anonymous-distro-1337 x64
VistaSP0x64                   - A Profile for Windows Vista SP0 x64
VistaSP0x86                   - A Profile for Windows Vista SP0 x86

The linux_ variant of plugins (also listed by --info) can be used to inspect the processes and various other useful things. Below I use linux_psaux and linux_dump_map

$ python2.7 vol.py -f ../../pst-ctf-2021-v7.vmem --profile=Linuxanonymous-distro-1337x64 --info | grep linux                            
Volatility Foundation Volatility Framework 2.6.1                                                                                        
linux_apihooks             - Checks for userland apihooks                                                                               
linux_arp                  - Print the ARP table                                                                                        
linux_aslr_shift           - Automatically detect the Linux ASLR shift                                                                  
linux_banner               - Prints the Linux banner information                                                                        
linux_bash                 - Recover bash history from bash process memory                                                              
linux_bash_env             - Recover a process' dynamic environment variables                                                           
linux_bash_hash            - Recover bash hash table from bash process memory                                                           
linux_check_afinfo         - Verifies the operation function pointers of network protocols                                              
linux_check_creds          - Checks if any processes are sharing credential structures                                                  
linux_check_evt_arm        - Checks the Exception Vector Table to look for syscall table hooking                                        
linux_check_fop            - Check file operation structures for rootkit modifications                                                  
linux_check_idt            - Checks if the IDT has been altered     
linux_check_inline_kernel  - Check for inline kernel hooks    
linux_check_modules        - Compares module list to sysfs info, if available
...                                                           

There was an emacs process that I noticed with linux_psaux, which I suspected could have an open buffer with some tasty flag data:

$ python2.7 vol.py -f ../../pst-ctf-2021-v7.vmem --profile=Linuxanonymous-distro-1337x64 linux_psaux | grep emacs
Volatility Foundation Volatility Framework 2.6.1
2595   1000   1000   /usr/bin/emacs                                                  

Dumping the emacs process using linux_dump_map:

$ python2.7 vol.py -f ../../pst-ctf-2021-v7.vmem --profile=Linuxanonymous-distro-1337x64 linux_dump_map -p 2595 --dump-dir=dumps/

Since other challenges had flags with a CTF tag included, I checked for that with strings against the task memory. Sure enough, there’s our flag.

$ strings task.2595.0x* | grep CTF
PS_20th_CTF{wh1skey_j4ck007_analys1s}

The challenge that stumped me was a steganography one, where we were to find GPS coordinates in a png. I used exiftool first to check for the standard metadata. Using an online steganography tool I discovered that by isolating the bit planes (“Browse bit planes”). I was able to see the hidden data in the image, but I could not figure out the data format with the output that the online tool provided. There also appeared to be two different sections of hidden data, or the first section was a header for a format that I wasn’t able to identify in time.