求:delphi 程序自删除代码 请问大家 如何实现delphi 程序自删除 ,我看病毒、木马类就可以实现这种功能。请问那是怎么实现的?提供下代码学习下。谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 program del;useswindows;begin WinExec(Pchar('cmd /c del ' + GetCommandLine),0); ExitProcess(0);end. {转自 http://topic.csdn.net/t/20020430/17/692138.html}procedure TForm1.Button1Click(Sender: TObject);var Selfname,BatFilename,s1,s2:string; BatchFile: TextFile;begin Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称 BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批处理文件名称 S1:='@del '+Selfname; S2:='if exist '+Selfname+' goto pp'; assignfile(BatchFile,BatFilename); rewrite(BatchFile); writeln(BatchFile,':pp'); writeln(BatchFile,S1); writeln(BatchFile,S2); writeln(BatchFile,'@del %0'); closefile(BatchFile); winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat application.Terminate;//退出程序end; procedure TForm1.Button1Click(Sender: TObject);var Selfname,BatFilename,s1,s2:string; BatchFile: TextFile;begin Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称 BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批处理文件名称 S1:='@del '+Selfname; S2:='if exist '+Selfname+' goto pp'; assignfile(BatchFile,BatFilename); rewrite(BatchFile); writeln(BatchFile,':pp'); writeln(BatchFile,S1); writeln(BatchFile,S2); writeln(BatchFile,'@del %0'); closefile(BatchFile); winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat application.Terminate;//退出程序end;------------------------------------------------------------------------这个我也试过,运行是可以删除应用程序本身,批处理也自删除。问题是我加载开机运行 就不能自删除。有没有不用批处理,效果更好的代码?等待中 。。 以前用C++写过,就几个API,楼主自己翻译一下吧.注意引用系统Shell方面的几单元.bool DeleteSelf(){ SHELLEXECUTEINFO shi; TCHAR ptszModule[MAX_PATH] = {0}; TCHAR ptszComspec[MAX_PATH] = {0}; TCHAR ptszParams[MAX_PATH] = {0}; // 获取执行路径 if ((0 != ::GetModuleFileName(0, ptszModule, MAX_PATH)) && (0 != ::GetShortPathName(ptszModule, ptszModule, MAX_PATH)) && (0 != ::GetEnvironmentVariable(_T("COMSPEC"), ptszComspec, MAX_PATH))) { // 设置参数 _stprintf_s(ptszParams, MAX_PATH, _T("/c del /f /q \"%s\" > nul"), ptszModule); shi.cbSize = sizeof(shi); shi.hwnd = 0; shi.lpVerb = _T("open"); shi.lpFile = ptszComspec; shi.lpParameters = ptszParams; shi.lpDirectory = 0; shi.nShow = SW_HIDE; shi.fMask = SEE_MASK_NOCLOSEPROCESS; // 调整程序进程和线程的优先级 if ((0 == ::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) || (0 == ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))) { return false; } // 执行删除 if (FALSE != ::ShellExecuteEx(&shi)) { // 先通知程序退出 ::PostQuitMessage(0); // 阻断 Command Shell 进程直到本程序退出 ::SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS); ::SetProcessPriorityBoost(shi.hProcess, TRUE); // 向 Explorer Shell 通知删除消息 ::SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, ptszModule, 0); return true; } else // 如果删除失败则恢复程序进程和线程的优先级 { ::SetPriorityClass(::GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_NORMAL); } } return false;} 楼上的兄弟应该也采用了CMD命令完成吧? 在网上找了段代码如下:但运行不能自删除。 请高手指点,或给自认为好的CODE。谢谢!~1////////////////////////////////////////////// procedure DeleteSelf; var pExitProcess: Pointer; pDeleteFile: Pointer; pUnmapViewOfFile: Pointer; hModule: THANDLE; cBuf:array[0..MAX_PATH]of Char; begin hModule := GetModuleHandle('kernel32'); if hModule <> 0 then begin pExitProcess := GetProcAddress(hModule, 'ExitProcess'); pDeleteFile := GetProcAddress(hModule, 'DeleteFileA'); pUnmapViewOfFile := GetProcAddress(hModule, 'UnmapViewOfFile'); end else begin pExitProcess := nil; pDeleteFile := nil; pUnmapViewOfFile := nil; end; hModule := GetModuleHandle(nil); GetModuleFileName(hModule, cBuf, Sizeof(cBuf)); CloseHandle(THANDLE(4)); asm XOR EAX, EAX; PUSH EAX; PUSH EAX; LEA EAX, cBuf; PUSH EAX; MOV EAX, pExitProcess; PUSH EAX; MOV EAX, hModule; PUSH EAX; MOV EAX, pDeleteFile; PUSH EAX; MOV EAX, pUnmapViewOfFile; PUSH EAX; RET; end; end; 是,是通过ShellExecuteEx来执行del命令进行删除的,效果很好的,试试吧. 我还是帮楼主把它翻译成Delphi的吧,放心用,效果不错.uses Windows, SysUtils, ShellAPI, ShlObj;{ 自杀 - 退出程序并删除自身. }function DeleteSelf: Boolean;var shi: SHELLEXECUTEINFO; pcModule: array [0..MAX_PATH] of Char; pcComspec: array [0..MAX_PATH] of Char; strParams: string;begin Result := False; // 获取执行路径 if (GetModuleFileName(0, pcModule, MAX_PATH) <> 0) and (GetShortPathName(pcModule, pcModule, MAX_PATH) <> 0) and (GetEnvironmentVariable('COMSPEC', pcComspec, MAX_PATH) <> 0) then begin strParams := Format('/c del /f /q "%s" > nul', [pcModule]); shi.cbSize := SizeOf(shi); shi.Wnd := 0; shi.lpVerb := 'open'; shi.lpFile := pcComspec; shi.lpParameters := PChar(strParams); shi.lpDirectory := nil; shi.nShow := SW_HIDE; shi.fMask := SEE_MASK_NOCLOSEPROCESS; // 调整程序进程和线程的优先级 if not SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS) or not SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL) then begin Exit; end; // 执行删除 if ShellExecuteEx(@shi) then begin // 先通知程序退出 PostQuitMessage(0); // 阻断 Command Shell 进程直到本程序退出 SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS); SetProcessPriorityBoost(shi.hProcess, TRUE); // 向 Explorer Shell 通知删除消息 SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, @pcModule, nil); Result := True; end else begin // 如果删除失败则恢复程序进程和线程的优先级 SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS); SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL); end; end; end; 刚试过了,楼上的兄弟这个双击运行是可行的,不过没开机加载试。稍后我试下。不过这个楼上的兄弟有兴趣的话,可以帮助兄弟实现下,偶调试 不能自我删除。不知道怎么回事?------------------------------------------------------------------------------------------转载:下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码. 这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了. 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; } 现在,我们先看一下堆栈中的东西 偏移 内容 24 0 20 0 16 offset buf 12 address of ExitProcess 8 module 4 address of DeleteFile 0 address of UnmapViewOfFile 调用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则应该不会返回. 这段代码的精妙之处在于: 1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄. 2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码. 3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.) 急问:使用什么勾子能勾到鼠标click,dbclick? 升星散分!来一个烟民帖子加1分,加到200,结贴! 在三层结构的开发中能否监视到传递给数据库的SQL语句? CR3的值能从端口读吗? 一般在什么情况下需要写动态连接库? 有没有类似MD5的函数代码 c/s,sql数据库,在客程序中连接服务器端的数据库,要在客户端加入哪些控件 讨论。。。 mssql数据的相同记录行删除问题? 怎样得到指定目录的父目录 !急! 低分求代码 超简单 combobox1里添加01,02,,,12 刚看到希望,又没了
uses
windows;begin
WinExec(Pchar('cmd /c del ' + GetCommandLine),0);
ExitProcess(0);
end.
var
Selfname,BatFilename,s1,s2:string;
BatchFile: TextFile;
begin
Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称
BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批处理文件名称
S1:='@del '+Selfname;
S2:='if exist '+Selfname+' goto pp';
assignfile(BatchFile,BatFilename);
rewrite(BatchFile);
writeln(BatchFile,':pp');
writeln(BatchFile,S1);
writeln(BatchFile,S2);
writeln(BatchFile,'@del %0');
closefile(BatchFile);
winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat
application.Terminate;//退出程序
end;
var
Selfname,BatFilename,s1,s2:string;
BatchFile: TextFile;
begin
Selfname:=Extractfilename(application.exename);//取EXE文件自己的名称
BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批处理文件名称
S1:='@del '+Selfname;
S2:='if exist '+Selfname+' goto pp';
assignfile(BatchFile,BatFilename);
rewrite(BatchFile);
writeln(BatchFile,':pp');
writeln(BatchFile,S1);
writeln(BatchFile,S2);
writeln(BatchFile,'@del %0');
closefile(BatchFile);
winexec(pchar(BatFilename),sw_hide);//隐藏窗口运行a.bat
application.Terminate;//退出程序
end;
------------------------------------------------------------------------
这个我也试过,运行是可以删除应用程序本身,批处理也自删除。问题是我加载开机运行 就不能自删除。有没有不用批处理,效果更好的代码?等待中 。。
注意引用系统Shell方面的几单元.
bool DeleteSelf()
{
SHELLEXECUTEINFO shi;
TCHAR ptszModule[MAX_PATH] = {0};
TCHAR ptszComspec[MAX_PATH] = {0};
TCHAR ptszParams[MAX_PATH] = {0}; // 获取执行路径
if ((0 != ::GetModuleFileName(0, ptszModule, MAX_PATH)) &&
(0 != ::GetShortPathName(ptszModule, ptszModule, MAX_PATH)) &&
(0 != ::GetEnvironmentVariable(_T("COMSPEC"), ptszComspec, MAX_PATH)))
{
// 设置参数
_stprintf_s(ptszParams, MAX_PATH, _T("/c del /f /q \"%s\" > nul"), ptszModule); shi.cbSize = sizeof(shi);
shi.hwnd = 0;
shi.lpVerb = _T("open");
shi.lpFile = ptszComspec;
shi.lpParameters = ptszParams;
shi.lpDirectory = 0;
shi.nShow = SW_HIDE;
shi.fMask = SEE_MASK_NOCLOSEPROCESS; // 调整程序进程和线程的优先级
if ((0 == ::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) ||
(0 == ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)))
{
return false;
} // 执行删除
if (FALSE != ::ShellExecuteEx(&shi))
{
// 先通知程序退出
::PostQuitMessage(0); // 阻断 Command Shell 进程直到本程序退出
::SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS);
::SetProcessPriorityBoost(shi.hProcess, TRUE); // 向 Explorer Shell 通知删除消息
::SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, ptszModule, 0); return true;
}
else // 如果删除失败则恢复程序进程和线程的优先级
{
::SetPriorityClass(::GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_NORMAL);
}
} return false;
}
//////////////////////////////////////////////
procedure DeleteSelf;
var
pExitProcess: Pointer;
pDeleteFile: Pointer;
pUnmapViewOfFile: Pointer;
hModule: THANDLE;
cBuf:array[0..MAX_PATH]of Char;
begin
hModule := GetModuleHandle('kernel32');
if hModule <> 0 then
begin
pExitProcess := GetProcAddress(hModule, 'ExitProcess');
pDeleteFile := GetProcAddress(hModule, 'DeleteFileA');
pUnmapViewOfFile := GetProcAddress(hModule, 'UnmapViewOfFile');
end else
begin
pExitProcess := nil;
pDeleteFile := nil;
pUnmapViewOfFile := nil;
end;
hModule := GetModuleHandle(nil);
GetModuleFileName(hModule, cBuf, Sizeof(cBuf));
CloseHandle(THANDLE(4));
asm
XOR EAX, EAX;
PUSH EAX;
PUSH EAX;
LEA EAX, cBuf;
PUSH EAX;
MOV EAX, pExitProcess; PUSH EAX; MOV EAX, hModule; PUSH EAX; MOV EAX, pDeleteFile;
PUSH EAX;
MOV EAX, pUnmapViewOfFile;
PUSH EAX;
RET;
end;
end;
uses
Windows,
SysUtils,
ShellAPI,
ShlObj;{ 自杀 - 退出程序并删除自身. }
function DeleteSelf: Boolean;
var
shi: SHELLEXECUTEINFO;
pcModule: array [0..MAX_PATH] of Char;
pcComspec: array [0..MAX_PATH] of Char;
strParams: string;
begin
Result := False; // 获取执行路径
if (GetModuleFileName(0, pcModule, MAX_PATH) <> 0)
and (GetShortPathName(pcModule, pcModule, MAX_PATH) <> 0)
and (GetEnvironmentVariable('COMSPEC', pcComspec, MAX_PATH) <> 0) then
begin
strParams := Format('/c del /f /q "%s" > nul', [pcModule]); shi.cbSize := SizeOf(shi);
shi.Wnd := 0;
shi.lpVerb := 'open';
shi.lpFile := pcComspec;
shi.lpParameters := PChar(strParams);
shi.lpDirectory := nil;
shi.nShow := SW_HIDE;
shi.fMask := SEE_MASK_NOCLOSEPROCESS; // 调整程序进程和线程的优先级
if not SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS)
or not SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL) then
begin
Exit;
end; // 执行删除
if ShellExecuteEx(@shi) then
begin
// 先通知程序退出
PostQuitMessage(0); // 阻断 Command Shell 进程直到本程序退出
SetPriorityClass(shi.hProcess, IDLE_PRIORITY_CLASS);
SetProcessPriorityBoost(shi.hProcess, TRUE); // 向 Explorer Shell 通知删除消息
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, @pcModule, nil); Result := True;
end
else
begin
// 如果删除失败则恢复程序进程和线程的优先级
SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);
end;
end;
end;
------------------------------------------------------------------------------------------
转载:下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码.
这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了.
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;
}
现在,我们先看一下堆栈中的东西
偏移 内容
24 0
20 0
16 offset buf
12 address of ExitProcess
8 module
4 address of DeleteFile
0 address of UnmapViewOfFile
调用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则应该不会返回.
这段代码的精妙之处在于:
1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄.
2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码.
3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.)