Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Патчер памяти на MASM

15K
29 ноября 2007 года
hel
78 / / 10.11.2007
На досуге возникла вот такая мысль... Очень хочется разобраться, как правильно патчить память. На C++ у меня получается вроде неплохо. Но вот на ассемблере у меня работа просто встала клином. :)

Для чего мне, собственно, это нужно?
- Ну к примеру для создания патчей или трейнеров, да и просто для расширения знаний.
Почему на ассемблере?
- Нужна предельная скорость пропатчивания и маленький размер, да и просто в данный момент меня наиболее интересует изучение именно этого языка.

Суть моего вопроса конечно же заключается в том, что сам додуматься, как правильно писать в память на MASM'е - не могу, ибо я уже успел запутаться в коде... Я ассемблером начал заниматься полтора месяца назад, многое неясно, многое непонятно, но потихоньку разбираюсь и даже нахожу аналогии в алгоритме с другими языками программирования.

Этот код я попытался перегнать из C++ в MASM. (руками естественно)
Вот код после перегонки (ясный пень где-то ошибки есть, ибо я просто так тему бы не создавал), так как ошибка появляется именно при использовании АПИ функции - думаю тему я запостил там где надо, этот код компилируется в DLL:
Код:
.486
.model flat,stdcall
option casemap:none

include windows.inc
include kernel32.inc
include user32.inc
include masm32.inc
includelib kernel32.lib
includelib user32.lib
includelib masm32.lib

.const
    replaceAt dd 00403000h ; по этому адресу нужно вставить
    replaceBy db "Hooked!",0 ; вот это

.data
    ProcessId dd 0 ; PID
    ProcessHandle dd 0 ; Открытый процесс
    Lentgh dd 0 ; Длина строки для патчинга (strlen(replaceBy))
    ProtectFlag dd 0 ; Тут сохраняются "права доступа" к памяти.
    msgCaption db "Dll message",0 ; Заголовок MessageBox
    msgErrorOpenProc1 db "Error while retrieving process id.",0 ; 1
    msgErrorOpenProc2 db "Error while opening process.",0 ; 2
    msgErrorMemReplace1 db "Replacing memory failed.",0 ; 3
    msgErrorMemReplace2 db "Replacing memory at first Virtual Protect failed.",0 ; 4
    msgErrorMemReplace3 db "Replacing memory at MemCopy failed.",0 ; 5
    msgErrorMemReplace4 db "Replacing memory at second Virtual Protect failed.",0 ; 6... 1,2,3,4,5,6 это тексты MessageBox.

.code
    ReplaceMem proc ReplaceAtAddr:DWORD,ReplaceByValue:DWORD,Len:DWORD ; Функция патчинга.
        invoke VirtualProtect,ReplaceAtAddr,Len,PAGE_EXECUTE_READWRITE,ADDR ProtectFlag ; Выставляем права(?) на доступ к памяти.
        .if eax==FALSE ; если VirtualProtect возвратила false - ошибка и завершение программы.
            invoke MessageBox,NULL,ADDR msgErrorMemReplace2,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        invoke MemCopy,ReplaceAtAddr,ADDR ReplaceByValue,Len ; Используем функцию Masm'а, MemCopy (аналог memcpy в C).
        .if eax==FALSE ; если MemCopy вернула false - ошибка и завершение программы.
            invoke MessageBox,NULL,ADDR msgErrorMemReplace3,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        invoke VirtualProtect,ReplaceAtAddr,Len,ProtectFlag,NULL ; Восстанавливаем права доступа к памяти из ProtectFlag.
        .if eax==FALSE ; Если VirtualProtect вернула false - ошибка и завершение программы.
            invoke MessageBox,NULL,ADDR msgErrorMemReplace4,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        mov eax,TRUE ;
        ret ; возвращаем true, что успешно выполнен патчинг.
    ReplaceMem endp ; конец функции патчинга
   
    LibMain proc hInstDLL:DWORD, dwReason:DWORD, unused:DWORD ; Это будет EP дллки, здесь происходит вызов патчера.
        .if dwReason==DLL_PROCESS_ATTACH
            invoke GetCurrentProcessId ; получаем PID нашего процесса (той проги то запустила DLL).
                mov ProcessId,eax ; кладём PID в ProcessId.
            .if ProcessId==FALSE ; Если ProcessId=false - ругаемся и выходим из программы.
                invoke MessageBox,NULL,ADDR msgErrorOpenProc1,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,ProcessId ; открываем процесс.
                mov ProcessHandle,eax ; записываем возвращёное значение в ProcessHandle
            .if ProcessHandle==FALSE ; если ProcessHandle=false - ругаемся и выходим
                invoke MessageBox,NULL,ADDR msgErrorOpenProc2,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            invoke StrLen,ADDR replaceBy ; Читаем длину строки.
                add eax,1 ; добавляем 1 (вспомним что строки кончаются символом 0h).
                mov Lentgh,eax ; суём длину строки в Lentgh
            invoke ReplaceMem,replaceAt,ADDR replaceBy,Lentgh ; вызываем нашу функцию патчинга.
            .if eax==FALSE ; если возвращён false - ругаемся и выходим.
                invoke MessageBox,NULL,ADDR msgErrorMemReplace1,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            mov eax,TRUE ;
            ret ; возвращаем TRUE.
        .elseif dwReason==DLL_PROCESS_DETACH
        .elseif dwReason==DLL_THREAD_ATTACH
        .elseif dwReason==DLL_THREAD_DETACH
        .endif
        ret
    LibMain endp
end LibMain


Нужно сделать так, чтобы "Message Title" сменилось на "Hooked!"
Если лень компилировать, вот сурсы и бинарники, также там есть рабочий пример длл на C++.
Надеюсь на помощь. Или хотя-бы подсказку, где я сплоховал.
Или может есть какие-нибудь полегче способы может?
367
30 ноября 2007 года
Meatcoins
303 / / 18.01.2006
Я немножко переписал твою программку, чтоб просто понятнее было...
Hook.asm:
Код:
.386
            .model flat, stdcall
             option casemap :none
             include E:\masm32\include\windows.inc
             include E:\masm32\include\kernel32.inc
             include E:\masm32\include\user32.inc
             includelib E:\masm32\lib\kernel32.lib
             includelib E:\masm32\lib\user32.lib
             include E:\masm32\macros\Strings.mac
       
             include E:\masm32\include\w2k\ntstatus.inc
             include E:\masm32\include\w2k\native.inc
             include E:\masm32\include\w2k\ntdll.inc          
             includelib E:\masm32\lib\w2k\ntdll.lib

includelib MemReplace.lib


extrn   _imp__My@0:dword
My equ _imp__My@0


.data
mytext db "My good Title Of Message Box",0h
myproc db "My",0h
.code
_start proc
LOCAL han:DWORD
LOCAL memory:DWORD
LOCAL heap:DWORD
LOCAL procaddr:DWORD
;call My

invoke GetProcessHeap
mov heap,eax
invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,1000h
mov memory,eax
invoke GetModuleHandle,$CTA0("MemReplace.dll")
mov han,eax
invoke GetModuleFileName,han,memory,1000h
;invoke MessageBox,0h,memory,$CTA0("Title"),MB_OK
invoke HeapFree,heap,0h,memory
invoke GetProcAddress,han,offset myproc
mov procaddr,eax
call eax

invoke MessageBox,0h,offset mytext,offset mytext,MB_OK
invoke ExitProcess,0h
_start endp
end _start


MemReplace.asm:
Код:
.486                      ; create 32 bit code
      .model flat, stdcall      ; 32 bit memory model
      option casemap :none      ; case sensitive



include E:\masm32\include\windows.inc
include E:\masm32\include\kernel32.inc
include E:\masm32\include\user32.inc
include E:\masm32\include\masm32.inc
includelib E:\masm32\lib\kernel32.lib
includelib E:\masm32\lib\user32.lib
includelib E:\masm32\lib\masm32.lib


.const
    replaceAt dd 00403000h
    replaceBy db "Hooked!",0

.data
    Buff db "number",0
    msgCaption db "Dll message",0
    msgErrorOpenProc1 db "Error while retrieving process id.",0
    msgErrorOpenProc2 db "Error while opening process.",0
    msgErrorMemReplace1 db "Replacing memory failed.",0
    msgErrorMemReplace2 db "Replacing memory at first Virtual Protect failed.",0
    msgErrorMemReplace3 db "Replacing memory at MemCopy failed.",0
    msgErrorMemReplace4 db "Replacing memory at second Virtual Protect failed.",0

      .data?
        hInstance dd ?
         ProcessId dd ?
        ProcessHandle dd ?
        Lentgh dd ?
        ProtectFlag dd ?
        ProtectFlag2 dd ?

      .code

Memoryproc proc ReplaceAtAddr:DWORD,ReplaceByValue:DWORD,Len:DWORD

mov edi,ReplaceAtAddr
mov esi,ReplaceByValue
mov ecx,Len
rep movsb

ret
Memoryproc endp


    ReplaceMem proc ReplaceAtAddr:DWORD,ReplaceByValue:DWORD,Len:DWORD
        invoke VirtualProtect,ReplaceAtAddr,Len,PAGE_EXECUTE_READWRITE,ADDR ProtectFlag
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace2,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        ;invoke MemCopy,ReplaceAtAddr,ReplaceByValue,Len
                        invoke Memoryproc,ReplaceAtAddr,ReplaceByValue,Len
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace3,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        invoke VirtualProtect,ReplaceAtAddr,Len,ProtectFlag,offset ProtectFlag2
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace4,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        mov eax,TRUE
        ret
    ReplaceMem endp

My proc
invoke MessageBox,0h,offset msgCaption,offset msgCaption,MB_OK
            invoke GetCurrentProcessId
                mov ProcessId,eax
            .if ProcessId==FALSE
                invoke MessageBox,NULL,ADDR msgErrorOpenProc1,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,ProcessId
                mov ProcessHandle,eax
            .if ProcessHandle==FALSE
                invoke MessageBox,NULL,ADDR msgErrorOpenProc2,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            invoke StrLen,ADDR replaceBy
                add eax,1
                mov Lentgh,eax
            invoke ReplaceMem,replaceAt,ADDR replaceBy,Lentgh
            .if eax==FALSE
                invoke MessageBox,NULL,ADDR msgErrorMemReplace1,ADDR msgCaption,MB_OK or MB_ICONERROR
                invoke ExitProcess,0h
            .endif
            mov eax,TRUE
            ret

My endp



LibMain proc instance:DWORD,reason:DWORD,unused:DWORD
    .if reason == DLL_PROCESS_ATTACH
      push instance
      pop hInstance
      mov eax, TRUE
    .elseif reason == DLL_PROCESS_DETACH
    .elseif reason == DLL_THREAD_ATTACH
    .elseif reason == DLL_THREAD_DETACH
    .endif
    ret
LibMain endp
end LibMain

И ещё:
invoke VirtualProtect,ReplaceAtAddr,Len,ProtectFlag,offset ProtectFlag2
Если последний параметр равен NULL, то функция обязательно провалится!
А у тебя вот так было:
Код:
ReplaceMem proc ReplaceAtAddr:DWORD,ReplaceByValue:DWORD,Len:DWORD
        invoke VirtualProtect,ReplaceAtAddr,Len,PAGE_EXECUTE_READWRITE,ADDR ProtectFlag
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace2,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        invoke MemCopy,ReplaceAtAddr,ADDR ReplaceByValue,Len
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace3,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        invoke VirtualProtect,ReplaceAtAddr,Len,ProtectFlag,NULL
        .if eax==FALSE
            invoke MessageBox,NULL,ADDR msgErrorMemReplace4,ADDR msgCaption,MB_OK or MB_ICONERROR
            mov eax,FALSE
            ret
        .endif
        mov eax,TRUE
        ret
    ReplaceMem endp


УДАЧИ во всём!!! И с наступающим Новым Годом!!!
15K
30 ноября 2007 года
hel
78 / / 10.11.2007
Meatcoins:
Большое спасибо. Есть ещё один вопрос по твоему коду.
У меня Memoryproc в открытом виде не работает. Прога не запускается. (при дебаге пишет, что ошибка чтения-записи в [00000000])
Поэтому я немного исправил код:
Код:
ReplaceMem proc ReplaceAtAddr:DWORD, ReplaceByVal:DWORD, Len:DWORD
    invoke VirtualProtect, ReplaceAtAddr, Len, PAGE_EXECUTE_READWRITE, ADDR ProtectFlag
    pusha
    mov edi,ReplaceAtAddr
    mov esi,ReplaceByVal
    mov ecx,Len
    rep movsb
    popa
    invoke VirtualProtect, ReplaceAtAddr, Len, ProtectFlag, ADDR ProtectFlag2
    ret
ReplaceMem endp


Или я где-то ошибся, или rep movsb юзает ещё какие-то регистры кроме esi, edi, ecx. Хотя в справочнике от интела указанны только они. Кстати, спасибо за этот способ копирования. :)
367
01 декабря 2007 года
Meatcoins
303 / / 18.01.2006
А у меня работает всё!
Если хочешь - посмотри архивчик!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог