UTCTF2021: Web: Cutest Cookie Clicker Rip-Off (100)

This is from the UTCTF2021 CTF

Challenge Author: Aya Abdelgawad

For this challenge we are given a little hint and a URL:

It is a game with an automatic timer that count’s down. You click the cookie to earn points. The high score is 1,000,000:

Given the name and theme of this game, I look to see what cookies it uses:

Neat, it stores my high score in a cookie. Let’s bake in a better score and refresh the page:

It applied my new highest score and is counting down:

When the clock runs out, it pops up with an alert containing the flag:

DaVinciCTF: Crypto: Substitution (25)

This is for the DaVinciCTF.

For this challenge, we are given the following ciphertext:

Rm xibkgltizksb, z hfyhgrgfgrlm xrksvi rh z nvgslw lu vmxibkgrmt rm dsrxs fmrgh lu kozrmgvcg ziv ivkozxvw drgs xrksvigvcg, zxxliwrmt gl z urcvw hbhgvn; gsv "fmrgh" nzb yv hrmtov ovggvih (gsv nlhg xlnnlm), kzrih lu ovggvih, girkovgh lu ovggvih, nrcgfivh lu gsv zylev, zmw hl uligs. Gsv ivxvrevi wvxrksvih gsv gvcg yb kviulinrmt gsv rmevihv hfyhgrgfgrlm.

Hfyhgrgfgrlm xrksvih xzm yv xlnkzivw drgs gizmhklhrgrlm xrksvih. Rm z gizmhklhrgrlm xrksvi, gsv fmrgh lu gsv kozrmgvcg ziv ivziizmtvw rm z wruuvivmg zmw fhfzoob jfrgv xlnkovc liwvi, yfg gsv fmrgh gsvnhvoevh ziv ovug fmxszmtvw. Yb xlmgizhg, rm z hfyhgrgfgrlm xrksvi, gsv fmrgh lu gsv kozrmgvcg ziv ivgzrmvw rm gsv hznv hvjfvmxv rm gsv xrksvigvcg, yfg gsv fmrgh gsvnhvoevh ziv zogvivw.

Gsviv ziv z mfnyvi lu wruuvivmg gbkvh lu hfyhgrgfgrlm xrksvi. Ru gsv xrksvi lkvizgvh lm hrmtov ovggvih, rg rh gvinvw z hrnkov hfyhgrgfgrlm xrksvi; z xrksvi gszg lkvizgvh lm ozitvi tilfkh lu ovggvih rh gvinvw klobtizksrx. Z nlmlzokszyvgrx xrksvi fhvh urcvw hfyhgrgfgrlm levi gsv vmgriv nvhhztv, dsvivzh z klobzokszyvgrx xrksvi fhvh z mfnyvi lu hfyhgrgfgrlmh zg wruuvivmg klhrgrlmh rm gsv nvhhztv, dsviv z fmrg uiln gsv kozrmgvcg rh nzkkvw gl lmv lu hvevizo klhhryrorgrvh rm gsv xrksvigvcg zmw erxv evihz.
weXGU{xi1kg3w_x1ks3i}

Given the challenge title, I head over to dcode.fr’s Mono-alphabetic Substitution cipher decoder:

Due to the amount of ciphertext, it took a few seconds to crank through it, but it did solve it:

And now I have the flag!

dvCTF{cr1pt3d_c1ph3r}

Vishwa CTF: Web: Redeeem (440)

This is from the 2021 Vishwa CTF

For this challenge, we are given a URL:

Going to the page, we get this:

Entering a coupon code does not appear to do anything. If we click the “BUY” button, we get this:

Inspecting the source, we see a hidden element named “current” with a value of “0”. This appears to be how my current balance is tracked.

I modify that element’s value to “7000” and then click the “BUY” button:

That gives us the flag!

UTCTF2021: Web: Source it!! (100)

This is from the UTCTF2021 CTF

Challenge Author: Rob H

For this challenge, we are given a little hint and a URL:

Here is the site:

I take a look at the source and find that it is doing client-side authentication in JavaScript:

I see that the password’s MD5 hash is “1bea3a3d4bc3be1149a75b33fb8d82bc”

A quick google search for that hash and I see that is has already been cracks and is “sherlock“.

I try logging in as admin with password sherlock and I’m in:

WinjaCTF2021: Find The Secret Person (550)

This is from the WinjaCTF2021.

For this challenge, we are given the following hint:

Going to the link give this page:

Looking at the source of the page, I see the images are named in sequential numbers:

Based on the hint “you are suppose to find the old person out them” on the page, I assume the image names (numbers) correspond to the order they were created. I look to see if there is a 0000.jpg file and there is!

I paste the name “Marie Collinsworth” into the text box and hit the enter key and get the flag as a response:

FLAG{Find_the_Secret_Agent_Y0u_F0uNd_Th3_R1gHt_P3rs0N}

WinjaCTF2021: JUSTWINTHIS (300)

This is from the WinjaCTF2021.

For this challenge, we are given he following hint:

Going to the link provided, we get this simple page:

After a bit of poking, I register an account:

When I log in with my new credentials, I am given this message:

Remembering a cipher I once saw that uses emojis, I try and decipher it using emojicipher.com

I see it decodes to “ar3_t0kens_$$$}”, which looks a lot like the tail end of a flag!

After some more poking, I see there is a cookie set by this site.

I decode the cookie value (base64) and see it is a JASON Web Token. Knowing how they are formatted, I break up the encoded cookie value and just decode the header to get this:

{"typ":"JWT","alg":"HS256"}{"iss":"http:\/\/ctf.winja.site","aud":"http:\/\/ctf.winja.site","role":"user","iat":1615014948,"exp":1615016748}

Seeing the “role” element with a value of “user”, I try changing the value to “admin” and then re-encoding the header and adding the preserved tail end of the original cookie value:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9jdGYud2luamEuc2l0ZSIsImF1ZCI6Imh0dHA6XC9cL2N0Zi53aW5qYS5zaXRlIiwicm9sZSI6ImFkbWluIiwiaWF0IjoxNjE1MDE0OTQ4LCJleHAiOjE2MTUwMTY3NDh9.Zsn6FXTUcHnRQ98d6PuYsJpLBuv7_FLOzx_8y8lu13c

I paste that cookie value into my browser and refresh the page to get this new message:

I just got the first half of the flag.

Combining the two I get the full flag value:

flag{justwinthis_all_i_w4nt_ar3_t0kens_$$$}

0x41414141 CTF: Register Secret PIN

This is from the 0x41414141 CTF.

When I went to register to compete in the 0x41414141 CTF I found that is was a little different from other CTFd based CTFs. Besides the normal registration information, it asks for a pin code (secret pin code for CTF registration).

Going back and looking through the site, I see on the About page that the secret pin code for CTF entry is hidden somewhere on the site:

After pouring through the source files for each page on the site, running curl POSTs, and looking at previous versions of the site on Archive.org, I considered the steganography approach.

Besides the normal social media link images, there are only two images on the site. One is the animated Offshift logo, which yielded no obvious results when running strings, binwalk, or other stego decoders:

The second image is a small Offshift logo that is used as the header logo:

After downloading this image, I ran strings on it to look for anything interesting:

Ahh! I see “secret: 100100100101” at the bottom of the results.

I convert the binary string to decimal:

echo "obase=10; ibase=2; 100100100101" | bc

Using the resulting decimal value as the pin, I am now able to register for the CTF.

0x41414141 CTF: Misc: optimizer (400)

This is from the 0x41414141 CTF by pop_eax.

For this challenge, we are just given details for two server instances; one for US and one for EU.

Connecting via netcat, we are told that we will be given a number of problems and we have to solve them. It mentions that level 1 is tower of hanoi. A quick google search and I find more information about it. After some trial and error using different possibilities for the number of pegs.

This presentation was especially helpful in determining the formula (moves = 2n – 1) to get the number of moves: http://www.cs.uvm.edu/~rsnapp/teaching/cs32/lectures/hanoi.pdf

A manual check confirms the formula is correct, but the server responds with another problem.

There are four disks listed, so n=4. 24 – 1 = 15

We will need to automate this 🙂

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('45.134.3.200', 9660))

print('Server:', str(s.recv(1024)))
#print s.recv(1024)
while True:
    data = s.recv(1024).strip()
    if data:
	count = 0
        data = str(data)
        print(data)
        for i in data:
		if i == ',':
			count = count + 1
	count = count + 1
	n = pow(2, count) - 1
        if '[' in data:
		s.send(str(n))
        	print('Client: ', n)
s.close()

When I run this script, it iterates through quite a few problems, then the server reports that I’m in level 2: and have to give the number of inversions for the provided output.

A quick google search helps me figure out how to do this in python. https://www.geeksforgeeks.org/python-program-for-count-inversions-in-an-array-set-1-using-merge-sort/

I add some checks for the current level to help apply the appropriate process and then calculate the inversions:

import socket
import re

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('45.134.3.200', 9660))

def getInvCount(arr, n): 
  
    inv_count = 0
    for i in range(n): 
        for j in range(i + 1, n): 
            if (arr[i] > arr[j]): 
                inv_count += 1
  
    return inv_count 
level = 1
print('Server:', str(s.recv(1024)))
while True:
    data = s.recv(2048).strip()
    if data == '':
        break
    if data:
		if 'level 1' in data:
			level = 1
			print ('********************************** Level 1 **********************************')
		if 'level 2' in data:
			level = 2
			print ('********************************** Level 2 **********************************')

		if level == 1:
		
			count = 0
			data = str(data)
			print str(data)
			for i in data:
					if i == ',':
							count = count + 1
			count = count + 1
			n = pow(2, count) - 1
			if '[' in data:
				s.send(str(n))
				#print('Client: ', n)
	
		if level == 2:
			print str(data)
			
			if '[' in data:
			    sep = ']'
			    stripped = data.split(sep, 1)[0]
			    arr1 = stripped.split(', ')
			    arr1 = map(lambda each:each.strip("["), arr1)
			    arr = arr1
			    arr = [int(numeric_string) for numeric_string in arr1]
			    n = len(arr)
			    inversioncount = getInvCount(arr,n)
			    s.send(str(inversioncount))
s.close()

Here is a video of the script in action:

And the flag:

I really appreciate the challenge!

0x41414141 CTF: Crypto: factorize (400)

This is from the 0x41414141 CTF by Soul.

For this challenge, we are provided with a c value, n value, and a python script.

c: 17830167351685057470426148820703481112309475954806278304600862043185650439097181747043204885329525211579732614665322698426329449125482709124139851522121862053345527979419420678255168453521857375994190985370640433256068675028575470040533677286141917358212661540266638008376296359267047685745805295747215450691069703625474047825597597912415099008745060616375313170031232301933185011013735135370715444443319033139774851324477224585336813629117088332254309481591751292335835747491446904471032096338134760865724230819823010046719914443703839473237372520085899409816981311851296947867647723573368447922606495085341947385255

n: 23135514747783882716888676812295359006102435689848260501709475114767217528965364658403027664227615593085036290166289063788272776788638764660757735264077730982726873368488789034079040049824603517615442321955626164064763328102556475952363475005967968681746619179641519183612638784244197749344305359692751832455587854243160406582696594311842565272623730709252650625846680194953309748453515876633303858147298846454105907265186127420148343526253775550105897136275826705375222242565865228645214598819541187583028360400160631947584202826991980657718853446368090891391744347723951620641492388205471242788631833531394634945663
import binascii
import random
from Crypto.Util.number import isPrime

flag = open("flag.txt", "rb").read().strip()
m = int(binascii.hexlify(flag), 16)

def genPrimes(size):
    base = random.getrandbits(size // 2) << size // 2
    base = base | (1 << 1023) | (1 << 1022) | 1
    while True:
        temp = base | random.getrandbits(size // 2)
        if isPrime(temp):
            p = temp
            break
    while True:
        temp = base | random.getrandbits(size // 2)
        if isPrime(temp):
            q = temp
            break
    return (p, q)

p, q = genPrimes(1024)
n = p * q
e = 0x10001

print("c:", pow(m, e, n))

Based on the provided values and script, this appears to be an RSA type challenge.

I got to https://www.alpertron.com.ar/ECM.HTM to get the possible primes for the provided n value. There are only two:

1521152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509185464641520736454955410019736330026303289754303711165526821866422766844554206047678337249535003432035470125187072461808523973483360158652600992259609986591
and
152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509191077550351496973264159350455849525747355370985161471258126994336297660442739951587911017897809328177973473427538782352524239389465259173507406981248869793

I iterate these in a script to calculate phi:

primes = [152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509185464641520736454955410019736330026303289754303711165526821866422766844554206047678337249535003432035470125187072461808523973483360158652600992259609986591, 152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509191077550351496973264159350455849525747355370985161471258126994336297660442739951587911017897809328177973473427538782352524239389465259173507406981248869793]

phi = 1
for p in primes:
  phi *= (int(p) - 1)

Based on the e value (e = 0x10001 = 65537) from the provided python script, I calculate d:

e = 65537
d = inverse(e,phi)

I then use the power function with the calculated d value and provided c and n values to get the plaintext value (which gets converted from long to bytes):

plaintext = pow(c,d,n)
print(long_to_bytes(plaintext))

This chunks out our flag:

The full python script:

from Crypto.Util.number import inverse, long_to_bytes

primes = [152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509185464641520736454955410019736330026303289754303711165526821866422766844554206047678337249535003432035470125187072461808523973483360158652600992259609986591, 152103631606164757991388657189704366976433537820099034648874538500153362765519668135545276650144504533686483692163171569868971464706026329525740394016509191077550351496973264159350455849525747355370985161471258126994336297660442739951587911017897809328177973473427538782352524239389465259173507406981248869793]

e = 65537

c = 17830167351685057470426148820703481112309475954806278304600862043185650439097181747043204885329525211579732614665322698426329449125482709124139851522121862053345527979419420678255168453521857375994190985370640433256068675028575470040533677286141917358212661540266638008376296359267047685745805295747215450691069703625474047825597597912415099008745060616375313170031232301933185011013735135370715444443319033139774851324477224585336813629117088332254309481591751292335835747491446904471032096338134760865724230819823010046719914443703839473237372520085899409816981311851296947867647723573368447922606495085341947385255

n = 23135514747783882716888676812295359006102435689848260501709475114767217528965364658403027664227615593085036290166289063788272776788638764660757735264077730982726873368488789034079040049824603517615442321955626164064763328102556475952363475005967968681746619179641519183612638784244197749344305359692751832455587854243160406582696594311842565272623730709252650625846680194953309748453515876633303858147298846454105907265186127420148343526253775550105897136275826705375222242565865228645214598819541187583028360400160631947584202826991980657718853446368090891391744347723951620641492388205471242788631833531394634945663

phi = 1

for p in primes:
  phi *= (int(p) - 1)
d = inverse(e,phi)

plaintext = pow(c,d,n)

print(long_to_bytes(plaintext))

Thank you for the challenge!