Chap 4 : infinite time
Đây là chap tương đổi khó, để infinite time chúng ta phải đảm bảo được 2 điều+ Tìm ra điạ chỉ của biến time
+ Tư tưởng đóng băng nó
I. Tìm ra địa chỉ của biến time :
Cách 1 : Tôi dò dưới chế độ Unknown value :
đầu tiên
Bước 2
Nghỉ tầm 1s để thanh time bar tụt đi 1 tí rồi tôi làm như này
sau đó cứ lặp lại bước 2 cho đến khi tìm thấy thì thôi
(Tốn khá nhiều time để bạn tìm thấy nó đấy)
Cách 2 : Cách 1 khá công phu và loằng ngoằng, nên theo kinh nghiệm, tôi ko làm như vậy, vào artmoney
xem vùng nhớ ở gần cái biến điểm tôi thấy có 1 vùng cứ nhẩy giá trị liên tằng tằng theo thời gian, tôi đoán đó là biến time
vô artmoney thử đóng băng cái giá trị đó tôi thấy thanh time bar nhúc nhíc quanh 1 điểm chứ ko tụt đi, vậy chính là nó
là 1 số thực 4byte (float) có địa chỉ là 004B6084 (Vậy là nó đứng ngay cạnh, đằng trước biến điểm)
II. Code đóng băng nó
thật ra cái biến time này nó là 1 biến float nhưng khi memory map tớ còn phát hiện ra như sau :
giả sử 4 byte của biến float đó là abcd
bỏ qua 2 byte a,b quan tâm đến c d tớ thấy
+ c chạy từ 0 đến 1 giá trị max rồi lại trở về 0 chạy tiếp, theo nhịp của trò chơi,
+ d càng nhỏ thì c chạy càng nhanh, khi d bằng 69 thì bắt đầu chạy từ từ, khi d cao đến gần 80 thì c chạy chậm hẳn
+ d=0 thì c chạy cực nhanh, cỡ mini dây, vụt 1 phát, d thành 69 luôn và c bắt đầu chạy từ từ với tộc dộ chậm dần
và vì vậy :
+ nếu set d thành số nhỏ hơn 69 thì ngay lập tức trở về bình thường
+ nếu set d thành -1 thì có nghĩa d chính là 255 (vì nó là 8bit mà) sẽ overflow ngay
+ nếu set cả biến float 4byte này thành 1 số âm thì theo cách tớ vừa mô tả ở trên d sẽ rất nhanh chóng phục hồi lại thành 69 và ko có tác dụng
+ nếu set cả biến float 4byte này thành 1 số lớn hơn mức cực đại thì sẽ kết thúc trận đấu luôn
==> thay đổi biến time này ko có hiệu quả
nhưng suy ra 1 cách đó là ta làm đóng băng giống như các cheat engine đóng băng : cứ 100ms thì lại set d=0 một lần, như thế thanh time bar vẫn max, time vẫn vô cùng
Tôi mất khá nhiều time để nghĩ và tìm ra cách đóng băng nó hay hơn
+ đầu tiên, đơn giản nhất, tôi nghĩ ra là sét giá trị cho nó 1 cách liên tục,
demo
PHP Code:
while (..)
{
set max time()
sleep(100)
}
+ tiếp theo : trong cái code decompile ra được, tôi thấy có 1 hàm sử lí TIMER, vậy tôi định kill timer của process này, nhưng còn loằng ngoằng hơn ..... và tôi chưa tìm được định danh của cái bộ timer này nên ..... lực bất tòng tâm
+ Cuối cùng, bực mình, sáng suốt tôi quyết định tìm ra nguyên nhân tay đổi nó.
ví dụ trong process có 1 đoạn là time=10+time/60 (ví dụ thế) .
Tôi quyết định dùng các kinh nghiệm đã có để tìm ra đoạn mã gán giá trị cho biến time này, rồi tôi thay đổi luôn đoạn mã này đi, thế là ok ? Đúng ko bạn
Bắt đầu nghĩ tôi thấy, time là 1 biến thực 4 byte, vậy với asm32 - float processing thì đoạn mã tôi cần tìm sẽ có dạng như sau
PHP Code:
fld real4 ptr [004B6084]
.....................
fstp real4 ptr [004B6084]
fstp viết tắt của float store point
tạm dịch sang ngôn ngữ nói nó là
PHP Code:
fload time
.... xử lí linh tinh....
fsave time
Cách 1 đơn giản nhất mang tính tình huống, tôi mở VB Decompiler Pro với quyền admin, rồi decompile upikachu (xem chap1) , sau đó vào Filevào Save all in one module file Được 1 file .bas . Mở file này bằng notepad rồi ấn Ctrl + F tìm kiếm chuỗi 004B6084, tìm đúng chỗ nào sử dụng toán tử fld với tham số là 004B6084 ta được
PHP Code:
004B02C4: fld real4 ptr [004B6084h] ;
004B02CA: fadd real8 ptr var_80
004B02CD: fild dword ptr var_14
004B02D0: mov var_14, ebx
004B02D3: fstp real8 ptr var_88
004B02D9: fsub real8 ptr var_88
004B02DF: fstp real4 ptr [004B6084h] ;
-> vào Ollybdb vào View vào Memory
-> Đúp chuột vào section .text
-> ra 1 cửa sổ dump, ta chuột phải, vào copy, vào select all
-> chuột phải lần nữa vào copy vào to file
-> được 1 file txt
-> tìm kiếm trên file này
chú ý : theo luật little-endian by order 004B6084 thì trong máy nó được tổ chức là 84 60 4B 00, nên chuỗi tìm kiếm của ta trong cách này phaỉ là 84604B00
tìm và thu được kết quả như sau
PHP Code:
004B02C4 D905 84604B00 FLD DWORD PTR [>
004B02CA DC45 80 FADD QWORD PTR >
004B02CD DB45 EC FILD DWORD PTR >
004B02D0 895D EC MOV [EBP-14],EB>
004B02D3 DD9D 78FFFFFF FSTP QWORD PTR >
004B02D9 DCA5 78FFFFFF FSUB QWORD PTR >
004B02DF D91D 84604B00 FSTP DWORD PTR >
III. Xử lý kết quả thu được như thế nào
Ta đã có đoạn mã và địa chỉ của đoạn mã này trong bộ nhớ rồi, ta phải làm thế nào bây giờ ?
Tôi nghĩ ra 1 cách , đó là tôi lái cái fld ra 1 chỗ khác, tôi cho nó fload sang ô điểm, hờ hờ hờ (như thế câu lệnh này sẽ trở thành)
PHP Code:
fload điểm
.... xử lí linh tinh....
fsave time
ở đây , tại ô nhớ 004B02C4 câu lệnh fld real4 ptr [004B6084h] ; dài 6 byte 2 byte đầu chính là mã của toán tử fld(0x5D9) (Tôi biết là 6byte vì câu lệnh tiếp theo có địa chỉ 004B02CA), 4byte sau chính là tham số của toán tử này 004B6084h.
==> chung quy lại tôi sẽ viết 1 chương trình đổi giá trị tại địa chỉ 004B02C6 từ giá trị ban đầu là 004B6084 thành 004B6088
Code
PHP Code:
#include
void SetInfiniteTime()
{
HWND hwnd =FindWindow(L"ThunderRT6FormDC", L"³s³s¬Ý2");
if (!hwnd)
{
MessageBox(HWND_DESKTOP,L"Bạn phải bật pikachu lên chơi trước đã",L"Thông báo",MB_OK);
}
else
{
DWORD pid;
int temp=0x4B6088;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE handle=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,pid);
int *address=(int*)0x4B02C6;
WriteProcessMemory(handle,address,&temp,sizeof(temp),0);
MessageBox(HWND_DESKTOP,L"Đã set thành công",L"Thông báo",MB_OK);
}
}
void UnSetInfiniteTime()
{
HWND hwnd =FindWindow(L"ThunderRT6FormDC", L"³s³s¬Ý2");
if (hwnd)
{
DWORD pid;
int temp=0x4B6084;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE handle=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,pid);
int *address=(int*)0x4B02C6;
WriteProcessMemory(handle,address,&temp,sizeof(temp),0);
MessageBox(HWND_DESKTOP,L"Đã unset thành công",L"Thông báo",MB_OK);
}
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
SetInfiniteTime();
return EXIT_SUCCESS;
}
PHP Code:
#include
void SetInfiniteTime()
{
HWND hwnd =FindWindow("ThunderRT6FormDC", "³s³s¬Ý2");
if (!hwnd)
{
MessageBox(HWND_DESKTOP,"Ban phai bat pikachu lon choi truoc do","Thung boo",MB_OK);
}
else
{
DWORD pid;
int temp=0x4B6088;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE handle=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,pid);
int *address=(int*)0x4B02C6;
WriteProcessMemory(handle,address,&temp,sizeof(temp),0);
MessageBox(HWND_DESKTOP,"Do set thanh cong","Thong bao",MB_OK);
}
}
void UnSetInfiniteTime()
{
HWND hwnd =FindWindow("ThunderRT6FormDC", "³s³s¬Ý2");
if (hwnd)
{
DWORD pid;
int temp=0x4B6084;
GetWindowThreadProcessId(hwnd,&pid);
HANDLE handle=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,pid);
int *address=(int*)0x4B02C6;
WriteProcessMemory(handle,address,&temp,sizeof(temp),0);
MessageBox(HWND_DESKTOP,"Do unset thanh cong","Thong bao",MB_OK);
}
}
int main()
{
SetInfiniteTime();
return 1;
}
Kết luận : Với tất cả 4 chap trên, bạn hoàn toàn có thể viết 1 cái hack tool cho pikachu rồi đấy, nếu ko có kinh nghiệm tạo các ứng dụng trên windows, các bạn hoàn toàn có thể dùng DEV-C để viết lên 1 chương trình có menu như bình thường, nhập 1 để add point, 2 để hack mạng .......... Chúc các bạn thành công và vui vẻ với loạt tut này.