|
|
| 首页 | 技术文章 | 软件下载 | 博客 | 论坛 | 精品教程 | 黑客动画 | 视频资源 | 在线服务 | 黑客游戏 | | ||||
|
|
||||||||
|
||||||||
|
|||||
| 程序自删除方法大总结 | |||||
作者:冰狐浪子… 文章来源:CnXHacker.Net 点击数: 更新时间:2004-11-8 ![]() |
|||||
|
程序的自删除早已经不是什么新鲜的话题了,对于各位大虾来说是更是比较容易的事情,但想想自己刚学时遇到的种种错误,我觉得有必要把自己所知道的各种方法总结一下,希望对新手的学习能够有所帮助。 程序的自删除广泛用于反安装程序最后的自删除(环保呀!),当然更多见于木马、病毒首次安装的自动销毁^*^,至于用于何种用途就看你自己啦! 经典自删除 说到程序的自删除就不能不说由 Gary Nebbett 等大虾所写的代码,经典之作呀!代码采用C语言内嵌汇编asm: 在Win9x下只要先对exe本身句柄执行FreeLibrary操作即可解除exe IMAGE在内存的映射,随后就可以通过调用DeleteFile来删除自身文件。 Win9x下的代码如下[selfkill-9x.c]: #include "windows.h" int main(int argc, char *argv[]) { char buf[MAX_PATH]; HMODULE module; module = GetModuleHandle(0); GetModuleFileName(module, buf, MAX_PATH); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push FreeLibrary ret } return 0; } 在WinNT/2K下则需要先调用CloseHandle关闭exe文件本身对应的IMAGE的句柄HANDLE[硬编码为4],然后调用UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,并且解除了程序本身在内存的映射对象,最后就可以用DeleteFile删除自身啦!(注意:本方法不适用于WinXP!) WinNT/2K下的代码如下[selfkill-nt.c]: #include "windows.h" int main(int argc, char *argv[]) { char buf[MAX_PATH]; HMODULE module; module = GetModuleHandle(0); GetModuleFileName(module, buf, MAX_PATH); CloseHandle((HANDLE)4); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push UnmapViewOfFile ret } return 0; } 把上面用于Win9x及WinNT/2K下的代码综合起来,即把两种平台用到的API代码全部执行一遍,虽然在一种平台上可能会有几个API运行失败,有几个API会运行成功,但最后的结果exe程序文件在退出前就删除了自身! Win9x和WinNT/2K下的代码如下[selfkill-9x+nt.c]: #include "windows.h" int main(int argc, char *argv[]) { char buf[MAX_PATH]; HMODULE module; module = GetModuleHandle(0); GetModuleFileName(module, buf, MAX_PATH); CloseHandle((HANDLE)4); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push module push UnmapViewOfFile push FreeLibrary ret } return 0; } 因为我自己在学习Win32下的汇编[MASM32],所以重新用汇编写了一遍,但结果却发现每次都执行失败,显示如图一的错误, =========== 在此插入图一 ============== 通过反汇编比较发现原来由于MASM32编译器对API调用的编码和C编译器的不同,导致使用FreeLibrary或UnmapViewOfFile解除程序在内存的映射后,调用DeleteFile时又引用IMAGE映射地址内的代码[JMP DeleteFile],导致读内存执行错误。 错误分析 普通程序进行API调用时,编译器会将一个API调用语句编译为几个参数压栈指令后跟一条间接调用语句(这是指Microsoft编译器,Borland编译器使用JMP DWORD PTR [XXXXXXXXh])形式如下: push arg1 push arg2 …… call dword ptr[XXXXXXXXh] 地址XXXXXXXXh在程序映像的导入(Import Section)段中,当程序被加载运行时,由装入器负责向里面添入API函数的地址; 一:用MASM32编译的程序其API函数调用格式为: Call capi ; …… …… …… capi: jmp dword ptr[XXXXXXXX] ;XXXXXXXX中存放着所调用的API函数真正地址 其中jmp dword ptr[XXXXXXXX]指令是由“编译器”在程序所有代码的后面自动加上的这样调用的好处是当多次调用同一API时可以减少代码体积,〈呵呵:)个人观点!〉 二:用C编译的程序其API函数调用格式为: Call dword ptr [XXXXXXXX] ;XXXXXXXX地址中存放着所调用的API函数真正地址 正是由于上面API函数调用格式不同导致用MASM32编译的程序自删除失败,因为当调用UnmapViewOfFile后其中代码段的jmp dword ptr[XXXXXXXX]指令所处的代码节变成了不可读,后面的DeleteFile这个API的执行就会失败,程序出错!所以我们如果用MASM32编译这种自删除程序时,应该把push DeleteFile指令改为: mov eax,DeleteFile ;取jmp dword ptr[XXXXXXXX]指令地址,机器码FF25XXXXXXXX inc eax inc eax mov eax,dword ptr[eax] push dword ptr[eax] 这样才是把DeleteFile的真正地址放入堆栈,当然用动态获取API也行,但不如这样代码少,下面是我改好的MASM32代码[selfkill9x-nt.asm]: .386 .model flat, stdcall option casemap :none include windows.inc include kernel32.inc includelib kernel32.lib .code start: mov ebp, esp invoke GetModuleHandle,NULL ;获取自身模块句柄 mov ebx,eax invoke GetModuleFileName,ebx,ebp,MAX_PATH ;获取自身路径 invoke CloseHandle,4 ;关闭exe文件本身对应的IMAGE的句柄[硬编码为4] push 0 ;ExitProcess的参数 push 0 push ebp ;DeleteFile的参数 mov eax,ExitProcess inc eax inc eax mov eax,dword ptr[eax] push dword ptr[eax] ;push ExitProcess push ebx ;UnmapViewOfFile的参数 mov eax,DeleteFile inc eax inc eax mov eax,dword ptr[eax] push dword ptr[eax] ;push DeleteFile push ebx ;FreeLibrary的参数 mov eax,UnmapViewOfFile inc eax inc eax mov eax,dword ptr[eax] push dword ptr[eax] ;push UnmapViewOfFile push FreeLibrary ;FreeLibrary不用改因为调用它时代码节还可以读 ret end start 远程线程插入自删除 远程线程插入如今广泛用于木马和病毒的自我保护及隐蔽自身,同样我们也可以把它用在程序的自删除。 其中所插入的删除自身的远程线程的代码如下: KREMOTE_CODE_START equ this byte call @F @@: pop ebx sub ebx,offset @B ;线程代码重定位 push 500 call [ebx+_lpselfkillSleep] ;休眠0.5秒 lea eax,[ebx+offset _selfkillselfname] push eax call [ebx+_lpselfkillDeleteFile] ;删除程序文件 ret _lpselfkillSleep dd ? ; Sleep的硬编码地址 _lpselfkillDeleteFile dd ? ; DeleteFile的硬编码地址 _selfkillselfname: ; 程序自身文件名,主程序内生成写入 KREMOTE_CODE_END equ this byte KREMOTE_CODE_LENGTH equ offset KREMOTE_CODE_END - offset KREMOTE_CODE_START 主程序中使用GetProcAddress来获取Sleep和DeleteFile的硬编码地址后写入上面,并用GetModuleFileName获取自身路径存入_selfkillselfname处,供远程线程使用。 Win9x下的用于在KERNEL32.DLL中建立远程线程代码如下: Kernel32 db "KERNEL32.DLL",0 SzCreateKernelThread db 'CreateKernelThread',0 _RemoteCode9X proc @_RmCodeStart,@_RmCodeLen local lpThreadID local lpCreateKernelThread local hProcess invoke GetModuleHandle,addr Kernel32 mov ebx,eax invoke GetProcAddress,ebx,offset szCreateKernelThread mov lpCreateKernelThread,eax ;取得CreateKernelThread的地址 ; _findProcess是一个根据名称查找进程PID的函数过程,详细代码见[selfkill-R9x.asm] invoke _findProcess,offset Kernel32 ;查找KERNEL32.DLL进程 .if eax invoke OpenProcess,PROCESS_ALL_ACCESS,TRUE,eax mov hProcess,eax invoke WriteProcessMemory,eax,80001100h,@_RmCodeStart,@_RmCodeLen,NULL .if eax xor eax,eax lea ecx,lpThreadID   |
|||||
| 文章录入:IceRiver 责任编辑:admin | |||||
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 | |||||
| 最新热点 | 最新推荐 | 相关文章 | ||
| 雅虎广告携带木马程序 发言人 德国拟用木马程序收集情报 跨出权限—世纪热线全站程序 利用木马程序盗账号3天从银行 HIPS(程序动作拦截器)规则割 Windows系统自动启动程序十大 Darkstat网络通信记录程序 监 Web 应用程序安全性问题本质 关于木马后门程序的运行原理 如何设定执行Java程序的Linu |
网友评论:(只显示最新5条。评论内容只代表网友观点,与本站立场无关!) |
| 关于我们 - 版权声明 - 帮助(?) - 广告服务 - 联系我们 - 友情链接 - 用户注册 - | Powered by ICE RIVER - STUDIO |
| » CnXHacker.CoM | © CopyRight 2002-2006, CnXHacker.CoM™, Inc. All Rights Reserved. |