# URCHINSEC - SEMI-FINALS OPENING CHALLENGE 2023
First of all the semi-finals was kinda off, I am pretty sure the participants hated this semi-finals. Since for this challenge they are provided with a file which is encrypted and they are required to decrypt it and fetch the flag :)
Now back to it! The description is as follows:

**DESCRIPTION**
```
Can you decrypt the secret that is hidden within this file! it's said there are two types of encryptions used! starting with XOR where we identified the key starts with "urchinsec" then "@" but we do not know the variation of the year that follows! Then we couldn't understand the type of encryption used, but it's said there is a seed , the seed was found to be : "1668176228"
```
There were also two hints provided and these were,
**HINT 1**
```
THE SEED WAS USED TO GENERATE THE IV AND THE KEY FOR ENCRYPTION
```
**HINT 2**
```
THE IV IS 16 BYTES AND THE KEY IS 32 BYTES
```
## XOR DECRYPTION
From the description, the first type of encryption done was XoR, provided with a partial key : `urchinsec@` which ended with a year. First thing first! We bruteforce the year to bruteforce the *.enc file. I wrote a simple script for this job!
`xor_bruter.go`
```go=
// pewpew by @tahaafarooq
package main
import (
"fmt"
"io/ioutil"
)
func decryptFile(filePath string, key string) []byte {
encryptedData, err := ioutil.ReadFile(filePath)
if err != nil {
fmt.Println("Failed to read the file:", err)
return nil
}
decryptedData := make([]byte, len(encryptedData))
for i := 0; i < len(encryptedData); i++ {
decryptedByte := encryptedData[i] ^ key[i%len(key)]
decryptedData[i] = decryptedByte
}
return decryptedData
}
func main() {
keyStart := "urchinsec@"
encryptedFilePath := "SEMI_FINALS_URCHIN.enc"
for year := 1900; year <= 2000; year++ {
key := keyStart + fmt.Sprint(year)
decryptedData := decryptFile(encryptedFilePath, key)
fmt.Printf("%d: %s\n", year, decryptedData)
}
}
```
Run the program and pipe it to print the output to a file, so as it's easier to review:
```shell
┌──(kali㉿kali)-[~/Desktop/urchinsec/ctf/semi-finals]
└─$ go run xor_bruter.go > output_data.txt
```

Now that the file is successfuly decrypted. Let's move forward to the JUICY PART!
## AES DECRYPTION
In the description we are provided with a seed. Before we get started familiarize your self with the concept of Initialization Vectors.
**REFERENCES**
1. https://en.wikipedia.org/wiki/Initialization_vector
2. https://www.ietf.org/rfc/rfc3394.txt
3. https://crypto.stackexchange.com/questions/3965/what-is-the-main-difference-between-a-key-an-iv-and-a-nonce
Let's get rocking! The concept of this part is actually from the machine "CODER" which is an insane rated machine from HTB, I got this while solving it and so I figured why not just make a challenge with it >_< pretty cool right!
The seed provided is : `1668176228`
Writing a cool script to generate the IV and Key from the seed in C#:
```csharp=
using System;
using System.IO;
int value = 1668176228;
Random random = new Random(value);
byte[] array = new byte[16];
random.NextBytes(array);
byte[] array2 = new byte[32];
random.NextBytes(array2);
Console.WriteLine(BitConverter.ToString(array2));
Console.WriteLine(BitConverter.ToString(array));
Console.WriteLine(value);
```
The output should be something like this:
```shell=
43-A7-43-C7-39-0F-42-E5-0A-E2-51-29-75-4D-1B-E0-1B-9F-E0-D6-D0-AF-CF-67-2B-80-0F-93-BB-EB-6D-48
F8-E3-B0-E2-9B-52-5C-EF-B4-B4-2A-93-5F-A6-E2-19
1668176228
```
Where the first is the Key , the second is the IV, and the third is our seed. *Remove the "-"*
## Getting The Flag!
In the list of outputs.txt which has the output of the year and the decrypted value from xor, we can bruteforce each one of the values and try to decrypt them with AES using the IV and Key that we now have and we will get that the key "urchinsec@1970" works great! You can write a script or use cyberchef! It's your choice and my final script for decryption is as follows:
```go=
// pewpew by @tahaafarooq
package main
import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
func decryptAES(ciphertext []byte, key []byte, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
mode := cipher.NewCBCDecrypter(block, iv)
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
padding := int(plaintext[len(plaintext)-1])
if padding > 0 && padding <= aes.BlockSize {
plaintext = plaintext[:len(plaintext)-padding]
}
return plaintext, nil
}
func main() {
ciphertextHex := "f68a3f1bad4c00120fe4a8d9455cef367f3c6197221ebe895897057fe4aae448c773e67f08b153743d3029ff25e18e71"
keyHex := "43A743C7390F42E50AE25129754D1BE01B9FE0D6D0AFCF672B800F93BBEB6D48"
ivHex := "F8E3B0E29B525CEFB4B42A935FA6E219"
ciphertext, err := hex.DecodeString(ciphertextHex)
if err != nil {
fmt.Println("Failed to decode ciphertext:", err)
return
}
key, err := hex.DecodeString(keyHex)
if err != nil {
fmt.Println("Failed to decode key:", err)
return
}
iv, err := hex.DecodeString(ivHex)
if err != nil {
fmt.Println("Failed to decode IV:", err)
return
}
plaintext, err := decryptAES(ciphertext, key, iv)
if err != nil {
fmt.Println("AES decryption error:", err)
return
}
fmt.Println("Decrypted plaintext:", string(plaintext))
}
```
Running this should provide us with the following output:
```shell
┌──(kali㉿kali)-[~/Desktop/urchinsec/ctf/semi-finals]
└─$ go run decryptor.go
Decrypted plaintext: urchinsec{0_x_0_r0ck3tz4M_P3W_TEN4NT_ZeR0_OK}
```
The Flag is : **urchinsec{0_x_0_r0ck3tz4M_P3W_TEN4NT_ZeR0_OK}**
---
<div style="width:100%;height:0;padding-bottom:75%;position:relative;"><iframe src="https://giphy.com/embed/Mfrua8zpQ3Qe4" width="100%" height="100%" style="position:absolute" frameBorder="0" class="giphy-embed" allowFullScreen></iframe></div>
Twitter : https://twitter.com/urchinsec_
Author : https://twitter.com/tahaafarooq