WriteProcessMemory не работает внутри функции

Привет, я новичок в перехвате функций, и я использовал код из статьи.

Это мой код

#include <windows.h>

#include <iostream>

FARPROC messageBoxAddress = NULL;

SIZE_T bytesWritten = 0;

unsigned char messageBoxOriginalBytes[6] = { } ;

int __stdcall HookedMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {

    printf("la la la ");

    printf("\n");

    WriteProcessMemory(GetCurrentProcess(), (LPVOID)messageBoxAddress, messageBoxOriginalBytes, sizeof(messageBoxOriginalBytes), &bytesWritten);

    return MessageBoxA(NULL, lpText, lpCaption, MB_OK);

}


int main()
{

    SIZE_T bytesRead = 0; 

    HINSTANCE library = LoadLibraryA("user32.dll");

    FARPROC messageBoxAddress =GetProcAddress(library, "MessageBoxA");

    ReadProcessMemory(GetCurrentProcess(), messageBoxAddress, messageBoxOriginalBytes, 6, &bytesRead);

    void* hookedMessageBoxAddress = &HookedMessageBox;

    char patch[6] = { 0 };

    memcpy_s(patch, 1, "\x68", 1);

    memcpy_s(patch + 1, 4, &hookedMessageBoxAddress, 4);

    memcpy_s(patch + 5, 1, "\xC3", 1);


    WriteProcessMemory(GetCurrentProcess(), (LPVOID)messageBoxAddress, patch, sizeof(patch), &bytesWritten);


    MessageBoxA(NULL, "hello", "Welcome", MB_OK);

    return 0;
}

Вывод

la la la
la la la
la la la
la la la
la la la
la la la
la la la

Проблема в том, что я хочу только один ля ля ля

Это показывает тысячу ла ла ла

WriteProcessMemory внутри int main () работает, но внутри «HookedMessageBox» не работает.

Может кто-нибудь указать мне исправление

Также я хочу придерживаться основ. Есть обходные пути к библиотекам и т.д.

Я попытался получить ошибку с помощью GetLastError (), и он показал 998, что означает отказ в доступе (поиск в сети)


person Habi Haris    schedule 21.05.2020    source источник
comment
Я предполагаю, что, поскольку функция была недавно выполнена, страница помечена как недоступная для записи. Вы можете попробовать настроить права доступа к памяти, как указано в ответе на этот вопрос. stackoverflow.com/questions/39732894/   -  person TheSteve    schedule 21.05.2020
comment
Вы не должны вызывать MessageBox внутри HookedMessageBox, потому что MessageBox перехватывается, и вместо этого вы вызываете свой перехватчик HookedMessabeBox. Таким образом, это приведет к бесконечной рекурсии. Вместо этого вы должны вызвать messageBoxOriginalBytes. Но messageBoxOriginalBytes должен содержать еще пять байтов в конце, jmp + адрес для следующих байтов в MessabeBox.   -  person armagedescu    schedule 21.05.2020
comment
@TheSteve Pages не помечаются как недоступные для записи в зависимости от того, как давно они были выполнены. Как недавно это было не имеет значения   -  person David Heffernan    schedule 21.05.2020
comment
Если вам нужны основы, начните с проверки ошибок.   -  person Jonathan Potter    schedule 21.05.2020
comment
Никогда не нужно использовать (Read|Write)ProcessMemory() с GetCurrentProcess(). У процесса есть доступ к собственному пространству памяти. Вместо этого будет достаточно простого memcpy() или CopyMemory().   -  person Remy Lebeau    schedule 21.05.2020
comment
Пожалуйста, не пытайтесь изменить память, которую вы выполняете. Переместите, запишите функцию и вызовите MessageBox за пределами функции. Вы можете обратиться к этому проекту обхода и использовать его.   -  person Drake Wu    schedule 22.05.2020


Ответы (3)


Это называется рекурсией крюка, чтобы решить проблему, связанную с использованием крюка для батута.

Крюк-батут похож на обычный обходной путь: он переходит к вашему коду, но затем он возвращается к адресу, следующему за вашей реальной инструкцией jmp, таким образом, он не выполняет ваш код снова и снова.

Вам не нужно использовать WriteProcessMemory () при внутренней работе, и вы не должны изменять свой хук внутри своего хука.

Вот мое решение вашей проблемы, в котором используется крюк для батута и, надеюсь, какой-то код, который имеет больше смысла:

#include <iostream>
#include <Windows.h>

bool Detour32(char* src, char* dst, const intptr_t len)
{
    if (len < 5) return false;

    DWORD  curProtection;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    intptr_t  relativeAddress = (intptr_t)(dst - (intptr_t)src) - 5;

    *src = (char)'\xE9';
    *(intptr_t*)((intptr_t)src + 1) = relativeAddress;

    VirtualProtect(src, len, curProtection, &curProtection);
    return true;
}

char* TrampHook32(char* src, char* dst, const intptr_t len)
{
    // Make sure the length is greater than 5
    if (len < 5) return 0;

    // Create the gateway (len + 5 for the overwritten bytes + the jmp)
    void* gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    //Write the stolen bytes into the gateway
    memcpy(gateway, src, len);

    // Get the gateway to destination addy
    intptr_t  gatewayRelativeAddr = ((intptr_t)src - (intptr_t)gateway) - 5;

    // Add the jmp opcode to the end of the gateway
    *(char*)((intptr_t)gateway + len) = 0xE9;

    // Add the address to the jmp
    *(intptr_t*)((intptr_t)gateway + len + 1) = gatewayRelativeAddr;

    // Perform the detour
    Detour32(src, dst, len);

    return (char*)gateway;
}

typedef int(__stdcall* tMessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
tMessageBoxA oMessageBoxA = nullptr;

int __stdcall hkMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
    lpText = "hax0red";

    return oMessageBoxA(hWnd, lpText, lpCaption, uType);
}

int main()
{
    oMessageBoxA = (tMessageBoxA)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");

    oMessageBoxA = (tMessageBoxA)TrampHook32((char*)oMessageBoxA, (char*)hkMessageBoxA, 5);

    MessageBoxA(NULL, "Body Message", "Title Here", MB_OK);

    return 0;
}
person GuidedHacking    schedule 03.06.2020
comment
спасибо, я обязательно попробую это, когда вернусь домой. - person Habi Haris; 04.06.2020
comment
@HabiHaris x64 требует другой функции, потому что он должен принимать адреса размером 64 бита. Используемая мной функция крюка для батута x64 доступна здесь guidedhacking.com/threads/code -detouring-hooking-guide.14185 - person GuidedHacking; 05.06.2020

Спасибо @GuidedHacking, я наконец сделал 64 рабочего кода.

Переименован в Detour64 и TrampHook64.

#include <iostream>
#include <Windows.h>

bool Detour64(char* src, char* dst, const intptr_t len)
{
    if (len < 12) return false;

    DWORD  curProtection;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    intptr_t  absoluteAddress = (intptr_t)(dst);

    *src = (char)'\x48';
    *(src + 1) = (char)'\xb8';

    *(src + 2) = absoluteAddress % 256;
    *(src + 3) = (absoluteAddress/256) % 256;
    *(src + 4) = (absoluteAddress/65536) % 256;
    *(src + 5) = (absoluteAddress/(65536*256)) % 256;
    *(src + 6) = (absoluteAddress/((long long)65536*65536)) % 256;
    *(src + 7) = (absoluteAddress/((long long)65536*65536*256)) % 256;
    *(src + 8) = (absoluteAddress/((long long)65536*65536*65536))%256;
    *(src + 9) = (absoluteAddress/((long long)65536*65536*65536*256)) % 256;

    *(src + 10) = (char)'\xff';
    *(src + 11) = (char)'\xe0';

    VirtualProtect(src, len, curProtection, &curProtection);
    return true;
}

char* TrampHook64(char* src, char* dst, const intptr_t len)
{
    // Make sure the length is greater than 5
    if (len < 12) return 0;

    // Create the ga+teway (len + 5 for the overwritten bytes + the jmp)
    void* gateway = VirtualAlloc(0, len + 12, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    //Write the stolen bytes into the gateway
    memcpy(gateway, src, len);

    // Get the gateway to destination addy
    intptr_t  gatewayAbsoluteAddr = (intptr_t)src+len;    
 // Add the jmp opcode to the end of the gateway
    *((char*)gateway + len) = 0xFF;
    *((char*)gateway + len + 1) = 0x25;

    *((char*)gateway + len + 2) = 0;
    *((char*)gateway + len + 3) = 0;
    *((char*)gateway + len + 4) = 0;
    *((char*)gateway + len + 5) = 0;
    // Add the address to the jmp
    *((char*)gateway + len + 6) = gatewayAbsoluteAddr % 256;

    *((char*)gateway + len + 7) = (gatewayAbsoluteAddr / 256) % 256;

    *((char*)gateway + len + 8) = (gatewayAbsoluteAddr / 65536) % 256;

    *((char*)gateway + len + 9) = (gatewayAbsoluteAddr / (65536 * 256)) % 256;

    *((char*)gateway + len + 10) = (gatewayAbsoluteAddr / ((long long)65536 * 65536)) % 256;

    *((char*)gateway + len + 11) = (gatewayAbsoluteAddr / ((long long)65536 * 65536 * 256)) % 256;

    *((char*)gateway + len + 12) = (gatewayAbsoluteAddr / ((long long)65536 * 65536 * 65536)) % 256;
    *((char*)gateway + len + 13) = (gatewayAbsoluteAddr / ((long long)65536 * 65536 * 65536 * 256)) % 256;
   
    // Perform the detour
    Detour64(src, dst, len);

    return (char*)gateway;
}

typedef int(__stdcall* tMessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
tMessageBoxA oMessageBoxA = nullptr;

int __stdcall hkMessageBoxA(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
    
    lpText = LPCTSTR("hax0red");
    
    return oMessageBoxA(hWnd, lpText, lpCaption, uType);
}

int main()
{

    HINSTANCE libr = LoadLibrary(L"User32.dll");
    
    oMessageBoxA = (tMessageBoxA)GetProcAddress(libr, "MessageBoxA");

    oMessageBoxA = (tMessageBoxA)TrampHook64((char*)oMessageBoxA, (char*)hkMessageBoxA, 14);
    
    MessageBoxA(NULL, "Body Message", "Title Here", MB_OK);

    return 0;
}

Надеюсь, это всегда правильно.

person Habi Haris    schedule 06.06.2020

Небольшая, но важная информация о коде @GuidedHacking. Обязательно измерьте длину крючка, который вы проходите, это не всегда 5, зависит от инструкций вашей исходной функции, это может быть 5, может быть 6 и т. Д. Вы можете увидеть это в IDA и указать правильный размер

person Just Damien    schedule 17.04.2021