首页
社区
课程
招聘
[原创]自删除的一点手记
发表于: 2006-7-25 13:21 7544

[原创]自删除的一点手记

2006-7-25 13:21
7544

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


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 184
活跃值: (108)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
2
好文,学习!
2006-7-25 13:25
0
雪    币: 370
活跃值: (78)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
3
学习学习。
2006-7-25 13:59
0
雪    币: 313
活跃值: (250)
能力值: ( LV9,RANK:650 )
在线值:
发帖
回帖
粉丝
4
好文,分析详细学习了
2006-7-25 17:15
0
雪    币: 97697
活跃值: (200834)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
5
sustain.
2006-7-25 17:31
0
雪    币: 277
活跃值: (312)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
6
如此会编程的不多
2006-7-26 20:52
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
觉得你是故意写个有问题的程序,然后又自己改正。这样分析未免有点故弄玄虚?
说你是故意写错,是因为你明显知道不行还要为之。例如:
.data
h dword ?
buf dword ?
程序销毁了,那么数据段中数据肯定不存在了。因此,你把参数放在数据段肯定得不到正确的数据。明显只有把全部数据保存到堆栈才能正确运行。
2006-7-26 21:57
0
雪    币: 66
活跃值: (15)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
8
最初由 gkend 发布
觉得你是故意写个有问题的程序,然后又自己改正。这样分析未免有点故弄玄虚?
说你是故意写错,是因为你明显知道不行还要为之。例如:
.data
h dword ?
buf dword ?
........

呵呵,抬举小弟了。一开始我就奇怪为什么在程序用特意用asm写这样一段,反应慢了点,不识其中奥妙,看着代码也不多,就根据思路自己写了一段,但编译后运行了程序却好好的在那里躺着,在代码上没看出来端倪,无奈之下就只能拿出了od,跟踪到
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
中的retn 4后,发现程序提前terminate了,细看后才发现是找不到跳转。
还有.data那里,也是od跟踪后观察到堆栈中异样才发现的。呵呵,见笑了
2006-7-28 07:55
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
“此处使用堆栈来依次执行这几个函数是关键兼精髓所在!”,这足以说明你懂。既然代码都到堆栈来执行,未免不知道数据不到堆栈就不行吗?
再就是本论坛以前就有关于自删除的讨论贴,你搜索一下就可以看到。
http://bbs.pediy.com/showthread.php?s=&threadid=6858&highlight=%D7%D4%C9%BE%B3%FD
2006-7-28 10:23
0
雪    币: 66
活跃值: (15)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
10
最初由 gkend 发布
“此处使用堆栈来依次执行这几个函数是关键兼精髓所在!”,这足以说明你懂。既然代码都到堆栈来执行,未免不知道数据不到堆栈就不行吗?
再就是本论坛以前就有关于自删除的讨论贴,你搜索一下就可以看到。

呵呵,这手记是在解决完这些问题后写的,都是后话了。我一开始就提到了我先看过那篇文章,可惜我看的是论坛精华的打包,暂时也还不想去看原贴中的讨论
谢谢你花时间关注这个,但是至少我觉得这并没什么意义,你觉得呢
2006-7-28 10:33
0
雪    币: 66
活跃值: (15)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
11
还是有点好奇,看了你发的那个link,确实这些问题以前都有人解决过了,但是以前别人解决过并不关我的事,我干什么是我的事,顺手写篇手记而已,别人解决没解决过与此无关。我只想说明这点
2006-7-28 10:40
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
你当然觉得没意义,因为你心里有愧。
老掉牙的东西还拿出来分析,你还好意思?(不说重点,你不知悔改)
2006-7-28 10:40
0
雪    币: 66
活跃值: (15)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
13
最初由 gkend 发布
你当然觉得没意义,因为你心里有愧。
老掉牙的东西还拿出来分析,你还好意思?(不说重点,你不知悔改)

还是有点好奇,看了你发的那个link,确实这些问题以前都有人解决过了,但是以前别人解决过并不关我的事,我干什么是我的事,顺手写篇手记而已,别人解决没解决过与此无关。我只想说明这点
。你觉得我抄袭也好,怎么也好,那是你的事,也与我无关,也不想干涉。ok?
2006-7-28 10:43
0
雪    币: 66
活跃值: (15)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
14
我只关注我感兴趣的东西,至于它有多久的历史我并不关心,你厉害,行啊,前人的东西你可以全部丢掉阿,这个我管不着。
我可没那么多时间和你争这个,走了
2006-7-28 10:50
0
游客
登录 | 注册 方可回帖
返回
//