exe ファイルの中にある ABCDEFG… は何なのか

exe ファイルやダンプファイルを見ていると、”ABCDEFGHIJKLMN…” といった文字列を目にすることがあります。
これは何なのでしょうか。

動作確認環境

  • Windows 11 Home 21H2
  • Visual Studio Community 2019

ABCDEFG… の文字列

何の処理もしないプログラム「ctest1.c」を書きます。

int main()
{
    return 0;
}

Visual C++ でビルドします。

C:\tmp>cl ctest1.c
......
/out:ctest1.exe
ctest1.obj

生成された「ctest1.exe」ファイルの中身を見てみます。

C:\tmp>certutil -f -encodehex ctest1.exe tmp 11
入力長 = 95232
出力長 = 442304
CertUtil: -encodehex コマンドは正常に完了しました。

C:\tmp>type tmp
......
e590	40 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f   @ABCDEFGHIJKLMNO
e5a0	50 51 52 53 54 55 56 57  58 59 5a 5b 5c 5d 5e 5f   PQRSTUVWXYZ[\]^_
e5b0	60 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f   `ABCDEFGHIJKLMNO
e5c0	50 51 52 53 54 55 56 57  58 59 5a 7b 7c 7d 7e 7f   PQRSTUVWXYZ{|}~.
......
153d0	77 78 79 7a 00 00 00 00  00 00 41 42 43 44 45 46   wxyz......ABCDEF
153e0	47 48 49 4a 4b 4c 4d 4e  4f 50 51 52 53 54 55 56   GHIJKLMNOPQRSTUV
153f0	57 58 59 5a 00 00 00 00  00 00 00 00 00 00 00 00   WXYZ............
......
15600	00 41 42 43 44 45 46 47  48 49 4a 4b 4c 4d 4e 4f   .ABCDEFGHIJKLMNO
15610	50 51 52 53 54 55 56 57  58 59 5a 00 00 00 00 00   PQRSTUVWXYZ.....
......

プログラムには書いていないのに、”ABCDEFG…” が 4 箇所に見つかります(exe ファイル内アドレス「0xe591」「0xe5b1」「0x153da」「0x15601」)。

ファイル内のアドレスからソースを探す

アドレス「0xe591」にある “ABCDEFG…” はどこから来た文字列なのでしょうか。

調査のため、マップファイル「ctest1.map」を生成しておきます(/Fm オプション)。

C:\tmp>cl /Fm ctest1.c
......
/out:ctest1.exe
/map:ctest1.map
ctest1.obj

また、exe ファイルのヘッダ情報を取得します。

C:\tmp>dumpbin /headers ctest1.exe
......
SECTION HEADER #1
   ......
     400 file pointer to raw data (00000400 to 0000C3FF)
   ......
SECTION HEADER #2
   ......
    C400 file pointer to raw data (0000C400 to 000151FF)
   ......
SECTION HEADER #3
   ......
   15200 file pointer to raw data (00015200 to 00015BFF)
   ......
SECTION HEADER #4
   ......
   15C00 file pointer to raw data (00015C00 to 000169FF)
   ......
SECTION HEADER #5
   ......
   16A00 file pointer to raw data (00016A00 to 00016BFF)
   ......
SECTION HEADER #6
   ......
   16C00 file pointer to raw data (00016C00 to 000173FF)
   ......

ヘッダ情報から、exe ファイル内のアドレス「0xe591」は、「SECTION HEADER #2」の「file pointer to raw data (0000C400 to 000151FF)」に含まれることがわかります(0xC400 <= 0xe591 <= 0x151FF)。
「セクションヘッダ #2」内でのオフセットは「0x2191」です(0xe591 – 0xC400)。

続いてマップファイル「ctest1.map」を参照し、「セクションヘッダ #2」内のオフセット「0x2191」、すなわち「0002:00002191」に何があるのか調べます。

......
0002:00001f50  __newclmap        000000014000ef50  libucrt:ctype.obj
0002:000020d0  __newcumap        000000014000f0d0  libucrt:ctype.obj
0002:00002250  ??_C@_15PJ......  000000014000f250  libucrt:get_qualified_locale.obj
......

「__newcumap」という変数(定数)の中を指しています(0002:000020d0 <= 0002:00002191 < 0002:00002250)。行末の「libucrt:ctype.obj」から、libucrt ライブラリ(マイクロソフトの C ランタイムライブラリ)内の「ctype.obj」で定義されていることもわかります

「ctype.obj」のソース「ctype.cpp」から「__newcumap」の定義を見てみます。
(私の PC では「C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\locale」内にありました。)

......
extern "C" extern unsigned char const __newcumap[384]
{
    ......
    0x41,   // 41 A
    0x42,   // 42 B
    0x43,   // 43 C
    0x44,   // 44 D
    0x45,   // 45 E
    0x46,   // 46 F
    0x47,   // 47 G
    ......

確かに、”ABCDEFG…” が定義されていました。

同様にヘッダ情報とマップファイルから探す

exe ファイル内のアドレス「0xe5b1」「0x153da」「0x15601」にある “ABCDEFG…” についても、同じように調査します。

exe ファイル内のアドレス「0xe5b1」は「セクションヘッダ #2」に含まれます(0000C400 to 000151FF)。
「セクションヘッダ #2」内でのオフセットは「0x21b1」です(0xe5b1 – 0xc400)。

マップファイルから「0002:000021b1」の場所を探すと、「ctype.obj」の「__newcumap」内であることがわかります(さきほどと同じ)。

0002:000020d0  __newcumap        000000014000f0d0  libucrt:ctype.obj

「__newcumap」の定義をあらためて見てみると、”ABCDEFG…” が 2 回定義されていました。

......
extern "C" extern unsigned char const __newcumap[384]
{
    ......
    0x41,   // 41 A
    0x42,   // 42 B
    0x43,   // 43 C
    0x44,   // 44 D
    0x45,   // 45 E
    0x46,   // 46 F
    0x47,   // 47 G
    ......
    0x41,   // 61 a
    0x42,   // 62 b
    0x43,   // 63 c
    0x44,   // 64 d
    0x45,   // 65 e
    0x46,   // 66 f
    0x47,   // 67 g
    ......

次です。

exe ファイル内のアドレス「0x153da」は「セクションヘッダ #3」に含まれます(00015200 to 00015BFF)。
「セクションヘッダ #3」内でのオフセットは「0x1da」です(0x153da – 0x15200)。

マップファイルから「0003:0000001da」の場所を探すと、「mbctype.obj」の「__acrt_initial_multibyte_data」内であることがわかります。

0003:00000060  __acrt_initial_multibyte_data  0000000140016060  libucrt:mbctype.obj

「mbctype.obj」のソース「mbctype.cpp」から「__acrt_initial_multibyte_data」の定義を見ると、確かに “ABCDEFG…”(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47…)が定義されていました。
(私の PC では「C:\Program Files (x86)\Windows Kits\10\Source\10.0.19041.0\ucrt\mbstring」内にありました。)

......
__crt_multibyte_data __acrt_initial_multibyte_data =
{
    ......
    0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
    0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
    0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00 /* rest is zero */
    ......

最後です。

exe ファイル内のアドレス「0x15601」も「セクションヘッダ #3」に含まれます(00015200 to 00015BFF)。
「セクションヘッダ #3」内でのオフセットは「0x401」です(0x15601 – 0x15200)。

マップファイルから「0003:00000401」の場所を探すと、「mbctype.obj」の「_mbcasemaps」内であることがわかります。

0003:000003a0  _mbcasemaps       00000001400163a0  libucrt:mbctype.obj

「mbctype.obj」のソース「mbctype.cpp」から「_mbcasemaps」の定義を見ると、確かに “ABCDEFG…”(0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47…)が定義されていました。

......
#define _MBCASEMAP_DEFAULT                                                      \
    {                                                                           \
        ......
        0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, \
        0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, \
        0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00 /* rest is zero */       \
    }

static unsigned char _mbcasemaps[__crt_state_management::state_index_count][256] =
{
    _MBCASEMAP_DEFAULT
    ......

“ABCDEFG…” は C ランタイムライブラリでした

予想はしていましたが、”ABCDEFG…” の実体は C ランタイムライブラリでした。

C ランタイムライブラリを exe ファイル内に抱えるのではなく、実行時に動的にリンクするよう指定すると(/MD オプション)、exe ファイル内から “ABCDEFG…” の文字が消えました。

C:\tmp>cl /MD ctest1.c

C:\tmp>certutil -f -encodehex ctest1.exe tmp 11

C:\tmp>type tmp | find "ABC"
<検索されず>

C:\tmp>type tmp | find "DEF"
<検索されず>