There is one famous crackme. After studying it, it turns out that for its hacking, it is enough to patch two bytes at 40138B (score a conditional jump with NOPs) and two bytes at 401243 (register an unconditional jump there). I want to write a program that does this automatically.
#include <iostream> #include <vector> #include <string> #include <Windows.h> enum {OK, CANT_OPEN}; int patch (TCHAR* fname) { char first_patch[2] = {0x90, 0x90}; // NOP NOP char second_patch[2] = {0xEB, 0x07}; // JMP 40124C HANDLE hFile = CreateFile(fname, FILE_ALL_ACCESS, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return CANT_OPEN; int SizeFile = GetFileSize(hFile, NULL); HANDLE MhFile = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, SizeFile, 0); HANDLE View = MapViewOfFile(MhFile, FILE_MAP_ALL_ACCESS, 0, 0, 0); UnmapViewOfFile(View); CloseHandle(hFile); CloseHandle(MhFile); return OK; } int main (int argc, char *argv[]) { TCHAR* default_fname = "CRACKME.EXE"; if (argc > 1) { default_fname = argv[1]; } patch(default_fname); std::cout << default_fname << std::endl; return 0; } I projected the executable file into the address space of the process and received the address of this projection. Now you need to patch this image, after which the UnmapViewOfFile procedure will save the changes to disk.
How to find addresses like 40138B and 401243 in this projection? Where can I see the theory and examples of editing PE files?
Next, I write crap , you can not read. Successfully printed the MZ signature, which means that using View you can fill in header structures, possibly using Chris Kaspersky's macros, for alignment.
char M = *((char *) View); char Z = *((char *) View + 1); std::cout << M << Z << std::endl; Verify that the DOS header is successfully loaded. Then add the code to catch possible errors.
unsigned myRVAtoRAW(HANDLE pe_image, unsigned rva) { IMAGE_DOS_HEADER dos_header; std::memcpy(reinterpret_cast<char*>(&dos_header), pe_image, sizeof(dos_header)); std::cout << (dos_header.e_magic == 'ZM') << std::endl; return 0; }