IPB

Добро пожаловать, гость ( Вход | Регистрация )

> Самоудаляющийся .EXE файл, Self-Deleting Executable
-=CHE@TER=-
Jun 23 2007, 10:13
Сообщение #1


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



Вот, есть такая статья: Self-Deleting Executables.
Она рассказывает о нелёгких поисках способа удалить программно .EXE файл изнутри. Т.е. написать такую программу, которая сможет себя удалить, когда вы её запустите. Как известно в DOS такой проблемы не существует и я, в своё время, делал Uninstall'ер для своей программы, который удалял всё, включая и себя самого, ибо после запуска .EXE файл уже был не нужен. В Windows .EXE файл недоступен (занят системой) до тех пор, пока запущенная программа не прекратила работать, в частности удалить его тоже нельзя.
Из данной статьи я взял универсальный способ-пример, довольно оригинального решения, файл "selfdel05.c" и попытался переписать его на Delphi (оригинал можно взять по ссылке выше - см. Download source).
CODE
//
//  selfdel.c
//
//  Self deleting executable for Win9x/WinNT (all versions)
//
//  J Brown 1/10/2003
//
//  This source file must be compiled with /GZ turned OFF
//  (basically, disable run-time stack checks)
//
//  Under debug build this is always on (MSVC6)
//
//
Uses Windows;
// #pragma pack(push, 1)
// #define
Const CODESIZE = $200;
//
//  Structure to inject into remote process. Contains
//  function pointers and code to execute.
//
Type
     PSELFDEL = ^TSELFDEL;
     TSELFDEL = Packed Record
            ARG0: PSELFDEL; // pointer to self
         opCodes: Array[0..CODESIZE-1] Of Byte; // code
         hParent: THandle; // parent process handle
      fnWaitForSingleObject: Function(hHandle: THandle; dwMilliseconds: DWORD): DWORD; stdcall;
              fnCloseHandle: Function(hObject: THandle): BOOL; stdcall;
               fnDeleteFile: Function(lpFileName: PChar): BOOL; stdcall;
                    fnSleep: Procedure(dwMilliseconds: DWORD); stdcall;
              fnExitProcess: Procedure(uExitCode: UINT); stdcall;
          fnRemoveDirectory: Function(lpPathName: PChar): BOOL; stdcall;
             fnGetLastError: Function: DWORD; stdcall;
                    fRemDir: LongBool;
                 szFileName: Array[0..MAX_PATH-1] Of Char; // file to delete
     End;

//#pragma pack(pop)

{$ifdef _DEBUG}
//{$define FUNC_ADDR(func) (PVOID)(*(DWORD *)((BYTE *)func + 1) + (DWORD)((BYTE *)func + 5))}
{$else}
//{$define FUNC_ADDR(func) func}
{$endif}

//
//  Routine to execute in remote process.
//
procedure remote_thread(remote: PSELFDEL); stdcall;
Begin
  // wait for parent process to terminate
  remote^.fnWaitForSingleObject(remote^.hParent, INFINITE);
  remote^.fnCloseHandle(remote^.hParent);
  // try to delete the executable file
  while (not remote^.fnDeleteFile(remote^.szFileName)) Do
  Begin
    // failed - try again in one second's time
    remote^.fnSleep(1000);
  End;
  // finished! exit so that we don't execute garbage code
  remote^.fnExitProcess(0);
End;

//
//  Delete currently running executable and exit
//  
Function SelfDelete(fRemoveDirectory: LongBool): Boolean;
Var
    si: STARTUPINFO;
    pi: PROCESS_INFORMATION;
    context: TContext;
    oldProt: DWORD;
    local: TSELFDEL;
    entrypoint: DWORD;
    szExe: Array[0..MAX_PATH-1] Of Char;

    remdel: Pointer;
    dummy: dword;
Begin
  result:=FALSE;
  szExe:='explorer.exe'#0;
  //
  //  Create executable suspended
  //
  ZeroMemory(@si, SizeOf(si));
  si.cb:=SizeOf(si);
  if CreateProcess(Nil, szExe, Nil, Nil, False, CREATE_SUSPENDED Or IDLE_PRIORITY_CLASS, Nil, Nil, si, pi) Then
  Begin
    local.fnWaitForSingleObject := @WaitForSingleObject;
    local.fnCloseHandle         := @CloseHandle;
    local.fnDeleteFile          := @DeleteFile;
    local.fnSleep               := @Sleep;
    local.fnExitProcess         := @ExitProcess;
    local.fnRemoveDirectory     := @RemoveDirectory;
    local.fnGetLastError        := @GetLastError;

    local.fRemDir               := fRemoveDirectory;

    // Give remote process a copy of our own process handle
    DuplicateHandle(GetCurrentProcess, GetCurrentProcess, pi.hProcess, @local.hParent, 0, FALSE, 0);
    GetModuleFileName(0, local.szFileName, MAX_PATH);

    // copy in binary code
    remdel:=@remote_thread;
    move(remdel, local.opCodes, CODESIZE); //move(local.opCodes, @remdel, CODESIZE); {!}

    //
    // Allocate some space on process's stack and place
    // our SELFDEL structure there. Then set the instruction pointer
    // to this location and let the process resume
    //
    context.ContextFlags := CONTEXT_INTEGER Or CONTEXT_CONTROL;
    GetThreadContext(pi.hThread, context);

    // Allocate space on stack (aligned to cache-line boundary)
    entrypoint := (context.Esp - sizeof(TSELFDEL)) And Cardinal(Not $1F);
    
    //
    // Place a pointer to the structure at the bottom-of-stack
    // this pointer is located in such a way that it becomes
    // the remote_thread's first argument!!
    //
    local.Arg0:=Ptr(entrypoint); // local.Arg0 := TSELFDEL(entrypoint);

    context.Esp := entrypoint - 4; // create dummy return address
    context.Eip := entrypoint + 4; // offset of opCodes within structure

    // copy in our code+data at the exe's entry-point
    VirtualProtectEx(pi.hProcess, Ptr(entrypoint), sizeof(local), PAGE_EXECUTE_READWRITE, Ptr(oldProt));
    WriteProcessMemory(pi.hProcess, Ptr(entrypoint), Pointer(@local), sizeof(local), dummy);

    FlushInstructionCache(pi.hProcess, Ptr(entrypoint), sizeof(local));

    SetThreadContext(pi.hThread, context);

    // Let the process continue
    ResumeThread(pi.hThread);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    result:=TRUE;
  End;
End;

Begin
  SelfDelete(False);
End.

Однако, где-то я чего-то упустил, ибо программа запускается, но ничего не делает.
Кто-нибудь может помочь?
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
 
Reply to this topicStart new topic
Ответов
-=CHE@TER=-
Jun 28 2007, 11:45
Сообщение #2


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,355
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 311 раз(а)



Heim!
Неа, не работает. Мне нужны адреса функций именно из адресного пространства другого процесса.
Вот код, который я сделал:
CODE
Uses Windows;
{$APPTYPE CONSOLE}

Type
     TInitStruct = Packed Record
                      pExitProcess: Pointer;
                      pWaitForSingleObject: Pointer;
                      pSleep: Pointer;
                      pDeleteFile: Pointer;
                      pCloseHandle: Pointer;
                      hParent: THandle;
                      szFileName: Array[0..MAX_PATH-1] Of Char;
                   End;

Procedure SelfDel; Assembler;
Asm
  jmp @code
  @pExitProcess: dd 00
  @pWaitForSingleObject: dd 00
  @pSleep: dd 00
  @pDeleteFile: dd 00
  @pCloseHandle: dd 00
  @hParent: dd 00
  // MAX_PATH = 260 { windows.pas }
  @szFileName: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  nop
  nop
  nop
  nop
  @code:
  // ******************************
  // full injection code:
  lea eax, @hParent
  push eax
  push INFINITE
  call DWORD(@pWaitForSingleObject)
  lea eax, @hParent
  push eax
  call DWORD(@pCloseHandle)
  @delfile:
    push 03E8h // 1 sec
    call DWORD(@pSleep)
    lea eax, @szFileName
    push eax
    call DWORD(@pDeleteFile)
    test eax, eax
  jz @delfile
  xor eax,eax
  push eax
  call DWORD(@pExitProcess)
End;

Function GetCodeSize(P: PByte): Cardinal; Assembler;
Asm
  mov ebx, eax
  mov cl, 0C3h
  @loop:
  inc eax
  cmp [eax], cl
  jnz @loop
  sub eax, ebx
  inc eax
End;

{
used links:
http://www.codeproject.com/useritems/selfdel.asp
http://undocumented.ntinternals.net/
}
Function GetProcessEntryPointAddress(hProcess, hThread: THandle): Cardinal;
Var
    context: TContext;
    entry: LDT_ENTRY;
    read, dwFSBase, dwImageBase, dwOffset, dwOptHeaderOffset: Cardinal;
      dd: cardinal;
Begin
  //
  // get the current thread context
  //
  context.ContextFlags:=CONTEXT_FULL Or CONTEXT_DEBUG_REGISTERS;
  GetThreadContext(hThread, context);
  //
  // use the segment register value to get a pointer to
  // the TEB
  //
  GetThreadSelectorEntry(hThread, context.SegFs, entry);
  dwFSBase:=(entry.BaseHi ShL 24) Or (entry.BaseMid ShL 16) Or (entry.BaseLow);
  //
  // read the teb
  //
  WriteLn(ReadProcessMemory(hProcess, Ptr(dwFSBase + 48), @dd, 4, read)); {1}
  //
  // read the peb from the location pointed at by the teb
  //
  WriteLn(ReadProcessMemory(hProcess, Ptr(dd + 8), @dwImageBase, 4, read)); {2}
  //
  // figure out where the entry point is located;
  //
  WriteLn(ReadProcessMemory(hProcess, Ptr(dwImageBase + $3C), @dwOffset, 4, read)); {3}

  dwOptHeaderOffset:=(dwImageBase + dwOffset + 4 + 20);

  WriteLn(ReadProcessMemory(hProcess, Ptr(dwOptHeaderOffset + 16), @dd, 4, read)); {4}

  result:=dwImageBase + dd;
End;

Function DeleteSelf: Boolean;
Var
    InitStruct: TInitStruct;
       hKrnl32: HModule;
         dummy: Cardinal;
            St: String;
            Pt: PByte;
{---}
            si: STARTUPINFO;
            pi: PROCESS_INFORMATION;
      CodeSize, oldprot, entrypoint: Cardinal;
Begin
  result:=False;
  With InitStruct Do
    Begin
      hKrnl32:=GetModuleHandle('kernel32');
      pExitProcess:=GetProcAddress(hKrnl32, 'ExitProcess');
      pWaitForSingleObject:=GetProcAddress(hKrnl32, 'WaitForSingleObject');
      pSleep:=GetProcAddress(hKrnl32, 'Sleep');
      pDeleteFile:=GetProcAddress(hKrnl32, 'DeleteFileA');
      pCloseHandle:=GetProcAddress(hKrnl32, 'CloseHandle');
      FillChar(szFileName, MAX_PATH, 0);
      St:=ParamStr(0);
      Move(St[1], szFileName, Length(St));
      hParent:=0;
    End;

  ZeroMemory(@si, SizeOf(si));
  si.cb:=SizeOf(si);
  If CreateProcess(Nil, PChar('explorer.exe'), Nil, Nil, False, CREATE_SUSPENDED Or IDLE_PRIORITY_CLASS, Nil, Nil, si, pi) Then
    Begin
      DuplicateHandle(GetCurrentProcess, GetCurrentProcess, pi.hProcess, @InitStruct.hParent, 0, FALSE, 0);
      Pt:=@selfdel;
      Inc(Pt, 5); // offset to structure
      WriteLn(WriteProcessMemory(GetCurrentProcess, Pt, @InitStruct, SizeOf(InitStruct), dummy));
      Dec(Pt, 5); // restore offset to program start
      CodeSize:=GetCodeSize(Pt);

      entrypoint:=GetProcessEntryPointAddress(pi.hProcess, pi.hThread);

      oldprot:=0;
      VirtualProtectEx(pi.hProcess, Ptr(entrypoint), CodeSize, PAGE_EXECUTE_READWRITE, oldProt);
      WriteLn(WriteProcessMemory(pi.hProcess, Ptr(entrypoint), Pt, CodeSize, dummy));
      FlushInstructionCache(pi.hProcess, Ptr(entrypoint), CodeSize);
      ResumeThread(pi.hThread);
      CloseHandle(pi.hThread);
      CloseHandle(pi.hProcess);
      result:=True;
    End;
End;

Begin
  DeleteSelf;
  WriteLn('ready');
End.


При запуске, если в код, сразу вставить C3, чтобы процесс завершил работу - то всё ок.
А вот адреса API функций - левые. Их нужно именно как-то получить из запущенного процесса.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Сообщения в этой теме
-=CHE@TER=-   Самоудаляющийся .EXE файл   Jun 23 2007, 10:13
-=CHE@TER=-   Немного поправил исходный код с move() и ещё пара ...   Jun 23 2007, 16:27
Siberian GRemlin   А не проще сделать генералицю .bat'ника с кома...   Jun 24 2007, 10:50
-=CHE@TER=-   А не проще сделать генералицю .bat'ника с кома...   Jun 24 2007, 13:43
-=CHE@TER=-   Гм, так и знал. EntryPoint от explorer.exe я получ...   Jun 25 2007, 12:30
Heim   Заменил local.fnWaitForSingleObject = (FAR...   Jun 28 2007, 11:29
-=CHE@TER=-   Heim! Неа, не работает. Мне нужны адреса функц...   Jun 28 2007, 11:45
Xplorer   Исправленный код: Procedure SelfDel; Assembler; As...   Jun 28 2007, 13:32
-=CHE@TER=-   Исправленный код: <cut> Адреса в kernel32.d...   Jun 28 2007, 13:56
nickolayer   Ох ты. Потрясающе. Я честно скажу, последние три с...   Jun 30 2007, 09:50
Axsis   Чё-то я не совсем понял принцип работы этого кода....   Jul 3 2007, 07:17
-=CHE@TER=-   Чё-то я не совсем понял принцип работы этого кода....   Jul 3 2007, 08:47
Axsis   Сразу со 2-го пункта: ругаться могут не столько ан...   Jul 4 2007, 17:16
-=CHE@TER=-   Сразу со 2-го пункта: ругаться могут не столько ан...   Jul 5 2007, 09:23
Axsis   Я не знаю ни одного трейнера который бы патчил ко...   Jul 5 2007, 15:38
-=CHE@TER=-   Я не знаю ни одного трейнера который бы патчил код...   Jul 5 2007, 17:00
Axsis   Хех, конечно я не вручную его проверял, есть тако...   Jul 5 2007, 20:25
-=CHE@TER=-   Хех, конечно я не вручную его проверял, есть такой...   Jul 5 2007, 21:35


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 15th June 2024 - 09:14