Programmers use if statements to alter program execution
based on certain conditions. if statements are common in C code
and disassembly. We’ll examine basic and nested if
statements in this section. Your goal should be to learn how to recognize different types of
if statements.
Example 6-8 displays a simple if statement in C with the assembly for this code shown in Example 6-9. Notice the conditional jump jnz at ❷. There must be a
conditional jump for an if statement, but not all conditional
jumps correspond to if statements.
Example 6-8. C code if statement example
int x = 1;
int y = 2;
if(x == y){
printf("x equals y.\n");
}else{
printf("x is not equal to y.\n");
}Example 6-9. Assembly code for the if statement example in Example 6-8
00401006 mov [ebp+var_8], 1
0040100D mov [ebp+var_4], 2
00401014 mov eax, [ebp+var_8]
00401017 cmp eax, [ebp+var_4] ❶
0040101A jnz short loc_40102B ❷
0040101C push offset aXEqualsY_ ; "x equals y.\n"
00401021 call printf
00401026 add esp, 4
00401029 jmp short loc_401038 ❸
0040102B loc_40102B:
0040102B push offset aXIsNotEqualToY ; "x is not equal to y.\n"
00401030 call printfAs you can see in Example 6-9, a decision
must be made before the code inside the if statement in Example 6-8 will execute. This decision corresponds to the conditional
jump (jnz) shown at ❷. The decision to jump is made based on the comparison (cmp), which checks to see if var_4 equals var_8 (var_4 and var_8 correspond to x and y in our source code) at ❶. If
the values are not equal, the jump occurs, and the code prints "x is not
equal to y."; otherwise, the code continues the path of execution and prints "x equals y."
Notice also the jump (jmp) that jumps over the else section
of the code at ❸. It is important that you recognize
that only one of these two code paths can be taken.
IDA Pro has a graphing tool that is useful in recognizing constructs, as shown in Figure 6-1. This feature is the default view for analyzing functions.
Figure 6-1 shows a graph of the assembly code
example in Example 6-9. As you can see, two different
paths (❶ and ❷) of code execution lead to the end of the function, and each path prints a different
string. Code path ❶ will print "x equals y.", and ❷ will print "x is not equal to y."
IDA Pro adds false
❶ and true
❷ labels at the decision points at the bottom of the
upper code box. As you can imagine, graphing a function can greatly speed up the reverse-engineering
process.
Example 6-10 shows C code for a nested if statement that is similar to Example 6-8, except that two additional if statements have been added within the original if
statement. These additional statements test to determine whether z is equal to 0.
Example 6-10. C code for a nested if statement
int x = 0;
int y = 1;
int z = 2;
if(x == y){
if(z==0){
printf("z is zero and x = y.\n");
}else{
printf("z is non-zero and x = y.\n");
}
}else{
if(z==0){
printf("z zero and x != y.\n");
}else{
printf("z non-zero and x != y.\n");
}
}Despite this minor change to the C code, the assembly code is more complicated, as shown in Example 6-11.
Example 6-11. Assembly code for the nested if statement example shown in
Example 6-10
00401006 mov [ebp+var_8], 0 0040100D mov [ebp+var_4], 1 00401014 mov [ebp+var_C], 2 0040101B mov eax, [ebp+var_8] 0040101E cmp eax, [ebp+var_4] 00401021 jnz short loc_401047 ❶ 00401023 cmp [ebp+var_C], 0 00401027 jnz short loc_401038 ❷ 00401029 push offset aZIsZeroAndXY_ ; "z is zero and x = y.\n" 0040102E call printf 00401033 add esp, 4 00401036 jmp short loc_401045 00401038 loc_401038: 00401038 push offset aZIsNonZeroAndX ; "z is non-zero and x = y.\n" 0040103D call printf 00401042 add esp, 4 00401045 loc_401045: 00401045 jmp short loc_401069 00401047 loc_401047: 00401047 cmp [ebp+var_C], 0 0040104B jnz short loc_40105C ❸ 0040104D push offset aZZeroAndXY_ ; "z zero and x != y.\n" 00401052 call printf 00401057 add esp, 4 0040105A jmp short loc_401069 0040105C loc_40105C: 0040105C push offset aZNonZeroAndXY_ ; "z non-zero and x != y.\n" 00401061 call printf00401061
As you can see, three different conditional jumps occur. The first occurs if var_4 does not equal var_8 at ❶. The other two occur if var_C
is not equal to zero at ❷ and ❸.