Có gì mới?

Diễn Đàn Cú Đêm

  • Bạn có những câu chuyện thầm kín nhưng không biết kể với ai, bạn buồn phiền vì chuyện tình cảm, gia đình, cuộc sống. Hãy chia sẻ tâm sự của bạn với cộng đồng cú đêm nhé. NGHIÊM CẤM SPAM QUẢNG CÁO.

Share Code Read Write Memory với C++ | Series game hacking cho người mới bắt đầu

zedcoder

Cú Đêm Member
Tham gia
28/8/21
Bài viết
9
Lượt thích
3
Điểm
3
Hello what's up anh em :cu:

Như anh em đã biết hoặc chưa biết =)) C/C++ là một ngôn ngữ thao tác với memory rất tốt. Và do đó nó là một ngôn ngữ được nhiều anh em lựa chọn trong việc đọc ghi bộ nhớ một process cụ thể trong hệ thống, cụ thể ở đây anh em có thể dùng vào nhiều mục đích khác nhau. Nhưng ở bài viết này mình dùng vào mục đích Hacking :bacda:

Ở bài viết này mình sẽ hướng dẫn anh em cách để đọc ghi bộ nhớ với C/C++ một cách đơn giản và dễ hiểu nhất.

Oke, vào thẳng vấn đề luôn, chúng ta có một con game huyền thoại mà chắc không anh em nào chưa từng chơi qua: Plant and zombie.
1630163991891.png


Để cho dễ hiểu thì mình sẽ lấy một ví dụ đơn giản nhất. Cái thứ anh em cần nhiều nhất ở con game này đó là số lượng mặt trời.
Anh em sẽ phải trồng cây để thu nhặt mặt trời vì số lượng mặt trời rơi tự nhiên rất ít :v
Mình là một thằng rất ghét chơi kiểuđó nêntựdưng trongđầu mình lóe raý tưởng thayđổi số mặt trờilên 9999 mà không cần ngồi nhặt từng cái :2lol:

1630164215316.png


Trước hết chúng ta sẽ tìm địa chỉ của vùng nhớ chứa giá trị là số lượng mặt trời hiện tại bằng Cheat Engine
Mở process list và chọn thằng Plant and zombie:
1630164259615.png

Oke, Cheat Engine sẽ Open Process này và mở quyền scan vùng nhớ đối với vùng nhớ của process này.

Oke tiếp theo, xét theo số lượng mặt trời có thể có tối đa, đó là 9999 do đó mình dự đoán vùng nhớ được lưu giá trị này ở trong bộ nhớ có độ lớn là 4 bytes, do đó mình sẽ tìm những giá trị 4 bytes trong bộ nhớ có đúng giá trị mà nó đang giữ là 75

1630164398961.png


Oke, nhặt tiếp một mặt trời nữa để giá trị thay đổi, ta sẽ lặp lại bước này tới khi tìm được giá trị đúng:


Giá trị hiện lại là 100


Oke, tìm giá trị 100 và nhấn Next scan:

1630164501175.png

Như vậy là chúng ta đã có giá trị chính xác lưu giá trị số lượng mặt trời có trong bộ nhớ :v

Ta sẽ chỉ chú ý tới địa chỉ của nó trong bộ nhớ nhé: 0x188F7FA8

1630164597927.png


Như anh em có thể đã biết hoặc chưa biết, những giá trị như này trong game thường được khai báo dưới dạng địa chỉ static (sang bên bộ nhớ người ta hay gọi nó là pointer)

Chúng ta sẽ tiến hành tìm con trỏ (pointer) trỏ tới địa chỉ này ở trong vùng nhớ của game :v

Hehe. Chỗ này mình sẽ viết chi tiết ở bài viết sau. Các bạn chỉ cần dùng Pointer scan của Cheat Engine là xong :v

Mình tìm được pointer base là: 0x00329670
Các offsets là 0x320, 0x18, 0x0, 0x8, 0x5578

Oke như vậy là mình đã có địa chỉ con trỏ trỏ tới vùng nhớ của địa chỉ chứa số lượng mặt trời, việc còn lại là đọc ghi với thằng C++.


Mình sẽ tính chính xácđịa chỉ của thằng nàyđể mỗi lần chúng ta khởiđộng lại game, giá trị này vẫn linhđộng theo:
Trước hết chúng ta cần base address của main module của game này:
Tìm địa chỉ đó bằng hàm này:

C++:
DWORD getModule(LPSTR moduleName)
{
    hModuleSnap = INVALID_HANDLE_VALUE;
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);

    if (hModuleSnap == INVALID_HANDLE_VALUE)
    {
        cout << "Khong the snapshot module list cua process " << pID << endl;
        CloseHandle(hModuleSnap);
        return false;
    }

    modEntry32.dwSize = sizeof(MODULEENTRY32);

    if (Module32First(hModuleSnap, &modEntry32))
    {
        if (!strcmp(moduleName, modEntry32.szModule))
        {
            cout << "Tim thay module " << modEntry32.szModule << " voi base address la: " << hex << (DWORD)modEntry32.modBaseAddr << endl;

            CloseHandle(hModuleSnap);
            return (DWORD)modEntry32.modBaseAddr;
        }
    }

    while (Module32Next(hModuleSnap, &modEntry32))
    {
        if (!strcmp(moduleName, modEntry32.szModule))
        {
            cout << "Tim thay module " << modEntry32.szModule << " voi base address la: " << hex << (DWORD)modEntry32.modBaseAddr << endl;
            CloseHandle(hModuleSnap);
            return (DWORD)modEntry32.modBaseAddr;
        }
    }

    cout << "Khong the tim thay module " << moduleName << " trong process " << pID << endl;
    CloseHandle(hModuleSnap);
    return false;
}

Sau đó ta sẽ tính địa chỉ chính xác mà pointer trỏ tới:


C++:
DWORD getPointerAddress(DWORD gameBaseAddress, DWORD address, vector<DWORD> offsets)
{
    DWORD offset_null = NULL;
    ReadProcessMemory(hProc, (LPVOID*)(gameBaseAddress + address), &offset_null, sizeof(offset_null), 0);
    DWORD pointerAddress = offset_null;
    for (int i = 0; i < offsets.size() - 1; i++)
    {
        ReadProcessMemory(hProc, (LPVOID*)(pointerAddress + offsets.at(i)), &pointerAddress, sizeof(pointerAddress), 0);
    }
    return pointerAddress += offsets.at(offsets.size() - 1);
}


Tiếp tục chúng ta cần attach vào process để lấy handle của nó bằng cách dùng OpenProcess
(OpenProcess return handle of the Process: anh em có thể tham khảo thêm tại đây: Open Process function)


C++:
bool attachProc(char* procName)
{
    procEntry32.dwSize = sizeof(PROCESSENTRY32);
    hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hProcSnap == INVALID_HANDLE_VALUE)
    {
        cout << "Khong the snap cac process" << endl;
        return false;
    }

    while (Process32Next(hProcSnap, &procEntry32))
    {
        if (!strcmp(procName, procEntry32.szExeFile))
        {
            cout << "Tim thay process " << procEntry32.szExeFile << " voi pID la " << procEntry32.th32ProcessID << endl;
            pID = procEntry32.th32ProcessID;
            hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEntry32.th32ProcessID);

            if (hProc == NULL)
            {
                cout << "Khong the tao handle cua process, exit." << endl;
                return false;
            }
            CloseHandle(hProcSnap);
            return true;
        }
    }

    cout << "Khong the tim thay process " << procName << " trong list process, vui long thu lai sau." << endl;
    CloseHandle(hProcSnap);
    return false;
}

Khi đã lấy được handle của nó thì mình làm mọe gì với nó cũng được, hấp diêm hoặc lấy nó làm vợ cũng được, oke chưa a e :2lol:

Tiếp theo là hàm đọc ghi bộ nhớ trong C++

//Hàm ghi
C++:
template <class dataType>
void wpm(dataType valToWrite, DWORD addressToWrite)
{
    WriteProcessMemory(hProc, (PVOID)addressToWrite, &valToWrite, sizeof(dataType), 0);
}
//Hàmđọc

C++:
template <class dataType>
void rpm(dataType valToRead, DWORD addressToRead)
{
    dataType rpmBuffer;
    ReadProcessMemory(hProc, (PVOID)addressToRead, &rpmBuffer, sizeof(dataType), 0);
    return rpmBuffer;
}


Ở đây mình dùng template để linh động trong việc ghi giá trị bộ nhớ, do các giá trị có kiểu dữ liệu rất đa dạng, do đó biến truyền vào kiểu dữ liệu nào thì mình ghi kiểu dữ liệu đó :2lol:

Oke việc còn lại là mình sẽ gọi hàm wpm để thực hiện ghi 9999 vào bộ nhớ tại địa chỉmà mình tìmđược bằng pointer

Hàm main của chúng ta:
C++:
int main()
{
    DWORD moduleBaseAddr = NULL;
    DWORD sunAddress = 0x00329670;
    DWORD realAddress = NULL;

    int val = 9999; // số lượng mặt trời muốn ghi vào bộ nhớ

    vector<DWORD> offsets = { 0x320, 0x18, 0x0, 0x8, 0x5578 };

    bool check = attachProc((char*)"popcapgame1.exe");
    if (check)
    {
        cout << "Thanh cong attach vao process " << pID << endl;
        moduleBaseAddr = getModule((LPSTR)"popcapgame1.exe");
        if (moduleBaseAddr == NULL)
        {
            cout << "Khong tim duoc module base address" << endl;
            return 0;
        }
        cout << "Base address: " << hex << moduleBaseAddr << endl;

        realAddress = getPointerAddress(moduleBaseAddr, sunAddress, offsets);

        if (realAddress == NULL)
        {
            cout << "Khong tim duoc realaddress cua " << hex << sunAddress << endl;
            return 0;
        }
        cout << "Dia chi sunaddress: " << hex << realAddress << endl;
        cout << "Nhap so luong mat troi: ";
        cin >> val;
        while (true)
        {
            wpm<int>(val, realAddress);
            cout << "Da thuc hien ghi " << val << " SUN vao bo nho" << endl;
            Sleep(1000);
        }
    }
    else {
        cout << "Khong the attach process, vui long thu lai";
        return 0;
    }

}

Oke chạy và nhận thành cmn quả:
1630165721990.png


:bacda:


1630166162642.png


:muaquat:Chúc anh em thành công không thành thụ :v

Video chi tiết hướng dẫn mình làm ở đây:

Source code chi tiết ở đây: https://github.com/zedterminator/SimpleGameHack/

:muaquat:
 

Supertroll

Cú Đêm Member
Tham gia
16/8/21
Bài viết
261
Lượt thích
48
Điểm
28
quá kinh khủng khiếp :3lol: kiến thức này quá khó để tiếp thu :yaoming:
 

khoailuoc

Kiểm Duyệt Viên
Tham gia
19/8/21
Bài viết
36
Lượt thích
8
Điểm
8
Ôi thím ơi, đi từ hello world chứ thím đi nhanh quá. E đang tập đi mà bác dạy vỉa cmnr:vozxit3:
 

Thành viên trực tuyến

Không có thành viên trực tuyến.
shape1
shape2
shape3
shape4
shape7
shape8
Top