CreateRemoteThread, doesn't start a thread - c

I use this function as usual, but the debug traces (OutputDebugString) don't work from injecting dlls. And in the target application no thread is created (I look through the process hacker)
GetlastError says 0
CreateRemoteThread says tid
but WaitForSingleObject exits immediately (why if all ok!?)
... I'm confused %
OS windows 10 x64
app and dll - x86
code dll is:
#include <stdio.h>
#include <windows.h>
WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID res)
{
CHAR pszMessage[1024] = { 0 };
sprintf(pszMessage, ("L2Proj: GetCurrentProcessId() %d, hModule 0x%p, nReason %d\r\n"), GetCurrentProcessId(), h, reason);
OutputDebugString(pszMessage);
switch(reason) {
case DLL_PROCESS_ATTACH:
//MessageBoxA(NULL, "inject success", "done", MB_OK);
TerminateProcess(GetCurrentProcess(), -1);
break;
}
return TRUE;
}
PS TerminateProcess in dll doesn't work either
PPS GetExitCodeThread() after WaitForSingleObject ends is 0
What it the problem with?
ADDED
APP code is:
NOTE: This is just test code (no control over return values ​​/ wrong label name codestyle etc.), pls do not tell me about it.
I wrote step by step in the comments which functions return which values
// process of course has access
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
// handle is valid
if(!hProcess) {
return GetLastError();
}
DWORD id;
char str[] = "G:\\workspace\\proj\\test.dll";
void *l = (void*)GetProcAddress(
GetModuleHandle("kernel32.dll"), "LoadLibraryA");
// addr is valid
if(!l) {
return 35;
}
DWORD str_size = strlen(str) + 1;
// memory addr is valid
LPVOID lp = VirtualAllocEx(hProcess, NULL, str_size, MEM_COMMIT |
MEM_RESERVE, PAGE_READWRITE);
BOOL res = WriteProcessMemory(hProcess, lp, str, str_size, NULL);
// res is true
HANDLE h = CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)l,
lp,
0,
&id);
// handle is valid
// id is valid (tid remote thread)
if(!h) {
return GetLastError();
}
DWORD err = GetLastError();
CHAR pszMessage[1024] = { 0 };
sprintf(pszMessage, ("L2Proj: GetProcessId() %d\r\n"), id);
OutputDebugString(pszMessage);
// ends immediately (no waiting)
WaitForSingleObject(h, INFINITE);
GetExitCodeThread(h, &id);
//id is 0 (exit code)
sprintf(pszMessage, ("L2Proj: GetExitCodeThread() %d (GetLastError=%d)\r\n"), id, err);
OutputDebugString(pszMessage);
// the only error after this function (VirtualFreeEx)
// GetLastError gives 87 (0x57) - ERROR_INVALID_PARAMETER
VirtualFreeEx(hProcess, lp, 0, MEM_RELEASE);
CloseHandle(h);
CloseHandle(hProcess);
I forgot, i use g++ (GCC) 9.3.0 - maybe the problem is because of this?

I solved the problem, just change the compiler.
Yes, the problem was with the compiler, everything works fine on the Microsoft compiler.
Thanks for answers.
problem in you not use debugger – RbMm yesterday
and yes, I always use the debugger, thanks a lot ...

Related

Windows DLL injector in C doesn't inject the DLL

I am trying to write a DLL injector to perform a DLL injector on a calculator process.
I wrote the DLL injector program in C and the DLL but the injector dosent inject the DLL or any other DLL (I tried to take some random windows DLL that the calculator doesn't use).
#include <stdio.h>
#include <Windows.h>
int main() {
LPCSTR dllpath = "C:\\Users\\......\\Dll1.dll";
printf("#### Starting ####\n");
printf("step 1: attaching the target process memory\n");
HANDLE hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
6456 // target process id
);
if (hProcess != NULL) {
printf("step 2: allocate the target memory process\n");
LPVOID dllPathMemoryAddr = VirtualAllocEx(
hProcess,
NULL,
strlen(dllpath),
MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE
);
if (dllPathMemoryAddr != NULL) {
printf("step 3: write to the process memory\n");
BOOL succeededWriting = WriteProcessMemory(
hProcess,
dllPathMemoryAddr,
dllpath,
strlen(dllpath),
NULL
);
if (succeededWriting) {
printf("step 4: execute.\n");
FARPROC loadLibAddr = GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"LoadLibraryA"
);
HANDLE rThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)loadLibAddr,
dllPathMemoryAddr,
0,
NULL
);
}
}
CloseHandle(hProcess);
}
return TRUE;
}
after running the injector I get this output:
#### Starting ####
step 1: attaching the target process memory
step 2: allocate the target memory process
step 3: write to the process memory
step 4: execute.
after that, I am still unable to see in process explorer the new DLL.
You are calling GetProcAddress() to get the address of LoadLibraryA(), this is returning the address of LoadLibraryA in your local process not the injected one. This is not guaranteed to be correct in the external process. You do not need to get the address manually, CreateRemoteThread will resolve the address for you.
Here is a very simple injector example that will explain how to do it
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
DWORD GetPid(char * targetProcess)
{
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap && snap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(snap, &pe))
{
do
{
if (!_stricmp(pe.szExeFile, targetProcess))
{
CloseHandle(snap);
return pe.th32ProcessID;
}
} while (Process32Next(snap, &pe));
}
}
return 0;
}
int main()
{
char * dllpath = "C:\\Users\\me\\Desktop\\dll.dll";
char * processToInject = "csgo.exe";
long pid = 0;
while (!pid)
{
pid = GetPid(processToInject);
Sleep(10);
}
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (hProc && hProc != INVALID_HANDLE_VALUE)
{
void * loc = VirtualAllocEx(hProc, 0, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(hProc, loc, dllpath, strlen(dllpath) + 1, 0);
HANDLE hThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, loc, 0, 0);
CloseHandle(hThread);
}
CloseHandle(hProc);
return 0;
}
I found the problem. I compiled the DLL as 64 but accidentally compiled the DLL injector has complied as 32 bit.

CreateFile over USB HID device fails with Access Denied (5) since Windows 10 1809

Since the latest Windows 10 1809 update we can no longer open a USB HID keyboard-like device of ours using CreateFile. We reduced the problem to this minimal example:
#include <windows.h>
#include <setupapi.h>
#include <stdio.h>
#include <hidsdi.h>
void bad(const char *msg) {
DWORD w = GetLastError();
fprintf(stderr, "bad: %s, GetLastError() == 0x%08x\n", msg, (unsigned)w);
}
int main(void) {
int i;
GUID hidGuid;
HDEVINFO deviceInfoList;
const size_t DEVICE_DETAILS_SIZE = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH;
SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = alloca(DEVICE_DETAILS_SIZE);
deviceDetails->cbSize = sizeof(*deviceDetails);
HidD_GetHidGuid(&hidGuid);
deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if(deviceInfoList == INVALID_HANDLE_VALUE) {
bad("SetupDiGetClassDevs");
return 1;
}
for (i = 0; ; ++i) {
SP_DEVICE_INTERFACE_DATA deviceInfo;
DWORD size = DEVICE_DETAILS_SIZE;
HIDD_ATTRIBUTES deviceAttributes;
HANDLE hDev = INVALID_HANDLE_VALUE;
fprintf(stderr, "Trying device %d\n", i);
deviceInfo.cbSize = sizeof(deviceInfo);
if (!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i,
&deviceInfo)) {
if (GetLastError() == ERROR_NO_MORE_ITEMS) {
break;
} else {
bad("SetupDiEnumDeviceInterfaces");
continue;
}
}
if(!SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo,
deviceDetails, size, &size, NULL)) {
bad("SetupDiGetDeviceInterfaceDetail");
continue;
}
fprintf(stderr, "Opening device %s\n", deviceDetails->DevicePath);
hDev = CreateFile(deviceDetails->DevicePath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if(hDev == INVALID_HANDLE_VALUE) {
bad("CreateFile");
continue;
}
deviceAttributes.Size = sizeof(deviceAttributes);
if(HidD_GetAttributes(hDev, &deviceAttributes)) {
fprintf(stderr, "VID = %04x PID = %04x\n", (unsigned)deviceAttributes.VendorID, (unsigned)deviceAttributes.ProductID);
} else {
bad("HidD_GetAttributes");
}
CloseHandle(hDev);
}
SetupDiDestroyDeviceInfoList(deviceInfoList);
return 0;
}
It enumerates all HID devices, trying to obtain the vendor ID/product ID for each one using CreateFile over the path provided by SetupDiGetDeviceInterfaceDetail and then calling HidD_GetAttributes.
This code runs without problems on previous Windows versions (tested on Windows 7, Windows 10 1709 and 1803, and the original code from which this was extracted works since always from XP onwards), but with the latest update (1809) all keyboard devices (including ours) cannot be opened, as CreateFile fails with access denied (GetLastError() == 5). Running the program as administrator doesn't have any effect.
Comparing the output before and after the update, I noticed that the devices that now cannot be opened gained a trailing \kbd in the device path, i.e. what previously was
\\?\hid#vid_24d6&pid_8000&mi_00#7&294a3305&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
now is
\\?\hid#vid_24d6&pid_8000&mi_00#7&294a3305&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}\kbd
Is it a bug/new security restriction in the latest Windows 10 version? Was this code always wrong and it worked by chance before? Can this be fixed?
Update
As a desperate attempt, we tried to remove the \kbd from the returned string... and CreateFile now works! So, now we have a workaround, but it would be interesting to understand if that's a bug in SetupDiGetDeviceInterfaceDetail, if it's intentional and if this workaround is actually the correct thing to do.
I think this is a new security restriction in the latest Windows 10 version.
I looked for the string KBD (in UTF-16 format) - it exists only in two drivers in version 1809, hidclass.sys and kbdhid.sys, and doesn't exist in version 1709.
In hidclass.sys they changed the HidpRegisterDeviceInterface function. Before this release it called IoRegisterDeviceInterface with GUID_DEVINTERFACE_HID and the ReferenceString pointer set to 0. But in the new version, depending on the result of GetHidClassCollection, it passes KBD as ReferenceString pointer.
Inside kbdhid.sys they changed KbdHid_Create, and here is a check for the KBD string to return errors (access denied or sharing violation).
To understand more exactly why, more research is needed. Some disasm:
For reference, HidpRegisterDeviceInterface from 1709 build
here ReferenceString == 0 always (xor r8d,r8d), and there's no check cmp word [rbp + a],6 on class collection data
However, KbdHid_Create in 1809 contains a bug. The code is:
NTSTATUS KbdHid_Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
//...
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (PFILE_OBJECT FileObject = IrpSp->FileObject)
{
PCUNICODE_STRING FileName = &FileObject->FileName;
if (FileName->Length)
{
#if ver == 1809
UNICODE_STRING KBD = RTL_CONSTANT_STRING(L"KBD"); // !! bug !!
NTSTATUS status = RtlEqualUnicodeString(FileName, &KBD, FALSE)
? STATUS_SHARING_VIOLATION : STATUS_ACCESS_DENIED;
#else
NTSTATUS status = STATUS_ACCESS_DENIED;
#endif
// log
Irp->IoStatus.Status = status;
IofCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
}
// ...
}
What it this function trying to do here? It looks for passed PFILE_OBJECT FileObject from Irp current stack location. It no FileObject is provided or it has an empty name, allow open; otherwise, the open fails.
Before 1809 it always failed with error STATUS_ACCESS_DENIED (0xc0000022), but starting from 1809, the name is checked, and if it's equal to KBD (case sensitive) another error - STATUS_SHARING_VIOLATION is returned. However, name always begins with the \ symbol, so it will never match KBD. It can be \KBD, so, to fix this check, the following line needs to be changed to:
UNICODE_STRING KBD = RTL_CONSTANT_STRING(L"\\KBD");
and perform the comparison with this string. So, by design we should have got a STATUS_SHARING_VIOLATION error when trying to open a keyboard device via *\KBD name, but due to an implementation error we actually got STATUS_ACCESS_DENIED here
Another change was in HidpRegisterDeviceInterface - before the call to IoRegisterDeviceInterface on the device it queries the GetHidClassCollection result, and if some WORD (2 byte) field in the structure is equal to 6, adds KBD suffix (ReferenceString). I guess (but I'm not sure) that 6 can be the Usage ID for keyboard, and the rationale for this prefix is to set Exclusive access mode
Actually, we can have a FileName begin without \ if we use relative device open via OBJECT_ATTRIBUTES. So, just for test, we can do this: if the interface name ends with \KBD, first open the file without this suffix (so with empty relative device name), and this open must work ok; then, we can try relative open file with name KBD - we must get STATUS_SHARING_VIOLATION in 1809 and STATUS_ACCESS_DENIED in previous builds (but here we will be have no \KBD suffix):
void TestOpen(PWSTR pszDeviceInterface)
{
HANDLE hFile;
if (PWSTR c = wcsrchr(pszDeviceInterface, '\\'))
{
static const UNICODE_STRING KBD = RTL_CONSTANT_STRING(L"KBD");
if (!wcscmp(c + 1, KBD.Buffer))
{
*c = 0;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, const_cast<PUNICODE_STRING>(&KBD) };
oa.RootDirectory = CreateFileW(pszDeviceInterface, 0,
FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (oa.RootDirectory != INVALID_HANDLE_VALUE)
{
IO_STATUS_BLOCK iosb;
// will be STATUS_SHARING_VIOLATION (c0000043)
NTSTATUS status = NtOpenFile(&hFile, SYNCHRONIZE, &oa, &iosb,
FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
CloseHandle(oa.RootDirectory);
if (0 <= status)
{
PrintAttr(hFile);
CloseHandle(hFile);
}
}
return ;
}
}
hFile = CreateFileW(pszDeviceInterface, 0,
FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
PrintAttr(hFile);
CloseHandle(hFile);
}
}
void PrintAttr(HANDLE hFile)
{
HIDD_ATTRIBUTES deviceAttributes = { sizeof(deviceAttributes) };
if(HidD_GetAttributes(hFile, &deviceAttributes)) {
printf("VID = %04x PID = %04x\r\n",
(ULONG)deviceAttributes.VendorID, (ULONG)deviceAttributes.ProductID);
} else {
bad(L"HidD_GetAttributes");
}
}
In a test on 1809 I actually got STATUS_SHARING_VIOLATION, that also shows another bug in kbdhid.KbdHid_Create - if we check FileName, we need to check RelatedFileObject - is it 0 or not.
Also, not related to bug, but as suggestion: it is more efficient to use CM_Get_Device_Interface_List instead of the SetupAPI:
volatile UCHAR guz = 0;
CONFIGRET EnumInterfaces(PGUID InterfaceClassGuid)
{
CONFIGRET err;
PVOID stack = alloca(guz);
ULONG BufferLen = 0, NeedLen = 256;
union {
PVOID buf;
PWSTR pszDeviceInterface;
};
for(;;)
{
if (BufferLen < NeedLen)
{
BufferLen = RtlPointerToOffset(buf = alloca((NeedLen - BufferLen) * sizeof(WCHAR)), stack) / sizeof(WCHAR);
}
switch (err = CM_Get_Device_Interface_ListW(InterfaceClassGuid,
0, pszDeviceInterface, BufferLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
case CR_BUFFER_SMALL:
if (err = CM_Get_Device_Interface_List_SizeW(&NeedLen, InterfaceClassGuid,
0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
default:
return err;
}
continue;
case CR_SUCCESS:
while (*pszDeviceInterface)
{
TestOpen(pszDeviceInterface);
pszDeviceInterface += 1 + wcslen(pszDeviceInterface);
}
return 0;
}
}
}
EnumInterfaces(const_cast<PGUID>(&GUID_DEVINTERFACE_HID));
The fix is in this windows update released today (March 1, 2019).
https://support.microsoft.com/en-us/help/4482887/windows-10-update-kb4482887
You can find a workaround at Delphi-Praxis in German
For short: Change in the Unit JvHidControllerClass
if not HidD_GetAttributes(HidFileHandle, FAttributes) then
raise EControllerError.CreateRes(#RsEDeviceCannotBeIdentified);
to
HidD_GetAttributes(HidFileHandle, FAttributes);
and recompile the Delhi JCL and JCVL Components by running the JEDI Install EXE.

my dll injection . succeed when compiled as 32 bit , but failed when compiled as 64 bit

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 .
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.
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);

Injecting DLL and printing a message

I'm dealing with 2 new things: writing a DLL and injecting it in another process. I think I inject it successfully because if I try to delete it I get a message that tells me it is used by another program.
I followed this steps in Visual Studio 2008 http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx but I wrote it in C, not C++.
And this is the code
DWORD
APIENTRY
DllMain(
HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
printf("Hello World\n");
Sleep(5000); // added this to make sure I see it when it happens
return TRUE;
}
I created an application that references the DLL just like in the MSDN documentation said and it works (it prints Hello World).
At each step in my DLL injection program I check for errors and print them. So I know that no function fails.
I check the exit code and it is 1927086080 which I don't know what means.
I don't know if it's needed, but here is the C source for my program.
#include <stdio.h>
#include <windows.h>
#include <string.h>
int main(int argc, TCHAR* argv[])
{
DWORD procId = 0;
DWORD pathLen = 0;
DWORD writeProcMemory = 0;
DWORD exitCode = 0;
HANDLE hProc = NULL;
HANDLE hDll = NULL;
HANDLE hThread = NULL;
LPVOID baseAdr = NULL;
LPVOID fAdr = NULL;
procId = atoi((char*)argv[1]);
pathLen = strlen((LPCSTR)argv[2]);
if(0 == pathLen)
{
printf("Check DLL path\n");
return 0;
}
// Open process
hProc = OpenProcess(PROCESS_ALL_ACCESS,
0,
procId);
if(NULL == hProc)
{
printf("OpenProcess failed\nGetLastError() = %d\n",
GetLastError());
return 0;
}
// Allocate memory
baseAdr = VirtualAllocEx(hProc,
0,
pathLen + 1,
MEM_COMMIT,
PAGE_READWRITE);
if(NULL == baseAdr)
{
printf("VirtualAllocEx failed\nGetLastError() = %d\n",
GetLastError());
CloseHandle(hProc);
return 0;
}
// write my dll path in the memory I just allocated
if(!WriteProcessMemory(hProc,
baseAdr,
argv[2],
pathLen + 1,
0))
{
printf("WriteProcessMemory failed\nGetLastError() = %d\n",
GetLastError());
VirtualFreeEx(hProc,
baseAdr,
0,
MEM_RELEASE);
CloseHandle(hProc);
return 0;
}
// get kernel32.dll
hDll = LoadLibrary(TEXT("kernel32.dll"));
if(NULL == hDll)
{
printf("LoadLibrary failed\nGetLastError() = %d\n",
GetLastError());
VirtualFreeEx(hProc,
baseAdr,
0,
MEM_RELEASE);
CloseHandle(hProc);
return 0;
}
// get LoadLibraryA entry point
fAdr = GetProcAddress(hDll,
"LoadLibraryA");
if(NULL == fAdr)
{
printf("GetProcAddress failed\nGetLastError() = %d\n",
GetLastError());
FreeLibrary(hDll);
VirtualFreeEx(hProc,
baseAdr,
0,
MEM_RELEASE);
CloseHandle(hProc);
return 0;
}
// create remote thread
hThread = CreateRemoteThread(hProc,
0,
0,
fAdr,
baseAdr,
0,
0);
if(NULL == hThread)
{
printf("CreateRemoteThread failed\nGetLastError() = %d\n",
GetLastError());
FreeLibrary(hDll);
VirtualFreeEx(hProc,
baseAdr,
0,
MEM_RELEASE);
CloseHandle(hProc);
return 0;
}
WaitForSingleObject(hThread,
INFINITE);
if(GetExitCodeThread(hThread,
&exitCode))
{
printf("exit code = %d\n",
exitCode);
}
else
{
printf("GetExitCode failed\nGetLastError() = %d\n",
GetLastError());
}
CloseHandle(hThread);
FreeLibrary(hDll);
VirtualFreeEx(hProc,
baseAdr,
0,
MEM_RELEASE);
CloseHandle(hProc);
return 0;
}
Now, when I inject a shellcode (with a slightly different program than the one above) into a process, I can see in process explorer how my shell code starts running and that the victim process is his parent. Here, I see nothing, but again, it's the first time I'm working with DLLs.
But it still gets loaded because I can't delete the dll file until I kill the victim process.
Also, when I run my injection program, I can see it doing nothing for 5 seconds so it's like the printf is skipped.
Doing this on Windows 7 x64. I know that there are cases in which CreateRemoteThread isn't working on Windows 7, but I use it in my shell code injection and it works and I use the same targets here.
UPDATE: changing my DLL to call ExitProcess(0); kills the victim process, so it all comes down to me not knowing how to print something.
How can I get it to print something?
You want to get messages from your DLL but you use printf. How can you see DLL's printf output? You better write your information to a file.
#define LOG_FILE L"C:\\MyLogFile.txt"
void WriteLog(char* text)
{
HANDLE hfile = CreateFileW(LOG_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD written;
WriteFile(hfile, text, strlen(text), &written, NULL);
WriteFile(hfile, "\r\n", 2, &written, NULL);
CloseHandle(hfile);
}
void WriteLog(wchar_t* text)
{
HANDLE hfile = CreateFileW(LOG_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD written;
WriteFile(hfile, text, wcslen(text) * 2, &written, NULL);
WriteFile(hfile, L"\r\n", 4, &written, NULL);
CloseHandle(hfile);
}
Replace all your printf calls with my function and see what happens actually. By the way, if you have thread in your DLL you can write log every second that will ensure you your code works. You can add time into log file too.
I think if you have enough privilege to inject a DLL into a process, nothing will stop you. Change your code and tell me what happens in log file.
Good luck

Windows Process injection crash

this is my first semi-major C project. I'm a self taught programmer so if my code has any major flaws OR if you happen to have any tips for me, please point them out, I'm very eager to learn. Thank you.
Anyway, I decided to code a process injector for windows, as title says, and I every time I attempt to inject the windows XP SP2 calc into designated process, it crashes. The reason I had decided to make it XP based was because this is a test version/POC/whatever.
Is this because the shellcode is only applicable for specific processes?
I had attempted different processes, explorer.exe, firefox.exe, etc. Still crashes.
Oh, and FYI my ASM isn't the best so I borrowed some shellcode from shell-storm
Also, how does the code look? I had some problems understanding the MSDN API for some of the psapi / windows parameters. It seemed kind of vague, and it was kind of hard to find examples online for some of my questions.
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#define BYTESIZE 100
void ProcessIdentf(DWORD ProcessID);
//Required for Process Handling rights
int SeDebugMode(HANDLE ProcessEnabled, LPCTSTR Base_Name);
int main(void){
//x86 | Windows XP SP2 | calc.exe call
//POC data
unsigned char call_calc[] =
"\x31\xc0\xeb\x13\x5b\x88\x43\x0e\x53\xbb\xad\x23\x86\x7c\xff\xd3\xbb"
"\xfa\xca\x81\x7c\xff\xd3\xe8\xe8\xff\xff\xff\x63\x6d\x64\x2e\x65\x78"
"\x65\x20\x2f\x63\x20\x63\x6d\x64";
//Process HANDLE && Process Identifier WORD
HANDLE FfHandle;
int ProcID;
//VirtualAllocMemPnter
LPVOID lpv = NULL;
//Typecasted pointer to Shellcode
char* shellptr = call_calc;
//Handle for CreateRemoteThread function
HANDLE ControlStructRemote;
//Number of bytes successfully executed
SIZE_T bytescom;
//Data for Process enumeration
DWORD xyProcesses[1024]; //Max_Proc
DWORD abProcesses, cntbNeeded;
unsigned int c;
printf("POC version x00.\nInjects example x86 shellcode into process.\n");
SeDebugMode(GetCurrentProcess(), SE_DEBUG_NAME);
printf("SE_DEBUG_PRIVILEGE successfully enabled.\nPrinting process' eligable for injection\n");
Sleep(10000);
if(!EnumProcesses(xyProcesses, sizeof(xyProcesses), &cntbNeeded)){
exit(1);
}
abProcesses = cntbNeeded / sizeof(DWORD);
//Enumerate processes owned by current user
for(c = 0; c < abProcesses; c++){
if(xyProcesses[c] != 0){
ProcessIdentf(xyProcesses[c]);
}
}
printf("Process PID required\n");
scanf("%d", &ProcID);
FfHandle = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
ProcID);
lpv = VirtualAllocEx(FfHandle,
NULL,
BYTESIZE,
MEM_COMMIT,
0x40); //PAGE_EXECUTE_READWRITE
if(WriteProcessMemory(FfHandle, lpv, &shellptr, sizeof(shellptr), &bytescom) != 0){
ControlStructRemote = CreateRemoteThread(FfHandle,
0,
0,
(DWORD (__stdcall*) (void*)) shellptr,
0,
0,
0);
if(ControlStructRemote){
printf("POC shellcode successful.\n");
}
else{
printf("Failure, CreateRemoteThread could not spawn a remote thread or failed to exec in target process\n");
}
}
return 0;
}
void ProcessIdentf(DWORD ProcID){
//Enumerates PID and modules. Prints. Implement in loop
//unicode char, max ntfs datafile
TCHAR szProcessname[MAX_PATH] = TEXT("<unknown>");
//open proc handle
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE, ProcID);
//enum modules
if(NULL != hProcess){
HMODULE hMod;
DWORD cbNeed;
if(EnumProcessModules(hProcess,&hMod, sizeof(hMod),&cbNeed))
{
GetModuleBaseName(hProcess, hMod, szProcessname,
sizeof(szProcessname)/sizeof(TCHAR));
}
}
//print PID
printf("%s PID: %u\n", szProcessname, ProcID);
//close processhandle
CloseHandle(hProcess);
}
int SeDebugMode(HANDLE xyProcess, LPCTSTR DebugPriv){
HANDLE hTokenProc;
LUID xDebugVal;
TOKEN_PRIVILEGES tPriv;
if(OpenProcessToken(xyProcess,
TOKEN_ADJUST_PRIVILEGES,
&hTokenProc)){
if(LookupPrivilegeValue(NULL, DebugPriv, &xDebugVal)){
tPriv.PrivilegeCount = 1;
tPriv.Privileges[0].Luid = xDebugVal;
tPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hTokenProc,
FALSE,
&tPriv,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL
);
if(GetLastError() == ERROR_SUCCESS){
return TRUE;
}
}
}
return FALSE;
}
You create the remote thread at shellptr, but it should be lpv where you wrote the code to.
BTW, try to avoid PROCESS_ALL_ACCESS, only specify what exact access you need (it's all on MSDN for each API)

Resources