ВНИМАНИЕ! Конкурс по программированию!
Проект Programmers.kz и школа hotPen3D2D предлагает Вам курсы по веб-дизайну, веб-программированию и компьютерной графике. Подробности здесь.
- Просмотров: 418
- Автор: AlexanderMS
Описание метода взлома игры FlashPoint
Категория: Программирование » Delphi » Статьи и исходники » Программа и интерфейс » Исследование программ
Автор: FreeExec
Проанализировав содержимое файла OperationFlashpoint.exe, я обнаружил, что названия сегментов не содержат не одного символа и экспортируется минимальный набор функций из модулей KERNEL32.DLL, USER32.dll: LoadLibraryA, GetProcAddress, VirtualProtect, ExitProcess, MessageBoxA. Так обычно поступают, чтобы скрыть содержимое файла от всяких дисассемблеров, т.е. когда файл запакован.
Далее запускаю SoftICE и ставлю брекпоинт на функцию определения типа устройства (bpx GetDriveTypeA). Вставляем CD и запускаем игру. Убеждаемся, что функцию вызвала игра, а не explorer.exe. Дальше жму F5 пока эту функцию не вызовут с параметром указывающий путь к CD.
00011E2: lea eax,[ebp][-000C] 00011E5: push eax 00011E6: call d,[000407018] ; GetDriveTypeA 00011EC: mov dl,al ; al=05 тут мы оказались после выхода из функ. 00011EE: lea edi,[ebp][0FFFFF254] ; ссылка на буфер с меткой тома диска 00011F4: or ecx,-001 00011F7: xor eax,eax 00011F9: repne scasb 00011FB: not ecx 00011FD: dec ecx ; ecx равен длине метки 00011FE: add ecx,esi ; esi соответствует адресу на 4 байта меньше чем адрес буфера, т..е обработке подлежат последние 4 символа 0001200: mov bl,[eax][ecx] 0001203: add bl,dl 0001205: mov [eax][ecx],bl ;увеличивают символы на 5(вернула функ.) позиций дальше 0001208: inc eax 0001209: cmp eax,004 ; всего 4 символа 000120C: jl 000001200 -------- (2) 000120E: mov ecx,[ebp][-0010] 0001211: lea edx,[ebp][0FFFFFD1F] 0001217: push ecx 0001218: lea eax,[ebp][0FFFFF254] 000121E: push edx 000121F: push eax 0001220: call 0000014C0 -------- (3) ; эта функция сравнивает два буфера переданные ей в параметрах 0001225: add esp,00C 0001228: test eax,eax 000122A: jne 0000012D5 -------- (4) Функция (3) возвращает 0, если буфера одинаковые, и значит (4)-ый переход не осуществляется. :00401230 lea ecx, dword ptr [ebp-6C] :00401233 push ecx :00401234 call dword ptr [00407014] ; GetStartupInfoA :0040123A xor eax, eax :0040123C mov cl, byte ptr [ebp+eax-00000179] ; mrc32.dll :00401243 mov byte ptr [ebp+eax-00000DAC], cl :0040124A inc eax :0040124B test cl, cl :0040124D jne 0040123C :0040124F lea edi, dword ptr [ebp+FFFFF254] :00401255 or ecx, FFFFFFFF :00401258 xor eax, eax :0040125A mov dx, word ptr [004080C0] :00401261 repnz :00401262 scasb :00401263 or ecx, FFFFFFFF :00401266 mov word ptr [edi-01], dx :0040126A mov edi, dword ptr [ebp+10] :0040126D repnz :0040126E scasb :0040126F not ecx :00401271 sub edi, ecx :00401273 lea edx, dword ptr [ebp+FFFFF254] :00401279 mov esi, edi :0040127B mov ebx, ecx :0040127D mov edi, edx :0040127F or ecx, FFFFFFFF :00401282 repnz :00401283 scasb :00401284 mov ecx, ebx :00401286 dec edi :00401287 shr ecx, 02 :0040128A repz :0040128B movsd :0040128C mov ecx, ebx :0040128E lea eax, dword ptr [ebp-28] :00401291 and ecx, 00000003 :00401294 push eax ; struct _PROCESS_INFORMATION :00401295 repz :00401296 movsb :00401297 lea ecx, dword ptr [ebp-6C] :0040129A lea edx, dword ptr [ebp+FFFFF254] :004012A0 push ecx ; struct _STARTUPINFO :004012A1 push 00000000 :004012A3 push 00000000 :004012A5 push 00000004 :004012A7 push 00000000 :004012A9 push 00000000 :004012AB push 00000000 :004012AD push edx ; mrc32.dll :004012AE push 00000000 :004012B0 call dword ptr [00407010] ; CreateProcess :004012B6 test eax, eax :004012B8 jne 00401307 ... :00401307 mov ecx, dword ptr [ebp+FFFFFCF8] :0040130D mov edx, dword ptr [ebp-28] :00401310 lea eax, dword ptr [ebp-08] :00401313 add ecx, 00400000 :00401319 push eax ; буфер, сюда вернут старые права :0040131A push 00000040 ; новый код доступа, 40h=PAGE_EXECUTE_READWRITE :0040131C push 00000100 ; размер :00401321 push ecx ; адрес региона для изменения доступа к странице памяти :00401322 push edx ; HANDLE hProcess из struct _PROCESS_INFORMATION :00401323 call dword ptr [0040700C] ; VirtualProtectEx :00401329 test eax, eax :0040132B jne 00401348 … :00401348 mov edx, dword ptr [ebp+FFFFFCF8] :0040134E lea eax, dword ptr [ebp-08] :00401351 push eax ; буфер, сюда вернут количество записанных байт :00401352 mov eax, dword ptr [ebp-28] :00401355 lea ecx, dword ptr [ebp+FFFFFD70] :0040135B push 00000100 ; размер буфера :00401360 add edx, 00400000 :00401366 push ecx ; адрес – откуда скопировать (12FCA4) :00401367 push edx ; адрес – куда писать (44CCBF) :00401368 push eax ; HANDLE hProcess :00401369 call dword ptr [00407008] ; WriteProccessMemory :0040136F test eax, eax :00401371 je 0040137C :00401373 cmp dword ptr [ebp-08], 00000100 :0040137A je 00401398 ; осуществляется прыжок … :00401398 mov ecx, dword ptr [ebp-24] :0040139B push ecx ; HANDLE hThread :0040139C call dword ptr [00407004] ; ResumeThread :004013A2 mov edx, dword ptr [ebp-28] :004013A5 push FFFFFFFF ; количество миллисикунд :004013A7 push edx ; HANDLE hHandle :004013A8 call dword ptr [00407000] ; WaitForSingleObject |
Теперь разберемся во всех вызывающихся функциях. GetStartupInfo нужна для получения одноименной структуры, требующейся для функции создания процесса - CreateProcess. Создаем процесс используя файл mrc32.dll, он то и есть ядро игры. Затем функцией VirtualProtectEx назначаем новые права коду загруженного модуля, а именно разрешаем выполнять этот код. Потом туда копируем код из адреса 12FCA4, и передаем управление созданному процессу, функцией WaitForSingleObject. Единственная трудность это получить код который мы копируем для исполнения. Можно было конечно переписать эти 256 байт и руками, но я сделал по другому.
Вставляю CD, ставлю брекпоинт на функцию GetDriveTypeA (bpx GetDriveTypeA), запускаю игру. После вылета в функцию, ставлю еще один брекпоинт (bpx 401355),жму F5. Теперь мне нужны адреса трех функций CreateFileA, WriteFile, ExitProcess. Получаю их поможью команды EXP (exp CreateFileA), в ответ должно быть что-то такое:
exp CreateFileA KERNEL32 001B:77E7A837 CreateFileA exp WriteFile KERNEL32 001B:77E79D8C WriteFile exp ExitProcess KERNEL32 001B:77E75CB5 ExitProcess |
Затем задаю параметры первой функции, прямо в стек.
d esp ## показать стек e ## начать редактировать его |
Должно это выглядеть как-то так. Функция на языке Си выгледит так: CreateFileA(&filename, 0x40000000, 0, 0, 2, 0x80, 0); 8C 9D E7 77 – это адрес возврата (на функцию WriteFile = 77E79D8C), туда попадаем после завершения функции CreateFileA. По адресу 0012E198 (98 E1 12 00) находится имя файла завершающееся нулевым символом. Этот файл должен сущуствовать. Теперь ставим указатель на начало функции CreateFileA.
r eip=77E7A837 # изменяем значение регистра EIP bpx WriteFile # что отловить момент когда завершится первая функция |
Жму F5. Если все нормально, то должен остановится на первой команде функции WriteFile, а EAX не равняться FFFFFFFF, потому что это код ошибки. У меня EAX=000007CC, это хэндл на только что созданный файл. Задаю параметры второй функции, прямо в стек.
d esp ## показать стек e ## начать редактировать его |
Должно это выглядеть как-то так. Функция на языке Си выгледит так: WriteFile(hHandle, 0x0012FCA4, 100, 0x0012E1C8, 0); где hHandle=0x7CC, 0x0012FCA4 – адрес буфера ради которого все и затеял, 100 его размер, 0x0012E1C8 – сюда напишут сколько реально записали байт. 5B 5C E7 77 – это адрес возврата (на функцию ExitProcess = 77E75CB5), туда попадаем после завершения функции CreateFileA. Теперь у меня есть все чтобы с имитировать запуск игры, т.е. написать загрузчик самому без всяких выкрутасов.
Приведен пример загрузчика:
File calldll.asm
.386 .model flat, stdcall option casemap :none ; case sensitive include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib .data? buff db 100h dup (?) prin db 100h dup (?) .code start: jmp @F libName db "mrc32.dll",0 include patch.inc @@: push offset buff call GetStartupInfo push offset prin push offset buff push 0 push 0 push 4 push 0 push 0 push 0 push offset libName push 0 call CreateProcess mov eax, offset [prin+20h] push eax push 000040h push 000100h mov ecx, 44CCBFh push ecx mov eax, dword ptr [prin] push eax call VirtualProtectEx mov eax, offset [prin+20h] push eax push 000100h push offset patch push 44CCBFh mov eax, dword ptr [prin] push eax call WriteProcessMemory mov eax, dword ptr [prin+4] push eax call ResumeThread push 0000FFh mov eax, dword ptr [prin] push eax call WaitForSingleObject invoke ExitProcess,eax end start |
file patch.ini
patch: db 055h,08Bh,0ECh,06Ah,0FFh,068h,018h,024h,06Eh,000h,068h,0ECh,020h,06Ch,000h,064h db 0A1h,000h,000h,000h,000h,050h,064h,089h,025h,000h,000h,000h,000h,083h,0ECh,058h db 053h,056h,057h,089h,065h,0E8h,0FFh,015h,00Ch,052h,06Ch,000h,033h,0D2h,08Ah,0D4h db 089h,015h,0C8h,070h,077h,000h,08Bh,0C8h,081h,0E1h,0FFh,000h,000h,000h,089h,00Dh db 0C4h,070h,077h,000h,0C1h,0E1h,008h,003h,0CAh,089h,00Dh,0C0h,070h,077h,000h,0C1h db 0E8h,010h,0A3h,0BCh,070h,077h,000h,033h,0F6h,056h,0E8h,0CAh,052h,0FFh,0FFh,059h db 085h,0C0h,075h,008h,06Ah,01Ch,0E8h,06Fh,04Eh,027h,000h,059h,089h,075h,0FCh,0E8h db 0B9h,062h,0FFh,0FFh,0FFh,015h,0D8h,051h,06Ch,000h,0A3h,064h,08Bh,077h,000h,0E8h db 08Fh,02Ah,0FFh,0FFh,0A3h,0FCh,070h,077h,000h,0E8h,0A3h,0A0h,0FFh,0FFh,0E8h,037h db 0A1h,0FFh,0FFh,0E8h,0F4h,036h,0FFh,0FFh,089h,075h,0D0h,08Dh,045h,0A4h,050h,0FFh db 015h,010h,052h,06Ch,000h,0E8h,0FEh,0FEh,0FFh,0FFh,089h,045h,09Ch,0F6h,045h,0D0h db 001h,074h,006h,00Fh,0B7h,045h,0D4h,0EBh,003h,06Ah,00Ah,058h,050h,0FFh,075h,09Ch db 056h,056h,0FFh,015h,0E8h,050h,06Ch,000h,050h,0E8h,099h,087h,0FDh,0FFh,089h,045h db 0A0h,050h,0E8h,0F3h,036h,0FFh,0FFh,08Bh,045h,0ECh,08Bh,008h,08Bh,009h,089h,04Dh db 098h,050h,051h,0E8h,060h,001h,000h,000h,059h,059h,0C3h,08Bh,065h,0E8h,0FFh,075h db 098h,0E8h,0C3h,036h,0FFh,0FFh,083h,03Dh,004h,071h,077h,000h,001h,075h,005h,0E8h |
file compl.bat
@echo off e:\masm32\bin\ml /Zf /Zi /c /coff /w calldll.asm if errorlevel 1 goto exit echo _ echo MASM32 OK ************************************************* echo _ e:\masm32\bin\Link /DEBUG /SUBSYSTEM:WINDOWS calldll.obj :exit pause |
Весь архив можно скачать (и он вроде даже работает :)
Источник: delphiworld.narod.ruМы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.




