【文章标题】: 一个简单的文件夹映射文件夹工具工作原理的简单分析
【文章作者】: ucantseeme
【软件名称】: junction.exe
【软件大小】: 93.3K
【下载地址】:
【保护方式】: 无
【操作平台】: 仅测试过XP,其他未知
【软件介绍】: 此工具提供文件夹映射文件夹的功能
【作者声明】: 阅读本文需要一些基础的汇编知识,跟API相关知识,转载请保证全文完整性
【学习目的】: 看看如何实现文件夹映射文件夹的功能
------------------------------------------------------------------------------------------
【详细过程】
1,先来说说前言,对不起,前言有点长。
首先说说这个文件夹映射文件夹是怎么一回事:简单的说来就是,操作这个文件夹中的内容,就等于操作另一个被映射的文件夹,操作另一个也就等于操作这个,操作这一个也就等于操作另一个。。。
其次我们知道本身windows操作系统就提供了一个叫“驱动器挂载点”的功能。这其实就是个文件夹映射磁盘分区的功能。具体
操作方式见下图:
先来到磁盘管理这个地方,如图1,选更改驱动器名和路径
然后来到图2的位置,点添加,在弹出新的窗口里面浏览一个空的文件夹便可完成映射
这样就完成文件夹映射分区了,除此之外,还有其他的方法,比如编程中可以用SetVolumeMountPoint的API来设置。
但是在实际生活应用中,我发现我需要文件夹映射到文件夹的功能。有了这个需求我就找啊找,终于找到了一款名叫junction的小工具
接下来我必须介绍此软件如何使用
从CMD打开此程序,可以看到使用说明,在CMD里面输入图中口令,按回车后,便会提示建立映射成功,如图3
2,好,介绍到一段落,开始分析。
本身操作系统没有提供文件夹映射文件夹的功能,我就对这个不到100K的小软件比较感兴趣,于是随便看了下,我们的目的很明确,就是看看怎么样文件夹映射文件夹的,其他的比如什么出错判断啊,撤销映射啊,统统不管他,首先就应该定位到关键代码处
代码如下:
首先OD从这个地方载入,并且输入参数,注意参数中不用加junction的文件名啦,直接两个文件夹路径,如图4
载入后看看OEP,感觉像Visual studio 200X编译的,不确定,不用管他
- 0040406C > $ E8 1C4B0000 call 00408B8D ; OEP
- 00404071 .^ E9 41FEFFFF jmp 00403EB7
复制代码一路跟踪来到了Main函数,不是关键代码,也不用关他,看都不用看一眼
1. 00402890 /$ 81EC 1C040000 sub esp, 41C ; Main
2. 00402896 |. A1 C0204100 mov eax, dword ptr [4120C0]
3. 0040289B |. 33C4 xor eax, esp
4. 0040289D |. 898424 180400>mov dword ptr [esp+418], eax
5. 004028A4 |. 53 push ebx
6. 004028A5 |. 55 push ebp
7. 004028A6 |. 57 push edi
8. 004028A7 |. 8BBC24 300400>mov edi, dword ptr [esp+430]
9. 004028AE |. 33ED xor ebp, ebp
复制代码一路F8往下跟,我们发现了有一处很长的循环判断,这串代码是有用的了,但还是无需细看,大概作用就是一些参数判断的,不过看到这段代码就说明我们离关键代码很近了,这个时候你就要注意的往下走了
1. 00402940 |. /0F8E BE010000 jle 00402B04
2. 00402946 |> |8B14B7 /mov edx, dword ptr [edi+esi*4] ; 取参数指针
3. 00402949 |. |68 6CF14000 |push 0040F16C ; UNICODE "/s"
4. 0040294E |. |52 |push edx
5. 0040294F |. |E8 D5090000 |call 00403329
6. 00402954 |. |83C4 08 |add esp, 8
7. (此处中间省去大量代码)
8. 00402A5B |. |C605 28304100>|mov byte ptr [413028], 1
9. 00402A62 |. |75 2D |jnz short 00402A91
10. 00402A64 |> |83C6 01 |add esi, 1
11. 00402A67 |. |3BB424 300400>|cmp esi, dword ptr [esp+430]
12. 00402A6E |.^|0F8C D2FEFFFF \jl 00402946
复制代码只要你的参数没打错,没其他什么问题,那走过那串循环判断,你就会跟我一样来到紧跟着循环判断的这些代码,经我跟踪,就是00402A84的那个call里面的代码,让我们进去看看
1. 00402A74 |. 8B4424 10 mov eax, dword ptr [esp+10]
2. 00402A78 |. 85C0 test eax, eax
3. 00402A7A |. 74 25 je short 00402AA1
4. 00402A7C |. 8B0C87 mov ecx, dword ptr [edi+eax*4] ; 取参二
5. 00402A7F |. 8B14AF mov edx, dword ptr [edi+ebp*4] ; 取参一
6. 00402A82 |. 51 push ecx
7. 00402A83 |. 52 push edx
8. 00402A84 |. E8 17FAFFFF call 004024A0 ; 关键,所有东西都在里面,当然是F7
9. 00402A89 |. 83C4 08 add esp, 8
10. 00402A8C |. E9 C0000000 jmp 00402B51
复制代码
重要
进入了call 004024A0这句以后一路F8,还是那句话,只要你的参数没错,就会来到这个地方,有两个API,一个是CreateDirectory,另一个是CreateFile,其中CreateDirectory的Path参数就是你输入的参数一的路径,上面图3也说过了,软件会自己创建目录,也就这创建的,创建好以后在用CreateFile打开它,看到这里那接下来的跟就更要小心了
1. 00402684 |> \6A 00 push 0 ; /pSecurity = NULL
2. 00402686 |. 55 push ebp ; |Path
3. 00402687 |. FF15 38C04000 call dword ptr [<&KERNEL32.CreateDire>; \CreateDirectoryW
4. 0040268D |. 6A 00 push 0 ; /hTemplateFile = NULL
5. 0040268F |. 68 00002002 push 2200000 ; |Attributes = BACKUP_SEMANTICS|200000
6. 00402694 |. 6A 03 push 3 ; |Mode = OPEN_EXISTING
7. 00402696 |. 6A 00 push 0 ; |pSecurity = NULL
8. 00402698 |. 6A 00 push 0 ; |ShareMode = 0
9. 0040269A |. 68 00000040 push 40000000 ; |Access = GENERIC_WRITE
10. 0040269F |. 55 push ebp ; |FileName
11. 004026A0 |. FF15 68C04000 call dword ptr [<&KERNEL32.CreateFile>; \CreateFileW
12. 004026A6 |. 8BF0 mov esi, eax
13. 004026A8 |. 83FE FF cmp esi, -1
14. 004026AB |. 75 37 jnz short 004026E4 ; 判断打开文件夹是否出错
复制代码
重要
接着一路F8,走不来多远又看到一个API,DeviceIoControl,顺着它往下看去,没多远就要ret了,这个call就要执行完了,经各方面分析,这个我不认识的API确实很重要,我又不认识他,干嘛用的呢,查查看吧,最后我在微软的MSDN网站上找到了相关文档说明,在下面
1. 0040276D |. 6A 00 push 0 ; /pOverlapped = NULL
2. 0040276F |. 8D4C24 14 lea ecx, dword ptr [esp+14] ; |
3. 00402773 |. 51 push ecx ; |pBytesReturned
4. 00402774 |. 6A 00 push 0 ; |OutBufferSize = 0
5. 00402776 |. 83C0 0C add eax, 0C ; |
6. 00402779 |. 6A 00 push 0 ; |OutBuffer = NULL
7. 0040277B |. 898424 380200>mov dword ptr [esp+238], eax ; |
8. 00402782 |. 83C0 08 add eax, 8 ; |
9. 00402785 |. 50 push eax ; |InBufferSize
10. 00402786 |. 8D9424 380200>lea edx, dword ptr [esp+238] ; |
11. 0040278D |. 52 push edx ; |InBuffer
12. 0040278E |. 68 A4000900 push 900A4 ; |IoControlCode = FSCTL_SET_REPARSE_POINT
13. 00402793 |. 56 push esi ; |hDevice
14. 00402794 |. FF15 70C04000 call dword ptr [<&KERNEL32.DeviceIoCo>; \DeviceIoControl
复制代码DeviceIoControl
对设备执行指定的操作
IoControlCode = FSCTL_SET_REPARSE_POINT
Operation
The FSCTL_SET_REPARSE_POINT control code sets a reparse point on a file or directory.
To perform this operation, call ZwFsControlFile with the following parameters.
Minifilters should use FltTagFile instead of FSCTL_SET_REPARSE_POINT to set a reparse point.
For more information about reparse points and the FSCTL_SET_REPARSE_POINT control code, see the Microsoft
Windows SDK documentation.
操作该FSCTL_SET_REPARSE_POINT控制代码设置一个文件或目录重分析点。要执行此操作,请使用以下参数
ZwFsControlFile。微筛选应使用FltTagFile而FSCTL_SET_REPARSE_POINT设置重分析点。如需重新分析点,
FSCTL_SET_REPARSE_POINT控制代码,信息,请参阅Microsoft Windows SDK文档。
小结:
看到这里也不用多说了,文档里面已经告诉我们了,虽然金山词霸有点衰,但大意还是在那的。此程序是通过使用API DeviceIoControl配合参数FSCTL_SET_REPARSE_POINT实现文件夹映射文件夹功能的,我们做个简单的实验就是把这条API调用给NOP掉,那这个映射无论如何也不会建立了。