0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

msvcrt.dllに依存しない実行ファイル(HelloWorld)を作る

Last updated at Posted at 2025-01-22

msvcrt.dllに依存しない実行ファイルを作ることにあまり意味はないですが、気になったためやってみました。

hello.c
void WriteFile(void *, void *, int, void *, void *);
void *GetStdHandle(int);
void f() { WriteFile(GetStdHandle(-11), "Hello,World!", 12, 0, 0); }

これがHelloWorldを表示するコードです。main関数がありませんが、その代わりにf関数から実行開始します。

$ clang hello.c -e f -nostartfiles -nostdlib -lkernel32

コンパイル時にはf関数から実行開始することを指定します。また、C言語の標準ライブラリを使用しないことを指定し、kernel32.dllを使用することを指定します。

$ ./a.exe
Hello,World!

作成された実行ファイル(a.exe)を実行すると ”Hello,World!” が表示されます。

$ objdump -d a.exe

a.exe:     file format pei-x86-64


Disassembly of section .text:

0000000140001000 <f>:
   140001000:   48 83 ec 28             sub    $0x28,%rsp
   140001004:   b9 f5 ff ff ff          mov    $0xfffffff5,%ecx
   140001009:   e8 32 00 00 00          call   140001040 <GetStdHandle>
   14000100e:   48 89 c1                mov    %rax,%rcx
   140001011:   48 8d 15 e8 0f 00 00    lea    0xfe8(%rip),%rdx        # 140002000 <__data_end__>
   140001018:   41 b8 0c 00 00 00       mov    $0xc,%r8d
   14000101e:   31 c0                   xor    %eax,%eax
   140001020:   41 89 c1                mov    %eax,%r9d
   140001023:   48 c7 44 24 20 00 00    movq   $0x0,0x20(%rsp)
   14000102a:   00 00
   14000102c:   e8 07 00 00 00          call   140001038 <WriteFile>
   140001031:   90                      nop
   140001032:   48 83 c4 28             add    $0x28,%rsp
   140001036:   c3                      ret
   140001037:   90                      nop

0000000140001038 <WriteFile>:
   140001038:   ff 25 0a 40 00 00       jmp    *0x400a(%rip)        # 140005048 <__imp_WriteFile>
   14000103e:   90                      nop
   14000103f:   90                      nop

0000000140001040 <GetStdHandle>:
   140001040:   ff 25 fa 3f 00 00       jmp    *0x3ffa(%rip)        # 140005040 <__IAT_start__>
   140001046:   90                      nop
   140001047:   90                      nop
   140001048:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
   14000104f:   00

実行ファイルの機械語は余計なコードがなく非常にシンプルです。

$ objdump -p a.exe | grep -i -E "\.dll"
        DLL Name: KERNEL32.dll

動的リンクしているDLLを確認すると、kernel32.dllのみリンクしています。
msvcrt.dllはリンクしていません。

$ strip -s a.exe

stripコマンドで実行ファイル(a.exe)から余計な情報を削除します。
そうすることで、実行ファイルは4kB程度の小さなものとなります。

WinAPIのWriteFile関数、ReadFile関数など使えば、printfやscanfなどの入出力機能、fopenやfread,fwriteなどのファイル入出力機能を実装することが可能です(浮動小数点数を文字列を変換するためにはRyuアルゴリズムなどを実装することが必要です。)
また、VirtualAllocEx関数、VirtualFreeEx関数など使えばmallocやfreeなどのメモリアロケーターを実装することが可能です(VirtualAllocEx関数である程度大きなメモリ領域を確保し、そのメモリ領域をglibcのmalloc/freeのような高速なアルゴリズムで管理するコードを自力で書く必要があります。)

頑張れば低レベルなWinAPIのみを使ってC言語標準ライブラリにある関数を自作することは可能ですが、車輪の再発明も甚だしいですね。素直にmsvcrt.dllを使えばいいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?