DawgCTF 2023 Writeup

この大会は2023/4/22 2:00(JST)~2023/4/24 2:00(JST)に開催されました。
今回もチームで参戦。結果は4850点で409チーム中11位でした。
自分で解けた問題をWriteupとして書いておきます。

Oh, Deer (Misc 200)

25個のファイルはシカの写真になっている。雄雌が関係あるようなので0.jpgから順に左右の雄雌を書き出す。

 0.jpg: メス、オス
 1.jpg: オス、メス
 2.jpg: オス、メス
 3.jpg: オス、オス
 4.jpg: オス、メス
 5.jpg: オス、メス
 6.jpg: メス、メス
 7.jpg: オス、メス
 8.jpg: メス、オス、メス
 9.jpg: メス、メス
10.jpg: オス、メス
11.jpg: メス、メス
12.jpg: メス、オス
13.jpg: オス、メス
14.jpg: オス、メス
15.jpg: メス、メス
16.jpg: オス、オス
17.jpg: メス、メス
18.jpg: オス、メス
19.jpg: メス、メス
20.jpg: メス、オス
21.jpg: メス、メス
22.jpg: オス、メス
23.jpg: メス、メス
24.jpg: オス、メス

ヒントを見ると、Bacon's cipherが関係ありそう。メスをA、オスをBとして暗号を考える。

ABBABABBBABAAABAABAAABAAAABBABAAABBAABAAAABAABAAABA

https://www.dcode.fr/bacon-cipherで復号する。ただし、暗号文は5の倍数の長さになるはずで、1文字はみ出しているので、末尾を削る。

暗号文:ABBABABBBABAAABAABAAABAAAABBABAAABBAABAAAABAABAAAB

復号結果は以下の通り。

NOREINDEER
DawgCTF{NOREINDEER}

These Names (Fwn 175)

LDAPの検索を実施する必要がある。JXplorerで以下の情報でLDAP接続する。

ホスト:130.85.56.42
ポート:4389
ベースDN:dc=initech,dc=com
セキュリティ
 Level   :User + Password
 User DN  :cn=guest,dc=initech,dc=com
 パスワード:guest

問題文にあるEngineering部門のGeorgeを探すために、usersのengineering配下のユーザを探す。uidからgivenNameがあまり紐付かないが、頭文字は一致しているようなので、uidが"g"から始まるユーザを探すと、givenNameが"George"となっているものが見つかった。

secretemployeeinformationに以下が設定されている。

RGF3Z0NURntpX2FpbnRfbm9fbGlnaHR3ZWlnaHR9

base64デコードする。

$ echo RGF3Z0NURntpX2FpbnRfbm9fbGlnaHR3ZWlnaHR9 | base64 -d
DawgCTF{i_aint_no_lightweight}
DawgCTF{i_aint_no_lightweight}

Celestial Caper II (Fwn 200)

天体の画像が添付されているので、その名前を答える問題。画像検索すると、すぐに天体の名前が見つかる。

Sh2-308
DawgCTF{Sh2-308}

Binary Bomb Phase 1 (Binary Bomb 50)

Ghidraでデコンパイルする。

undefined8 phase1(char *param_1,size_t param_2)

{
  int iVar1;
  size_t sVar2;
  
  iVar1 = strncmp(param_1,"BabYs_F1rS7_RE",param_2);
  if ((iVar1 == 0) && (sVar2 = strlen("BabYs_F1rS7_RE"), param_2 == sVar2)) {
    return 0;
  }
  return 1;
}

round 1は以下を入力すればよい。

BabYs_F1rS7_RE
$ ./dawg_bbomb 
Welcome to the DawgCTF Binary Bomb!
Type HELP for help.
Starting off with small strings...
Enter round 1 input: BabYs_F1rS7_RE
You did it!!
Flag: DawgCTF{BabYs_F1rS7_RE}
DawgCTF{BabYs_F1rS7_RE}

Binary Bomb Phase 2 (Binary Bomb 75)

Ghidraでデコンパイルする。

undefined8 phase2(char *param_1,ulong param_2)

{
  int iVar1;
  size_t sVar2;
  int local_14;
  
  for (local_14 = 0; (ulong)(long)local_14 < param_2; local_14 = local_14 + 1) {
    param_1[local_14] = param_1[local_14] ^ 9;
  }
  iVar1 = strncmp(param_1,"]a=gbVPf\\VO9{VA:ey8gn",param_2);
  if ((iVar1 == 0) && (sVar2 = strlen("]a=gbVPf\\VO9{VA:ey8gn"), param_2 == sVar2)) {
    return 0;
  }
  return 1;
}

round 2は以下の条件を満たす文字列を入力すればよい。

"]a=gbVPf\\VO9{VA:ey8gn"と9のXOR
>>> s = b"]a=gbVPf\\VO9{VA:ey8gn"
>>> ''.join([chr(c ^ 9) for c in s])
'Th4nk_YoU_F0r_H3lp1ng'
$ ./dawg_bbomb 
Welcome to the DawgCTF Binary Bomb!
Type HELP for help.
Starting off with small strings...
Enter round 1 input: SKIP
Skipping phase 1...

Can you help me? I lost my key and can't read my string
Enter round 2 input: Th4nk_YoU_F0r_H3lp1ng
You did it!!
Flag: DawgCTF{Th4nk_YoU_F0r_H3lp1ng}
DawgCTF{Th4nk_YoU_F0r_H3lp1ng}

Binary Bomb Phase 3 (Binary Bomb 100)

Ghidraでデコンパイルする。

undefined8 phase3(char *param_1,ulong param_2)

{
  int iVar1;
  size_t sVar2;
  int local_1c;
  
  for (local_1c = 0; (ulong)(long)local_1c < param_2; local_1c = local_1c + 1) {
    func3_2(param_1 + local_1c,0x16);
    func3_1(param_1 + local_1c);
    func3_2(param_1 + local_1c,0x2d);
    func3_1(param_1 + local_1c);
    func3_2(param_1 + local_1c,0x21);
  }
  iVar1 = strncmp(param_1,"siDgabDzXZa]XsibaabgMXGa]XlpDgaOgz",param_2);
  if ((iVar1 != 0) && (sVar2 = strlen("siDgabDzXZa]XsibaabgMXGa]XlpDgaOgz"), param_2 != sVar2)) {
    return 1;
  }
  return 0;
}

byte * func3_1(byte *param_1)

{
  char cVar1;
  
  if ((0x40 < *param_1) && (*param_1 < 0x5b)) {
    *param_1 = *param_1 - 0xd;
    if (*param_1 < 0x41) {
      cVar1 = '\x1a';
    }
    else {
      cVar1 = '\0';
    }
    *param_1 = *param_1 + cVar1;
  }
  if ((0x60 < *param_1) && (*param_1 < 0x7b)) {
    *param_1 = *param_1 - 0xd;
    if (*param_1 < 0x61) {
      cVar1 = '\x1a';
    }
    else {
      cVar1 = '\0';
    }
    *param_1 = *param_1 + cVar1;
  }
  return param_1;
}

byte * func3_2(byte *param_1,char param_2)

{
  char cVar1;
  
  if ((0x20 < *param_1) && (*param_1 < 0x7f)) {
    *param_1 = param_2 + *param_1;
    if (*param_1 < 0x7f) {
      cVar1 = '\0';
    }
    else {
      cVar1 = '^';
    }
    *param_1 = *param_1 - cVar1;
  }
  return param_1;
}

func3_1関数はrot13、func3_2関数はASCII characters 33 through 126のシーザー暗号。
round 3は、各文字についてfunc3_1, func3_2の処理をして、以下の文字列になるものを逆算する。

siDgabDzXZa]XsibaabgMXGa]XlpDgaOgz
#!/usr/bin/env python3
def func3_1(c):
    if 0x40 < c and c < 0x5b:
        c = c - 0xd
        if c < 0x41:
            c = c + 0x1a
    if 0x60 < c and c < 0x7b:
        c = c - 0xd
        if c < 0x61:
            c = c + 0x1a
    return c

def rev_func3_2(c, n):
    if 0x20 < c and c < 0x7f:
        c = c - n
        if c < 0x21:
            c += 94
    return c

enc = b'siDgabDzXZa]XsibaabgMXGa]XlpDgaOgz'

flag = ''
for c in enc:
    c = rev_func3_2(c, 0x21)
    c = func3_1(c)
    c = rev_func3_2(c, 0x2d)
    c = func3_1(c)
    c = rev_func3_2(c, 0x16)
    flag += chr(c)
print(flag)

逆算した結果は以下の通り。

Sp1nNi1g_aNd_SpiNNinG_4Nd_sP1nNIng
$ ./dawg_bbomb 
Welcome to the DawgCTF Binary Bomb!
Type HELP for help.
Starting off with small strings...
Enter round 1 input: SKIP
Skipping phase 1...

Can you help me? I lost my key and can't read my string
Enter round 2 input: SKIP
Skipping phase 2...

I've been spun around so much... my head kinda hurts now :/
Enter round 3 input: Sp1nNi1g_aNd_SpiNNinG_4Nd_sP1nNIng
You did it!!
Flag: DawgCTF{Sp1nNi1g_aNd_SpiNNinG_4Nd_sP1nNIng}
DawgCTF{Sp1nNi1g_aNd_SpiNNinG_4Nd_sP1nNIng}

Binary Bomb Phase 4 (Binary Bomb 125)

Ghidraでデコンパイルする。

bool phase4(long param_1,ulong param_2)

{
  size_t sVar1;
  size_t sVar2;
  bool bVar3;
  int local_2c;
  
  if ((*(char *)(param_1 + (param_2 - 1 >> 1)) == 's') ||
     (*(char *)(param_1 + (param_2 - 1 >> 1) + 1) == '7')) {
    for (local_2c = 0; (ulong)(long)local_2c < (param_2 >> 1) - 2; local_2c = local_2c + 2) {
      if ((*(char *)(param_1 + local_2c) != (&DAT_0010522b)[local_2c]) ||
         (*(char *)(param_1 + (param_2 - (long)local_2c) + -1) != "El4Sm0C1GGI"[local_2c])) {
        return true;
      }
      if ((*(char *)(param_1 + (long)local_2c + 1) != (&DAT_00105238)[local_2c]) ||
         (*(char *)(param_1 + (param_2 - (long)local_2c) + -2) != "repc0p_nn_r"[local_2c])) {
        return true;
      }
    }
    sVar1 = strlen("TEl4Sm0C1GGI");
    sVar2 = strlen("3repc0p_nn_r");
    bVar3 = param_2 != sVar2 + sVar1 + 2;
  }
  else {
    bVar3 = true;
  }
  return bVar3;
}

文字列の真ん中あたりに"s7"が来る。local_2cが0の場合から順に考える。

s[0]  = "TEl4Sm0C1GGI"[0] = "T"
s[-1] = "El4Sm0C1GGI"[0] = "E"
s[1]  = "3repc0p_nn_r"[0] = "3"
s[-2] = "repc0p_nn_r"[0] = "r"
s[2]  = "TEl4Sm0C1GGI"[2] = "l"
s[-3] = "El4Sm0C1GGI"[2] = "4"
s[3]  = "3repc0p_nn_r"[2] = "e"
s[-4] = "repc0p_nn_r"[2] = "p"
          :

このことから該当する位置に文字を埋めていき、フラグを求める。

#!/usr/bin/env python3
s1 = 'TEl4Sm0C1GGI'
s2 = '3repc0p_nn_r'

flag1 = ''
flag2 = ''
for i in range(0, len(s1), 2):
    flag1 += s1[i]
    flag2 = s1[i+1] + flag2
    flag1 += s2[i]
    flag2 = s2[i+1] + flag2

flag = flag1 + 's7' + flag2
print(flag)

実行結果は以下の通り。

T3leSc0p1nG_s7rInG_C0mp4rE
$ ./dawg_bbomb 
Welcome to the DawgCTF Binary Bomb!
Type HELP for help.
Starting off with small strings...
Enter round 1 input: SKIP
Skipping phase 1...

Can you help me? I lost my key and can't read my string
Enter round 2 input: SKIP
Skipping phase 2...

I've been spun around so much... my head kinda hurts now :/
Enter round 3 input: SKIP
Skipping phase 3...

I spy with my little eye... a flag!
Enter round 4 input: T3leSc0p1nG_s7rInG_C0mp4rE
Defused phase 4
Flag: DawgCTF{T3leSc0p1nG_s7rInG_C0mp4rE}
DawgCTF{T3leSc0p1nG_s7rInG_C0mp4rE}

Binary Bomb Phase 5 (Binary Bomb 150)

Ghidraでデコンパイルする。

undefined8 phase5(char *param_1,ulong param_2)

{
  int iVar1;
  undefined8 uVar2;
  size_t sVar3;
  long in_FS_OFFSET;
  int local_40;
  int local_3c;
  undefined8 local_38;
  undefined3 local_30;
  undefined5 uStack_2d;
  undefined3 uStack_28;
  undefined8 local_25;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_38 = 0x4c1c1d3a644e3856;
  local_30 = 0x731c7d;
  uStack_2d = 0x4e7a161679;
  uStack_28 = 0x132c2d;
  local_25 = 0xf234c53260b0d3d;
  if (param_2 < 2) {
    uVar2 = 1;
  }
  else {
    for (local_40 = 0; (ulong)(long)local_40 < param_2 - 1; local_40 = local_40 + 1) {
      param_1[local_40] = param_1[local_40] ^ param_1[(long)local_40 + 1];
      param_1[local_40] = param_1[local_40] ^ 0x11;
    }
    param_1[param_2 - 1] = param_1[param_2 - 1] ^ 0x11;
    for (local_3c = 0; (ulong)(long)local_3c < param_2 >> 1; local_3c = local_3c + 1) {
      param_1[local_3c] = param_1[local_3c] ^ param_1[(param_2 - (long)local_3c) + -1];
      param_1[(param_2 - (long)local_3c) + -1] =
           param_1[(param_2 - (long)local_3c) + -1] ^ param_1[local_3c];
      param_1[local_3c] = param_1[local_3c] ^ param_1[(param_2 - (long)local_3c) + -1];
    }
    iVar1 = strncmp(param_1,(char *)&local_38,param_2);
    if (iVar1 == 0) {
      sVar3 = strlen((char *)&local_38);
      if (param_2 == sVar3) {
        uVar2 = 0;
        goto LAB_00102cf6;
      }
    }
    uVar2 = 1;
  }
LAB_00102cf6:
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar2;
}

以下の処理をして比較している。

・フラグの長さ(=n)-1だけ以下繰り返し
 ・s[i] = s[i] ^ s[i+1]
 ・s[i] = s[i] ^ 0x11
・s[n-1] = s[n-1] ^ 0x11
・フラグの長さの半分だけ以下繰り返し
 ・s[i] = s[i] ^ s[n-i-1]
 ・s[n-i-1] = s[n-i-1] ^ s[i]
 ・s[i] = s[i] ^ s[n-i-1]

この処理の結果がlocal_38以下のデータになるよう逆算する。

#!/usr/bin/env python3
enc = (0x4c1c1d3a644e3856).to_bytes(8, 'little')
enc += (0x731c7d).to_bytes(3, 'little')
enc += (0x4e7a161679).to_bytes(5, 'little')
enc += (0x132c2d).to_bytes(3, 'little')
enc += (0xf234c53260b0d3d).to_bytes(8, 'little')

s = list(enc)

n = len(s)
for i in range((n >> 1) - 1, -1, -1):
    s[i] = s[i] ^ s[n - i - 1]
    s[n - i - 1] = s[n - i - 1] ^ s[i]
    s[i] = s[i] ^ s[n - i - 1]
s[n - 1] = s[n - 1] ^ 0x11
for i in range(n - 2, -1, -1):
    s[i] = s[i] ^ 0x11
    s[i] = s[i] ^ s[i+1]

flag = ''
for c in s:
    flag += chr(c)
print(flag)

逆算結果は以下の通り。

A_m0rE_ComPl3X_X0R_3ncoD1nG
DawgCTF{A_m0rE_ComPl3X_X0R_3ncoD1nG}

DM the bot! (Reverse Engineering 100)

条件を満たしたときのメッセージを表示すると、base64エンコードされているので、デコードする。デコードした結果、再びbase64エンコードされているので、デコードする。

#!/usr/bin/env python3
from base64 import *

klist = ["TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaX","Bpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFVybmEgY29uZGltZW50dW0gbWF0dGlzIHBlbGxlbnRlc3F1ZSBpZCBuaWJoIHRvcnRvciBpZCBhbGlxdWV0LiBGYW==","NpbGlzaXMgbWFnbmEgZXRpYW0gdGVtcG9yIG9yY2kgZXUH607JkNwW8rNqyEwI0KsHSXavqGb3iXl0PnPvpa72f8=uIFNhcGllbiBldCBsaWd1bGEgdWxsYW1jb3JwZXIgbWFsZXN1YWRhLiBUcmlzdGlxdWUgbnVsbGE","gYWxpcXVldCBlbmltIHRvcnRvciBhdC4gUXVpcyByaXN1cb'kpXpSMY0j53jg-b-WFChVOmcn5r20RktR66SB3_BYwE='yBzZWQgdnVscHV0YXRlIG9kaW8uIFNhZ2l0dGlzIGFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVt","IGFyY3Ugdml0YWUgZWxlbWRGF3Z0NURns1dDR0MWNfMHJfZHluNG0xYz99VudHVtIGN1cmFiaXR1ci4gSGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdCBxdW=","lzcXVlIHNhZ2l0dGlzIHB1cnVzIHNpdCBhbWV0LiBQdXJ1cyBncmF2aWRhIHF1aXMgYmxhbmRpdCB0dXJwaXMgY3Vyc3VzIGluIGhhYyBoYWJpdGFzc2UuIFZvbHV0cGF0IGFjIHRpbmNpZHVudCB2aXRhZSBzZW1wZXIuIFF1YW0gZWxlbWVudHVtIHB1b==","HZpbmFyIGV0aWFtIG5vbiBxdWFtIGxhY3VzLiBBbWV0IHRlbGx1cyBjcmFzIGFkaXBpc2NpbmcgZW5pbSBldSB0dXJwaXMgZWdlc3Rhcy4KCkZldWdpYXQgbmlzbCBwcmV0aXVtIGZ1c2NlIGlkIHZlbGl0IHV0IHRvcnRvciBwcmV0aXVtIHZpdmVycmEuIEVuaW0gZGlhbSB2dWxwdXRhdGUgdXQgcGhhcmV0cmEgc2l0IGFtZ","XQuIEZldWdpYXQgcHJldGl1bSBuaWJoIGlwc3VtIGNvbnNlcXVhdCBuaXNsLiBCaWJlbmR1bSB1dCB0cmlzdGlxdWUgZXQgZWdlc3RhcyBxdWlzIGlwc3VtIHN1c3BlbmRpc3NlIHVsdHJpY2VzLiBWaXZlcnJhIGlwc3VtIG51bmMgYWxpcXVldCBi","aWJlbmR1bSBlbmltIGZhY2lsaXNpcyBncmF2aWRhIG5lcXVlLiBDb25zZWN0ZXR1ciBhZGlwaXNjaW5nIGVsaXQgdXQgYWxpcXVhbSBwdXJ1cyBzaXQgYW1ldCBsdWN0dXMuIEVyYXQgdmVsaXQgc2NlbG","VyaXNxdWUgaW4gZGljdHVtIG5vbiBjb25zZWN0ZXR1ciBhIGVyYXQuIERpYW0gc29sbGljaXR1ZGluIHRlbXBvciBpZCBldSBuaXNsIG51bmMgbWkgaXBzdW0uIFJpc3VzIHF1aXMgdmFyaXVzIHF1YW0gcXVpc3F1ZSBpZCBkaWFtIHZlbCBxdWFtIGV","sZW1lbnR1bS4gUG9zdWVyZSBsb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCBjb25zZWN0ZXR1ci4gVWxsYW1jb3JwZXIgbW9yYmkgdGluY2lkdW50IG9ybmFyZSBtYXNzYS4gUXVhbSBhZGlwaXNjaW5nIHZpdGFlIHByb2luIHNhZ2l0dGlzIG5pc2wgcmhvbmN1cy4gRXUgY29uc2VxdWF0IGFjIGZlbGlzIGRvbmVjIGV0IG9kaW8gcGVsbGVudGVzcX","VlIGRpYW0gdm9sdXRwYXQuIEV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMgbmFzY2V0dXIuIEFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVtIGFyY3Ugdml0YWUuIEluIG51bGxhIHBvc3VlcmUgc29sbGljaXR1ZGluIGFsaXF1YW0u"]
mlist = ["TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaX","Bpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFVybmEgY29uZGltZW50dW0gbWF0dGlzIHBlbGxlbnRlc3F1ZSBpZCBuaWJoIHRvcnRvciBpZCBhbGlxdWV0LiBGYW==","NpbGlzaXMgbWFnbmEgZXRpYW0gdGVtcG9yIG9yY2kgZXUH607Jb'gAAAAABkQfn3TpdZBGFeG4VfZObYKIL3f25CVBupi27swEARiUnK6c6ry6951JgI9lPqbPa3MkJ0Yg5huinb6_SNoTVZp1wdvYiIo3QZd-qb1p-nDsOeX_I='kNwW8rNqyEwI0KsHSXavqGb3iXl0PnPvpa72f8=uIFNhcGllbiBldCBsaWd1bGEgdWxsYW1jb3JwZXIgbWFsZXN1YWRhLiBUcmlzdGlxdWUgbnVsbGE","gYWxpcXVldCBlbmltIHRvcnRvciBhdC4gUXVpcyByaXN1ckpXpSMY0j53jg-b-WFChVOmcn5r20RktR66SB3_BYwE=yBzZWQgdnVscHV0YXRlIG9kaW8uIFNhZ2l0dGlzIGFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVt","IGFyY3Ugdml0YWUgZWxlbWRGF3Z0NURns1dDR0MWNfMHJfZHluNG0xYz99VudHVtIGN1cmFiaXR1ci4gSGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdCBxdW=","lzcXVlIHNhZ2l0dGlzIHB1cnVzIHNpdCBhbWV0LiBQdXJ1cyBncmF2aWRhIHF1aXMgYmxhbmRpdCB0dXJwaXMgY3Vyc3VzIGluIGhhYyBoYWJpdGFzc2UuIFZvbHV0cGF0IGFjIHRpbmNpZHVudCB2aXRhZSBzZW1wZXIuIFF1YW0gZWxlbWVudHVtIHB1b==","HZpbmFyIGV0aWFtIG5vbiBxdWFtIGxhY3VzLiBBbWV0IHRlbGx1cyBjcmFzIGFkaXBpc2NpbmcgZW5pbSBldSB0dXJwaXMgZWdlc3Rhcy4KCkZldWdpYXQgbmlzbCBwcmV0aXVtIGZ1c2NlIGlkIHZlbGl0IHV0IHRvcnRvciBwcmV0aXVtIHZpdmVycmEuIEVuaW0gZGlhbSB2dWxwdXRhdGUgdXQgcGhhcmV0cmEgc2l0IGFtZ","XQuIEZldWdpYXQgcHJldGl1bSBuaWJoIGlwc3VtIGNvbnNlcXVhdCBuaXNsLiBCaWJlbmR1bSB1dCB0cmlzdGlxdWUgZXQgZWdlc3RhcyBxdWlzIGlwc3VtIHN1c3BlbmRpc3NlIHVsdHJpY2VzLiBWaXZlcnJhIGlwc3VtIG51bmMgYWxpcXVldCBi","aWJlbmR1bSBlbmltIGZhY2lsaXNpcyBncmF2aWRhIG5lcXVlLiBDb25zZWN0ZXR1ciBhZGlwaXNjaW5nIGVsaXQgdXQgYWxpcXVhbSBwdXJ1cyBzaXQgYW1ldCBsdWN0dXMuIEVyYXQgdmVsaXQgc2NlbG","VyaXNxdWUgaW4gZGljdHVtIG5vbiBjb25zZWN0ZXR1ciBhIGVyYXQuIERpYW0gc29sbGljaXR1ZGluIHRlbXBvciBpZCBldSBuaXNsIG51bmMgbWkgaXBzdW0uIFJpc3VzIHF1aXMgdmFyaXVzIHF1YW0gcXVpc3F1ZSBpZCBkaWFtIHZlbCBxdWFtIGV","sZW1lbnR1bS4gUG9zdWVyZSBsb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCBjb25zZWN0ZXR1ci4gVWxsYW1jb3JwZXIgbW9yYmkgdGluY2lkdW50IG9ybmFyZSBtYXNzYS4gUXVhbSBhZGlwaXNjaW5nIHZpdGFlIHByb2luIHNhZ2l0dGlzIG5pc2wgcmhvbmN1cy4gRXUgY29uc2VxdWF0IGFjIGZlbGlzIGRvbmVjIGV0IG9kaW8gcGVsbGVudGVzcX","VlIGRpYW0gdm9sdXRwYXQuIEV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMgbmFzY2V0dXIuIEFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVtIGFyY3Ugdml0YWUuIEluIG51bGxhIHBvc3VlcmUgc29sbGljaXR1ZGluIGFsaXF1YW0u"]
blist = ["YzNSbmMyUnlaMlJoWm1kbVJsZEdWMFJFUkVaWFpIZG1Da1pGUmtWSFptUmxaM0puUmtWR1JVZG1aR1ZuY21kemR3cEdSVVpGUjJaa1pXZHlaM04zUmtSRlIwWkhaM05uWkdnS1pXZHlaMFpIVjBaRVJVZEdSMmR6WjJSb1JuTjNSa1JGQ25KblpHVmxSMFpIWjNObmMyVmxSMFpIWjNOblpHaEdjd3BuYzJka2FFVkdSVWRtWkdWbmNrWkdaM05uWkdoeVoyUUtaR1ZuY2taR1ozTm5aR2h5WjJSbFpVZEdSMmRuWkdoeUNtUm9SVVpGUjJaeloyUm9Sbk4zUmtSRlpHZG5kMFpFUlFweVoyUmxaVWRHUjJkelozTmxaVWRHUjJkeloyUm9Sbk1LWjNOblpHaEZSa1ZIWm1SbFozSkdSbWR6WjJSb2NtZGtDbkpuWkdWbFIwWkhaM05uYzJWbFIwWkhaM05uWkdoR2N3cG5jMmRrYUVWR1JVZG1aR1ZuY2taR1ozTm5aR2h5WjJRS1pHVm5ja1pHWjNOblpHaHlaMlJsWlVkR1IyZG5aR2h5Q21Sb1JVWkZSMlp6WjJSb1JuTjNSa1JGWkdkbmQwWkVSUXB5WjJSbFpVZEdSMmR6WjNObFpVZEdSMmR6WjJSb1JuTUtaM05uWkdoRlJrVkhabVJsWjNKR1JtZHpaMlJvY21ka0NtZHpaMlJvY21ka1pXVkhSa2RuYzJka2FFWnpkMFpFUlFweVoyUmxaVWRHUjJkeloyUm9aM05uWkdoR2MzZEdSRVVLY21ka1pXVkhSa2RsWlVkR1IyZHpaMlJvUm5OM1JrUkZDbkpuWkdWbFIwWkhaM05uWkdoRlJrVkhabVJsWjNKR1JncEVZWGRuUTFSR2Uwd3pORkpPWDFRd1gwUXpVRXd3V1gwS2NtZGtaV1ZIUmtkbmMyZGthRVZHUlVkSFJrZG5jMmRrQ25KblpHVmxSMFpIWjNOblpHaEhjMmRrYUVaemQwWkVSUXB5WjJSbFpVZEdSMmR6WjNObFpVZEdSMmR6WjJSb1JuTUtaM05uWkdoRlJrVkhabVJsWjNKR1JtZHpaMlJvY21ka0NtUmxaM0pHUm1keloyUm9jbWRrWldWSFJrZG5aMlJvY2dwa2FFVkdSVWRtYzJka2FFWnpkMFpFUldSblozZEdSRVVLWm1SbFozSkdSbWR6WjJSb2NtZGtaV1ZIUmtkblJVWkZDbVprWldkeVJrWm5jMmRrYUhKblpHVmxhRVp6ZDBaRVJRcHlaMlJsWlVkR1IyZHpaM05sWlVkR1IyZHpaMlJvUm5NS1ozTm5aR2hGUmtWSFptUmxaM0pHUm1keloyUm9jbWRrQ21SbFozSkdSbWR6WjJSb2NtZGtaV1ZIUmtkbloyUm9jZ3BrYUVWR1JVZG1jMmRrYUVaemQwWkVSV1JuWjNkR1JFVUtjbWRrWldWSFJrZG5jMmR6WldWSFJrZG5jMmRrYUVaekNtZHpaMlJvUlVaRlIyWmtaV2R5UmtabmMyZGthSEpuWkFweVoyUmxaVWRHUjJkelozTmxaVWRHUjJkeloyUm9Sbk1LWjNOblpHaEZSa1ZIWm1SbFozSkdSbWR6WjJSb2NtZGtDbVJsWjNKR1JtZHpaMlJvY21ka1pXVkhSa2RuWjJSb2NncGthRVZHUlVkbWMyZGthRVp6ZDBaRVJXUm5aM2RHUkVVS2NtZGtaV1ZIUmtkbmMyZHpaV1ZIUmtkbmMyZGthRVp6Q21keloyUm9SVVpGUjJaa1pXZHlSa1puYzJka2FISm5aQXBrWldkeVJrWm5jMmRrYUhKblpHVmxSMFpIWjJka2FISUtaR2hGUmtWSFpuTm5aR2hHYzNkR1JFVmtaMmQzUmtSRg=="]

msg = blist[ord(mlist[2][12])-70][ord(klist[1][1])-112:]
msg = b64decode(msg)
msg = b64decode(msg).decode()
print(msg)

実行結果は以下の通り。

                :
gsgdhEFEGfdegrFFgsgdhrgd
gsgdhrgdeeGFGgsgdhFswFDE
rgdeeGFGgsgdhgsgdhFswFDE
rgdeeGFGeeGFGgsgdhFswFDE
rgdeeGFGgsgdhEFEGfdegrFF
DawgCTF{L34RN_T0_D3PL0Y}
rgdeeGFGgsgdhEFEGGFGgsgd
rgdeeGFGgsgdhGsgdhFswFDE
rgdeeGFGgsgseeGFGgsgdhFs
gsgdhEFEGfdegrFFgsgdhrgd
degrFFgsgdhrgdeeGFGggdhr
                :

この中にフラグが含まれていた。

DawgCTF{L34RN_T0_D3PL0Y}

DM the bot? (Reverse Engineering 100)

条件を満たしたときのメッセージを表示すると、base64エンコードされているので、デコードする。

#!/usr/bin/env python3
from base64 import *

STRING = 4
START = 22
STOP = 58

msglist = ["TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaX","Bpc2NpbmcgZWxpdCwgc2VkIGRvIGVpdXNtb2QgdGVtcG9yIGluY2lkaWR1bnQgdXQgbGFib3JlIGV0IGRvbG9yZSBtYWduYSBhbGlxdWEuIFVybmEgY29uZGltZW50dW0gbWF0dGlzIHBlbGxlbnRlc3F1ZSBpZCBuaWJoIHRvcnRvciBpZCBhbGlxdWV0LiBGYW==","NpbGlzaXMgbWFnbmEgZXRpYW0gdGVtcG9yIG9yY2kgZXUuIFNhcGllbiBldCBsaWd1bGEgdWxsYW1jb3JwZXIgbWFsZXN1YWRhLiBUcmlzdGlxdWUgbnVsbGE","gYWxpcXVldCBlbmltIHRvcnRvciBhdC4gUXVpcyByaXN1cyBzZWQgdnVscHV0YXRlIG9kaW8uIFNhZ2l0dGlzIGFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVt","IGFyY3Ugdml0YWUgZWxlbWRGF3Z0NURns1dDR0MWNfMHJfZHluNG0xYz99VudHVtIGN1cmFiaXR1ci4gSGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdCBxdW=","lzcXVlIHNhZ2l0dGlzIHB1cnVzIHNpdCBhbWV0LiBQdXJ1cyBncmF2aWRhIHF1aXMgYmxhbmRpdCB0dXJwaXMgY3Vyc3VzIGluIGhhYyBoYWJpdGFzc2UuIFZvbHV0cGF0IGFjIHRpbmNpZHVudCB2aXRhZSBzZW1wZXIuIFF1YW0gZWxlbWVudHVtIHB1b==","HZpbmFyIGV0aWFtIG5vbiBxdWFtIGxhY3VzLiBBbWV0IHRlbGx1cyBjcmFzIGFkaXBpc2NpbmcgZW5pbSBldSB0dXJwaXMgZWdlc3Rhcy4KCkZldWdpYXQgbmlzbCBwcmV0aXVtIGZ1c2NlIGlkIHZlbGl0IHV0IHRvcnRvciBwcmV0aXVtIHZpdmVycmEuIEVuaW0gZGlhbSB2dWxwdXRhdGUgdXQgcGhhcmV0cmEgc2l0IGFtZ","XQuIEZldWdpYXQgcHJldGl1bSBuaWJoIGlwc3VtIGNvbnNlcXVhdCBuaXNsLiBCaWJlbmR1bSB1dCB0cmlzdGlxdWUgZXQgZWdlc3RhcyBxdWlzIGlwc3VtIHN1c3BlbmRpc3NlIHVsdHJpY2VzLiBWaXZlcnJhIGlwc3VtIG51bmMgYWxpcXVldCBi","aWJlbmR1bSBlbmltIGZhY2lsaXNpcyBncmF2aWRhIG5lcXVlLiBDb25zZWN0ZXR1ciBhZGlwaXNjaW5nIGVsaXQgdXQgYWxpcXVhbSBwdXJ1cyBzaXQgYW1ldCBsdWN0dXMuIEVyYXQgdmVsaXQgc2NlbG","VyaXNxdWUgaW4gZGljdHVtIG5vbiBjb25zZWN0ZXR1ciBhIGVyYXQuIERpYW0gc29sbGljaXR1ZGluIHRlbXBvciBpZCBldSBuaXNsIG51bmMgbWkgaXBzdW0uIFJpc3VzIHF1aXMgdmFyaXVzIHF1YW0gcXVpc3F1ZSBpZCBkaWFtIHZlbCBxdWFtIGV","sZW1lbnR1bS4gUG9zdWVyZSBsb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCBjb25zZWN0ZXR1ci4gVWxsYW1jb3JwZXIgbW9yYmkgdGluY2lkdW50IG9ybmFyZSBtYXNzYS4gUXVhbSBhZGlwaXNjaW5nIHZpdGFlIHByb2luIHNhZ2l0dGlzIG5pc2wgcmhvbmN1cy4gRXUgY29uc2VxdWF0IGFjIGZlbGlzIGRvbmVjIGV0IG9kaW8gcGVsbGVudGVzcX","VlIGRpYW0gdm9sdXRwYXQuIEV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMgbmFzY2V0dXIuIEFsaXF1YW0gbWFsZXN1YWRhIGJpYmVuZHVtIGFyY3Ugdml0YWUuIEluIG51bGxhIHBvc3VlcmUgc29sbGljaXR1ZGluIGFsaXF1YW0u"]

msg = msglist[STRING][START:STOP]
msg = b64decode(msg).decode()
print(msg)
DawgCTF{5t4t1c_0r_dyn4m1c?}

Briefcase (Cryptography 50)

画像には以下のように書いてある。

N=253
e=7
C=217

RSA暗号と推測して復号する。
Nを素因数分解すると、以下のようになる。

N = 11 * 23

あとは通常通り復号する。

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

N = 253
e = 7
C = 217
p = 11
q = 23
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(C, d, N)
print(m)

復号結果の数値は以下の通り。

182

指定されたフラグの形式にする。

DawgCTF{thesecretnumberis182}

Celestial Caper (Cryptography 50)

Lunar Alphabetと推測し、https://www.dcode.fr/lunar-alphabet-leandro-katzで復号する。

moonman
DawgCTF{moonman}

Birds! (Cryptography 75)

Birds on a Wire Cipher。https://www.dcode.fr/birds-on-a-wire-cipherで復号する。

ONEINHANDORTWOINBUSH
DawgCTF{oneinhandortwoinbush}

Choo Choo! (Cryptogtaphy 100)

Rail Fence Cipher。https://www.geocachingtoolbox.com/index.php?lang=en&page=railFenceCipherで復号する。レール数10で復号できた。

DawgCTF{1_l1k3_tr41ns_th3y_4r3_5up3r_C0o1!}

Et tu, Bacon? (Cryptography 100)

Bacon's cipherと推測する。11100は存在しないので、0, 1を逆にする。https://www.dcode.fr/bacon-cipherで復号する。

SDRENFOEGAUGNALEHTSINITALUM

このままだと意味がわからないので、逆順にする。

>>> 'SDRENFOEGAUGNALEHTSINITALUM'[::-1]
'MULATINISTHELANGUAGEOFNERDS'
DawgCTF{MULATINISTHELANGUAGEOFNERDS}

Linear Algebra Homework? (Cryptography 100)

画像に以下のように書かれてる。

[ 6 24  1]
[13 16 10]
[20 17 15]

yidethw rmx vpsgiqqgf utwz ecnb

https://www.dcode.fr/hill-cipherで復号する。

chapter six exercises odds only
DawgCTF{chapter_six_exercises_odds_only}

You step away for just ONE minute! (Cryptography 100)

写真に以下のように文字が並んでいる。

wTw13!!5aC{_vs1gDgF30_bn}

インデックスを確認する。

          111111111122222
0123456789012345678901234
wTw13!!5aC{_vs1gDgF30_bn}

モジュラス25で16から順に8マイナスしたものをインデックスとして、文字を並べていけばよい。

#!/usr/bin/env python3
enc = 'wTw13!!5aC{_vs1gDgF30_bn}'

flag = ''
index = 16
for _ in range(len(enc)):
    flag += enc[index]
    index = (index - 8) % 25
print(flag)
DawgCTF{w3_10v3_s!b1!ng5}

Chuck's Code (Cryptography 125)

Chuck Norris Unary Codeというのがあるらしい。https://www.dcode.fr/chuck-norris-codeでデコードする。

DawgCTF{chuck_n0rr1s_p0w3rs!}

Maximum Head Space (Cryptography 150)

動画のことがいつ起こったことなのかを答える問題。内容的にはOSINT問題のようだ。動画の途中の画面を画像検索すると、マックスヘッドルーム事件のことであることがわかる。https://zozozo.jp/rumor/story-116を見てみると、発生日は1987年11月22日であるとわかった。

DawgCTF{11/22/1987}

Thermodynamic Analysis (Cryptography 150)

テキストの15行目までの行の先頭と末尾を結合していくとフラグになる。

#!/usr/bin/env python3
with open('STUDYME.txt', 'rb') as f:
    lines = f.read().splitlines()

flag = b''
for line in lines[:15]:
    flag += bytes([line[0]])
    flag += bytes([line[-1]])

flag = flag[:-1].decode()
print(flag)
DawgCTF{therm0dyn4mic5sucks!}

Bravo Six, Going Dark (Cryptography 200)

動画の途中、Bill cipherの暗号の紙が映る。

https://gravityfalls.fandom.com/f/p/3284249067127257187/r/3284249067127271496を参考にして復号する。

HEISWAT
CHINGY
OU
DawgCTF{HEISWATCHINGYOU}

Bravo Six, Going Dark II (Cryptography 350)

光が点滅している。モールス信号と推測できる。

... -.-. .--. .... .- ... -... .-. . .- 

これをデコードする。

SCPHASBREA
DawgCTF{SCPHASBREA}