Что я упускаю тут?
Для x86 код работает. Но для 64 где то ошибка.
Для x86 код работает. Но для 64 где то ошибка.
C++:
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <string>
void _memcpy(void* dst, const void* src, size_t size) {
BYTE* _dst = (BYTE*)dst;
BYTE* _src = (BYTE*)src;
while (size--) {
*_dst++ = *_src++;
}
}
std::vector<std::wstring> loadedDlls;
DWORD peSize;
PIMAGE_DOS_HEADER GetDosHeader(BYTE* data) {
return (PIMAGE_DOS_HEADER)data;
}
PIMAGE_NT_HEADERS GetNtHeaders(BYTE* data) {
PIMAGE_DOS_HEADER dosHeader = GetDosHeader(data);
return (PIMAGE_NT_HEADERS)(data + dosHeader->e_lfanew);
}
PIMAGE_SECTION_HEADER GetFirstSectionHeader(BYTE* data) {
PIMAGE_NT_HEADERS ntHeaders = GetNtHeaders(data);
return IMAGE_FIRST_SECTION(ntHeaders);
}
PIMAGE_IMPORT_DESCRIPTOR GetImportDescriptor(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
}
PIMAGE_THUNK_DATA GetThunkData(LPVOID pBase, PIMAGE_IMPORT_DESCRIPTOR pImport, bool useOriginal) {
if (useOriginal && pImport->OriginalFirstThunk) {
return (PIMAGE_THUNK_DATA)((DWORD_PTR)pBase + pImport->OriginalFirstThunk);
} else {
return (PIMAGE_THUNK_DATA)((DWORD_PTR)pBase + pImport->FirstThunk);
}
}
FARPROC GetFunction(HMODULE hDll, PIMAGE_THUNK_DATA pThunk, LPVOID pBase) {
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) {
return GetProcAddress(hDll, (LPCSTR)(pThunk->u1.Ordinal & 0xFFFF));
} else {
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pBase + pThunk->u1.AddressOfData);
FARPROC funcAddr = GetProcAddress(hDll, pName->Name);
if (!funcAddr) {
DWORD error = GetLastError();
printf("Func not found: %d\n", error);
// обработка ошибки
}
return funcAddr;
}
}
PIMAGE_BASE_RELOCATION GetRelocationEnd(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
DWORD_PTR relocationStart = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
DWORD relocationSize = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
return (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pBase + relocationStart + relocationSize);
}
PIMAGE_BASE_RELOCATION GetBaseRelocation(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
if ((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
return NULL;
}
return (PIMAGE_BASE_RELOCATION)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
}
PIMAGE_TLS_DIRECTORY GetTlsDirectory(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return (PIMAGE_TLS_DIRECTORY)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
}
ULONGLONG getEntryPoint(LPVOID pBase, PIMAGE_NT_HEADERS ntHeaders) {
return ntHeaders->OptionalHeader.AddressOfEntryPoint;
}
DWORD GetExportedFunctionCount(LPCWSTR dllName) {
HMODULE hDll = LoadLibraryExW(dllName, NULL, DONT_RESOLVE_DLL_REFERENCES);
if (!hDll) {
return 0;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hDll;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hDll + pDosHeader->e_lfanew);
if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size == 0) {
FreeLibrary(hDll);
return 0;
}
PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hDll + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD functionCount = pExportDir->NumberOfFunctions;
FreeLibrary(hDll);
return functionCount;
}
PVOID loadPe(BYTE* peImageBuffer) {
DWORD secp2vmemp[2][2][2] = {
{{PAGE_NOACCESS, PAGE_WRITECOPY}, {PAGE_READONLY, PAGE_READWRITE}},
{{PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY}, {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE}}
};
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)peImageBuffer;
PIMAGE_NT_HEADERS ntHeaders = GetNtHeaders(peImageBuffer);
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE || (dosHeader->e_lfanew % sizeof(DWORD)) != 0) {
return NULL;
}
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
return NULL;
}
if (!ntHeaders->OptionalHeader.AddressOfEntryPoint ||
!ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
return NULL;
}
LPVOID pBase = VirtualAlloc(NULL, ntHeaders->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pBase) {
printf("Failed to allocate memory\n");
return NULL;
}
if ((DWORD_PTR)pBase % ntHeaders->OptionalHeader.SectionAlignment != 0) {
printf("VirtualAlloc returned unaligned address\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
_memcpy(pBase, peImageBuffer, ntHeaders->OptionalHeader.SizeOfHeaders);
PIMAGE_SECTION_HEADER firstSectionHeader = GetFirstSectionHeader(peImageBuffer);
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
if (firstSectionHeader[i].SizeOfRawData <= firstSectionHeader[i].Misc.VirtualSize) {
_memcpy((BYTE*)pBase + firstSectionHeader[i].VirtualAddress,
peImageBuffer + firstSectionHeader[i].PointerToRawData,
firstSectionHeader[i].SizeOfRawData);
} else {
printf("SizeOfRawData is greater than the size of the section in the file.\n"); //todo: fix
_memcpy((BYTE*)pBase + firstSectionHeader[i].VirtualAddress,
peImageBuffer + firstSectionHeader[i].PointerToRawData,
firstSectionHeader[i].SizeOfRawData);
}
}
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) {
PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pBase, ntHeaders);
while (pImport->Name) {
WCHAR wDllName[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)((DWORD_PTR)pBase + pImport->Name), -1, wDllName, MAX_PATH);
HMODULE hDll = LoadLibraryW(wDllName);
if (!hDll) {
printf("dll not load!\n");
}
if (hDll) {
DWORD exportCount = GetExportedFunctionCount(wDllName);
DWORD importCount = 0;
PIMAGE_THUNK_DATA pThunk = GetThunkData(pBase, pImport, true);
PIMAGE_THUNK_DATA pFunc = GetThunkData(pBase, pImport, false);
if (!pImport->OriginalFirstThunk) {
pThunk = pFunc;
}
for (; pThunk->u1.AddressOfData; ++pFunc, ++pThunk) {
importCount++;
}
if (importCount > exportCount) {
printf("Too many functions imported!\n");
}
for (; pThunk->u1.AddressOfData; ++pFunc, ++pThunk) {
FARPROC funcAddr = GetFunction(hDll, pThunk, pBase);
if (!funcAddr) {
DWORD error = GetLastError();
// обработка ошибки
}
pFunc->u1.Function = (ULONGLONG)funcAddr;
}
}
loadedDlls.push_back(wDllName);
++pImport;
}
}
PIMAGE_BASE_RELOCATION curReloc = GetBaseRelocation(pBase, ntHeaders);
while (curReloc < GetRelocationEnd(pBase, ntHeaders) && curReloc->VirtualAddress) {
DWORD count = curReloc->SizeOfBlock / sizeof(WORD);
PDWORD curEntry = (PDWORD)(curReloc + 1);
DWORD_PTR pageVA = (DWORD_PTR)pBase + curReloc->VirtualAddress;
if ((DWORD_PTR)curReloc + curReloc->SizeOfBlock > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation block is out of bounds\n");
}
for (; count; ++curEntry, --count) {
DWORD Type = *curEntry >> 16;
DWORD Offset = *curEntry & 0xFFFF;
if (Type == IMAGE_REL_BASED_DIR64) {
if (pageVA + Offset > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation entry is out of bounds\n");
return NULL;
}
PDWORD64 dest = (PDWORD64)(pageVA + Offset);
*dest += (DWORD64)pBase - ntHeaders->OptionalHeader.ImageBase;
} else if (Type == IMAGE_REL_BASED_HIGHLOW) {
if (pageVA + Offset > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Relocation entry is out of bounds\n");
return NULL;
}
PDWORD dest = (PDWORD)(pageVA + Offset);
*dest += (DWORD)pBase - ntHeaders->OptionalHeader.ImageBase;
}
}
curReloc = (PIMAGE_BASE_RELOCATION)((DWORD_PTR)curReloc + curReloc->SizeOfBlock);
}
DWORD dwOldProtect;
BOOL bProtect = VirtualProtect(pBase, ntHeaders->OptionalHeader.SizeOfImage, PAGE_READWRITE, &dwOldProtect);
if (!bProtect) {
DWORD dwLastError = GetLastError();
printf("Failed to set memory protection: %d\n", dwLastError);
} else {
printf("Memory protection changed successfully\n");
}
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
if (firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) {
VirtualFree((LPVOID)((DWORD_PTR)pBase + firstSectionHeader[i].VirtualAddress),
firstSectionHeader[i].Misc.VirtualSize,
MEM_DECOMMIT);
continue;
}
DWORD_PTR vmemp = secp2vmemp[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_EXECUTE)]
[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_READ)]
[!!(firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_WRITE)];
if (firstSectionHeader[i].Characteristics & IMAGE_SCN_MEM_NOT_CACHED) {
vmemp |= PAGE_NOCACHE;
}
DWORD sectionSize = firstSectionHeader[i].SizeOfRawData;
BOOL bProtect = VirtualProtect((LPVOID)((DWORD_PTR)pBase + firstSectionHeader[i].VirtualAddress),
sectionSize,
PAGE_EXECUTE_READWRITE,
&dwOldProtect);
if (!bProtect) {
DWORD dwLastError = GetLastError();
printf("Failed to set memory protection for section %d: %d\n", i, dwLastError);
}
}
auto err = GetLastError();
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) {
PIMAGE_TLS_DIRECTORY pTls = GetTlsDirectory(pBase, ntHeaders);
PIMAGE_TLS_CALLBACK* pCallback = (PIMAGE_TLS_CALLBACK*)pTls->AddressOfCallBacks;
if (pCallback) {
for (; *pCallback; ++pCallback) {
(*pCallback)((LPVOID)pBase, DLL_PROCESS_ATTACH, NULL);
}
}
}
// получаем адрес функции входной точки
ULONGLONG dwEntry = getEntryPoint(pBase, ntHeaders);
if (dwEntry == 0) {
printf("Invalid entry point\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
// проверяем, что функция входной точки существует и не является нулевой
if ((DWORD_PTR)pBase + dwEntry > (DWORD_PTR)pBase + ntHeaders->OptionalHeader.SizeOfImage) {
printf("Invalid entry point\n");
VirtualFree(pBase, 0, MEM_RELEASE);
return NULL;
}
peSize = ntHeaders->OptionalHeader.SizeOfImage;
return (LPVOID)((DWORD_PTR)pBase + ntHeaders->OptionalHeader.AddressOfEntryPoint);
}
void* load_file_to_memory(const char* filename) {
HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE) {
CloseHandle(hFile);
return NULL;
}
LPVOID lpFileData = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT, PAGE_READWRITE);
if (lpFileData == NULL) {
CloseHandle(hFile);
return NULL;
}
DWORD dwBytesRead;
if (!ReadFile(hFile, lpFileData, dwFileSize, &dwBytesRead, NULL)) {
CloseHandle(hFile);
VirtualFree(lpFileData, 0, MEM_RELEASE);
return NULL;
}
CloseHandle(hFile);
return lpFileData;
}
int main() {
void* file_data = load_file_to_memory("C:\\work\\ConsoleApplication1_messagebox_64.exe");
if (file_data == NULL) {
printf("Failed to load file\n");
return 1;
}
LPVOID pBase = loadPe(reinterpret_cast<BYTE*>(file_data));
if (pBase == NULL) {
printf("Failed to load PE\n");
return 1;
}
if (memcmp(file_data, pBase, peSize) == 0) {
printf("File and memory contents are identical\n");
} else {
printf("File and memory contents are not identical\n");
}
// вызываем функцию входной точки
typedef int(*EntryPointFunction)();
auto addr = (DWORD_PTR)pBase;
EntryPointFunction entryPoint = (EntryPointFunction)(addr);
ExitProcess(0);
}
