"/NODEFAULTLIB"リンカオプションを使うと、標準CRTをリンクしないようになる。
サイズの小さいEXEやDLL、あるいは標準以外のCRTを使いたい場合にこのオプションを使うことになるが、 C言語系/memos/VC++/09, スタック破壊の検出・防止("/GS", "/RTC", "/GZ") で取りあげたように "/GS" オプションがデフォルトで有効になっている為、Cookie値関連のシンボルが解決出来ずリンカエラーになる場合がある。
対象:Visual C++ 2008 Express Edition, Windows XP SP3 (Japanese)
> cl Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. > link Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved.
dll.c:
#include <windows.h> int __declspec(dllexport) funcA(int a, int b) { return a + b + funcB(a, b); } int funcB(int a, int b) { return a * b; } /* int mycpy(const char *src) { char buf[20]; int i = 0; for (i = 0; i < 20; i++, src++) { buf[i] = *src; } return i; } */ BOOL WINAPI DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: MessageBox(NULL, "DLL_PROCESS_ATTACH", "dll", MB_OK); break; case DLL_PROCESS_DETACH: MessageBox(NULL, "DLL_PROCESS_DETACH", "dll", MB_OK); break; } return TRUE; }
main.c:
#include <windows.h> int __declspec(dllimport) funcA(int a, int b); /* int mycpy(const char *src) { char buf[20]; int i = 0; for (i = 0; i < 20; i++, src++) { buf[i] = *src; } return i; } */ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { int a = funcA(2, 3); MessageBox(NULL, "WinMain", "main", MB_OK); return 0; }
この時点ではまだ"/GS"によるスタック保護の対象となる"mycpy()"関数がコメントアウトされている為、Cookie値チェックのコードは埋め込まれない。
コンパイル:
> cl dll.c /LD user32.lib /link /entry:DllMain /nodefaultlib > cl main.c user32.lib dll.lib /link /entry:WinMain /nodefaultlib
ところが、コメントマークを外して"mycpy()"関数を有効にすると、Cookie値チェックのコードが埋め込まれそれにより__security_cookie, __security_check_cookieへの参照が埋め込まれる。しかし標準CRTが"/nodefaultlib"オプションによりリンクされない為、参照が解決出来ずリンカエラーとなる。
dllの場合:
dll.obj : error LNK2019: 未解決の外部シンボル ___security_cookie が関数 _mycpy で参照されました。 dll.obj : error LNK2019: 未解決の外部シンボル @__security_check_cookie@4 が関数 _mycpy で参照されました。 dll.dll : fatal error LNK1120: 外部参照 2 が未解決です。
exeの場合:
main.obj : error LNK2019: 未解決の外部シンボル ___security_cookie が関数 _mycpy で参照されました。 main.obj : error LNK2019: 未解決の外部シンボル @__security_check_cookie@4 が関数 _mycpy で参照されました。 main.exe : fatal error LNK1120: 外部参照 2 が未解決です。
もしも自分のコードに自信があれば、"/GS-"オプションを指定する。これによりCookie値チェック関連のコードが挿入されず、リンカエラーも消える。
コンパイル:
> cl dll.c /GS- /LD user32.lib /link /entry:DllMain /nodefaultlib > cl /GS- main.c user32.lib dll.lib /link /entry:WinMain /nodefaultlib
ただし "/GS" によるスタック破壊のチェックが使えなくなる為、そのセキュリティ上のデメリットを考慮して"/GS-"オプションを指定する。
参考: