DLL
dll建立的時候必須在linker加上 /DLL 讓OS知道
address space分兩種
inplicit load-time &
DLL & process addr space
DLL function looks at a threads stack to retrieve its passed parameter and use thread stack for any local variable that it needs.
common error:
有些是c++ runtime而非dll ,在free的時候要注意
VOID EXEFunc() {
PVOID pv = DLLFunc();
// Access the storage pointed to by pv...
// Makes no assumptions about C/C++ run-time heap
DLLFreeFunc(pv);
}
PVOID DLLFunc() {
// Allocate block from DLL's C/C++ run-time heap
PVOID pv = malloc(100);
return(pv);
}
BOOL DLLFreeFunc(PVOID pv) {
// Free block from DLL's C/C++ run-time heap
return(free(pv));
}
__declspec(dllexport)
會把dll內的function列出,產生.rba檔去對照位置
When the DLL is linked, the linker detects this embedded information about the exported variable, function, or class and automatically produces a .lib file. This .lib file contains the list of symbols exported by the DLL. This .lib file is, of course, required to link any executable module that references this DLL's exported symbols. In addition to creating the .lib file, the linker embeds a table of exported symbols in the resulting DLL file. This export section contains the list (in alphabetical order) of exported variables, functions, and class symbols. The linker also places the relative virtual address (RVA), indicating where each symbol can be found in the DLL module.
Using the Microsoft Visual Studio DumpBin.exe utility (with the -exports switch), you can see what a DLL's export section looks like. The following is a fragment of Kernel32.dll's export section. (I've removed some of DUMPBIN's output so that it won't occupy too many pages in this book.)
C:\Windows\System32>DUMPBIN -exports Kernel32.DLL
Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file Kernel32.DLL
File Type: DLL
Section contains the following exports for KERNEL32.dll
00000000 characteristics
4549AD66 time date stamp Thu Nov 02 09:33:42 2006
0.00 version
1 ordinal base
1207 number of functions
1207 number of names
ordinal hint RVA name
3 0 AcquireSRWLockExclusive (forwarded to
NTDLL.RtlAcquireSRWLockExclusive)
4 1 AcquireSRWLockShared (forwarded to
NTDLL.RtlAcquireSRWLockShared)
5 2 0002734D ActivateActCtx = _ActivateActCtx@8
6 3 000088E9 AddAtomA = _AddAtomA@4
7 4 0001FD7D AddAtomW = _AddAtomW@4
8 5 000A30AF AddConsoleAliasA = _AddConsoleAliasA@12
9 6 000A306E AddConsoleAliasW = _AddConsoleAliasW@12
10 7 00087935 AddLocalAlternateComputerNameA =
_AddLocalAlternateComputerNameA@8
11 8 0008784E AddLocalAlternateComputerNameW =
_AddLocalAlternateComputerNameW@8
12 9 00026159 AddRefActCtx = _AddRefActCtx@4
13 A 00094456 AddSIDToBoundaryDescriptor =
_AddSIDToBoundaryDescriptor@8
...
1205 4B4 0004328A lstrlen = _lstrlenA@4
1206 4B5 0004328A lstrlenA = _lstrlenA@4
1207 4B6 00049D35 lstrlenW = _lstrlenW@4
Summary
3000 .data
A000 .reloc
1000 .rsrc
C9000 .text
As you can see, the symbols are in alphabetical order and the numbers under the RVA column identify the offset in the DLL file image where the exported symbol can be found. The ordinal column is for backward compatibility with 16-bit Windows source code and should not be used in modern-day applications. The hint column is used by the system to improve performance and is not important for our discussion.
Delay load Dll
delayLoadInfo會在意外產生的時候產生, 會告訴你dll name跟function name
可藉由此結構知道錯誤在哪裡
或者用DelaoLoadDllExceptionFilter, 可用getExceptioninformation拉資料
他會取得資料丟到delayLoadinfo結構, 判斷例外種類做處理(dll不見或是function沒有)
可以在不用時候 unload, 在linker內做設定 support unload
呼叫unload delay load的時候,要確定你有設定他為delay load不然會找不到dll
請一組使用
使用上路徑必須有case sensitive, 且不得有path
free lib也會幫你處理, 請勿自行來
如何掌握delay load的進度?
在delayImp.lib內定義兩個全域變數, 可觀察進度跟失敗
Windows Via C/C++ - Books24x7
PfnDliHook __pfnDliNotifyHook2 = DliHook;
PfnDliHook __pfnDliFailureHook2 = DliHook;
DliHook是你的function, 會不停地幫你callback進去
裡面可以判斷每個狀況
case dliStartProcessing:
case dliNotePreLoadLibrary:
case dliFailLoadLib:
case dliNotePreGetProcAddress
case dliFailGetProc:
case dliNoteEndProcessing:
Forwarding
Windows Via C/C++ - Books24x7
C:\Windows\System32
>
DumpBin -Exports Kernel32.dll
(some output omitted)
75 49 CloseThreadpoolIo (forwarded to NTDLL.TpReleaseIoCompletion)
76 4A CloseThreadpoolTimer (forwarded to NTDLL.TpReleaseTimer)
77 4B CloseThreadpoolWait (forwarded to NTDLL.TpReleaseWait)
78 4C CloseThreadpoolWork (forwarded to NTDLL.TpReleaseWork)
(remainder of output omitted)
後面才是真正用的dll & function
用法:
You can take advantage of function forwarders in your DLL module as well. The easiest way to do this is by using a pragma directive, as shown here:
// Function forwarders to functions in DllWork
#pragma comment(linker, "/export:SomeFunc=DllWork.SomeOtherFunc")
已知的DLL:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
Value name: SomeLib
Value data: SomeOtherLib.dll
如果今天用loadLibrary, 檔案名稱如果有副檔名, 會先用檔名去reg內搜尋
LoadLibrary(TEXT("SomeLib.dll"));
假如沒有, 就會依照原本的規則: 檔案目錄, 系統目錄
LoadLibrary(TEXT("SomeLib"));
Dll redirect:
建議大家再肚子裡放.exe.local , 但預設是關著的
SuperApp.exe.local.
Rebased modules
可執行黨: 0x00400000
dll module: 0x10000000
假如用到兩個dll, 位置會重疊,所以如何錯開?
在多個module下要指定不同的base adr, 可以在link底下的base address自行設定
也可以用tool幫忙, rebase.exe
他會先模擬module load進來後的情況. 需要給base adr跟大小, 就會幫你錯開並更改machine code, 就要更新每個header file
例如: 我要load兩個dll, 兩人prefer base adr相同, 用tool把兩者load近來,錯開
再把machine code改掉, 回存
建議在安裝的時候做處理
在vista以後已被修改
https://en.wikipedia.org/wiki/Security_and_safety_features_new_to_Windows_Vista#Preventing_exploits
"Starting with Windows Vista, Microsoft implemented Address Space Layout Randomization
which moves the system DLLs around every time you load them, and optionally the user DLLs as well."
https://blogs.msdn.microsoft.com/oldnewthing/20170118-00/?p=95205
Bind.exe
RVA: 每個的offset 在寫回file name, 讓loading的時候不用重新計算
效果會如下面這段, 可在初始化的時候避免消耗資源
Bound to SHELL32.dll [4549BDB4] Thu Nov 02 10:43:16 2006
Bound to ADVAPI32.dll [4549BCD2] Thu Nov 02 10:39:30 2006
Bound to OLEAUT32.dll [4549BD95] Thu Nov 02 10:42:45 2006
Bound to ole32.dll [4549BD92] Thu Nov 02 10:42:42 2006
Bound to ntdll.dll [4549BDC9] Thu Nov 02 10:43:37 2006
Bound to KERNEL32.dll [4549BD80] Thu Nov 02 10:42:24 2006
Bound to GDI32.dll [4549BCD3] Thu Nov 02 10:39:31 2006
Bound to USER32.dll [4549BDE0] Thu Nov 02 10:44:00 2006
Bound to msvcrt.dll [4549BD61] Thu Nov 02 10:41:53 2006