Перейти к содержанию

VDV

Пользователи
  • Постов

    93
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные VDV

  1. Не правильно.

    Мы изменяем уже существующий экземпляр класса в игре.

    Выведи в консоль себе адрес localPlayer->Recoil

    вывел - то есть не выводит , крашит.

    ----------------------------------------------------

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

  2. практиковался по видео уроку Кодера , а именно "реверсинг".

    ------------------------------------------

    сам код:

    начал с простенького,отреверсил , скопировал класс c генератора РЕКЛАССА , класс простенький , состоящий только из одного параметра(для тренировки)

    class RecoilPlayer;

    class RecoilPlayer
    {
    public:
    __int32 Recoil; //0x0000
    char _0x0004[60];

    static RecoilPlayer* Singleton (int*address)
    {
    return *(RecoilPlayer**)address;
    }
    };//Size=0x0040

    далее:

    CreateConsole();
    DWORD Recoil_Eng = (DWORD)GetModuleHandle("Game.exe") + 0x13F135C;
    DWORD offsets[] = {0x50 , 0x138 , 0xC , 0x4 , 0x3C};
    int* locPlayer = ReadPointer(Recoil_Eng, offsets ,5);
    RecoilPlayer* localPlayer = RecoilPlayer::Singleton(locPlayer);
    printf (" address = %X\n%X\n%d\n" , Recoil_Eng , locPlayer , localPlayer);

    localPlayer->Recoil = 100;

    в отладочной консоле все верно - Recoil_Eng - поинтер верный , locPlayer - адресс верный , localPlayer - значение адреса соответственно верное.

    При попытке

    localPlayer->Recoil = 100;

    - краш,не могу понять , в чем дело.

    ==========================================================================

    Я правильно понимаю , что мы создаём копию игрового класса и изменяем эту копию , а не сам адрес и поэтому при просмотре в СЕ сам адрес не будет изменен никак , а будет изменена только наша копия класса?

  3. Да. Видишь, когда тебе не подносишь на блюдечке код, а лишь подсказываешь, в каком направлении примерно нужно двигаться, у тебя начинает получаться, потому что ты читаешь, и начинаешь осознавать, что именно ты делаешь.

    нужно сделать саму функцию сначала , а затем с помощью неё искать , я правильно рассуждаю , она будет аналогична FindPattern , да что там идентична?

  4. Если тебе нужно сканировать область выделенной памяти, а не принадлежащей модулю, надо расширять сканер, используя VirtualQuery (если из dll) или VirtualQueryEx (если из внешнего приложения).

    Получается что для игры каждый раз выделяется некоторая область памяти (по разному при каждом перезаходе), значит мне нужно сканировать область выделенной памяти - я правильно мыслю?

    мне нужна вот эта штука(для dll)?

    HRESULT VirtualQuery (
    [in] void* lpAddress,
    [out] void* lpBuffer,
    [in] SIZE_T dwLength,
    [out] SIZE_T* pResult
    );

  5. Начнём с того, у dll есть доступ к любой памяти, принадлежащей приложению.

    А закончим тем, что второй параметр FindPattern это length (длина), и у тебя она не 0x18000000, а (0x18000000 - 0x16000000).

    А крашится потому что ты уходишь за пределы памяти выделенной под приложение. Access Violation: 0xC0000005.

    это я знаю что длина - это просто пример я показал. Все правильно ухожу за пределы , но если я в функции указываю

    DWORD pattern_address2 = FindPattern (модуль,его длину ,
    (PBYTE)"\x72\x65\x63\x6F\x69\x5F" , "xxxxxx");

    то адрес не находится , потому что я сканирую длину модуля (к примеру от 0х1000 до 0х2000) , а адрес находится, к примеру,от 0х3000 до 0х3100

    и не принадлежит не к какому модулю, как быть? Если я укажу в FindPattern (0х3000,0х100 ,)(к примеру) то FindPattern начнет сканировать этот участок

    памяти и где-нибудь в диапазоне от 0х3050 до0х3080 будет "память за пределами" , а адрес который мне нужен будет 0х3090 и когда сканер дойдет до

    0х3050 будет краш , как правильно сделать?

  6. Все вопросы обсуждаю только на форуме.

    вот тебе вопрос:

    Например ,если я сканирую массив байт в пределе игрового модуля , допустим модуль "crysis.exe" начало 0х100000 конец 0х200000 (размер 100000 получается), то я нахожу нужный мне адрес по массиву байт ,все отлично работает. НО !!! если мне нужно просканировать к примеру район от 0х3000000 до 0х4000000(так как в этом районе памяти находится динамический адрес , который мне нужен,при каждом перезаходе в игру адрес меняется ,но остаётся в этом участке памяти) и этот район памяти не является не одим модулем игры (выделенный участок динамической памяти). Проблема вот в чем - в данном участке памяти от 0х3000000 до 0х4000000 нужный мне адрес может находиться как по адресу ,к примеру, 0х3155FF00 ,а после перезахода в игру, по адресу 0х4000000 - думаю это понятно что ДМА. Но каждый раз в этом диапазоне памяти при перезаходе в игру есть места памяти которые недоступны для чтения\записи , мало того этот участок памяти может быть к примеру от 0х3000000 до 0х3200000 , а адрес который мне нужен 0х3500000 , при перезаходе в игру участок не читаемой\записываемой памяти будет от 0х3400000 до 0х3600000 а адрес нужный мне 0х3100000. Поэтому когда FindPattern сканирует заданный диапазон памяти (от 0х3000000 до 0х4000000 к примеру) и натыкается на участок не читаемой\записываемой памяти - происходит краш игры,как это избежать. Объяснить очень тяжело было , но я попытался. Смысл в том , что когда Find Pattern натыкается на недоступную для чтения\записи память - краш.

    (все в dll, не винапи)

    DWORD pattern_address2 = FindPattern (0x16000000,0x18000000 ,
    (PBYTE)"\x72\x65\x63\x6F\x69\x5F" , "xxxxxx");

  7. И тут я выстрелил себе в голову...

    Потом воскрес и снова сделал это...

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

    Автор, без обид, но я реально уже в шоке с тебя!!!

    Ты говорил что знаешь С++ хотя бы на базовом уровне? - Ты никогда ещё так в жизни не ошибался.

    Ты вообще не знаешь С++ и устройство памяти.

    Для начала вот что я тебе скажу:

    1) Идёшь и читаешь про адресацию памяти

    2) Учишь что такое типы данных, их многообразие. Расположение переменных в памяти.

    3) Учишься работать с массивами, перебирать их (попутно изучая циклы, и устройство указателей).

    4) Изучаешь функции, что это такое и что такое аргументы функции.

    5) Изучаешь WinAPI (хотя бы тех функций, которые необходимы).

    6) Изучаешь особенности dll и вообще для чего они используются.

    И после всех этих шагов, ты сможешь сделать то, что желаешь.

    Друг давай без нравоучений - просто скажи что в коде не верно , а я сам разбирусь что к чему.

    p.s. если ты хорошо знаешь программирование - это не значит что нужно всем незнающим говорить что они глупые и вообще не в ту степь лезут. Да , я не мастер в программировании , но код я брал ТВОЙ из ТВОЕГО урока и с ТВОИМИ объяснениями, также этот код я попросил проверить у "King Orgy" через "teem viewer" он не поленился и уделил немного времени , подправил кое-что и сказал что "вот в таком виде как сверху" верно - и проблема в хуке - я не смог переписать хук , так , чтобы не крашило и обратился на русскоязычный сайт,думал что тут помогут ...делаем вывод ....

    Хочешь для сравнения я тебе опишу похожую ситуацию?

    Это как если бы ты вышел со мной на спарринг(бокс) и простоял со мной 1 раунд и спросил бы "у меня нечего не получается , может у меня стойка не правильная или я не так бью?" и я тебе после этого сказал бы "иди ка ты домой и читай книжки о боксе и пока отжиматься не научишься 150 раз , а потом бегать 10 км без передышки , а после этого отстоять спарринг с перворазрядником , у тебя нечего получится в боксе , как все это научишся делать так и молодец будешь"

  8. не могу записать в массив байт , просьба найти ошибки или подсказать что не правильно в коде(исходный код из урока кодера)


    DWORD WINAPI Game_thread (LPVOID);
    DWORD APIENTRY DllMain (HMODULE hModule ,DWORD ul_reason_for_call , LPVOID lpReservid )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    CreateThread (NULL,NULL,Game_thread,NULL,NULL,NULL);

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return true;
    }

    BOOL bCompare(const BYTE* pData, const BYTE* bMask, const char* szMask)
    {
    for(;*szMask;++szMask,++pData,++bMask)
    {
    if(*szMask == 'x' && *pData != *bMask)
    return 0;
    }
    return (*szMask)==NULL;
    }


    DWORD FindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask)
    {
    for(DWORD i=0; i < dwLen; i++)
    if( bCompare( (BYTE*)( dwAddress+i ),bMask,szMask) )

    return (DWORD)(dwAddress+i);
    return 0;
    }
    DWORD WINAPI Game_thread (LPVOID)
    {
    DWORD old_protect = 0;
    for(;;/*Sleep(75)*/)
    {

    DWORD Recoil = FindPattern (0xFFFFFF , NULL , (PBYTE)"\x72\x65\x63\x6F\x69\x6C\x20\x61" ,"xxxxxxxx");
    VirtualProtect ((PBYTE)Recoil, 8 , PAGE_EXECUTE_READWRITE , &old_protect);
    memcpy ((void*)Recoil ,PBYTE("\x71\x65\x63\x6F\x69\x6C\x20\x61"), 8 );
    VirtualProtect ((PBYTE) Recoil, 8 , old_protect , &old_protect);
    }
    }

    Смысл в том чтобы заменить массив байт \x72\x65\x63\x6F\x69\x6C\x20\x61 на \x71\x65\x63\x6F\x69\x6C\x20\x61.

    Все нормально компилируется , но при инжекте краш игры.

  9. Ну, смотри, для начала, тебе нужно составить алгоритм. В данном случае, приблизительный алгоритм примерно такой:

    1. Обойти сканером всю память процесса, Каждое совпадение записать в вектор (динамический массив).

    2. Обойти массив полученных адресов, добавляя к каждому нужное смещение (+20 в твоем случае)

    3. В каждую полученную ячейку записать нужное значение.

    4. Повторять третий пункт по таймеру (если нужна непрерывная запись).

    Собственно, под эти пункты тебе и нужно модифицировать свой код.

    всю память мне нужно сканировать - а лиш часть памяти от 06000000 до 07000000

    там находятся нужные мне адреса


  10. VirtualProtect ((PBYTE)"\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01" , 4 , PAGE_EXECUTE_READWRITE , &old_protect);
    memcpy ((PBYTE) "\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01" ,PBYTE("\0x6C \0x5F \0x60 \0x74 \0x74 \0x00 \0x00 \0x01"), 4 );//72 65 63 6F 69 6C 5F 61 74 74 00 00 01 31 F8 16
    VirtualProtect ((PBYTE)"\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01", 4 , old_protect , &old_protect);

    Давай разберем твои ошибки.

    1. VirtualProtect в качестве параметров принимает (по порядку слева направо) - адрес, для которого задается новая "защита"; количество байтов памяти, на которые будет распостраняться защита; идентификатор новой защиты (константа); адрес переменной, в которую попадет текущая защита (нужно для последующего восстановления исходной защиты).

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

    2. memcpy также принимает в качестве приемника и источника адреса ячеек памяти, которые нужно скопировать. У тебя опять же передается массив. Снова та же ошибка. В этой же функции ты снова бездумно задаешь для копирования 4 байта, тогда как копировать нужно ВЕСЬ массив.

    Вывод: ты абсолютно не разбираешься в программировании в целом, и в использовании WinAPI в частности. Если тебе все это просто объяснить - ты ничего не поймешь, ибо понимание начинается с азов и далее к усложнению подаваемого материала. У тебя же нет знания азов, а ты сразу замахиваешься на сложный материал. Потому тебе и рекомендовали сначала почитать теорию как следует, и потом уже переходить к программированию. И в программировании тебе следует тоже идти от простого к сложному. Скачивай из сети самоучители по С++ и штудируй, штудируй, штудируй. Когда ты выучишь основы, можешь переходить к изучению использования WinAPI (таких самоучителей тоже хватает в сети). Когда ты выучишь и это, рекомендую тебе снова зайти в эту тему и посмотреть на свои модификации кода. Уверен, тебе самому станет дико смешно. А если же ты не хочешь учиться, а просто хочешь, чтобы за тебя написали готовый код - знай, этого не будет. Мы не пишем код за юзеров, мы помогаем им обучиться, и поясняем какие-то непонятные моменты, но учить с азов тебя также никто не станет. Каждый на нашем форуме постигал азы самостоятельно.

    ЗЫ. Извиняюсь за некоторую резкость высказываний, у меня семейные проблемы.

    не надо извинятся - ты все правильно говоришь , код в попыхах кривой кинул - это моя ошибка , как работает код я понимаю(спс Кодеру за уроки огромное!) , запись в память тоже работает , у меня не работает одно - я не могу сделать сканер который бы искал все адреса принадлежащие массиву байт "72 65 63 6F 69 6C 5F 61 74 74 00 00 01 31 F8 16" , а затем к найденным адресам прибавлял смещение + 20 , а затем значение найденных адресов с уже прибавленным смещением +20 приравнивал к адресу 0х123FFB8 вот такую сложную штуку я не могу решить.

    Если кто-то на что-то обиделся так и скажите...хотя я не кого не оскорбил и не унизил вроде бы......

  11. Вы ведёте себя крайне вызывающе, я нахожу ваши слова оскорбительными.

    Мало того, что за вас весь код написали, так вы ещё и что-то предъявляете, не сильно ли это нагло?

    Знания как раз таки идут не из воздуха, а от чтения и ещё раз чтения, а потом практики.

    На данный момент вы не понимаете что такое dll, winapi, да и возможности языка C++.

    Вам нужно учить самые азы.

    P.S. терпение и труд всё перетрут.

    ну во первых за код спасибо , но он не работает

    во - вторых я некого не оскорбил!либо ты не знаешь что такое слово "оскорблять" , либо тебе нужно вести себя как мужчина.

    в - третьих длл я понимаю что такое (как раз таки азы)и код типа:

    DWORD WINAPI thread (LPVOID);
    DWORD APIENTRY D3Dmain (HMODULE hModule ,DWORD ul_reason_for_call , LPVOID lpReservid )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    CreateThread (NULL,NULL,thread,NULL,NULL,NULL);

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return true;
    }

    int* ReadPointer (DWORD base , int offsets[] , int level)
    {
    int* pointer = (int*) base;
    for (int i=0; i<level; i++)
    {
    pointer = (int*)(*pointer + offsets[i]);

    }
    return pointer;
    }


    DWORD WINAPI thread (LPVOID)
    {
    DWORD old_protect = 0;

    for(;;Sleep(75))
    {
    if(GetAsyncKeyState(VK_DOWN)&1)
    {
    //if(GetAsyncKeyState(VK_DOWN) &1)
    //{
    //int offsets[5] = {0x3B4,0xF4,0xC,0x4,0x3C};
    //DWORD base = 0x0200118C;
    //int* pointer;
    //pointer = ReadPointer(base , offsets , 5);
    VirtualProtect ((PBYTE)"\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01" , 4 , PAGE_EXECUTE_READWRITE , &old_protect);
    memcpy ((PBYTE) "\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01" ,PBYTE("\0x6C \0x5F \0x60 \0x74 \0x74 \0x00 \0x00 \0x01"), 4 );//72 65 63 6F 69 6C 5F 61 74 74 00 00 01 31 F8 16
    VirtualProtect ((PBYTE)"\0x6C \0x5F \0x61 \0x74 \0x74 \0x00 \0x00 \0x01", 4 , old_protect , &old_protect);

    }

    }

    не работает(уроки я смотрел)

    p.s. вместо того чтобы намекнуть хотя бы ,я не говорю уже про "объяснить" .......

  12. Ты заменил названия функций. А винапи функции так и не убрал. Для сведения: WinAPI функции - это функции, которые предоставляет винда, а не те, которые программист пишет самостоятельно. Переименование самостоятельно написанных функций не избавит от винапи. В приведенном тобой коде винапи функцией является ReadProcessMemory, которая, если почитать мсдн, читает память стороннего процесса. Если же ты делаешь длл-ку, то тебе сразу доступна память целевого процесса, поскольку именно туда ты длл-ку и внедряешь (инжектишь). Следовательно, от ReadProcessMemory можно отказаться, и сразу подставлять нужные адреса. Естественно, функции для этого придется несколько видоизменить. Судя по твоим действиям, уж извини, твой уровень знаний не соответствует тому, что ты хочешь сделать. Следовательно - повышай уровень знаний, чтобы понимать код, а не просто рандомно его менять в надежде на то, что он вдруг заработает.

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

  13. а что мешает заменить функции винапи стандартными функциями Си?

    что-то типа этого??? я запутался....

    bool VerifyAddress(HANDLE hProcess, DWORD dwAddress, PBYTE bMask, char *szMask)
    {
    PBYTE *pTemp = { 0 };

    for ( int i = 0; *szMask; ++szMask, ++bMask, ++i )
    {
    if ( !ReadProcessMemory( hProcess, reinterpret_cast<LPCVOID>(dwAddress + i), &pTemp, 2048, 0 ) )
    return false;

    if ( *szMask == 'x' && reinterpret_cast<char*>(pTemp) != reinterpret_cast<char*>(*bMask))
    return false;
    }


    return true;
    }

    DWORD ForzaExternalFindPattern( HANDLE hProcess, PBYTE bMask, char *szMask )
    {
    for ( DWORD dwCurrentAddress = 0x401000; dwCurrentAddress < 0x7FFFFFF; dwCurrentAddress++ )
    if ( VerifyAddress( hProcess, dwCurrentAddress, bMask, szMask ) )
    return dwCurrentAddress;

    return -1;
    }




    DWORD address = 0;
    address = ForzaExternalFindPattern(yourprocesshandle, (BYTE*)"байты", "маска")

    кстати этот код тоже не работает....почему-то,другого я не придумал...

  14. Очевидно же:

    1) Зачем используешь функции, которые предназначены для удалённого получения данных о процессе? (это касается всего MemoryEditor класса)

    * Раз уж ты пишешь DLL то будь проще, используй memcpy, memset и т.д. WinAPI тебе тут не нужен практически

    2) Зависает потому что это нужно делать в отельном потоке

    а как правильно сделать и чтобы работало быстро. Смысл в том, чтобы создать цикл который будет сканировать участок памяти игры (от 0х06000000 до 0х07000000 ) и выдавать все адреса которые будут найдены по этому массиву байт ("\0x03\0x00\0x00\0x11\0xFF\0xFF\0xFF\0xFF").

  15. 1) Я же предупреждал что код написал в блокноте (он не проверялся!)

    2) Неужели не понятно, что функции типа void не возвращают никакое значение (самые самые азы C++)

    Так это же функция void, она не возвращает никакое значение, убери вообще return module;

    Я хочу сделать цикл - то есть , чтобы постоянно сканировалась память и постоянно находились адреса - не будет ли это работать очень медленно? если да , то как можно ускорить?

    получился вот такой код:

    Хендл на процесс

    DWORD GetProcessByName (char*pName)
    {
    DWORD pID = 0;
    HANDLE snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 pInfo;
    pInfo.dwSize = sizeof (PROCESSENTRY32);

    if (Process32First(snapshot,&pInfo))
    {
    while (Process32Next(snapshot,&pInfo))

    if (_stricmp(pName,pInfo.szExeFile)==0)
    {
    pID = pInfo.th32ProcessID;
    CloseHandle(snapshot);
    break;

    }
    }

    CloseHandle(snapshot);
    return pID;
    }

    DWORD pID = GetProcessByName("Game.exe");

    void GetModuleInfo(MODULEENTRY32& module, char* module_name, bool main_process) //(из класса MemoryEditor), если хочешь юзать вне класса,
    //не забудь pID дополнительно передавать
    {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
    module.dwSize = sizeof(MODULEENTRY32);
    if (Module32First(snapshot, &module))
    {
    if (main_process)
    {
    CloseHandle(snapshot);

    }
    while (Module32Next(snapshot, &module))
    {
    if (_stricmp(module.szModule, module_name) == 0)
    {
    CloseHandle(snapshot);

    }
    }
    }

    }

    #define MAX_ADDRLISTSIZE 255
    void FindPattern (DWORD* addrList, // массив адресов
    BYTE& matches, // кол-во совпадений
    DWORD start_address, // начало сканирования
    DWORD length, // сколько памяти просканируем
    BYTE* pattern, // вставка
    char *mask) // маска
    {
    matches = 0; // счётчик совпадений
    for (DWORD i = 0; i < length; i++)
    {
    if (DataCompare (ReadMemory<BYTE*>(start_address + i), pattern , mask)) // если мы нашли совпадение
    {
    addrList[matches] = (DWORD)(start_address + i); /* Записываем в наш список адресов найденный адрес
    (стартовый адрес + i (кол-во уже просканированных байт))*/
    matches++; // увеличиваем счётчик совпадений
    }
    }
    }

    void findPatterns()
    {
    DWORD addressList[MAX_ADDRLISTSIZE] = {0}; // список адресов
    BYTE matches = 0; // кол-во совпадений
    MODULEENTRY32 peInfo = {0};
    GetModuleInfo(peInfo, "Game.exe", true); // берём инфу о самом процессе
    FindPattern(addressList, // передаём наш массив функции (в него она запишет адреса)
    matches, // передаём ей наш счётчик, куда функция запишет кол-во совпадений
    (DWORD)0x06000000, // откуда сканируем? базовый адрес приложения
    (DWORD)0x07000000, // сколько сканируем? размер приложения
    (PBYTE)"\0x03\0x00\0x00\0x11\0xFF\0xFF\0xFF\0xFF", // наша вставка
    "xxxxxxxx");
    // наша маска
    for (BYTE i = 0; i < matches; i++);
    //printf("Result #%d = 0x%X\n", addressList[i]);
    //PrintText2(50, 50, WHITE, dMenu.pFont, "Result #%d = 0x%X\n" , addressList);
    }

    Краш при инжекте или просто игра зависает . Все дело в функции "FindPattern" наверно она не правильно передаёт значение аргументов??? Помогите разобраться в чем ошибка

  16. спасибо большое , у тебя очень понятно и граматно все в видео уроках, поэтому учился по твоим исходам и использую в основном их

    Но не могу понять:

    (понравился 2 вариант,он чуть по проще)"GetModuleInfo" это типа хендела на процесс , только доступ на модуль? ,не пойму аргумент "module", студия его подчеркивает,как его инициализировать??? , так же не совсем понятно с

    FindPattern(addressList, // передаём наш массив функции (в него она запишет адреса)- это понятно
    matches, // передаём ей наш счётчик, куда функция запишет кол-во совпадений - это тоже
    (DWORD)info.modBaseAddr, // откуда сканируем? базовый адрес приложения - прописывать нужно 0x401000?
    (DWORD)info.modBaseSize, // сколько сканируем? размер приложения - солько сканировать я не пойму тут нужно наверно от 0x401000 до 0x7FFFFFF???? я не знаю как найти размер приложения
    (PBYTE)"\0x90\0x90\0x90\0x90", // наша вставка -тут ясно
    "xxxx"); // наша маска -тут тоже

  17. А что сложного?

    Как вариант можно так (код накидал в блокноте):


    #define MAX_ADDRLISTSIZE 255
    void GetModuleInfo(MODULEENTRY32& module, char* module_name, bool main_process) //(из класса MemoryEditor), если хочешь юзать вне класса,
    //не забудь pID дополнительно передавать
    {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
    module.dwSize = sizeof(MODULEENTRY32);
    if (Module32First(snapshot, &module))
    {
    if (main_process)
    {
    CloseHandle(snapshot);
    return module;
    }
    while (Module32Next(snapshot, &module))
    {
    if (_stricmp(module.szModule, module_name) == 0)
    {
    CloseHandle(snapshot);
    return module;
    }
    }
    }
    return module;
    }
    void findPatterns()
    {
    MODULEENTRY32 peInfo = {0};
    GetModuleInfo(peInfo, "", true); // берём инфу о самом процессе
    int startAddress = (DWORD)info.modBaseAddr; // к примеру берём точку входа
    int finalAddress = startAddress + (DWORD)info.modBaseSize; // конец модуля
    int scanLen = (DWORD)info.modBaseSize; // размер модуля
    DWORD addressList[MAX_ADDRLISTSIZE] = {0}; // список адресов
    BYTE matches = 0; // количество совпадений
    int currentAddress = 0; // текущий адрес
    while (currentAddress < finalAddress)
    {
    currentAddress = FindPattern(startAddress + currentAddress, // откуда ищем? точка входа + последний найденный адрес
    scanLen - currentAddress, // сколько памяти просканируем? Длина модуля - посл. найденный адрес
    (PBYTE)"\0x90\0x90\0x90\0x90", // наша вставка
    "xxxx"); // наша маска

    if (currentAddress > 0)
    {
    addressList[matches] = currentAddress; // записываем в массив адресов наш адрес
    matches++; // увеличиваем счётчик совпадений
    }
    else break;
    }
    for (BYTE i = 0; i < matches; i++)
    {
    printf("Result #%d = 0x%X\n", addressList[i]);
    }
    }

    Вот второй вариант (тоже накидал в блокноте, возможно в вызове FindPattern перед matches, нужно будет поставить оператор взятия адреса):


    #define MAX_ADDRLISTSIZE 255
    void FindPattern (DWORD* addrList, // массив адресов
    BYTE& matches, // кол-во совпадений
    DWORD start_address, // начало сканирования
    DWORD length, // сколько памяти просканируем
    BYTE* pattern, // вставка
    char *mask) // маска
    {
    matches = 0; // счётчик совпадений
    for (DWORD i = 0; i < length; i++)
    {
    if (DataCompare (ReadMemory<BYTE*>(start_address + i), pattern , mask)) // если мы нашли совпадение
    {
    addrList[matches] = (DWORD)(start_address + i); /* Записываем в наш список адресов найденный адрес
    (стартовый адрес + i (кол-во уже просканированных байт))*/
    matches++; // увеличиваем счётчик совпадений
    }
    }
    }
    void findPatterns()
    {
    DWORD addressList[MAX_ADDRLISTSIZE] = {0}; // список адресов
    BYTE matches = 0; // кол-во совпадений
    MODULEENTRY32 peInfo = {0};
    GetModuleInfo(peInfo, "", true); // берём инфу о самом процессе
    FindPattern(addressList, // передаём наш массив функции (в него она запишет адреса)
    matches, // передаём ей наш счётчик, куда функция запишет кол-во совпадений
    (DWORD)info.modBaseAddr, // откуда сканируем? базовый адрес приложения
    (DWORD)info.modBaseSize, // сколько сканируем? размер приложения
    (PBYTE)"\0x90\0x90\0x90\0x90", // наша вставка
    "xxxx"); // наша маска
    for (BYTE i = 0; i < matches; i++)
    printf("Result #%d = 0x%X\n", addressList[i]);
    }

    спасибо большое , у тебя очень понятно и граматно все в видео уроках, поэтому учился по твоим исходам и использую в основном их

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.