Trao đổi với tôi

http://www.buidao.com

10/18/10

[Reverse] Chap 6: Trainer Pikachu(Tổng hợp 5 chap-langman + Auto Pikachu-puss)

Chap 6: Trainer Pikachu(Tổng hợp 5 chap-langman + Auto Pikachu-puss)

Những thứ chúng ta cần:
0. Đã đọc và hiểu kỹ 5 chap do langman viết.
1. Tạo 1 giao diện thuận tiện cho việc sử dụng.
2. Địa chỉ biến thời gian: pTime ->Code đóng băng thời gian
3. Địa chỉ biến điểm: pPoint ->Code tăng 100 điểm / 1 lần ăn
4. Địa chỉ biến lượt đổi: pLife ->Code Vô hạn lượt đổi
5. Địa chỉ số lượng con quái còn trên màn hình: pNumber -> Code Ăn 1 con win luôn trong màn hiện tại
6. Địa chỉ số lượng quái vật khi vào màn chơi mới sẽ gán: pNumberConst ->Code Ăn 1 con win luôn vẫn có tác dụng trong các cửa tiếp theo
7. Địa chỉ ma trận lưu các thông tin trạng thái về các con quái: pMap -> Code Ăn 2 con khác nhau
8. Thuật toán tìm 2 con ăn được trên ma trận bản đồ -> Code tìm 2 con ăn
9. Mở rộng thêm 1 chút phần 7 để viết 1 auto tự chơi pikachu theo lựa chọn Single/All (auto 1 màn / auto đến màn cuối).


Những thứ chúng ta đã có (ai chưa hiểu đề nghị đọc lại kỹ 5 chap của langman):
2. Địa chỉ biến thời gian: pTime=0x004B6084; ->Code đóng băng thời gian
3. Địa chỉ biến điểm: pPoint=0x004B6088; ->Code tăng 100 điểm / 1 lần ăn
4. Địa chỉ biến lượt đổi: pLife=0x004B60AA; ->Code Vô hạn lượt đổi

Ok, bắt đầu thôi!

Phần 0. Đã đọc và hiểu kỹ 5 chap do langman viết
Cái này bạn nào chưa hiểu kỹ thì đọc lại nhé, rất quan trọng đấy.

Phần 1. Tạo giao diện:


Nhìn chung giao diện sẽ thế này:

Ghi chú: 4 chức năng đầu tiên khi bấm sẽ thêm dấu * ở cuối tức là chức năng tương ứng đã được kích hoạt, bấm 1 lần nữa dấu * sẽ biến mất và chức năng tương ứng sẽ bị tắt


Code giao diện:
Code:
#include  #include   #define BTN_FROZENTIME            1 #define BTN_POINTEAT            2 #define BTN_ULTIMATELIFE        3 #define BTN_WIN                    4 #define BTN_SAME                5 #define BTN_CHEAT                6 #define BTN_AUTO                7 #define RAD_STATUSAUTOSINGLE    8 #define RAD_STATUSAUTOALL        9   //Khai bao ham LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //Sau này sẽ viết thêm code khai báo hàm vào chỗ này  //Khai bao dia chi cac pointer //Sau này sẽ viết thêm code khai báo pointer vào chỗ này   //Khai bao cac bien //Sau này sẽ viết thêm code khai bao biến vào chỗ này   //Cac thong tin ve cua so Pikachu static HWND hwin; static HANDLE hProcess; static DWORD pid; //Sau này sẽ viết thêm code khai báo thông tin cửa sổ pikachu vào chỗ này   int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow) {     static TCHAR szAppName[]=TEXT("Pikachu Trainer");     HWND hwnd;     MSG msg;     WNDCLASS wndclass;          wndclass.style=CS_HREDRAW|CS_VREDRAW;     wndclass.lpfnWndProc=WndProc;     wndclass.cbClsExtra=0;     wndclass.cbWndExtra=0;     wndclass.hInstance=hInstance;     wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);     wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);     wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);     wndclass.lpszMenuName=NULL;     wndclass.lpszClassName=szAppName;          if (!RegisterClass(&wndclass))     {         MessageBox(NULL, TEXT("This program requires Windows NT"), szAppName, MB_ICONERROR);         return 0;     }               hwnd=CreateWindow(szAppName, TEXT("Pikachu Trainer"),                     WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,                     CW_USEDEFAULT,                     CW_USEDEFAULT,                     198,                     350,                     NULL,                     NULL,                     hInstance,                     NULL);                          ShowWindow(hwnd, iCmdShow);     UpdateWindow(hwnd);          while (GetMessage(&msg, NULL, 0, 0))     {         TranslateMessage(&msg);         DispatchMessage(&msg);     }          return msg.wParam; }   LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {     HDC hdc;     PAINTSTRUCT ps;          static int cxChar, cyChar;          static HWND hwndBtnFrozenTime, hwndBtnPointEat, hwndBtnUltimateLife, hwndBtnWin, hwndBtnCheat,                  hwndBtnSame, hwndRadStatusAutoSingle, hwndRadStatusAutoAll, hwndBtnAuto;          static char cPointEatStatus, cFrozenTimeStatus, cUltimateLifeStatus, cWinStatus, cAutoStatus;          TCHAR t[100];          HWND h;           switch(message)     {         case WM_CREATE:             cxChar = LOWORD (GetDialogBaseUnits ()) ;             cyChar = HIWORD (GetDialogBaseUnits ()) ;                           cFrozenTimeStatus=0;             hwndBtnFrozenTime = CreateWindow (TEXT("button"),                                     TEXT("Dong bang thoi gian"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*1,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_FROZENTIME,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                                         cPointEatStatus=0;              hwndBtnPointEat = CreateWindow (TEXT("button"),                                     TEXT("100 diem/1 lan an"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*3,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_POINTEAT,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                                                   cUltimateLifeStatus=0;             hwndBtnUltimateLife = CreateWindow (TEXT("button"),                                     TEXT("Vo han luot doi"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*5,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_ULTIMATELIFE,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                           cWinStatus=0;                                 hwndBtnWin = CreateWindow (TEXT("button"),                                     TEXT("An 1 con Win luon"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*7,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_WIN,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                                                  hwndBtnSame = CreateWindow (TEXT("button"),                                     TEXT("An lung tung"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*9,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_SAME,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                                   hwndBtnCheat = CreateWindow (TEXT("button"),                                     TEXT("Tim 2 con an"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*11,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_CHEAT,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);               hwndBtnAuto = CreateWindow (TEXT("button"),                                     TEXT("Auto Pikachu"),                                    WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,                                    cxChar, cyChar*13,                                    22 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) BTN_AUTO,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                          hwndRadStatusAutoSingle = CreateWindow (TEXT("button"),                                     TEXT("Single"),                                    WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,                                    cxChar, cyChar*15,                                    10* cxChar, 7* cyChar / 4,                                    hwnd, (HMENU) RAD_STATUSAUTOSINGLE,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);              SendMessage(hwndRadStatusAutoSingle, BM_SETCHECK, 1, 0);              cAutoStatus=0;                                                  hwndRadStatusAutoAll = CreateWindow (TEXT("button"),                                     TEXT("All"),                                    WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,                                    12*cxChar, cyChar*15,                                    10 * cxChar, 7 * cyChar / 4,                                    hwnd, (HMENU) RAD_STATUSAUTOALL,                                    ((LPCREATESTRUCT) lParam)->hInstance, NULL);                          //Find Window Pikachu                         hwin=FindWindow(TEXT("ThunderRT5Form"), TEXT("³s³s¬Ý2"));             if (hwin==NULL){                 MessageBox(NULL, TEXT("Ban phai bat pikachu len da."), TEXT("Error"), 0);                 SendMessage(hwnd, WM_CLOSE, 16, 1);                 return 0;             }                          //Open Process Pikachu             GetWindowThreadProcessId(hwin, &pid);             hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);                                      //Find Client             //Sau này sẽ viết thêm code vào chỗ này                                       //Init some value             //Sau này sẽ viết thêm code khởi tạo 1 số giá trị vào chỗ này                                       return 0;                  case WM_PAINT:             hdc=BeginPaint(hwnd, &ps);                                       wsprintf(t, TEXT("Made by langman, puss"));             TextOut(hdc, cxChar, cyChar*18, t, wcslen(t));                          EndPaint(hwnd, &ps);             return 0;                      case WM_COMMAND:             switch(LOWORD(wParam)){                 case BTN_FROZENTIME:                     //Sau này sẽ viết thêm code đóng băng vào chỗ này                                          break;                 case BTN_POINTEAT:                     //Sau này sẽ viết thêm code ăn 100 điểm / 1 lần vào chỗ này                                          break;                 case BTN_ULTIMATELIFE:                     //Sau này sẽ viết thêm code vô hạn lượt đổi vào chỗ này                                      break;                                      case BTN_WIN:                     //Sau này sẽ viết thêm code ăn 1 con win luôn vào chỗ này                                          break;                                  case BTN_SAME:                     //Sau này sẽ viết thêm code ăn 2 con khác nhau vào chỗ này                                          break;                                      case BTN_CHEAT:                     //Sau này sẽ viết thêm code tìm 2 con ăn vào chỗ này                                          break;                 case BTN_AUTO:                     //Sau này sẽ viết thêm code auto chơi pikachu vào chỗ này                     break;                 case RAD_STATUSAUTOSINGLE:                     cAutoStatus=0;                     break;                 case RAD_STATUSAUTOALL:                     cAutoStatus=1;                     break;             }             return 0;                  case WM_DESTROY:             PostQuitMessage(0);             return 0;     }          return DefWindowProc(hwnd, message, wParam, lParam); }
Ok, vậy là xong phần giao diện.

Phần 2. Đóng băng thời gian:

Trong chap đóng băng thời gian, bạn langman đã thay đổi như sau:
Code:
fld điểm     xử lý linh tinh fsave time như thế này rõ ràng là chả có biến nào bị thay đổi cả rồi, hờ hờ hờ hờ (vì thằng điểm được load nhưng ko được save, thằng time được save nhưng bên trên đó lại chưa load, đâm ra chả có gì thay đổi cả)
Mình xin đính chính lại 1 chút.
Thật ra là biến time vẫn bị thay đổi.
Nguyên nhân thay đổi biến thời gian có thể tưởng tượng như sau:
time=MAX_TIME-time*x;
Làm theo cách của bạn langman thì sau khi sửa biểu thức trên sẽ thành:
time=MAX_TIME-điểm*x; tức là nó fld điểm thay vào chỗ của time
vì biến time tính theo giây, kiểu float lên sau vài giây sẽ to rất nhanh.
Lúc mới chơi điểm thấp nên bạn hầu như không có cảm giác vạch thời gian chạy,
nếu khi bạn chơi điểm cao cao 1 chút thì để ý thấy vạch thời gian có tụt đi 1 tí, đó là vì time vẫn bị trừ.

Giải quyết trọn vẹn vấn đề này thế nào?
1 cách rất đơn giản, ta sẽ sửa lại biểu thức thay đổi time thành:
y=MAX_TIME-time*x; (y là 1 biến nào đấy)
như vậy thì time chẳng bao giờ bị thay đổi cả, chỉ có biến y nào đó bị thay đổi thôi.
Hơn nữa nếu làm theo cách này, code đóng băng sẽ đẹp hơn. Khi bạn đóng băng ở chỗ nào thì vạch thời gian sẽ dừng ngay tại chỗ đó.
Và khi bạn tắt đóng băng thì thời gian sẽ chạy tiếp ở chỗ đã dừng.
Vấn đề nan giải ở chỗ phải chọn ai là kẻ "đóng thế" cho time? Chọn lung tung có thể gay crash chương trình ấy chứ.


Mở onllydbg ra nào, Ctrl+G tới địa chỉ mà langman đã tìm thấy là: 4B02C4 xem kiếm được gì không?
Bạn sẽ thấy thế này:


FLD DWORD PTR DS: [4B6084]
FADD QWORD PTR SS: [EBP-80]
FILD DWORD PTR SS:[EBP-14]
MOV DWORD PTR SS:[EBP-14],EBX
FSTP QWORD PTR SS:[EBP-88]
FSUB QWORD PTR SS:[EBP-88]
FSTP DWORD PTR DS:[4B6084]

Hô hô, bạn thấy "diễn viên đóng thế" chúng ta cần tìm rồi chứ?
Bạn để ý chỗ này nhé:
FSTP QWORD PTR SS:[EBP-88]
FSUB QWORD PTR SS:[EBP-88]
FSTP DWORD PTR DS:[4B6084] //lưu điểm


bạn còn nhớ cái biểu thức làm thay đổi thời gian phía trên không?
time=MAX_TIME-time*x
địa chỉ [EBP-88] có thể coi chính là thằng x trong biểu thức trên.
vậy thì ta chỉ cần sửa lại thế này:
FSTP DWORD PTR DS:[4B6084] thành FSTP DWORD PTR SS:[EBP-88]
tức là biểu thức thay đổi thời gian sẽ thành:
x=MAX_TIME-time*x;


FSTP DWORD PTR DS:[4B6084] có mã hex là: D91D 84604B00
FSTP DWORD PTR SS:[EBP-88] có mã hex là D99D 78FFFFFF


Thời cơ tới rồi, mở code giao diện ra, tới phần Khai báo các pointer và khai báo địa chỉ chỗ đóng băng thời gian:
Code:
const int pFrozenTime=0x004B02DF;
Tiếp theo ta khai báo ngay 2 mảng 6 byte ở chỗ khai báo biến:
Code:
static unsigned char arrUnFrozenTime[6]={0xd9, 0x1d, 0x84, 0x60, 0x4b, 0x00}; static unsigned char arrFrozenTime[6]={0xd9, 0x9d, 0x78, 0xff, 0xff, 0xff};
Tới chỗ "Sau này sẽ viết thêm code đóng băng vào chỗ này" và viết thôi!
Code:
if (cFrozenTimeStatus==0){     WriteProcessMemory(hProcess, (int *)pFrozenTime, arrFrozenTime, 6*sizeof(char), NULL);     SetWindowText(hwndBtnFrozenTime, TEXT("Dong bang thoi gian *")); } else{     WriteProcessMemory(hProcess, (int *)pFrozenTime, arrUnFrozenTime, 6*sizeof(char), NULL);     SetWindowText(hwndBtnFrozenTime, TEXT("Dong bang thoi gian")); } cFrozenTimeStatus=1-cFrozenTimeStatus;
Ok men, vậy là đã chạy ngon!


Phần 3. 100 điểm/1 lần ăn:


Theo chap hack điểm của langman, chúng ta đã có được địa chỉ của biến điểm là 1 số thức 4 byte
Địa chỉ của biến điểm là: pPoint=0x004B6088;
Làm thế nào để mỗi khi ăn ta được cộng thêm 100 điểm chứ không phải 20 điểm như bình thường?
theo kinh nghiệm của bạn langman trong chương đóng băng thời gian, mình đoán đoạn code khi ăn điểm sẽ được tăng lên thế này:

Code:
FLD điểm     cộng thêm vào điểm 20 FSTP điểm
bắt tay vào tìm luôn, vào onllydbg, bấm nút home cho nó về đầu entry, bấm ctrl+b, chọn dòng HEX, gõ vào chuỗi 88604B00 chọn forward và Search


Search khoảng 3~5 lần gì đó, bạn sẽ tới được chỗ này:


Bạn có nhìn rõ cái gì kia không??? FLOAT -20.00000, 1 số thực có giá trị là -20.00000!!!!
Haha, hóa ra là mỗi lần ta ăn 2 con, nó sẽ trừ vào số điểm của ta -20 điểm,
chứ không phải cộng thêm 20 điểm như ta vẫn nghĩ.
Xem kỹ dòng lệnh tại đây nào:
Code:
004b0829    d825 5c104000    FSUB DWORD PTR DS:[40105C]    FLOAT -20.00000
vậy có nghĩa là địa chỉ 40105c chính là nơi lưu con số -20.00000 yêu quí của chúng ta.

Làm luôn xem sao?
Mở code, tới phần khai báo pointer và thêm đoạn sau:
Code:
const int pPointEat=0x0040105C;
Tới phần khai báo biến và thêm đoạn này:
Code:
static float fPointEat;
Tới phần "Sau này sẽ viết thêm code ăn 100 điểm / 1 lần vào chỗ này" và viết
Code:
if (cPointEatStatus==0){     fPointEat=-100;     SetWindowText(hwndBtnPointEat, TEXT("100 diem/1 lan an *")); } else{     fPointEat=-20;     SetWindowText(hwndBtnPointEat, TEXT("100 diem/1 lan an")); }  cPointEatStatus=1-cPointEatStatus; WriteProcessMemory(hProcess, (int *)pPointEat, &fPointEat, sizeof(float), NULL);

Phần 4. Vô hạn lượt đổi:


Theo chap vô hạn lượt đổi của langman, ta có địa chỉ của biến lượt đổi là: pLife=0x004B60AA;
Bạn langman đã set lại giá trị của ô lượt đổi để chúng ta có nhiều lượt đổi hơn.

Hi, giờ mình sẽ nghĩ ra 1 trò chơi mới với cái ô địa chỉ điểm này.
Mình sẽ làm cho mỗi khi không còn con nào ăn trên bản đồ, chương trình sẽ đổi sang bàn mới, nhưng không bị trừ lượt đổi nào cả.
Hehe, làm thế này thì dù bạn chỉ còn 1 lượt đổi thì cũng chẳng bao giờ bị hết cả.
Bắt tay vào làm nên hạnh phúc nào!

Trước tiên tìm hiểu kỹ về "kẻ địch" một chút:
địa chỉ ô lượt đổi là: pLife=0x004B60AA;
giá trị tại ô lượt đổi là 1 số nguyên có dấu 2byte, vậy ta có thể set giá trị tối đa cho lượt đổi là 2^(16-1) = 32.768;
Mỗi lần hết con ăn, chương trình sẽ chuyển sang bàn mới và trừ vào lượt đổi 1 lần.

Tình hình đoạn code sẽ có dạng thế này:
Code:
Hết con ăn, đổi sang bàn mới:     Khởi tạo lại bản đồ mới     Trừ 1 lần vào biến đổi     ... Kết thúc
Vào onnlydbg, bấm nút home về đầu, ctrl+b, vào ô hex và gõ: AA604B00, chọn forward, Search
Lần này có vẻ vất vả quá, bấm Search tận 9 lần mình mới thấy chỗ này:


Code:
MOV AX,WORD PTR DS:[4B60AA]    //Nó sẽ chuyển giá trị của biến lượt đổi vào thanh ghi AX (vì lượt đổi chỉ có 2 byte) XOR ECX,ECX PUSH EBX DEC AX        //Trừ thanh ghi AX đi 1 ..... MOV WORD PTR DS:[4B60AA],AX //Lưu lại giá trị thanh ghi AX vào địa chỉ 4B60AA
Hihi, các bạn biết chúng ta phải làm gì rồi chứ?
Ở chỗ DEC AX, chúng ta sẽ sửa lại thành NOP, NOP hết (tức là chương trình sẽ chẳng làm gì hết).
Vậy là chẳng có cái gì bị thay đổi cả hehe.

Code:
DEC AX có mã hex là 0x4866 NOP NOP có mã hex là 0x9090
Start Code:
Tới phần khai báo các pointer và thêm dòng này:
Code:
const int pLifeSub=0x004B0FB8;
Tới phần khai báo biến:
Code:
static unsigned short int vFirst=0x4866; static unsigned short int vChange=0x9090;
Tới phần "Sau này sẽ viết thêm code vô hạn lượt đổi vào chỗ này":
Code:
if (cUltimateLifeStatus==0){     WriteProcessMemory(hProcess, (int *)pLifeSub, &vChange, sizeof(vChange), NULL);     SetWindowText(hwndBtnUltimateLife, TEXT("Vo han luot doi *")); } else{     WriteProcessMemory(hProcess, (int *)pLifeSub, &vFirst, sizeof(vFirst), NULL);     SetWindowText(hwndBtnFrozenTime, TEXT("Vo han luot doi")); } cUltimateLifeStatus=1-cUltimateLifeStatus;
Xong, phần tiếp theo...

Phần 5. Ăn 1 con win luôn (chỉ có tác dụng trong 1 cửa):

Mở pikachu lên, các bạn thấy ngay pikachu có một bản đồ gồm 9 hàng và 16 cột.
Suy ra tổng cộng có tất cả 9*16=144 hình quái vật.
Suy ra biến lưu số lượng quái vật có khả năng sẽ là byte.
Mở artMoney lên, Search kiểu 1 byte giá trị 144.
Vào pikachu ăn 2 con, rồi ra ArtMoney scan 142.
Tiếp theo ăn 2 con nữa, rồi ra ArtMoney scan 140.
....
Làm 2~3 lần các bạn sẽ có được địa chỉ số lượng con quái còn trên màn hình: pNumber=0x004B6078;
Tới đây các bạn chỉ cần set giá trị tại ô nhớ pNumber thành 2, rồi ăn 1 con nữa là sẽ Win luôn.
Nhưng làm như thế này, nó sẽ chỉ có tác dụng trong 1 màn đang chơi.
Nếu đổi sang màn sau, lại phải chỉnh giá trị tại pNumber thành 2 thì mới có tác dụng.
Mình muốn khi nào tắt đi thì nó mới hết cơ...

Cần phải tìm ra gốc rễ của vấn đề thôi.

Phần 6. Ăn 1 con win luôn (khi nào tắt thì mới hết):


Khi vào 1 màn chơi mới hoặc khi bạn qua cửa, giá trị tại địa chỉ pNumber sẽ được gán bằng 144.
Vậy ta cần phải tìm ra nơi chứa con số 144 đó, và sửa nó lại thành số 2.
Vậy là bất cứ khi nào ta bắt đầu trò chơi mới, hoặc khi qua cửa thì giá trị tại địa chỉ
pNumber sẽ tự được gán bằng 2, và ta chỉ cần ăn 1 con là Win luôn.

Vào OnllyDbg, Home, Ctrl+B, gõ vào ô Hex: 78604B00, Search.
Ối dời ơi, mới Search có 1 phát đã thấy luôn cái này:


Code:
MOV WORD PTR DS:[4B6078],90
90 trọng hệ 16 đổi sang hệ 10 vừa bằng 144
quá đẹp, ta chỉ cẩn sửa con số 90 này thành số 2 là ok!

Bắt tay vào viết code Ăn 1 con win luôn!

Thêm cái này vào chỗ khai báo pointer:
Code:
const int pNumber=0x004B6078; const int pNumberConst=0x004A8866;
Thêm cái này vào chỗ khai báo biến:
Code:
static unsigned char cNumber; static unsigned char cNumberConst;
Tới chỗ: "Sau này sẽ viết thêm code ăn 1 con win luôn vào chỗ này"
Code:
if (cWinStatus==0){     cNumber=2;     WriteProcessMemory(hProcess, (int *)(pNumber), &cNumber, 1, NULL);     cNumberConst=2;     WriteProcessMemory(hProcess, (int *)(pNumberConst+7), &cNumberConst, 1, NULL);     SetWindowText(hwndBtnWin, TEXT("An 1 con Win luon *")); } else{     cNumberConst=144;     WriteProcessMemory(hProcess, (int *)(pNumberConst+7), &cNumberConst, 1, NULL);     SetWindowText(hwndBtnWin, TEXT("An 1 con Win luon")); } cWinStatus=1-cWinStatus;
Vậy là hôm nay mình đã hướng dẫn các bạn làm 6 phần đầu tiên của Tut Trainer Pikachu.
Còn 3 phần nữa khá dài và khó hơn 6 phần đầu 1 chút nên mấy hôm nữa rảnh mình sẽ post tiếp.
Chúc các bạn vui vẻ!

Upload luôn file code, nhé.


PHP Code:
#include
#include

#define BTN_FROZENTIME 1
#define BTN_POINTEAT 2
#define BTN_ULTIMATELIFE 3
#define BTN_WIN 4
#define BTN_SAME 5
#define BTN_CHEAT 6
#define BTN_AUTO 7
#define RAD_STATUSAUTOSINGLE 8
#define RAD_STATUSAUTOALL 9


//Khai bao ham
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//Sau này s? vi?t thêm code khai báo hàm vào ch? này

//Khai bao dia chi cac pointer
const int pFrozenTime=0x004B02DF;
const
int pPointEat=0x0040105C;
const
int pLifeSub=0x004B0FB8;

//Sau này s? vi?t thêm code khai báo pointer vào ch? này

//Gia tri tai cac pointer
//Sau này s? vi?t thêm code khai báo giá tr? pointer vào ch? này

//Khai bao cac bien

static unsigned char arrUnFrozenTime[6]={0xd9, 0x1d, 0x84, 0x60, 0x4b, 0x00};
static
unsigned char arrFrozenTime[6]={0xd9, 0x9d, 0x78, 0xff, 0xff, 0xff};
static
float fPointEat;
static
unsigned short int vFirst=0x4866;
static
unsigned short int vChange=0x9090;

//Sau này s? vi?t thêm code khai bao bi?n vào ch? này


//Cac thong tin ve cua so Pikachu
static HANDLE hwin, hProcess;
static
DWORD pid;
//Sau này s? vi?t thêm code khai báo thông tin c?a s? pikachu vào ch? này


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow)
{
static
TCHAR szAppName[]=TEXT("Pikachu Trainer");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;

wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;

if (!
RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT"), szAppName, MB_ICONERROR);
return
0;
}


hwnd=CreateWindow(szAppName, TEXT("Pikachu Trainer"),
WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
198,
350,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);

while (
GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return
msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;

static
int cxChar, cyChar;

static
HWND hwndBtnFrozenTime, hwndBtnPointEat, hwndBtnUltimateLife, hwndBtnWin, hwndBtnCheat,
hwndBtnSame, hwndRadStatusAutoSingle, hwndRadStatusAutoAll, hwndBtnAuto;

static
char cPointEatStatus, cFrozenTimeStatus, cUltimateLifeStatus, cWinStatus, cAutoStatus;

TCHAR t[100];

HWND h;


switch(
message)
{
case
WM_CREATE:
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;


cFrozenTimeStatus=0;
hwndBtnFrozenTime = CreateWindow (TEXT("button"),
TEXT("Dong bang thoi gian"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*1,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_FROZENTIME,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);


cPointEatStatus=0;
hwndBtnPointEat = CreateWindow (TEXT("button"),
TEXT("100 diem/1 lan an"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*3,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_POINTEAT,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);


cUltimateLifeStatus=0;
hwndBtnUltimateLife = CreateWindow (TEXT("button"),
TEXT("Vo han luot doi"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*5,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_ULTIMATELIFE,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);

cWinStatus=0;
hwndBtnWin = CreateWindow (TEXT("button"),
TEXT("An 1 con Win luon"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*7,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_WIN,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);

hwndBtnSame = CreateWindow (TEXT("button"),
TEXT("An lung tung"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*9,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_SAME,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);


hwndBtnCheat = CreateWindow (TEXT("button"),
TEXT("Tim 2 con an"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*11,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_CHEAT,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);


hwndBtnAuto = CreateWindow (TEXT("button"),
TEXT("Auto Pikachu"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar, cyChar*13,
22 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) BTN_AUTO,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);

hwndRadStatusAutoSingle = CreateWindow (TEXT("button"),
TEXT("Single"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
cxChar, cyChar*15,
10* cxChar, 7* cyChar / 4,
hwnd, (HMENU) RAD_STATUSAUTOSINGLE,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);
SendMessage(hwndRadStatusAutoSingle, BM_SETCHECK, 1, 0);
cAutoStatus=0;

hwndRadStatusAutoAll = CreateWindow (TEXT("button"),
TEXT("All"),
WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
12*cxChar, cyChar*15,
10 * cxChar, 7 * cyChar / 4,
hwnd, (HMENU) RAD_STATUSAUTOALL,
((
LPCREATESTRUCT) lParam)->hInstance, NULL);

//Find Window Pikachu
hwin=FindWindow(TEXT("ThunderRT5Form"), TEXT("³s³s¬Ý2"));
if (
hwin==NULL){
MessageBox(NULL, TEXT("Ban phai bat pikachu len da."), TEXT("Error"), 0);
SendMessage(hwnd, WM_CLOSE, 16, 1);
return
0;
}

//Open Process Pikachu
GetWindowThreadProcessId(hwin, &pid);
hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

//Find Client
//Sau này s? vi?t thêm code vào ch? này


//Init some value
//Sau này s? vi?t thêm code kh?i t?o 1 s? giá tr? vào ch? này


return 0;

case
WM_PAINT:
hdc=BeginPaint(hwnd, &ps);


wsprintf(t, TEXT("Made by langman, puss"));
TextOut(hdc, cxChar, cyChar*18, t, wcslen(t));

EndPaint(hwnd, &ps);
return
0;

case
WM_COMMAND:
switch(
LOWORD(wParam)){
case
BTN_FROZENTIME:
//Sau này s? vi?t thêm code dóng bang vào ch? này
if (cFrozenTimeStatus==0){
WriteProcessMemory(hProcess, (int *)pFrozenTime, arrFrozenTime, 6*sizeof(char), NULL);
SetWindowText(hwndBtnFrozenTime, TEXT("Dong bang thoi gian *"));
}
else{
WriteProcessMemory(hProcess, (int *)pFrozenTime, arrUnFrozenTime, 6*sizeof(char), NULL);
SetWindowText(hwndBtnFrozenTime, TEXT("Dong bang thoi gian"));
}
cFrozenTimeStatus=1-cFrozenTimeStatus;
break;
case
BTN_POINTEAT:
//Sau này s? vi?t thêm code an 100 di?m / 1 l?n vào ch? này
if (cPointEatStatus==0){
fPointEat=-100;
SetWindowText(hwndBtnPointEat, TEXT("100 diem/1 lan an *"));
}
else{
fPointEat=-20;
SetWindowText(hwndBtnPointEat, TEXT("100 diem/1 lan an"));
}

cPointEatStatus=1-cPointEatStatus;
WriteProcessMemory(hProcess, (int *)pPointEat, &fPointEat, sizeof(float), NULL);

break;

case
BTN_ULTIMATELIFE:
//Sau này s? vi?t thêm code vô h?n lu?t d?i vào ch? này
if (cUltimateLifeStatus==0){
WriteProcessMemory(hProcess, (int *)pLifeSub, &vChange, sizeof(vChange), NULL);
SetWindowText(hwndBtnUltimateLife, TEXT("Vo han luot doi *"));
}
else{
WriteProcessMemory(hProcess, (int *)pLifeSub, &vFirst, sizeof(vFirst), NULL);
SetWindowText(hwndBtnFrozenTime, TEXT("Vo han luot doi"));
}
cUltimateLifeStatus=1-cUltimateLifeStatus;


break;

case
BTN_WIN:
//Sau này s? vi?t thêm code an 1 con win luôn vào ch? này

break;

case
BTN_SAME:
//Sau này s? vi?t thêm code an 2 con khác nhau vào ch? này

break;

case
BTN_CHEAT:
//Sau này s? vi?t thêm code tìm 2 con an vào ch? này

break;
case
BTN_AUTO:
//Sau này s? vi?t thêm code auto choi pikachu vào ch? này
break;
case
RAD_STATUSAUTOSINGLE:
cAutoStatus=0;
break;
case
RAD_STATUSAUTOALL:
cAutoStatus=1;
break;
}
return
0;

case
WM_DESTROY:
PostQuitMessage(0);
return
0;
}

return
DefWindowProc(hwnd, message, wParam, lParam);
}