home *** CD-ROM | disk | FTP | other *** search
- 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 <g>
- 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
-