From: http://bbs.pediy.com/showthread.php? T = 89379
Question: [Share] from C language to assembly, from assembly to C Language
Author: wzjok
Time: 2009-05-20, 17: 03
Chain: http://bbs.pediy.com/showthread.php? T = 89379
To engage in "reverse engineering" or be interested in it, you must be familiar with the assembly language. However, our understanding of computer languages begins with advanced languages (such as C, VB, and dephi. When we read machine languages translated from advanced languages, we will certainly encounter many obstacles. Below are some notes I made after reading the relevant books. I hope it will be of reference value!
I. Cyclic statements and compiled machine language
1. For Loop
Below is a piece of C language code. Our purpose is to look at the results of its disassembly:
Int myfunction (int A, int B)
{
Int c = A + B;
Int I;
For (I = 0; I <50; I ++)
{
C = c + I;
}
Return c;
}
The previous disassembly will temporarily ignore it. Here, the disassembly will start from the place of for, and the result is as follows:
For (I = 0; I <50; I ++)
00412BC7 mov dword ptr [I], 0 // I = 0; assign the initial value to the cyclic variable
00412BCE jmp myfunction + 39 h (412BD9h) // jump to the first loop
> 00412bd0 mov eax, dword ptr [I]
| 00412bd3 add eax, 1 // I ++; modify the cyclic variable
| 00412bd6 mov dword ptr [I], eax
| 00412bd9 cmp dword ptr [I], 32 h // compare the relationship between I and 50 and check the cyclic conditions
| 00412bdd jge myfunction + 4ah (412 Beah) // when I> = 50 [that is! (I <50 )]
| {
| C = c + I;
| 00412BDF mov eax, dword ptr [c] // variable c
| 00412BE2 add eax, dword ptr [I] // variable I
| 00412BE5 mov dword ptr [c], eax // c = c + I;
|}
<00412BE8 jmp myfunction + 30 h (412BD0h) // jump back and modify the Loop Variable
00412BEA mov eax, dword ptr [c]
}
We can see that the for loop mainly uses the following commands to implement: mov initialization. Jmp skips the loop variable to change the code. Cmp implements condition judgment, and jge redirects Based on the condition.
Use jmp to return to the loop and change the code for the next loop. Therefore, the for structure has the following notable features:
Mov <cyclic variable>, <initial value>; assigns the initial value to the cyclic variable
Jmp B; jump to the first loop
A: (change the cyclic variable); Modify the cyclic variable.
...
B: cmp <cyclic variables>, <restricted variables>; check cyclic conditions
Jgp jump out of Loop
(Loop body)
...
Jmp A; jump back and modify the Loop Variable
2. do Loop
Let's take a look at the do loop. Because the do loop does not modify the part of the loop variable, it is simpler than the for loop.
Do
{
C = c + I;
00411A55 mov eax, dword ptr [c]
00411A58 add eax, dword ptr [I]
00411A5B mov dword ptr [c], eax
} While (c <100 );
00411A5E cmp dword ptr [c], 64 h
00411A62 jl myfunction + 35 h (411A55h)
Return c;
The do loop is a simple conditional jump back. There are only two commands:
Cmp <cyclic variable>, <restriction variable>
Jl <cycle start point>
3. while Loop
While (c <100 ){
00411A55 cmp dword ptr [c], 64 h
00411A59 jge myfunction + 46 h (411A66h)
C = c + I;
00411A5B mov eax, dword ptr [c]
00411A5E add eax, dword ptr [I]
00411A61 mov dword ptr [c], eax
}
00411A64 jmp myfunction + 35 h (411A55h)
Return c;
Obviously, we will find that while is more complicated. In addition to determining the cyclic conditions at the beginning, the while must return to the starting point of the loop with an unconditional jump. Three commands are used for implementation:
A: cmp <cyclic variables> and <restricted variables>
Jge B
(Loop body)
...
Jmp
B: (the loop is over)
In this way, the analysis of the cycle structure in C language is basically finished! Of course, we can use the same method to analyze the relationship between C code and machine disassembly code in the "branch statement" of C language and other data structures!
For the sake of Knowledge integrity, here is a supplement to the branch statement in C Language
Ii. Branch statements
1. if-else statement
To observe its Assembly statements, the following is a simple if judgment structure:
If (a> 0 & A <10)
{
Printf ("a> 0 ");
}
Else if (a> 10 & A <100)
{
Printf ("A> 10 & A <100 ");
}
Else
{
Printf ("a> 10 & a <100 ");
}
If statements are based on cmp and conditional jump commands. Generally, if (A & B) is rejected. If A is not true, immediately jump to the next branch. In turn, if B is not true, it also jumps out of a branch.
Cmp Conditions
Next branch of jle
So the first part of the disassembly is:
If (a> 0 & a <10)
00411A66 cmp dword ptr [c], 0
00411A6A jle 411A81h; jump to the next else if judgment point
00411A6C cmp dword ptr [c], 0Ah
00411A70 jge 411A81h; jump to the next else if judgment point
{
Printf ("a> 0 ");
00411A72 push offset string "a> 0" (4240DCh)
00411A77 call @ ILT + 1300 (_ printf) (411519 h)
00411A7C add esp, 4
}
Else if and else both start with an unconditional jump to the judgment end, and stop the previous branch from directly entering the branch after execution. The only way this branch can be executed is that the previous judgment conditions are not met.
Else performs the operation directly after jmp. Else if starts to repeat the operations after if, uses cmp for comparison, and then uses the conditional jump command for line jump.
Else if (a> 10 & a <100)
00411A7F jmp 411AA9h; jump directly outside the judgment Block
00411A81 cmp dword ptr [c], 0Ah; comparison + conditional jump, the target is the next branch
00411A85 jle 411A9Ch
00411A87 cmp dword ptr [c], 64 h
00411A8B jge 411A9Ch
{
Printf ("A> 10 & A <100 ");
00411a8d push offset string "A> 10 & A <100" (424288 H)
00411a92 call @ ILT + 1300 (_ printf) (411519 H)
00411a97 add ESP, 4
}
Else
00411A9A jmp 411AA9h; here is else, so there is only one simple jump.
{
Printf ("a> 10 & a <100 ");
00411A9C push offset string "a> 10 & a <100" (424288 h)
00411AA1 call @ ILT + 1300 (_ printf) (411519 h)
00411AA6 add esp, 4
}
Return c;
2. switch-case statement
A switch is characterized by multiple judgments. Because swtich obviously does not need to judge whether it is greater than or less than, it is all je (therefore, switch statements in C language do not support float type variables), jump to each case. The last one is the unconditional jump, directly jump to the default place. The following code:
Switch ()
{
Case 0:
Printf ("a> 0 ");
Case 1:
{
Printf ("a> 10 & a <100 ");
Break;
}
Default:
Printf ("a> 10 & a <100 ");
}
Disassembly switch ()
00411A66 mov eax, dword ptr [a]
00411A69 mov dword ptr [ebp-0E8h], eax
00411A6F cmp dword ptr [ebp-0E8h], 0 // case 0:
00411A76 je 411A83h
00411a78 cmp dword ptr [ebp-0E8h], 1 // Case 1:
00411a7f je 411a90h
00411a81 JMP 411a9fh // default:
{
...
It is obvious to compare whether a is 0 and 1. Assembly instructions first move a to the [ebp-0E8h] address, and then compare, This is the characteristics of the debug version compilation. Is it possible to prevent stack corruption caused by direct stack operations? The last one jumps directly to the default place. Of course, if there is no default, it will jump out of swtich.
From this point, we can find that in the switch statement, the command that completes the "comparison judgment" will be two parts of the "case" command. in the Assembly, it is not translated one by one according to the C statement, it is implemented separately by two command modules!
Case 0:
Printf ("a> 0 ");
00411A83 push offset string "a> 0" (4240DCh)
00411A88 call @ ILT + 1300 (_ printf) (411519 h)
00411A8D add esp, 4
Case 1:
{
Printf ("a> 10 & a <100 ");
00411A90 push offset string "a> 10 & a <100" (424288 h)
00411A95 call @ ILT + 1300 (_ printf) (411519 h)
00411A9A add esp, 4
Break;
00411A9D jmp myfunction + 8Ch (411 AACh)
}
Default:
Printf ("a> 10 & a <100 ");
00411A9F push offset string "a> 10 & c <100" (424288 h)
00411AA4 call @ ILT + 1300 (_ printf) (411519 h)
00411AA9 add esp, 4
}
For the case and default branches, if break exists, an unconditional jump Assembly command is added. Without a break, there is no circular control code.
Summary: if multiple consecutive "comparison cmp" and "equal jump je" statements are found in the disassembly code, the "switch" statement will be reminiscent!