Directory

- Code Restoration Technology
- I. Introduction code Restoration
- Ii. Data Type representation in code Restoration
- 1. Integer type
- 2. unsigned integer
- 3. signed integer
- 4. Floating Point Data Type
- 5. Floating Point Encoding
- 4. Double Type resolution.

- Trigger floating point assembly
- 1. Floating Point Stack
- 2. Floating Point Assembly
- 3. Use inline floating point assembly for addition

- Iv. boolean type
- Address, pointer, and reference expression

Code Restoration Technology I. Introduction code Restoration

- Example 1: many of us have learned assembly. but the core knowledge of assembly is what I can understand. someone uses the Assembly as a plug-in. for example, I want to track the offset. watch the video. then another game is still like this. but one day, you may find it boring. this is because all this knowledge is dead. for example, we want to see what the code has done in the game. at this time, you need to convert the Assembly to advanced code for viewing. ida F5 plug-in. generally. but many of them cannot. for example, in the game. in this code, you can find an object + What is the offset. but it will reverse the person. this code is written out. convert to advanced code. A look. the original meaning. + What is the function. what other functions are implemented. this is the core technology. why do other people have many plug-ins. you have fewer. its core is here.
- Example 2: inverse algorithms, such as a software. let you get the registration code. you may have cracked the attack. however, if you can reverse the algorithm. so is it the first to improve yourself, the second, you can write the registration machine specifically for this program to generate a registration code.
- Example 3: If you work for a company. maybe one day, the company needs you to reverse. it is found that xx software has a better function. what do you need to do now. this function is completely reversed Based on the Assembly. and let the company make this function. this is also a good example.

Ii. Data Type representation in code Restoration

I have mentioned a lot above, so I will explain it in the beginning.

1. Integer type

There are three basic data types of integers in C ++: int long short. In vc6.0, int long occupies 4 bytes of memory.

Two short bytes. The hexadecimal format is used as an example. Int long is four bytes, respectively. Short is two bytes. one byte is eight bytes.

2. unsigned integer

In the memory, the unsigned integer is used to represent the value. If the value is 32 bits, the value range is 0x00000000 ~ 0 xfffffff

10 hexadecimal: 0 ~ 4294967295. Because of the unsigned number, the highest bit is filled with 0. Therefore, the value is relatively large.

3. signed integer

The signed integer is the same as the unsigned integer. only the high position is used to represent the symbol bit, and the other low positions represent the value. this is a signed integer. the value is only 31 bits. the range is 0x80000000 ~ Convert 0x7fffff to decimal:-2147483648 ~ 2147483647

Because the highest bit is the symbol bit, it can represent a negative number. For example,-3

In the memory, negative numbers are all expressed in the complement form.

`Complement rule: the complement rule uses 0 to remove the absolute value of this number.`

For example, the result of 0-3 is the representation of-3 in the memory.

Because the complement code has a high value of 1, it is also in the form of a 0-complement code to convert the value to the true value. However, in general computer calculations, the complement code is usually used to obtain the true value through the reverse + 1 operation. The front side carries the symbol.

Why does a negative number always have one more value than an integer.

For example:

-2147483648 ~ 2147483647

Cause:

The four-byte complement 0x80000000 represents-0. but for 0. it is unnecessary to distinguish between positive and negative values. therefore, 0x800000000 specifies the minimum value of the 4-byte complement code. so this is also the reason why the negative number is one more than the positive number.

4. Floating Point Data Type

There are a lot of scientific disputes about floating point storage. There are many ways to store real numbers (decimal places), but they are rarely used. So we will not introduce them any more.

No matter how it is stored, it can be divided into fixed-point real number Storage and floating-point real number storage.

- Fixed Point real number Storage

The fixed-point real number Storage refers to the length of the specified integer and decimal place. for example, four bytes are used to store integers in two bytes. stores real numbers in two lower bytes. the advantage is that the computing efficiency is high, and the disadvantage is that the storage is not flexible. for example, the integer part 65536.5 cannot be stored.
- Floating Point real number Storage

Floating Point real number Storage stores the decimal point location information with some binary digits. We can call it an exponential domain. Other data bits are used to store data and Symbols without decimal points. We can call it a data domain or symbol domain.

For example:

67.625 we can use the floating point real number storage, and the data field can store 67625 decimal places, which can be remembered as 10 ~ -To the power of 3, when accessing this number, you only need to calculate it.

Advantages and disadvantages: the first one is the opposite. before the 80286cpu, programmers often use real numbers for computing, which is a headache. finally, the floating point coprocessor is released. can assist in CPU computing. the efficiency of programmers in calculating real numbers is greatly improved. so now the floating point storage method has been promoted.

Note: The second method is used for storage now. It is not a fixed-point storage method.
- Floating Point in C ++

In C ++, float and double are used to store floating point numbers. Float 4 bytes. Double 8 bytes.

Because the double space is large, the precision is high. the two data types are in the same hex storage in the memory. however, it is different from hexadecimal in decimal mode. float dobule has a large hexadecimal value.

Reason: The floating point type does not convert a floating point decimal point to binary for storage. instead, the floating point decimal point is converted into binary and re-encoded. then store. floating Point Numbers in C/C ++ are signed.

It is worth noting that converting a floating point to an integer is not rounded in, but rounded to 0. That is to say, dropping decimal places.

For example, a = 3.78; int B = (INT) A; at this time, the value of B is 3 rather than 4 in the traditional sense, because it is not rounded.

5. Floating Point Encoding

- Floating Point encoding conversion.

As we mentioned above, floating point numbers are reencoded for storage. so we only need to understand the encoding. then you can calculate how the floating point is represented in the memory. or reverse. how to convert hexadecimal to floating point
- Floating-point encoding adopts IEEE-defined encoding.

Float double is converted in the same way. Because the indicated range is different, the encoding method is somewhat special.
- 1. Floating-point Encoding

Floating-point encoding converts a floating-point number to a binary number. It is divided into three parts by scientific notation.

1. symbol domain

2. Index domain

3. End number field

As shown in:

The highest bit is the sign bit, indicating positive and negative

The eight digits after removing the symbol bit are exponential fields.

The last 23 digits indicate the ending number.

1. Convert Positive floating point to hexadecimal Representation

2. Convert floating point to hexadecimal Storage

Now we need to convert the floating point number into hexadecimal format and store it in the memory. The conversion steps

1. convert a floating point number to binary

For example, 12.25 is converted to binary = 1100.01.

The integer can be directly converted to binary. The decimal number is continuously rounded to * 2.

Example: 0.25

0.25*2 = 0.5 integer = 0

0.5*2 = 1.0 the sum is 1.

Convert all 12.25 to binary, which means 1100.01

2. Calculate the index bit

To calculate the index, first move the decimal point to the place where the highest digit is 1.

That is, the symbol bit or not. Move to the place where the highest bit is 1. After conversion of 7.25

When 0111.01 is moved to the highest bit, it is 1.1101.

1100.01 move 1.10001: a total of three places are moved. One place is moved at a time, and the index is + 1.

As the index moves three digits, 3 + 127 (8 digits) = 130 is converted to binary 10000010, which is the index bit.

That is to say, the eight digits after the symbol bits are the exponent bits. The value above is the exponent bits.

Why + 127. A negative number may occur. Decimal 127 can represent binary 01111111. IEEE floating-point encoding rules

When the index field is <0111111, It is a negative number. if it is greater than 01111111, it is a positive number. so 01111111 is 0. IEEE floating point encoding. so remember it. 127. it can also be understood that the index field is 8 bits, indicating a value of 128. but IEE stipulates. therefore, the maximum value of the-1 index is-1.

3. Calculate the ending number

After calculation, our symbol is 1, but the symbol bit remains unchanged. Because it is a positive floating point, the symbol bit is 0:

Exponential value: 130 10000010

Calculate the ending number. The ending number is the value after the decimal point.

The ending number of 1.10001 is 10001, but it is not a group of 23 digits, So we fill in 0.

1000 1000 0000 0000 0000 000 after 0 population, we need to separate from left to right by 4 bytes

100 0100 0000 0000 0000 after separation.

In this case, add the previous symbol bit and index bit.

0100 0001 0100 0100 0000 0000 0000 0000 this is spliced. we convert it to a hex system for storage.

0x41440000 in memory, our floating point number 12.25 is actually stored in hexadecimal format 0x41 44 00.

2. convert a negative floating point to a hexadecimal representation.

The negative number is the same as the above. The exponential bit is also calculated as follows:

1. Convert to scientific notation.

2. Mobile index position.

3. Calculate the index bit

4. Zero to 23 digits of the ending number.

5. Splice and convert binary data into hexadecimal data.

1. Convert to scientific notation

-0.125 = 0.001

2. Mobile index bit

At this time, the moving index is to move to the right of the decimal point, to the place where the highest digit is 1.

0.001 => 1.0 move three digits, calculate-3. Move to the right is a negative number.

If the value is 1.0, 1 indicates a negative number, and the index is a negative number.

3. Calculate the index bit.

In the above calculation, the index is to move to the left of the decimal point. So the index is added. Now it is to move to the right. So subtract

127-3 = 124 convert to binary = 01111100

4. Zero-padding

0000 0000 0000 0000 0000

5. concatenate the ending number of the symbol bit index bit

1011 1110 0000 0000 0000 0000 0000 (32-bit in total)

Convert to hexadecimal

0xbe00 0000

Therefore, the hexadecimal value of-0.125 in the memory is 0xbe000000.

3. Convert Positive floating point hexadecimal to floating point resolution

We will convert it to hexadecimal, so we need to convert it back.

1.16 hexadecimal split into binary.

2. Separate the signed bits and the ending bits

3. Determine whether the index is a negative number or an integer.

4. Mobile index bit

For example, our 12.25f. hexadecimal format is x41440000.

1.16 hexadecimal to binary

0100 0001 0100 0100 0000 0000 0000

2. Separate the signed bits and the ending bits

0 10000010 10001000000000000000000

3. Obtain the exponent bit

The index position is 10000010> 01111111, so we can determine that our decimal point is a positive number.

10000010-01111111 = 130-127 = 3;

The number of digits we want to move

4. Mobile index bit

First, the calculated index is converted to a 2-digit System 3 = 0011;

Then, in turn, the ending number moves three places to the right, as shown in the following figure.

100010> 3 = 100.010 the maximum number of tails is not required.

Then add the symbol.

The sign bit is 0, indicating a positive number. Therefore, + 1

1100.010

Another example

7.25 The hexadecimal value of memory is 0x40e8

Convert 1.16 hexadecimal to binary

0100 0000 1110 1000 0000 .....

2. Calculate the index position. Move the ending number to the right of the Commission for Discipline Inspection.

10000001-01111111 = 129-127 = 2; 2 digits are moved.

3. Move the ending number

Because the high position is 0, it indicates that the converted floating point number is positive. In the end, we must add 1 to the high position.

11010 => 2 bits = 11.010

The sign bit is 0. Therefore, the high position is supplemented by 1.

111.01 the binary value is converted to decimal to 7.25.

Convert decimal to decimal:

. 01 is a two-digit two to the power of 1 to the power of 2-two.

First Digit: 0x1/2-1 to the power.

Second digit: 1x1/2 to the power.

Add the final result.

If there are three digits, use the third digit * 1/2-3 power.

0*1/2 + 1*1/4 = 0. 25. So we can calculate 0.25

4. Double Type resolution.

The double type conversion is the same as float, except that the index bit is changed to 11 bits. The remaining 42 BITs indicate the ending bits.

2 ~ The power of 11-1, that is, the index used for calculation, that is, 1023.

3. Floating Point Assembly 1. Floating Point Stack

Because of the floating point coprocessor, the operation of floating point commands is a little different. It is implemented through floating point registers.

The floating-point register is implemented through the stack structure. It is also called the floating-point stack. It is written from St (0)-ST (7), where St (0) is written by default)

To operate any floating point stack, you must add the serial number ST (7 );

It is worth noting that the floating-point stack is a cyclic stack. That is to say, the data from the St (0) stack will be placed in the ST (7.

2. Floating Point Assembly

For coprocessor, the corresponding assembly is also provided for operation.

The FST command and fcom FADD command

Uppercase

- Stack pressure command

Using in pushes a floating point in to the floating point stack.

Fild in pushes integers into the floating point stack mem32/64 80

Fldz defaults to 0, and floating point stack is 0
Output stack command

FST out stores the value of the floating point stack top (ST (0) to the out storage. out can be mem32/64, but not the stack.

Fstp out stores the same value as FST out, but will output the stack.

The fistp out stack is stored as an integer for out.

- Stack comparison

You can also compare the values in the stack to change the flag space.

Fcom in compares the content of the in address with that of the floating point stack (ST (0 ));

Ftst compares top stack (ST (0); is it empty.
Floating Point Addition

FADD in adds the data of ST (0) to in. The value is stored in the top ST (0); of the stack.

Faddp ST (N), St calculates the data in the ST (n) stack on the data in the ST (0). There are 7 Floating Point stacks. Then the value of N is 0 ~ 7;

Execute an export stack winter jujube, and then add the result to store it in St (0.

3. Use inline floating point assembly for addition

`int main(int argc, char* argv[]){ float a = 11.25; float c = 12.35; float d = 13.25f; float b = 0.0f; __asm{ fld dword ptr[ebp - 0x4]; fld dword ptr[ebp - 0x8]; fld dword ptr[ebp - 0xc]; faddp st(1),st(0) fstp dword ptr[ebp - 0x10]; } printf("%f \r\n",b); return 0; }`

Implementation result:

- Return Value of Floating Point

`float GetFloatValue(){ return 12.25f;}int main(int argc, char* argv[]){ int value = GetFloatValue(); return 0; }`

Watch the Assembly. The Assembly is divided into two layers: calling and calling.

In-call: that is, inside the getfloatvalue () function.

` push ebp mov ebp,esp sub esp,40h push ebx push esi push edi lea edi,[ebp-40h] mov ecx,10h mov eax,0CCCCCCCCh rep stos dword ptr [edi] fld dword ptr [[email protected]@4002c400000000000000 (00423fd0)]`

Let's look at the last one. The swap memory value is actually converting our floating point number into IEE encoding and putting it in the memory.

It is actually stored in the memory.

Outer call: after the call is completed.

`0040EB1D call __ftol (004010ec)0040EB22 mov dword ptr [ebp-4],eax`

After the call is completed, the _ ftol. floating point number will be converted to an integer for conversion. The following return values will be placed in our local variables.

So we will see this operation later. The returned value is float or double type. The conversion is performed.

_ Ftol internal

`004010ec push mov EBP, esp004010ef add ESP, 0f4h; floating point exception check 004010f2 wait004010f3 fnstcw word PTR [ebp-2] 004010f6 wait004010f7 mov ax, word PTR [ebp-2] 004010fb or ah, 0ch004010fe mov word PTR [ebp-4], ax00401102 fldcw word PTR [ebp-4]; take eight bytes from STR (0) and put them in the local variable EBP-Och. therefore, qword PTR represents 8 bytes .; pop up ST (0); from the stack. 00401105 fistp qword PTR [ebp-0Ch] 00401108 fldcw word PTR [ebp-2]; The eax edX below is used together, And eax stores the 4-byte integer section. edX stores the fractional part. 0040110b mov eax, dword ptr [ebp-0Ch] 0040110e mov edX, dword ptr [ebp-8] flat return. 00401111 leave00401112 RET`

Internally, floating point conversion, comparison, and so on.

Iv. boolean type

Boolean is represented by 0 and 1. In the memory, this is the representation form. 0 is false. 1 is true.

Address, pointer, and reference expression

- Address

In C ++, use the & get address symbol to use the address. Get the memory address of a variable.
- Pointer

The essence of pointer is to store the address, but there is a type to describe how to store the address. For example

Char szbuff [10] = {1, 2, 3 ...};

Char*SZ = szbuffer; then SZ stores the address of szbuffer, except that a is interpreted as 1 byte.*

For example, SZ ++, because it is char type, the address is + 1. If it is int type, + 1 is + 4 bytes.

If you describe the contentSZ, the value at this time is 2, because it is Char*Type description address SZ ++*SZ is 3
Reference

In C ++, create a reference type & A = szbuffer; when creating a reference, you must initialize the variable.

Essentially, it is the alias of a variable. In memory, it is actually an operation to get the address content.

1. pointer addressingWe have said that pointers have different expressions, such as byte * short.*...*

Because pointers have different expressions, auto-increment and auto-subtraction will generate offset calculation.

For example:

MoV eax, byte PTR [EBP-0xc];

MoV EBX, byte PTR [EBP-0xb];

MoV ECx, byte PTR [EBP-0xa];

....

So we can sum up an addressing formula.

Destination Address = first address + sizeof (type)N value.

The destination address is what we want to address.

Sizeof (type) is your data type size

The value of N is your offset.

For example, an array:

Char szbuf [10] = {1, 2... 7, 8, 9, 10 };

We want to obtain the value at the position where the subscript is 8.

Advanced Code: int A = szbuf [8]; finished.

Because there is a formula, we don't need to write it like this.

As follows:

Destination Address = first address + sizeof (type) * n; set of Formulas

Szbuffer = szbuffer + sizeof (char) * 8;

In this case, the address of szbuffer points to the position of 8 in the following table of the array. We can obtain the value of szbuffer from the content.

`int main(int argc, char* argv[]){ char szBuf[10] = {1,2,3,4,5,6,7,8,9,10}; char *dst = szBuf + sizeof(char) * 8; printf("Value = %d\r\n",*dst); system("pause"); return 0; }`

PC reverse code Restoration Technology: first, the presentation of basic data types in memory. Floating Point and pointer addressing Formulas