root💀bl4ck4non-sec:~#

Hack. Eat. Sleep. Repeat!!!

View on GitHub

I participated in the CyberStarters CTF qualifier competition organized by the Diary of Hackers, took place between April 28th to April 30th 2023. For me personally I got to learn new things

This is a writeup of the challenges I solved during the event. Lets jump right into it

Challenges Solved

Sanity Check

Steg

Web

Cryptography

Osint

BlockChain

Sanity Check

Discord (10 points)


image

Clicking on the link takes us to the Disocrd Server

image

Well, scrolling down that channel we find a base64 code just sitting there

image

Let’s go ahead and crack this RG9IQ1RGe3RyeV90b19iZV9oYWNrdGl2ZV9vbl9kaXNjb3JkX2hlaGVoZWhlaGVoZX0K since we already know it’s base64 hehe

command:echo RG9IQ1RGe3RyeV90b19iZV9oYWNrdGl2ZV9vbl9kaXNjb3JkX2hlaGVoZWhlaGVoZX0K | base64 --d

image

Cool, we got our flag hehe😎

FLAG:- DoHCTF{try_to_be_hacktive_on_discord_hehehehehehe}


DoHCTF{_colwSPs:(} (10 points)


image

Yeah, this challenge is just to check if your sanity is still intact lool. The flag is the name of the challenge.

FLAG:- DoHCTF{_colwSPs:(}


Twitter (10 points)


image

The link redirects you to their twitter page

image

Following them gives us the answer to this challenge.

FLAG:- yes

Steg

OK (46 points)


image

Lets download the file to our machine

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Steg]
└─$ ls    
0cold_flag.txt
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Steg]
└─$ file 0cold_flag.txt 
0cold_flag.txt: ASCII text

A text file, cool. Lets try to read the contents of the file

command:cat 0cold_flag.txt

image

oops, there seems to be some spacing after the word “Iceeeedddd”. I have once solved a similar challenge and I remember using stegnow to solve it. To install stegsnow sudo apt install stegsnow

command:stegsnow -C 0cold_flag.txt

image

cool, we got our flag

FLAG:- DoHCTF{another_quite_simple_one}

Web

None Shall Pass (68 points)


image

Goint to the link provided should get you this

image

Who are you?? I am BlackAnon lool😂. There was nothing else asides the who are you?. There was also nothing in the source page.

At this point I had to invite Burpsuite to join the party😎. Lets try to capture requests

image image

Lets send this to repeater

image

We can see that the cookie uses a jwt token. Lets try to crack this token. You can do that here

image

Lets try changing the guest name to admin

image

Now, lets replace the jwt token with this new one

image

oops, We got the Invalid Token error

Well, after a bit of research I found something interesting. I remember completing the owasptop10 2021 room on TryHackMe. Checking the notes I took down I saw this

image

Now, this vulnerability falls under the owasptop10, the name of the vulnerability is Data Integrity Failures. You can learn more about it here.

At this point I just had to follow what I had in my note😎. Let’s go this webpage

image

This is my JWT Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imd1ZXN0In0.iJ9U4tIUxxLbbOb_YXVkpvkBqtPsFtAxWIvmcakDfL0. So the first part eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 is the header. The second part eyJ1c2VybmFtZSI6Imd1ZXN0In0 is the payload while the last part iJ9U4tIUxxLbbOb_YXVkpvkBqtPsFtAxWIvmcakDfL0 is the signature.

So, we’ll be modifying only the header and the payload. Lets start with the header

image

Lets go ahead and change the alg HS256 to none. Then we encode in base64

image

cool we have modified the header eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0=. Lets do the same for the payload

image

Lets go ahead and change the username guest to admin. Then we encode in base64

image

cool, we have also modified the payload eyJ1c2VybmFtZSI6ImFkbWluIn0=.

Now, joining the header, payload and signature together, we have eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0=.eyJ1c2VybmFtZSI6ImFkbWluIn0=.iJ9U4tIUxxLbbOb_YXVkpvkBqtPsFtAxWIvmcakDfL0.

The last thing left to do is replacing the old jwt token to the modified one

image

showing this response in the web browser

image

We got our flag😎

FLAG:- DoHCTF{jwt_has_a_none_algo_loll}


^_^ (200 points)


image

We were told not to bruteforce lool, this means we don’t need directory fuzzing tools. Lets navigate to the webpage

image

We get this, take note of the url

image

Now, those look like base64 code. Checking the source page

image

We get 2 more directories also looking like base64 code. Now, trying to crack this was giving me some weird strings.

What do I mean??

These are the directories that look base64 ish

/GgoXAQ4QGxMCHA4ZA1JKDFlWAEFRG1YQGw/c2RzZHZ5dXdnZGd3ZzcyZTcyZTk4dTJ1Yw
/HwEBBw0WGQ0HAQEaVBYcEAwHHw0QHRAaHxAdEAEQ/c2R1c2hkdWhzdWRoOHNoZGl1c2hkaXVoc3VpZGRi
/ISdFLDRLKitfPDRKRT0SCRcHEBIIFwsTEg/QEUqWUAqSEQqSFUoKkhmaHVoZWZpdWRmZg

For example, lets try to crack this ISdFLDRLKitfPDRKRT0SCRcHEBIIFwsTEg

command:echo ISdFLDRLKitfPDRKRT0SCRcHEBIIFwsTEg | base64 --d

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Web]
└─$ echo ISdFLDRLKitfPDRKRT0SCRcHEBIIFwsTEg | base64 --d                  
!'E,4K*+_<4JE=  
               base64: invalid input

Now, this is the weird string I was talking about.

Well, I had to sacrifice 20 points to unlock the hint so as to know the next course of action

image

Now, from the hint we got ^ bitwise operation.

The bitwise XOR (^)(exclusive OR) operation takes two bit patterns of equal length and performs a logical XOR operation on each pair of corresponding bits. The resulting bit pattern has a 1 in each position where the corresponding bits in the operands are different, and a 0 where they are the same.

Taking a look at the directories you’ll observe they have the same length (i.e before and after the /).

For example,

We’ll be xoring HwEBBw0WGQ0HAQEaVBYcEAwHHw0QHRAaHxAdEAEQ with c2R1c2hkdWhzdWRoOHNoZGl1c2hkaXVoc3VpZGRi to see if we can get something.

I’ll be using this python script

import base64

# Example base64 encoded strings
encoded_str1 = "HwEBBw0WGQ0HAQEaVBYcEAwHHw0QHRAaHxAdEAEQ"
encoded_str2 = "c2R1c2hkdWhzdWRoOHNoZGl1c2hkaXVoc3VpZGRi"

# Base64 decode the encoded strings
decoded_str1 = base64.b64decode(encoded_str1)
decoded_str2 = base64.b64decode(encoded_str2)

# XOR the two decoded strings
xored_str = bytes([a ^ b for a, b in zip(decoded_str1, decoded_str2)])

# Print the result
print(xored_str)

This script demonstrates how to perform XOR operation between two base64-encoded strings

Lets run it

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Web]
└─$ ls
abeg.py
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Web]
└─$ python abeg.py
b'letterletterletterletterletter'

cool, I got this. Fortunately they gave a free hint which goes like this

indexindexindexindexindex
aboutaboutaboutaboutabout
letterletterletterletterletter
flagflagflagflagflag

From our script we ran earlier we can tell that we are on the right path. Now, what we have to do is to look for a way to encode the flagflagflagflagflag to it’s base64 representation then we xor null byte with null byte which will give A. After we can make the length of the base64 encoded form of A to be equal to len of null byte which is 28.

The reason why we are using null byte is because when you xor something with zero you get that samme value being xored and when you xor two things that are the same you get zero.

For this we’ll be using a python script

from pwn import xor
import base64 as b

flag = b'flagflagflagflagflag'
encoded_flag = b.b64encode(flag)

null = b'0x0'
xored = xor(null, null)
second_ = b.b64encode(xored) * 7


print(encoded_flag+b'/'+second_)

Save this script and run it

image

We got the output we wanted, lets navigate to this directory, hopefully we get our flag

image

cool, we got our flag😎

FLAG:- DoHCTF{xor_rox_xor}

Cryptography

di_sease (100 points)


image

Lets download the file to our machine

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ ls 
flag.png
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ file flag.png      
flag.png: PNG image data, 814 x 156, 8-bit/color RGBA, non-interlaced

Okay,this is a PNG image. Lets try to use zsteg on the image, we might find something interesting hehe

command:zsteg flag.png

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ zsteg flag.png      
meta Software       .. text: "gnome-screenshot"
meta Creation Time  .. text: "Thu 27 Apr 2023 14:24:34"
b1,r,msb,xy         .. file: Unicode text, UTF-32, big-endian
b1,rgba,lsb,xy      .. text: ["w" repeated 8 times]
b1,abgr,msb,xy      .. text: ["w" repeated 8 times]
b2,r,lsb,xy         .. text: "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUP"
b2,rgba,lsb,xy      .. text: ["?" repeated 17 times]
b2,abgr,msb,xy      .. text: ["?" repeated 17 times]
b4,r,lsb,xy         .. text: ["U" repeated 247 times]
b4,g,lsb,xy         .. text: ["w" repeated 247 times]
b4,b,lsb,xy         .. text: "333333337wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
b4,rgb,lsb,xy       .. text: "5wWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwW"
b4,bgr,lsb,xy       .. text: "uwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuwWuw"

oops, nothing

Lets try to check what the image is all about

image

hehe, this is a navy signal code. We’ll be using dcode.fr for this.

image

image

We got something DOHCTFTHEFLAGSREVEALED009, looks like the flag, but it is not the flag because that is not the right format.

Lets rearrange it

FLAG:- DoHCTF{The_flags_revealed_009}


Hensel’s Mystery (360 points)


image

Lets download the files to our machine

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ ls    
flag.png  output.txt  ring.py
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ file output.txt  
output.txt: ASCII text, with very long lines (884)
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ file ring.py   
ring.py: Python script, ASCII text executable

We got ourselves an ASCII text and a Python script.

The content of both files

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ cat output.txt 
45406770103725904509890104231914678754265961643298482440409237765195072368733672685631587979562241346*x^4 + 42764372489624602989152383173709795403796386376344802703066528962696589468564501897000324538498812883*x^3 + 37672731284607729155480237866218406485893919987814572486490754064498223292180995037432012350216544417*x^2 + 55462425449896168600390367564436787134741290054741525865807795492693442375757671549228298754153509613*x + 6778690755895128168751737959454411972187106669733266559106651743590246692689398562032067795146717162848413292299573013038367117575935673619248776925892672201933424467005517162118712395701681263279585553299544107860626811206695844212433182471614373859755499052750286667585910623259340579702249091680614010546399687179863049582625671630876108790555962058243905551470611736992489702159306356102118074450673803009393106039180751255185874156459283395261688861
                                                                                                                                                                                                
┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/CyberStarters_CTF/Cryptography]
└─$ cat ring.py   
from sage.all import *
import codecs

def read_flag():
    with open('flag.txt', 'r') as file:
        return file.read().strip()

def encode_flag(flag):
    encoded = codecs.encode(flag.encode(), 'hex')
    return int(encoded, 16)

def generate_polynomial(flag):
    ranges = int(log(flag, 2))
    p = 35671
    k = 100
    N = p**k
    d = 5
    P = PolynomialRing(Zmod(N), names='x', implementation='NTL')
    x = P.gen()
    poly = 0
    for c in range(d):
        poly += ZZ.random_element(2**ranges, 2**(ranges+1))*x**c
    remainder = poly(flag)
    poly = poly - remainder
    assert poly(flag) == 0
    return poly

def main():
    flag = read_flag()
    encoded_flag = encode_flag(flag)
    poly = generate_polynomial(encoded_flag)
    print(poly)

if __name__ == '__main__':
    main()

what does this script do??

This Python script uses the SageMath library to generate a polynomial with a specific property. The polynomial is generated based on an encoded flag read from a file called "flag.txt". The encoding of the flag is done by converting the flag string to its hexadecimal representation and then converting the hexadecimal representation to an integer.

Well, I am not really a cryptography fanboy. Went online to read writeups and I found this

From the script it is clear that the output is the root of a polynomial, and the file output..txt contains some polynomials. So, the challenge is to find the root of the polynomial.

To solve this challenge, we can first find a solution for the given polynomial over mod p and then use Hensel’s lifting lemma to find a solution

Hensel's lifting lemma, also known as Hensel's lemma or Hensel's lemma for polynomials, is a theorem in algebra that allows the lifting of a solution to a modular equation to a solution of a nearby polynomial equation with integer coefficients. Specifically, the theorem provides a method for constructing solutions to congruences modulo prime powers by iteratively lifting a solution modulo a prime to a solution modulo a higher power of the same prime. The lemma is useful in various areas of mathematics and computer science, including number theory, algebraic geometry, and cryptography.

I’ll be using this python script to solve the challenge

from sage.all import *

p = 35671
k = 100
N = p**k

P = PolynomialRing(Zmod(p), names='x', implementation='NTL')
x = P.gen()
pol = 45406770103725904509890104231914678754265961643298482440409237765195072368733672685631587979562241346*x**4 + 42764372489624602989152383173709795403796386376344802703066528962696589468564501897000324538498812883*x**3 + 37672731284607729155480237866218406485893919987814572486490754064498223292180995037432012350216544417*x**2 + 55462425449896168600390367564436787134741290054741525865807795492693442375757671549228298754153509613*x + 6778690755895128168751737959454411972187106669733266559106651743590246692689398562032067795146717162848413292299573013038367117575935673619248776925892672201933424467005517162118712395701681263279585553299544107860626811206695844212433182471614373859755499052750286667585910623259340579702249091680614010546399687179863049582625671630876108790555962058243905551470611736992489702159306356102118074450673803009393106039180751255185874156459283395261688861

# help polynomial
var('y')
f = 45406770103725904509890104231914678754265961643298482440409237765195072368733672685631587979562241346*y**4 + 42764372489624602989152383173709795403796386376344802703066528962696589468564501897000324538498812883*y**3 + 37672731284607729155480237866218406485893919987814572486490754064498223292180995037432012350216544417*y**2 + 55462425449896168600390367564436787134741290054741525865807795492693442375757671549228298754153509613*y + 6778690755895128168751737959454411972187106669733266559106651743590246692689398562032067795146717162848413292299573013038367117575935673619248776925892672201933424467005517162118712395701681263279585553299544107860626811206695844212433182471614373859755499052750286667585910623259340579702249091680614010546399687179863049582625671630876108790555962058243905551470611736992489702159306356102118074450673803009393106039180751255185874156459283395261688861
# derivative of f
fd = 4*45406770103725904509890104231914678754265961643298482440409237765195072368733672685631587979562241346*y**3 + 42764372489624602989152383173709795403796386376344802703066528962696589468564501897000324538498812883*3*y**2 + 37672731284607729155480237866218406485893919987814572486490754064498223292180995037432012350216544417*2*y + 55462425449896168600390367564436787134741290054741525865807795492693442375757671549228298754153509613

# First, find roots modulo p
sols = []
for i in range(p):
    if Mod(pol(i),p) == 0:
        sols.append(i)

derivs = [fd(y=s) for s in sols]

sols_old = sols
for n in range(k-1):
    sols = []
    for s_old,d in zip(sols_old, derivs):
        sols.append(int(Mod(s_old-int(f(y=s_old))*int(Mod(d,p**(n+2))**(-1)), p**(n+2))))
    sols_old = sols
    
print("The bytes for all roots:")
[print(i, int.to_bytes(s, 500, 'big').lstrip(b"\x00"), end="\n\n") for i,s in enumerate(sols)]

Save it, then run it

┌──(bl4ck4non㉿bl4ck4non)-[~/Downloads/CTF/cyberstarter_ctf/crypto]
└─$ python abeg.py  
Traceback (most recent call last):
  File "/home/bl4ck4non/Downloads/CTF/cyberstarter_ctf/crypto/abeg.py", line 1, in <module>
    from sage.all import *
ModuleNotFoundError: No module named 'sage'

As you can see we got a ModuleNotFoundError which says No module named sage. Well, installing sage from my end was a drag. I went on to do a little research and I found this webpage

image

I definitely can run my script here without any No module named sage error.

Pasting our script to the web browser and running it

image

cool, we got our flag💆

FLAG:- DoHCTF{univariate_polynomial_ring_go_brrr}

Osint

Rogue (151 points)


image

So task is to look for a guy whose name is Mustapha.

What information were we provided with?

  1. Third Name which is Mustapha
  2. A phone number +2348109439442

I tried lots of stuffs, downloaded lots of osint tools and still didn’t get anywhere😞. Not until I thought of PalmPay😂, and this is because PalmPay do use the phone number of their clients as their account numbers. In this case the account number will be 8109439442. Lets try sending money to this account number, if we are lucky we’ll see his full name there.

image

Well Well Well, We found a name Adebayo Ekeh, if you recall they provided us with a third name Mustapha. Now, lets go over to LinkedIn to look for our rogue hacker.

fullname: Adebayo Mustapha Ekeh

image

cool we found our rogue hacker😎. Lets decode the base64 code

command:echo RG9IQ1RGe3RoYXRfd2FzX2Vhc3lfcmlnaHQ/X3JpZ2h0P30K | base64 --d

image

We found our flag

FLAG:- DoHCTF{that_was_easy_right?_right?}

BlockChain

Ask The Block (96 points)


image

I really don’t know much about Web3, so I used chatgpt for this chall. When I asked chatgpt what Goerli means and how I can identify the blocks, I got this response

Here are the steps you can follow:

  1. Go to a blockchain explorer website such as Etherscan or Blockchair.
  2. Search for the Goerli testnet.
  3. Look for the block explorer or block search function.
  4. Enter the block number that you want to check.
  5. Look for the list of transactions in that block.
  6. Check if there is at least one transaction with a non-zero value.

Doing further research I found this site.

image image

change the show rows to 100, this made the search faster. Also, we’ll be starting from the last transactions

image

when the Txn has the value 1 we are going to take note of that block. If you recall the task description was to get First block on Goerli with non-zero transaction.

After lots of clicking, I eventually found one

image

cool, we got our flag already😎

FLAG:- DoHCTF{5644}



Back To Home