C++ to PB. Headaches, white nights, etc..

Everything else that doesn't fall into one of the other PB categories.
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

C++ to PB. Headaches, white nights, etc..

Post by Inf0Byt3 »

Hi! I found this code that help creating global API hooks without entering ring0 with a vxd and it seems pretty cool. Unfortunately it is in C++ and I can't manage to translate it :(. Any help is much appreciated. It has 2 parts: an injector (app) and a dll. The code is not big (~4 kb each).

Oh, and what does "->" means in C++? I can't find any replacement in PB...

The injector

Code: Select all

#include <windows>
#include <stdlib>
#include <conio>

int DoHook(int pid, bool UnHook, HMODULE hFreeModule)
{

	HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, // Specifies all possible access flags
									FALSE, 
									pid);
	if (hProcess == NULL) 
		return 0;

	char szLibFile[MAX_PATH] = "C:\\work\\vc6\\SharedModule\\Debug\\sharedmodule.dll";
 
	int cch = 1 + strlen(szLibFile);

	PSTR pszLibFileRemote = (PSTR)::VirtualAllocEx(hProcess, NULL, cch, MEM_COMMIT, PAGE_READWRITE);

	if (pszLibFileRemote == NULL) 
	{
		printf("pszLibFileRemote was NULL");
		return 0;
	}

	if (!::WriteProcessMemory(hProcess, (PVOID)pszLibFileRemote, (PVOID)szLibFile, cch, NULL))
	{
		printf("\nWriteProcessMemory Failed");
		return 0;
	}

	PTHREAD_START_ROUTINE pfnThreadRtn = NULL;

	if(UnHook)
		pfnThreadRtn = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle("Kernel32"), "FreeLibrary");
	else
		pfnThreadRtn = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle("Kernel32"), "LoadLibraryA");

	if (pfnThreadRtn == NULL) 
	{
		printf("\nGetProcAddress Failed");
		return 0;
	}
 
	HANDLE hThread;
 
	if(UnHook)
		hThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, (HMODULE)hFreeModule, 0, NULL);
	else
		hThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, (PVOID)pszLibFileRemote, 0, NULL);

	if (hThread == NULL) 
	{
		printf("\nCreateRemoteThread Failed");
		return 0;
	}

	::WaitForSingleObject(hThread, INFINITE);

	if (pszLibFileRemote != NULL) 
	  ::VirtualFreeEx(hProcess, (PVOID)pszLibFileRemote, 0, MEM_RELEASE);

	if (hThread  != NULL) 
		::CloseHandle(hThread);

	if (hProcess != NULL) 
		::CloseHandle(hProcess);

	return 1;
}

// We will require this function to get a module handle of our
// original module

HMODULE EnumModules(int pid, char szLibFile[MAX_PATH])
{
	HMODULE hMods[1024];
	DWORD cbNeeded;

	unsigned int i;

	HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, // Specifies all possible access flags
									FALSE, 
									pid);

	if (hProcess == NULL) 
		return 0;

    HMODULE m_hModPSAPI = ::LoadLibraryA("PSAPI.DLL");

	typedef BOOL (WINAPI * PFNENUMPROCESSMODULES)
	(
		HANDLE hProcess,
		HMODULE *lphModule,
		DWORD cb,
		LPDWORD lpcbNeeded
	);

	typedef DWORD (WINAPI * PFNGETMODULEFILENAMEEXA)
	(
		HANDLE hProcess,
		HMODULE hModule,
		LPSTR lpFilename,
		DWORD nSize
	);

    PFNENUMPROCESSMODULES   m_pfnEnumProcessModules;
    PFNGETMODULEFILENAMEEXA m_pfnGetModuleFileNameExA;

	m_pfnEnumProcessModules = (PFNENUMPROCESSMODULES)::GetProcAddress(m_hModPSAPI, "EnumProcessModules");

	m_pfnGetModuleFileNameExA = (PFNGETMODULEFILENAMEEXA)::GetProcAddress(m_hModPSAPI, "GetModuleFileNameExA");

	if( m_pfnEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
	{
		for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
		{
			char szModName[MAX_PATH];

			// Get the full path to the module's file.

			if ( m_pfnGetModuleFileNameExA( hProcess, hMods[i], szModName, sizeof(szModName)))
			{
				// Print the module name and handle value.

				printf("\t%s (0x%08X)\n", szModName, hMods[i] );

				if(strcmp(szModName, szLibFile) == 0)
				{
					::FreeLibrary(m_hModPSAPI);

					return hMods[i];
				}
			}
		}
	}

	if (hProcess != NULL) 
	::CloseHandle(hProcess);

	return 0;
}

int main(int argc, char* argv[])
{
	int pid = atol(argv[1]);
	HMODULE hModule; 

	DoHook(pid, false, 0);

	hModule = EnumModules(pid,"C:\\work\\vc6\\SharedModule\\Debug\\sharedmodule.dll");

	getch();

	if(0 != hModule)
		DoHook(pid, true, hModule);

	printf("\n");

	EnumModules(pid,"C:\\Parag\\pidwatcher\\Debug\\sharedmodule.dll");

	return 0;
}
DLL module:

Code: Select all

#include <stdio>
#include <imagehlp>
#include <stdlib>

HANDLE g_hModule = INVALID_HANDLE_VALUE;
PROC g_OriginalCopyFileW;

typedef BOOL WINAPI MyCopyFileW_t
(
	LPCWSTR lpExistingFileName,
	LPCWSTR lpNewFileName,
	BOOL bFailIfExists
);

BOOL WINAPI MyCopyFileW(LPCWSTR lpExistingFileName,	LPCWSTR lpNewFileName, BOOL bFailIfExists)
{
	BOOL ReturnValue;
	
	MyCopyFileW_t* fn = (MyCopyFileW_t*)g_OriginalCopyFileW;
	
	ReturnValue = (*fn)(lpExistingFileName, lpNewFileName, bFailIfExists);

	return ReturnValue;
}

void SetHook(HMODULE hModuleOfCaller, LPSTR LibraryName, PROC OldFunctionPointer, PROC NewFunctionPointer)
{
	if(hModuleOfCaller == g_hModule)
		return;
	if(hModuleOfCaller == 0)
		return;

	ULONG ulSize;

	// Get the address of the module’s import section
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData
	(
		hModuleOfCaller, 
		TRUE, 
		IMAGE_DIRECTORY_ENTRY_IMPORT, 
		&ulSize
	);

	// Does this module have an import section ?
	if (pImportDesc == NULL)
		return;

	// Loop through all descriptors and find the 
	// import descriptor containing references to callee’s functions
	while (pImportDesc->Name)
	{
		PSTR pszModName = (PSTR)((PBYTE) hModuleOfCaller + pImportDesc->Name);
		
		if (stricmp(pszModName, LibraryName) == 0) 
			break; // Found

		pImportDesc++;
	} // while

	if (pImportDesc->Name == 0)
		return;

	//Get caller’s IAT 
	PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)( (PBYTE) hModuleOfCaller + pImportDesc->FirstThunk );

	PROC pfnCurrent = OldFunctionPointer;

	// Replace current function address with new one
	while (pThunk->u1.Function)
	{
		// Get the address of the function address
		PROC* ppfn = (PROC*) &pThunk->u1.Function;
		// Is this the function we’re looking for?
		BOOL bFound = (*ppfn == pfnCurrent);

		if (bFound) 
		{
			MEMORY_BASIC_INFORMATION mbi;
			
			::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));

			// In order to provide writable access to this part of the 
			// memory we need to change the memory protection

			if (FALSE == ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect))
				return;

			*ppfn = *NewFunctionPointer;

			BOOL bResult = TRUE;

			// Restore the protection back
			DWORD dwOldProtect;

			::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
			
			break;
		} // if

		pThunk++;

	} // while
}

PROC EnumAndSetHooks(LPSTR BaseLibraryName, LPSTR BaseFunctionName, PROC NewFunctionPointer, bool UnHook, PROC Custom)
{
	HMODULE hMods[1024];
	DWORD cbNeeded;
	unsigned int i;
	typedef BOOL (WINAPI * PFNENUMPROCESSMODULES)
	(
		HANDLE hProcess,
		HMODULE *lphModule,
		DWORD cb,
		LPDWORD lpcbNeeded
	);

	HMODULE hBaseLib = LoadLibrary(BaseLibraryName);

	PROC hBaseProc;

	if(UnHook)
		hBaseProc = (PROC) Custom;
	else
		hBaseProc = GetProcAddress(hBaseLib, BaseFunctionName);

	PFNENUMPROCESSMODULES m_pfnEnumProcessModules;
	HMODULE m_hModPSAPI = ::LoadLibraryA("PSAPI.DLL");

	m_pfnEnumProcessModules = (PFNENUMPROCESSMODULES)::GetProcAddress(m_hModPSAPI, "EnumProcessModules");

	HANDLE hProcess = ::GetCurrentProcess();

	if( m_pfnEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
	{
		for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
		{
			SetHook(hMods[i], BaseLibraryName, hBaseProc, NewFunctionPointer); 
		}
	}

	return hBaseProc;
}

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
			g_hModule = hModule;
			
			g_OriginalCopyFileW = EnumAndSetHooks("KERNEL32.DLL", "CopyFileW", (PROC) MyCopyFileW, false, 0);
				
			break;
		case DLL_PROCESS_DETACH:
			EnumAndSetHooks("KERNEL32.DLL", "CopyFileW", (PROC) GetProcAddress(LoadLibrary("KERNEL32"),"CopyFileW"), true, (PROC) MyCopyFileW);
			break;
	}

	return TRUE;
}
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

-> is similar to the \ in purebasic for structures. However it won't have the same effect because in C++ the -> can be a reference from a pointer (get it, it looks like an arrow) to a function call, not just normal data types.

PB Simplifies it a bit. In Pb, structures no matter how they are defined:

*src.MYSTRUC = alocatememory(sizeof(MYSTRUC))
src2.MYSTRUC

Both of these can have thier member fields access by

*src\x=3
src2\x=3

In C/C++ you would have to use -> for the top version and . for the bottom.


(Though it seems there aren't any classes/objects in this code so it should be an easy conversion)
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Thanks. I had a hunch, but wasn't shure about it...

[Edit]
Oh, i see... Hmm, what about compiling this with VC2005 Express and than including it in a lib? Would it be hard?
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Not sure I haven't really messed with PB4 yet. Still waiting on the nix version
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Oh :D. I didn't have any problems until now, and I hope I'll never have :). But a bugfix version would be cool (one with SendNetworkFile with callback and buffered transfer :D).

For now I'll wait until VC++ completes (just started downloading it) and try to make an object out of the code. I hope this will work.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Click Me: not tested (my antivirus always block the app and i don't want to deactivate it ^_^).
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Wow that's amazing! Thank you very much! I will now see how it works and make some tests.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Hmm, this is strange, I was trying to use it but it seems not to work here. Can you please try to make an example (hook messageboxa for example)? I used 'explorer.exe' as programparameter. it enumerates its modules and after that it quits...
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Did you try the original code to compare with the PB code ? Perhaps the original code do nothing too :?:
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

You're right... Here is the original page with the code. I'll try to make it work.

http://www.codeproject.com/system/api_m ... eashed.asp
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Henrik
Enthusiast
Enthusiast
Posts: 404
Joined: Sat Apr 26, 2003 5:08 pm
Location: Denmark

Post by Henrik »

@Inf0Byt3 here is another article about it
API monitoring unleashed - I to IV
Starts at the bottom of this page:
http://www.itvidya.com/article/650
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Thanks. It's allmost like like the article I found :D.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Henrik
Enthusiast
Enthusiast
Posts: 404
Joined: Sat Apr 26, 2003 5:08 pm
Location: Denmark

Post by Henrik »

Inf0Byt3 wrote:Thanks. It's allmost like like the article I found :D.
the code is the same but the article is in greater detail, if i rember correct. hmm, i think it's is :roll:

Annyway
best Henrik
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

It's good. I allmost made it... When it is done, I will make a lib or an include out of it.
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Henrik
Enthusiast
Enthusiast
Posts: 404
Joined: Sat Apr 26, 2003 5:08 pm
Location: Denmark

Post by Henrik »

Cool Infobyt 8)
Did you compile it with VC2005 Express ?
Post Reply