Исходник Ищем функции в CE

Vadim.dll

Известный
Автор темы
168
80
Есть тут замечательная тема с инжектом в функции от могайки: https://blast.hk/threads/2370/#post-27225
Все в ней хорошо, только не рассказывается как искать функции и параметры к ним. Сейчас покажу как перехватывать сообщения, введенные нами в чат.

Значит для начала запускаем ЖТА и логинимся на рандомный аккаунт, чтобы был доступ к чату.
В чате пишем что-нибудь на русском, в CE выбираем процесс с ЖТА, тип исхомых данных выбираем String, ставим галочку напротив UTF-16, вводим что-нибудь в чате, тоже самое в поиске и находим наш адрес.

upload_2019-5-26_12-28-0.png


Добавляем в выбранные адреса, жмем ПКМ по добавленному адресу -> Find out what writes to this address. Потом отправляем сообщение в сампе и смотрим что произошло:

upload_2019-5-26_12-29-56.png


обнаружена инструкция, взаимодействующая с нашими данными в строке ввода. В данном случае эта инструкция обнуляет буффер после отправки сообщения. Жмем Show Dissasembler и вот мы в теле какой-то функции. Перемещаемся к началу:

upload_2019-5-26_12-33-21.png


(Начало можно определить по куче int опкодов). Значит видим в начале две инструкции, которые занимаю 5 байт, как раз хватит для того, чтобы сделать jmp к нашей функции. Дело осталось за малым.

Пишем инжект:
C++:
void _declspec(naked) Hook( void )
{
 
    _asm {
        pushad

        push[esp + 0x28] // arg2
        push[esp + 0x28] // arg1

        call myfunc

        popad

        push edi
        mov edi, [esp+0xC]
        jmp ret_addr
    }

}

void SetupHook(DWORD dwSamp)
{

    DWORD dwAddr = dwSamp + CLEAR_CHAT_HOOK;
    ret_addr = (LPVOID)(dwAddr + 5);

    DWORD dwProt = PAGE_EXECUTE_READWRITE;

    VirtualProtect((void *)dwAddr, 5, dwProt, &dwProt);

    unsigned char* pdata = (unsigned char*)dwAddr;
    pdata[0] = 0xE9; // jmp
    *(unsigned int*)& pdata[1] = (unsigned int)Hook - (dwAddr + 5);

    VirtualProtect((void*)dwAddr, 5, dwProt, NULL);
}

Теперь надо бы определить, какие аргументы в эту функцию передаются, я делал это так: накидываю push'ей, потом смотрю какие данные передаются туда.
Здесь например 2 push'a, запускаем данный скрипт в игре и ставим Break and Trace instructions на нашей jmp:
upload_2019-5-26_12-41-43.png



Вводим любое сообщение в чат и смотрим, какие данные передаются в наших push'ах. В первом пуше - во втором аргументе передается какой-то непонятный DWORD
upload_2019-5-26_12-43-47.png


Во втором пуше - первом аргументе какой-то указатель, возможно это указатель на нашу строку.

upload_2019-5-26_12-44-16.png


Так и есть
upload_2019-5-26_12-45-35.png


Теперь осталось дописать нашу функцию, которая будет ловить эти сообщения. Второй параметр можно убрать.

C++:
void __stdcall myfunc(wchar_t* arg1)
{
    MessageBox(NULL, arg1, L"TEST", MB_OK);
}

void _declspec(naked) Hook( void )
{
 
    _asm {
        pushad

        push[esp + 0x24] // arg1

        call myfunc

        popad

        push edi
        mov edi, [esp+0xC]
        jmp ret_addr
    }
}

В итоге получаем перехват сообщения:
upload_2019-5-26_12-48-1.png


C++:
#include <Windows.h>
#include <process.h>
#include <stdio.h>

#define CLEAR_CHAT_HOOK 0x7FF00

LPVOID ret_addr;

void __stdcall myfunc(wchar_t* arg1)
{
    MessageBox(NULL, arg1, L"TEST", MB_OK);
}

void _declspec(naked) Hook( void )
{
 
    _asm {
        pushad

        push[esp + 0x24] // arg1

        call myfunc

        popad

        push edi
        mov edi, [esp+0xC]
        jmp ret_addr
    }
}

void SetupHook(DWORD dwSamp)
{

    DWORD dwAddr = dwSamp + CLEAR_CHAT_HOOK;
    ret_addr = (LPVOID)(dwAddr + 5);

    DWORD dwProt = PAGE_EXECUTE_READWRITE;

    VirtualProtect((void *)dwAddr, 5, dwProt, &dwProt);

    unsigned char* pdata = (unsigned char*)dwAddr;
    pdata[0] = 0xE9; // jmp
    *(unsigned int*)& pdata[1] = (unsigned int)Hook - (dwAddr + 5);

    VirtualProtect((void*)dwAddr, 5, dwProt, NULL);
}

void attach(PVOID)
{

    DWORD dwSamp = (DWORD)GetModuleHandle(L"samp.dll");
    while (dwSamp == NULL)
    {
        Sleep(1000);
        dwSamp = (DWORD)GetModuleHandle(L"samp.dll");
    }

    SetupHook(dwSamp);
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) _beginthread(attach, NULL, NULL);
    return TRUE;
}

Вообще не понятно, что данная функция делает, но наша цель была перехватить сообщение, выводимое в чат, цель достигнута.
Я только изучаю все это дело, поэтому способ может быть не самый лучший. Может кто знает что-нибудь по лучше?
 

Вложения

  • upload_2019-5-26_12-29-42.png
    upload_2019-5-26_12-29-42.png
    169.5 KB · Просмотры: 265
  • upload_2019-5-26_12-47-31.png
    upload_2019-5-26_12-47-31.png
    300.9 KB · Просмотры: 264
Последнее редактирование:

wD.D159

Известный
Друг
446
479
Код под спойлером бы привел в порядок, читаемость его ужасна. А так молодец, гайд удался, я все понял!
 

Vintik

Мечтатель
Проверенный
1,411
851
спасибо за гайд, так сказать) скинь литературу, откуда ты про это прочитал. а то мои навыки остановились пока что на том, чтобы найти адрес, а после найти его базовый + все поинтеры и смещения.