Jump to content
Hannock

PE Injector shows error 87 when Program is open

Recommended Posts

Hey everyone,

 

I am not from Romania , forgive my English. i have a Question i want to ask. 

 

I have Written a PE Injector, judging from zwclose source(credits to him) in C, now i want to inject a simple Messagebox into a C++ application i created as well. it shows error 87 even when the application is open. Started to wonder what the problem was.

 

My source code looks like this

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>

DWORD WINAPI ThreadProc()
{
	MessageBoxA(NULL, "I am a Test MessageBox", "Message", MB_OK);
	return 0;
}

BOOL SetDebugPriviledge(BOOL State)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	DWORD dwSize;
	ZeroMemory(&tp, sizeof(tp));
	tp.PrivilegeCount = 1;
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
	{
		return FALSE;
	}
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
	{
		CloseHandle(hToken);
	}
	if (State)
	{
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	}
	else
	{
		tp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
	}
	if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, &dwSize))
	{
		CloseHandle(hToken);
	}
	return CloseHandle(hToken);
}

DWORD GetProcessID(IN PCHAR szExeName)
{
	DWORD dwRet = 0;
	DWORD dwCount = 0;

	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot != INVALID_HANDLE_VALUE)
	{
		PROCESSENTRY32 pe = { 0 };
		pe.dwSize = sizeof(PROCESSENTRY32);

		BOOL bRet = Process32First(hSnapshot, &pe);

		while (bRet)
		{
			if (!_stricmp(pe.szExeFile, szExeName))
			{
				dwCount++;
				dwRet = pe.th32ProcessID;
			}
			bRet = Process32Next(hSnapshot, &pe);
		}

		CloseHandle(hSnapshot);
	}
	return dwRet;

}

void InjectFF()
{
	SetDebugPriviledge(TRUE);
	PIMAGE_DOS_HEADER pIDH;
	PIMAGE_NT_HEADERS pINH;
	PIMAGE_BASE_RELOCATION pIBR;

	HANDLE hProcess, hThread;
	PUSHORT TypeOffset;

	PVOID ImageBase, Buffer, mem;
	ULONG i, Count, Delta, *p;

	hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, GetProcessID("hannock.exe"));
	if (!hProcess)
	{
		printf("\nError: Unable to open target process (%u)\n", GetLastError());
		return -1;
		getchar();
	}
	ImageBase = GetModuleHandle(NULL);
	pIDH = (PIMAGE_DOS_HEADER)ImageBase;
	pINH = (PIMAGE_NT_HEADERS)((PUCHAR)ImageBase + pIDH->e_lfanew);
	mem = VirtualAllocEx(hProcess, NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (!mem)
	{
		printf("\nError: Unable to allocate memory in target process (%u)\n", GetLastError());

		CloseHandle(hProcess);
		getchar();
		return 0;
	}

	Buffer = VirtualAlloc(NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	memcpy(Buffer, ImageBase, pINH->OptionalHeader.SizeOfImage);

	pIBR = (PIMAGE_BASE_RELOCATION)((PUCHAR)Buffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	Delta = (ULONG)mem - (ULONG)ImageBase;

	while (pIBR->VirtualAddress)
	{
		if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))
		{
			Count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
			TypeOffset = (PUSHORT)(pIBR + 1);

			for (i = 0; i<Count; i++)
			{
				if (TypeOffset[i])
				{
					p = (PULONG)((PUCHAR)Buffer + pIBR->VirtualAddress + (TypeOffset[i] & 0xFFF));
					*p += Delta;
				}
			}
		}

		pIBR = (PIMAGE_BASE_RELOCATION)((PUCHAR)pIBR + pIBR->SizeOfBlock);
	}

	if (!WriteProcessMemory(hProcess, mem, Buffer, pINH->OptionalHeader.SizeOfImage, NULL))
	{
		printf("\nError: Unable to write process memory (%u)\n", GetLastError());

		VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
		CloseHandle(hProcess);
		getchar();

		return -1;
	}

	VirtualFree(Buffer, 0, MEM_RELEASE);
	hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((PUCHAR)ThreadProc + Delta), NULL, 0, NULL);
	if (!hThread)
	{
		printf("\nError: Unable to create thread in target process (%u)\n", GetLastError());

		VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
		CloseHandle(hProcess);

		return -1;
		getchar();
	}

	WaitForSingleObject(hThread, INFINITE);
	VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
	CloseHandle(hProcess);
}

int main()
{
	InjectFF();
	return 0;
}

What am I not getting clearly?

Edited by Hannock
  • Upvote 2
Link to comment
Share on other sites

39 minutes ago, Hannock said:

[...] it shows error 87 [...]

Can you be more specific? Where, during the execution, does it encounter this error?

Also in SetDebugPriviledge, your call to AdjustTokenPrivileges is off: it should be 

AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)

as per https://msdn.microsoft.com/en-us/library/windows/desktop/aa375202(v=vs.85).aspx and https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx (casting is optional).

 

Try adding some break-points or debug statements to check the variables or return codes.

Edited by u0m3
Clarifications
  • Upvote 2
Link to comment
Share on other sites

46 minutes ago, u0m3 said:

Can you be more specific? Where, during the execution, does it encounter this error?

Also in SetDebugPriviledge, your call to AdjustTokenPrivileges is off: it should be 


AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)

as per https://msdn.microsoft.com/en-us/library/windows/desktop/aa375202(v=vs.85).aspx and https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx (casting is optional).

 

Try adding some break-points or debug statements to check the variables or return codes.

 

 

Made the adjustments and still the same.

 

it returns something like this 

 

Error: Unable to open target process (87)

 

 

Link to comment
Share on other sites

Error code 87 is invalid parameter

ERROR_INVALID_PARAMETER
87 (0x57)
The parameter is incorrect.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

 

When dealing with GetLastError this is helpful https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx. Just keep in mind it uses some fancy macro tricks to abstract the use of char vs wchar_t for storing strings. In your case, if you don't just use the code (which will use MessageBox to display the error) you should substitute the macro stuff so the resulting string can be used with printf (or alternatively use _tprintf which uses the same abstraction).

 

Now regarding the cause of the error: my first suspect is GetProcessID; you never check if it returns a valid value. Second on the list is the flag PROCESS_CREATE_THREAD as it is restricted: 

Quote

The following specific access rights are not allowed from a process to a protected process:

[...]

PROCESS_CREATE_THREAD

[...]

as specified https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx (bottom of page). You never specified what operating system you are using, so if you are using Windows Vista or above (which is quite probable) you should try to run the injector as administrator (if you are not doing that already).

Link to comment
Share on other sites

See what happened here. I open Processhacker and i check from the ProcessID and it injects successfully, suppose i close it and re inject , it fails again.

 

I figured it should be from the GetProcessID Function.  My Code Looks like this now.

 

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>

void InjectFF();

DWORD WINAPI ThreadProc()
{
	MessageBoxA(NULL, "Hi From Injected Code", "Message", MB_OK);
	return 0;
}

BOOL SetDebugPriviledge(BOOL State)
{
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	DWORD dwSize;
	ZeroMemory(&tp, sizeof(tp));
	tp.PrivilegeCount = 1;
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
	{
		return FALSE;
	}
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
	{
		CloseHandle(hToken);
	}
	if (State)
	{
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	}
	else
	{
		tp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
	}
	if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
	{
		CloseHandle(hToken);
	}
	return CloseHandle(hToken);
}

DWORD GetProcessID(IN PCHAR szExeName)
{
	DWORD dwRet = 0;
	DWORD dwCount = 0;

	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot != INVALID_HANDLE_VALUE)
	{
		PROCESSENTRY32 pe = { 0 };
		pe.dwSize = sizeof(PROCESSENTRY32);

		BOOL bRet = Process32First(hSnapshot, &pe);

		while (bRet)
		{
			if (!_stricmp(pe.szExeFile, szExeName))
			{
				dwCount++;
				dwRet = pe.th32ProcessID;

				InjectFF();
			}
			bRet = Process32Next(hSnapshot, &pe);
		}

		CloseHandle(hSnapshot);
	}
	return dwRet;
}

void InjectFF()
{
	PIMAGE_DOS_HEADER pIDH;
	PIMAGE_NT_HEADERS pINH;
	PIMAGE_BASE_RELOCATION pIBR;

	HANDLE hProcess, hThread;
	PUSHORT TypeOffset;

	PVOID ImageBase, Buffer, mem;
	ULONG i, Count, Delta, *p;

	hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE,5908);
	if (!hProcess)
	{
		printf("\nError: Unable to open target process (%u)\n", GetLastError());
		return -1;
		getchar();
	}
	ImageBase = GetModuleHandle(NULL);
	pIDH = (PIMAGE_DOS_HEADER)ImageBase;
	pINH = (PIMAGE_NT_HEADERS)((PUCHAR)ImageBase + pIDH->e_lfanew);
	mem = VirtualAllocEx(hProcess, NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (!mem)
	{
		printf("\nError: Unable to allocate memory in target process (%u)\n", GetLastError());

		CloseHandle(hProcess);
		getchar();
		return 0;
	}

	Buffer = VirtualAlloc(NULL, pINH->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	memcpy(Buffer, ImageBase, pINH->OptionalHeader.SizeOfImage);

	pIBR = (PIMAGE_BASE_RELOCATION)((PUCHAR)Buffer + pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	Delta = (ULONG)mem - (ULONG)ImageBase;

	while (pIBR->VirtualAddress)
	{
		if (pIBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION))
		{
			Count = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
			TypeOffset = (PUSHORT)(pIBR + 1);

			for (i = 0; i<Count; i++)
			{
				if (TypeOffset[i])
				{
					p = (PULONG)((PUCHAR)Buffer + pIBR->VirtualAddress + (TypeOffset[i] & 0xFFF));
					*p += Delta;
				}
			}
		}

		pIBR = (PIMAGE_BASE_RELOCATION)((PUCHAR)pIBR + pIBR->SizeOfBlock);
	}

	if (!WriteProcessMemory(hProcess, mem, Buffer, pINH->OptionalHeader.SizeOfImage, NULL))
	{
		printf("\nError: Unable to write process memory (%u)\n", GetLastError());

		VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
		CloseHandle(hProcess);
		getchar();

		return -1;
	}

	VirtualFree(Buffer, 0, MEM_RELEASE);
	hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((PUCHAR)ThreadProc + Delta), NULL, 0, NULL);
	if (!hThread)
	{
		printf("\nError: Unable to create thread in target process (%u)\n", GetLastError());

		VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
		CloseHandle(hProcess);

		return -1;
		getchar();
	}

	WaitForSingleObject(hThread, INFINITE);
	VirtualFreeEx(hProcess, mem, 0, MEM_RELEASE);
	CloseHandle(hProcess);
}

int main()
{
	SetDebugPriviledge(TRUE);
	InjectFF();
	return 0;
}

Where 5908 is the Process ID when i looked it up from Process Hacker.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...