-3

I am using visual studios 2017 on windows 10 and I wrote a c++ program to open a handle to a process. The program runs and opens the process. I ran the program in the debugger and it looks like all the functions passed. However I know the DLL is not injecting because when I run this application on a 32 bit game. I can delete the test.dll I used which means it is not being used. Any suggestions on why this runs fine but is not injecting?

PS remThread is value 0x0000011c

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

#include "stdafx.h"
int InjectDLL(DWORD, string*);
int getDLLpath(string*);
int getPID(int*);
int getProc(HANDLE*, DWORD);
void enableSeDebug();

int main()
{
    //Escalate privlege 
    enableSeDebug();

    system("title Dll Injector");
    string dllPath = "";
    int PID = -1;

    getDLLpath(&dllPath);
    getPID(&PID);


    InjectDLL(PID, &dllPath);
    system("pause");
    return 0;
}

int getDLLpath(string* dllPath)
{
    cout << "Please enter the path to your DLL file\n";
    cin >> *dllPath;
    return 1;
}

int getPID(int* PID)
{
    cout << "Please enter the PID to your target process\n";
    cin >> *PID;
    return 1;
}

int getProc(HANDLE* handleToProc, DWORD pid)
{

    //Create a handle to the process
    *handleToProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
    if (*handleToProc != 0)
    {
        cout << "Unable to open process.\n";
        return -1;
    }
    else
    {
        cout << "process opened.\n";
        return 1;
    }
}


int InjectDLL(DWORD PID, string* dllPath)
{

    HANDLE handleToProc;
    LPVOID LoadLibAddr;
    LPVOID baseAddr;
    HANDLE remThread;

    //Get handle to process
    if (getProc(&handleToProc, PID) < 0)
        return -1;

    //Load kernel32 library
    LoadLibAddr = (LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");

    if (!LoadLibAddr)
        return -1;

    //Allocate memory for DLL injection
    baseAddr = VirtualAllocEx(handleToProc, NULL, dllPath->length(), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    if (!baseAddr)
        return -1;

    //Write dll path
    if (!WriteProcessMemory(handleToProc, baseAddr, dllPath, dllPath->length(), NULL))
        return -1;

    //Create remote thread
    remThread = CreateRemoteThread(handleToProc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, baseAddr, 0, NULL);

    if (!remThread)
        return -1;

    //Wait untill DLL exits then deallocate memmory
    WaitForSingleObject(remThread, INFINITE);

    //Freing memmory
    VirtualFreeEx(handleToProc, baseAddr, dllPath->length(), MEM_RELEASE);

    //Closing handles
    if (CloseHandle(remThread) == 0)
    {
        cout << "Failed to close handle to remote thread.\n";
        return -1;
    }

    if (CloseHandle(handleToProc) == 0)
    {
        cout << "Failed to close handle to target process.\n";
        return -1;
    }

    return 1;
}



void enableSeDebug()
{
    /////////////////////////////////////////////////////////
    //   Note: Enabling SeDebugPrivilege adapted from sample
    //     MSDN @ http://msdn.microsoft.com/en-us/library/aa446619%28VS.85%29.aspx
    // Enable SeDebugPrivilege
    HANDLE hToken = NULL;
    TOKEN_PRIVILEGES tokenPriv;
    LUID luidDebug;
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE)
    {
        if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug) != FALSE)
        {
            tokenPriv.PrivilegeCount = 1;
            tokenPriv.Privileges[0].Luid = luidDebug;
            tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            if (AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, 0, NULL, NULL) != FALSE)
        {
                // Always successful, even in the cases which lead to OpenProcess failure
                cout << "SUCCESSFULLY CHANGED TOKEN PRIVILEGES" << endl;
            }
            else
            {
                cout << "FAILED TO CHANGE TOKEN PRIVILEGES, CODE: " << GetLastError() << endl;
            }
        }
    }
    CloseHandle(hToken);
    // Enable SeDebugPrivilege
}

The above code can open a 32 bit process and runs without a function call failing but the DLL is not injecting?

User
  • 363
  • 7
  • 24
  • 3
    *not sure why* - begin from `GetLastError()` – RbMm Aug 19 '18 at 00:18
  • `if (!handleToProc == 0)` test is always true, since `handleToProc` is a valid pointer. Did you mean to check `*handleToProc`? – Igor Tandetnik Aug 19 '18 at 00:31
  • I changed the condition to *handleToProc != 0 and it still prints "unable to open process". I alsu used if(handleToProc) and the same result. – User Aug 19 '18 at 00:42
  • I have also tried enabling seDebugPrivelege and running as admin but didn't work. This is the sample i used https://stackoverflow.com/questions/2932461/windows-vista-windows-7-privilege-sedebugprivilege-openprocess – User Aug 19 '18 at 00:54
  • 1
    `0xcccccccc` means uninitialized stack memory: https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations – drescherjm Aug 19 '18 at 01:05
  • Ok, so that is happening because the function call to openProcc failed? – User Aug 19 '18 at 01:11
  • 1
    You still haven't called GetLastError – David Heffernan Aug 19 '18 at 05:56
  • Where is the `handleToProc` variable used by `main()` defined? It is not in the code shown – Remy Lebeau Aug 19 '18 at 06:01
  • I only included a snippet of my code but I just updated the question to show everything. – User Aug 19 '18 at 06:49
  • return value of `AdjustTokenPrivileges` no sense, need call and base only on`GetLasrError()` here – RbMm Aug 19 '18 at 08:23

3 Answers3

1

I was able to resolve my issue. When checking getProc I needed to do

int getProc(HANDLE* handleToProc, DWORD pid)
{

  //Create a handle to the process
  *handleToProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
  if (*handleToProc == NULL) //I changed this line to check for NULL
  {
      cout << "Unable to open process.\n";
      return -1;
  }
  else
  {
      cout << "process opened.\n";
      return 1;
  }
}

The second part I needed to change was my dllPath which was a string needed to be a char*. So when I wrote the DLL string it was a different encoding. Using a char* pointer fixed this and now the injector works.

User
  • 363
  • 7
  • 24
  • Using a `char` in Windows doesn't solve any character encoding issues, other than by coincidence. `char` is ambiguous (could be ASCII, ANSI, UTF-8, something else). Use a `wchar_t`, which represents a UTF-16LE code unit in Windows. – IInspectable Aug 21 '18 at 07:32
  • I looked at the process memmory using process hacker. Using string caused the data to be all messed up. When I used char* I could see the dll path in the target process memory. If or if not my explanation is accurate could be argued but having string didn't work for me. – User Aug 21 '18 at 13:13
  • Of course a `std::string` is a C++ class template. You cannot treat it as if it were just an array of characters. Replacing `std::string` with `char*` does not change the character encoding. It replaces one type for another. My previous comment still applies: Don't use `std::string` or `char*` in Windows. Use `std::wstring` or `wchar_t*`. – IInspectable Aug 21 '18 at 13:16
  • Ok, why not use char* though? – User Aug 21 '18 at 13:23
  • That is explained in my first comment. Its encoding is inherently ambiguous. – IInspectable Aug 21 '18 at 13:40
0

Um, I think the test in getProc should be:

if (*handleToProc == 0)
    ...

Plus what others have said in the comments about testing and reporting GetLastError.

There may be other problems, I only skimmed the code

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • So I can open a 32-bit process I am assuming because my application is 32 bit. I ran through the debugger on vs 2017 and everything runs and I get normal values. I put a system("pause") before closing the handles but I can tell the DLL didn't inject because deleting the DLL file does not tell me it is in use. – User Aug 19 '18 at 15:46
  • This is moot now, yes? – Paul Sanders Aug 21 '18 at 03:40
-1

Here You have, had to rewrite it to the more "proper" code. (Not pro tho). You had some problems with condition checking. All works for me.

#include <windows.h>
#include <iostream>
#include <tlhelp32.h>
#include <string>
using namespace std;

void getPID(DWORD&);
int  getProc(HANDLE&, DWORD);

int main()
{
    cout << "title Dll Injector" << endl;
    string dllPath = "";
    DWORD PID = NULL;
    HANDLE handleToProc = nullptr;

    getPID(PID);

    if (getProc(handleToProc, PID) < 0)
        return -1;


    //Lets check is the handle valid
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (hSnapshot) {
        PROCESSENTRY32 pe32;
        pe32.dwSize = sizeof(PROCESSENTRY32);
        if (Process32First(hSnapshot, &pe32)) {
            do {
                if (pe32.th32ProcessID == GetProcessId(handleToProc))
                {
                    wstring name = wstring(pe32.szExeFile);
                    wcout << "Process id: " << pe32.th32ProcessID << ", Exe filename: " << name << endl;
                }
            } while (Process32Next(hSnapshot, &pe32));
        }
        CloseHandle(hSnapshot);
    }

    //Cleanup is a must!
    CloseHandle(handleToProc);
    return 0;
}

//Create a handle to process
int getProc(HANDLE& handleToProc, DWORD pid)
{
    //Create a handle to the process
    handleToProc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
    if (handleToProc == nullptr)
    {
        DWORD error = GetLastError();

        cout << "Unable to open process. Error: " << error << "\n";
        return -1;
    }
    else
    {
        cout << "process opened.\n";
        return 0;
    }
}

//Get PID from user
void getPID(DWORD& PID)
{
    cout << "Please enter the PID to your target process\n";
    cin >> PID;
}

The problem was with the pointer to the handle assignment, and then later check for valid handle.

XoRdi
  • 1
  • 3
  • 1
    This does not answer the question that was asked. Besides, a good answer should at least explain, what's the issue, and how the proposed solution addresses it. Since you didn't identify the issue, the code you proposed doesn't solve it. See [answer] for help. – IInspectable Aug 19 '18 at 09:38