id:n7shi:20110418で告知した第4回 PE勉強会用にサンプルの準備を始めました。進捗状況は以下のリポジトリの04フォルダで確認できます。
第3回(id:n7shi:20110416)では、簡単なプログラムならC++を本格的に勉強していなくても勘で使えるだろうという希望的観測により、サンプルをC++で書きました。しかしある程度複雑になって来るとC++自体の知識が必要になります。これはC++に限らずどの言語でも事情は同じです。
今後のPE勉強会は言語を指定せずに進めたいのですが、説明のために何らかのコードの提示は必要です。とりあえずVB.NETで書きながら様子を見ます。
空ファイルを出力
まず、空の1KBのファイルを出力します。
Imports System.IO Module Module1 Dim image(&H3FF) As Byte Sub Main() Using fs = New FileStream("output.exe", FileMode.Create) fs.Write(image, 0, image.Length) End Using End Sub End Module
実行できるEXEを出力
imageの中にデータを書き込めばPEを出力できます。第3回と同じことをやるわけですが、VB.NETではWin32の構造体が定義されていないので、オフセットを指定してベタ書きします。
Imports System.IO Imports System.Text Module Module1 Dim image(&H3FF) As Byte Sub write16(pos%, v As UShort) image(pos) = v And &HFF image(pos + 1) = v >> 8 End Sub Sub write32(pos%, v%) image(pos) = v And &HFF image(pos + 1) = (v >> 8) And &HFF image(pos + 2) = (v >> 16) And &HFF image(pos + 3) = (v >> 24) And &HFF End Sub Sub write8s(pos%, ParamArray bin As Byte()) Array.Copy(bin, 0, image, pos, bin.Length) End Sub Sub writestr(pos%, s$) write8s(pos, Encoding.UTF8.GetBytes(s)) End Sub Sub Main() ' dos header writestr(0, "MZ") write16(2, &H90) write16(4, 3) write16(8, 4) write16(&HC, &HFFFF) write16(&H10, &HB8) write16(&H18, &H40) write32(&H3C, &H80) ' dos binary write8s(&H40, &HB8, 1, &H4C, &HCD, &H21) ' PE header writestr(&H80, "PE") write16(&H84, &H14C) write16(&H86, 1) write16(&H94, &HE0) write16(&H96, &H102) write16(&H98, &H10B) image(&H9A) = 10 write32(&H9C, &H200) write32(&HA8, &H1000) write32(&HAC, &H1000) write32(&HB0, &H2000) write32(&HB4, &H400000) write32(&HB8, &H1000) write32(&HBC, &H200) write16(&HC0, 5) write16(&HC2, 1) write16(&HC8, 5) write16(&HCA, 1) write32(&HD0, &H2000) write32(&HD4, &H200) write16(&HDC, 2) write16(&HDE, &H8500) write32(&HE0, &H100000) write32(&HE4, &H1000) write32(&HE8, &H100000) write32(&HEC, &H1000) write32(&HF5, &H10) ' section header writestr(&H178, ".text") write32(&H180, 1) write32(&H184, &H1000) write32(&H188, &H200) write32(&H18C, &H200) write32(&H19C, &H60000020) ' .text image(&H200) = &HC3 Using fs = New FileStream("output.exe", FileMode.Create) fs.Write(image, 0, image.Length) End Using End Sub End Module
これでは何をやっているのか非常にわかりにくいです。次回はクラスを定義して改善を図ります。