Hướng dẫn debug và lập trình tool Editor cho RTK XI

Thảo luận trong 'RTK và others' bắt đầu bởi dungsi3t, 3/10/08.

  1. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Hi các bác,
    Sau khi hoàn thành tool editor cho RTK XI (English-PC), tôi có một số kinh nghiệm về debug và phát triển tool editor cho thể loại này.
    Có thể các kiến thức này kô mới, nhưng hy vọng giúp các bác mới làm quen với debug có thêm kinh nghiệm.
    Hy vọng các bác yêu thích RTK + lập trình có thể phát triển tool editor cho riêng mình.

    Thanks all,
    dungsi3t
    www.TruBatGioi.net

    Download Full (Bài viết + Source)
    ============================
    Bài 1: Khởi động

    Yêu cầu:
    1) RTK XI bản English for PC (yêu cầu bắt buộc :devil:)
    2) Cheat Engine (CE) (hoặc Art Money ...), trong bài này mình sẽ hướng dẫn về CE để debug.
    3) Sử dụng VC++ để phát triển Tool.

    Mong nhận được sự góp ý và hỗ trợ của các bác yêu thích.
    Sẵn sàng chia sẻ kinh nghiệm và giúp đỡ các bác bước đầu làm quen với việc debug và phát triển tool editor.
     
  2. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Bài 2: Sử dụng Cheat Engine (CE) để debug và edit

    Bài này chỉ cung cấp các bước cần thiết cho việc debug và edit bằng CE. Các bác có thể tìm hiểu thêm thông tin trên internet.

    Step 1: Khởi động game RTK XI

    Step 2: Run Cheat Engine, tôi đang sử dụng version 5.3

    Step 3: Chọn game RTK XI để debug và edit

    [​IMG] [​IMG]

    Step 4: New Scan và Next Scan
    Khi muốn scan một giá trì nào đó, các bác phải xác định Scan Type và Value Type.
    Lần đầu scan, các bác chọn New Scan --> sẽ cho kết quả là danh sách scan được. Sau đó các bác vào game làm cho giá trị "đã scan trước đó" thay đổi, và tiếp tục Next Scan với giá trị mới.

    Ví dụ 1: scan giá trị với Type: Exact Value và Type: 4 bytes.
    [​IMG]

    Ví dụ 2: scan giá trị với Type: Search for Text và Type: Text.
    [​IMG]

    ------------
    Lấy một ví dụ cụ thể: scan thông tin của City An Ding

    Step 1: hiện tại Food là 42261 và tôi New Scan được danh sách sau
    [​IMG]

    Step 2: tôi vào game làm cho giá trị Food thay đổi thành 42561. Và tôi chọn Next Scan với giá trị mới (42561) sẽ được kết quả
    [​IMG]

    Và bây giờ chỉ còn một address (0x071A1098) thôi, nên tôi biết đó là chỉ số Food của An Ding. Nếu danh sách của các bác còn dài, các bác có thể tiếp tục lặp lại bước này cho đến khi danh sách tối ưu nhất. Nếu danh sách vẫn còn dài, các bác sẽ phải chọn từng address mà ... "đoán".

    Step 3: add address vừa tìm được list của CE và có thể trace thêm một số thông tin khác.
    [​IMG]

    Khi các bác right-click vào dòng trong list, chọn Browse this memory region sẽ xuất hiện window Memory Viewer, scroll lên trên một tí các bác sẽ thấy chữ An Ding (cửa sổ này rất quan trọng, sẽ đề cập trong bài sau).
    [​IMG]

    Step 4: muốn edit chỉ số Food hiện tại, các bác có thể double click vào cột Value tương ứng và edit.
    [​IMG]

    Các bác có thể tiếp tục với các chỉ số tiếp theo (Gold, Troops, Spears, ...).
     
  3. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    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
    [​IMG]

    Và khi View Memory các bác sẽ thấy một số điều thú vị sau.
    [​IMG]

    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.
    [​IMG]

    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).
    [​IMG]

    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.
    [​IMG]

    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
     

    Các file đính kèm:

  4. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Kết thúc bài viết.
    Thanks all,
    dungsi3t
     
  5. ~Pawn~

    ~Pawn~ Donkey Kong

    Tham gia ngày:
    8/7/06
    Bài viết:
    430
    Nơi ở:
    RTK & others
    Cảm ơn bác dungsi3t nhiều lắm. Bài viết này của bác vô cùng giá trị :Rose:
    Nhớ lúc đầu em học lt, thì cái C++ là cái học đầu tiên...Sau này toàn làm việc với code của C# thành ra C++ quên sạch:'> Cách đây vài tháng, lúc em cần viết cái tool cho TSonline...viết bằng C#, mún kiếm một cái turtorial kiểu như bài của bác thế này để viết cho nhanh mà lết từ codeproject đến csharpcorner...đỏ mắt cũng hẻm thấy.
    Cho nên lúc đó ngồi mò từng tí một, rất là vất vả, mãi mới hoàn thành xong cái tool nhỏ như con kiến=((. Có điều viết bằng C# thì cần framework mới run được, rất khó chịu. Giá lúc đó em gặp cái bài này thì khỏe rồi.

    Cảm ơn bác 1 lần nữa:'>
     
  6. Diesel Industry

    Diesel Industry Nam Việt Đại tướng quân

    Tham gia ngày:
    16/5/07
    Bài viết:
    2,477
    Nơi ở:
    The theatre of dreams
    Công nhận bài viết rất hay, có thể áp dụng cho nhiều trường hợp khác nữa.
     
  7. lukepro

    lukepro Youtube Master Race

    Tham gia ngày:
    28/4/07
    Bài viết:
    92
    Hay cái này đáng để nghiên cứu thx bác :;)
     
  8. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Mấy bác cứ nghiên cứu, cần thêm thông tin gì tôi sẽ post lên và thảo luận.
    Các bác thử tìm Base_Addr của Officer (hoặc Forces, District ...) xem sao?
     
  9. banzai4u

    banzai4u Youtube Master Race

    Tham gia ngày:
    22/9/08
    Bài viết:
    7
    Cám ơn bác dungsi3t nghen ... hong hiểu chắc ghé nhà bác chỉ dùm em wá :D .... rỏ ràng wá ... chắc bi giờ mở sách C++ mò từng chử wá :-/
     
  10. thangl0n9

    thangl0n9 Youtube Master Race

    Tham gia ngày:
    9/10/08
    Bài viết:
    45
    bác dungsi3t có cách nào sửa số ngày của 1 turn không?
    1 turn là 10 ngày nhanh quá. Chưa thống nhất được mà tướng đã chết tùm lum hết :((
    Có cách nào thay 1 turn = 1 ngày không vậy bác? :hug:
     
  11. Fireemblem&me

    Fireemblem&me Dragon Quest

    Tham gia ngày:
    22/3/07
    Bài viết:
    1,424
    Nơi ở:
    HCM
    hay đó cái này mình có thể làm được nhưng chắc để tết đi
    giờ bận quá
    :D
     
  12. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Vấn đề này chắc có nhiều hướng giải quyết:
    1) Edit Lifespan hoặc Death của Officer
    2) Edit lại current day của game --> có thể làm được
    3) Hook vào game để xử lý cái turn ... cho nó khỏi tăng ngày luôn :hug:

    Ý tưởng là vậy ... bác nào rãnh làm thử xem :>
     
  13. _TVL_

    _TVL_ Space Marine Doomguy Lão Làng GVN

    Tham gia ngày:
    6/4/08
    Bài viết:
    5,964
    Vậy nếu xét theo khía cạnh thực tế

    30 ngày = 30 turn mới có 1k vàng 8-}

    90 turn mới có 20k food 8-}

    Thế thì thành ko sập thì quân tướng cũng chết đói cả 8-}
     
  14. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Yes, thực tế là thế.
    Nhưng xét về khía cạnh lập trình ... có thể hook vào game để làm cho mọi thứ như bình thường (Gold, Food tăng normal), nhưng ngày trôi qua là ... 1 ngày hoặc kô trôi :o
    Bàn bạc và làm cho vui thôi ... chứ can thiệp như thế game mất vui rồi, vì ngày kô tăng thì mất rất nhiều Event hay.
     
  15. thangl0n9

    thangl0n9 Youtube Master Race

    Tham gia ngày:
    9/10/08
    Bài viết:
    45
    Đấy là em ví dụ 1 turn = 1 ngày. Phần mềm có thể cho người chơi tùy ý lựa chọn 1 turn = 1 , 2 , 3 ,5 , 6...(ước số của 30) ngày mà?
    Lương thực cứ 9 turn là thu hoạch / tiền cứ 3 turn là thu....
    có được không bác?
     
  16. ~Pawn~

    ~Pawn~ Donkey Kong

    Tham gia ngày:
    8/7/06
    Bài viết:
    430
    Nơi ở:
    RTK & others
    Mới ngồi ôn lại c++ nên cho pawn hỏi ngoài lề tí nha bác::),
    Sao dungsi3t không dùng MFC của visual C++ 6.0? mà lại dùng cái MFC sử dụng ở dạng Static library trong bộ visual studio 2008, như vậy thì file thực thi hơi bị nhớn?
    mà không biết dạo này bác còn hay vào box không hay bị cô nào gọi hồn rùi:p
     
  17. dungsi3t

    dungsi3t Youtube Master Race

    Tham gia ngày:
    3/2/05
    Bài viết:
    91
    Uh, trước kia cũng sử dụng VC++ 6.0. Nhưng đợt rồi lỡ nâng cấp lên VS 2008 rồi ... nên code luôn cho các ứng dụng về sau (lười code lại mà :devil:)

    Bác có thể build lại với VC++ 6.0 cho mình, vì thực ra cũng chỉ sử dụng Read/WriteMemoryProcess thôi.

    Bác code thử ứng dụng nho nhỏ cho vui, cần thêm Address nào thì tôi sẽ post lên thêm.
     
  18. coder_gate

    coder_gate Youtube Master Race

    Tham gia ngày:
    28/4/08
    Bài viết:
    2
    theo ý hiểu của tui ( tui không chơi game này nên không rõ ) thì tool của bạn cho phép người sử dụng nhập các thông tin cần thay đổi vào file hack game,sau đó nhờ vào địa chỉ cố định của các thông tin như Gold,food... bạn sử dụng hàm WriteProcessMemory để thay đổi thông tin trong game,nếu vậy thì mình thấy game này còn dễ,chứ như game World of Warcraft thì địa chỉ nó cứ thay đổi lung tung,mỗi lần load cheat Engine lên là lại 1 địa chỉ,vì vậy rất khó để thay đổi được thông tin của nó
     

Chia sẻ trang này