JerseyCTF 2023

Hello ctfian’s! I played JerseyCTF 2023 which was happened from 15 Apr to 16 Apr. I played it with the team Invaders0x1. This time I scored 2600+ points. And our Team secured 125th place in CTF.

Progess

This time I solved 6 challs in crypto which is my fav category.

Crypto Challs

missing employee-1

missingemp1

TGltYSBBbHBoYSBLaWxvIEVjaG8gTWlrZSBJbmRpYSBDaGFybGllIEhvdGVsIEluZGlhIEdvbGYgQWxwaGEgTm92ZW1iZXI= Decoded this text from base64

mj0ln1r@Linux:~JerseyCTF/crypto/missing_employe_done$ echo "TGltYSBBbHBoYSBLaWxvIEVjaG8gTWlrZSBJbmRpYSBDaGFybGllIEhvdGVsIEluZGlhIEdvbGYgQWxwaGEgTm92ZW1iZXI=" | base64 -d
Lima Alpha Kilo Echo Mike India Charlie Hotel India Golf Alpha November

Submitted this in flag format, but it doesn’t worked for me. The did a quick google search these words. And i found that these are the NATO phonetic alphabets. And decoded it by following the representations of this words.

Lima - l
Alpha - a
Kilo - k
Echo - e
and so on.

Flag: jctf{lake-michigan}

jack-and-jill

jackandjill

Ciphertext is given : pgQVJFCohpccuyBSbwxcxpVZCAATRT. A 2x2 matrix is given [[3,9],[4,7]].

By observing the description i found that this is a hill cipher. I quickly searched for the hill cipher decoder online. I used this site to decipher the text.

jackandjilldecode

The deciphered text is hiTHEREwelcomeTOlinearALGEBRAZ

Flag : jctf{hiTHEREwelcomeTOlinearALGEBRAZ}

space-dust

spacedust

The challenge have this attachment message_from_tom.txt

First of all, I observed a == at the end of the content of the file. Immediated I decoded it from base64 and stored in other file. And the file size is a bit suspicious so I observed its hexdump. It contains a PNG header. So, I renamed the image image into decoded.png. Then i opened the image it has the flag in it.

mj0ln1r@Linux:~/space-dust$ cat message_from_tom.txt | base64 -d >> decoded
mj0ln1r@Linux:~/space-dust$
mj0ln1r@Linux:~/space-dust$ xxd decode | head
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
00000010: 0000 0a00 0000 05a0 0806 0000 0092 001a  ................
00000020: df00 0000 0173 5247 4200 aece 1ce9 0000  .....sRGB.......
00000030: 0004 6741 4d41 0000 b18f 0bfc 6105 0000  ..gAMA......a...
00000040: 0009 7048 5973 0000 0ec3 0000 0ec3 01c7  ..pHYs..........
00000050: 6fa8 6400 00ff a549 4441 5478 5ee4 fd67  o.d....IDATx^..g
00000060: 776c 3b92 a609 1a35 e9d4 fae8 2b43 6556  wl;....5....+CeV
00000070: 5677 4fcf 879e 5933 ffad fe5d d7a8 55d5  VwO...Y3...]..U.
00000080: 5599 1915 1157 9c7b 34b5 763a f5bc cf6b  U....W.{4.v:...k

mj0ln1r@Linux:~/space-dust$ mv decoded decoded.png

The decoded image is decoded.png .

Flag : jctf{th1s_1s_n0t_a_game}

roko-cipher-in-the-console

roko

We can see this is a transpositional cipher. f1stg}th10_ej{s__act_nam. I observed that the flag is plaintext but it was transposed. We can observe that the jctf{} letters in the ciphertext.

I wrote this ciphertext in different deapths. Like writing it in 4 columns, 5 columns and so on . I observed a standard format when I write this in 6 columns.

rokocol

We can get the flag by reading column by column and in every column the order of reading letters is row-3,row-4,row-2,row-1.

That is first column should be taken as jctf. Second column is {th1 and so on.

Flag : jctf{th1s_1s_n0t_a_game}

supply-stash

supplystash1 supplystash2

This is medium level challenge in crypto. The challenge has a java file name numericalEncoder.java

//Encoding program originally by Logan DesRochers
import java.lang.Math;
import java.util.ArrayList;
import java.util.Scanner; 

public class numericalEncoder{ 
	public static void main(String[] args){ 
		String alphabet = "abcdefghijklmnopqrstuvwxyz";
		Scanner sc = new Scanner(System.in); 
		System.out.println("Enter string to be encoded: ");
		String m = sc.nextLine(); 
		m = m.toLowerCase(); 
		System.out.println("Enter int block size: ");
		int r = sc.nextInt();  

		//padding to variable block size 
		if(m.length() % r != 0){ 
			while(m.length() % r != 0){ 
				m = m + "x";
			}
		}
		System.out.println("M after padding: " + m);
		
		//Variable block size 
		ArrayList<Integer> encodedBlocks = new ArrayList<Integer>();
		int numBlocks = m.length() / r; 
		for(int i = 0; i < numBlocks; i++){ 
			String block = m.substring(i * r, r + i * r); 
			System.out.println(block);
			int power = block.length() - 1;
			int representation = 0;
			for(int j = 0; j < block.length(); j ++){
                        	String currentLetter = block.substring(j,j+1);
                        	int letterValue = alphabet.indexOf(currentLetter);
                        	representation += letterValue * Math.pow(26, power);
                        	power--;
                	} 
			encodedBlocks.add(representation);
		}
	        System.out.println("Encoded blocks are as follows: ");	
		for(int num : encodedBlocks){
			System.out.println(num);
		}
	}
}

The output of the above code is SUPPLIES: 6639182 5837362 7923517 8463981 3588695 8358510" and this is the encoded vesion of our flag. So analyzed the code and reversed the encoding program.

My observations are, the above code is doing generating a integer for for a block of characters. That is 6639182 is on encoded version of a block of characters. This is generated by accessing the index of the character from alphabet string and this is multiplied pow(26,power) where power=len(block)-1 and this power is decreased for every new character in the block.

Okay, lets have some math. lets assume block size = 4
power = 3
the initial encoded block value will become
index(char)x26^3 + index(char)x26^2 + index(char)x26^1 + index(char)x26^0
Simply it is doing a base26 operation. So, in the decode program, we have to perform decoding of base26.

This is the solution script which can give the decoded message from encoded blocks.

import string
alphabet = string.ascii_lowercase
input_str = input("Enter numerical blocks to be decoded (separated by spaces): ")
# split input into individual numerical blocks
input_blocks = input_str.split(" ")
decoded_blocks = []
for block in input_blocks:
    num = int(block)
    decoded = ""
    while num > 0:
        remainder = num % 26
        decoded_letter = alphabet[remainder]
        decoded = decoded_letter + decoded
        num //= 26
    decoded_blocks.append(decoded)
# combine decoded blocks into original message
decoded_message = "".join(decoded_blocks)
print("Decoded message: " + decoded_message)
#6639182 5837362 7923517 8463981 3588695 8358510
# onthemuddyriversnorthwestshore
# jctf{onthemuddyriversnorthwestshore}

Flag : jctf{onthemuddyriversnorthwestshore}

play-reasonably

playreasonably

This one is a special challenge. I spent more than an hour to solve this. And at the end of the ctf play-reasonably has only 11 solves.

Okay coming to challenge, I searched many keywords online but I havent find any thing positive. By observing carefully the ciphertext looks like it is from an old cipher. And I know about play-fair cipher. And they said play-reasonably and it matched with it. So, i started deciphering this playfair ciphertext.

Ciphertext : WTATRHABWKYKACBMWD
I tried it with the key THEBOYSAREBACKINTOWN as the description highlighted it. I solved it with pen and paper as i know the working of playfair. Tried evry possible 5x5 key matrix.

THEBOYSARCKINWDFGLMPQUVXZ (-J)
THEBOYSARCKINWDFGJLMPQUXZ (-V)
THEBOYSARCKINWDFGJLMPUVXZ (-Q)
THEBOYSARCKINWDFGJLMPQUVX (-Z)
None of them are worked. So, I read the description again, They said theboysarebackintown are playing in reverse.
So, I tried the key matrix in reverse order.
NWOTIKCABERSYH And the key matrix will be NWOTIKCABERSYHDFGLMPQUVXZ (-J)

And I got the plaintext : NOBODYCANCRACKTHIS
Here is my paper work might help you out.

playreasonablypaper

You can use this site to decrypt or learn more about playfair ciper here.

Flag : jctf{NOBODYCANCRACKTHIS}


Web - Look-Im-Hacking

look

A simple web challenge. The challenge url has the login page. I looked at the source code of it. And found this script.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="text/html">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script type="text/javascript">
        var passkey = '';

        function createPass() {
            const valids = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$#@!&%"
            for (let i = 0; i < 20; i++) {
                passkey += valids.charAt(Math.floor(Math.random() * valids.length))
            }
            passkey = btoa(passkey);
        }

        function checkPass() {
            console.log(passkey)
            if (document.getElementById("un1").value == "admin" && document.getElementById("pw2").value == atob(passkey)) {
                loadFlag();
            }
        }

        function loadFlag() {
            const xhttp = new XMLHttpRequest();
            xhttp.onload = function () {
                document.getElementById("reveal").innerHTML = this.responseText;
            }
            xhttp.open("GET", "./flag.txt")
            xhttp.send();
        }
    </script>
</head>

Found that there is a /flag.txt end point. And simply curling it results the flag.

mj0ln1r@Linux:~/web$ curl https://www.jerseyctf.online/flag.txt
$Hacker&?r3@L$

Flag : jctf{$Hacker&?r3@L$}


Forensics - unknown-origin

unknown

The challenge have this attached Photo.jpg.

Simple strings does the job.

mj0ln1r@Linux:~/forensics$ strings Photo.jpg | grep jctf
jctf{0gre$_h@ve_l@yers}

Flag : jctf{0gre$_h@ve_l@yers}

Forensics - firefox-history

firefox

Attached file : places.sqlite

So, i quickly searched for sqlite viewer online (I dont want to install additionally :) )

Found this site to view sqlite file.

As the file name hints places. So selected moz_places table to view.

firefox places

As the description said, i looked for the jerseyctf.com entry in the table. It was on 137th row.

firefox jersey

I copied the last time visited value of the 137th entry. As the flag format is jctf{YYYY-MM-DD-HH-MM-SS} of this time, I used a seconds to epoch converter to get this format.

1674907264007000 to epoch on this site

firefox epoch

And the correct format is the date in GMT that is 2023-01-28-12-01-04

Flag : jctf{2023-01-28-12-01-04}


bin - plain

plain

The challenge has bin executable named plain

strings done the job for us again.

mj0ln1r@Linux:~/forensics$ strings plain | grep jctf
jctf{i_<3_5tr1Ng5_59af0c0ed}

Flag : jctf{i_<3_5tr1Ng5_59af0c0ed}


OSINT - record-me

recordme

The challenge is highlighting record and jerseyctf.com. So, I search for all the DNS records of jerseyctf.com.

I search all the whois records of the jerseyctf.com. And in there a string pw-d714d7aa25df63925ec2b3893928671b. As they are talking about password pw tempts me to submit it as flag.
But afer many unsuccesful tries I tried dig to fetch DNS records of jerseyctf.com.

And finally the flag is available at TXT records of jerseyctf.com. I used dig to do it.

mj0ln1r@Linux:~/osint$ dig jerseyctf.com txt

; <<>> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu <<>> jerseyctf.com txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48664
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;jerseyctf.com.			IN	TXT

;; ANSWER SECTION:
jerseyctf.com.		3600	IN	TXT	"jctf{hop_OFF_TIKTOK_and_GET_s0me_SUN_OUTSID3!}"

;; Query time: 732 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Fri Apr 21 12:14:36 IST 2023
;; MSG SIZE  rcvd: 101

Flag : jctf{hop_OFF_TIKTOK_and_GET_s0me_SUN_OUTSID3!}

OSINT - geo-guess

geoguess

So, its clear that we have to find the name of the building given in the picture.

geo

I did a quick google image search and found the building name right on the top of result.

geo

Flag: jctf{west-edmonton-mall}


Misc - pits-of-tartarus

pits

The attached file : file834.tar.gz

This tar is a hundrends of recompressions of tar.gz

So, I run this command to loop over all the compressions in it and extract the files.

mj0ln1r@Linux:~/misc$ for i in {834..1}; do tar -xf file$i.tar.gz; rm file$i.tar.gz; done
mj0ln1r@Linux:~/misc$ ls
file0.tar.gz

The above command will extract the zips and deletes it prior zip to make directory clean. As we can see now file0.tar.gz is the last one left.

Again this file0.tar.gz contains zips from file-1.tar.gz, and so on. So i extracted file0.tar.gz just one time then modified above command lil bit to extract this sequece of tars.

mj0ln1r@Linux:~/misc$ tar -xf file0.tar.gz
mj0ln1r@Linux:~/misc$ ls
file-1.tar.gz
mj0ln1r@Linux:~/misc$ for i in {1..833}; do tar -xf file-$i.tar.gz; rm file-$i.tar.gz; done
tar: file-390.tar.gz: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
mj0ln1r@Linux:~/misc$ ls
file.txt
mj0ln1r@Linux:~/misc$ cat file.txt
jctf{N0t_$tuck_in_tHe_t@r}

I assumed that there will be again 834 zips so I tried the above loop. But actually there were only 389 tars. Eventhough the above command extracted the file that we want but returned some error. The flag is present in file.txt

Flag : jctf{N0t_$tuck_in_tHe_t@r}


Misc - crack-keepass

keepass

Attached file : Databse.kdbx

This time I installed keepassx on my machine.

mj0ln1r@Linux:~/misc$ sudo apt install keepassx

And I Opened the Database.kdbx with kepassx GUI app. It prompts me for a master password. As the challenge hints that crack, I cracked it with JOHN and rockyou.txt.

mj0ln1r@Linux:~/misc$ keepass2john Database.kdbx >> database_hashes_new.hash
mj0ln1r@Linux:~/misc$ john --wordlist=/usr/share/wordlists/rockyou.txt -format:keepass databse_hashes_new.hash
Using default input encoding: UTF-8
		Loaded 1 password hash (KeePass [SHA256 AES 32/64])
		Cost 1 (iteration count) is 60000 for all loaded hashes
		Cost 2 (version) is 2 for all loaded hashes
		Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
		Press 'q' or Ctrl-C to abort, almost any other key for status
		1jersey          (?)
		1g 0:01:57:04 DONE (2023-04-16 16:24) 0.000142g/s 53.41p/s 53.41c/s 53.41C/s 1jersey
		Use the "--show" option to display all of the cracked passwords reliably
		Session completed

Master key of the database is 1jersey.

So, I opened it the database file with master key. When I am navigating through the database file in keepassx app. I found a file named flag in General category.

Flag : jctf{pr073c7_y0ur_v4ul7}