//[Last update 2003-05-17] program DelSelf; uses Windows; procedure DeleteSelf; {$DEFINE XPVERSIONCHECK} { This code is only compatible with Windows 95, 98, Me and NT 4, 2000! No XP support, yet. If I find out how this could work, I'll update the code. If your code will definitely not run on XP, you may undefine the compiler variable XPVERSIONCHECK which will strip the version checking off the code :) Note, this version will only work, as long as the functions are imported through the import table. This is true for any Win32 app and Kernel32.dll! Anyway, if you introduce symbol names, that conflict with the function names, this code is likely to break! I am not sure wether this is possible at all for kernel32 functions, because kernel32.dll is implicitly bound, but maybe it is ... so be warned! Also, this code is only compatible with the i386 processor architecture. This becomes evident as soon as you recognise the assembler parts in the code. This code is PUBLIC DOMAIN!!! } var szModuleName: array[0..MAX_PATH - 1] of Char; pExitProcess, pDeleteFile, pFreeLibrary, pUnmapViewOfFile: Pointer; hModule: THandle; {$IFDEF XPVERSIONCHECK} osvi:TOSVersionInfo; {$ENDIF XPVERSIONCHECK} asm {$IFDEF XPVERSIONCHECK} // Check for version and exit if XP detected lea eax, osvi push eax // Set size member mov osvi.dwOSVersionInfoSize, $94 call GetVersionEx test eax, eax jz @@ExitThis // Version could not be determined! // Check for version 5 (2000, XP) cmp osvi.dwMajorVersion, 5 jl @@startthrough // Check for minor version greater or equal 1 (means XP or higher) cmp osvi.dwMinorVersion, 1 jl @@startthrough // else Exit @@ExitThis: call ExitProc @@startthrough: mov eax, osvi.dwPlatformId mov hModule, 0 cmp eax, VER_PLATFORM_WIN32_NT je @@foo1 mov hModule, $80000000 // 9x, Me @@foo1: push hModule {$ELSE XPVERSIONCHECK} call GetVersion push eax {$ENDIF XPVERSIONCHECK} (*** Get real address of ExitProcess ***) { Dereference the function addresses from the jump table: I'll briefly explain on this first function ('ExitProcess') Load effective address. EAX points to code like FF 25 XX XX XX XX -> jmp ds:XXXXXXXX } lea eax, [ExitProcess] { Ignore the jump instruction of 2 bytes size (i.e. FF 25) } mov eax, [eax+2] { EAX holds now the XX XX XX XX from above metacode, i.e. a pointer to the 'real' address } mov eax, [eax] { EAX now holds the 'real' address of the function ExitProcess within our realm } mov pExitProcess, eax { The following code works accordingly ...} (*** Get real address of DeleteFileA ***) lea eax, [DeleteFileA] mov eax, [eax+2] mov eax, [eax] mov pDeleteFile, eax (*** Get real address of FreeLibrary ***) lea eax, [FreeLibrary] mov eax, [eax+2] mov eax, [eax] mov pFreeLibrary, eax (*** Get real address of UnmapViewOfFile ***) lea eax, [UnmapViewOfFile] mov eax, [eax+2] mov eax, [eax] mov pUnmapViewOfFile, eax (*** Now the "main code" ***) push 0 call GetModuleHandleA mov hModule, eax (*** Got module handle of this instance ***) push MAX_PATH lea eax, szModuleName push eax push hModule call GetModuleFileNameA (*** szModuleName now holds the file name of our instance's module ***) (*** Checking for Windows 9x / Windows NT platform ***) pop eax test eax, $80000000 jz @@NTplatform //@@9xplatform: // Windows 95, 98, Me lea eax, szModuleName push System.ExitCode push 0 push eax push pExitProcess push hModule push pDeleteFile push pFreeLibrary ret @@NTplatform: // Windows NT, 2000 push 4 call CloseHandle; lea eax, szModuleName push System.ExitCode push 0 push eax push pExitProcess push hModule push pDeleteFile push pUnmapViewOfFile ret {$IFDEF XPVERSIONCHECK}{$UNDEF XPVERSIONCHECK}{$ENDIF} end; begin DeleteSelf; end. { Looking at the older code (without XP version check) from a disassembler ;) DeleteSelf proc near szModuleName = byte ptr -118h hModule = dword ptr -14h pUnmapViewOfFile= dword ptr -10h pFreeLibrary = dword ptr -0Ch pDeleteFile = dword ptr -8 pExitProcess = dword ptr -4 push ebp mov ebp, esp add esp, -118h lea eax, ExitProcess_JumpEntry mov eax, [eax+2] mov eax, [eax] mov [ebp+pExitProcess], eax lea eax, DeleteFile_JumpEntry mov eax, [eax+2] mov eax, [eax] mov [ebp+pDeleteFile], eax lea eax, FreeLibrary_JumpEntry mov eax, [eax+2] mov eax, [eax] mov [ebp+pFreeLibrary], eax lea eax, UnmapViewOfFile_JumpEntry mov eax, [eax+2] mov eax, [eax] mov [ebp+pUnmapViewOfFile], eax push 0 call GetModuleHandleA_0 mov [ebp+hModule], eax push 260 lea eax, [ebp+szModuleName] push eax push [ebp+hModule] call GetModuleFileNameA_1 call GetVersion test eax, 80000000h jz short NTplatform lea eax, [ebp+szModuleName] push ds:system_Exitcode push 0 push eax push [ebp+pExitProcess] push [ebp+hModule] push [ebp+pDeleteFile] push [ebp+pFreeLibrary] retn NTplatform: push 4 call CloseHandle_0 lea eax, [ebp+szModuleName] push ds:system_Exitcode push 0 push eax push [ebp+pExitProcess] push [ebp+hModule] push [ebp+pDeleteFile] push [ebp+pUnmapViewOfFile] retn DeleteSelf endp }