看到了精华区的一篇老文章《一篇在程序还未结束运行时就能把自身删除的文章》,试了一下遇到几个问题,觉得有必要就作了一点手记,反复思考,对其他有心之士或许能有些许帮助,所以不敢独享。本人自愧菜鸟一个,大侠们见笑了
有什么可以和我讨论,the0crat.cn@gmail.com


int main(int argc, char *argv[]) 

    HMODULE module = GetModuleHandle(0); 
    CHAR buf[MAX_PATH]; 
    GetModuleFileName(module, buf, sizeof buf); 
    CloseHandle(HANDLE(4)); 
    __asm { 
        lea    eax, buf 
        push    0 
        push    0 
        push    eax 
        push    ExitProcess 
        push    module 
        push    DeleteFile 
        push    UnmapViewOfFile 
        ret 
    } 
    return 0; 



        lea    eax, buf 
        push    0 
        push    0 
        push    eax 
        push    ExitProcess 
        push    module 
        push    DeleteFile 
        push    UnmapViewOfFile 
此处使用堆栈来依次执行这几个函数是关键兼精髓所在!
用ollydbg调试中发现,如果__asm中部分改成这样:
  push module
  call UnmapViewOfFile
  push module
  call DeleteFileA
  mov eax,buf
  push 0
  push 0
  push eax
  call ExitProcess
那么程序在执行完call UnmapViewOfFile后,虽然堆栈中的地址指向push h这一行,但是!先看这!
7C80B7FC >  8BFF            mov     edi, edi                         ; ntdll.7C930738
7C80B7FE    55              push    ebp
7C80B7FF    8BEC            mov     ebp, esp
7C80B801    56              push    esi
7C80B802    8B35 6012807C   mov     esi, [<&ntdll.NtUnmapViewOfSecti>; ntdll.ZwUnmapViewOfSection
7C80B808    57              push    edi
7C80B809    FF75 08         push    dword ptr [ebp+8]
7C80B80C    6A FF           push    -1
7C80B80E    FFD6            call    esi
7C80B810    8BF8            mov     edi, eax
7C80B812    85FF            test    edi, edi
7C80B814    0F8C DE140300   jl      7C83CCF8
7C80B81A    33C0            xor     eax, eax
7C80B81C    40              inc     eax
7C80B81D    5F              pop     edi
7C80B81E    5E              pop     esi
7C80B81F    5D              pop     ebp
7C80B820    C2 0400         retn    4

这是UnmapViewOfFile代码,单步执行,同时注意之前call UnmapViewOfFile在堆栈中压入push h这行的地址,但是,当retn时,程序出错了,push h已经以下的代码都被Unmap了,当然也就不会再有call DeleteFileA了。
所以,用堆栈来避开程序主体直接跳转到相应的函数是此处一个重要的技巧!这就是为什么之前说此手法是一大精髓的原因

下面用asm直接来写
.data
h dword ?
buf dword ?
.code
main:
  push 0
  call GetModuleHandleA  ;pModule=NULL
  mov h,eax
  push 104h  ;BufSize=104h
  mov eax,offset buf
  push eax  ;PathBuffer
  mov ecx,h
  push ecx  ;hModule
  call GetModuleFileNameA
  push 4  ;hObject=00000004
  call CloseHandle
  mov eax,offset buf
  push 0
  push 0
  push eax
  push ExitProcess
  push h
  push DeleteFileA
  push UnmapViewOfFile
  retn
end main

debug,程序同样出错了,但是是另外一个原因,和前面一样,在UnmapViewOfFile中的retn后出的错,但是看堆栈
0012FFAC   00401072  temp.DeleteFileA
0012FFB0   00400000
0012FFB4   00401078  temp.ExitProcess
0012FFB8   00404004  offset temp.buf

不是kernel32.DeleFileA,同样没避开程序主体,ollydbg中看到:
00401005 >/$ /E9 06000000   jmp     main
0040100A  |  |CC            int3
0040100B  |  |CC            int3
0040100C  |  |CC            int3
0040100D  |  |CC            int3
0040100E  |  |CC            int3
0040100F  |  |CC            int3
00401010 >|> \6A 00         push    0
00401012  |?  E8 6D000000   call    GetModuleHandleA                 ;  jmp to kernel32.GetModuleHandleA
00401017  |?  A3 00404000   mov     [h], eax
0040101C  |?  68 04010000   push    104
00401021  |?  B8 04404000   mov     eax, offset buf                  ;  ASCII "G:\asm\temp.exe"
00401026  |?  50            push    eax
00401027  |.  8B0D 00404000 mov     ecx, [h]                         ; \GetModuleHandleA
0040102D  |?  51            push    ecx
0040102E  |?  E8 4B000000   call    GetModuleFileNameA               ;  jmp to kernel32.GetModuleFileNameA
00401033  |.  6A 04         push    4                                ; \CloseHandle
00401035  |?  E8 32000000   call    CloseHandle                      ;  jmp to kernel32.CloseHandle
0040103A  |?  B8 04404000   mov     eax, offset buf                  ;  ASCII "G:\asm\temp.exe"
0040103F  |?  6A 00         push    0
00401041  |?  6A 00         push    0
00401043  |.  50            push    eax                              ; /FileName
00401044  |.  68 78104000   push    ExitProcess                      ; \DeleteFileA
00401049  |.  FF35 00404000 push    dword ptr [h]                    ;  temp.00400000
0040104F   ?  68 72104000   push    DeleteFileA                      ;  jmp to kernel32.DeleteFileA
00401054 >    68 8A104000   push    UnmapViewOfFile                  ;  jmp to kernel32.UnmapViewOfFile
00401059      C3            retn
0040105A >    CC            int3
0040105B      CC            int3
0040105C      CC            int3
0040105D      CC            int3
0040105E      CC            int3
0040105F      CC            int3
00401060 >    CC            int3
00401061      CC            int3
00401062      CC            int3
00401063      CC            int3
00401064 > $  CC            int3
00401065   ?  CC            int3
00401066 > ?  CC            int3
00401067   ?  CC            int3
00401068   ?  CC            int3
00401069   ?  CC            int3
0040106A > $  CC            int3
0040106B   ?  CC            int3
0040106C > ?- FF25 B4504000 jmp     [<&kernel32.CloseHandle>]        ;  kernel32.CloseHandle
00401072 > ?- FF25 B8504000 jmp     [<&kernel32.DeleteFileA>]        ;  kernel32.DeleteFileA
00401078 > ?- FF25 BC504000 jmp     [<&kernel32.ExitProcess>]        ;  kernel32.ExitProcess
0040107E > ?- FF25 C0504000 jmp     [<&kernel32.GetModuleFileNameA>] ;  kernel32.GetModuleFileNameA
00401084 > ?- FF25 C4504000 jmp     [<&kernel32.GetModuleHandleA>]   ;  kernel32.GetModuleHandleA
0040108A > ?- FF25 C8504000 jmp     [<&kernel32.UnmapViewOfFile>]    ;  kernel32.UnmapViewOfFile
00401090 >  - FF25 FC504000 jmp     [<&user32.wsprintfA>]            ;  user32.wsprintfA

找到问题所在了,避开程序直接执行这几个函数才行。
masm32给我们push到堆栈的都是上面末端这几个地址,而没有直接到真正的函数入口,怎么办呢~[疑点]
先手工修改一下push的数据暂时解决这个问题
另外,DeleteFileA需要程序的路径,同样不能将此数据放在程序的主体中,同样是堆栈操作
00401044  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)
00401049  |.  8D85 F8FEFFFF lea     eax, [ebp-108]                   ; |这里
0040104F  |.  50            push    eax                              ; |PathBuffer
00401050  |.  8B4D FC       mov     ecx, [ebp-4]                     ; |
00401053  |.  51            push    ecx                              ; |hModule
00401054  |.  FF15 58414200 call    [<&KERNEL32.GetModuleFileNameA>] ; \GetModuleFileNameA
.
.
.
00401072  |.  8D85 F8FEFFFF lea     eax, [ebp-108]  ;这里
00401078  |.  6A 00         push    0
0040107A  |.  6A 00         push    0
0040107C  |.  50            push    eax


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
vc++编译的没问题的文件
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00401005  /$ /E9 06000000   jmp     main
0040100A  |  |CC            int3
0040100B  |  |CC            int3
0040100C  |  |CC            int3
0040100D  |  |CC            int3
0040100E  |  |CC            int3
0040100F  |  |CC            int3
00401010 >|> \55            push    ebp
00401011  |.  8BEC          mov     ebp, esp
00401013  |.  81EC 48010000 sub     esp, 148
00401019  |.  53            push    ebx
0040101A  |.  56            push    esi
0040101B  |.  57            push    edi
0040101C  |.  8DBD B8FEFFFF lea     edi, [ebp-148]
00401022  |.  B9 52000000   mov     ecx, 52
00401027  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
0040102C  |.  F3:AB         rep     stos dword ptr es:[edi]
0040102E  |.  8BF4          mov     esi, esp
00401030  |.  6A 00         push    0                                ; /pModule = NULL
00401032  |.  FF15 5C414200 call    [<&KERNEL32.GetModuleHandleA>]   ; \GetModuleHandleA
00401038  |.  3BF4          cmp     esi, esp
0040103A  |.  E8 C1000000   call    _chkesp
0040103F  |.  8945 FC       mov     [ebp-4], eax
00401042  |.  8BF4          mov     esi, esp
00401044  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)
00401049  |.  8D85 F8FEFFFF lea     eax, [ebp-108]                   ; |
0040104F  |.  50            push    eax                              ; |PathBuffer
00401050  |.  8B4D FC       mov     ecx, [ebp-4]                     ; |
00401053  |.  51            push    ecx                              ; |hModule
00401054  |.  FF15 58414200 call    [<&KERNEL32.GetModuleFileNameA>] ; \GetModuleFileNameA
0040105A  |.  3BF4          cmp     esi, esp
0040105C  |.  E8 9F000000   call    _chkesp
00401061  |.  8BF4          mov     esi, esp
00401063  |.  6A 04         push    4                                ; /hObject = 00000004
00401065  |.  FF15 54414200 call    [<&KERNEL32.CloseHandle>]        ; \CloseHandle
0040106B  |.  3BF4          cmp     esi, esp
0040106D  |.  E8 8E000000   call    _chkesp
00401072  |.  8D85 F8FEFFFF lea     eax, [ebp-108]
00401078  |.  6A 00         push    0
0040107A  |.  6A 00         push    0
0040107C  |.  50            push    eax
0040107D  |.  FF35 50414200 push    dword ptr [<&KERNEL32.ExitProces>;  kernel32.ExitProcess
00401083  |.  FF75 FC       push    dword ptr [ebp-4]                ;  a.00400000
00401086  |.  FF35 4C414200 push    dword ptr [<&KERNEL32.DeleteFile>;  kernel32.DeleteFileA
0040108C  |.  FF35 48414200 push    dword ptr [<&KERNEL32.UnmapViewO>;  kernel32.UnmapViewOfFile
00401092  \.  C3            retn



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
最初存在问题的程序(masm32)
参数
ml -Zi -c -Fl -coff %1.asm
link %1.obj kernel32.lib /subsystem:console /debug
可能是参数设置的不正确导致的吧,不太清楚,应该怎么设置请大侠们指教
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00401005 > $ /E9 06000000     jmp     main
0040100A     |CC              int3
0040100B     |CC              int3
0040100C     |CC              int3
0040100D     |CC              int3
0040100E     |CC              int3
0040100F     |CC              int3
00401010 > > \6A 00           push    0                                ; /pModule = NULL
00401012   .  E8 6D000000     call    GetModuleHandleA                 ; \GetModuleHandleA
00401017   .  A3 00404000     mov     [h], eax
0040101C   .  68 04010000     push    104                              ; /BufSize = 104 (260.)
00401021   .  B8 04404000     mov     eax, offset buf                  ; |
00401026   .  50              push    eax                              ; |PathBuffer => offset temp.buf
00401027   .  8B0D 00404000   mov     ecx, [h]                         ; |
0040102D   .  51              push    ecx                              ; |hModule => NULL
0040102E   .  E8 4B000000     call    GetModuleFileNameA               ; \GetModuleFileNameA
00401033   .  6A 04           push    4                                ; /hObject = 00000004
00401035   .  E8 32000000     call    CloseHandle                      ; \CloseHandle
0040103A   .  B8 04404000     mov     eax, offset buf
0040103F   .  6A 00           push    0
00401041   .  6A 00           push    0
00401043   .  50              push    eax
00401044   .  68 78104000     push    ExitProcess                      ;  jmp to kernel32.ExitProcess
00401049   .  FF35 00404000   push    dword ptr [h]
0040104F   .  68 72104000     push    DeleteFileA                      ;  jmp to kernel32.DeleteFileA
00401054   .  68 8A104000     push    UnmapViewOfFile                  ;  jmp to kernel32.UnmapViewOfFile
00401059   .  C3              retn                                     ;  RET used as a jump to UnmapViewOfFile
0040105A      CC              int3
0040105B      CC              int3
0040105C      CC              int3
0040105D      CC              int3
0040105E      CC              int3
0040105F      CC              int3
00401060      CC              int3
00401061      CC              int3
00401062      CC              int3
00401063      CC              int3
00401064      CC              int3
00401065      CC              int3
00401066      CC              int3
00401067      CC              int3
00401068      CC              int3
00401069      CC              int3
0040106A      CC              int3
0040106B      CC              int3
0040106C > $- FF25 84504000   jmp     [<&kernel32.CloseHandle>]        ;  kernel32.CloseHandle
00401072 > .- FF25 70504000   jmp     [<&kernel32.DeleteFileA>]        ;  kernel32.DeleteFileA
00401078 > .- FF25 74504000   jmp     [<&kernel32.ExitProcess>]        ;  kernel32.ExitProcess
0040107E > $- FF25 78504000   jmp     [<&kernel32.GetModuleFileNameA>] ;  kernel32.GetModuleFileNameA
00401084 > $- FF25 7C504000   jmp     [<&kernel32.GetModuleHandleA>]   ;  kernel32.GetModuleHandleA
0040108A > >- FF25 80504000   jmp     [<&kernel32.UnmapViewOfFile>]    ;  kernel32.UnmapViewOfFile

.data
h dword ?
buf dword ?
.code
main:
  push 0
  call GetModuleHandleA  ;pModule=NULL
  mov h,eax
  push 104h  ;BufSize=104h
  mov eax,offset buf
  push eax  ;PathBuffer
  mov ecx,h
  push ecx  ;hModule
  call GetModuleFileNameA
  push 4  ;hObject=00000004
  call CloseHandle
  mov eax,offset buf
  push 0
  push 0
  push eax
  push ExitProcess
  push h
  push DeleteFileA
  push UnmapViewOfFile
  retn
end main
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
上述经修正后的程序
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
00401005 >/$ /E9 06000000   jmp     00401010
0040100A  |  |CC            int3
0040100B  |  |CC            int3
0040100C  |  |CC            int3
0040100D  |  |CC            int3
0040100E  |  |CC            int3
0040100F  |  |CC            int3
00401010  |> \8BEC          mov     ebp, esp
00401012  |.  81EC 00020000 sub     esp, 200
00401018  |.  6A 00         push    0                                ; /pModule = NULL
0040101A  |.  E8 69000000   call    <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
0040101F  |.  8945 FC       mov     [ebp-4], eax
00401022  |.  68 04010000   push    104                              ; /BufSize = 104 (260.)
00401027  |.  8D85 F8FEFFFF lea     eax, [ebp-108]                   ; |
0040102D  |.  50            push    eax                              ; |PathBuffer
0040102E  |.  8B4D FC       mov     ecx, [ebp-4]                     ; |
00401031  |.  51            push    ecx                              ; |hModule
00401032  |.  E8 4B000000   call    <jmp.&kernel32.GetModuleFileName>; \GetModuleFileNameA
00401037  |.  6A 04         push    4                                ; /hObject = 00000004
00401039  |.  E8 32000000   call    <jmp.&kernel32.CloseHandle>      ; \CloseHandle
0040103E  |.  8D85 F8FEFFFF lea     eax, [ebp-108]
00401044  |.  6A 00         push    0
00401046  |.  6A 00         push    0
00401048  |.  50            push    eax
00401049  |.  68 7D0EE777   push    kernel32.ExitProcess
0040104E  |.  FF75 FC       push    dword ptr [ebp-4]
00401051  |.  68 51E3E677   push    kernel32.DeleteFileA
00401056  |.  68 4098E677   push    kernel32.UnmapViewOfFile
0040105B  \.  C3            retn


.data
.code
main:
  mov ebp,esp
  sub esp,200h
  push 0
  call GetModuleHandleA  ;pModule=NULL
  mov [ebp-4h],eax
  push 104h  ;BufSize=104h
  lea eax,[ebp-108h]
  push eax  ;PathBuffer
  mov ecx,[ebp-4h]
  push ecx  ;hModule
  call GetModuleFileNameA
  push 4  ;hObject=00000004
  call CloseHandle
  lea eax,[ebp-108h]
  push 0
  push 0
  push eax
  push ExitProcess
  push dword ptr [ebp-4h]
  push DeleteFileA
  push UnmapViewOfFile
  retn
end main
并且手工修正函数地址
并且发现在2k adv server cn sp4和XP home cn sp2中ExitProcess等函数在文件中的地址是不同的
2k adv server cn sp4下测试通过
一点手记,见笑了