0

I have found a code that promises to intercept and detour calls to the TerminateProcess function and thus prevent my software from being killed directly from other program.

But this code is not working and I am still able to kill my process via other program.

Here is the last my attempt with a code I have found in this YouTube video:

PS: victim.exe is the killer program.

DLL

// DllRedirectAPI.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include <Windows.h>

BYTE MOV[10] = { 0x48, 0xB8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; 
BYTE JMP_RAX[2] = { 0xFF, 0xE0 }; 
#define BuffSizeX64 (sizeof(MOV) + sizeof(JMP_RAX))

BOOL Hook_Det_x64(char LibName[], char API_Name[], LPVOID NewFun) {
    DWORD OldProtect;
    DWORD64 OrgAddress = (DWORD64)GetProcAddress(LoadLibraryA(LibName), API_Name);
    if (OrgAddress == NULL) return 0;

    memcpy(&MOV[2], &NewFun, 8);
    VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, PAGE_EXECUTE_READWRITE, &OldProtect);
    memcpy((LPVOID)OrgAddress, MOV, sizeof(MOV));
    memcpy((LPVOID)(OrgAddress + sizeof(MOV)), JMP_RAX, sizeof(JMP_RAX));
    VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, OldProtect, &OldProtect);

    return 1;
}

int WINAPI MessageBoxAX(
    HWND hWnd,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType) {

    MessageBoxExA(0, "Hooked ...", "Mahmoud", 0, 0);
    return 999;
}

BOOL WINAPI DllMain(HMODULE hModule, DWORD Call_Reason, LPVOID lpReserved) {
    switch (Call_Reason) {
    case DLL_PROCESS_ATTACH:
        Hook_Det_x64("Kernel32.dll", "TerminateProcess", MessageBoxAX);
    }
    return 1;
}

INJECTOR

// Injector.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#include <comdef.h>

#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)


BOOL Inject(DWORD pID, const char * DLL_NAME);
DWORD GetTargetThreadIDFromProcName(const char * ProcName);

int main(int argc, char * argv[])
{
    //###############  CHANGE HERE ONLY   ###################
    char *Target_Process = "victim.exe"; //###
    //#######################################################



    char *buf;
    DWORD pID = GetTargetThreadIDFromProcName(Target_Process);
    buf = "DllRedirectAPI.dll";

    if (!Inject(pID, buf))
    {

        printf("DLL Not Loaded!");
    }
    else{
        printf("DLL is Injected in torget Process");
    }

    _getch();
    return 0;
}

BOOL Inject(DWORD pID, const char * DLL_NAME)
{
    HANDLE Proc;
    char buf[50] = { 0 };
    LPVOID RemoteString, LoadLibAddy;

    if (!pID)
        return false;

    Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
    if (!Proc)
    {
        sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
        printf(buf);
        return false;
    }

    LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");

    RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);

    CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);

    CloseHandle(Proc);
    return true;
}

DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
    PROCESSENTRY32 pe;
    HANDLE thSnapShot;
    BOOL retval, ProcFound = false;

    thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (thSnapShot == INVALID_HANDLE_VALUE)
    {
        printf("Error: Unable create toolhelp snapshot!");
        return false;
    }

    pe.dwSize = sizeof(PROCESSENTRY32);

    retval = Process32First(thSnapShot, &pe);
    while (retval)
    {
        if (_bstr_t(pe.szExeFile) == _bstr_t(ProcName))
        {
            return pe.th32ProcessID;
        }
        retval = Process32Next(thSnapShot, &pe);
    }
    return 0;
}

Can someone help me, telling me where I'm making a mistake?

My system is Windows 7 Ultimate 64 Bits.

Thanks in advance.

  • Are you certain TaskManager even uses `TerminateProcess()`? A lot of the features built into Windows don't use kernel32, but use the native API directly (which would be `NtTerminateProcess()` in this case.) – MrEricSir Nov 04 '15 at 01:52
  • 1
    AFAIK: In Windows, you cannot prevent your application from being closed if it's being killed – Tas Nov 04 '15 at 01:59
  • @Tas, and why the antivirus products for example, not can be killed? [see](http://i.imgur.com/i7aHuxs.png) –  Nov 04 '15 at 02:10
  • Probably for the simple reason that you don't have [permission](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx). Processes are created using security tokens. Pretty good chance you can't read their memory either. – Rollen Nov 04 '15 at 02:17
  • 1
    You might also be interested in this: http://security.stackexchange.com/questions/30985/create-a-unterminable-process-in-windows. Short answer is they don't prevent themselves _in code_ from being killed. – Tas Nov 04 '15 at 02:19
  • 3
    Your hook applies (assuming it even works as advertised) only to calls to `TerminateProcess` by the *process you load it in*. You're not loading it into Task Manager, so it doesn't affect Task Manager. – nobody Nov 04 '15 at 03:49
  • @AndrewMedico, Probably this must be the reason that not works. Could you give me an example of how to apply this function in Task Manager.? –  Nov 04 '15 at 14:07
  • 1
    Are you writing a virus? Else - WHY would you prevent user from terminating your process??? – Vlad Feinstein Nov 04 '15 at 19:31
  • As Andrew Medico says -- you need to execute this code inside the Task Manager process. One of the ways is to compile your code as a dll and inject it into the running instance of Task Manager via e.g. [process hacker](http://processhacker.sourceforge.net/) (the "Miscellaneous>Inject DLL..." function). – vlp Nov 05 '15 at 21:52
  • @vlp, I tested [this](https://www.youtube.com/watch?v=loxzk2XAA78) example, but don't worked in my computer. PS: I also have tested the x64 version of code that was left in comments of video. Where I'm making wrong? –  Nov 06 '15 at 00:22

1 Answers1

1

(Wanted to write a comment, but it got quite long...)

As @AndrewMedico says in the comment: You need to hook the TerminateProcess of the Task Manager process to prevent the Task Manager from terminating anything.


I suggest you the following approach:

  1. Try a simple DLL injection

    a/ Make a DLL which prints some text in its DllMain, e.g. printf("I am here\n"); fflush(stdout);

    b/ Try to inject it into some other command line process using the process hacker's Miscellaneous>Inject DLL...

    c/ Verify your DLL was executed inside the target process by checking it's standard output

  2. Try a simple API hook:

    a/ Make a command line application which waits for a key and then terminates itself using some variant of TerminateProcess(GetCurrentProcess(), 1);. Add code to print some text after the TerminateProcess call.

    b/ Run this application to verify the text after calling the TerminateProcess is not printed.

    c/ Hook the TerminateProcess before waiting for the key using, e.g. mhook. Print some text in the replacement function and then return. Do not call the original TerminateProcess here.

    d/ Run this application to verify the text inside the hook is printed and the text after the TerminateProcess call is printed as well (i.e. verify the process termination was suppressed).

  3. Combine the results of previous steps to reach your goal:

    a/ Put the hooking code from from step 2 into the DLL from step 1

    b/ Inject it into the application from step 2b (i.e. the one without the hook) while it is waiting for the key and verify the text after TerminateProcess is printed.

    c/ Enjoy (or debug/blame me)

Good luck!


EDIT>

OK, here is my view of what we have here:

  1. Code in the question:

    • (Is an application very similar to what I suggest in "2b")

    • Hooks the TerminateProcess and shows a message box instead.

    • Should display a message box when executed

    • (Looks like it is a 32-bit only version)

  2. YouTube video

    • Shows an application "Terminate process.exe" which terminates process given by name

    • After the "Injector.exe" is executed the application ceases to terminate the process and displays a message box instead (IMHO the "Injector.exe" injects a "DllFile.dll" into the running "Terminate process.exe")

  3. Source code for the injector in the YouTube comments

    • This code injects DLL "C:\DllRedirectAPI.dll" into the first process with name "victim.exe" it finds

    • (It does not inject into "Terminate process.exe", it does not use "DllFile.dll")

  4. Source code for the DLL in the YouTube comments

    • This code hooks function MessageBoxA that it shows a different message box instead. It is worth noting that the hook code itself calls the original MessageBoxA and takes the approach that it reverts the modification it did during the hooking, calls the original function and then re-applies the hook.

    • (It does not hook 'TerminateProcess' at all)

    • (Looks like it is a 32-bit only version)

  5. 64-bit version excerpts

    • Destructive hook of MessageBoxA (i.e. does not backup the original code)

    • The hook uses MessageBoxExA (which is intact) to display a different message box instead (i.e. it does not use the overwritten MessageBoxA)

    • (It does not hook 'TerminateProcess' at all)

    • (It is a 64-bit version)

Disclaimer: I am not that proficient with the topic to be 100% sure, feel free to correct/clarify me.


For the actual hooking I personally recommend to use the mhook library, which worked for me. It's documentation is worth reading as well.

See e.g. this for some alternatives (I have not tried any of them)...


EDIT>

This one works for me on Win XP inside VirtualBox:

#include <windows.h>
#include <stdio.h>
#include <mhook.h>

static BOOL WINAPI
(*_TerminateProcess)(
  _In_ HANDLE hProcess,
  _In_ UINT   uExitCode
) = NULL;

BOOL WINAPI
TerminateProcessImpl(
  _In_ HANDLE hProcess,
  _In_ UINT   uExitCode) {

    printf("\nBlocked\n"); fflush(stdout);
    return 0;
}

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved) {
    if(Reason==DLL_PROCESS_ATTACH) {
        printf("\nDLL attached!\n"); fflush(stdout);
        HMODULE h = LoadLibrary("Kernel32");
        if(h!=NULL) {
            printf("\nGot Kernel32!\n"); fflush(stdout);
            _TerminateProcess=(void*)GetProcAddress(h,"TerminateProcess");
            if(_TerminateProcess!=NULL) {
                printf("\nAbout to hook...\n"); fflush(stdout);
                if(Mhook_SetHook((void*)&_TerminateProcess, &TerminateProcessImpl)) {
                    printf("\nHooked OK!\n"); fflush(stdout);
                } else {
                    printf("\nHook failed!\n"); fflush(stdout);
                }
            }
        }
    }
    return TRUE;
}
Community
  • 1
  • 1
vlp
  • 7,811
  • 2
  • 23
  • 51
  • @vip, OK. About the Youtube video above that I left link, the injection made for Autor is only in `TaskMgr.exe` or on both process ('calc.exe' and `TaskMgr.exe`)? I don't understood this. –  Nov 06 '15 at 11:01
  • @Cloud.NET I would say it is into the `Terminate Process.exe`. The source code is _probably_ different than the one used for the video. (And BTW _probably_ not for a 64-bit system, given the 32-bit pointer). – vlp Nov 06 '15 at 11:14
  • @vip, Yes the code that I left above not is the same of video, is other that I captured on another site. But the autor this video also left a x64 code in comments, probably you saw. I also tested the x64 code, but without sucess. When you can, you also could test and tell me the test result? Probably I made some step wrong. –  Nov 06 '15 at 12:13
  • I have tested the `Detour_x64.h` that autor had left in comments of Youtube Video, injecting the dll on `Task Manager.exe` (victim.exe) of Windows (x64 in my case), but still this way not worked. You think that `Task Manager` of Windows have some protection against this technique? And I made all modifications on code for `kernel32.dll` and the api function `TerminateProcess`. And yes,I will go test the MHook library. –  Nov 06 '15 at 22:32
  • How did you inject the dll? Maybe it would be easier to test with your own process killer program (as in the YouTube video). And consider updating the question with your latest progress...other (more knowledgeable) people will help if they see you are working hard... – vlp Nov 08 '15 at 09:39
  • @Cloud.NET Did not test the code, but there is one obvious mistake in the injector...it should allocate `strlen()+1` bytes and copy `strlen()+1` bytes to copy the `0x00` byte terminating the string as well. As I have written in the answer....do add some text output to the DllMain when your dll is attached to be sure _the injection works_ (or use the process hacker). The sequence described in the answer has the property that in each step you are chasing just one rabbit...because if you chase two rabbits you lose them both. Good luck! – vlp Nov 08 '15 at 19:49
  • You could edit your answer with this suggestion of code that you said me in this last comment please? Because if this work, I already mark your answer as accepted! This code above, works fine with you? –  Nov 08 '15 at 22:26
  • @Cloud.NET Do you have any news? – vlp Nov 10 '15 at 19:54
  • here nothing works, already followed all yours hints, but without sucess until now. This code above works with you? –  Nov 10 '15 at 20:33
  • @Cloud.NET And what specifically does not work? Did you actually try to get it working using the suggested approach? This is not a do it for me site. Did you even try to output some text inside the `DllMain`? Was it shown? Did you try to inject the dll using the process hacker? I am afraid I can not help you as you do not do/share any progress (and I am not a mind-reader), – vlp Nov 10 '15 at 20:42
  • @Cloud.NET Another thing you can test is to use a virtual machine with 32-bit windows and test the 32-bit variant here – vlp Nov 10 '15 at 20:49
  • I have tested exactly as posted on code above, and only displays that "_The dll was injected with sucess_" (the injection works only if **victim.exe** is running), after this process I will open `calc.exe` for example, but **victim.exe** always is capable of kill `calc.exe`. Then, for this reason that I said that not works for me :-). PS: I have made with x64 code that the autor showed on Youtube Video above. –  Nov 10 '15 at 21:33
  • @Cloud.NET and did you test to inject the dll using the process hacker? – vlp Nov 10 '15 at 22:16
  • @Cloud.NET there is _probably_ another problem with the code.. the LoadLibrary should take `"Kernel32"` as an argument, not `"Kernel32.dll"`. See [here](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx). – vlp Nov 10 '15 at 22:19