看到了精华区的一篇老文章《一篇在程序还未结束运行时就能把自身删除的文章》,试了一下遇到几个问题,觉得有必要就作了一点手记,反复思考,对其他有心之士或许能有些许帮助,所以不敢独享。本人自愧菜鸟一个,大侠们见笑了
有什么可以和我讨论,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下测试通过
一点手记,见笑了
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!