動態鏈接庫(dynamic link library)介紹 代碼放到exe中,肯定會造成磁碟冗餘; 電腦ABCD四個軟體,lib加入到代碼中不是在編譯期進入的,而是在運行期 (A進程啟動,把dll加入到A進程中……),編譯的時候不需要這份代碼, 尾碼是.dll 如果要更新軟體,把dll換掉就可以了, ...
動態鏈接庫(dynamic link library)介紹
代碼放到exe中,肯定會造成磁碟冗餘; 電腦ABCD四個軟體,lib加入到代碼中不是在編譯期進入的,而是在運行期 (A進程啟動,把dll加入到A進程中……),編譯的時候不需要這份代碼, 尾碼是.dll
如果要更新軟體,把dll換掉就可以了,所有軟體都會跟著更新
分析DLL的工具
.dll中凡是能給外面用的函數叫 導出函數;
這個工具能看導出函數;
調win api的時候跟不到源碼中,因為放到了dll中了
動態庫的創建
文件導入並去掉巨集,巨集在靜態庫和動態庫表現不一致
直接編譯,生成dll文件,dll文件用工具打開, 然而並沒有導出函數顯示
導出函數
編譯之後,用工具打開發現 預設的沒有導出函數, 需要手動指定後,才導出;
就像類一樣,預設時私有的;
用編譯器命令導出
註意細節1:
兩個cpp文件中把頭文件註釋掉了,編譯之後,在工具中發現沒有導出函數,為什麼?
.h在預處理時期,預編譯時把頭文件中東西拷貝到.cpp文件中,沒有包含頭文件就沒有導出函數了
註意細節2:
再把頭文件加上,有了導出函數之後,編譯之後生成了lib; 這裡和靜態的lib有區別,這裡文件大小2kb;
這裡只是一個描述性的lib,裡面沒有代碼,這裡描述dll中有哪些導出函數,是給開發者使用的
使用dll
使用dll, 頭文件的這裡改成dllimport, 告訴編譯器這裡用的是dll中的函數;
編譯有誤,找不到函數是在哪個dll文件中;
問題: 一個.cpp 兩個.h聲明,通過這些能判斷這兩個函數要載入哪個dll嗎?
此時就用到了描述性的lib文件,拷到目錄下(類似Makefile)
和靜態的lib用法相同
編譯的時候不需要dll,運行的時候需要;這裡是運行狀態; dll拿出來放到Debug文件里
1-導出全局變數
全局變數可以導出
VS的bug: dll中的全局變數,在VS的監視視窗中看不到值
2-導出類
類可以導出
但這樣寫不能導出,報錯內容如下:
這樣寫就可以了
工具輸出的內容,上面兩個是構造還是有重載,下麵那個是自己寫的類
這個時候斷點跟源碼,能跟到自己寫的庫里,因為調試信息都放到.pdb文件里了;把這個刪了就跟不進去了;
導出和導出函數的巨集處理
這個東西,每次要用都要改,文件多了就很麻煩,用巨集給它安排下
源碼中 : 把巨集的開關放到這裡,全局的巨集放置的位置
工具里導出的都是C++的符號,如果C的呢?
隱式/顯示載入方式
隱式載入方式:
lib + .h (函數 全局變數 類 都可以用)
顯示載入方式:
Ollydebug中強大的是插件,很多的dll,使用某個功能的時候,就會去載入dll
Ollydebug發佈的時候,有沒有用人家寫的插件dll的lib和.h?沒有啊, 所以它的載入方式和這裡隱式載入方式不同,Ollydebug是顯示的載入方式;
並不知道別人寫的插件叫啥名字,是怎麼載入別人寫的dll呢?
做法: 當前路徑下的某個文件夾,遍歷文件夾下尾碼為.dll的文件,載入到進程; 這時候的載入,只要有個文件名和文件路徑就可以載入,顯示載入 (函數 全局變數 類(很麻煩))
使用dll,調用導出函數的方法(Ollydebug載入dll的做法)
載入dll(載入到進程記憶體中) -> 獲取導出函數的地址 -> 然後調用(通過函數地址的方式調用)-> 從進程中卸掉dll
01載入dll的api
參數: 的module指的是 dll / exe(主模塊) 的地址 ;
返回值: 模塊句柄和HINSTANCE兩個是等價的;
HINSTANCE是可執行文件exe在記憶體中的首地址
HMODULE是dll在記憶體中的首地址
作用: 把dll載入到進程記憶體中
code:
註意細節:
調用多個 loadLibrary, 不會調用多個dll,而是句柄引用計數的值會增加;
調用兩個loadLibrary,也要有兩個FreeLibrary才能卸載掉;
02獲取函數地址
模塊句柄還有函數名填進去,返回的就是函數地址;
code: 用的函數指針接收
註意全局變數:
如果要拿全局變數怎麼訪問? 這裡拿到的是地址
全局變數這樣訪問,指針p保存的是地址 *p訪問值
調用: 普通調用就行
一步一步調試看現象
03從進程中卸掉dll
code:
code
#include <iostream> #include <windows.h> using PFN_ADD = int(*)(int, int); int main() { HMODULE hDll = LoadLibrary(R"(C:\Users\Yuna\Desktop\CR2\windows\win01\UseDll\Debug\dll.dll)"); if (NULL == hDll) { std::cout << "載入失敗" << std::endl; return 0; } PFN_ADD pfnAdd = (PFN_ADD)GetProcAddress(hDll,"Add"); if (NULL == pfnAdd) { std::cout << "獲取函數地址失敗" << std::endl; return 0; } int nRet = pfnAdd(1,4); int i = 0; //為了調試上一句 FreeLibrary(hDll); }