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)