如何查看某进程调用的DLL文件

如何查看某进程调用的DLL文件,第1张

运行你想知道的

应用程序

,然后在进入

dos窗口

(开始->运行->command),输入命令:

tasklist

/m

|more

就可以看到你那个应用程序调用的

dll文件

或者

tasklist

/m

>c:\dlltxt

就把结果保存在c:\dlltxt文件里面,想怎么看就怎么看!

关于公用系统DLL的版本用API写程序,经常少不了对Windows公用组件的调用,比如打开、保存对话框、选择文件夹对话框等,都是多数程序都使用的作为打开、保存文件时的标准对话框,因为这些组件是由Windows自己提供的,除了方便,还可以让自己的程序和其它Windows程序有相同的风格,方便用户使用。但是由于这些组件是由Windows提供,随着Windows的升级、系统软件的更新,这些组件可能也被更新了,就可能出现各台计算机上文件版本不同。一般地,软件针对低版本公用系统文件的设计,在高版本中使用是没问题,但是反过来就不一定,因为可能针对高版本的设计中使用到低版本中没有的功能,所以在设计程序的时候,根据文件的版本来做适当调整是很有需要的。这一话我要向你介绍一个获得公用组件版本的办法--使用DllGetVersion()

DllGetVersion并不是一个一定可以使用的API微软在自己的新版本的公用系统DLL中使用了这个函数,但是早期版本的系统DLL中并没有,而这个函数并不是一个获得其它DLL的版本的函数,而是由DLL自己告诉你它的版本,所以你不可以把它当成一个一般API来看待。那么怎么使用它呢?为了得知要调用的DLL是否有这个函数,我找到了这个方法:用GetProcaddress()

GetProcAddress()能访问一个DLL,返回一个指定的函数的入口地址。使用这个函数,还需要另外两个API:

LoadLibrary()和 FreeLibrary()以下是声明:

Private Declare Function LoadLibrary Lib “kernel32”Alias“LoadLibraryA”(ByVal lpLibFileName As String)As LongPrivate Declare Function FreeLibrary Lib “kernel32”(ByValhLibModule As Long)As LongPrivate Declare Function GetProcAddress Lib “kernel32”(ByValhModule As Long,ByVal lpProcName As String)As Long比如你要获得 COMCTL32DLL 的版本(如果是其它系统DLL 的话,也应该每个都声明),就要按下面这样声明(虽然你不知道是否有这个函数在该DLL 中):

Private Declare Function DllGetVersion Lib “COMCTL32”(pdviAs DLLVERSIONINFO)As Long这个函数使用到了一个DLLVERSIONINFO 的用户定义类型:

Private Type DLLVERSIONINFOcbSize As LongdwMajor As LongdwMinor As LongdwBuildNumber As LongdwPlatformID As LongEnd TypeDLLVERSIONINFO 类型是由微软规定,无论你要访问哪个系统DLL,如果它有DllGetVersion 这个函数,那么它的参数也是这个类型。

接下来就可以这么做:

Dim hmod As LongDim lR As LongDim lptrDLLVersion As LongDim tDVI As DLLVERSIONINFOhmod =LoadLibrary(“comctl32dll”)If (hmod <>0)ThenlptrDLLVersion =GetProcAddress(hmod,“DllGetVersion”)If (lptrDLLVersion <>0)ThentDVIcbSize =Len(tDVI)lR =DllGetVersion(tDVI)If (lR =&H0)ThenDebugPrint “Major:”&tDVIdwMajor,“Minor:”&tDVIdwMinor,“Build:”&tDVIdwBuildNumberEnd IfElseDebugPrint “DllGetVersion Failed”

End IfFreeLibrary hmodEnd If上面这一段就是整个过程。首先用LoadLibrary把系统DLL装载进内存,如果成功就返回非0,然后对返回的句柄执行GetProcAddress,这时是在假设DLL中有DllGetVersion这个函数的情况下调用的,如果成功,GetProcAddress返回非0,如果失败(包括找不到函数),则返回0,所以我们就可以知道DllGetVersion()函数可不可以调用。

调用DllGetVersion()时,需要为DLLVERSIONINFO类型参数设置好cbSize,它告诉DLL你的参数占用多少内存。如果调用DllGetVersion成功,返回值是0,这时dwMajor、dwMinor和dwBuildNumber分别是主、副版本号和编译号,而dwPlatformID是DLL的使用平台:NT(DLLVER_PLATFORM_NT)还是WIN9X(DLLVER_PLATFORM_WINDOWS)其中,DLLVER_PLATFORM_NT值是&H2,DLLVER_PLATFORM_WINDOWS值是&H1,这是API浏览器中找不到的,记下来吧。

最后注意要用FreeLibrary把系统DLL从内存中释放,不然它将一直占用系统资源。

第十六话 最后的礼物这是《细水长流话API》的最后一节,从最早的《从消息说起》到上一期的《回调》,我们一起度过了许多时光,用到了许多可以说是使用API的必备知识,现在我们就来完成一个综合的题目,作为本次连载的压轴。

图1是大家经常看过的选择文件夹对话框,它是常用的Windows公用组件之一,当然,这里吸引你的并不只是如何显示这个对话框,还有图2,在图1的基础上为它初始化了选择的文件夹,并在上面添加了一个可以让你直接输入文件夹路径的文本框。它是怎么做的?相信这是许多人迫切想知道的。

最初我们需要用到以下的API和用户定义类型:

Public Declare Function SHBrowseForFolder Lib “shell32”(lpbiAs BrowseInfo)As LongPublic Declare Function SHGetPathFromIDList Lib “shell32”(ByValpidList As Long,ByVal lpBuffer As String)As LongPublic Type BrowseInfohWndOwner As LongpIDLRoot As LongpszDisplayName As LonglpszTitle As LongulFlags As LonglpfnCallback As LonglParam As LongiImage As LongEnd TypeSHBrowseForFolder调用shell32dll中的函数,它不同于CommonDialog等在comctldll中的函数,而是外壳函数,主要执行系统已经存在的一些功能。我很愿意向你逐一解释BrowseInfo的所有成员的作用,但是我觉得已经没有必要了,因为你已经学到了这里,是时候自己领悟一下了,所以我只说明示例中我认为需要说明的:

hWndOwner 设置所属窗体句柄,它将一直在该窗体之上lpszTitle 指向标题的指针ulFlags 设置对话框的参数,例如:

BIF_BROWSEFORCOMPUTER 只返回计算机,选择其它文件夹将无法点击确定按钮BIF_BROWSEFORPRINTER 只返回打印,选择其它文件夹将无法点击确定按钮BIF_EDITBOX 添加一个输入路径的文本框,需要shell32dll 版本在471 以上BIF_RETURNONLYFSDIRS 只返回本系统的文件夹,选择的文件夹如果不在本机,将无法点击确定按钮BIF_DONTGOBELOWDOMAIN 不显示网络文件夹我需要说明lpszTitle应如何使用。一般情况下,你可以通过我以前讲的办法给它传递一个字符串的指针,但是你马上会发现,假如你正确的使用StrPtr(“Look!”),你却得到了错误的结果:只有一个“L”字母。更糟的是,如果你使用中文,它显示的是一堆乱码。

这是为什么?我说过,Windows9x和部分Windows NT的API使用ANSI字符集,但是VB使用UNICODE这个情况下,“Look!”在内存中表示成16进制是6C 00 6F 00 6F 00 21 00,API用NULL(即0)表示字符串结束,这就是原因,所以我们需要找一个让lpszTitle指向ANSI字符集的办法。

你可能见过一些人(包括许多国外程序员写的示例)使用这样一种方法:lstrcat(“Look!”,“”),没错,lstrcat把两个字符串连接起来,并返回指针,因为字符串传递给API时已经由VB转换为ANSI字符了,所以它看起来似乎没问题。但是我要建议你不要这样做,因为它可以让你的指针成为无效指针,不信你试试在它返回指针之后,先用DebugPrint打印一次指针(或用其它方法访问这个变量一次)后再使用这个指针,你的指针的返回结果会变成没用的。那么你应该怎么做呢?

Dim szTitle() As ByteszTitle=StrConv(“Look!”,vbFromUnicode)lpszTitle=VarPtr(szTitle(0))上面就是我的办法。我用数组存放,并用StrConv把字符串转换为ANSI的。

在设置好所需要的值给BrowseInfo类型的变量后,就可以调用SHBrowseForFolder了。当选择对话框显示过后(你按了“确定”或“取消”),SHBrowseForFolder会返回一个值(取消则返回0),它又是一个指针,这个指针指向你选择的路径,不过不要试图用CopyMemory把这个指针指向的内容当成字符串般复制下来,你应该使用SHGetPathFromIDList取回(类似函数我已经讲过使用方法,这里不再说明)

用这种方法调用的对话框,就如图1,如果你需要初始化路径,那么你要用到回调。lpfnCallback就是指向函数入口的指针。不过不幸的是,AddressOf是关键字,所以你无法把AddressOf得到的值直接赋给变量,怎么办?

Public Function MyAddressOf(AddressOfX As Long)AsLongMyAddressOf =AddressOfXEnd Function上面是MyAddressOf 函数,我们变通一下,把AddressOf 的得到的值传递给自己的一个函数,再由这个函数返回AddressOf 的结果。通过MyAddressOf(AddressOf functionA)就可以得到 AddressOf functionA 的结果了。

那么接下来是SHBrowseForFolder 所要求的回调函数的形式:

Public Function BrowseForFoldersProc(ByVal hWnd As Long,ByVal uMsg As Long,ByVal lParam As Long,ByVal lpData AsLong)As LonghWnd 是对话框的句柄,uMsg 是消息,lParam 随着uMsg 的不同,有时有作用,有时没有,而lpData,如以前所说过的一些回调函数,也是由你的程序来定,API把它传给回调函数,与之相对应的是BrowseInfo 中的lParam

这个回调函数在浏览文件夹对话框发送不同消息时被调用,BFFM_INITIALIZED 消息在对话框初始化完成时被发送,在这个时候,我们就可以为对话框设置选择哪个文件夹:用 SendMessage

SendMessage hWnd,BFFM_SETSELECTIONA,1,ByVallpData我事先为BrowseInfo 类型变量中的lParam 设置好要初始化的文件夹的路径(ANSI 的),当回调函数被调用并且是发生BFFM_INITIALIZED 消息时,我向对话框发送BFFM_SETSELECTIONA 消息,使对话框选择某个文件夹。当然如果你不使用lpData,你也可以在要发送时再把路径的指针作为参数发送,它们没什么不同的。

最后,如果API 成功返回了一个路径,我建议你调用一下CoTaskMemFree:

Public Declare Sub CoTaskMemFree Lib “ole32dll”(ByValhMem As Long)CoTaskMemFree 的参数是指向一段内存的指针,由于SHBrowseForFolder 返回了一个指向路径的指针,即是说它可能在内存中保留了一部分资源,CoTaskMemFree则可以把这资源回收。虽然如果你不这么做可能不会马上发现问题,但是小心一点总是好的。

好了,除去声明,我把我的整个调用过程列出如下:

Const MAX_PATH =260Dim lpIDList As LongDim sBuffer As StringDim tBrowseInfo As BrowseInfoDim szTitle()As ByteDim sPath()As ByteszTitle =StrConv(“你要选择哪个文件夹?”&vbNullChar,vbFromUnicode)sPath =StrConv(“C:\ ”&vbNullChar,vbFromUnicode)With tBrowseInfohWndOwner =MehWndlpszTitle =VarPtr(szTitle(0))ulFlags =BIF_RETURNONLYFSDIRS OrBIF_DONTGOBELOWDOMAIN Or BIF_EDITBOXl p f n C a l l b a c k =M y A d d r e s s O f (A d d r e s s OfBrowseForFoldersProc)lParam =VarPtr(sPath(0))End WithlpIDList =SHBrowseForFolder(tBrowseInfo)If (lpIDList)ThensBuffer =Space(MAX_PATH)SHGetPathFromIDList lpIDList,sBufferCoTaskMemFree lpIDListsBuffer =Left(sBuffer,InStr(sBuffer,vbNullChar)-1)MsgBox sBufferEnd If以下是标准模块中的回调函数:

Public Function BrowseForFoldersProc(ByVal hWnd As Long,ByValuMsg As Long,ByVal lParam As Long,ByVal lpData As Long)As LongSelect Case uMsgCase BFFM_INITIALIZEDSendMessage hWnd,BFFM_SETSELECTIONA,1&,ByVallpDataCase BFFM_SELCHANGED'Selection changedEnd SelectEnd Function注意看我使用字符串的那两个地方,记得结尾加上vbNullChar 以表示字符串结束。

好了,关于这一个的内容我就只讲这么多,有不明白的地方,可以参考上面我的调用过程。一些地方我没有讲,我相信你已经有能力自己进一步去探讨了。关于这个对话框的更复杂的使用,我想MSDN 应该是最好的辅助工具书了。

由于API 浏览器中查不到我给出的常量的值,所以我把这个API 常用到的一些值帮你列在下面:

浏览文件夹的常量:

BIF_RETURNONLYFSDIRS =1BIF_DONTGOBELOWDOMAIN =2BIF_STATUSTEXT =4BIF_RETURNFSANCESTORS =8BIF_EDITBOX =&H10BIF_VALIDATE =&H20BIF_BROWSEFORCOMPUTER =&H1000BIF_BROWSEFORPRINTER =&H2000BIF_BROWSEINCLUDEFILES =&H4000对话框发出的消息:

BFFM_INITIALIZED =1BFFM_SELCHANGED =2BFFM_VALIDATEFAILEDA =3BFFM_VALIDATEFAILEDW =4发给对话框的消息:

WM_USER =&H400BFFM_SETSTATUSTEXTA =(WM_USER +100)BFFM_ENABLEOK =(WM_USER +101)BFFM_SETSELECTIONA =(WM_USER +102)BFFM_SETSELECTIONW =(WM_USER +103)BFFM_SETSTATUSTEXTW =(WM_USER +104)第十七话 再见很高兴你一直看到这里,但愿我在这次连载中没有出什么大差错。我也相信你开始喜欢上了API API 可以帮助VB 完成许多别人认为不可能的事情。我不禁又要提起自己的NaviEdit,不仅我用它赚钱(笑),我更重视的是,它是我从初次接触API 到熟练使用API 的见证。例如正当许多人正不知从何入手制作Office XP 风格的菜单的时候,我在去年年末就用VB 为NaviEdit 写出了这种风格的菜单(见图3),我靠的是API,同时也是靠一系列的方法。是谁说VB 就不好呢?我就很喜欢用。如果你想得心应手的使用VB,那么API 是必不可少的。虽然关于GDI 方面,我未能在本次连载中讲到,但我相信你已经有独立进入更深一层研究的坚实基础。记住这些基础,继续学习,并应用到实际中去,加油吧!再见!

当你运行的程序正在调用某个dll文件时,正在使用的文件是当然不可能给你删除的。一般会提示:另一个程序正在使用此文件 or 拒绝访问等那么,到底是哪个程序在调用这个dll文件呢。一个方法可以把那个程序很容易的找出来。。在运行里输入cmd进入命令提示符。然后输入命令:tasklist /mc:\123txt不要急。到C盘下面去找一找,是不是有了一个123txt?(当然。你可以自己设定文件的输出路径,名字,甚至后缀。但要是文本文件哦。。)打开他。里面就是目前运行的各个程序正在调用的dll文件。找出来了后问题就好办多了。打开任务管理器。把对应的那个程序给关了。。就可以顺利删除了。。那就不必进安全模式,进DOS那么麻烦了。。。当然。有些应用程序是以服务形式运行的。那么你就有可能查到的是svhostexe但是。里面有很多个哦。。这个也好办。仍然打开命令提示符。输入tasklist /svc,当然,你也可以把他输出为文本文件,如tasklist /svcC:\234txt。看到了吗?每个svchostexe后面是不是对应有一个ID呢?有了ID一对照也可以知道是哪个服务了。。如果是可关的。就关了他。。不过记住。。系统进程可别乱关哦。

关键的问题是你是需要DLL在目标进程中的基址,而且你自己的写的程序并没有加载那个DLL,所以你总是得到0,所以你需要把自己的程序注入到进程中,才能得到你所要的DLL在目标进程中的基地址。

DLL注入比较常用的方法是利用OpenProcess得到目标进程的句柄,然后利用CreateRemoteThread调用LoadLibrary函数,加载你自己的DLL,在这个DLL的DLLMain里面遍历所有的DLL找到你想要的。这个程序在网上很多,你自己Google就可以找得到了。

HMODULE hModule = GetModuleHandle(_T("bdll")); // 获取bdll句柄

MODULEINFO mi;

GetModuleInformation(NULL, hModule, &mi, sizeof(MODULEINFO)); // 获取bdll信息

// milpBaseOfDll就是bdll的加载起始地址

实例句柄这个东西,MSDN说了,就是加载进程映像的基址,每个进程都是一样的,你得到其他的进程也在你自己的进程里用不了。比如,你建立任何一个进程,GetModuleHandle(NULL)函数返回的就是进程的实例句柄,一般都是0x400000(可能少写或多写了一个0)。所以,要得到一个进程的路径,只有一个方法,把自己的代码注入到目标进程的地址空间中,在被注入的代码中使用GetMoudleFileName(GetModuleHandle(NULL),szModPath,MAX_PATH)来得到这个进程的所在路径。

这就涉及到注入进程这个有意思的东西了。简单而易用的方法,就是用《Windows核心编程》中提到的方法,用创建远程线程来把自己的DLL注入到目标进程的方法来实现。创建远程线程用CreateRemoteThread(),很简单,与CreateThread()使用方法一样,只不过多出的第一个参数是目标进程句柄(记住,要有PROCESS_CREATE_THREAD权限),其他的参数,都要是在目标进程的地址空间中的。

基本的流程应该是:

用OpenProcess()函数打开目标进程,权限要有PROCESS_CREATE_THREAD,PROCESS_VM_READ,PROCESS_VM_WRITE。然后用VirtualAllocEx函数在目标进程中分配一个内存空间,这个空间要保存你的Dll文件的路径,然后用WriteProcessMemory把这个字符串写入,再用GetProcAddress得到LoadLibraryA函数的地址,当然得到的地址是自己进程地址空间中的地址,但一般情况下绝大部分进程的这个地址处都是同样的LoadLibraryA函数。利用得到的在目标进程中分配的内存的地址及LoadLibraryA函数,就可以利用创建远程线程的方法把自己的DLL文件注入进去。

只有把自己的代码注入到目标进程中,你才可能利用GetModuleFileName函数得到目标进程的路径。当然这个工作是由已经注入到目标进程中的DLL来做。

使用腾讯电脑管家修复下,打开腾讯电脑管家找到“工具箱”然后“电脑诊所”在搜索栏中搜(dll组件)然后找到遇到的问题选择立即修复就可以了。 腾讯电脑管家,是腾讯公司推出的一款免费安全软件, 能有效预防和解决计算机上常见的安全风险。

以上就是关于如何查看某进程调用的DLL文件全部的内容,包括:如何查看某进程调用的DLL文件、VB 如何获得DLL导出函数在其他进程中的地址、查找dll被什么程序正在调用的方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9598515.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存