-1

My OS is Windows 8.1 64 bit . My program is to inject a DLL file to a target process,and when this DLL file attached to a process , it will create a .txt file on D: and write some words into it and save .It is just a test.But when I compile my program as a 32 bit program and my DLL code is compiled as 32 bit , it succeed , it can create the file and save the content . But when I compile my code of DLL and my program as 64 bit , it hasnot throw any exception , all seems that it succeed . But you cannot find the .txt file it create . So , it fails , not excuting the things you want to do .

The follow is my code of my DLL

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

BOOL create();

BOOL APIENTRY DllMain( HMODULE hModule,
                   DWORD  ul_reason_for_call,
                   LPVOID lpReserved
                 )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
    create();
    break;
case DLL_PROCESS_DETACH:
    break;
}
return TRUE;
}


BOOL create()
{
wchar_t FileName[] = L"D:\\x64injecttest.txt";
HANDLE hFile = ::CreateFile(FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
    printf("createfile fails,the error code is:%u\n", GetLastError());
    system("PAUSE");
    return 0;
}

char str[] = "if you see this file,then you have success\n";
WriteFile(hFile, str, strlen(str) + 1, NULL, NULL);

CloseHandle(hFile);
return TRUE;
}

The follow is the code of my program

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<TlHelp32.h>


LPTHREAD_START_ROUTINE lpThreadProc;   //pointes to the address of LoadLibraryW API
typedef DWORD(WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnknown); //I inject DLL to other process with the NtCreateThreadEx API , and this function pointer would point to the address of this API 


DWORD SearchForTarget(wchar_t target[])
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);

HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
    printf("fails when createtoolhelp32snapshot,the error code is:%u\n", GetLastError());
    system("PAUSE");
    exit(-1);
}

BOOL b = ::Process32First(hSnap, &pe32);
while (b)
{
    printf("the process name is:%ws\n", pe32.szExeFile);
    printf("the process id is:%u\n", pe32.th32ProcessID);

    if (wcscmp(pe32.szExeFile, target) == 0)
        return pe32.th32ProcessID;

    b = Process32Next(hSnap, &pe32);
}

return -1;

}

BOOL InjectDLL(DWORD pid)
{

wchar_t DLLPath[] = L"C:\\Users\\Dell-pc\\Desktop\\x64InjectTest\\Debug\\DLL.dll";

DWORD length = wcslen(DLLPath);
DWORD trueLength = length * 2 + 2;

HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == INVALID_HANDLE_VALUE)
{
    printf("openprocess fails,the error code is:%u\n", GetLastError());
    system("PAUSE");
    exit(-1);
}

LPVOID pBaseAddress = ::VirtualAllocEx(hProcess, NULL, trueLength, MEM_COMMIT, PAGE_READWRITE);
if (pBaseAddress == NULL)
{
    printf("virtualallocex fails,the error code is:%u\n", GetLastError());
    system("PAUSE");
    exit(-1);
}

BOOL b = WriteProcessMemory(hProcess, pBaseAddress, DLLPath, trueLength, NULL);
if (b == 0)
{
    printf("writeprocessmemory fail,the error code is:%u\n", GetLastError());
    system("PAUSE");
    exit(-1);
}

HMODULE hModule = ::LoadLibrary(L"kernel32.dll");
lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, "LoadLibraryW");

HMODULE hNtdll = ::LoadLibrary(L"ntdll.dll");
pFunction pFunc = (pFunction)GetProcAddress(hNtdll, "NtCreateThreadEx");

printf("it is ready to create thread\n");

HANDLE hRemoteThread;
pFunc(&hRemoteThread, 0x1FFFFF, NULL, hProcess, lpThreadProc, pBaseAddress, FALSE, NULL, NULL, NULL, NULL);

if (hRemoteThread == NULL)
{
    printf("nrcreateprocessex fails,the error code is:%u\n", GetLastError());
    system("PAUSE");
    exit(-1);
}

WaitForSingleObject(hRemoteThread, INFINITE);

return TRUE;
}

int main()
{
wchar_t target[] = L"notepad.exe";   //inject my DLL to notepad.exe
DWORD pid = SearchForTarget(target);
if (pid == -1)
{
    printf("not find the target \n");
    system("PAUSE");
    return -1;
}
InjectDLL(pid);

system("PAUSE");

return 0;
}

I compile my code (both my program and my DLL ) as 32 bit , and run it on my Windows 8.1 64 bit OS , it succeed . But when I compile it (both my program and my DLL) as 64 bit , it hasnot throw any exception , and it seems it succeed , only except it has not create the file and write some words into it (and this is what should do when the DLL attached to the process ) . So , anyone know where the problem is ? One more thing , I use Visual Studio 2013 .

freedom3
  • 1
  • 1
  • 1
    Is the target a 64 bit process. You also ignore return value of NtCreateThreadEx. Don't. What is that value. – David Heffernan Oct 26 '16 at 07:04
  • FWIW your code leaks handles like crazy but perhaps you know and don't care. – David Heffernan Oct 26 '16 at 07:10
  • @DavidHeffernan it is the 64 bit notepad.exe , and I have also try to inject to the 64 bit Internet Explore.exe – freedom3 Oct 26 '16 at 07:13
  • And the return value? After all, in case of failure what is there to set hRemoteThread to NULL? – David Heffernan Oct 26 '16 at 07:41
  • you need simply debug injector and target process for understand where/why error – RbMm Oct 26 '16 at 08:15
  • @DavidHeffernan how to get the return value? And it cannot set hRemoteThread to NULL? [here](http://securityxploded.com/ntcreatethreadex.php) sets it to null – freedom3 Oct 26 '16 at 08:24
  • @DavidHeffernan I have debug it with x64dbg, the return value of it is `00000000C00000F2` . – freedom3 Oct 26 '16 at 08:34
  • @RbMm I debug it with x64dbg , I attach x64dbg to the target process (64 bit notepad.exe) , and I set the debug events to be break when DLL attachs . But it doesnot break . – freedom3 Oct 26 '16 at 08:39
  • That's `STATUS_INVALID_PARAMETER_4`, the 4th parameter is invalid. Failing to perform error checking is really poor. Injection is not easy. Ignoring the feedback doesn't make it easier. – David Heffernan Oct 26 '16 at 08:50
  • @DavidHeffernan So you mean the parameter `hProcess` is invalid? But when I call `VirtualAllocEx` and `WriteProcessMemory` , it doesnot throw any exception . – freedom3 Oct 26 '16 at 08:58
  • It's invalid in the eyes of `NtCreateThreadEx`. Of course, what the rules are for `NtCreateThreadEx` are unknown, it being undocumented. Why did you choose this particular injection method? So you can inject into a process in a different session? If you don't need to do that you can use other methods that use documented functions. – David Heffernan Oct 26 '16 at 09:04
  • @DavidHeffernan what other methods can inject to other process in a different session? – freedom3 Oct 26 '16 at 10:07
  • I didn't say that there were other methods. I asked if that was why you chose this method – David Heffernan Oct 26 '16 at 10:23
  • Are you sure that you have the correct signature for the 64-bit version of NtCreateThreadEx ? – Harry Johnston Oct 27 '16 at 03:19

2 Answers2

0

I'd guess that the line causing you the 32/64-bit problem in your example is the following.

lpThreadProc = (LPTHREAD_START_ROUTINE)::GetProcAddress(hModule, 
"LoadLibraryW");

This gives you the address of LoadLibraryW in your current process, not that target process. Given the target process is 64-bit, the address is 99.99999% going to be different.

Even within 32-bit processes you shouldn't generally assume that DLLs will always load into the same address footprint.

To get around your issue you will probably have to enumerate modules within the target process and find your entry point from there. There are API's to help with this. A google for GetRemoteProcAddress will also point you in the right direction.

That aside, there are many other issues with your loader. Personally I'd advise you to use one that someone else has already written. There used to be plenty of good loaders around that cover many of the caveats and have multiple injection mechanisms too.

djgandy
  • 1,125
  • 6
  • 15
0

Thanks everyone , I have solved the problem . About the function NtCreateThreadEx , the type of the 8th , 9th and 10 th paramter (the stacksize parameter, the dw1 parameter , the dw2 parameter) should be SIZE_T , not DWORD . If it is DWORD , the it has no problem when you compile the code as 32 bit , but it would not work if you compile it as 64 bit . So , this line of code should be written as below

typedef NTSTATUS (WINAPI *pFunction)(PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, SIZE_T dwStackSize, SIZE_T dw1, DWORD SIZE_T, LPVOID pUnknown);
freedom3
  • 1
  • 1