#cpp #winapi #pe
Есть один известный крэкми. После его изучения оказывается, что для его взлома достаточно пропатчить два байта по адресу 40138B (забить условный переход NOP'ами) и два байта по адресу 401243 (прописать там безусловный переход). Я хочу написать программу, которая делает это автоматически. #include#include #include #include 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; } Я спроецировал исполняемый файл в адресное пространство процесса и получил адрес этой проекции. Теперь надо пропатчить этот образ, после чего процедура UnmapViewOfFile сохранит изменения на диск. Как в этой проекции найти адреса типа 40138B и 401243? Где можно посмотреть теорию и примеры по редактированию PE-файлов? Далее пишу хрень, можно не читать. Успешно напечатал сигнатуру MZ, это значит, что при помощи View можно заполнять структуры заголовков, используя, возможно, для выравнивания макросы Криса Касперски. char M = *((char *) View); char Z = *((char *) View + 1); std::cout << M << Z << std::endl; Проверка того, что заголовок дос успешно загружен. Потом добавлю код для отлавливания возможных ошибок. unsigned myRVAtoRAW(HANDLE pe_image, unsigned rva) { IMAGE_DOS_HEADER dos_header; std::memcpy(reinterpret_cast (&dos_header), pe_image, sizeof(dos_header)); std::cout << (dos_header.e_magic == 'ZM') << std::endl; return 0; }
Ответы
Ответ 1
Можно пойти двумя путями: Разобраться и написать самому. Тогда рекомендую почитать статью: Разработка функций RvaToRaw и RawToRva. Либо воспользоваться функций из известной dbghelp.dll. Я бы посоветовал разобраться, благо это не сложно. Также следует отметить знаменитую статью Об упаковщиках в последний раз: Часть первая - теоретическаяОтвет 2
Что касаемо патчинга: int main() { HWND hWnd = FindWindow(0, "Calculator"); if(hWnd == 0){ MessageBox(0, "Error cannot find window.", "Error", MB_OK|MB_ICONERROR); } else { DWORD proccess_ID; GetWindowThreadProcessId(hWnd, &proccess_ID); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proccess_ID); if(!hProcess){ MessageBox(0, "Could not open the process!", "Error!", MB_OK|MB_ICONERROR); } else { DWORD newdatasize = sizeof(newdata); if(WriteProcessMemory(hProcess, (LPVOID)0x40138B , "0x90", newdatasize, NULL)){ MessageBox(NULL, "WriteProcessMemory worked.", "Success", MB_OK + MB_ICONINFORMATION); } else { MessageBox(NULL, "Error cannot WriteProcessMemory!", "Error", MB_OK + MB_ICONERROR); } CloseHandle(hProcess); } } return 0; } Адреса искать по паттерну(уникальной сигнатуре), сделать ее можно в любом отладчике
Комментариев нет:
Отправить комментарий