SharkyCTF Writeup

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

Welcome (Misc 10)

Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。

shkCTF{N0W_G3T_TH3_5H4RKY_68caef0fd1aa55bad4d34e556198e8bf}

z 3 r o b o t w a v e s (Reverse200)

Ghidraでデコンパイルする。

undefined8 check_flag(byte *pbParm1)

{
  undefined8 uVar1;
  byte bVar2;
  
  if (((((((((((pbParm1[0x14] ^ 0x2b) == pbParm1[7]) &&
             ((int)(char)pbParm1[0x15] - (int)(char)pbParm1[3] == -0x14)) &&
            ((char)pbParm1[2] >> 6 == 0)) &&
           ((pbParm1[0xd] == 0x74 && (((int)(char)pbParm1[0xb] & 0x3fffffffU) == 0x5f)))) &&
          ((bVar2 = (byte)((char)pbParm1[0x11] >> 7) >> 5,
           (int)(char)pbParm1[7] >> ((pbParm1[0x11] + bVar2 & 7) - bVar2 & 0x1f) == 5 &&
           (((pbParm1[6] ^ 0x53) == pbParm1[0xe] && (pbParm1[8] == 0x7a)))))) &&
         ((bVar2 = (byte)((char)pbParm1[9] >> 7) >> 5,
          (int)(char)pbParm1[5] << ((pbParm1[9] + bVar2 & 7) - bVar2 & 0x1f) == 0x188 &&
          (((((int)(char)pbParm1[0x10] - (int)(char)pbParm1[7] == 0x14 &&
             (bVar2 = (byte)((char)pbParm1[0x17] >> 7) >> 5,
             (int)(char)pbParm1[7] << ((pbParm1[0x17] + bVar2 & 7) - bVar2 & 0x1f) == 0xbe)) &&
            ((int)(char)pbParm1[2] - (int)(char)pbParm1[7] == -0x2b)) &&
           (((pbParm1[0x15] == 0x5f && ((pbParm1[2] ^ 0x47) == pbParm1[3])) &&
            ((*pbParm1 == 99 && ((pbParm1[0xd] == 0x74 && ((pbParm1[0x14] & 0x45) == 0x44)))))))))))
         ) && ((pbParm1[8] & 0x15) == 0x10)) &&
       (((pbParm1[0xc] == 0x5f && ((char)pbParm1[4] >> 4 == '\a')) && (pbParm1[0xd] == 0x74)))) &&
      (((((bVar2 = (byte)((char)*pbParm1 >> 7) >> 5,
          (int)(char)*pbParm1 >> ((*pbParm1 + bVar2 & 7) - bVar2 & 0x1f) == 0xc &&
          (pbParm1[10] == 0x5f)) &&
         ((((int)(char)pbParm1[8] & 0xacU) == 0x28 &&
          ((pbParm1[0x10] == 0x73 && ((pbParm1[0x16] & 0x1d) == 0x18)))))) &&
        ((pbParm1[9] == 0x33 &&
         ((((pbParm1[5] == 0x31 && (((int)(char)pbParm1[0x13] & 0x3fffffffU) == 0x72)) &&
           ((char)pbParm1[0x14] >> 6 == 1)) &&
          (((char)pbParm1[7] >> 1 == '/' && (pbParm1[1] == 0x6c)))))))) &&
       (((((((char)pbParm1[3] >> 4 == '\a' &&
            (((pbParm1[0x13] & 0x49) == 0x40 && (pbParm1[4] == 0x73)))) &&
           ((pbParm1[0xb] & pbParm1[2]) == 0x14)) &&
          (((((*pbParm1 == 99 && ((int)(char)pbParm1[5] + (int)(char)pbParm1[4] == 0xa4)) &&
             (((int)(char)pbParm1[0xf] & 0x3ffffffU) == 0x5f)) &&
            ((((pbParm1[10] ^ 0x2b) == pbParm1[0x11] && ((pbParm1[0xc] ^ 0x2c) == pbParm1[4])) &&
             (((int)(char)pbParm1[0x13] - (int)(char)pbParm1[0x15] == 0x13 &&
              ((pbParm1[0xc] == 0x5f && (pbParm1[0xc] == 0x5f)))))))) &&
           ((char)pbParm1[0xf] >> 1 == '/')))) &&
         (((pbParm1[0x13] == 0x72 && ((int)(char)pbParm1[0x12] + (int)(char)pbParm1[0x11] == 0xa8))
          && (pbParm1[0x16] == 0x3a)))) &&
        (((pbParm1[0x15] & pbParm1[0x17]) == 9 &&
         (bVar2 = (byte)((char)pbParm1[0x13] >> 7) >> 5,
         (int)(char)pbParm1[6] << ((pbParm1[0x13] + bVar2 & 7) - bVar2 & 0x1f) == 0x18c)))))))) &&
     (((((((int)(char)pbParm1[7] + (int)(char)pbParm1[3] == 0xd2 &&
          ((((int)(char)pbParm1[0x16] & 0xedU) == 0x28 && (((int)(char)pbParm1[0xc] & 0xacU) == 0xc)
           ))) && ((pbParm1[0x12] ^ 0x6b) == pbParm1[0xf])) &&
        ((((((((pbParm1[0x10] & 0x7a) == 0x72 && ((*pbParm1 & 0x39) == 0x21)) &&
             ((pbParm1[6] ^ 0x3c) == pbParm1[0x15])) &&
            ((pbParm1[0x14] == 0x74 && (pbParm1[0x13] == 0x72)))) && (pbParm1[0xc] == 0x5f)) &&
          (((pbParm1[2] == 0x34 && (pbParm1[0x17] == 0x29)) &&
           ((pbParm1[10] == 0x5f &&
            ((((pbParm1[9] & pbParm1[0x16]) == 0x32 &&
              ((int)(char)pbParm1[2] + (int)(char)pbParm1[3] == 0xa7)) &&
             ((int)(char)pbParm1[0x11] - (int)(char)pbParm1[0xe] == 0x44)))))))) &&
         (((pbParm1[0x15] == 0x5f && ((pbParm1[0x13] ^ 0x2d) == pbParm1[10])) &&
          ((((int)(char)pbParm1[0xc] & 0x3fffffffU) == 0x5f &&
           (((((pbParm1[6] & 0x40) != 0 && ((pbParm1[0x16] & pbParm1[0xc]) == 0x1a)) &&
             ((bVar2 = (byte)((char)pbParm1[0x13] >> 7) >> 5,
              (int)(char)pbParm1[7] << ((pbParm1[0x13] + bVar2 & 7) - bVar2 & 0x1f) == 0x17c &&
              ((((pbParm1[0x14] ^ 0x4e) == pbParm1[0x16] && (pbParm1[6] == 99)) &&
               (pbParm1[0xc] == pbParm1[7])))))) &&
            (((int)(char)pbParm1[0x13] - (int)(char)pbParm1[0xd] == -2 &&
             ((char)pbParm1[0xe] >> 4 == 3)))))))))))) &&
       (((pbParm1[0xc] & 0x38) == 0x18 &&
        (((bVar2 = (byte)((char)pbParm1[10] >> 7) >> 5,
          (int)(char)pbParm1[8] << ((pbParm1[10] + bVar2 & 7) - bVar2 & 0x1f) == 0x3d00 &&
          (pbParm1[0x14] == 0x74)) &&
         ((bVar2 = (byte)((char)pbParm1[0x16] >> 7) >> 5,
          (int)(char)pbParm1[6] >> ((pbParm1[0x16] + bVar2 & 7) - bVar2 & 0x1f) == 0x18 &&
          (((((int)(char)pbParm1[0x16] - (int)(char)pbParm1[5] == 9 &&
             (bVar2 = (byte)((char)pbParm1[0x16] >> 7) >> 5,
             (int)(char)pbParm1[7] << ((pbParm1[0x16] + bVar2 & 7) - bVar2 & 0x1f) == 0x17c)) &&
            (pbParm1[0x16] == 0x3a)) &&
           ((pbParm1[0x10] == 0x73 && ((pbParm1[0x17] ^ 0x1d) == pbParm1[0x12])))))))))))) &&
      ((((int)(char)pbParm1[0xe] + (int)(char)pbParm1[0x17] == 0x59 &&
        (((pbParm1[2] & pbParm1[5]) == 0x30 && (((int)(char)pbParm1[0xf] & 0x9fU) == 0x1f)))) &&
       ((pbParm1[4] == 0x73 &&
        (((pbParm1[0x17] ^ 0x4a) == *pbParm1 && ((pbParm1[6] ^ 0x3c) == pbParm1[0xb])))))))))) {
    uVar1 = 1;
  }
  else {
    uVar1 = 0;
  }
  return uVar1;
}

この条件を満たすようz3で解く。

from z3 import *

xs = [BitVec('x%d' % i, 8) for i in range(24)]

s = Solver()
s.add((xs[0x14] ^ 0x2b) == xs[7])
s.add(xs[0x15] - xs[3] == -0x14)
s.add(xs[2] >> 6 == 0)
s.add(xs[0xd] == 0x74, (xs[0xb] & 0x3fffffff) == 0x5f)
bVar2 = (xs[0x11] >> 7) >> 5
s.add(xs[7] >> ((xs[0x11] + bVar2 & 7) - bVar2 & 0x1f) == 5)
s.add(xs[6] ^ 0x53 == xs[0xe], xs[8] == 0x7a)
bVar2 = (xs[9] >> 7) >> 5
s.add(xs[5] << ((xs[9] + bVar2 & 7) - bVar2 & 0x1f) == 0x188)
s.add(xs[0x10] - xs[7] == 0x14)
bVar2 = (xs[0x17] >> 7) >> 5
s.add(xs[7] << ((xs[0x17] + bVar2 & 7) - bVar2 & 0x1f) == 0xbe)
s.add(xs[2] - xs[7] == -0x2b)
s.add(xs[0x15] == 0x5f, xs[2] ^ 0x47 == xs[3])
s.add(xs[0] == 99, xs[0xd] == 0x74, xs[0x14] & 0x45 == 0x44)
s.add(xs[8] & 0x15 == 0x10)
s.add(xs[0xc] == 0x5f, xs[4] >> 4 == 7, xs[0xd] == 0x74)
bVar2 = (xs[0] >> 7) >> 5
s.add(xs[0] >> ((xs[0] + bVar2 & 7) - bVar2 & 0x1f) == 0xc)
s.add(xs[10] == 0x5f)
s.add(xs[8] & 0xac == 0x28)
s.add(xs[0x10] == 0x73, (xs[0x16] & 0x1d) == 0x18)
s.add(xs[9] == 0x33)
s.add(xs[5] == 0x31, xs[0x13] & 0x3fffffff == 0x72)
s.add(xs[0x14] >> 6 == 1)
s.add(xs[7] >> 1 == 47, xs[1] == 0x6c)
s.add(xs[3] >> 4 == 7)
s.add(xs[0x13] & 0x49 == 0x40, xs[4] == 0x73)
s.add((xs[0xb] & xs[2]) == 0x14)
s.add(xs[0] == 99, xs[5] + xs[4] == 0xa4)
s.add(xs[0xf] & 0x3ffffff == 0x5f)
s.add(xs[10] ^ 0x2b == xs[0x11], xs[0xc] ^ 0x2c == xs[4])
s.add(xs[0x13] - xs[0x15] == 0x13)
s.add(xs[0xc] == 0x5f, xs[0xc] == 0x5f)
s.add(xs[0xf] >> 1 == 47)
s.add(xs[0x13] == 0x72, xs[0x12] + xs[0x11] == 0xa8)
s.add(xs[0x16] == 0x3a)
s.add(xs[0x15] & xs[0x17] == 9)
bVar2 = (xs[13] >> 7) >> 5
s.add(xs[6] << ((xs[0x13] + bVar2 & 7) - bVar2 & 0x1f) == 0x18c)
s.add(xs[7] + xs[3] == 0xd2)
s.add(xs[0x16] & 0xed == 0x28, xs[0xc] & 0xac == 0xc)
s.add(xs[0x12] ^ 0x6b == xs[0xf])
s.add(xs[0x10] & 0x7a == 0x72, xs[0] & 0x39 == 0x21)
s.add(xs[6] ^ 0x3c == xs[0x15])
s.add(xs[0x14] == 0x74, xs[0x13] == 0x72, xs[0xc] == 0x5f)
s.add(xs[2] == 0x34, xs[0x17] == 0x29)
s.add(xs[10] == 0x5f)
s.add(xs[9] & xs[0x16] == 0x32)
s.add(xs[2] + xs[3] == 0xa7)
s.add(xs[0x11] - xs[0xe] == 0x44)
s.add(xs[0x15] == 0x5f, xs[0x13] ^ 0x2d == xs[10])
s.add(xs[0xc] & 0x3fffffff == 0x5f)
s.add(xs[6] & 0x40 != 0, xs[0x16] & xs[0xc] == 0x1a)
bVar2 = (xs[0x13] >> 7) >> 5
s.add(xs[7] << ((xs[0x13] + bVar2 & 7) - bVar2 & 0x1f) == 0x17c)
s.add(xs[0x14] ^ 0x4e == xs[0x16], xs[6] == 99)
s.add(xs[0xc] == xs[7])
s.add(xs[0x13] - xs[0xd] == -2)
s.add(xs[0xe] >> 4 == 3)
s.add(xs[0xc] & 0x38 == 0x18)

r = s.check()
if r == sat:
    m = s.model()
    flag = ''
    for i in range(24):
        flag += chr(m[xs[i]].as_long())
    print flag
else:
    print 'Not found!'

途中まで条件を書いたら、特定できた。

cl4ss1c_z3___t0_st4rt_:)
$ ./z3_robot 
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :z3 Z3Z3z3 Zz3 zz33 3Z Passz3rd? Zz3 zZ3 3Z Z3Z3z
-> cl4ss1c_z3___t0_st4rt_:)   
      \_/
     (* *)
    __)#(__
   ( )...( )(_)
   || |_| ||//
>==() | | ()/
    _(___)_
   [-]   [-]   Z3 robot says :
Well done, valdiate with shkCTF{cl4ss1c_z3___t0_st4rt_:)}
shkCTF{cl4ss1c_z3___t0_st4rt_:)}

basic LSB (Steganography 100)

Stegsolveで開き、[Analyse]-[Data Extract]からRGBそれぞれのLSBのみチェックを入れると、テキストデータとしてフラグが表示された。

shkCTF{Y0u_foUnD_m3_thr0ugH_LSB_6a5e99dfacf793e27a}

Romance Dawn (Forensics 100)

pngバイナリエディタで見てみると、IDATチャンクがなく、EASYチャンクが4つある。"EASY"を"IDAT"に置換して保存すると、画像として表示でき、フラグが書いてあった。
f:id:satou-y:20200514193524p:plain

shkCTF{7uffy_1s_pr0ud_0f_y0u_0a2a9795f0bdf8d17e4}

Pain in the ass (Forensics 200)

SQLインジェクションをしていて、No.13580のパケットからdev_usernameを割り出そうとしている。

' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),1,1) = 'a' and '1
               :
' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),1,1) = 'k' and '1
Found. Redirecting to /login?returnurl=undefined&error=Multiple%20rows%20were%20not%20expected.

Multiple%20rows%20were%20not%20expected.の場合、存在すると考えられる。このリプライが来る前のpasswordの設定値を取り出す。

' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),2,1) = '3' and '1
' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),3,1) = 'v' and '1
' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),4,1) = 'i' and '1
' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),5,1) = 'n' and '1
' or substr((SELECT dev_username FROM developpers LIMIT 1 OFFSET 0),6,1) = '"' and '1
Found. Redirecting to /login?returnurl=undefined&error=No%20data%20returned%20from%20the%20query.
dev_username = k3vin

続いてdev_passwordを割り出そうとしている。

' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),1,1) = 's' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),2,1) = 'h' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),3,1) = 'k' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),4,1) = 'C' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),5,1) = 'T' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),6,1) = 'F' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),7,1) = '{' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),8,1) = '4' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),9,1) = 'l' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),10,1) = 'm' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),11,1) = '0' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),12,1) = 's' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),13,1) = 't' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),14,1) = '_' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),15,1) = 'h' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),16,1) = '1' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),17,1) = 'd' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),18,1) = 'd' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),19,1) = '3' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),20,1) = 'n' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),21,1) = '_' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),22,1) = '3' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),23,1) = 'x' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),24,1) = 't' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),25,1) = 'r' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),26,1) = '4' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),27,1) = 'c' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),28,1) = 't' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),29,1) = '1' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),30,1) = '0' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),31,1) = 'n' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),32,1) = '_' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),33,1) = '0' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),34,1) = 'e' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),35,1) = '1' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),36,1) = '8' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),37,1) = 'e' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),38,1) = '3' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),39,1) = '3' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),40,1) = '6' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),41,1) = 'a' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),42,1) = 'd' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),43,1) = 'c' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),44,1) = '8' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),45,1) = '2' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),46,1) = '3' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),47,1) = '6' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),48,1) = 'a' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),49,1) = '0' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),50,1) = '4' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),51,1) = '5' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),52,1) = '2' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),53,1) = 'c' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),54,1) = 'd' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),55,1) = '5' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),56,1) = '7' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),57,1) = '0' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),58,1) = 'f' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),59,1) = '7' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),60,1) = '4' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),61,1) = '5' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),62,1) = '4' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),63,1) = '2' and '1
' or substr((SELECT dev_password FROM developpers LIMIT 1 OFFSET 0),64,1) = '}' and '1

以上からdev_passwordがわかり、フラグになっている。

shkCTF{4lm0st_h1dd3n_3xtr4ct10n_0e18e336adc8236a0452cd570f74542}

Backflip in the kitchen (Crypto 300)

emerald51アカウントを作成し、ログインしてみる。

ID : 137
Username : emerald51
Administrator : 0

f:id:satou-y:20200514194044p:plain
クッキーのdebugの値をfalseからtrueにしてリロードすると、HTMLソースに以下のように記載されていた。

console.log({"id":137,"is_admin":0,"username":"emerald51"});

クッキーのauthentication_tokenを見る。

zl95wM%2BYMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP%2FRMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g%3D%3D

URLデコードする。

zl95wM+YMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g==

恐らく暗号化データ長から考えても、平文は以下のデータ。

{"id":137,"is_admin":0,"username":"emerald51"}

AES-CBC暗号になっているようなので、ブロック単位に行で分けると、以下のようなイメージになるはず。

0123456789abcdef
{"id":237,"is_ad
min":0,"username
":"emerald51"}PP

暗号文の最初の16バイトをIVと推測して、試しに7バイト目が2になるようXORで変更してみる。

import base64

b64 = 'zl95wM+YMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g=='

enc = b64.decode('base64')
new_enc = enc[:6] + chr(ord(enc[6]) ^ ord('1') ^ ord('2')) + enc[7:]
new_enc = base64.b64encode(new_enc)
print new_enc

実行結果は以下の通り。

zl95wM+YM2rJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g==

URLエンコードする。

zl95wM%2BYM2rJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP%2FRMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g%3D%3D

この値をクッキーにセットしてみる。

ID : 237
Username : emerald51
Administrator : 0

console.log({"id":237,"is_admin":0,"username":"emerald51"});

推測は合っているようだ。

0123456789abcdef
{"jd":137,"is_ad
min":0,"username
":"emerald51"}PP

試しに"id"でなく"jd"にしたらどうなのかを見てみる。

import base64

b64 = 'zl95wM+YMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g=='

enc = b64.decode('base64')
new_enc = enc[:2] + chr(ord(enc[2]) ^ ord('i') ^ ord('j')) + enc[3:]
new_enc = base64.b64encode(new_enc)
print new_enc

実行結果は以下の通り。

zl96wM+YMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g==

URLエンコードする。

zl96wM%2BYMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP%2FRMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g%3D%3D

この値をクッキーにセットしてみる。

ID :
Username : emerald51
Administrator : 0

f:id:satou-y:20200514194525p:plain
IDには値はセットされず、特にエラーにはならない。id属性はなくてもよいので、以下のようなデータを構成するように暗号化データを作成することにする。

0123456789abcdef
{"is_admin":1,"a
min":0,"username
":"emerald51"}PP
import base64

def str_xor(s1, s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2))

b64 = 'zl95wM+YMGrJ67OjdE9pHsvoJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g=='

enc = b64.decode('base64')
iv = enc[:16]
enc = enc[16:]

pt0 = '{"id":137,"is_ad'
pt0_new = '{"is_admin":1,"a'
iv_new = str_xor(str_xor(pt0, iv), pt0_new)

enc_new = base64.b64encode(iv_new + enc)
print enc_new

実行結果は以下の通り。

zl9517LDZTSXqbPwNjwqG8voJ2tpAQxwrdcmgbrhgGP/RMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g==

URLエンコードする。

zl9517LDZTSXqbPwNjwqG8voJ2tpAQxwrdcmgbrhgGP%2FRMsuAiDptOy3Na7UB1ZEKcYyYklDsCZuP8IWc5g34g%3D%3D

この値をクッキーにセットしてみる。

ID :
Username : emerald51
Administrator : 1

f:id:satou-y:20200514194642p:plain
Administratorになれた!Admin panelを見てみると、フラグが表示された。
f:id:satou-y:20200514194730p:plain

shkCTF{EnCrypTion-1s_N0t_4Uth3nTicatiOn_faef0ead1975be01}

Beware my big exponent (Crypto 300)

pcapngファイルが添付されている。No.32のパケットから証明書をエクスポートし、証明書(公開鍵)の内容を見てみる。

$ openssl x509 -in 32.cer -text -pubkey -inform DER
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ae:08:2f:9d:46:36:f3:86
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = AU, ST = Sharky land, L = Sharky pool, O = Sharky swimming company, OU = Novice swimmers, CN = sharky.local, emailAddress = sergeant_roderick@sharky.local
        Validity
            Not Before: Apr 20 19:24:00 2020 GMT
            Not After : Apr 20 19:24:00 2023 GMT
        Subject: C = AU, ST = Sharky land, L = Sharky pool, O = Sharky swimming company, OU = Novice swimmers, CN = sharky.local, emailAddress = sergeant_roderick@sharky.local
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:de:50:82:37:65:9b:f9:dd:fe:a3:17:1e:51:b7:
                    ba:b7:be:61:ca:6f:c8:84:2d:60:70:30:f2:b8:36:
                    fb:2f:e9:ad:33:c4:e8:8d:96:36:2a:69:ce:ba:a0:
                    c5:e3:64:64:47:a0:51:ce:15:e6:f8:12:22:f3:7e:
                    02:65:5b:ed:04:1f:21:ac:e1:2c:69:0d:50:ca:ad:
                    1c:1a:2d:42:9d:1b:15:d8:50:16:d5:1b:cd:58:16:
                    c1:57:a2:0c:e5:17:14:28:58:f1:c8:a8:3d:84:c5:
                    46:4e:b1:b4:d5:de:e0:fc:61:89:24:b9:57:69:71:
                    7e:10:e6:0e:ad:93:41:45:46:98:36:0b:88:c2:3b:
                    ee:8b:5c:19:e2:cb:3f:81:cc:80:20:c2:36:02:43:
                    39:ac:2d:74:04:2b:94:76:4d:df:d0:dc:e6:c1:da:
                    29:1d:2b:28:b1:87:5d:9e:0c:35:a1:88:39:62:bc:
                    17:8b:69:7a:37:13:a1:33:72:9a:45:10:51:0a:48:
                    f0:cb:d8:78:0c:78:18:f2:55:71:07:3b:2d:39:24:
                    ae:1c:67:c5:be:21:7b:68:29:f4:ff:6c:f3:dc:be:
                    63:19:5d:7a:e9:bc:86:18:ae:2a:b4:74:9b:e5:4b:
                    0d:b5:59:15:2d:02:5f:b1:4d:13:65:75:c0:d8:4a:
                    fd:9d
                Exponent:
                    00:92:cb:d9:20:05:56:3d:ae:d0:6c:4b:01:0f:bc:
                    53:dd:98:c6:37:11:da:d7:b4:71:2b:ad:8b:a6:be:
                    c3:8a:ce:7f:3e:f4:8e:49:1c:88:e4:6f:38:b4:b3:
                    c4:43:d6:80:99:76:83:8f:dd:aa:02:37:24:04:5c:
                    f0:42:b2:13:25:be:66:93:98:40:06:8b:56:9a:73:
                    66:ce:c0:13:ce:ec:fe:9d:3b:63:b6:81:7b:cf:e6:
                    d1:4d:72:a8:69:92:18:98:80:aa:13:92:37:36:6d:
                    d7:6b:19:7a:d1:30:ae:c9:80:60:56:e7:55:b6:c7:
                    ea:97:c4:12:dc:82:26:8c:f6:cb:95:b6:87:49:77:
                    8b:79:e6:76:d8:df:ea:67:f7:9b:eb:f9:50:b1:18:
                    d6:1a:ca:71:8e:57:64:44:62:65:90:71:c2:ee:f9:
                    a7:5f:bf:2d:6f:ea:2d:54:b4:c6:58:65:15:68:a9:
                    58:ee:9c:2a:c1:54:2f:0b:02:a0:07:87:af:1e:cf:
                    bc:f8:b5:ca:c1:f2:f3:42:15:fe:af:67:4c:55:ea:
                    b4:f9:d2:89:fc:fa:09:89:47:af:3c:17:e1:e1:ae:
                    a3:f0:28:ca:07:7c:a3:5b:82:19:95:30:1f:fd:e7:
                    13:36:4d:9a:ac:9a:3c:9e:e4:81:a8:fc:b5:d5:98:
                    b6:c1
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                F1:86:8E:50:43:C2:6A:3F:10:75:E6:C8:0C:58:6E:59:90:B9:50:91
            X509v3 Authority Key Identifier: 
                keyid:F1:86:8E:50:43:C2:6A:3F:10:75:E6:C8:0C:58:6E:59:90:B9:50:91

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         65:88:01:ad:6d:9f:7e:42:b5:d5:45:ca:2c:11:09:c3:e5:fa:
         4a:6a:51:a3:b1:27:8d:d4:2f:8f:c0:42:3f:9d:39:d3:14:5b:
         32:70:76:1b:42:4a:db:71:d4:74:b1:5a:a2:a3:d4:e6:18:e7:
         04:35:d2:5f:43:54:78:a9:c1:7d:78:9c:95:80:74:6a:3d:b1:
         45:f9:ed:fe:ee:99:48:cd:29:4b:09:1b:91:65:18:60:28:2f:
         9f:fd:a4:9b:e2:11:91:b8:33:f9:a2:69:f7:df:a6:a4:b1:cf:
         b7:e1:18:c6:bd:a9:e9:5a:bd:ad:ea:b4:3b:c9:e4:8a:c8:bf:
         0d:84:5f:89:53:54:5d:86:4b:2f:86:56:8b:3c:ec:c8:59:f5:
         62:7e:63:8b:97:96:03:53:63:be:e8:5d:15:dd:a1:5e:0d:46:
         f0:be:30:63:ba:bc:70:af:7a:a5:9f:76:38:cb:58:45:3d:22:
         cb:7c:cd:0f:84:3a:e9:e2:52:52:2a:71:e5:21:9e:b1:ec:73:
         bf:ff:1f:8d:49:81:62:ac:6b:3a:a2:a7:18:1c:bb:a8:cf:51:
         a9:4c:bf:8c:39:ed:e9:81:47:47:42:f9:f2:be:db:04:44:40:
         59:c2:f5:43:a4:25:3d:e6:24:97:3d:b5:45:18:5c:84:7d:0a:
         d0:37:47:67
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAQEA3lCCN2Wb+d3+oxceUbe6
t75hym/IhC1gcDDyuDb7L+mtM8TojZY2KmnOuqDF42RkR6BRzhXm+BIi834CZVvt
BB8hrOEsaQ1Qyq0cGi1CnRsV2FAW1RvNWBbBV6IM5RcUKFjxyKg9hMVGTrG01d7g
/GGJJLlXaXF+EOYOrZNBRUaYNguIwjvui1wZ4ss/gcyAIMI2AkM5rC10BCuUdk3f
0NzmwdopHSsosYddngw1oYg5YrwXi2l6NxOhM3KaRRBRCkjwy9h4DHgY8lVxBzst
OSSuHGfFviF7aCn0/2zz3L5jGV166byGGK4qtHSb5UsNtVkVLQJfsU0TZXXA2Er9
nQKCAQEAksvZIAVWPa7QbEsBD7xT3ZjGNxHa17RxK62Lpr7Dis5/PvSOSRyI5G84
tLPEQ9aAmXaDj92qAjckBFzwQrITJb5mk5hABotWmnNmzsATzuz+nTtjtoF7z+bR
TXKoaZIYmICqE5I3Nm3Xaxl60TCuyYBgVudVtsfql8QS3IImjPbLlbaHSXeLeeZ2
2N/qZ/eb6/lQsRjWGspxjldkRGJlkHHC7vmnX78tb+otVLTGWGUVaKlY7pwqwVQv
CwKgB4evHs+8+LXKwfLzQhX+r2dMVeq0+dKJ/PoJiUevPBfh4a6j8CjKB3yjW4IZ
lTAf/ecTNk2arJo8nuSBqPy11Zi2wQ==
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
MIIFTjCCBDagAwIBAgIJAK4IL51GNvOGMA0GCSqGSIb3DQEBCwUAMIG7MQswCQYD
VQQGEwJBVTEUMBIGA1UECAwLU2hhcmt5IGxhbmQxFDASBgNVBAcMC1NoYXJreSBw
b29sMSAwHgYDVQQKDBdTaGFya3kgc3dpbW1pbmcgY29tcGFueTEYMBYGA1UECwwP
Tm92aWNlIHN3aW1tZXJzMRUwEwYDVQQDDAxzaGFya3kubG9jYWwxLTArBgkqhkiG
9w0BCQEWHnNlcmdlYW50X3JvZGVyaWNrQHNoYXJreS5sb2NhbDAeFw0yMDA0MjAx
OTI0MDBaFw0yMzA0MjAxOTI0MDBaMIG7MQswCQYDVQQGEwJBVTEUMBIGA1UECAwL
U2hhcmt5IGxhbmQxFDASBgNVBAcMC1NoYXJreSBwb29sMSAwHgYDVQQKDBdTaGFy
a3kgc3dpbW1pbmcgY29tcGFueTEYMBYGA1UECwwPTm92aWNlIHN3aW1tZXJzMRUw
EwYDVQQDDAxzaGFya3kubG9jYWwxLTArBgkqhkiG9w0BCQEWHnNlcmdlYW50X3Jv
ZGVyaWNrQHNoYXJreS5sb2NhbDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggEBAN5Qgjdlm/nd/qMXHlG3ure+YcpvyIQtYHAw8rg2+y/prTPE6I2WNippzrqg
xeNkZEegUc4V5vgSIvN+AmVb7QQfIazhLGkNUMqtHBotQp0bFdhQFtUbzVgWwVei
DOUXFChY8cioPYTFRk6xtNXe4PxhiSS5V2lxfhDmDq2TQUVGmDYLiMI77otcGeLL
P4HMgCDCNgJDOawtdAQrlHZN39Dc5sHaKR0rKLGHXZ4MNaGIOWK8F4tpejcToTNy
mkUQUQpI8MvYeAx4GPJVcQc7LTkkrhxnxb4he2gp9P9s89y+Yxldeum8hhiuKrR0
m+VLDbVZFS0CX7FNE2V1wNhK/Z0CggEBAJLL2SAFVj2u0GxLAQ+8U92YxjcR2te0
cSuti6a+w4rOfz70jkkciORvOLSzxEPWgJl2g4/dqgI3JARc8EKyEyW+ZpOYQAaL
VppzZs7AE87s/p07Y7aBe8/m0U1yqGmSGJiAqhOSNzZt12sZetEwrsmAYFbnVbbH
6pfEEtyCJoz2y5W2h0l3i3nmdtjf6mf3m+v5ULEY1hrKcY5XZERiZZBxwu75p1+/
LW/qLVS0xlhlFWipWO6cKsFULwsCoAeHrx7PvPi1ysHy80IV/q9nTFXqtPnSifz6
CYlHrzwX4eGuo/Aoygd8o1uCGZUwH/3nEzZNmqyaPJ7kgaj8tdWYtsGjUzBRMB0G
A1UdDgQWBBTxho5QQ8JqPxB15sgMWG5ZkLlQkTAfBgNVHSMEGDAWgBTxho5QQ8Jq
PxB15sgMWG5ZkLlQkTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
AQBliAGtbZ9+QrXVRcosEQnD5fpKalGjsSeN1C+PwEI/nTnTFFsycHYbQkrbcdR0
sVqio9TmGOcENdJfQ1R4qcF9eJyVgHRqPbFF+e3+7plIzSlLCRuRZRhgKC+f/aSb
4hGRuDP5omn336aksc+34RjGvanpWr2t6rQ7yeSKyL8NhF+JU1RdhksvhlaLPOzI
WfVifmOLl5YDU2O+6F0V3aFeDUbwvjBjurxwr3qln3Y4y1hFPSLLfM0PhDrp4lJS
KnHlIZ6x7HO//x+NSYFirGs6oqcYHLuoz1GpTL+MOe3pgUdHQvnyvtsEREBZwvVD
pCU95iSXPbVFGFyEfQrQN0dn
-----END CERTIFICATE-----
n = 0x00de508237659bf9ddfea3171e51b7bab7be61ca6fc8842d607030f2b836fb2fe9ad33c4e88d96362a69cebaa0c5e3646447a051ce15e6f81222f37e02655bed041f21ace12c690d50caad1c1a2d429d1b15d85016d51bcd5816c157a20ce517142858f1c8a83d84c5464eb1b4d5dee0fc618924b95769717e10e60ead9341454698360b88c23bee8b5c19e2cb3f81cc8020c236024339ac2d74042b94764ddfd0dce6c1da291d2b28b1875d9e0c35a1883962bc178b697a3713a133729a4510510a48f0cbd8780c7818f25571073b2d3924ae1c67c5be217b6829f4ff6cf3dcbe63195d7ae9bc8618ae2ab4749be54b0db559152d025fb14d136575c0d84afd9d
e = 0x0092cbd92005563daed06c4b010fbc53dd98c63711dad7b4712bad8ba6bec38ace7f3ef48e491c88e46f38b4b3c443d6809976838fddaa023724045cf042b21325be66939840068b569a7366cec013ceecfe9d3b63b6817bcfe6d14d72a86992189880aa139237366dd76b197ad130aec9806056e755b6c7ea97c412dc82268cf6cb95b68749778b79e676d8dfea67f79bebf950b118d61aca718e57644462659071c2eef9a75fbf2d6fea2d54b4c658651568a958ee9c2ac1542f0b02a00787af1ecfbcf8b5cac1f2f34215feaf674c55eab4f9d289fcfa098947af3c17e1e1aea3f028ca077ca35b821995301ffde713364d9aac9a3c9ee481a8fcb5d598b6c1

eが非常に大きいので、Wiener's Attackで攻めてみたが、ダメだった。念のため拡張Wiener's Attackで攻めてみる。

#!/usr/bin/env sage -python
def wiener(e, n):
    m = 12345
    c = pow(m, e, n)
    q0 = 1

    list1 = continued_fraction(Integer(e)/Integer(n))
    conv = list1.convergents()
    for i in conv:
        k = i.numerator()
        q1 = i.denominator()

        for r in range(30):
            for s in range(30):
                d = r*q1 + s*q0
                m1 = pow(c, d, n)
                if m1 == m:
                    return d
        q0 = q1
    return None

n = 0x00de508237659bf9ddfea3171e51b7bab7be61ca6fc8842d607030f2b836fb2fe9ad33c4e88d96362a69cebaa0c5e3646447a051ce15e6f81222f37e02655bed041f21ace12c690d50caad1c1a2d429d1b15d85016d51bcd5816c157a20ce517142858f1c8a83d84c5464eb1b4d5dee0fc618924b95769717e10e60ead9341454698360b88c23bee8b5c19e2cb3f81cc8020c236024339ac2d74042b94764ddfd0dce6c1da291d2b28b1875d9e0c35a1883962bc178b697a3713a133729a4510510a48f0cbd8780c7818f25571073b2d3924ae1c67c5be217b6829f4ff6cf3dcbe63195d7ae9bc8618ae2ab4749be54b0db559152d025fb14d136575c0d84afd9d
e = 0x0092cbd92005563daed06c4b010fbc53dd98c63711dad7b4712bad8ba6bec38ace7f3ef48e491c88e46f38b4b3c443d6809976838fddaa023724045cf042b21325be66939840068b569a7366cec013ceecfe9d3b63b6817bcfe6d14d72a86992189880aa139237366dd76b197ad130aec9806056e755b6c7ea97c412dc82268cf6cb95b68749778b79e676d8dfea67f79bebf950b118d61aca718e57644462659071c2eef9a75fbf2d6fea2d54b4c658651568a958ee9c2ac1542f0b02a00787af1ecfbcf8b5cac1f2f34215feaf674c55eab4f9d289fcfa098947af3c17e1e1aea3f028ca077ca35b821995301ffde713364d9aac9a3c9ee481a8fcb5d598b6c1

d = wiener(e, n)
print 'd =', d

実行結果は以下の通り。

d = 12943142410604045324963573717399150995389999892438958933300438824584828677265304042959568659708458383668696495604670543369903677147732370774826294074933249

秘密鍵がわかったので、秘密鍵ファイルを生成する。

from Crypto.PublicKey import RSA

n = 0x00de508237659bf9ddfea3171e51b7bab7be61ca6fc8842d607030f2b836fb2fe9ad33c4e88d96362a69cebaa0c5e3646447a051ce15e6f81222f37e02655bed041f21ace12c690d50caad1c1a2d429d1b15d85016d51bcd5816c157a20ce517142858f1c8a83d84c5464eb1b4d5dee0fc618924b95769717e10e60ead9341454698360b88c23bee8b5c19e2cb3f81cc8020c236024339ac2d74042b94764ddfd0dce6c1da291d2b28b1875d9e0c35a1883962bc178b697a3713a133729a4510510a48f0cbd8780c7818f25571073b2d3924ae1c67c5be217b6829f4ff6cf3dcbe63195d7ae9bc8618ae2ab4749be54b0db559152d025fb14d136575c0d84afd9d
e = 0x0092cbd92005563daed06c4b010fbc53dd98c63711dad7b4712bad8ba6bec38ace7f3ef48e491c88e46f38b4b3c443d6809976838fddaa023724045cf042b21325be66939840068b569a7366cec013ceecfe9d3b63b6817bcfe6d14d72a86992189880aa139237366dd76b197ad130aec9806056e755b6c7ea97c412dc82268cf6cb95b68749778b79e676d8dfea67f79bebf950b118d61aca718e57644462659071c2eef9a75fbf2d6fea2d54b4c658651568a958ee9c2ac1542f0b02a00787af1ecfbcf8b5cac1f2f34215feaf674c55eab4f9d289fcfa098947af3c17e1e1aea3f028ca077ca35b821995301ffde713364d9aac9a3c9ee481a8fcb5d598b6c1
d = 12943142410604045324963573717399150995389999892438958933300438824584828677265304042959568659708458383668696495604670543369903677147732370774826294074933249

key = RSA.construct(map(long, (n, e, d)))

with open('secret.pem', 'w') as f:
    f.write(key.exportKey())

この秘密鍵ファイルを以下のパラメータでWiresharkに設定し、復号する。

IP address: 127.0.0.1
Port: 465
Protocol: http
Key File: 生成した秘密鍵ファイル

No.68のパケットにフラグがあった。

shkCTF{Publ1c_3xp_t0o_b1G_6a8eaf56ab89cb}

Heavy computation (Crypto 400)

derive_key関数の中の処理が現実的でない。簡単に計算できるよう書き換える。

for i in range(NB_ITERATIONS):
    start = start ** e
    start %= N

この部分はこうなる。

start = pow(start, pow(e, NB_ITERATIONS), N)
      = pow(start, pow(e, NB_ITERATIONS, phi(N)), N)
key = 1
for i in range(NB_ITERATIONS):
    key = key ** e
    key %= N
    key *= start
    key %= N

この部分について、iが増えていくのを見てみる。

i = 0
- key = pow(1, e, N) = 1
- key = (1 * start) % N = start % N
i = 1
- key = pow(start, e, N)
- key = pow(start, e, N) * start
i = 2
- key = pow(pow(start, e, N), e, N) * pow(start, e, N)
      = pow(start, pow(e, 2), N) * pow(start, e, N)
      = pow(start, pow(e, 2, phi(N)), N) * pow(start, e, N)
- key = pow(start, pow(e, 2, phi(N)), N) * pow(start, e, N) * start
            :

以上のことからこの部分はこうなる。

key = (pow(start, pow(e, NB_ITERATIONS - 1, phi(N)), N)
      * pow(start, pow(e, NB_ITERATIONS - 2, phi(N)), N)
            :
      * pow(start, pow(e, 0, phi(N)), N)) % N
    = pow(start,
      pow(e, NB_ITERATIONS - 1, phi(N)) + pow(e, NB_ITERATIONS - 2, phi(N))
      + ... + pow(e, 0, phi(N)), N)
    = pow(start,
      (pow(e, NB_ITERATIONS, phi(N)) - 1) * inverse(e - 1, phi(N)) % phi(N), N)

ここで (e^(n-1) + ... + e^2 + e + 1) * (e - 1) = e^n - 1 (mod N) であることを使った。
Nをfactordbで素因数分解する。

N = 5 * 23 * 61 * 701 * 3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651847

このことからphi(N)は以下の値になる。

phi(N) = 4 * 22 * 60 * 700 * 3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651846

passwordは2バイトのprintable文字なので、その範囲でブルートフォースで復号する。

from Crypto.Util.number import bytes_to_long, long_to_bytes, inverse
from Crypto.Cipher import AES
from hashlib import sha256
import itertools
import string

NB_ITERATIONS = 10871177237854734092489348927
e = 65538

N = 14968794114523720195251887716913440457986979987674770429103169854116498198112478103466085455257317270930523061714030307370028304505577267672733143013124254253285088080041831478700041394909740024011681885623055622400205

phi = 4 * 22 * 60 * 700 * 3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651846

def unpad(s):
    return s[:-ord(s[-1])]

def derive_key(password):
    start = bytes_to_long(password)
    start = pow(start, pow(e, NB_ITERATIONS, phi), N)

    key = pow(start, ((pow(e, NB_ITERATIONS, phi) - 1)
        * inverse(e - 1, phi)) % phi, N)

    return sha256(long_to_bytes(key)).digest()

with open('flag.enc', 'rb') as f:
    enc = f.read()

IV = 'random_and_safe!'
for c in itertools.product(string.printable, repeat=2):
    password = ''.join(c)
    key = derive_key(password)
    cipher = AES.new(key, AES.MODE_CBC, IV)
    flag = cipher.decrypt(enc)
    if 'shkCTF' in flag:
        flag = unpad(flag)
        print 'password =', password
        print 'flag =', flag
        break

実行結果は以下の通り。

password = ~@
flag = shkCTF{M4ths_0v3r_p4t13Nce_b4453d1f9f5386a1846e57a3ec95678f}
shkCTF{M4ths_0v3r_p4t13Nce_b4453d1f9f5386a1846e57a3ec95678f}

Noisy RSA (Crypto 400)

ct[0] = pow(rand<<24, e, N)
ct[1] = pow(pow(flag[0],e,N)+(rand<<24)), e, N)
      :

rand<<24はpow(flag[0],e,N)に比べて、相当大きい数値。Coppersmith's Short Pad Attackで平文の差を求めることができるので、pow(ord(flag[i]), e, N)がわかる。あとは総当たりで1文字ずつ割り出せばよい。

#!/usr/bin/env sage -python
from Crypto.Util.number import *

def short_pad_attack(c1, c2, e, n):
    PRxy.<x,y> = PolynomialRing(Zmod(n))
    PRx.<xn> = PolynomialRing(Zmod(n))
    PRZZ.<xz,yz> = PolynomialRing(Zmod(n))

    g1 = x^e - c1
    g2 = (x+y)^e - c2

    q1 = g1.change_ring(PRZZ)
    q2 = g2.change_ring(PRZZ)

    h = q2.resultant(q1)
    h = h.univariate_polynomial()
    h = h.change_ring(PRx).subs(y=xn)
    h = h.monic()

    kbits = n.nbits()//(2*e*e)
    diff = h.small_roots(X=2^kbits, beta=0.5)[0]

    return diff

N = 166340340660877519226247260987065058211371932250499241074633026863387096385721863889904212902371869444274842128829082337552709506851212430322777753756706525557339442213042322434951929492350910439291882068704178535251621706072605607671593003649095340546077718624006859019891494745600258808326203381366558360403
e = 3
ct = [72881243587279652525011668389480886731233379003340815331672052156449010464010693304931728042216088657642642153607136661251184626426811987027166068591298345434705349712743185809458404592395692720660113774009080627872192793713309891346264883115832358507857462312275400764420518834080531059771744334365221989634, 120942671498483330060520229769388972851903750065221974908980408800142585447054246279988215440838619341480941425987900671088263735178370517975791870374867924130327757712683134115691371457608477285865042459315287349798635279186783640977356463108475695769654664032379733434805748471608372219467852099247995100354, 54386721895465415656380957950904549736556479738021646221378610804716311415487489890511325316136147797305298472141912927119981772909238569622011245533731281983191346046284859394790231772028252518442679512839637492607553340532809710322773811504243675887595893870027501332275699811129878490987811760210612933716, 11880608396225790010445065580521875175061872208660894746829118793512943619971524121478717841011400135261229783025937064418918601127967160357411168420601774736659384789997048040351658493530688273612377115151262034051994763105375544562895885062209362727602445255344375603649722778117002022142839193392169140155, 34262804237414967784095746862926505482411871306209985790333569121663906637851039566918091263054617465026253062843532579902701026208809691179769018946180076876857420352339823918103265462137093108116023833864597048470675101950451759586030780575038185816404101133953700662926926027420922572812387481166380600319, 65653704057688264978003973922645648256979974922919329953623851472975207650528025404030907092387036823584435973146229680140576473399739548535342606760275676943806366442724070704029438952987323599590770284440114140762709263828323843328178670561141642056012935689834006667977718666064941565552524742974547019939, 161880034229720654298159616403742309112225639615645086154702474216799072088950563874680835183227036451624031621341884764052350511614833507245691944837495793558829705792931077219580756224869616340632910522096913853494599851613171898013779120082349231785111350903925591733389933077006049586368638494120853989027, 104239497870036181475153086131462646449605150601194400100481151159311719775750630473695452074169918071403885809829425029902754068736890395620546755543209278933521229026770385528263396377647955317191128185570286300550000895443385590067588200678975711683469845723962879914265001863309468754686139765477612185087, 92674223102640974167579467658876003975701212559445768284533906072958579780751109060637069492215349071440238826599184419499336228627331101243585563126400716496066608419914873866575904640669167592797303026302216421966055971106061780589229175120429193604531855609647051437884735592914416794132631918290938940609, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 59880731602893098870237860517360711492498689242956189579684724496705931290861158617913613988951992687054236471463086575366061250509985298259061534494343622073465754999935278636979552531805954695554263073965201013043313042422970218419268713551162036590536533555689035780552569935768439476380220332453698240382, 68495202482771380812120424238242712116179683150755000667513625188027550434724412573573687010996882435098478802087890093223517471674861486798806652225241952568999494601954177986066249363501490679608456030498682161850572273862904941963096782232949955981518736822611712476658381465811398157304843272006247858215, 67355253715174142813679972637829069011938946913569440657280962826544565558311947732037916509553366332205568215074504943167167261717347597441432988467257080307929267498099274022615413159398511167079600799697141523178828853309714031982157707544531167170678069696490812193826309900335674738646155658692139926400, 92674223102640974167579467658876003975701212559445768284533906072958579780751109060637069492215349071440238826599184419499336228627331101243585563126400716496066608419914873866575904640669167592797303026302216421966055971106061780589229175120429193604531855609647051437884735592914416794132631918290938940609, 145388553754700074878094750380079349071257763768841548615288131552167391290085089559038649683170316902720650949767212149600159696106177983743880461300927695592624286461566112376387853543214679044845953673099884246520751412892917396220320003992419351548988182920553076959124258660399452741260663424640189495427, 54830946004549036563556581795155724798510053935980243332432354500828917099091931525262518623478459816636460991332724153627273932230231471128816986242405749412646865270981814746727424234326447348154751066986673137595635647156606004365175885104032602886392793873140143944486155487815414055040147350440646207059, 86698953691931849119646183135977333385413301185700335940576783650746237236745527914380031083197382680841434357133940812280633032477919529200177505493582566464356663043902285836686693996833345687341737689915875804650694790870393528075308616114942945418606287380804608329387797869761033495149643445834636353852, 67355253715174142813679972637829069011938946913569440657280962826544565558311947732037916509553366332205568215074504943167167261717347597441432988467257080307929267498099274022615413159398511167079600799697141523178828853309714031982157707544531167170678069696490812193826309900335674738646155658692139926400, 59880731602893098870237860517360711492498689242956189579684724496705931290861158617913613988951992687054236471463086575366061250509985298259061534494343622073465754999935278636979552531805954695554263073965201013043313042422970218419268713551162036590536533555689035780552569935768439476380220332453698240382, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 145388553754700074878094750380079349071257763768841548615288131552167391290085089559038649683170316902720650949767212149600159696106177983743880461300927695592624286461566112376387853543214679044845953673099884246520751412892917396220320003992419351548988182920553076959124258660399452741260663424640189495427, 59027035351209289645247574199510610178554499985067863318105207701344016605715321491181999825401346945618254025387623130032530300131748601706601460943571625469524963534425515109590621922984982788214005252858139978815941143569735773399163696793911859751571932945214950875693157085041553032013803763006092899098, 149236719750342117194860032475863311944635932795769610560074812854784594781707774839572534086347443280265839288104874012598532377415546036801795705989928718058517205838649833806768678096029472223010693883613142248361161765769714509483290038238084178935039967339455481688830368936492364294191635978280195797826, 67355253715174142813679972637829069011938946913569440657280962826544565558311947732037916509553366332205568215074504943167167261717347597441432988467257080307929267498099274022615413159398511167079600799697141523178828853309714031982157707544531167170678069696490812193826309900335674738646155658692139926400, 143780111767680668223663666604536614874222026976963818624146239588181330402941735388233651052562360129969989210572660006611912426685802751239814273374330556786490656314216350706146432493607631898581070832309613841956302308335892261107167682978608710187061737493049667942950113340159869191963595319216300654796, 59027035351209289645247574199510610178554499985067863318105207701344016605715321491181999825401346945618254025387623130032530300131748601706601460943571625469524963534425515109590621922984982788214005252858139978815941143569735773399163696793911859751571932945214950875693157085041553032013803763006092899098, 112154513541022252722994644831425109159741749657800729461543628703329197179375758850605230927049063411169184725631254278872961646449918410771537794623792958041052972272766819753691279730102811935958417832065696806328771473727100811927065419366652895167609709840293683151617543010812224580602524349396364694209, 67355253715174142813679972637829069011938946913569440657280962826544565558311947732037916509553366332205568215074504943167167261717347597441432988467257080307929267498099274022615413159398511167079600799697141523178828853309714031982157707544531167170678069696490812193826309900335674738646155658692139926400, 106839734514788577088553099852963996165502019758872693751731384334728289731293262191484352928552086426764174402231325380670958998722810553675683763937277371984480817983944492567301873099172830328514795470149828405494026311352371191980123007626099996466823932348346879317851077005970047391690052679034004396547, 39935983604275256358074710586888027514533864414604960205836839571829532521919187280608482408494171550463388076280000826560502672409306736851954514342553257040587215092455093291334791101859200442540223510471617745552416961870092834856811136670762761604079039949052394768560714334590556468070557244249912165069, 143522829394130333644563185202598228506481728613114987607815854946981791849827094972737356457563664801144301673524195833562030084205297942706782572894202082215947061104713161787097516227192682300675377718317559721436263821235154197751430033478460795052351764897658928943577797801171878759896044099893302230848, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 112154513541022252722994644831425109159741749657800729461543628703329197179375758850605230927049063411169184725631254278872961646449918410771537794623792958041052972272766819753691279730102811935958417832065696806328771473727100811927065419366652895167609709840293683151617543010812224580602524349396364694209, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 120190697564953338722965600497152932815422939084424607823861028590466910896794698533194080565068409171704468785963512911276662897291263446488122642167624565546839624403524751019340529813743850370915425048303577902589320848898445910561400891037412827789494597640359428655121125893334774600183060739731597934441, 83498090311112650169168060392734537215779286895636329911983843824337881186919704536512449352752487208012044179253540637039284767828472178152055086552307307694029249236654623877455367424363175738587410727221740458456140586788957344185257325369880318577830313574884052622097862323539709337580005712128816641522, 143522829394130333644563185202598228506481728613114987607815854946981791849827094972737356457563664801144301673524195833562030084205297942706782572894202082215947061104713161787097516227192682300675377718317559721436263821235154197751430033478460795052351764897658928943577797801171878759896044099893302230848, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 11108156924497246746144901672654677464519563685641550210738469724593267708612324134125573320178760349331094518817544035153258117188207407406320520770249272838975170665664367313633725237179238655327553097624527120745987440714932795917665483528890013841381660942123030465191558189716256600514376334423309291208, 43240675732214937541582642428659750715397884100933033976936703232338833687757297512835224080474890947381691398437226963418528412932781370397886654552500681644628059193715436362474719182455245458743057958298304328827788033459138295843463513910121311419429864366418358757207486882491511046353343359365380968621, 86638607735968467954820425772208560606826243416887953379268542233230940820283742510444907216292884011975130467096025720885771684768674807652590340922016573997730738678745862865911059567844066439988273812148801986649183281425216551413665638038055332305132998885134122508682655418418668224711047341850710915508, 83498090311112650169168060392734537215779286895636329911983843824337881186919704536512449352752487208012044179253540637039284767828472178152055086552307307694029249236654623877455367424363175738587410727221740458456140586788957344185257325369880318577830313574884052622097862323539709337580005712128816641522, 112154513541022252722994644831425109159741749657800729461543628703329197179375758850605230927049063411169184725631254278872961646449918410771537794623792958041052972272766819753691279730102811935958417832065696806328771473727100811927065419366652895167609709840293683151617543010812224580602524349396364694209, 34190955654972312048540730949593234414534088494782749363911620925477786552163829558050454181365670976625475857778164688123961437443500050938245597246123955245933367357494212550073059289223717967548633658654404081857545505729141383155883294273231209212728904593916372393077169134384276691002213981661050203233, 112154513541022252722994644831425109159741749657800729461543628703329197179375758850605230927049063411169184725631254278872961646449918410771537794623792958041052972272766819753691279730102811935958417832065696806328771473727100811927065419366652895167609709840293683151617543010812224580602524349396364694209, 83498090311112650169168060392734537215779286895636329911983843824337881186919704536512449352752487208012044179253540637039284767828472178152055086552307307694029249236654623877455367424363175738587410727221740458456140586788957344185257325369880318577830313574884052622097862323539709337580005712128816641522, 83498090311112650169168060392734537215779286895636329911983843824337881186919704536512449352752487208012044179253540637039284767828472178152055086552307307694029249236654623877455367424363175738587410727221740458456140586788957344185257325369880318577830313574884052622097862323539709337580005712128816641522, 120190697564953338722965600497152932815422939084424607823861028590466910896794698533194080565068409171704468785963512911276662897291263446488122642167624565546839624403524751019340529813743850370915425048303577902589320848898445910561400891037412827789494597640359428655121125893334774600183060739731597934441, 112154513541022252722994644831425109159741749657800729461543628703329197179375758850605230927049063411169184725631254278872961646449918410771537794623792958041052972272766819753691279730102811935958417832065696806328771473727100811927065419366652895167609709840293683151617543010812224580602524349396364694209, 146208102390977991040722795029329240182560407320173858403439172895987069545183159283863752131423538146383363456599517097368650734718910841670079906185802128357898643431246472533116457014808308303177777726663780979741828570561990987982995924709035902156752922244034162914071748272579996183506873904616777537708, 39935983604275256358074710586888027514533864414604960205836839571829532521919187280608482408494171550463388076280000826560502672409306736851954514342553257040587215092455093291334791101859200442540223510471617745552416961870092834856811136670762761604079039949052394768560714334590556468070557244249912165069, 39935983604275256358074710586888027514533864414604960205836839571829532521919187280608482408494171550463388076280000826560502672409306736851954514342553257040587215092455093291334791101859200442540223510471617745552416961870092834856811136670762761604079039949052394768560714334590556468070557244249912165069, 86638607735968467954820425772208560606826243416887953379268542233230940820283742510444907216292884011975130467096025720885771684768674807652590340922016573997730738678745862865911059567844066439988273812148801986649183281425216551413665638038055332305132998885134122508682655418418668224711047341850710915508, 86638607735968467954820425772208560606826243416887953379268542233230940820283742510444907216292884011975130467096025720885771684768674807652590340922016573997730738678745862865911059567844066439988273812148801986649183281425216551413665638038055332305132998885134122508682655418418668224711047341850710915508, 106839734514788577088553099852963996165502019758872693751731384334728289731293262191484352928552086426764174402231325380670958998722810553675683763937277371984480817983944492567301873099172830328514795470149828405494026311352371191980123007626099996466823932348346879317851077005970047391690052679034004396547, 11108156924497246746144901672654677464519563685641550210738469724593267708612324134125573320178760349331094518817544035153258117188207407406320520770249272838975170665664367313633725237179238655327553097624527120745987440714932795917665483528890013841381660942123030465191558189716256600514376334423309291208, 86698953691931849119646183135977333385413301185700335940576783650746237236745527914380031083197382680841434357133940812280633032477919529200177505493582566464356663043902285836686693996833345687341737689915875804650694790870393528075308616114942945418606287380804608329387797869761033495149643445834636353852, 23017984756564001865693587169148457239063175358872766361897027111380775748810954273494863654870468736844300856603821317211963862477279506032917579807080462159849244774727164293028640419171050713848804946855196691189181764452391938795857167396595623175177872267796950587546316583723370686292284449646725709438, 86698953691931849119646183135977333385413301185700335940576783650746237236745527914380031083197382680841434357133940812280633032477919529200177505493582566464356663043902285836686693996833345687341737689915875804650694790870393528075308616114942945418606287380804608329387797869761033495149643445834636353852, 86698953691931849119646183135977333385413301185700335940576783650746237236745527914380031083197382680841434357133940812280633032477919529200177505493582566464356663043902285836686693996833345687341737689915875804650694790870393528075308616114942945418606287380804608329387797869761033495149643445834636353852, 4805679921477589071270382595930149735812110248154929216185664017771852251140810791946359283143064364968036660046368184303616369354213296056029776011885733031210935168219878702583763074429771679291509617430818906704402387172896705345580447104116478842219246365258681532513194759794416604362422193757080970388]

flag = ''
for c in ct[1:]:
    diff = short_pad_attack(ct[0], c, e, N)
    for code in range(32, 127):
        if pow(code, e, N) == diff:
            flag += chr(code)
            break

print flag
shkCTF{L0NG_LIV3_N0ISY_RS4_b86040a760e25740477a498855be3c33}

Casino (Crypto 400)

apkファイルが添付されている。Bytecode Viewerでデコンパイルする。

package com.example.casino.ui.notifications;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import com.example.casino.ui.notifications.NotificationsFragment.1;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class NotificationsFragment extends Fragment {
   private static byte[] key;
   private static SecretKeySpec secretKey;
   private NotificationsViewModel notificationsViewModel;

   public static String decrypt(byte[] var0, String var1) {
      try {
         setKey(var1);
         Cipher var6 = Cipher.getInstance("AES/ECB/PKCS5PADDING");
         var6.init(2, secretKey);
         String var4 = new String(var6.doFinal(var0));
         return var4;
      } catch (Exception var3) {
         PrintStream var5 = System.out;
         StringBuilder var2 = new StringBuilder();
         var2.append("Error while decrypting: ");
         var2.append(var3.toString());
         var5.println(var2.toString());
         return null;
      }
   }

   public static void setKey(String var0) {
      try {
         key = var0.getBytes("UTF-8");
         byte[] var3 = MessageDigest.getInstance("SHA-1").digest(key);
         key = var3;
         key = Arrays.copyOf(var3, 16);
         SecretKeySpec var4 = new SecretKeySpec(key, "AES");
         secretKey = var4;
      } catch (NoSuchAlgorithmException var1) {
         var1.printStackTrace();
      } catch (UnsupportedEncodingException var2) {
         var2.printStackTrace();
      }

   }

   public View onCreateView(LayoutInflater var1, ViewGroup var2, Bundle var3) {
      this.notificationsViewModel = (NotificationsViewModel)ViewModelProviders.of(this).get(NotificationsViewModel.class);
      View var4 = var1.inflate(2131427374, var2, false);
      EditText var6 = (EditText)var4.findViewById(2131230969);
      TextView var5 = (TextView)var4.findViewById(2131230832);
      ((Button)var4.findViewById(2131230789)).setOnClickListener(new 1(this, var5, var6, new byte[]{111, -27, -52, 111, -15, -78, 14, -10, 6, 119, 113, -100, 26, -120, 12, -128, 32, -112, 69, 42, 8, -100, 32, -24, 93, -6, -21, -122, -28, -14, -86, 51, -125, 59, 44, 127, 69, 11, -26, -10, 106, -27, -31, -106, 26, 41, 117, 13, 117, -91, 107, -41, 13, -52, -91, 123, -100, -108, -115, 80, 22, -46, -67, -124}));
      return var4;
   }
}

入力したデータをキーにコード中のデータを復号するとフラグになるようだが、コードのみではパラメータがわからない。
BlueStacksでapkを実行してみると、タイトル通り、カジノのような画像で、乱数予測をすることが必要そうだ。Trainメニューで乱数予測を試すことができる。一回適当な値を入れながら、正解をメモしておくと以下のような順になった。

-1894021709
1348335974
-1814362937
-1786103166
666653972
1740947442

https://crypto.stackexchange.com/questions/51686/how-to-determine-the-next-number-from-javas-random-methodのコードを参考に上記の乱数を確認してみる。

$ cat Test.java
import java.util.Random;

public class Test {
    public static int next(long seed) {
        int bits=32;
        long seed2 = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
        return (int)(seed2 >>> (48 - bits));
    }

    public static void main(String[] args) {
        System.out.println("Starting");
        long i1 = -1894021709L;
        long i2 = 1348335974L;
        long seed =0;
        for (int i = 0; i < 65536; i++) {
            seed = i1 *65536 + i;
            if (next(seed) == i2) {
                System.out.println("Seed found: " + seed);
               break;
            }
        }
        Random random = new Random((seed ^ 0x5DEECE66DL) & ((1L << 48) - 1));
        int o1 = random.nextInt();
        int o2 = random.nextInt();
        int o3 = random.nextInt();
        System.out.println("So we have that nextInt is: "+o1+" and the third one is: "+o2+", and the forth one is: "+o3+" with seed: "+seed);

    }
}
$ javac Test.java
$ java Test
Starting
Seed found: -124126606719083
So we have that nextInt is: 1348335974 and the third one is: -1814362937, and the forth one is: -1786103166 with seed: -124126606719083

予測と実際の結果が一致した。
f:id:satou-y:20200514200212p:plain
Flag入手の条件をコードに反映し、実行する。

$ cat Predict.java
import java.util.Random;

public class Predict {
    public static int next(long seed) {
        int bits=32;
        long seed2 = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
        return (int)(seed2 >>> (48 - bits));
    }

    public static void main(String[] args) {
        System.out.println("Starting");
        long i1 = -583975528L;
        long i2 = 1737279113L;
        long seed =0;
        for (int i = 0; i < 65536; i++) {
            seed = i1 *65536 + i;
            if (next(seed) == i2) {
                System.out.println("Seed found: " + seed);
               break;
            }
        }
        Random random = new Random((seed ^ 0x5DEECE66DL) & ((1L << 48) - 1));
        int o1 = random.nextInt();
        int o2 = random.nextInt();
        int o3 = random.nextInt();
        System.out.println("So we have that nextInt is: "+o1+" and the third one is: "+o2+", and the forth one is: "+o3+" with seed: "+seed);

    }
}
$ javac Predict.java
$ java Predict
Starting
Seed found: -38271420153990
So we have that nextInt is: 1737279113 and the third one is: 855926031, and the forth one is: 124149931 with seed: -38271420153990

次の2つは855926031、124149931になるはず。掛け算したのが入力値。

>>> 855926031*124149931
106263157689753861L

細かい処理を考えるのが面倒なので、Javaコードに該当するパラメータを入れて復号してみる。

import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Solve {
    private static byte[] key;
    private static SecretKeySpec secretKey;

    public static String decrypt(byte[] var0, String var1) {
        try {
            setKey(var1);
            Cipher var6 = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            var6.init(2, secretKey);
            String var4 = new String(var6.doFinal(var0));
            return var4;
        } catch (Exception var3) {
            PrintStream var5 = System.out;
            StringBuilder var2 = new StringBuilder();
            var2.append("Error while decrypting: ");
            var2.append(var3.toString());
            var5.println(var2.toString());
            return null;
        }
    }

   public static void setKey(String var0) {
      try {
         key = var0.getBytes("UTF-8");
         byte[] var3 = MessageDigest.getInstance("SHA-1").digest(key);
         key = var3;
         key = Arrays.copyOf(var3, 16);
         SecretKeySpec var4 = new SecretKeySpec(key, "AES");
         secretKey = var4;
      } catch (NoSuchAlgorithmException var1) {
         var1.printStackTrace();
      } catch (UnsupportedEncodingException var2) {
         var2.printStackTrace();
      }

   }

    public static void main(String[] args) {
        String flag = decrypt(new byte[]{111, -27, -52, 111, -15, -78, 14, -10, 6, 119, 113, -100, 26, -120, 12, -128, 32, -112, 69, 42, 8, -100, 32, -24, 93, -6, -21, -122, -28, -14, -86, 51, -125, 59, 44, 127, 69, 11, -26, -10, 106, -27, -31, -106, 26, 41, 117, 13, 117, -91, 107, -41, 13, -52, -91, 123, -100, -108, -115, 80, 22, -46, -67, -124}, "106263157689753861");
        System.out.println("flag: " + flag);
    }
}

実行結果は以下の通り。

flag: shkCTF{Use_5ecUr3_R4nd0m_d5be1a37393b19e6d8f9f9d6aa1feab7}
shkCTF{Use_5ecUr3_R4nd0m_d5be1a37393b19e6d8f9f9d6aa1feab7}