Có gì mới?

Chào mừng bạn đến với diễn đàn Tui Học Web

Vui lòng đăng ký hoặc đăng nhập để sử dụng hết các tính năng của forum nhé!
  • Thông báo: Hiện tại do admin không có nhiều thời gian và không thể tiếp tục quản trị và maintain forum, do đó forum sẽ có dự định được đóng lại từ 06/2022, cảm ơn mọi người đã đồng hành cùng forum suốt thời gian vừa qua. Cảm ơn rất nhiều.

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

Share code
Hello what's up anh em :v

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.
1630576329870.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:

1630576364483.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:
1630576381498.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

1630576392113.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:

1630576410844.png

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

1630576427617.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

1630576442627.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:
Ồ, bạn chưa phải thành viên của forum Đăng nhập hoặc đăng ký ngay.
)


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ả:

1630576470093.png

:bacda:


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:
Ồ, bạn chưa phải thành viên của forum Đăng nhập hoặc đăng ký ngay.


:daica:
 

phamhau

Tế bào
Member
Tham gia
4 Tháng năm 2022
Bài viết
4
Điểm tương tác
0
Điểm
1
Cái này xài DLL inject vào process write pointer cho lẹ nhỉ :v đỡ dùng API !
 
Bài viết và chủ đề liên quan
Người mở bài Tiêu đề Diễn đàn Trả lời Date
LeDung Chia sẻ Memory Hack - Bước đầu làm quen với việc chỉnh bộ nhớ Kiến thức nền về máy tính 0

Bài viết và chủ đề liên quan

shape1
shape2
shape3
shape4
shape7
shape8
Bên trên