Адрес DLL из стороннего процесса с++

Статус
В этой теме нельзя размещать новые ответы.

Gafask

Участник
Автор темы
137
13
Пробыв год в одном месте и потеряв все исходники и знания я задам теперь вопрос который меня щас мучает ооочень сильно !
Пример: У нас есть адрес в формате samp.dll+0x12D8F8 который был найден в Cheat Engine и адрес 0xS3FSFD + 0х9201 который нам кто-то дал ( ну или нашли где-то ) .
😘🤓😘😇Практика : 😘🤓😘😇


ReadProcessMemory(process, (LPCVOID)(0xS3FSFD), &TestS, sizeof(TestS), NULL)[/COLOR][/SIZE][/B][/CENTER][/CENTER][/HEADING] [HEADING=2][CENTER][CENTER][B][SIZE=5][COLOR=rgb(0, 0, 0)]ReadProcessMemory(process, (LPCVOID)(TestS+0х9201 ), &TestD, sizeof(TestD), NULL);

Значит адрес 0xS3FSFD + 0х9201 мы вроде как можем прочитать и вроде все верно или нет то посоветуйте как правильнее 🙂, так дальше .🙂
Адрес формата : samp.dll+0x12D8F8 я не могу прочитать так как я не знаю как правильно прочитать samp.dll что-бы к нему 🙂добавить смещение 0x12D8F8 . 🙂
Вопрос : Как прочитать адрес samp.dll+0x12D8F8 а точнее samp.dll что бы к примеру его прочитать и вывести в консоль или 🙂наоборот изменить его . 🙂
Я пишу на языке с++ , использую консольно приложение , редактирую адреса памяти не через DLL ! а используя консольое 😘🤓😘😇приложение .exe тоесть из левой программы пытаюсь взаимодействовать с гта са . 😘🤓😘😇
Надеюсь я правильно все вам написал и вы правильно мой вопрос поняли , даже если не знаете на него ответ ) . 😘

😘🤓😘😇Спасибо за внимание жду ваших ответов с примерами желательно . 😇 😇 😇
🥰🥰Всем удачи ! Денег , дачи .🥰🥰
 
Последнее редактирование модератором:
Решение
Привет-привет.
Давай все по порядку.

1) Что такое адрес? Адрес – это цифра, правда в шестнадцатеричной системе, но все же это обычная цифра. И по каждому адресу находится какое-то значение от 0 до 255 (1 байт). Все типы данных (int; float; char...) складываются из некого массива байт. Ближе к делу.
Поэтому если у тебя адрес такой:
0x3FBFD + 0x9201
То тебе нужно просто сложить его (0x3FBFD + 0x9201 = 0x48DFE) и прочитать уже значение по адресу, который является найденной суммой. Кстати, не стоит забывать, что нужно установить корректный уровень защиты на память, которую читаешь или в которую записываешь.
C++:
DWORD bytes; // вместо DWORD любой тип данных, который ты хочешь прочитать
DWORD oldProtect = 0;
VirtualProtectEx(process...

Vintik

Мечтатель
Проверенный
1,456
908
Привет-привет.
Давай все по порядку.

1) Что такое адрес? Адрес – это цифра, правда в шестнадцатеричной системе, но все же это обычная цифра. И по каждому адресу находится какое-то значение от 0 до 255 (1 байт). Все типы данных (int; float; char...) складываются из некого массива байт. Ближе к делу.
Поэтому если у тебя адрес такой:
0x3FBFD + 0x9201
То тебе нужно просто сложить его (0x3FBFD + 0x9201 = 0x48DFE) и прочитать уже значение по адресу, который является найденной суммой. Кстати, не стоит забывать, что нужно установить корректный уровень защиты на память, которую читаешь или в которую записываешь.
C++:
DWORD bytes; // вместо DWORD любой тип данных, который ты хочешь прочитать
DWORD oldProtect = 0;
VirtualProtectEx(process, (void*)0x48DFE, sizeof(bytes), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)0x48DFE, &bytes, sizeof(bytes), NULL);
VirtualProtectEx(process, (void*)0x48DFE, sizeof(bytes), oldProtect, NULL);

2) Если у тебя адрес формата:
samp.dll + 0x12D8F8
То как это вообще понимать? Я ведь говорил, что адрес – число, да? Каждая DLL библиотека, которая присоединяется к процессу, записывает свои данные в память. Но ведь часть памяти уже занята, поэтому она начинает записывать с некоторого свободного адреса (он почти всегда разный). Нам сперва придётся его найти и просто, как уже я написал в пункте 1, сложить "базовый адрес модуля" и наше число. Например, так (простой пример кода):
C++:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

DWORD getModuleBaseAddress(DWORD pID, TCHAR *szModuleName) // функция, которая получает этот адрес "samp.dll". её трогать не надо
{
    DWORD dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (strcmp(ModuleEntry32.szModule, szModuleName) == 0)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

int main()
{
    HWND hWnd = FindWindow(NULL, L"GTA SA:MP");
    DWORD pId;
    GetWindowThreadProcessId(hWnd, &pId);
    HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, pId);
    DWORD moduleBase = getModuleBaseAddress(pId, L"samp.dll"); // вот тут в кавычках имя твоего модуля. и всё, в переменной уже хранится его базовый адрес

    int my_number; // опять же, любой тип данных тут может быть. не забывай, что в 4 строках ниже нужно поменять название переменной, если ты захочешь её переименовать тут
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)(moduleBase + 0x12D8F8), sizeof(my_number), PAGE_EXECUTE_READWRITE, &oldProtect);
    ReadProcessMemory(process, (void*)(moduleBase + 0x12D8F8), &my_number, sizeof(my_number), NULL);
    VirtualProtectEx(process, (void*)(moduleBase + 0x12D8F8), sizeof(my_number), oldProtect, NULL);

    std::cout << my_number << std::endl; // для примера: выведем число в консоль.
}

3) А вот что ты писал про сумму – это не совсем сумма. Это указатель. То есть по одному адресу памяти хранится значение другого адреса памяти, уже который хранит именно нужные тебе данные (обычно это число).
0x3FBFD –> 0x9201–> нужное тебе число (или не число, любой тип данных)
Тогда надо поступить вот так:
C++:
DWORD bytes;
DWORD oldProtect = 0;
// читаем данные по адресу 0x3FBFD и записывает в bytes
VirtualProtectEx(process, (void*)0x3FBFD, sizeof(bytes), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)0x3FBFD, &bytes, sizeof(bytes), NULL);
VirtualProtectEx(process, (void*)0x3FBFD, sizeof(bytes), oldProtect, NULL);
// прибавляет к нему наш "оффсет" (смещение)
bytes += 0x9201;
// это и есть наш новый адрес, который хранит нужные данные. читаем его:
float my_number; // например, найдём число с плавающей точкой (нецелое) по этому адресу
VirtualProtectEx(process, (void*)bytes, sizeof(my_number), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)bytes, &my_number, sizeof(my_number), NULL);
VirtualProtectEx(process, (void*)bytes, sizeof(my_number), oldProtect, NULL);
// нашли. теперь делай с ним, что хочешь. для примера: выведу в консоль
std::cout << my_number << std::endl;

Надеюсь, что я ответил на все поставленные тобой вопросы. Удачи.
 
Последнее редактирование:

Gafask

Участник
Автор темы
137
13
Привет-привет.
Давай все по порядку.

1) Что такое адрес? Адрес – это цифра, правда в шестнадцатеричной системе, но все же это обычная цифра. И по каждому адресу находится какое-то значение от 0 до 255 (1 байт). Все типы данных (int; float; char...) складываются из некого массива байт. Ближе к делу.
Поэтому если у тебя адрес такой:
0x3FBFD + 0x9201
То тебе нужно просто сложить его (0x3FBFD + 0x9201 = 0x48DFE) и прочитать уже значение по адресу, который является найденной суммой. Кстати, не стоит забывать, что нужно установить корректный уровень защиты на память, которую читаешь или в которую записываешь.
C++:
DWORD bytes; // вместо DWORD любой тип данных, который ты хочешь прочитать
DWORD oldProtect = 0;
VirtualProtectEx(process, (void*)0x48DFE, sizeof(bytes), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)0x48DFE, &bytes, sizeof(bytes), NULL);
VirtualProtectEx(process, (void*)0x48DFE, sizeof(bytes), oldProtect, NULL);

2) Если у тебя адрес формата:
samp.dll + 0x12D8F8
То как это вообще понимать? Я ведь говорил, что адрес – число, да? Каждая DLL библиотека, которая присоединяется к процессу, записывает свои данные в память. Но ведь часть памяти уже занята, поэтому она начинает записывать с некоторого свободного адреса (он почти всегда разный). Нам сперва придётся его найти и просто, как уже я написал в пункте 1, сложить "базовый адрес модуля" и наше число. Например, так (простой пример кода):
C++:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

DWORD getModuleBaseAddress(DWORD dwProcessID, TCHAR *lpszModuleName) // функция, которая получает этот адрес "samp.dll". её трогать не надо
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
    DWORD dwModuleBaseAddress = 0;
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32 = { 0 };
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
                {
                    dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

int main()
{
    HWND hWnd = FindWindow(NULL, L"GTA SA:MP");
    DWORD pId;
    GetWindowThreadProcessId(hWnd, &pId);
    HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, pId);
    DWORD moduleBase = getModuleBaseAddress(pId, L"samp.dll"); // вот тут в кавычках имя твоего модуля. и всё, в переменной уже хранится его базовый адрес

    int my_number; // опять же, любой тип данных тут может быть. не забывай, что в 4 строках ниже нужно поменять название переменной, если ты захочешь её переименовать тут
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)(moduleBase + 0x12D8F8), sizeof(my_number), PAGE_EXECUTE_READWRITE, &oldProtect);
    ReadProcessMemory(process, (void*)(moduleBase + 0x12D8F8), &my_number, sizeof(my_number), NULL);
    VirtualProtectEx(process, (void*)(moduleBase + 0x12D8F8), sizeof(my_number), oldProtect, NULL);

    std::cout << my_number << std::endl; // для примера: выведем число в консоль.
}

3) А вот что ты писал про сумму – это не совсем сумма. Это указатель. То есть по одному адресу памяти хранится значение другого адреса памяти, уже который хранит именно нужные тебе данные (обычно это число).
0x3FBFD –> 0x9201–> нужное тебе число (или не число, любой тип данных)
Тогда надо поступить вот так:
C++:
DWORD bytes;
DWORD oldProtect = 0;
// читаем данные по адресу 0x3FBFD и записывает в bytes
VirtualProtectEx(process, (void*)0x3FBFD, sizeof(bytes), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)0x3FBFD, &bytes, sizeof(bytes), NULL);
VirtualProtectEx(process, (void*)0x3FBFD, sizeof(bytes), oldProtect, NULL);
// прибавляет к нему наш "оффсет" (смещение)
bytes += 0x9201;
// это и есть наш новый адрес, который хранит нужные данные. читаем его:
float my_number; // например, найдём число с плавающей точкой (нецелое) по этому адресу
VirtualProtectEx(process, (void*)bytes, sizeof(my_number), PAGE_EXECUTE_READWRITE, &oldProtect);
ReadProcessMemory(process, (void*)bytes, &my_number, sizeof(my_number), NULL);
VirtualProtectEx(process, (void*)bytes, sizeof(my_number), oldProtect, NULL);
// нашли. теперь делай с ним, что хочешь. для примера: выведу в консоль
std::cout << my_number << std::endl;

Надеюсь, что я ответил на все поставленные тобой вопросы. Удачи.
Да вы ответили на мои вопросы , я вам очень благодарен за это и удивлён что на этот вопрос отреагировал сам ДаркПиксель охохо🤩 , ладно не буду терять голову 🧐 ) .
Есть еще 4 вопроса , думаю вы не затруднитесь ответить на него , я буду вам благодарен😇 .
Вопросы :🤔🤔🤔🤔🤔🤔
1. Для чего менять уровень защиты через VirtualProtectEx ?🤔
2. Где необходимо/рекомендуется применять VirtualProtectEx при работе с памятью ?🤔
3. Если не использовать VirtualProtectEx то какие последствия могу быть ?🤔
4. Использование L для чего ? Пример : DWORD moduleBase = getModuleBaseAddress(pId,
L"samp.dll"); что дает эта L ? Вить что с ней что без нее все работает , всегда убирал и не ставил ее так как с ней не работает у меня , или я чего то не понимаю ? ( это вопрос ради интереса , так как появилась возможность получить ответы на вопросы ) . 😘
 
Последнее редактирование:
  • Влюблен
Реакции: Vintik

Vintik

Мечтатель
Проверенный
1,456
908
Да вы ответили на мои вопросы , я вам очень благодарен за это и удивлён что на этот вопрос отреагировал сам ДаркПиксель охохо🤩 , ладно не буду терять голову 🧐 ) .
Есть еще 4 вопроса , думаю вы не затруднитесь ответить на него , я буду вам благодарен😇 .
Вопросы :🤔🤔🤔🤔🤔🤔
1. Для чего менять уровень защиты через VirtualProtectEx ?🤔
2. Где необходимо/рекомендуется применять VirtualProtectEx при работе с памятью ?🤔
3. Если не использовать VirtualProtectEx то какие последствия могу быть ?🤔
4. Ошибка E0020 идентификатор "_tcscmp" не определен , я исправлял с помощью подключения библиотеки <tchar.h> она исправила эту ошибку , то есть компилятор перестал кричать на нее но при попытке запустить код для тестов в режиме отладчика я понял что getModuleBaseAddress не работает тесть она не находит не samp.dll , nvd3dum.dll и тд. и почему то мне кажется что в этом вся проблема , что мне нужно поменять в проекте что-бы исправить эту ошибку так как я подозреваю что это в этом проблема или в том что библиотека "stdafx.h" не видна у меня а точнее не определяется . В чем же проблема и как ее решить ?
Отвечаю на вопросы 1, 2 и 3.
VirtualProtectEx нужен для того, чтобы установить нужному кусочку памяти необходимый уровень защиты для того, чтобы читать и записывать данные. Условно: сказать программе, что есть разрешение на запись/чтение этого участка памяти.
Использовать стоит везде, где ты её читаешь или записываешь.
Последствия, с которыми сталкивался я, – краш от античита с причиной "Нарушение прав доступа к памяти". Пример:
1616438552482.png

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

Теперь по поводу вопроса 4.
Измени ту функцию на вот эту. Вероятно, у тебя возникнет ошибка, просто надо поставить многобайтовую кодировку. В VS это делается вот так.
C++:
DWORD getModuleBaseAddress(DWORD pID, TCHAR *szModuleName) // функция, которая получает этот адрес "samp.dll". её трогать не надо
{
    DWORD dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (strcmp(ModuleEntry32.szModule, szModuleName) == 0)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

 
Последнее редактирование:
  • Ха-ха
  • Вау
Реакции: F0RQU1N and и Gafask

Gafask

Участник
Автор темы
137
13
Отвечаю на вопросы 1, 2 и 3.
VirtualProtectEx нужен для того, чтобы установить нужному кусочку памяти необходимый уровень защиты для того, чтобы читать и записывать данные. Условно: сказать программе, что есть разрешение на запись/чтение этого участка памяти.
Использовать стоит везде, где ты её читаешь или записываешь.
Последствия, с которыми сталкивался я, – краш от античита с причиной "Нарушение прав доступа к памяти". Пример:
Посмотреть вложение 90314
Это из краш-лога одного пользователя, который воспользовался моим скриптом без VirtualProtectEx.

Теперь по поводу вопроса 4.
Измени ту функцию на вот эту. Вероятно, у тебя возникнет ошибка, просто надо поставить многобайтовую кодировку. В VS это делается вот так.
C++:
DWORD getModuleBaseAddress(DWORD pID, TCHAR *szModuleName) // функция, которая получает этот адрес "samp.dll". её трогать не надо
{
    DWORD dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (strcmp(ModuleEntry32.szModule, szModuleName) == 0)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

Спасибо за ответ , я вам очень признателен , теперь буду юзать VirtualProtectEx ну или просто переделаю ReadProcessMemory c встроенным VirtualProtectEx в нее🥸🤠 это должно уменьшить код ) .
Про стиль общения это маска дабы общение было приятным ( 🥷 я не такой 🥷 ) . 🤩 🥰 😀
 

Vintik

Мечтатель
Проверенный
1,456
908
Спасибо за ответ , я вам очень признателен , теперь буду юзать VirtualProtectEx ну или просто переделаю ReadProcessMemory c встроенным VirtualProtectEx в нее🥸🤠 это должно уменьшить код ) .
Про стиль общения это маска дабы общение было приятным ( 🥷я не такой🥷 ) . 🤩 🥰 😀
Вот такое есть готовое решение с использованием шаблонов (template). Просто в начало кода закинуть эти функции.
C++:
template <typename T>
T readMem(DWORD address)
{
    T buffer;
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)address, sizeof(buffer), PAGE_EXECUTE_READWRITE, &oldProtect);
    ReadProcessMemory(process, (void*)address, &buffer, sizeof(buffer), 0);
    VirtualProtectEx(process, (void*)address, sizeof(buffer), oldProtect, NULL);
    return buffer;
}

template <typename T>
void writeMem(DWORD address, T value)
{
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtect);
    WriteProcessMemory(process, (void*)address, &value, sizeof(value), 0);
    VirtualProtectEx(process, (void*)address, sizeof(value), oldProtect, NULL);
}
Использовать его вот так:
C++:
auto money = readMem<int>(0xB6F5F0); // int – тип данных. обязательно надо указывать
(этот код запишет в money твоё состояние, в смысле сколько денег)
Или вот так:
C++:
auto CPed = readMem<DWORD>(0xB6F5F0); // DWORD указывать, чтобы знать какой тип данных надо считать.
float health = 55.0;
writeMem<float>(CPed + 0x540, health); // float так же обязательно надо указывать.
(а этот изменит твоё здоровье до 55 единиц)

Просто и со вкусом
 
Последнее редактирование:

Gafask

Участник
Автор темы
137
13
Вот такое есть готовое решение с использованием шаблонов (template). Просто в начало кода закинуть эти функции.
C++:
template <typename T>
T readMem(DWORD address)
{
    T buffer;
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)address, sizeof(buffer), PAGE_EXECUTE_READWRITE, &oldProtect);
    ReadProcessMemory(process, (void*)address, &buffer, sizeof(buffer), 0);
    VirtualProtectEx(process, (void*)address, sizeof(buffer), oldProtect, NULL);
    return buffer;
}

template <typename T>
void writeMem(DWORD address, T value)
{
    DWORD oldProtect = 0;
    VirtualProtectEx(process, (void*)address, sizeof(value), PAGE_EXECUTE_READWRITE, &oldProtect);
    WriteProcessMemory(process, (void*)address, &value, sizeof(value), 0);
    VirtualProtectEx(process, (void*)address, sizeof(value), oldProtect, NULL);
}
Использовать его вот так:
C++:
auto money = readMem<int>(0xB6F5F0); // int – тип данных. обязательно надо указывать
(этот код запишет в money твоё состояние, в смысле сколько денег)
Или вот так:
C++:
auto CPed = readMem<DWORD>(0xB6F5F0); // DWORD указывать, чтобы знать какой тип данных надо считать.
float health = 55.0;
writeMem<float>(CPed + 0x540, health); // float так же обязательно надо указывать.
(а этот изменит твоё здоровье до 55 единиц)

Просто и со вкусом
1.Данный вариант лучше того ?
2. Или есть свои плюсы и минусы ?
Просто по визуальному эффекту данный код меньше и скорее всего он перспективнее или он проще обнаруживается анти читом в разных играх или разницы нету чисто ради красоты .
 

Vintik

Мечтатель
Проверенный
1,456
908
1.Данный вариант лучше того ?
2. Или есть свои плюсы и минусы ?
Просто по визуальному эффекту данный код меньше и скорее всего он перспективнее или он проще обнаруживается анти читом в разных играх или разницы нету чисто ради красоты .
Лучше чего? Это один и тот же код.
Просто в этом я объединил чтение/запись в память и установку защиты на адрес в одну функцию, отсюда и "визуальный эффект перспективности".

Я сделал то, что хотел ты
Спасибо за ответ , я вам очень признателен , теперь буду юзать VirtualProtectEx ну или просто переделаю ReadProcessMemory c встроенным VirtualProtectEx в нее🥸🤠 это должно уменьшить код ) .
 

Gafask

Участник
Автор темы
137
13
Лучше чего? Это один и тот же код.
Просто в этом я объединил чтение/запись в память и установку защиты на адрес в одну функцию, отсюда и "визуальный эффект перспективности".

Я сделал то, что хотел ты
А да ? Круто , я уже сонный и так как ты мне дал инфу которую я долго ждал , я сижу и пишу универсальную дичь , хотя она мне не нужна будет но чисто что-то меня двигает ее писать ) . Лучше бы в доту поиграл ей богу . 🙄
 

rumboorumboo

Новичок
3
0
В асишке не было дичи. Там было *(float*)0xb6f600 и т. д.
Доброго времени суток! Если не затруднит, поясните пожалуйста. Выдаёт несколько ошибок, по приведению типов переменных...
В плюсах ноль, понимаю что это просто из за типизации, но как с этим быть не понимаю..
аргумент типа "WCHAR *" несовместим с параметром типа "const char *"
аргумент типа "TCHAR *" несовместим с параметром типа "const char *" mBYTE
"int strcmp(const char *,const char *)": невозможно преобразовать аргумент 1 из "WCHAR [256]" в "const char *"

аргумент типа "const wchar_t *" несовместим с параметром типа "TCHAR *" 53
"DWORD getModuleBaseAddress(DWORD,TCHAR *)": невозможно преобразовать аргумент 2 из "const wchar_t [11]" в "TCHAR *"

=: преобразование "DWORD_PTR" в "DWORD", возможна потеря данных

#include <iostream>
#include <Windows.h>
#include <string>
#include <psapi.h>
#include <tchar.h>
#include <tlhelp32.h>
using namespace std
 
Статус
В этой теме нельзя размещать новые ответы.