一个运行中的程序,怎样删除自己?(200分)

  • 主题发起人 主题发起人 finger
  • 开始时间 开始时间
F

finger

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题在论坛中被提过多次了。但是回答我并不满意。<br>不过,我也看到较好的回答。比如:<br>来自:xf-wangyi, 时间:2002-7-3 21:20:00, ID:1187629 <br>我没有试过,你试一下<br><br>这样取得的地址实际上是这个封装代码的,而这段代码又处于 UnmapViewOfMap 解除映像范围类,因此,到调用 DeleteFile 函数的时候就无法反问到这段代码了。<br><br>解决的办法是,用GetProcAddress动态取得这几个API的地址。 <br><br>Delphi&amp;CB代码如下: <br><br>//////////////////////////////////////////////<br>procedure DeleteSelf;<br>var<br>&nbsp; pExitProcess: Pointer;<br>&nbsp; pDeleteFile: Pointer;<br>&nbsp; pUnmapViewOfFile: Pointer;<br>&nbsp; hModule: THANDLE;<br>&nbsp; cBuf:array[0..MAX_PATH]of Char;<br>begin<br>&nbsp; hModule := GetModuleHandle('kernel32');<br>&nbsp; if hModule &lt;&gt; 0 then<br>&nbsp; begin<br>&nbsp; &nbsp; pExitProcess := GetProcAddress(hModule, 'ExitProcess');<br>&nbsp; &nbsp; pDeleteFile := GetProcAddress(hModule, 'DeleteFileA');<br>&nbsp; &nbsp; pUnmapViewOfFile := GetProcAddress(hModule, 'UnmapViewOfFile');<br>&nbsp; end else<br>&nbsp; begin<br>&nbsp; &nbsp; pExitProcess := nil;<br>&nbsp; &nbsp; pDeleteFile := nil;<br>&nbsp; &nbsp; pUnmapViewOfFile := nil;<br>&nbsp; end; <br>&nbsp; hModule := GetModuleHandle(nil);<br>&nbsp; GetModuleFileName(hModule, cBuf, Sizeof(cBuf));<br>&nbsp; CloseHandle(THANDLE(4));<br>&nbsp; asm<br>&nbsp; &nbsp; XOR EAX, EAX;<br>&nbsp; &nbsp; PUSH EAX;<br>&nbsp; &nbsp; PUSH EAX;<br>&nbsp; &nbsp; LEA EAX, cBuf;<br>&nbsp; &nbsp; PUSH EAX;<br>&nbsp; &nbsp; MOV EAX, pExitProcess; &nbsp; &nbsp;PUSH EAX; &nbsp; &nbsp;MOV EAX, hModule; &nbsp; &nbsp;PUSH EAX; &nbsp; &nbsp;MOV EAX, pDeleteFile;<br>&nbsp; &nbsp; PUSH EAX;<br>&nbsp; &nbsp; MOV EAX, pUnmapViewOfFile;<br>&nbsp; &nbsp; PUSH EAX;<br>&nbsp; &nbsp; RET;<br>&nbsp; end;<br>end;<br>但是,我在调试时发现它只是杀掉进程,大家用什么好方法吗?最好有源码。<br>&nbsp;<br>
 
这个你试试。<br>unit Unit1;<br><br>interface<br><br>uses<br>Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>StdCtrls;<br>type<br>TForm1 = class(TForm)<br>Button1: TButton;<br>procedure My_DeleteMe; //自定义程序自杀过程<br>procedure Button1Click(Sender: TObject);<br>private<br>{ Private declarations }<br>public<br>{ Public declarations }<br>end;<br><br>var<br>Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br>My_DeleteMe;<br>end;<br>procedure TForm1.My_DeleteMe; //程序自杀<br>var<br>BatchFile: TextFile;<br>BatchFileName: string;<br>ProcessInfo: TProcessInformation;<br>StartUpInfo: TStartupInfo;<br>begin<br>{By Lovejingtao.http://Lovejingtao.126.com,Lovejingtao@21cn.com}<br>BatchFileName := ExtractFilePath(ParamStr(0)) + '$$a.bat';<br>AssignFile(BatchFile, BatchFileName);<br>Rewrite(BatchFile);<br>Writeln(BatchFile, ':try');<br>Writeln(BatchFile, 'del "' + ParamStr(0) + '"');<br>Writeln(BatchFile,<br>'if exist "' + ParamStr(0) + '"' + ' goto try');<br>Writeln(BatchFile, 'del "' + BatchFileName + '"');<br>Writeln(BatchFile, 'cls');<br>CloseFile(BatchFile);<br>FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);<br>StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;<br>StartUpInfo.wShowWindow := SW_HIDE;<br>if CreateProcess(nil, PChar(BatchFileName), nil, nil,<br>False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,<br>ProcessInfo) then<br>begin<br>CloseHandle(ProcessInfo.hThread);<br>CloseHandle(ProcessInfo.hProcess);<br>end;<br>//Application.Terminate; &nbsp; &nbsp;原程序如此。后运行不畅改为close.<br>close;<br>end;<br>end.<br>//补充:1、上面的批处理的 del %0等同于 del a.bat,用del a.bat则批处理文件必须为a.bat,用del %0则可以随意。<br><br>
 
这个也是我转贴来的,我并没有试过行不行,我来试试楼上这位的方法
 
xf-wangyi:你的方法不错,再努力一下阿。 <br>kifo:你的方法我知道。谢谢你了。其实,你的程序不是真重意义上的自己删自己。<br>我知道可以向CIH那样,取得RING0级控制。不过我不知用DELPHI的实现代码。
 
做到这一步就行了,你删得再好,别为运行前先备份你一下,还是能分析出来的。
 
to kifo:我并不是真要做这样的删除程序。如果是这样,以前的帖子已经解决问题了。<br>我只是想知道直接控制的方法。例如如何取得RING0及控制。你的方法构思很巧妙,但实际上<br>严格地说不是庸庸程序本身删除了自己。<br>&nbsp; 不过,谢谢你。我会给分给你的。
 
再转一贴,这个我还没有完全看懂<br>下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码. <br>这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了. <br>int main(int argc, char *argv[]) <br>{ <br>&nbsp; &nbsp;HMODULE module = GetModuleHandle(0); <br>&nbsp; &nbsp;CHAR buf[MAX_PATH]; <br>&nbsp; &nbsp;GetModuleFileName(module, buf, sizeof buf); <br>&nbsp; &nbsp;CloseHandle(HANDLE(4)); <br>&nbsp; &nbsp;__asm { <br>&nbsp; &nbsp; &nbsp; &nbsp;lea &nbsp; &nbsp; eax, buf <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;0 <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;0 <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;eax <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;ExitProcess <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;module <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;DeleteFile <br>&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;UnmapViewOfFile <br>&nbsp; &nbsp; &nbsp; &nbsp;ret <br>&nbsp; &nbsp;} <br>&nbsp; &nbsp;return 0; <br>} <br>现在,我们先看一下堆栈中的东西 <br><br>偏移 内容 <br>24 &nbsp; 0 <br>20 &nbsp; 0 <br>16 &nbsp; offset buf <br>12 &nbsp; address of ExitProcess <br>8 &nbsp; &nbsp;module <br>4 &nbsp; &nbsp;address of DeleteFile <br>0 &nbsp; &nbsp;address of UnmapViewOfFile <br><br>调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出错.而调用ExitProcess则应该不会返回. <br>这段代码的精妙之处在于: <br>1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄. <br>2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码. <br>3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.) <br><br>Gary Nebbett果然是WIN系列平台的顶尖高手之一.能写出如此代码.独辟蹊径啊:)<br> 
 
来源自<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=836219
 

Similar threads

后退
顶部