Category Archives: 7-1.ファイル・アーカイブ

EXEファイルも直接書き換えできる?


アニメ『ヨルムンガルド』(2012)

最近ガンアクションに飢えており、既に見たアニメですがまた見てます。やはり内容を忘れてしまっているので結構楽めるし、ガンアクションにも満足です。

a.outを編集してprintfの出力を変更する」で、a.out(ELF)を直接書き換えて出力文字列を変更しましたが、WindowsのEXEファイル(PEフォーマット)も同じようなことができるでしょうか。
C#のコンパイラcscで生成したファイルを確認してみます。

使うソースはこれです。

C:\Users\takk\tmp>type t.cs
class Test
{
        static void Main()
        {
                System.Console.WriteLine("HELLO");
        }
}

C:\Users\takk\tmp>
C:\Users\takk\tmp>csc t.cs

省略

C:\Users\takk\tmp>

では、生成されたt.exeを、Linuxで確認。

takk@deb9:~/tmp$ ls -l t.exe
-rw-r--r-- 1 takk takk 3584  8月 16 17:12 t.exe
takk@deb9:~/tmp$ 

EXEファイルの先頭にはマジックナンバーMZが埋め込まれています。

takk@deb9:~/tmp$ hd t.exe | head
00000000  4d 5a 90 00 03 00 00 00  04 00 00 00 ff ff 00 00  |MZ..............|
00000010  b8 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 80 00 00 00  |................|
00000040  0e 1f ba 0e 00 b4 09 cd  21 b8 01 4c cd 21 54 68  |........!..L.!Th|
00000050  69 73 20 70 72 6f 67 72  61 6d 20 63 61 6e 6e 6f  |is program canno|
00000060  74 20 62 65 20 72 75 6e  20 69 6e 20 44 4f 53 20  |t be run in DOS |
00000070  6d 6f 64 65 2e 0d 0d 0a  24 00 00 00 00 00 00 00  |mode....$.......|
00000080  50 45 00 00 4c 01 03 00  f5 31 75 5b 00 00 00 00  |PE..L....1u[....|
00000090  00 00 00 00 e0 00 02 01  0b 01 0b 00 00 04 00 00  |................|
takk@deb9:~/tmp$ 

EXEファイル中の文字列を確認します。

takk@deb9:~/tmp$ strings t.exe -td
     77 !This program cannot be run in DOS mode.
    376 .text
    415 `.rsrc
    455 @.reloc
    616 BSJB
    632 v4.0.30319
    668 #Strings
    700 #GUID
    716 #Blob
    953 <Module>
    962 t.exe
    968 Test
    973 mscorlib
    982 System
    989 Object
    996 Main
   1001 .ctor
   1007 System.Runtime.CompilerServices
   1039 CompilationRelaxationsAttribute
   1071 RuntimeCompatibilityAttribute
   1103 Console
   1111 WriteLine
   1201 WrapNonExceptionThrows
   1282 _CorExeMain
   1294 mscoree.dll
   2259 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   2316 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   2391   <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
   2457   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
   2513     <security>
   2529       <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
   2599         <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
   2670       </requestedPrivileges>
   2700     </security>
   2717   </trustInfo>
   2733 </assembly>
takk@deb9:~/tmp$ 

HELLOがどこにもありません。プログラム中の文字列は、そのままバイナリになるわけではないようです。

念のため、grepで確認。

takk@deb9:~/tmp$ !! | grep HELLO
strings t.exe -td | grep HELLO
takk@deb9:~/tmp$ 

やはりありません。ということは、EXEファイルを書き換えて、文字列変更することはできない、ということになります。

EXEファイル中のその他のデータを書き換えることはできるでしょうか。
さきほどのstringsの一覧でファイル名らしきデータがありました。ファイル名なら書き換えても動作するかと思います。

    962 t.exe

EXEファイルに埋め込まれているt.exeをu.exeに変更してみます。

takk@deb9:~/tmp$ cp t.exe u.exe
takk@deb9:~/tmp$ echo u | dd seek=962 bs=1 count=1 conv=notrunc of=u.exe
1+0 レコード入力
1+0 レコード出力
1 byte copied, 0.000325551 s, 3.1 kB/s
takk@deb9:~/tmp$ 

差分確認。

takk@deb9:~/tmp$ cmp -l t.exe u.exe
 963 164 165
takk@deb9:~/tmp$ 

正しく変更されたようです。

では、Windowsにもどって、データを書き換えたEXEファイルが実行できるか確認してみます。

C:\Users\takk\tmp>u
HELLO

C:\Users\takk\tmp>

実行できました。
ELFだけでなくEXEファイル(PEフォーマット)の構造にも興味が沸いてきました。