DLL にはエクスポート関数やエクスポート変数に実態をもたせないで、別の DLL に転送する機能があります。以下は dumpbin.exe で XP の KERNEL32.DLL の転送されているエクスポート一覧を表示したものです。
C:\>dumpbin.exe /exports c:\windows\system32\kernel32.dll | grep forwarded 9 8 AddVectoredExceptionHandler (forwarded to NTDLL.RtlAddVectoredExceptionHandler) 122 79 DecodePointer (forwarded to NTDLL.RtlDecodePointer) 123 7A DecodeSystemPointer (forwarded to NTDLL.RtlDecodeSystemPointer) 128 7F DeleteCriticalSection (forwarded to NTDLL.RtlDeleteCriticalSection) 147 92 EncodePointer (forwarded to NTDLL.RtlEncodePointer) 148 93 EncodeSystemPointer (forwarded to NTDLL.RtlEncodeSystemPointer) 151 96 EnterCriticalSection (forwarded to NTDLL.RtlEnterCriticalSection) 361 168 GetLastError (forwarded to NTDLL.RtlGetLastWin32Error) 515 202 HeapAlloc (forwarded to NTDLL.RtlAllocateHeap) 521 208 HeapFree (forwarded to NTDLL.RtlFreeHeap) 525 20C HeapReAlloc (forwarded to NTDLL.RtlReAllocateHeap) 527 20E HeapSize (forwarded to NTDLL.RtlSizeHeap) 536 217 InitializeSListHead (forwarded to NTDLL.RtlInitializeSListHead) 541 21C InterlockedFlushSList (forwarded to NTDLL.RtlInterlockedFlushSList) 543 21E InterlockedPopEntrySList (forwarded to NTDLL.RtlInterlockedPopEntrySList) 544 21F InterlockedPushEntrySList (forwarded to NTDLL.RtlInterlockedPushEntrySList) 577 240 LeaveCriticalSection (forwarded to NTDLL.RtlLeaveCriticalSection) 653 28C QueryDepthSList (forwarded to NTDLL.RtlQueryDepthSList) 695 2B6 RemoveVectoredExceptionHandler (forwarded to NTDLL.RtlRemoveVectoredExceptionHandler) 703 2BE RestoreLastError (forwarded to NTDLL.RtlRestoreLastWin32Error) 705 2C0 RtlCaptureContext (forwarded to NTDLL.RtlCaptureContext) 706 2C1 RtlCaptureStackBackTrace (forwarded to NTDLL.RtlCaptureStackBackTrace) 707 2C2 RtlFillMemory (forwarded to NTDLL.RtlFillMemory) 708 2C3 RtlMoveMemory (forwarded to NTDLL.RtlMoveMemory) 709 2C4 RtlUnwind (forwarded to NTDLL.RtlUnwind) 710 2C5 RtlZeroMemory (forwarded to NTDLL.RtlZeroMemory) 759 2F6 SetCriticalSectionSpinCount (forwarded to NTDLL.RtlSetCriticalSectionSpinCount) 788 313 SetLastError (forwarded to NTDLL.RtlSetLastWin32Error) 853 354 TryEnterCriticalSection (forwarded to NTDLL.RtlTryEnterCriticalSection) 872 367 VerSetConditionMask (forwarded to NTDLL.VerSetConditionMask)
.def ファイルにエクスポート名と転送先を記述するだけで作れます。
forward.def
LIBRARY FORWARD EXPORTS MessageBoxW = USER32.MessageBoxW
forward.cpp
#include <windows.h> #pragma comment(linker, "/nodefaultlib") extern "C" BOOL WINAPI _DllMainCRTStartup(HMODULE, DWORD, void*) { return TRUE; }
C:\>cl forward.cpp forward.def /link user32.lib Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.10.6030 for 80x86 Copyright (C) Microsoft Corporation 1984-2002. All rights reserved. forward.cpp Microsoft (R) Incremental Linker Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. /out:forward.exe user32.lib /def:forward.def forward.obj ライブラリ forward.lib とオブジェクト forward.exp を作成中 C:\>dumpbin /exports forward.dll Microsoft (R) COFF/PE Dumper Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file forward.dll File Type: DLL Section contains the following exports for FORWARD.dll 00000000 characteristics 4A4C612C time date stamp Thu Jul 02 16:26:36 2009 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 MessageBoxW (forwarded to USER32.MessageBoxW) Summary 1000 .rdata 1000 .reloc 1000 .textコンパイルは古めの VS 2003 でやってます。出来上がった forward.lib を user32.lib の代わりにリンクすると USER32.dll からではなく FORWARD.dll から MessageBoxW をインポートする実行可能ファイルの出来上がりです。
forward.def
LIBRARY FORWARD EXPORTS MessageBoxW = USER32.MessageBoxW @200 NONAME GetModuleHandleA = KERNEL32.GetModuleHandleA @202 NONAME GetStartupInfoA = KERNEL32.GetStartupInfoA @203 NONAME GetCommandLineA = KERNEL32.GetCommandLineA @204 NONAME GetVersionExA = KERNEL32.GetVersionExA @205 NONAME ExitProcess = KERNEL32.ExitProcess @206 NONAME GetProcAddress = KERNEL32.GetProcAddress @207 NONAME TerminateProcess = KERNEL32.TerminateProcess @208 NONAME GetCurrentProcess = KERNEL32.GetCurrentProcess @209 NONAME WriteFile = KERNEL32.WriteFile @210 NONAME GetStdHandle = KERNEL32.GetStdHandle @211 NONAME GetModuleFileNameA = KERNEL32.GetModuleFileNameA @212 NONAME UnhandledExceptionFilter = KERNEL32.UnhandledExceptionFilter @213 NONAME FreeEnvironmentStringsA = KERNEL32.FreeEnvironmentStringsA @214 NONAME GetEnvironmentStrings = KERNEL32.GetEnvironmentStrings @215 NONAME FreeEnvironmentStringsW = KERNEL32.FreeEnvironmentStringsW @216 NONAME WideCharToMultiByte = KERNEL32.WideCharToMultiByte @217 NONAME GetLastError = KERNEL32.GetLastError @218 NONAME GetEnvironmentStringsW = KERNEL32.GetEnvironmentStringsW @219 NONAME SetHandleCount = KERNEL32.SetHandleCount @220 NONAME GetFileType = KERNEL32.GetFileType @221 NONAME HeapDestroy = KERNEL32.HeapDestroy @222 NONAME HeapCreate = KERNEL32.HeapCreate @223 NONAME VirtualFree = KERNEL32.VirtualFree @224 NONAME HeapFree = KERNEL32.HeapFree @225 NONAME LoadLibraryA = KERNEL32.LoadLibraryA @226 NONAME GetACP = KERNEL32.GetACP @227 NONAME GetOEMCP = KERNEL32.GetOEMCP @228 NONAME GetCPInfo = KERNEL32.GetCPInfo @229 NONAME HeapAlloc = KERNEL32.HeapAlloc @230 NONAME VirtualAlloc = KERNEL32.VirtualAlloc @231 NONAME HeapReAlloc = KERNEL32.HeapReAlloc @232 NONAME RtlUnwind = KERNEL32.RtlUnwind @233 NONAME InterlockedExchange = KERNEL32.InterlockedExchange @234 NONAME VirtualQuery = KERNEL32.VirtualQuery @235 NONAME HeapSize = KERNEL32.HeapSize @236 NONAME QueryPerformanceCounter = KERNEL32.QueryPerformanceCounter @237 NONAME GetTickCount = KERNEL32.GetTickCount @238 NONAME GetCurrentThreadId = KERNEL32.GetCurrentThreadId @239 NONAME GetCurrentProcessId = KERNEL32.GetCurrentProcessId @240 NONAME GetSystemTimeAsFileTime = KERNEL32.GetSystemTimeAsFileTime @241 NONAME LCMapStringA = KERNEL32.LCMapStringA @242 NONAME MultiByteToWideChar = KERNEL32.MultiByteToWideChar @243 NONAME LCMapStringW = KERNEL32.LCMapStringW @244 NONAME GetStringTypeA = KERNEL32.GetStringTypeA @245 NONAME GetStringTypeW = KERNEL32.GetStringTypeW @246 NONAME GetLocaleInfoA = KERNEL32.GetLocaleInfoA @247 NONAME VirtualProtect = KERNEL32.VirtualProtect @248 NONAME GetSystemInfo = KERNEL32.GetSystemInfo @249 NONAME IsBadWritePtr = KERNEL32.IsBadWritePtr @250 NONAME
test.cpp
#include <windows.h> #pragma comment(linker, "/nodefaultlib:kernel32.lib") #pragma comment(lib, "forward.lib") int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { return MessageBoxW(NULL, L"world!", L"Hello", MB_OK); }
C:\>dumpbin /imports test.exe Microsoft (R) COFF/PE Dumper Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file test.exe File Type: EXECUTABLE IMAGE Section contains the following imports: FORWARD.dll 405000 Import Address Table 405D50 Import Name Table 0 time date stamp 0 Index of first forwarder reference Ordinal 200 Ordinal 202 Ordinal 203 Ordinal 204 Ordinal 205 Ordinal 206 Ordinal 207 Ordinal 208 Ordinal 209 Ordinal 210 Ordinal 211 Ordinal 212 Ordinal 213 Ordinal 214 Ordinal 215 Ordinal 216 Ordinal 217 Ordinal 218 Ordinal 219 Ordinal 220 Ordinal 221 Ordinal 222 Ordinal 223 Ordinal 224 Ordinal 225 Ordinal 226 Ordinal 227 Ordinal 228 Ordinal 229 Ordinal 230 Ordinal 231 Ordinal 232 Ordinal 233 Ordinal 234 Ordinal 235 Ordinal 236 Ordinal 237 Ordinal 238 Ordinal 239 Ordinal 240 Ordinal 241 Ordinal 242 Ordinal 243 Ordinal 244 Ordinal 245 Ordinal 246 Ordinal 247 Ordinal 248 Ordinal 249 Summary 1000 .data 1000 .rdata 4000 .text何をインポートしているか分からない EXE の出来上がり。逆アセンブラでも転送先をおっかけてまで表示するようなものはなかなかないようです。OllyDbg では IAT やコードから判断するのでばれちゃいますけどね。あとは forward.dll のエクスポートを列挙して一つ一つ序数とかけあわせれば何をインポートしているかは分かりますが面倒です。