操作被占用的文件unlocker机理分析.docx
《操作被占用的文件unlocker机理分析.docx》由会员分享,可在线阅读,更多相关《操作被占用的文件unlocker机理分析.docx(18页珍藏版)》请在冰点文库上搜索。
操作被占用的文件unlocker机理分析
操作被占用的文件-unlocker机理分析
====================================================================
以下为转帖
操作被占用的文件-unlocker机理分析
*[标题]:
操作被占用的文件-unlocker机理分析
*[作者]:
gz1X[gz1x(at)tom(dot)com]
EagleNet[hklt594(at)163(dot)com]
*[来自]:
中国黑客联盟[CHU]
*[原始链接]:
http:
//blog.china-
[前言]
——————————————————————
之前给原作者发过邮件,不过没能得到unlocker的源代码,所以自己逆向了一份;
逆向的很匆忙,因为近来事情太多,而且unlocker本身也是版权所有,所以不好做的太露骨;
本人也还有不少地方不是很明白,有机会和我联系,一起探讨:
-)
感谢EagleNet的讨论.
[关于unlocker]
——————————————————————
Unlocker是一个免费的工具,原作者的网站是:
http:
//ccollomb.free.fr/unlocker
当使用者发现有某个文件或目录无法删除时,只要按下鼠标右键中的"Unlocker",
程序会显示出是哪一些程序占用了该目录或文件,接着只要按下"Unlock"就能够为你的文件解锁.
==============================Herewestart=================================
[大致流程]
——————————————————————
主程序Unlocker.exe通过ZwQuerySystemInformation查询当前系统的所有句柄信息,然后调用OpenProcess获取目标进程句柄,遍历当前所有进程,根据进程ID,得到此进程打开的所有句柄信息,接下来用DuplicateHandle复制Handle到本地进程,然后把文件句柄发给驱动UnlockerDriver5.sys进行名字的查询,sys将返回文件句柄对应的内核文件对象的完整名字.确定文件名后,如果要删除文件,则调用OpenProcess与DuplicateHandle关闭句柄,然后ZwDeleteFile删除文件.
[UnlockerAssistant.exe]
[UnlockerHook.dll]
——————————————————————
UnlockerAssistant.exe主要是实现系统托盘等辅助功能,同时安装钩子:
.text:
00403AC9 publicstart
.text:
00403AC9start:
//...
.text:
00403AD5 call sub_40391E
跟进,能看到主要的实现代码:
.text:
00403925 call sub_402E83
//...
.text:
00403944 push offsetLibFileName;"UnlockerHook.dll"
.text:
00403949 call ds:
LoadLibraryA
//...
.text:
0040398A push offsetProcName;"HookInstall"
.text:
00403994 call edi;GetProcAddress
注册窗口消息,初始化控件,安装钩子;
.text:
00403A1A call ds:
Shell_NotifyIconA
.text:
00403A20 call sub_40359E ;RegOpenKeyExA...
设置托盘图标,写入注册表启动项;
.text:
00403A69 push offsets_Hookuninstall;"HookUninstall"
卸载钩子.
当然也有绿化版本只写入右键,这些大家自己看反汇编的代码,详细的钩子过程反汇编UnlockerHook.dll,也不再做纠缠.
我们只看UnlockerHook.dll里一处:
.text:
10001102sub_10001102 procnear ;
//...
.text:
10001181 call ds:
GetModuleFileNameW
.text:
1000118E call ds:
PathRemoveFileSpecW
//...
.text:
100011A7 push offsets_SUnlocker_exe;"\"%s\\Unlocker.exe\""
//...
.text:
100011E0 call ds:
ShellExecuteExW
呼出主程序,进行文件处理.
[UnlockerDriver5.sys分析]
——————————————————————
反汇编驱动文件,跳到入口点:
INIT:
00402000;int__stdcallstart(PDRIVER_OBJECTDriverObject,int)
INIT:
00402000 publicstart
INIT:
00402000start procnear
//...
INIT:
0040203D call ds:
IoCreateDevice
//...
INIT:
004020E3 call ds:
IoCreateSymbolicLink
//...
上面就是DriverEntry了.注意这一段:
INIT:
004020AB mov dwordptr[ecx],offsetloc_401000
INIT:
004020B1 mov dwordptr[esi+40h],offsetloc_401000
INIT:
004020B8 mov dwordptr[esi+44h],offsetsub_401090
INIT:
004020BF mov dwordptr[esi+48h],offsetloc_401020
INIT:
004020C6 mov dwordptr[esi+34h],offsetsub_401240
经典的,处理MajorFunction[IRP_MJ_DEVICE_CONTROL*(sizeofPVOID)]等等.
我们跟踪这两个函数,先跟sub_401240,如下:
PAGE:
0040124D call ds:
RtlInitUnicodeString
//...
PAGE:
00401257 call ds:
IoDeleteSymbolicLink
//...
PAGE:
00401265 call ds:
IoDeleteDevice
很明显的DriverUnload函数;
接着跟sub_401090,这个函数就是类似于DispatchControl(IRP_MJ_DEVICE_CONTROL)了;
我们挑关键的看,RtlInitUnicodeString函数填充UNICODE_STRING结构就不多做纠缠:
PAGE:
004010FA call ds:
ObReferenceObjectByHandle
获取由句柄描述的对象的指针,也就是获取FILE_OBJECT对象;
这里,想想内核级文件的Read和Write,通过HANDLE执行就要先用ObReferenceObjectByHandle函数来获得Handle对应的FileObject,
然后我们再给FileObject发送IRP进行实质操作.
略过分配内存,接着往下走:
PAGE:
00401158 call ds:
ObQueryNameString
这个函数将获取设备名,然后和FILE_OBJECT的FileName构成完整的名字返回(应用层在注册表中保存设备名+目录名);
PAGE:
00401214 call ds:
ObfDereferenceObject
再一次调用ObfDereferenceObject,将对象的引用计数器恢复到先前的值,防止泄漏;
PAGE:
0040122D call ds:
IofCompleteRequest
MajorFunction[IRP_MJ_CLOSE*(sizeofPVOID)],完成操作.
回头看看这个驱动,实际上是很经典也很简单的驱动程序,实现的功能也很简单:
返回文件句柄对应的内核文件对象的完整名字,传给主程序进行文件"删除""移动"等操作.
[Unlocker.exe分析]
——————————————————————
直接跳到入口点:
.text:
004135FB publicstart
.text:
004135FBstart procnear
//...
.text:
00413607 call sub_412EDC
跟进去,挑重点:
.text:
00412EEF call sub_40D1FF ;命令行用法说明
.text:
00412EFC call sub_40D78C ;查询注册表
.text:
00412F0C push offsetCaption;"Unlocker1.8.5"
.text:
00412F11 call sub_413DEF ;创建线程,网络升级,在线辅助
//...
.text:
00412F1C mov ecx,eax
.text:
00412F1E call sub_40FA79 ;这里开始!
=============================================================================
我把sub_40FA79列出来(有省略),如下:
.text:
0040FA79sub_40FA79 procnear ;CODEXREF:
sub_412EDC+42p
.text:
0040FA79 push ebx
.text:
0040FA7A push esi
.text:
0040FA7B push offsetLibFileName;"ntdll.dll"
.text:
0040FA82 call ds:
LoadLibraryA
//...
.text:
0040FA8E push edi
.text:
0040FA8F mov edi,ds:
GetProcAddress
.text:
0040FA95 push offsetProcName;"ZwQuerySystemInformation"
.text:
0040FA9D push offsets_Zwqueryobject;"ZwQueryObject"
.text:
0040FAA7 push offsets_Zwdeletefile;"ZwDeleteFile"
.text:
0040FAB2 push offsets_Rtlinitunicod;"RtlInitUnicodeString"
.text:
0040FABD push offsets_Rtladjustpriv;"RtlAdjustPrivilege"
.text:
0040FAC8 push offsets_Ntloaddriver;"NtLoadDriver"
.text:
0040FAD3 push offsets_Ntunloaddrive;"NtUnloadDriver"
.text:
0040FAD8 push ebx ;hModule
.text:
0040FAD9 mov [esi+14h],eax
.text:
0040FADC call edi;GetProcAddress
这一段的代码是unlocker的重点部分,获取ntdll.dll地址后,调用其中的函数:
1)ZwQuerySystemInformation函数获得系统当前所以进程的所建立的句柄及其相关信息;
2)ZwQueryObject获取句柄所代表对象信息,查出目标文件(设备名+目录名);
3)ZwDeleteFile删除目标文件;
4)NtLoadDriver加载驱动,当然还需要后面的注册表修改;
===========================================================================
再往下:
.text:
00412F9E call ds:
PathRemoveFileSpecW
.text:
00412FAB push offsets_SUnlocker_cfg;"%s\\Unlocker.cfg"
.text:
00412FB5 call ds:
wsprintfW
//...
.text:
00412FC2 call sub_40D3F4
跟进sub_40D3F4函数,发现作用是将驱动信息写入注册表;
.text:
00413008 push dwordptr[eax+8];lpFileName
.text:
0041300B call sub_410E28
//...
.text:
004133E8 call ds:
QueryDosDeviceA
//...
.text:
004134B7 push offsets_DeviceLanmanr;"\\Device\\LanmanRedirector"
.text:
004134BC push eax ;LPWSTR
.text:
004134BD mov [ebp+lpSrch],eax
.text:
004134C0 call ds:
wsprintfW
遍历查询DOS设备,进行重定向;
.text:
00413504 mov esi,ds:
DialogBoxParamA
.text:
0041350A mov edi,ds:
GetModuleHandleA
//...
.text:
00413529 call sub_411A59 //--->getfullname
创建一个对话框窗口,显示所有枚举出的相关进程;
sub_411A59函数将获取对象文件的完整名,并返回,我们跟进去:
.text:
00411F63 push dwordptr[esi];dwProcessId
.text:
00411F65 mov edi,ds:
OpenProcess
.text:
00411F6B push ebx ;bInheritHandle
.text:
00411F6C push 450h ;dwDesiredAccess
.text:
00411F71 call edi;OpenProcess
之前是进程和模块遍历,找到相关联的所有进程和模块,OpenProcess打开需要操作的文件;
.text:
00411F93 call ds:
GetCurrentProcess
//...
.text:
00411FA2 call ds:
DuplicateHandle
获取本地进程,将对象进程的句柄复制到本地进程(句柄进程相关);
.text:
00411FBB push offsets_?
Unlockerdriv;"\\\\?
\\UnlockerDriver5"
.text:
00411FC0 call ds:
CreateFileW
//...
将句柄发送给驱动程序,驱动将返回文件句柄对应的内核文件对象的完整名字;
[文件操作选择]
——————————————————————
现在退出sub_411A59函数返回主线,我们走到这里:
.text:
00413536 cmp byteptr[eax+3],0
.text:
0041353A jz shortloc_41357B
.text:
0041353A
.text:
0041353C mov eax,cInitial
.text:
00413541 test eax,eax
.text:
00413543 jz shortloc_413571 ;"移动"或者"重命名"操作;
.text:
00413543
.text:
00413545 xor ebx,ebx
.text:
00413547 test eax,eax
.text:
00413549 jbe shortloc_41355F ;"删除"操作
这里将进行文件处理的选择,是无动作?
删除?
还是移动?
重命名?
.text:
0041353A jz shortloc_41357B
//...
.text:
0041357B xor ebx,ebx
.text:
0041357D cmp cInitial,ebx
.text:
00413583 jz shortloc_4135AE
cInitial存放的值代表当前的窗口是否为初始窗口;
a)
我们先看是派生窗口时的处理,loc_4135AE:
.text:
004135B5 push offsetsub_412D62;lpDialogFunc
//...
.text:
00412DA4 push [esp+800h+hDlg];hDlg
.text:
00412DAB call sub_412371 //-->toMoveFile
生成一个浏览对话框供选择路径保存文件:
.text:
004123AB call sub_410064
//--->
.text:
00410082 call ds:
CoInitialize
.text:
004100D6 call ds:
SHBrowseForFolderW
.text:
004100E4 call ds:
SHGetPathFromIDListW
.text:
004100F4 call ds:
CoUninitialize
//<---
.text:
004123DE call ds:
PathIsDirectoryW
.text:
0041242C call ds:
GetSaveFileNameW
.text:
00412451 call sub_4115AE //-->inject
实际上查看sub_412371这个函数的交叉引用(实际上你不用看引用也很容易就会发现),会发现:
.text:
00412478sub_412478 procnear //-->GuiControlDeal
这里是一个对话框,也就是我们右键unlocker时产生的界面,它将生成unlocker的主界面,
也将处理各种用户操作的消息,发给各个子程序去处理;
回到:
.text:
004135C7 call esi;DialogBoxParamA
.text:
004135CF call sub_410F86 //-->MoveFile
由于cInitial值为0,所以此时必定是用户选择了"移动"或"重命名";
=========================================================================
跟进sub_410F86,看到:
.text:
00410F96 jnz loc_4110C2 ;重命名
//...
.text:
00411145 call esi;wsprintfW
//...
.text:
00411173 call edi;SHFileOperationW
//...
.text:
00411166 mov [ebp+FileOp.wFunc],4 ;ReName
text:
00411217