Lesson 1: C # use the window API and perform memory operations.
This lesson is something simple that can be learned directly. Considering that most people who use C # Work on websites and may not have the chance to contact them, I will give a rough introduction here.
Step 1: Get to know winapi
Many functions are provided in windows. If we do plug-ins, we need to use the functions (API ). (Nonsense: These APIs are encapsulated in DLL files in the system path. In fact, we don't have to worry about where it is. We only need to know how to use it.) It's easy to use and the format is as follows:
Public partial class form1: Form
{
[Dllimport ("kernel32.dll")]/
Public static extern int readprocessmemory (|
Int hprocess, |
Int lpbaseaddress, |
Int [] lpbuffer,> code segment 1
Int nsize, |
Int lpnumberofbyteswritten |
);/
...
Public form1 ()
{
Initializecomponent ();
Readprocessmemory (processhandle,...> Code 2
...
}
...
}
Code snippet 1 refers to the code that references the API. The referenced function is the most common function used for plug-ins. It can be seen from its name that it is used to read the process memory. (Nonsense: From the code, we can easily see that this function is encapsulated in the kernel32.dll file .) After referencing, we can use this function in our own code (for example, code 2 ).
(Nonsense: Windows also provides many APIs. If you are interested, you can search for winapi manuals online. For more information, see msdn .)
Step 2: read/write memory
Next I will explain how to use the API referenced in the previous step to read game data. Let's take a look at the parameters:
Public static extern int readprocessmemory (
Int hprocess, // process. If you are using a plug-in, it indicates the game you want to play.
Int lpbaseaddress, // The memory address you want to read
Int [] lpbuffer, // What is read from the above parameter address (this function is called for it) No matter what type this parameter is, it should be an array, otherwise, nothing can be read.
Int nsize, // length, the previous parameter, type is int, that length should use 4
Int lpnumberofbyteswritten // use 0. If you want to know what it is, go to msnd.
I will talk about how to obtain the first hprocess parameter later. If it has been done, we need to focus on the lpbaseaddress and lpbuffer, both the read address and the read value. (Nonsense: By the way, this function seems to have another return value, which we cannot use here. If you are interested in learning, msdn) The read value out int lpbuffer is declared as int when we reference the API. However, the value we want to read from memory is not always Int. We can reference this API multiple times, with 3rd parameters of different types.
Next, we will write a piece of code to read the HP code of the fairy. First, we need to know the IP address of the person HP (nonsense: How to know this address, use ce or IE, you can do it yourself .) I'm http://www.ghoffice.com/bbs/read.php here with IE? The tid-35908-fpage-2.html found it, which is written here as follows:
Character Base Address: [[& h12f830] + & H28] = base
Life: [base + & h254]
(Note: & H indicates hexadecimal, which is expressed by 0x in C)
A pair of [] indicates the read address. That is to say, 123 indicates the value of 123, and [123] indicates the value read from address 123. For several pairs of [], we need to use readprocessmemory several times. Let's write the code:
Int [] Base = new int [1];
Int [] HP = new int [1];
Readprocessmemory (process, 0x12f830, base;, 4, 0); // equivalent to base = [& h12f830]
Readprocessmemory (process, base + 0x28, base;, 4, 0); // equivalent to base = [base + & H28]
// Read the base address of the character
Readprocessmemory (process, base + 0x254, HP;, 4, 0); // equivalent to HP = [base + & h254]
// Read HP
It's easy.
We only use three rows of readprocessmemory for reading HP. Sometimes, reading a value may require a lot of [] pairs, so we need to write n rows of readprocessmemory, which is very troublesome and looks dizzy. Next we will write a function to make the READ memory process look similar to the [] notation.
// To look good, the function name is better to be shorter, so we use R to indicate read
Public static int R (INT add)
{
Int [] r = new int [1];
Try
{
Readprocessmemory (process, add, R, 4, 0 );
Return R [0];
}
Catch (exception ex)
{
Return-1;
}
}
This function is very simple. I don't need to talk about it.
With this function, the above Code for reading hp can be written as follows:
Int base;
Int HP;
Base = R (0x12f830) + 0x28 );
// Read the base address of the character
HP = R (base + & h254 );
// Read HP
It looks much clearer.
Next I will read the string and first reference the API:
[Dllimport ("kernel32.dll")]
Public static extern int readprocessmemory (
Int hprocess,
Int lpbaseaddress,
Byte [] lpbuffer,
Int nsize,
Int lpnumberofbytesread
);
Then, like above, write a method for reading strings.
Public static string rstring (intptr process, uint add)
{
String [] R;
String temp;
Byte [] B = new byte [256];
Try
{
Api. readprocessmemory (process, (intptr) add, B, 256, (intptr) 0 );
// Read byte [] to be unicode encoded as a string
Temp = system. Text. encoding. Unicode. getstring (B );
// Intercept the first string
R = temp. Split (''/0 '');
Return R [0];
}
Catch (exception ex)
{
Return "error ";
}
}
This function is similar to the above function. It has been written in many comments and is also very simple. You don't need to talk nonsense.
Next, let's read the name of the character. As shown in the previous post, the character name offset is as follows:
Role name: [[base + 3a4] + 0]
The Code is as follows:
String name;
Name = rstring (R (Basse + 0x3a4) + 0x0); // + 0x0 can be removed
Reading other types of data is the same as reading an int. you can do it yourself.
Now everything is ready, this process is worse. Next, if you get the process handle of the game (nonsense: Process Handle: an integer that represents a process. Generally, ** handle indicates the integer value of ). In two steps, Step 1:
System. Diagnostics. Process [] gamesprocess
= System. Diagnostics. process. getprocessesbyname ("elementclient ");
This step uses the. NET method. system. Diagnostics. process is the process class in. net. The getprocessesbyname static method obtains the process array through the process name. After this line of statements is executed, all game processes are placed in gamesprocess. If you want to do more, you can use the gamesprocess array to determine the game to be played.
Step 2:
Int processid = gamesprocess [0]. ID;
Int process = OpenProcess (0x1f0fff, 0, processid );
Row 3 shows the process ID, which is the PID shown in the task manager. Row 3 gets the process handle. OpenProcess is also a system API and also in kernel32.dll. The three parameters and return values are declared as Int. For details about how to reference the data, see step 1. You can see how to use it. The first parameter is the process ID, and the returned result is the process handle (nonsense: what is the use of the 1, 2 parameter? If you want to know it, please refer to msdn. Just use the parameters in the example. I will not talk about such nonsense in the future ).
Here, you can try to write a small item that reads character data. Of course, the premise is that you need to know the address of the information.
Write memory:
(Nonsense: modifying game data is not of great significance for writing online game plug-ins. Because important data is processed on the server, it is useless to modify it. People use the write memory, which is usually used to change the game code to implement some special functions, such as the wall-crossing and infinite hop in the fairy tree. To know how to change it, we need disassembly and analysis experience. This is not what cainiao can do, haha)
Writeprocessmemory (process, (intptr) add, bytes, (uint32) bytes. length, 0 );
Write process memory functions. The parameters of this API correspond to readprocessmemory one by one. You can declare it on your own. If you like it, you can also write a function on the top of the page to simplify writing memory code. In the next lesson, we will use this function to write code to the game.
The next lesson will be something more interesting. We need to execute some operations on the game through plug-ins. So stay tuned.
Lesson C # Injection
This course is actually very simple, but there are not many people who know it.
Step 3: inject
Injection is not complex. It is a very simple process. Write your code in another program and execute it in one sentence.
(Nonsense: Legend injection is divided into three types. Which one do I mean? I can use it if I think about it .)
It is easy to implement, just a few lines of code:
Copy code
Byte [] bytes = {0xc3}; // code to be written
Int ADDR = virtualallocex (process, 0, bytes. length, 0x1000, 0x40); // 1, apply for Space
Writeprocessmemory (process, ADDR, bytes, bytes. length, 0); // write the code
Int hthread = createremotethread (process, 0, 0, ADDR, 0, 0, threadid); // three, execute the written code
Waitforsingleobject (hthread, 0 xffffffff); // wait for the end of the thread
Virtualfreeex (process, ADDR, 0, 0x8000); // 4. Release the requested space.
Closehandle (hthread); // 5. Close the thread sentence cake.
By taking a closer look at these lines of code, you will find it very simple and almost no need to say anything. The functions not available in these beans are APIs. Refer to the above method to use it. The parameters and returned values you can understand require your attention. Ignore unknown parameters. simply use the above values. If you have any questions, refer to the winapi manual. It is worth noting that step 4 releases the application. If you read the API manual, you will find that the third parameter is the size, but if you use bytes. length is wrong. It must be 0.
(Nonsense: If you don't know how to reference the API based on the method above, I will simply say a few words. In the second behavior example, we can see that the returned values of virtualallocex and the five parameters are both int rows, so we can declare them as follows:
[Dllimport ("kernel32.dll")] // unless otherwise specified, APIs are generally referenced from this DLL
Public static extern int virtualallocex (
Int P1,
Int P2,
Int P3,
Int P4,
Int P5
);
As you can see, to declare an API, you only need to know the type of each parameter and return value, and the DLL file name. If you like it, you can make the parameter name meaningful .)
Just a few lines of code can be injected. Isn't it as complicated as you think? Haha.
The question is, where does the Code come from?
You can use my tools to convert the call you found into a machine code. (Nonsense: the principle of this tool is to call MASM compilation, so any syntax and commands (within the limit function) You can use in MASM can be used here. Of course, the syntax is the same as that in MASM. The method used is described in detail in the attachment, so I will not waste the chapter here .)
The Conversion Result of the tool is a string of Type 60b8d0305a00ffd08b561c83c40461c3. You can use the following method to convert it to byte []
Copy code
Public static byte [] getbytes (string HEX)
{
Byte [] bytes = new byte [Hex. Length/2];
For (INT I = 0; I <bytes. length; I ++)
{
Bytes [I] = convert. tobyte (int32.parse (Hex. substring (I * 2, 2 ),
System. Globalization. numberstyles. allowhexspecifier ));
}
Return bytes;
}
Okay. Now, you can try to use a plug-in to call the attack call in the game. (If you don't want to call the call, you can try to find it in this forum)
In the next section, I will illustrate how to use Parameters Using Skill call.
I have corrected some mistakes in the previous lesson and marked them in red. If someone suffers a setback in practice due to these mistakes, I apologize.
I may write a simple demo in a few days. Please wait.