Jump to content

Mu Moi ra - Vina MU

Cộng đồng Âm nhạc Việt Nam

Photo

Hướng dẫn lập chương trình AutoPlay VLTK

* * * * * 1 votes

  • This topic is locked This topic is locked
630 replies to this topic

#1
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Đáp ứng lòng mong mỏi của các bạn tôi xin viết bài này để tổng hợp lại các đoạn code và hướng dẫn các bạn viết một phần mềm tự chơi hoàn chỉnh.

Tôi sẽ lần chia bài viết thành từng phần theo thứ tự như sau:

Bài 1 – Lấy các thông tin cơ bản về nhân vật và tự BUFF máu, mana
Bài 2 – Lấy thông tin về tọa độ nhân vật, tự tìm quái đánh, tự nhặt đồ
Bài 3 – Điều khiển nhân vật chạy

Ở đây không bàn đến việc dùng kỹ thuật đồ họa và chiếm chuột để điều khiển nhân vật. Các phần mềm hiện nay thường dùng chương trình chính Autoplay thực hiện việc đọc bộ nhớ Game lấy thông tin và dùng cơ chế Hook để ghi thông tin cần thay đổi vào bộ nhớ Game. Một điểm lưu ý là khi Hook sẽ chiếm tài nguyên, nên ta có thể dùng một mẹo nhỏ, sau khi Hook ta Unhook ngay lập tức và dùng LoadLibrary để nạp hook.dll vào bộ nhớ game, thay đổi địa chỉ WndProc để thực hiện nhiều ý đồ khác.
(Các bạn có thể tham khảo bài viêt sau để biết cách dùng Hook và mẹo này: http://www.codeproje...eads/winspy.asp). Ngoài ra, để chương trình có thêm nhiều chức năng, có thể ta sẽ phải gọi các hàm trong game_y.exe và khi đó ta phải mở rộng cái Hook.dll để có thể hook + inject code vào Game process (sẽ nói trong bài 3).

Bài 1 - Lấy các thông tin cơ bản về nhân vật và tự BUFF máu, mana
Tất cả các nhân vật (người chơi, quái, Npc...) được lưu thông tin trong mảng gồm 256 đối tượng, mỗi đối tượng kích thước 0x7E4C, địa chỉ lưu địa chỉ của mảng trên là 0x00D3A570. Đối tượng 0 để trống, đối tượng 1 là người chơi, còn lại là quái & Npc.
Khi chưa dùng cơ chế inject code nói trên ta có thể đọc bộ nhớ của Game bằng hàm ReadProcessMemory. Dưới đây là minh họa lớp đối tượng Npc và một số biến thành viên cần dùng (phần ... là phần dữ liệu chưa dùng tới, các bạn phải đặt một mảng BYTE với kích thước tương ứng vào đó để các địa chỉ OFFSET của các biến được chính xác)

#define 	NPC_BASE_ADD	0x00D3A570
#define 	NPC_DATA_SIZE	0x00007E4C
#define	MAX_NPC		256
#define 	PLAYER_INDEX	1

class CNpc
{
	...
	DWORD		m_NpcKind;	//0x0020 1=mod, 1=player,...
	...
	DWORD		m_Doing;	//0x00EC 1=stand, 2=walk, 3=run...
	...
	int		m_CurLife;	//0x0B44
	int		m_CurLifeMax;
	int		m_CurLifeRep;
	int		m_CurMana;
	int		m_CurManaMax;
	...
	BOOL		m_bRideHorse;	//0x0D58
	char		Name[32];		//0x0D5C Ten nhan vat
	int		m_nSex;
	...
	BOOL		m_FightMode;	//0x0EAC
	
};

// Tim cua so va xac dinh Game Process Handle o day
...
CNpc Npc;
LPBYTE lpBaseAdd, lpCurAdd;
//Read start Address of Npc Array
ReadProcessMemory(m_hVLProcess, (LPBYTE)NPC_BASE_ADD, (LPVOID)&lpBaseAdd, 4, NULL);
//Start Address of PLAYER
lpCurAdd = lpBaseAdd + PLAYER_INDEX*NPC_DATA_SIZE;
//Read PLAYER ìnormation
ReadProcessMemory(m_hVLProcess, lpCurAdd, (LPVOID)&Npc, sizeof(CNpc), NULL);
...

Khi đọc được các thông số máu và mana rồi ta có thể dùng hàm PostMessage(hWnd, WM_KEYDOWN...) để gửi phím 1, 2, 3. Các bạn thấy ở trên có 1 biến m_FightMode dùng để xác định nhân vật đang ở chế độ đánh (ở bản đồ có quái) hoặc đang ở trong thành (không dùng chiêu được). Căn cứ vào đó ta có thể gửi phím 1, 2, 3 khi cần thiết (m_FightMode=TRUE). Nếu nhân vật về thành rồi khỏi bơm máu nữa (nhiều khi dính độc về cả phút mà cứ đứng trong thành bơm máu thì phí quá).

Linh tinh khác: Game VLTK có định nghĩa một số hàm macro có thể dùng ở dòng gõ CHAT, ví dụ:
“/Switch Horse”, “/Switch Sit”, “/SayPhrase 0”, , “/SayPhrase 1” các bạn thử mà xem, cũng thũ vị lắm. Các bạn mở file UIconfig.ini sẽ thấy nhiều hàm hơn. Dưới đây là đoạn code mà có thể thêm vào chương trình của mình dùng để chat hoặc chạy một hàm macro trong Game. Bạn có thể lập trình lên xuống ngựa hay ngồi xuống, đứng lên, ... mà ko phải dùng WM_KEYDOWN gửi phím tắt V, M (vì ở chế độ phím Mặc định, nhấn V sẽ ko ngồi đâu).

void PostChatMessage(LPCTSTR szChatMsg)
{
	//Set focus to CHAT edit control
	::PostMessage(m_hVLWin, WM_KEYDOWN, VK_RETURN, 0x001C0001);
	//Clear CHAT edit control
	::PostMessage(m_hVLWin, WM_KEYDOWN, VK_DOWN, 0x00500001);
	while (szChatMsg[0])
	{
		::PostMessage(m_hVLWin, WM_CHAR, LOBYTE(szChatMsg[0]), 0);
		szChatMsg++;
	}
	//Set focus to Game Window
	::PostMessage(m_hVLWin, WM_KEYDOWN, VK_RETURN, 0x001C0001);
}

Đến đây các bạn có thể lập được một chương trình tự buff mana, ngồi rao bán hàng rồi đấy. Ở bài 2 tôi sẽ nói về cách xác định tọa độ nhân vật (cũng giống như của các Npc khác) và đồ. Địa chỉ OFFSET tọa độ của nhân vật & Npc không phải là 0x10F8 như các bạn tưởng đâu, đó là địa chỉ đích Npc sẽ chạy tới, sẽ đánh tới... nếu nhân vật ngồi xuống, giá trị này sẽ bằng 0.

Edited by ngocnl, 19 April 2006 - 10:56 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#2
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Bài 2 – Lấy thông tin về tọa độ nhân vật, tự tìm quái đánh, tự nhặt đồ

Hix, được các bác admin quan tâm, em lại viết tiếp.
Bây giờ đến phần toạ độ của nhân vật. Bổ sung thêm các biến thành viên vào lớp CNpc, chúng ta có các thông tin về toạ độ và thông tin đối tượng cần đánh/ theo sau/ đồ cần nhặt:

class CNpc
{
public:
	...
	int	m_NextAdd;	//0x000C – xac dinh Npc ton tai hay ko
	...
	int	m_ActiveSkill;	//0x0114 – ky nang dang su dung
	...
	int	m_MapX, m_MapY, m_MapZ;	//0x0D0C – toa do Cell
	int	m_OffX, m_OffY;		//0x0D18 – toa do Npc trong Cell (*1024)
	...
	int	m_nPeopleIdx;	//0x0DE0 Npc can tan cong, hoac theo sau
	...
	int	m_nObjectIdx;	//0x0DEC Obj can nhat
	...
	WORD	m_RegX;		//0x0EC4 – toa do Region
	WORD	m_RegY;
public:
	void GetMapPos(int *nX, int *nY);
};

Toàn bàn đồ được chia thành nhiều vùng, có kích thước 512x1024, mỗi vùng lại chia thành nhiều cell, có kích thước là 32x32. Hai biến WORD RegX, RegY lưu giá trị vùng (Region), các biến MapX, MapY lưu giá trị của cell; OffX,OffY là toạ độ Npc trong ô đó (giá trị = 1024/pixel).

Toạ độ của nhân vật được tính như sau:

#define REGION_WIDTH	512
#define REGION_HEIGHT	1024
#define CELL_WIDTH		32
#define CELL_HEIGHT		32

void CNpc::GetMapPos(int *nX, int *nY)
{
	*nX = m_RegX*REGION_WIDTH + m_MapX*CELL_WIDTH + (m_OffX>>10);
	*nY = m_RegY*REGION_HEIGHT + m_MapY*CELL_HEIGHT + (m_OffY>>10);
}

Hàm sẽ trả về nX, nY giá trị toạ độ tuyệt đối của nhân vật/ Npc trên bản đồ, tính theo pixel (không phải toạ độ vẫn thường nói trong GAME đâu). Còn toạ độ trong Game (thể hiện trên bản đồ nhỏ) sẽ được tính bằng:

nOrgX = nX>>8; // dich phai 8 bit, chia cho 256
nOrgY = nY>>9; // dich phai 9 bit, chia cho 512

Đến đây các bạn có thể xác định được toạ độ của nhân vật cũng như của Npc bất kỳ trong mảng 256 Npc rồi, và do đó sẽ xác định được khoảng các giữa chúng. Vấn đề là khi quái bị chết, không phải tất cả dữ liệu trong đối tượng bị xoá, trừ khi có quái hoặc player khác được nạp vào vùng nhớ đó. Tôi có thấy 1 địa chỉ ở OFFSET 0x000C, tạm đặt tên biến là m_NextAdd vì thấy nó lưu các địa chỉ quanh quanh trong mảng 256 Npc, khi quái chết, hoặc ra khỏi vùng nhớ (đi ra xa), giá trị m_NextAdd được đặt về 0.

Vậy thuật toán đơn giản để tìm quái để tấn công sẽ như sau:

CNpc Player; Npc;
int nX, nY;
int nMinIndex, nMinDistance=2000;
//Read PLAYER information
lpCurAdd = lpBaseAdd + NPC_DATA_SIZE;
ReadProcessMemory(m_hVLProcess, lpCurAdd, (LPVOID)&Player, sizeof(CNpc), NULL);
for (int i=2; i<MAX_NPC; i++)
{
	//Read NPC information
	lpCurAdd = lpBaseAdd + i*NPC_DATA_SIZE;
	ReadProcessMemory(m_hVLProcess, lpCurAdd, (LPVOID)&Npc, sizeof(CNpc), NULL);
	if (!Npc.m_NextAdd) continue; //  Npc does not exist
	if (Npc.m_CurLife<=0 || Npc.m_NpcKind != 0) continue;
	//Xac dinh toa do quai
	Npc.GetMapPos(int &nX, &nY);
	//Tinh khoang cach den nhan vat
	int nDistance = ...
	//Kiem tra xem khoang cach la nho nhat de tan cong truoc
	if (nDistance<=nMinDistance)
	{
		nMinDistance = nDistance;
		nMinIndex = i;
	}
}
//Player.m_nPeopleIdx = nMinIndex;	// Tan cong quai o gan nhat
SendMessage(WM_HOOK_WRITE,...);	// Ghi gia tri vao bo nho Game thong qua Hook

Vòng for trên tôi viết đơn giản hoá để dễ hiểu, các bạn có thể viết thêm các chức năng kiểm tra lag (sau khi đánh một lúc mà quái ko mất máu thì đổi con khác). Có 1 lưu ý nhỏ ở đây là khi máu quái = 0 nó vẫn sống, < 0 nó mới chết nên trong việc kiểm tra đánh quái, các bạn đánh đến khi máu < 0 thì mới search tiếp con khác. Đó là việc ở trước vòng for này, còn trong vòng for ở trên vì sao tôi vẫn kiểm tra Npc.m_CurLife<=0 thì bỏ qua Npc, các bạn có thể tự tìm hiểu nhé.

phù... khuya quá rồi, mai tôi sẽ viết tiếp bài 2.

Edited by ngocnl, 20 April 2006 - 04:02 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#3
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts

Quote

XIN MOD ĐỪNG XÓA BÀI NÀY NHÉ !!!

Ban ngocnl ơi cho mình hỏi nè : các tọa độ ở địa chì 0x0D0C, 0x0D18, 0x0EC4 có kích thước bao nhiêu byte?? Đọc được chỉ có 1 số thì làm sao để tách ra thành x và y riêng rẻ nè ??? Bạn làm ơn giải thích rõ rõ tí nhé.

Ở đây tôi dùng Class để đọc toàn bộ dữ liệu của Npc cho nhanh, ko phải đọc giá trị từng địa chỉ Offset riêng lẻ. Tuy nhiên nếu bạn đọc lại khai báo Class CNpc bạn sẽ thấy các biến đó có kiểu int, tức là 4 bytes.

Dòng khai báo:
int	m_MapX; m_MapY, m_MapZ;	//0x0D0C – toa do Cell
có nghĩa là 3 biến int liền nhau, biến đầu tiên ở địa chỉ OFFSET 0x0D0C. Ở trên có một lỗi typo nhỏ, các bạn thay dấu ( ; ) ở sau m_MapX thành dấu ( , ) nhé.

Edited by ngocnl, 20 April 2006 - 02:24 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#4
MyNickName

MyNickName

    Thành viên mới

  • Advance Member
  • 30 posts
Bài viết hay lắm =))
Viết nhanh qua phần di chuyển đê, mình đang mắc ở đó.
Sét cách thức di chuyển: = 3(chạy) vào địa chỉ 0x0EC
Sét giá trị được tính ra từ tốc độ di chuyển: =[0x1070]*[0xe40]/[0xc40]
vào địa chỉ 0x0F4
Sét giá trị 5 vào địa chỉ 0x0f0.
Tọa độ cần di chuyển tới vào địa chỉ: 0xd20 và 0xd24

Nhân vật di chuyển ngon lành, nhưng nếu di chuyển quá 1 phạm vi (khỏang 512 thì nhân vật ngay lập tức bị kéo trả về chỗ cũ).
Chắc tại sét thiếu một giá trị nào đó nữa =))

#5
hiepsi

hiepsi

    Căn bản tin học tốt

  • Advance Member
  • Pip
  • 47 posts

Quote

Ở đây tôi dùng Class để đọc toàn bộ dữ liệu của Npc cho nhanh, ko phải đọc giá trị từng địa chỉ Offset riêng lẻ. Tuy nhiên nếu bạn đọc lại khai báo Class CNpc bạn sẽ thấy các biến đó có kiểu int, tức là 4 bytes.
Dòng khai báo:

int	m_MapX; m_MapY, m_MapZ;	//0x0D0C – toa do Cell
có nghĩa là 3 biến int liền nhau, biến đầu tiên ở địa chỉ OFFSET 0x0D0C. Ở trên có một lỗi typo nhỏ, các bạn thay dấu ( ; ) ở sau m_MapX thành dấu ( , ) nhé.


Cảm ơn bạn nhiều nhé. Nhưng mà sao tui vẫn không làm cho nó đi theo sau được. Không bít là tại vì sai địa chỉ mem hay là tại vì không write vào mem được. Nếu được bạn chỉ tui cách write vào mem nhé. Mấy cái vụ hook tui chẳng hiểu gì cả nên phải sử dụng hàm WriteProcessMemory vì vậy không bít là có write vào mem được hay k nữa hic hic hic. Làm ơn giúp tui với.

Edited by hoahongtim, 20 April 2006 - 04:09 PM.


#6
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Bài 2 – Lấy thông tin về tọa độ nhân vật, tự tìm quái đánh, tự nhặt đồ (tiếp theo)

Nào, em mới đi làm về, ăn xong lại ngồi vào viết bài cho mọi người đây. =))

Có một số thắc mắc trên diễn đàn về việc dùng hàm WriteProcessMemory để gán giá trị. Theo tôi là không được vì sẽ có tranh chấp vùng nhớ. Chúng ta phải dùng cơ chế hook để ghi giá trị vào bộ nhớ của Game. Các bạn có thể tham khảo thêm hook.dll của bạn TinhLaGi trong bài viết này nhé. ...

Bài viết của TinhLaGi: http://cuasotinhoc.c...opic=6706&st=20
Và file đính kèm: HookLib

Khi các bạn đã có thể lấy toạ độ quái thì nên chọn thuật toán đánh quái ở gần trước. Theo tôi mình ko nên chọn phương pháp đánh quái ít máu trước vì sẽ bị KS hết điểm kn và nhân vật phải chạy tới chạy lui tít xa, không tối ưu.

Tiếp theo ta sẽ nghiên cứu mảng lưu thông tin đồ rớt ra. Mảng này gồm 256 đối tượng, nằm bắt đầu ở địa chỉ tĩnh 0x00DC2750, kích thước mỗi đối tượng là 0x03C4. Ta chỉ cần lấy phần dữ liệu ở đầu đối tượng và định nghĩa thành lớp CObj của chúng ta như dưới đây.

class CObj		//dung nham lan voi CObject cua VC++ day nhe
{
public:
	int		m_nID;	// -1 la do ko ton tai, > 0 la ton tai
	int		m_nData1;	// Unused data
	int		m_ObjKind;	// 3=item, 4=money,..10=Property Box
	int		m_Index;
	WORD		m_RegX, m_RegY;	// Toa do Region
	int		m_nData2[2];	// Unused data
	int		m_MapX, m_MapY;	// 0x001C, toa do Cell
	int		m_OffX, m_OffY;	// 0x0024, toa do Off trong Cell
	int		m_nData3[13];	// Unused data
	char		m_szName[32];	// 0x0060
	int		m_nData4;	// Unused data
	int		m_nColor;	// Mau cua do (0=trang, 3=xanh, ?=vang...)
	int		m_nData5[3];	// Unused data
	int		m_nMoneyNum;	// Luong tien
public:
	void GetMapPos(int *nX, int *nY);
};

Chặc, đến đây các bạn lại thấy quá dễ để tính tọa độ của đồ rồi đúng ko, cũng theo cách tính như ở CNpc thôi. Nhặt đồ thì dễ hơn đánh quái nhiều, tìm cái đồ nào ở gần thì nhặt. Khoảng cách có thể nhặt đô trong Game đặt là 64, nhưng nếu cần các bạn cứ tìm trong khoảng 200-300 gì đó, nhân vật chỉ cần nhích đi một chút là nhặt được đồ. Các bạn còn nhớ cái biến thành viên m_nObjectIdx trong lớp CNpc ko? Nó sẽ xác định địa chỉ cần gán cho đối tượng người chơi để nhặt đồ (cũng theo vị trí của đồ trong mảng 256 đối tượng kia)

Bổ sung: Lần đầu tiên khi nhân vật bắt đầu đánh, các bạn phải gán chiêu thức vào m_ActiveSkill ở OFFSET 0x0114 nhé (tham khảo thêm bài viết của TinhLaGi). Ngoài ra ở phần trên tôi có bỏ sót một biến thành viên tại địa chỉ Offset 0x0C58, đó là m_nSkillRadius - bán kính hiệu quả của chiêu thức. Trước khi gán lệnh đánh, bạn gán giá trị này một số nhỏ, ví dụ 75 chẳng hạn là bán kính quyền cơ bản, nhân vật sẽ tiếp sát rồi mới đánh quái. Nếu ko để chế độ đánh tiếp cận, sau khi đánh 1 chiêu có bán kính hiệu quả = 0 (ví dụ NLTD), các bạn lại phải gán lại số này đủ lớn, nếu ko nhân vật sẽ chạy lại sát quái mà vẫn ko với tay đánh được. Có thể gán = 75 hoặc thậm chí = 5000, game sẽ tự reset lại.

Thêm nữa, phần đọc tọa độ của nhân vật, Npc & Obj có một số bạn dùng địa chỉ offset 0x0D20, 0x1088.. gì đó. Thực ra các địa chỉ này chỉ là kết quả của các tính toán hoặc gán tham số tọa độ cho các thao tác của nhân vật nên đôi khi mình đọc ra sẽ thu được một kết quả không chính xác.

Bài viết tiếp theo tôi sẽ đề cập đến việc điều khiển nhân vật chạy đến một tọa độ cho trước.

Hết bài 2.

Edited by ngocnl, 21 April 2006 - 08:32 AM.

VLAuto website: http://vlauto.net
Email: [email protected]

#7
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Bài 3 – Điều khiển nhân vật chạy

Nào hôm nay chúng ta sẽ nghiên cứu đến cái việc điều khiển quái chạy. Dưới đây là các biến thành viên bổ sung cho lớp CNpc:
class CNpc
{
public:

	...
	int		CmdKind;	//0x1088, 2=walk, 3=run
	int		Param_X;
	int		Param_Y;
};
Để cho nhân vật chạy hoặc đi bộ đến 1 điểm nào đó, các bạn gán các giá trị thích hợp vào các địa chỉ trên, bao gồm loại lệnh (chạy, đi bộ) và tọa độ X, Y.

SendMessage(WM_HOOK_WRITE, ...3);
SendMessage(WM_HOOK_WRITE, ...nX);
SendMessage(WM_HOOK_WRITE, ...nY);

Tuy nhiên, công việc ko chỉ dừng lại ở đó, nếu ko nhân vật sẽ tự giật lại vị trí cũ. Bước tiếp theo là chúng ta phải gửi một gói tin đến server, báo rằng nhân vật di chuyển đến tọa độ mới. Như các bạn biết, đôi khi mạng lag, ta điều khiển nhân vật chạy được một đoạn nó lại giật lại chỗ cũ là vì gói tin báo đã ko gửi đi được.

Để làm được việc đó ta sẽ viết code gọi hàm gửi tin đến server. Sau khi nghiên cứu, tôi đã tìm được địa chỉ các hàm gửi lệnh RUN và hàm gửi lệnh WALK trong game_y.exe. Cũng may là mấy hàm này ko viết trong Class nên việc gọi cũng đỡ cực hơn. Trong chương trình HookDll, các bạn bổ sung các đoạn code sau:

//Global Functions
void (*SendCmdRunToServer)(int, int);
void (*SendCmdWalkToServer)(int, int);

#define RUN_FUNC_ADD	0x004C41B7	// Send Client DoRun Function
#define WLK_FUNC_ADD	0x004C4204	// Send Client DoWalk Function

Và khởi tạo các địa chỉ hàm SendCmdRunToServer & hàm SendCmdWalkToServer bằng cách chèn đoạn code sau vào vị trí nào thích hợp (nhớ rằng chúng ta phải thực hiện việc này trong HookProc, tức là đang ở trong Process của Game. Việc gán trực tiếp bằng toán tử gán ( = ) sẽ ko thực hiện được vì VC++ sẽ báo lỗi nên ta dùng đoạn mã ASM.

__asm
{
	mov SendCmdRunToServer, RUN_FUNC_ADD;
	mov SendCmdWalkToServer, WLK_FUNC_ADD;
}

Đến đây chúng ta đã hoàn tất 90% công việc rồi, quay trở lại phần code của chương trình chính, sau khi ra đã gán các giá trị CmdKind, Param_X, Param_Y ta phải gửi một thông điệp WM_HOOK_WRITE nữa để báo HookProc chạy hàm SendCmdRunToServer hoặc SendCmdWalkToServer.

Đoạn mã đó như sau:
//SendMessage(m_hVLWindow, WM_HOOK_WRITE, 2, 0); // Send Walk Cmd
SendMessage(m_hVLWindow, WM_HOOK_WRITE, 3, 0); // Send Run Cmd

Còn ở HookProc, các bạn cải tiến một chút như dưới đây thì ta sẽ có được đoạn gửi lệnh RUN, WALK lên Server.

#define pCW ((CWPSTRUCT*)lParam)
LRESULT HookProc (int nCode, WPARAM wParam, LPARAM lParam)
{
	int nAdd = pCW->wParam;
	int nVal = pCW->lParam;
	int *pX, *pY;
	switch (nAdd)
	{
	case 2:		// DO WALK
		pX = (int*)(PlayerBaseAdd + 0x108C);
		pY = (int*)(PlayerBaseAdd + 0x1090);
		SendCmdWalkToServer(*pX, *pY);
		break;
	case 3:		// DO RUN
		pX = (int*)(PlayerBaseAdd + 0x108C);
		pY = (int*)(PlayerBaseAdd + 0x1090);
		SendCmdRunToServer(*pX, *pY);
		break;
	default:		// ASSIGN OTHER VALUES 
		pX = (int*)nAdd;
		*pX = nVal;
	}
}

Kết thúc loạt bài về viết chương trình AutoPlay. Từ đây các bạn có thể cải tiến chương trình theo ý thích của mình, làm bao nhiêu chức năng tùy ý. Và từ sau bài này các bạn vào trao đổi và có cao kiến hay thắc mắc gì cứ nêu ra chúng ta cùng bàn luận nhé. Các đoạn code trên có nhiều chỗ tôi gõ trực tiếp lên đây (ko phải copy từ chương trình ra vì chỉ cần lấy phần cơ bản cho dễ hiểu) nên đôi khi gõ tắt hoặc gõ lỗi tí xíu, các bạn tự sửa lấy nhé.

P/S: Tôi muốn gửi phần mềm tôi viết lên đây tặng mọi người mà hình như diễn đàn ko cho upload file lớn (cả bộ gồm Help chừng gần 200K thôi), các bác ADMIN có giúp được ko?

Edited by ngocnl, 22 April 2006 - 12:26 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#8
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts

th01b1, on Apr 21 2006, 10:51 PM, said:

- Bạn ơi cho mình hỏi tý: Offset để ghi giá trị khỏang cách nhặt đồ của nhân vật là bao nhiêu vậy bạn? THANK

Khoảng cách nhặt đồ được đặt là 1 hằng số, ko đổi được (đổi được có mà chết :busy" )

Edited by ngocnl, 22 April 2006 - 12:01 AM.

VLAuto website: http://vlauto.net
Email: [email protected]

#9
jollyjoker

jollyjoker

    Aishiteru P mochiron

  • Advance Member
  • PipPipPipPipPip
  • 1,287 posts

Quote

QUOTE(ngocnl @ Apr 21 2006, 11:59 PM)


QUOTE(th01b1 @ Apr 21 2006, 10:51 PM)

- Bạn ơi cho mình hỏi tý: Offset để ghi giá trị khỏang cách nhặt đồ của nhân vật là bao nhiêu vậy bạn? THANK


Khoảng cách nhặt đồ được đặt là 1 hằng số, ko đổi được (đổi được có mà chết )



-Bạn ơi, ý mình hỏi là Offset để ghi khỏang cách nhặt đồ nằm ở đâu trong dử liệu của đối tượng. THANK


là hằng số rùi thì tìm địa chỉ làm gì hả bạn???
Love will grow and nothing come in the way
It's true that love is here to stay
All we have to do to face tomorrow

#10
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts

jollyjoker, on Apr 22 2006, 12:08 PM, said:

Quote

QUOTE(ngocnl @ Apr 21 2006, 11:59 PM)
- Bạn ơi cho mình hỏi tý: Offset để ghi giá trị khỏang cách nhặt đồ của nhân vật là bao nhiêu vậy bạn? THANK
Khoảng cách nhặt đồ được đặt là 1 hằng số, ko đổi được (đổi được có mà chết )
-Bạn ơi, ý mình hỏi là Offset để ghi khỏang cách nhặt đồ nằm ở đâu trong dử liệu của đối tượng. THANK

là hằng số rùi thì tìm địa chỉ làm gì hả bạn???

Cái thông tin này được đặt bằng 1 giá trị cố định, ko có OFFSET nào lưu nó cả. Ví dụ trong lập trình Game có đoạn sau if (KhoangCach<64) NhatDo(); thì bạn thử nghĩ cái số 64 nó được lưu ở OFFSET nào? Thêm nữa, trên server nó cũng đặt cái hằng số này nên đôi khi nhân vật của bạn đứng gần vật phẩm nhưng trên server chưa kịp đồng bộ, thành ra vẫn còn xa và nó báo về là "Vật phẩm quá xa, không nhặt được".
VLAuto website: http://vlauto.net
Email: [email protected]

#11
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Do có một số bạn hỏi tôi về cách Hook vào Game, tôi xin gửi mã nguồn HOOK.DLL (theo cơ chế động) và giải thích cơ chế hoạt động như sau:

(Tham khảo từ bài viết http://www.codeproje...eads/winspy.asp)

- Từ chương đkhiển VLAuto, gọi hàm InjectDll(hVLWnd) hay UnmapDll(hVLWnd) để bật tắt chế độ hook (hVLWnd là handle của cửa sổ Game)

- Khi gọi InjectDll, hàm HookProc sau khi nhận được thông điệp WM_HOOKEX_RK báo Hook thì ngay lập tức UnHook rồi dùng LoadLibrary để mở HookDll. Kể từ đây ta đã ở trong process của Game nhưng ko còn Hook nữa => tiết kiệm tài nguyên. Việc can thiệp vào chương trình sẽ được làm bằng cách thay thế WinProc của game thành NewWinProc của chúng ta, lúc đó ta muốn làm gì thì làm.

- Sau khi Hook OK rồi thì từ chương đkhiển VLAuto, gửi thông điệp WM_HOOK_WRITE đến hVLWnd với các tham số wParam là địa chỉ cần ghi dữ liệu, lParam là giá trị cần ghi thì sẽ thực hiện được ý đồ của chúng ta. Trong trường hợp này các bạn có thể dùng PostMessage, vì WM_HOOK_WRITE chỉ đơn giản là một thông điệp bình thường, ko phải thông điệp gửi vào HookProc.

- Khi gọi UnmapDll, công việc sẽ làm ngược lại.

Chúc mọi người vui.
P/S: Đừng có hỏi thêm là import dll thế nào nhé, chịu khó đọc MSDN đi

Attached Files


Edited by ngocnl, 22 April 2006 - 12:46 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#12
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Khai báo 2 lớp CNpc & CObj

Các bạn lập trình viên,

Sau loạt bài viết trên, tôi xin gửi thêm bản đầy đủ khai báo các lớp và hằng số được sử dụng trong chương trình.

Còn cái vụ Hook thì đã gửi hôm trước rùi, nếu các bạn ko nhớ thì down ở đây HookInj.zip :dede

Attached Files


Edited by ngocnl, 23 April 2006 - 05:30 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#13
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Thê theo lời yêu cầu của một số bạn, mình gửi lên đây mã nguồn chương trình đọc thông tin của nhân vật, bao gồm: Tên, KN, SL, NL viết bằng Visual Basic

Các bạn có thể ứng dụng để làm chương trình tự bơm máu, mana lúc đi PK.
(1 bình máu bơm sẽ mất 5s, mỗi nửa giây tăng 1/10 giá trị bình máu)

Nhưng nếu bơm máu đi PK chắc các bạn phải bơm nhanh hơn 1 chút.

Chúc vui.

Attached Files


Edited by ngocnl, 23 April 2006 - 10:33 PM.

VLAuto website: http://vlauto.net
Email: [email protected]

#14
hongnam

hongnam

    Thành viên mới

  • Advance Member
  • 28 posts
Cám ơn bạn Ngọc. Cũng là dân IT mà kỹ năng lập trình tui hơi bị kém, không rành cái trò hook này. Hy vọng viết autoPlay sẽ lên tay hơn. Cũng xin nói luôn là tui đang tìm hiểu source Linux, ai có cùng mục đích thì chúng ta có thể làm quen học hỏi :ehh
---------------------------------------------------
Ai biết VB.NET chỉ dùm nha :(( : chỉ mình cách xài hàm ReadProcessMemory() để đọc được nhiều byte (khỏang 4KB) một lần được kô?
---------------------------------------------------
Alô, mình lại có thắc mắc một chút khi quan sát TLG1.5 và VLLite1.2:
- Trong VLLite, khi bơm máu, hay mana, chtrình sẽ tự gửi phím 1 hoặc 2 đến cửa sổ game VL
- Trong TLG1.5, mình không thấy nó gửi phím 1 hay 2.
Mình kiểm tra chuyện này bằng cách cho nhân vật của mình đứng giữa bầy quái để nó đánh, sau đó nhấn enter (để vào chế độ chat). Đối với vllite mình thấy nó hiện ra 1, hoặc 2 trong đọan text đang chat. Trong khi với TLG, mình không thấy xuất hiện ký tự 1,2 trong đọan text
Do đó, có thể hiểu được vì sao dùng vllite khó chat hơn TLG. Anh Ngọc giải thích cho em với (Bác TLG cũng được)

Edited by anhthattinh, 11 May 2006 - 11:01 AM.


#15
TinhLaGi

TinhLaGi

    Trung cấp CSTH

  • Advance Member
  • PipPipPip
  • 528 posts
Góp ý một chút: Các chương trình bot, cheat đều họat động dựa trên cơ chế pointer và offset, nên sử dụng các ngôn ngữ không hỗ trợ pointer để viết bot là một điều cực kỳ khó khăn. Mà hình như VB không có pointer thì phải. VC được chọn vì VC họat động gần như dựa vào pointer

#16
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts

rfc_clubmx, on May 17 2006, 11:47 PM, said:

Ngocnl cho mình hỏi Mình gọi hàm InjectDll trong C# nó trả về 1 , vậy là hook thành công hay không ??
Bạn đừng có .. giận vì mình cũng biết trong C++ true = 1 mà false = 0 ( chỉ vì mình quen lập trình java rồi nên cũng hơi có khác tí xíu ) :jeje:
Vì hàm nó gọi CallNextHookEx mà hàm này trả về LRESULT dựa theo cái hook nên mình muốn biết là hook được hay chưa . Nói về hook là bó giò .
Thêm nữa , do cái file include của bạn dùng mangled name cho function nen muốn xài được ở ngôn ngữ khác thì nên thêm vào cái extern "C" để tránh mangling name .
Vẫn đang cố gắng ...

Hi hi, nếu cái InjectDll nó trả về 1 tức là 99.9% là được, còn lại là lỗi Windows hoặc máy bị treo :jeje:
Trong C thì true=-1 hoặc nếu ép kiểu thì cứ != 0 thì là true, còn lại = 0 thì là false. OK cho cái vụ extern "C" :- .

Quote

ui trời! tui hổng có rành VC co' ai chỉ bằng VB không?
Thứ 1: Dịch trái và dịch phải -> VB Phải làm sao? => có thể dùng phép chia & nhân, dịch phải 9 bits tức là chia cho 512 (tức 2^9), dịch trái 9 bits thì là nhân với 2^9
Thứ 2: Các địa chỉ Offset cụ thể trong VB là phải như thế nào? cũng thế thôi mà
Mình đọc được Máu, Mana, Exp, Name nhưng Tọa độ không đọc được! Hix
Thư 3: Cách Hook trong VC và VB khác nhau chỗ nào?

Nếu bạn đã đọc được Máu, Mana... theo mã nguồn mình đã cung cấp trên thì hoàn toàn có thể dựa vào đó đọc được tọa độ, thay cái địa chỉ offset của tọa độ vào là xong.
Để có thể dùng hook bằng VB, bạn có thể tham khảo thêm mã nguồn chương trình AutoPT của bg1102 ở đây => http://cuasotinhoc.c...?showtopic=7705
VLAuto website: http://vlauto.net
Email: [email protected]

#17
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Nào, bây giờ xin tặng các bạn một project hoàn chỉnh, bao gồm các chức năng cơ bản:

- Tự buff máu, mana
- Đánh quái
- Nhặt đồ
- Kiểm tra đồ hư

Còn các tính năng khác thì các bạn tự phát triển thêm nhé...

Chúc thành công

Ngọc

Attached Files


Edited by ngocnl, 27 May 2006 - 10:32 AM.

VLAuto website: http://vlauto.net
Email: [email protected]

#18
rfc_clubmx

rfc_clubmx

    Căn bản tin học tốt

  • Advance Member
  • Pip
  • 57 posts

ngocnl, on May 19 2006, 11:29 PM, said:

Nào, bây giờ xin tặng các bạn một project hoàn chỉnh, bao gồm các chức năng cơ bản:

- Tự buff máu, mana
- Đánh quái
- Nhặt đồ
- Kiểm tra đồ hư

Còn các tính năng khác thì các bạn tự phát triển thêm nhé...

Chúc thành công

Ngọc

Ặc thế này còn gì hay nữa , hix dù sao cũng cám ơn bạn Ngọc tui down rồi :-j :-j
Tiếp tục viết C# tiếp hix hix .

handois, on Apr 27 2006, 02:35 PM, said:

ngọc cho anh hỏi tý nhé!

nếu dùng trên C# thì de lay cai title cua games ta phải dùng hàm gì. và để lấy infomation cua nhân vật thì code như thế nào. hic pó tay phần này kô biết sao cho nó lấy được


using Microsoft.Win32;
using Microsoft;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;

public const string gameAppName = "game_Y";
System.Diagnostics.Process[] mProcess =
System.Diagnostics.Process.GetProcessesByName(gameAppName);

Còn lấy tọa độ nhân vật thì bạn search ProcessMemoryReader trên codeproject đó , hình như là prj của C# nói về edit memory trong game Mine của Window . Lấy đọan code đó về mà đọc thông tin .
Nói chung cũng phải đọc tài liệu nhiều lắm , C# cũng khá mạnh mà xài mệt mỏi lắm , đồ M$ mà .

#19
anhemFSA

anhemFSA

    Căn bản tin học tốt

  • Advance Member
  • Pip
  • 56 posts
Rất cảm ơn bạn NgocNL đã chia sẻ kinh nghiệm với mọi người, mình cũng thích lập trình lắm nhưng biết không nhiều về lĩnh vực này. Mấy cái mã máy là mình mù tịt à.

Có điều này mình muốn hỏi bạn Ngoc là mình không thể nào viết hàm di chuyển nhân vật được. Bình thường mình test thì đúng như bạn nói, nhân vật có di chuyển trên cilent nhưng đi lại bị giựt lại do không gửi gói tin di chuyển đến máy chủ. Mình làm theo hướng dẫn của bạn, sử dụng hàm và đọan mã ASM gán địa chỉ của hàm thì Game bị xung đột ngay. Không biết mình làm sai ở đâu. Mình thêm đọan code vào hàm HookProc như sau :


#define pCW ((CWPSTRUCT*)lParam)

LRESULT HookProc (int nCode, WPARAM wParam, LPARAM lParam)
{
	  HWND hVLWnd = pCW->hwnd;
	  HHOOK hHook = (HHOOK)pCW->wParam;

	  if (pCW->wParam == 3) // mình chỉ test với chế độ chạy
	  {
			LPDWORD dc = (LPDWORD)NPC_BASE_ADD;
			int lpBaseAdd = *dc;
			int *pX, *pY;
			pX = (int*)(lpBaseAdd + 0x108C + 0x7E4C);
			pY = (int*)(lpBaseAdd + 0x1090 + 0x7E4C);
			SendCmdRunToServer(*pX, *pY);
	   }
	   else 
	   {	 //trường hợp khác ( ghi một giá trị vào bộ nhớ tại đỉa chỉ xác định )
	   }

	   if((pCW->message == WM_HOOKEX) && pCW->lParam)
	{
				  // Đọan này mình giữ nguyên ko thay đổi
	}
	else if(pCW->message == WM_HOOKEX) 
	{
				  //...
		  }
	   return CallNextHookEx(hHook, nCode, wParam, lParam);
}

Cứ khi mình gọi hàm SendMessage(hVLTK, WM_HOOK_WRITE, 3, 0); là game lại bị treo vì xung đột ! Mong bạn hướng dẫn cho mình với !

Edited by anhemFSA, 22 May 2006 - 05:30 AM.


- khùa khụa -

#20
ngocnl

ngocnl

    Cao đẳng CSTH

  • VIP
  • PipPipPipPip
  • 719 posts
Hình như cái HookProc của bạn làm chưa đúng... Bạn đã kết hợp 2 cách Hook khác nhau của mình rồi :hihi

Cách mà ban đầu mình gửi Code lên diễn đàn thì đúng là HookProc, do đó lấy wParam và lParam của hàm SendMessage qua pWC. Nhưng trong phần mã nguồn của Project mới gửi lên thì mình dùng Hook để đổi địa chỉ WinProc sang NewWinProc rồi lấy trực tiếp wParam, lParam... bạn coi lại nhé.

Ngọc

Edited by ngocnl, 22 May 2006 - 09:25 AM.

VLAuto website: http://vlauto.net
Email: [email protected]




1 user(s) are reading this topic

1 members, 0 guests, 0 anonymous users




Stars Counter Game

Balloon vs. Thorns

MU Phuc Hung

Làm Việc Tài Nhà

Mu Da Nang

Tuyển Nhân Viên Bán Hàng

Tư vấn sức khỏe trực tuyến