很多時(shí)候我們用rundll32.exe作為宿主來(lái)運(yùn)行dll的某個(gè)函數(shù),每次都是潦草的搬一段代碼完事盆昙。
這次有個(gè)dll需要導(dǎo)出給rundll32運(yùn)行的函數(shù),就先找了下資料,匯總了一下相關(guān)的知識(shí)點(diǎn)骡楼。
用法
rundll32.exe <dllname>,<entrypoint> <optional arguments>
<dllname>最好給完整路徑,且注意路徑中不能有空格稽鞭、逗號(hào)和引號(hào)鸟整,所以最好把路徑轉(zhuǎn)成短文件名來(lái)避免出現(xiàn)非法字符
<dllname>和<entrypoint>之間用,隔開(kāi),不能有空格朦蕴,<entrypoint>和<optional arguments>之間必須有空格
<optional arguments>這部分rundll32不會(huì)解析篮条,而是作為<entrypoint>的第三個(gè)參數(shù)傳遞過(guò)去
導(dǎo)出函數(shù)
我們先來(lái)看下導(dǎo)出函數(shù)的原型
void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
首先容易被忽略的一個(gè)知識(shí)點(diǎn)就是認(rèn)為導(dǎo)出函數(shù)就是上面這樣的MBCS編碼的(第三個(gè)參數(shù)可見(jiàn)),但是現(xiàn)在大多數(shù)情況下吩抓,我們都是使用Unicode編碼了涉茧,難道是因?yàn)檫@是歷史原因嗎?
當(dāng)然不是琴拧,其實(shí)是可以導(dǎo)出Unicode版本的降瞳,我們先來(lái)看下rundll32是如何找到這個(gè)導(dǎo)出函數(shù)的:
- 給函數(shù)名加上W后綴,用GetProcAddress找(可見(jiàn)首先找的就是Unicode版本)
- 如果1沒(méi)找到蚓胸,那么加上A后綴找
- 如果2也沒(méi)找到挣饥,那么就用原名字找
從上面的三個(gè)查找步驟,我們可以知道沛膳,如果我們要導(dǎo)出Unicode版本的扔枫,那么就得導(dǎo)出類(lèi)似EntryPointW這樣的函數(shù)名,且第三個(gè)參數(shù)為L(zhǎng)PWSTR锹安,然后使用的時(shí)候短荐,要用rundll32 abc.dll,EntryPoint <傳遞的命令參數(shù)>
這樣才能正確工作倚舀。
而如果導(dǎo)出函數(shù)是帶A后綴,或者不帶后綴的話(huà)忍宋,rundll32就會(huì)視為這個(gè)是MBCS編碼的導(dǎo)出函數(shù)了痕貌。
總結(jié)
從上面的描述,可以知道糠排,如果我們導(dǎo)出Unicode版本的函數(shù)舵稠,在使用的時(shí)候就要注意去掉W后綴
一旦有了這種潛規(guī)則,給別人使用的時(shí)候入宦,就很容易出問(wèn)題哺徊,所以一般情況下,還是建議導(dǎo)出不帶后綴的MBCS版本