|
You last visited: Today at 12:49
Advertisement
Perfect World Bot PWI-Prophet Bot Recoded
Discussion on Perfect World Bot PWI-Prophet Bot Recoded within the PW Hacks, Bots, Cheats, Exploits forum part of the Perfect World category.
10/18/2010, 08:15
|
#631
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
Thank VuDuy for your idea, I will change in my code.
Combining with the block using{} then the memory for MemoryStream will be released right after use right ?
Currently, I knows only 2 ways to inject the function
1. Use C++ and Assembly, then export as a DLL and use them in C# application
2. The above way, creating the opcode and CreateRemoteThread to run these opcode.
Is there other way to do this with better performance ?
@Vuduy: I do review for bot, for every client you create an tab for it. so, for managing these GUI components and mapping them to the Character, you have to handle it manually ?
|
|
|
10/18/2010, 08:46
|
#632
|
elite*gold: 0
Join Date: Mar 2008
Posts: 109
Received Thanks: 64
|
With SINS 2.x series using WinForms, the game tab thread has to update the UI every second via BeginInvoke. The new version coming up SINS 2.1 is written in WPF; so everything is data-bounded. No need to update anything, the data-binding takes care of itself.
The nice thing about WPF is the simplicity; the code size is reduced to about 1/2 compared to WinForms; but the drawback is the CPU usage. WPF uses DirectX so it sucks up a lot CPU with its UI because they look so much nicer.
Back to your question, with C#, you don't need to free/release any variables unless you are using unsafe codes and/or direct memory allocations. That's the beauty of managed API because there won't be any memory leaks nor performance penalty.
Method #1 is a lot more efficient and simpler than #2. You can set up inter-process communications between your C# program and the C++ DLL to do all the dirty work because it has direct access to the game's memory/functions.
An example is to setup named pipes between the DLL and C#. The DLL thread will sleep most of the time waiting for data from the pipe, and just call the game Send() function whenever data arrives.
The simplest way and fastest IPC option is to use Memory Mapped Files; they are as close as possible to having direct access to the game's memory from the C# program.
|
|
|
10/18/2010, 08:57
|
#633
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
Can you explain more about the "DLL Thread", because I built my Dll as Class Library and there is only one class in that DLL for handling in-game function. In the main project, I call these via an object.
|
|
|
10/18/2010, 09:14
|
#634
|
elite*gold: 0
Join Date: Mar 2008
Posts: 109
Received Thanks: 64
|
Supposed that you want to create a DLL to interact with your C# program to do all the dirty work with the game's memory/functions, then your DLL's design is very simple.
- Create its own thread
- Setup IPC mechanism (eg. named pipes or memory mapped files)
- Wait for connection with the C# program
- Once connection is established then preliminary setup can be initiated; for example, your C# program may want to pass the game's current base pointer and send function address to the DLL so that it won't have to hard-code these addresses.
- DLL thread remains idle looping and waiting for "send data" from the C# program and execute it whenever it arrives.
The DLL will be very small in code and very efficient.
|
|
|
10/18/2010, 09:29
|
#635
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
 I got your idea. but why do we need a thread ? is your DLL a Class Library or and VC++ console application exported as dll.
As you mentioned, how much memory that SINS may consume? My simple bot is under testing but the memory for it is about 14K with one client.
When I do the mapping between the UI component and object attribute, I setup the name convention for component + characterName.
For example : lbl_CharacterLV_MyCharName, and for updating that component I have to search them and update.
Doing searching for updating every second is not efficient right ? any better idea ?
|
|
|
10/18/2010, 09:46
|
#636
|
elite*gold: 0
Join Date: Mar 2008
Posts: 109
Received Thanks: 64
|
DLL is a library; it is not an application.
The reason why you want to create a separate thread in your DLL is because you don't want to be looping forever in your DllMain.
Memory usage for C# programs depends on its complexity. SINS 2.x uses about 5-10k of memory per client and 0.5% cpu per client on my PC (quad-core). Yes, even with all those features
As for updating the UI, why are you making things so complicated? Why and what are you searching?
If you have a TextBox called playernameTextBox, and you want to update it, just assign it directly "playernameTextBox.Text = gamedata.playername" or whatever object is holding the name.
If you are updating from another thread than the UI thread, you have to use BeginInvoke otherwise it will throw exception because you can't modify UI from another thread directly.
|
|
|
10/18/2010, 11:35
|
#637
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
Is your Gui component created at runtime or you create them all at the beginning and then set them visible ?
If you create them at runtime, then how to get the object to call set text ?
|
|
|
10/18/2010, 16:10
|
#638
|
elite*gold: 0
Join Date: Mar 2008
Posts: 109
Received Thanks: 64
|
It doesn't matter whether you create your UI at design time or runtime; just make sure to keep a reference for the UI component that you want to update and access it directly.
If you are creating a TextBox object at runtime to display the player's name, then after initializing the TextBox, make a copy reference of the object with a local variable and when you need to update it, use the local variable name.
|
|
|
10/18/2010, 16:33
|
#639
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
I will test that kind of mapping tonight 
ah, your bot is just amazing work since you stated that you are not a programmer  ) When you release the new bot in WPF, please give me a chance to test it  )
I stuck with the sendPackage in C++, I need to pass 2 things
- the source of the package (LPVOID)
- package size (int)
as the old method, I put all the same type a param into LPVOID and call it before code Assembly. now 2 different types, I really dont know how to merge them >_<
|
|
|
10/18/2010, 19:52
|
#640
|
elite*gold: 0
Join Date: Mar 2008
Posts: 109
Received Thanks: 64
|
What kind of design are you doing? Keep it simple. Here's a simple design using memory mapped files without any synchronization. The layout of the memory map is as follow:
In the DLL, create a memory file mapping of say 64k in size with
Code:
HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 64000, "Name");
unsigned int *data = (unsigned int*) MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 64000);
*data = command value
*(data+1) = base address
*(data+2) = send function address
*(data+10) = size of byte[] data
(data+11) = the start address of byte[] data
then in your loop
Code:
while (1)
{
if (*data == 99) break; // command 99 = exit thread and unload the DLL
if (*data == 1) // send function command
{
unsigned int base = *(data+1);
unsigned int send = *(data+2);
unsigned int length = *(data+10);
unsigned int *buffer = data+11;
__asm
{
pushad
push length
push buffer
mov eax, base
mov edx, [eax]
mov ecx, [edx + 0x20]
mov esi, send
call esi
popad
ret
}
*data = 0;
}
Sleep(5);
}
From the C#, you create a memory map view:
Code:
IntPtr hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "Name");
IntPtr pData = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 64000);
Then, to setup the base address and send address do:
Code:
Marshal.WriteInt32(pData, 4, baseaddress);
Marshal.WriteInt32(pData, 8, sendaddress);
To send some opcodes, build the opcodes first (example to select target id):
Code:
uint targetid = 0x8000000;
MemoryStream stream = new MemoryStream();
stream.Write(BitConverter.GetBytes(2), 0, 2); // 02 00
stream.Write(BitConverter.GetBytes(targetid), 0, 4);
byte[] data = stream.ToArray();
Marshal.Copy(data, 0, (IntPtr)(pData.ToInt64() + 44), data.Length); // writing the buffer to (data+11) position
Marshal.WriteInt32(pData, 40, data.Length); // writing the buffer size to *(data+10)
Marshal.WriteInt32(pData, 0, 1) // writing command 1
|
|
|
10/19/2010, 03:03
|
#641
|
elite*gold: 0
Join Date: Jun 2008
Posts: 16
Received Thanks: 1
|
Hi Interest07,
The code for auto follow doesn't seem to be working in PW PH. Below is my code snippet written in C#.net:
Code:
// Real BaseAddress
ReadProcessMemory(ProcessHandle, (IntPtr)OxFBaseAddress, &FBaseAddress, 4, out bytesRead);
// StructurePointer
ReadProcessMemory(ProcessHandle, (IntPtr)(FBaseAddress + 0x1C), &StructPointer, 4, out bytesRead);
// PlayerPointer
ReadProcessMemory(ProcessHandle, (IntPtr)(StructPointer + 0x20), &PlayerPointer, 4, out bytesRead);
// ActionStruct
ReadProcessMemory(ProcessHandle, (IntPtr)(PlayerPointer + OxPlayerActionStruct), &ActionStruct, 4, out bytesRead);
// TargetID
ReadProcessMemory(ProcessHandle, (IntPtr)(PlayerPointer + OxTargetOffset), &TargetID, 4, out bytesRead);
// ActionList
ReadProcessMemory(ProcessHandle, (IntPtr)(ActionStruct + 0x30), &ActionList, 4, out bytesRead);
// FollowPlayer
ReadProcessMemory(ProcessHandle, (IntPtr)(ActionList + 0x1C), &FollowPlayer, 4, out bytesRead);
WriteProcessMemory(ProcessHandle, (IntPtr)(FollowPlayer + 0x8), 0, 4, out bytesOut);
WriteProcessMemory(ProcessHandle, (IntPtr)(FollowPlayer + 0x20), TargetID, 4, out bytesOut);
WriteProcessMemory(ProcessHandle, (IntPtr)(ActionStruct + 0xC), FollowPlayer, 4, out bytesOut);
WriteProcessMemory(ProcessHandle, (IntPtr)(ActionStruct + 0x18), 1, 4, out bytesOut);
WriteProcessMemory(ProcessHandle, (IntPtr)(ActionStruct + 0x14), FollowPlayer, 4, out bytesOut);
|
|
|
10/19/2010, 03:31
|
#642
|
elite*gold: 0
Join Date: Sep 2008
Posts: 35
Received Thanks: 0
|
I'll try it after work
|
|
|
10/19/2010, 08:03
|
#643
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
Quote:
Originally Posted by serpentmind
Hi Interest07,
The code for auto follow doesn't seem to be working in PW PH. Below is my code snippet written in C#.net:
|
Are you getting sensible values from your readmemory calls? Because your offsets seem to be alright, but I can't judge on how you implemented your read and write memory functions.
just tried it in C# and the offsets definitely work in PWI, so they most likely should in PW RU too.
follow function: (values is my player structure as it's read from memory, with actionStructPointer obviously being the pointer to the actionStruct hehe)
Code:
public void follow(int playerId)
{
int actionStruct = values.actionStructPointer;
int actionList = MemFunctions.MemReadInt(pr_processHandle, actionStruct + 0x30);
int followAction = MemFunctions.MemReadInt(pr_processHandle, actionList + 0x1C);
MemFunctions.MemWriteInt(pr_processHandle, followAction + 0x8, 0); //Set error = 0
MemFunctions.MemWriteInt(pr_processHandle, followAction + 0x20, playerId); //Set playerId to follow
//MemFunctions.MemWriteInt(pr_processHandle, followAction + 0x48, 0); //Set stopped following = 0
MemFunctions.MemWriteInt(pr_processHandle, actionStruct + 0xC, followAction); //Set new action at position 1
MemFunctions.MemWriteInt(pr_processHandle, actionStruct + 0x18, 1); //Set next action position to 1
MemFunctions.MemWriteInt(pr_processHandle, actionStruct + 0x14, followAction); //Set new action type follow as next action
}
The MemFunctions used:
Code:
[DllImport("Kernel32.dll")]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesWritten);
public static void MemWriteInt(IntPtr processHandle, int address, int value)
{
bool success;
byte[] buffer = BitConverter.GetBytes(value);
UInt32 nBytesRead = 0;
success = WriteProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
}
public static int MemReadInt(IntPtr processHandle, int address)
{
bool success;
byte[] buffer = new byte[4];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, 4, ref nBytesRead);
return BitConverter.ToInt32(buffer, 0);
}
|
|
|
10/19/2010, 08:42
|
#644
|
elite*gold: 0
Join Date: Jun 2008
Posts: 16
Received Thanks: 1
|
Hi Interest07,
Can you show me how you created this player structure (values.actionStructPointer)?
|
|
|
10/19/2010, 08:53
|
#645
|
elite*gold: 0
Join Date: Mar 2010
Posts: 862
Received Thanks: 576
|
How you build up your struct would depend on your version of course (it's not as flexible as working with offsets for every single value that you can obtain for all version by offsetFinders, but I only play one version so I don't mind that :P)
edit: I'm not claiming any of my methods are efficient, just in case. Should prolly consult vuduy about that kinda thing.
Code:
values = (playerStruct)MemFunctions.MemReadStruct(pr_processHandle, playerAddress, typeof(playerStruct));
public static object MemReadStruct(IntPtr processHandle, int address, Type anyType)
{
int rawsize = Marshal.SizeOf(anyType);
bool success;
byte[] buffer = new byte[rawsize];
UInt32 nBytesRead = 0;
success = ReadProcessMemory(processHandle, (IntPtr)address, buffer, (UInt32)rawsize, ref nBytesRead);
return RawDeserialize(buffer, 0, anyType);
}
private static object RawDeserialize(byte[] rawData, int position, Type anyType)
{
int rawsize = Marshal.SizeOf(anyType);
if (rawsize > rawData.Length)
return null;
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
object retobj = Marshal.PtrToStructure(buffer, anyType);
Marshal.FreeHGlobal(buffer);
return retobj;
}
And apologies to Prophets as his thread is getting hijacked again as usual :P And not even with AutoIt code, so it's particularly useless to him
|
|
|
All times are GMT +1. The time now is 12:50.
|
|