Beginner Malware Reversing Challenges Writeup
常設なので解き方のみ。
Hide and Seek
strings1
Ghidraで開いて静的解析すればプログラム内で使用されているFlagを入手することができます。
strings2
超シンプルなStackstrings問題。floss
に投げればFlagを入手することができます。
strings3
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)