Log.i53

Themidaのアンパックを目指すブログ改め使い物になるえんじにゃを目指すブログ

Pythonで隠蔽された文字列を抽出してみる その①

前記事で参照文字列の簡単な隠蔽手法とdiStormの使い方について纏めたので、Pythonを用いてバイナリから隠蔽文字列を抽出する手法を考えて行こうと思います。

バイト単位で単純に分解されている場合

f:id:i53:20150427183938p:plain
diStromを利用して1バイトの代入命令をプログラム内から抽出して、第二オペランドだけを抽出して元の文字列を形成します。

# from distorm3 import Decode, Decode32Bits
# 
# l = Decode(0x00400000, open('test.exe', 'rb').read(), Decode32Bits)
# insts = []
# for i in l:
#     if 'MOV BYTE' in i[2]:
#         insts.append(i[2])

insts = [
    "MOV BYTE [0x20043e], 0x1",
    "MOV BYTE [EBP-0x10], 0x48",
    "MOV BYTE [EBP-0xf], 0x65",
    "MOV BYTE [EBP-0xe], 0x6c",
    "MOV BYTE [EBP-0xd], 0x6c",
    "MOV BYTE [EBP-0xc], 0x6f",
    "MOV BYTE [EBP-0xb], 0x20",
    "MOV BYTE [EBP-0xa], 0x57",
    "MOV BYTE [EBP-0x9], 0x6f",
    "MOV BYTE [EBP-0x8], 0x72",
    "MOV BYTE [EBP-0x7], 0x6c",
    "MOV BYTE [EBP-0x6], 0x64",
    "MOV BYTE [EBP-0x5], 0x21",
    "MOV BYTE [EBP-0x4], 0x0",
]

def get_ascii(s):
    if "0x" in s and (len(s) == 3 or len(s) ==4):
        c = int(s, 16)
        if c >= 0x20 and c <= 0x7E:
            return c
        elif c == 0:
            return 0
    return -1

for i in insts:
    c = get_ascii(i.split(" ")[3])
    if c != -1:
        print chr(c)

見た目は美しくないですがとりあえずこれで"Hello World!"が出力されます。ただし、このままでは第二オペランドレジスタ(AL, DLなど...)であるサンプルに対応できないので次回はレジスタも評価するスクリプトを作成します。