【文章标题】: 一个简单的文件夹映射文件夹工具工作原理的简单分析
【文章作者】: 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编译的,不确定,不用管他

  1. 0040406C > $  E8 1C4B0000   call    00408B8D                         ;  OEP
  2. 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掉,那这个映射无论如何也不会建立了。