Bài 3: Cách tổ chức thông tin trong Mem của RTK XI
Step 1: Sau khi scan một số thông tin về Troop, Food, Gold ... của City, các bác sẽ tiếp tục.
Ví dụ đây là kết quả tôi scan với Chen Liu
Và khi View Memory các bác sẽ thấy một số điều thú vị sau.
1) Bên dưới Chen Liu sẽ thấy Xu Chang với Base_Addr như nhau (78 5E 76 00) và cách nhau 0x0244 bytes.
2) Name = Base_Addr + 0x04
3) Troop = Base_Addr + 0x3C
4) Gold = Base_Addr + 0x40
5) Và tương tự với các thông số khác ...
Step 2: Tiếp tục dò lên trên các vùng mem "tương tự" (chú ý "78 5E 76 00") sẽ thấy được City đầu tiên là Xiang Ling. Mỗi City cách nhau là 0x0244 bytes.
Step 3: Vậy muốn tìm thông tin của một City bất kì?
Đầu tiên, phải biết index (CITY_ID) của City đó trong vùng Mem. Tạm thời các bác sử dụng số index trong Tool Editor nhé (sẽ hướng dẫn các lấy nó sau).
Và công thức tính Base_Addr của City bất kì sẽ là
= CITY_BASE_ADDR + index * CITY_DATA_SIZE
Tương tự như thế với Gate và Port các bác sẽ hiểu cách tổ chức Mem.
Step 4: scan các define của City (sẽ sử dụng nó trong phần lập trình).
Mã:
#define CITY_BASE_ADDR 0x0719E548
#define CITY_DATA_SIZE 0x0244
#define CITY_NAME 0x04
#define CITY_PREFECT 0x30
#define CITY_TROOPS 0x3C
#define CITY_GOLD 0x40
#define CITY_FOOD 0x44
#define CITY_SPEARS 0x4C
#define CITY_PIKES 0x50
#define CITY_BOWS 0x54
#define CITY_HORSES 0x58
=========================
Bài 4: Sử dụng VC++ để viết tool editor cho RTK XI
Step 1: Về phần thiết kế giao diện và ngôn ngữ lập trình trên VC++ tôi kô đề cập nhiều (cái này các bác phải tự tìm hiểu). Lấy ví dụ tool editor đơn giản với City, Gate, Port thôi.
Step 2: Làm quen một số hàm cần thiết (cần thêm thông tin các bác search trên Google dùm nhé).
1) Find RTK window: tìm handle của RTK window
Mã:
int CRTKWnd::FindRTKWindows() {
...
EnumWindows(EnumWindowCallBack, NULL);
...
}
BOOL CALLBACK CRTKWnd::EnumWindowCallBack(HWND hwnd, LPARAM lParam) {
TCHAR szClassName[256];
GetClassName(hwnd, szClassName, 256);
if (_tcscmp(szClassName,_T("KOEI_SAN_11_WINDOW")) == 0) {
...;
}
return true;
}
2) Sử dụng Read/WriteProcessMemory để read/write Mem
+ ReadProcessMemory copies the data in the specified address range from the address space of the specified process into the specified buffer of the current process. Any process that has a handle with PROCESS_VM_READ access can call the function. Typically but not always, the process with address space that is being written to is being debugged.
http://msdn.microsoft.com/en-us/library/ms680553(VS.85).aspx
+WriteProcessMemory copies the data from the specified buffer in the current process to the address range of the specified process. Any process that has a handle with PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process to be written to can call the function. Typically but not always, the process with address space that is being written to is being debugged.
http://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx
Step 3: Lấy danh sách City
Các define của City:
Mã:
#define CITY_BASE_ADDR 0x0719E548
#define CITY_DATA_SIZE 0x0244
#define CITY_NAME 0x04
#define CITY_TROOPS 0x3C
#define CITY_GOLD 0x40
#define CITY_FOOD 0x44
#define CITY_SPEARS 0x4C
#define CITY_PIKES 0x50
#define CITY_BOWS 0x54
#define CITY_HORSES 0x58
#define CITY_WILL 0x80
#define CITY_ORDER 0x81
class RTKCity {
public:
int m_city_id;
CString m_city_name;
int m_city_troops;
int m_city_gold;
int m_city_food;
int m_city_spears;
int m_city_pikes;
int m_city_bows;
int m_city_horses;
int m_city_order;
byte m_city_will;
void init() {
m_city_id = -1;
m_city_name = _T("");
m_city_troops = 0;
m_city_gold = 0;
m_city_food = 0;
m_city_spears = 0;
m_city_pikes = 0;
m_city_bows = 0;
m_city_horses = 0;
m_city_order = 0;
m_city_will = 0;
}
};
Lấy danh sách City từ Mem rồi add vào combo box:
Mã:
void CRTKWnd::GetCityNameList() {
CString strTmp = _T("");
cboName.ResetContent();
for (int i = 0; i < MAX_CITY; i++) {
CString name = GetCity(i);
if (name.IsEmpty()) {
name = _T("");
}
strTmp.Format(_T("%d"), i);
cboName.AddString(name + _T("(") + strTmp + _T(")"));
}
return;
}
CString CRTKWnd::GetCity(int idx) {
HWND hWin = GetWin(m_curIdx);
if (!IsWindow(hWin)) {
return _T("");
}
DWORD dwProcessID;
::GetWindowThreadProcessId(hWin, &dwProcessID);
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwProcessID);
if (!hProcess) {
return _T("");
}
LPBYTE lpBaseAdd = (LPBYTE) (CITY_BASE_ADDR + idx * CITY_DATA_SIZE);
char szName[32];
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_NAME), (LPVOID) szName, sizeof(szName), NULL);
CloseHandle(hProcess);
return CString(szName);
}
Lấy thông tin của City:
Mã:
RTKCity CRTKWnd::GetCityInfo(int idx) {
HWND hWin = GetWin(m_curIdx);
RTKCity city;
city.init();
if (!IsWindow(hWin)) {
return city;
}
DWORD dwProcessID;
::GetWindowThreadProcessId(hWin, &dwProcessID);
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwProcessID);
if (!hProcess) {
return city;
}
LPBYTE lpBaseAdd = (LPBYTE) (CITY_BASE_ADDR + idx * CITY_DATA_SIZE);
city.m_city_id = idx;
char szName[32];
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_NAME), (LPVOID) szName, sizeof(szName), NULL);
city.m_city_name = szName;
int troops;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_TROOPS), (LPVOID) &troops, 4, NULL);
city.m_city_troops = troops;
int gold;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_GOLD), (LPVOID) &gold, 4, NULL);
city.m_city_gold = gold;
int food;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_FOOD), (LPVOID) &food, 4, NULL);
city.m_city_food = food;
int spears;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_SPEARS), (LPVOID) &spears, 4, NULL);
city.m_city_spears = spears;
int pikes;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_PIKES), (LPVOID) &pikes, 4, NULL);
city.m_city_pikes = pikes;
int bows;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_BOWS), (LPVOID) &bows, 4, NULL);
city.m_city_bows = bows;
int horses;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_HORSES), (LPVOID) &horses, 4, NULL);
city.m_city_horses = horses;
byte will;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_WILL), (LPVOID) &will, 1, NULL);
city.m_city_will = will & 0xFF;
byte order;
ReadProcessMemory(hProcess, (LPBYTE) (lpBaseAdd + CITY_ORDER), (LPVOID) &order, 1, NULL);
city.m_city_order = order & 0xFF;
CloseHandle(hProcess);
return city;
}
Step 4: edit thông tin của City (phải biết index của City), ví dụ như Troops
Mã:
void CRTKWnd::EditTroops(int idx, int nValue) {
HWND hWin = GetWin(m_curIdx);
if (!IsWindow(hWin)) {
return;
}
DWORD dwProcessID;
::GetWindowThreadProcessId(hWin, &dwProcessID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
if (!hProcess) {
return;
}
LPBYTE lpBaseAdd;
byte buffer[4];
buffer[0] = (byte)(nValue & 0xFF);
buffer[1] = (byte)((nValue >> 8) & 0xFF);
buffer[2] = (byte)((nValue >> 16) & 0xFF);
buffer[3] = (byte)((nValue >> 24) & 0xFF);
lpBaseAdd = (LPBYTE) (CITY_BASE_ADDR + idx * CITY_DATA_SIZE);
WriteProcessMemory(hProcess, (LPVOID) (lpBaseAdd + CITY_TROOPS), (LPVOID) buffer, 4, NULL);
CloseHandle(hProcess);
return;
}
Step 5: Cuối cùng, sẽ upload lên source (RTKEditorLite) của ví dụ này để các bác tham khảo (source sử dụng VC++ 2008)
(xem file đính kèm)
Thanks all.
dungsi3t