; ---------------------------------------------------------------------------- ; process killer written in pure ASM. ; ; by urut , jan03 ; License: GPL. ; ; requires NASM and ALINK . uses NASM syntax. ; ---------------------------------------------------------------------------- ; ; compile with nasm+alink as following: ; nasm -fobj killer.asm ; ..\al\alink -subsys console -oPE killer.obj ..\al\kernel32Custom.lib ; ; ; ---------------------------------------------------------------------------- ; kernel32Custom.lib is made with alib. the alib.exe from the net only runs ; with an installed RSXNT environment (GCC port for win32) so better download ; the source of alib and re-compile it with some c++ compiler. ; ; ---------------------------------------------------------------------------- ; win32n.inc is from the win32asm package. ; ; ---------------------------------------------------------------------------- %include "win32n.inc" ;imports from kernel32.dll extern ExitProcess extern GetStdHandle extern WriteConsoleA extern TerminateProcess extern CreateToolhelp32Snapshot extern Process32First extern Process32Next extern AllocConsole extern OpenProcess extern GetLastError extern GetCommandLineA ;definitions from platform SDK struc PROCESSENTRY32 dwSize: resd 1 cntUsage: resd 1 th32ProcessID: resd 1 th32DefaultHeapID: resd 1 th32ModuleID: resd 1 cntThreads: resd 1 th32ParentProcessID: resd 1 pcPriClassBase: resd 1 dwFlags: resd 1 szExeFile: resb 260 endstruc PROCESS_ALL_ACCESS equ (STANDARD_RIGHTS_REQUIRED + SYNCHRONIZE + 0FFFh) ;------------------------------------------------------------------------------ segment .data USE32 %macro STRING 2+ %1: db %2 .end: %define %1.length %1.end - %1 %endmacro ;value is from TLHELP32.H TH32CS_SNAPPROCESS: db 0x00000002 NoErrorMsg: db 'No Error',8 msg: db 'Process Killer', 14 processHandle: db 0 ; handle to process written:db 0 written2:db 0 snapshot: resd 1 ; uninitialised data, 1 double word (resd) ;commandLine: dd 0 CONVERTRESULT: db 100 PID: dd 0 STRING welcomeMsg, 'Process Killer v0.0.1 by urut. License: GPL.',0Dh,0Ah STRING errorMsg, 'Error, something went wrong. Cant continue',0Dh,0Ah STRING successMsg, 'Successfull.', 0Dh, 0Ah STRING killingMsg, 'Killing:',0Dh,0Ah STRING noArgsMsg, 'No Arguments provided. provide PID as argument or - for list of PIDs',0Dh,0Ah STRING listingMsg, 'Listing Processes - not supported yet. Use taksmgr!',0Dh,0Ah STRING linebreakMsg, '', 0Dh, 0Ah STRING headerMsg, 'PID Name',0Dh,0Ah STRING spaceMsg, ' ' ;LPPROCESSENTRY32 for ProcessFirst/ProcessNext function calls lppe: istruc PROCESSENTRY32 at dwSize, dd 296 ; 296=sizeof(PROCESSENTRY32) at cntUsage, dd 1 at th32ProcessID, dd 1 at th32DefaultHeapID, dd 1 at th32ModuleID, dd 1 at cntThreads, dd 1 at th32ParentProcessID, dd 1 at pcPriClassBase, dd 1 at dwFlags, dd 1 at szExeFile, TIMES 260 db 0 iend ;------------------------------------------------------------------------------ segment .code USE32 ; util code ;puts and GetConsole is from an article about linked listes by mammon_ GetConsole: ;GetConsole() [section data] hConsole DD 0 [section code] call AllocConsole push dword -11 ; STD_OUTPUT_HANDLE EQU -11 call GetStdHandle mov [hConsole], eax xor eax, eax ret puts: ;puts( ptrString, NumBytes ) [section data] NumWrote DD 0 [section code] %define _ptrString ebp + 20 ; 16= offset because of additional push'es %define _strlen ebp + 24 push edx push ecx push ebx push ebp mov ebp,esp push eax push dword 0 push dword NumWrote mov eax, [ _strlen ] push dword eax mov eax, [ _ptrString ] push dword eax push dword [hConsole] call WriteConsoleA pop eax mov esp, ebp pop ebp pop ebx pop ecx pop edx ret 8 ;prints out details about a process entry. lppe must be set printoutInfo: mov ebx, [lppe+th32ProcessID] push dword CONVERTRESULT push dword ebx call dword2text push dword 5 push dword CONVERTRESULT call puts push dword spaceMsg.length push dword spaceMsg call puts mov ebx, lppe add ebx, 36 ; now identify process name. ; edx = position in string ; ecx = number of chars ; mov edx, ebx xor ecx,ecx ;zero counter @moreChars: inc ecx inc edx ;find zero cmp byte [edx],0 jne @moreChars push dword ecx push dword ebx call puts push dword linebreakMsg.length push dword linebreakMsg call puts ret 0 ..start call GetConsole ; GetStdHandle /AllocConsole push dword welcomeMsg.length push dword welcomeMsg call puts ;extract cmd line arguments call GetCommandLineA ;mov dword [commandLine], eax mov ebx,eax ;ebx holds commandLine!! ;debug:printout cmd line ;push dword 10 ;push dword ebx ;call puts ;find beginning of cmd line arg @again1: ;push dword 1 ;push dword ebx ;call puts cmp byte [ebx],' ' ; 0x20=space in hex je @found1 ; space found inc ebx jmp @again1 @found1: inc ebx mov ecx,ebx xor dl,dl ;zero, 8 bit registers ;find end of cmd line argument @again2: cmp byte [ecx],0 je @found2 inc ecx jmp @again2 @found2: dec ecx ;ebx contains start, ecx contains end ;test if there was an argument provided inc ebx cmp dword ebx, ecx je NEAR @noArgs dec ebx ;test if list was requested cmp dword [ebx],'-' je NEAR @listProcesses ;---------------------------------------------- ;now calculate PID as dword from string provided as cmd line argument mov edi, 1 ; init eax ;edx holds int number of PID ;edi holds position, starting with 1 (10^0=1, 10^1=10, 10^2=100 ....) dec ebx @convertContinue: xor eax,eax mov byte al, [ecx] ; get char sub eax, 48 ; convert to number from ASCII mul edi ; eax = eax*edi, multiply with 10^x add [PID], eax ; add to final result push ebx ;save ebx for later usage mov ebx,10 mov eax,edi ; next digit, 10^(x+1) mul ebx ; ; eax= eax*ebx; mov edi,eax ;edi=eax pop ebx ;restore ebx dec ecx cmp ebx,ecx je NEAR @killProcess jmp NEAR @convertContinue @listProcesses: push dword listingMsg.length push dword listingMsg call puts ;----- header push dword headerMsg.length push dword headerMsg call puts ;determine handle ;HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID); push dword 0 ;push dword TH32CS_SNAPPROCESS push dword 2 call CreateToolhelp32Snapshot ;handle to snapshot is now in eax, move to [snapshot] mov [snapshot], eax ;BOOL WINAPI Process32First(HANDLE hSnapshot,LPPROCESSENTRY32 lppe); push dword lppe push dword [snapshot] call Process32First ;returns true (1) if successful cmp eax,FALSE je NEAR @hasError ; jump if zero ;extract info call printoutInfo @nextEntry: ;BOOL WINAPI Process32Next(HANDLE hSnapshot,LPPROCESSENTRY32 lppe)); push dword lppe push dword [snapshot] call Process32Next cmp eax,FALSE je NEAR @noError ;finished ;extract info call printoutInfo jmp @nextEntry @killProcess: mov eax,[PID] push dword CONVERTRESULT push dword eax call dword2text push dword killingMsg.length push dword killingMsg call puts push dword 5 push dword CONVERTRESULT call puts push dword linebreakMsg.length push dword linebreakMsg call puts ;HANDLE OpenProcess( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); push dword eax ; process id push dword FALSE push dword PROCESS_ALL_ACCESS call OpenProcess cmp eax,NULL je @hasError ; jump if zero ;now kill it ; BOOL TerminateProcess( HANDLE hProcess, UINT uExitCode) push dword 0 push dword eax ; push return value of OpenProcess call which is the handle of the process call TerminateProcess cmp eax,NULL je @hasError ; jump if zero, kill didn't succeed jmp @noError @hasError: call GetLastError push dword errorMsg.length push dword errorMsg call puts jmp @end @noArgs: push dword noArgsMsg.length push dword noArgsMsg call puts jmp @end @noError: call GetLastError push dword successMsg.length push dword successMsg call puts jmp @end @end: ; ExitProcess(0) push dword 0 call ExitProcess ;--------------------- ;some supporting code (convert number to string) SECTION .code ; Params: push on the stack ; first param: dword to convert ; second param: result dword2text: push ebp mov ebp,esp pushad xor edx,edx xor ecx,ecx mov eax,[ebp+8] mov edi,[ebp+12] mov esi,g_mychar_table mov ebx,g_mysizes_table or eax,eax jg @L1 je @L3 mov byte [edi],'-' neg eax inc edi @L1: cmp eax,[ebx + ecx*4] jae @L2 inc ecx jmp short @L1 @L2: lea ebx,[ebx + ecx*4] @L4: idiv dword [ebx] add al,30h stosb xor eax,eax xchg edx,eax cmp dword [ebx],01h mov byte [edi],00h je @L5 add ebx,4 jmp short @L4 @L3: mov byte [edi],'0' mov byte [edi+1],0 @L5: popad leave ret 8 ; dword2text SECTION .data g_mychar_table db '0123456789',0 g_mysizes_table dd 1000000000, 100000000, 10000000 dd 1000000, 100000, 10000 dd 1000, 100, 10 dd 1, 0