おさらい
アセンブルとは、アセンブリ言語をバイナリに変換すること。逆アセンブルはバイナリをアセンブリ言語に変換することである。アセンブルしたものを逆アセンブルしても完全にもとに戻るとは限らない。
アセンブリ言語で書かれたソースコードではなくバイナリを実行する。
何をするか
メモリを直接書き換えることで、出力結果を強制的に変更する。
例によってアセンブリ言語のソースコード。 アドレスから直接データを書き換えているので、文字がかわる。
"HEllo"
/ write(1, hello, 6); mov $1, r0 sys write hello 6 / r1 = hello; / *(uint16_t *)r1 = 0x4548; mov $hello, r1 mov $42510, (r1) / write(1, hello, 6); mov $1, r0 sys write hello 6 / exit(0); mov $0, r0 sys exit .data hello: <hello\n>
オレオレ逆アセンブラ
// 逆アセンブラ 7run -d write-1.out // 0000: 15c0 0001 mov $1, r0 // 0004: 8904 sys 4 ; write // 0006: 0022 ; arg // 0008: 0006 ; arg // 000a: 15c1 0022 mov $22, r1 // 000e: 15c9 4548 mov $4548, (r1) // 0012: 15c0 0001 mov $1, r0 // 0016: 8904 sys 4 ; write // 0018: 0022 ; arg // 001a: 0006 ; arg // 001c: 15c0 0000 mov $0, r0 // 0020: 8901 sys 1 ; exit let aout = System.IO.File.ReadAllBytes "write-1.out" let read16 (a:byte[]) b = (int a.[b]) ||| ((int a.[b+1]) <<< 8) let tsize = read16 aout 2 let dsize = read16 aout 4 let mem = aout.[16 .. 16 + tsize + dsize - 1] let mutable pc = 0 let show len dis = let words = [ for i in pc .. 2 .. pc + len - 1 -> sprintf "%04x" (read16 mem i) ] printfn "%04x: %-14s %s" pc (String.concat " " words) dis pc <- pc + len while pc < tsize do match read16 mem pc with | 0x15c0 -> let n = read16 mem (pc + 2) show 4 (sprintf "mov $%x, r0" n) | 0x15c1 -> let n = read16 mem (pc + 2) show 4 (sprintf "mov $%x, r1" n) | 0x15c9 -> let n = read16 mem (pc + 2) show 4 (sprintf "mov $%x, r1" n) | 0x8901 -> show 2 "sys 1 ; exit" | 0x8904 -> show 2 "sys 4 ; write" show 2 "; arg" show 2 "; arg" | _ -> show 2 "???"
正解
let aout = System.IO.File.ReadAllBytes "../../stest/write-1.out" let read16 (a:byte[]) b = (int a.[b]) ||| ((int a.[b+1]) <<< 8) let tsize = read16 aout 2 let dsize = read16 aout 4 let mem = aout.[16 .. 16 + tsize + dsize - 1] let mutable pc = 0 let show len dis = let words = [ for i in pc .. 2 .. pc + len - 1 -> sprintf "%04x" (read16 mem i) ] printfn "%04x: %-14s %s" pc (String.concat " " words) dis pc <- pc + len while pc < tsize do match read16 mem pc with | 0x15c0 -> show 4 (sprintf "mov $%x, r0" (read16 mem (pc + 2))) | 0x15c1 -> show 4 (sprintf "mov $%x, r1" (read16 mem (pc + 2))) | 0x15c9 -> show 4 (sprintf "mov $%x, (r1)" (read16 mem (pc + 2))) | 0x8901 -> show 2 "sys 1 ; exit" | 0x8904 -> show 2 "sys 4 ; write" show 2 "; arg" show 2 "; arg" | _ -> show 2 "???"