CryptixCTF'19 Writeup

この大会は2019/10/12 21:30(JST)~2019/10/13 21:30(JST)に開催されました。
今回もチームで参戦。結果は2595点の満点で275チーム中4位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome gift (Make yourself comfortable 10)

Crypto問題。Base64文字列が与えられている。

$ echo ZmxhZ3t3ZWxjb21lX3RvX2NyeXB0aXhDVEZfYmFzZTY0aXRpc30K | base64 -d
flag{welcome_to_cryptixCTF_base64itis}
flag{welcome_to_cryptixCTF_base64itis}

You made it here! (Make yourself comfortable 10)

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

<!-- Came for the flag? Bingo!
      first part: flag{Pr3tty_ 
-->

リンクされているweb1/style.cssを見ると、コメントにこう書いてある。

/* second part: b4s1c_ */

リンクされているweb1/script.jsを見ると、コメントにこう書いてある。

// last part: 5tuff}

全部結合すると、フラグになる。

flag{Pr3tty_b4s1c_5tuff}

Secret Code (Make yourself comfortable 25)

Rev問題。stringsするだけ。

$ strings secret_code | grep flag
flag{sTring5_To_tH3_R35cU3}
flag{sTring5_To_tH3_R35cU3}

Mixed Up (Moving On 50)

Crypto問題。換字式暗号のようなので、調整しながら、quipqiupで復号する。調整した変換文字は「q=k x=x v=w」。

Cryptography, the use of codes and ciphers to protect secrets, began thousands of years ago. Until recent decades, it has been the story of what might be called classic cryptography ? that is, of methods of encryption that use pen and paper, or perhaps simple mechanical aids. The invention of complex mechanical and electromechanical machines, such as the Enigma rotor machine, provided more sophisticated and efficient means of encryption; and the subsequent introduction of electronics and computing has allowed elaborate schemes of still greater complexity, most of which are entirely unsuited to pen and paper. The development of cryptography has been paralleled by the development of cryptanalysis ? the breaking of codes and ciphers. The discovery and application, early on, of frequency analysisflag{freqanalysisworkxzz} to the reading of encrypted communications has, on occasion, altered the course of history. Thus the Zimmermann Telegram triggered the United States' entry into World War I; and Allied reading of Nazi Germany's ciphers shortened World War II, in some evaluations by as much as two years. Earlier, secure cryptography was largely the preserve of governments. Two events have since brought it squarely into the public domain: the creation of a public encryption standard{DES}, and the invention of public-key cryptography.

文中にフラグが入っている。

flag{freqanalysisworkxzz}

Where to run this (Moving On 75)

Rev問題。添付ファイルの実体はapkファイル。Bytecode Viewerでデコンパイルする。

public abstract class AppComputActivity extends AppCompatActivity {
   int a = 57;
   int b = 29;
   int[] key = new int[]{4817, 6356, 3107, 6014, 2993, 6584, 5444, 2195, 5444, 4817, 6527, 6014, 3050};

   int obf(String var1) {
      for(int var2 = 0; var2 < var1.length(); ++var2) {
         char var3 = var1.charAt(var2);
         if (this.a * var3 + this.b != this.key[var2]) {
            return 0;
         }
      }

      return 1;
   }
}

これを元に逆算して、return 1となるvar1を求める。

a = 57
b = 29
key = [4817, 6356, 3107, 6014, 2993, 6584, 5444, 2195, 5444, 4817, 6527, 6014, 3050]

secret = ''
for k in key:
    code = (k - 29) / 57
    secret += chr(code)

flag = 'flag{%s}' % secret
print flag
flag{To6i4s_&_Tri5}

Infiltrate (Moving On 75)

Web問題。SQLインジェクションを試す。
以下を入力し、ログインすると、フラグが表示された。

Username: ' or 1=1 #
flag{s1mpl3_5QL_1nj3cti0n}

The Spy (Still Manageable 100)

Crypto問題。恐らくRSA暗号。factordbでnらしきものを素因数分解する。

3073416132828889709313918053975078361304902307 = 13558774610046711780701 * 226673591177742970257407

eは通常の65537。cが1217323181436745647195685030986548015017805440として復号する。

from Crypto.Util.number import *

n = 3073416132828889709313918053975078361304902307
e = 65537
p = 13558774610046711780701
q = 226673591177742970257407
c = 1217323181436745647195685030986548015017805440

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

flag = long_to_bytes(m)
print flag
flag{w3ak_R5A_bad}

Weird machine (Still Manageable 150)

Crypto問題。seed値は1以上10000以下で、それによりXORのkeyが決まる。ブルートフォースで逆算して復号する。

import random
import string

alphanum = string.ascii_letters + string.digits

def random_string(rand_seed, l):
    random.seed(rand_seed)
    rand_string = ''
    for i in range(l):
        rand_string += alphanum[random.randint(1, 1000) % len(alphanum)]
    return rand_string

def decrpyt(random_str, bin_message):
    decrpyted = ''
    for i in range(len(bin_message) // 8):
        k = int(bin_message[i*8:i*8+8], 2) ^ ord(random_str[i])
        decrpyted += chr(k)
    return decrpyted

with open('seq.txt', 'r') as f:
    enc = f.read()

for rand in range(1, 10001):
    rand_string = random_string(rand, len(enc) // 8)
    flag = decrpyt(rand_string, enc)
    if flag.startswith('flag{'):
        break

print(flag)
flag{R4nd0m_s33d_s4v3d_y0u}

Let's climb the ladder (Welcome to the real deal 250)

Rev問題。Ghidraでデコンパイルする。

void check(char *pcParm1)

{
  size_t sVar1;
  
  sVar1 = strlen(pcParm1);
  if ((int)sVar1 == 0x15) {
    if ((int)pcParm1[7] == (uint)(pcParm1[0x10] == 0)) {
      fail();
    }
    else {
      if ((int)pcParm1[1] == (uint)(pcParm1[0xb] == 0)) {
        fail();
      }
      else {
        if ((int)pcParm1[2] == (uint)(pcParm1[8] == 0)) {
          fail();
        }
        else {
          if ((int)pcParm1[8] == (uint)(pcParm1[0x12] == 0)) {
            fail();
          }
          else {
            if ((int)pcParm1[3] == (uint)(pcParm1[0x11] == 0)) {
              fail();
            }
            else {
              if ((int)pcParm1[5] == (uint)(pcParm1[0x14] == 0)) {
                fail();
              }
              else {
                if ((int)pcParm1[9] == (uint)(pcParm1[10] == 0)) {
                  fail();
                }
                else {
                  if ((int)pcParm1[0xc] == (uint)(pcParm1[0x13] == 0)) {
                    fail();
                  }
                  else {
                    if (*pcParm1 == 'r') {
                      if ((int)pcParm1[2] - (int)pcParm1[1] == 1) {
                        if ((int)pcParm1[10] - (int)pcParm1[8] == 1) {
                          if (pcParm1[2] == '4') {
                            if ((int)*pcParm1 + (int)pcParm1[3] == 0xd6) {
                              if ((int)pcParm1[4] - (int)pcParm1[3] == 5) {
                                if ((int)pcParm1[6] + (int)pcParm1[5] == 0xd5) {
                                  if ((int)pcParm1[5] - (int)pcParm1[6] == 7) {
                                    if ((int)pcParm1[7] - (int)pcParm1[8] == 0x2b) {
                                      if ((int)pcParm1[0xd] + (int)pcParm1[0xc] == 0xcf) {
                                        if ((int)pcParm1[0xd] * (int)pcParm1[0xc] == 0x29ba) {
                                          if ((int)pcParm1[0xf] - (int)pcParm1[0xe] == 0xd) {
                                            if ((int)pcParm1[0xf] - (int)*pcParm1 == 7) {
                                              success();
                                            }
                                            else {
                                              fail();
                                            }
                                          }
                                          else {
                                            fail();
                                          }
                                        }
                                        else {
                                          fail();
                                        }
                                      }
                                      else {
                                        fail();
                                      }
                                    }
                                    else {
                                      fail();
                                    }
                                  }
                                  else {
                                    fail();
                                  }
                                }
                                else {
                                  fail();
                                }
                              }
                              else {
                                fail();
                              }
                            }
                            else {
                              fail();
                            }
                          }
                          else {
                            fail();
                          }
                        }
                        else {
                          fail();
                        }
                      }
                      else {
                        fail();
                      }
                    }
                    else {
                      fail();
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  else {
    fail();
  }
  return;
}

条件を確認する。

・長さは21(0番目~20番目)
・7番目と16番目は同じ
・1番目と11番目は同じ
・2番目と8番目は同じ
・8番目と18番目は同じ
・3番目と17番目は同じ
・5番目と20番目は同じ
・9番目と10番目は同じ
・12番目と19番目は同じ
・0番目は'r'
・2番目-1番目=1
・10番目-8番目=1
・2番目は'4'
・0番目+3番目=0xd6
・4番目-3番目=5
・6番目+5番目=0xd5
・5番目-6番目=7
・7番目-8番目=0x2b
・13番目+12番目=0xcf
・13番目*12番目=0x29ba
・15番目-14番目=13
・15番目-0番目=7

条件を満たすよう位置を考えながら、文字を埋めていく。

          11111111112
012345678901234567890
r34ding_4553mbly_d4mn
flag{r34ding_4553mbly_d4mn}

Your ID please (Welcome to the real deal 300)

Web問題。添付されているコードを読むと、IDは"SuperUser1337"であればよいことがわかる。
あとはパスワードだが、phpの比較がstrcmpで"==0"になっているので、配列を使って条件を満たすようにする。

$ curl -X POST -d 'ID=SuperUser1337&pwd[]=a' https://cryptixctf.com/web4/login.php
<br />
<b>Warning</b>:  strcmp() expects parameter 2 to be string, array given in <b>/app/login.php</b> on line <b>7</b><br />
Hey, you are in!  SuperUser1337<br>Your Flag: flag{Why_Juggl3_th3_Typ5}
flag{Why_Juggl3_th3_Typ5}

Hidden deep within (Finally... 400)

Stegano問題。添付されているpngファイルをStegsolveで開き、Data ExtractでRGBのLSBにチェックを入れると、PNGが抽出できる。
f:id:satou-y:20191019060606p:plain
抽出した画像にはこう書いてある。

flag{Haha_fake_flag}
nice try through!

まだ先がありそう。抽出したPNGファイルをStegsolveで開き、Data ExtractでRGBのLSBにチェックを入れると、フラグが見えた。
f:id:satou-y:20191019060725p:plain

flag{st3g4n0gr4phy_i5_34sy}