//[Last update 2004-06-05] #define WIN32_LEAN_AND_MEAN #define _DLL #define _MT #define UNICODE #include #pragma warning(push, 4) #pragma optimize("gsy",on) #pragma comment(lib,"kernel32.lib") #pragma comment(lib,"user32.lib") #if (_MSC_VER<1300) #pragma comment(linker,"/RELEASE") #endif #pragma comment(linker, "-opt:nowin98") #pragma comment(linker, "-entry:Main") #pragma comment(linker, "-opt:ref") #pragma comment(linker, "-merge:.rdata=.text") #pragma comment(linker, "-merge:.reloc=.text") #pragma comment(linker, "-subsystem:windows") void 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!!! */ CHAR szModuleName[MAX_PATH]; HMODULE hModule; DWORD pExitProcess, pDeleteFile, pFreeLibrary, pUnmapViewOfFile; #ifdef XPVERSIONCHECK OSVERSIONINFO osvi; #endif XPVERSIONCHECK __asm { /* Get call addresses */ mov eax, [ExitProcess] mov pExitProcess, eax mov eax, [DeleteFileA] mov pDeleteFile, eax mov eax, [FreeLibrary] mov pFreeLibrary, eax mov eax, [UnmapViewOfFile] mov pUnmapViewOfFile,eax #ifdef XPVERSIONCHECK // Check for version and exit if XP detected lea eax, osvi push eax // Set size member mov osvi.dwOSVersionInfoSize, 0x114 mov eax, [GetVersionEx] call eax test eax, eax jz ExitThis // Version could not be determined! // Check for version 5 (2000, XP) cmp osvi.dwMajorVersion, 0x5 jl startthrough // Check for minor version greater or equal 1 (means XP or higher) cmp osvi.dwMinorVersion, 0x1 jl startthrough jmp ExitThis startthrough: mov eax, osvi.dwPlatformId mov hModule, 0x0 cmp eax, VER_PLATFORM_WIN32_NT je foo1 mov hModule, 0x80000000 // 9x, Me foo1: push hModule #else XPVERSIONCHECK mov eax, [GetVersion] call eax push eax #endif XPVERSIONCHECK /*** Now the "main code" ***/ push 0x0 mov eax, [GetModuleHandleA] call eax mov hModule, eax /*** Got module handle of this instance ***/ push MAX_PATH lea eax, szModuleName push eax push hModule mov eax, [GetModuleFileNameA] call eax /*** szModuleName now holds the file name of our instance's module ***/ /*** Checking for Windows 9x / Windows NT platform ***/ pop eax test eax, 0x80000000 jz NTplatform //9xplatform: // Windows 95, 98, Me lea eax, szModuleName push 0x0 push 0x0 push eax push pExitProcess push hModule push pDeleteFile push pFreeLibrary ret NTplatform: // Windows NT, 2000 mov eax, [CloseHandle] push 0x4 call eax lea eax, szModuleName push 0x0 push 0x0 push eax push pExitProcess push hModule push pDeleteFile push pUnmapViewOfFile // else Exit #ifdef XPVERSIONCHECK ExitThis: #endif XPVERSIONCHECK ret #undef XPVERSIONCHECK } } void __cdecl Main(void) { DeleteSelf(); } /* Looking at the older code (without XP version check) from a disassembler ;) DeleteSelf proc near hModule = dword ptr -118h pDeleteFileA = dword ptr -114h pExitProcess = dword ptr -110h pUnmapViewOfFile= dword ptr -10Ch Filename = byte ptr -108h pFreeLibrary = dword ptr -4 push ebp mov ebp, esp sub esp, 118h push ebx push esi push edi mov eax, ds:ExitProcess mov [ebp+pExitProcess], eax mov eax, ds:DeleteFileA mov [ebp+pDeleteFileA], eax mov eax, ds:FreeLibrary mov [ebp+pFreeLibrary], eax mov eax, ds:UnmapViewOfFile mov [ebp+pUnmapViewOfFile], eax mov eax, ds:GetVersion call eax push eax push 0 mov eax, ds:GetModuleHandleA call eax mov [ebp+hModule], eax push 104h lea eax, [ebp+Filename] push eax push [ebp+hModule] mov eax, ds:GetModuleFileNameA call eax ; GetModuleFileNameA pop eax test eax, 80000000h jz short NTplatform lea eax, [ebp+Filename] push 0 push 0 push eax push [ebp+pExitProcess] push [ebp+hModule] push [ebp+pDeleteFileA] push [ebp+pFreeLibrary] retn NTplatform: mov eax, ds:CloseHandle push 4 call eax ; CloseHandle lea eax, [ebp+Filename] push 0 push 0 push eax push [ebp+pExitProcess] push [ebp+hModule] push [ebp+pDeleteFileA] push [ebp+pUnmapViewOfFile] retn DeleteSelf endp */