Solution to Kee LUR-the process killer (tank_) by Verulam Introduction ------------ Well this is my solutoin to tank_'s ReverseMe Kee LUR.exe that can be found at reversemes.cjb.net The program requires an 'are you sure?' prompt and the code to kill the currenty selected process when the kill button is pressed. Tools ----- Softice WDASM DeDe HIEW Procdump Essay ----- First thing to do is to find out how to kill a process, you could search your API reference for functions that do such a thing or you could just do what I did, know of a program that does such a thing and dissasemble it (Procdump). Procdump gave me the two functions OpenProcess and TerminateProcess, there are a couple more used but I'll explain them later. The next thing to do was to fire up DeDe, a great little program which disassembles Delphi programs. This gave me: TForm1.Image1Click 45A2AC TForm1.Button3Click 45A29C TForm1.ComboBox1Click 45A0B0 TForm1.Button2Click 45A0A8 TForm1.Button1Click 45A074 TForm1.FormCreate 45A06C And also a disassembly of the code at each function. From the dissassembly Button1 is clearly the Kill Button. The first thing to do is to find some space for our 'are you sure?' dialog box. The about text you get when you click on the image mentions reversing and the readme.txt file both of which become irrelevant once we have finishded so I cut it short with a convieniently placed 0 and added my own 'Kill Task' and 'Are you sure?'. So this gives: 45A074: pushad 45A075: mov eax, 24 ; MB_ICONQUESTION | MB_YESNO 45A07A: push eax 45A07B: push 45A30B ; 'Kill Task' 45A080: jmp 45A570 ; need to find some more room 45A570: push 45A2FD ; 'Are you sure?' 45A575: xor eax, eax 45A577: push eax ; 0 = non-window specific, bad really 45A578: call MessageBoxA 45A57E: cmp eax, 7 ; IDNO 45A583: jz 45A5C6 45A585: push 12345678 ; a marker for pid, more about this later 45A58A: xor eax, eax 45A58C: mov al, 01 45A58E: push eax ; 2 parameters given from dis-asm of procdump 45A58F: push eax ; they are bound to work 45A590: push 45F6BC ; 'kernel32.dll' 45A595: call LoadLibraryA 45A59B: push 45A088 ; 'OpenProcess' 45A5A0: push eax 45A5A1: call GetProcAddress 45A5A7: call eax ; parameters are already on stack pid,01,01 45A5A9: xor ebx,ebx 45A5AB: push ebx ; exit code for process 45A5AC: push eax ; handle returned from openprocess 45A5AD: push 45F6BC ; 'kernel32.dll' a little redundant now 45A5B2: call LoadLibraryA 45A5B8: push 45A088 ; 'TerminateProcess' 45A5BD: push eax 45A5BE: call GetProcAddress 45A5C4: call eax ; again parameters already on stack 45A5C6: popad 45A578: ret I'll have to explain the push 12345678 The ProcessID value needed is based on which process is being displayed currently, the hwnd value is displayed as a string and is probably stored as one (it is if you look) so the value in hex is going to have to be pulled out and kept somewhere when the OnChange Event for the listbox fires. We need somewhere to store it and where better than the actual code we will use to kill it. So at startup and when the listbox changes we write the pid value to 45A586. This serves as quite a neat solution and if I didn't recall LoadLibrary and kept the return from the first it would be even better. So let's find the current ProcessID It's a safe bet that all the processing is done at startup and all the combobox does is write values to textboxes on selection. This is deduced from a) it's common practice when using a visual programming language. b) there is a refresh button which means the data isn't real-time/sampled. c) looking at the code at 45A0B0 so we need to know which process is currently selected, looking at the code starting at 45A0B0 we see: 45A0D7: call 0041FA24 45A0DC: inc eax 45A0DD: and eax, 000000FF 45A0E2: lea eax, dword ptr [eax+4*eax] 45A0E5: lea esi, dword ptr [8*eax+0045D874] 45A0EC: mov eax, dword ptr [esi] The call at 41FA24 returns 0 for the first item in the listbox, 1 for the second, 2 for the third and so on. A zero based array. All the + and * should be a big clue there's an array of structures involved and no self respecting reverse project would be started without a little research. To get a list of processes you can: CreateToolhelp32Snapshot, Process32First, Process32Next. The Process32 functions use a structure called PROCESSENTRY which with other important information contains the processid as the second structure entry so: 45A0E5: JMP 45A5C8 45A0EA: nop ; for neatness 45A0EB: nop ; or inc eax, dec eax if you wish and 45A5C8: lea esi, [eax*8+45D874] ; our overwritten code 45A5CF: push eax ; save eax 45A5D0: mov eax, [esi+08] ; the second structure entry 45A5D3: mov [45A586], eax ; self modifying code 45A5D8: pop eax ; restore eax 45A5D9: jmp 45A0EC ; jump to next instruction All that is left is to fire up procdump and edit the permissions for the code section replacing the 6 at the start with a C. This is done because by default you don't want to go messing with your code. Further Enhancements The code as it stands doesn't work as a program should, when you kill a process you need to hit the refresh button otherwise it is still listed and people my think they wern't able to kill it so: Add a call to 459EC0 before you return and it will refresh them. Another thing is to add a call to WaitForSingleObject specifying a process event in the call so the programm gives the process a bit of time to die before refreshing the list. ------- Verulam