☆Obaby's H4cking W0rld☆

Hack-Crack==Backdoors - RATs - Trojans // Binders-Packers - Rootkits

破解-黑客-零日漏洞-灰鸽子/上兴/PCShare-木马免杀-网站入侵-信息安全

2009年1月13日星期二

运行完毕后删除自己的程序

procedure DeleteSelf;
var
  module            : HMODULE;
  buf               : array[0..MAX_PATH - 1] of char;
  p                 : ULONG;
  hKrnl32           : HMODULE;
  pExitProcess, pDeleteFile, pFreeLibrary: pointer;
begin
  module := GetModuleHandle(nil);
  GetModuleFileName(module, buf, sizeof(buf));

  CloseHandle(THandle(4));

  p := ULONG(module) + 1;

  hKrnl32 := GetModuleHandle('kernel32');
  pExitProcess := GetProcAddress(hKrnl32, 'ExitProcess');
  pDeleteFile := GetProcAddress(hKrnl32, 'DeleteFileA');
  pFreeLibrary := GetProcAddress(hKrnl32, 'FreeLibrary');

  asm
    lea eax, buf
    push 0
    push 0
    push eax
    push pExitProcess
    push p
    push pDeleteFile
    push pFreeLibrary
    ret
  end;
end;
把DeleteSelf代码放在DPR文件的最后一句即可,程序关闭之后,就会自动删除文件!此外,如果要任何时候都删除Exe的话,可以配合ExitProc&TerminateProc全局变量和AddExitProc&AddTerminateProc来做到这一点!!这个过程的优点在于不需要一个临时文件,保密程度和技术方面都比较强的。当然,你也可以利用一个临时的批处理文件来达到目的!
procedure DeleteMe;
var
  BatchFile: TextFile;
  BatchFileName: string;
  ProcessInfo: TProcessInformation;
  StartUpInfo: TStartupInfo;
begin
  BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat';

  AssignFile(BatchFile, BatchFileName);
  Rewrite(BatchFile);

  Writeln(BatchFile, ':try');
  Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
  Writeln(BatchFile,
    'if exist "' + ParamStr(0) + '"' + ' goto try');
  Writeln(BatchFile, 'del %0');
  CloseFile(BatchFile);

  FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
  StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartUpInfo.wShowWindow := SW_HIDE;

  if CreateProcess(nil, PChar(BatchFileName), nil, nil,
    False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
    ProcessInfo) then
  begin
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
  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不被删除.) 
#include Windows.h

int main(int argc, char *argv[]) 
    HMODULE module = GetModuleHandle(0);
    CHAR buf[MAX_PATH];
    GetModuleFileName(module, buf, sizeof(buf));
    MessageBox(0,"Del Me","Test",MB_OK);
    CloseHandle((HANDLE)4);
    __asm {
        lea    eax, buf
        push    0
        push    0
        push    eax
        push    ExitProcess
        push    module
        push    DeleteFile
        push    UnmapViewOfFile
        ret
    }
    return 0; 
}
采用vc++6.0的控制台模式编译
运行该程序后自动把自己删掉

0 评论:

发表评论