# Disassembler > Sucessful reverse engineers do not evaluate each instruction individually unless they must. The process is too tedious. ### Global vs Local Variables *Global variables* can be accessed and used by any function in the program. *Local variables* can be accessed only by the function in which they are defined. Both types of variables are declared similarly in `c` but completely differently in assembly. > **Global** variables are referenced by **memory addresses** > > **Local** variables are referenced by **stack addresses** ### Recognising if Statements In IDA, branches will be represented as such: ```c int x = 1; int y = 2; if (x == y){ printf("x equals y\n"); } else { printf("x does not equals y\n"); } ``` ```assembly 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 printf ``` Here the instruction `jnz` on line 5 causes the branch. A `cmp` is done between `ebp+var_8` (y) and `ebp+var_4`(x). If the values are not equal, then we jump to “x is not equal to y” This is what that looks like in IDA ![1646766562.png](img/1646766562.png) ### Recognising Loops ##### Finding for loops For loops have 4 basic components: 1. initialisation 2. comparison 3. execution instructions 4. increment/decrement ```c int i; for (i=0; i<100; i++) { printf("i equals %d\n", i); } ``` ```assembly mov [ebp+var_4], 0 ; INITIALISATION jmp short loc_401016 loc_40100D: mov eax, [ebp+var_4] ; INCREMENT START add eax, 1 mov [ebp+var_4], eax ; INCREMENT STOP loc_401016: cmp [ebp+var_4], 64h ; COMPARISON jge short loc_40102F ; COMPARISON mov ecx, [ebp+var_4] push ecx push offset aID ; "i equals %d\n" call printf add esp, 8 jmp short loc_40100D ; UNCONDITIONAL JUMP ``` ![1646766968.png](img/1646766968.png) Note: the box on the bottom right is the function’s epilogue ##### Finding While Loops While loops look similar to for loops in assembly, but are easier to understand. ```c int status = 0; int result = 0; while (status == 0) { result = performAction(); status = checkResult(result); } ``` The assembly for this code will look similar to before; however, it lacks the *increment* section. ```assembly mov [ebp+var_4], 0 mov [ebp+var_8], 0 loc_401044: cmp [ebp+var_4], 0 jnz short loc_401063 ; CONDITIONAL JUMP call performAction mov [ebp+var_8], eax mov eax, [ebp+var_8] push eax call checkResult add esp, 4 mov [ebp+var_4], eax jmp short loc_401044 ; UNCONDITIONAL JUMP ``` A conditional jump occurs on line 5 and an unconditional jump at line 13, but the only way for this code to stop executing repeatedly is for that conditional jump to occur. #### Understanding Function Call Conventions Function call conventions govern: - The order in which parameters are placed on the stack or in registers - Whether the caller or callee is responsible for cleaning up the stack Calling convention depends on the compiler used ```c int adder(int a, int b) { return a+b; } void main() { int x=1; int y=2; printf("adder(1,2): %d", adder(x,y)); } ``` ![1646767431.png](img/1646767431.png) ### Switch Statements Switch statements are compiled in two different ways: if style or using jump tables ```c switch(i) { case 1: printf("i = %d", i+1); break; case 2: printf("i = %d", i+2); break; case 3: printf("i = %d", i+3); break; default: break; } ``` ##### If Style ![1646767721.png](img/1646767721.png) ##### Jump Table This example is usually found with large contiguous `switch` statements. The compiler optimises the code to avoid needing to make so many comparisons ![1646767841.png](img/1646767841.png) This assembly uses a jump table which defines offsets to additional memory locations. The switch variable (stored in `ecx`) is used as an index into the jump table. `edx` is multiplied by 4 and added to the base of the jump table to determine which case code block to jump to. It is multiplied by 4 because each entry in the jump table is an address that is 4 bytes in size. ### Disassembling Arrays ```c int b[5] = {123, 87, 487, 7, 978}; void main() { int i; int a[5]; for(i = 0; i<5; i++) { a[i] = i; b[i] = i; } } ``` In assembly, arrays are accessed using a base address as a starting point. The size of each element is not always obvious, but can be determined by seeing how the array is being indexed. ```assembly 00401006 mov [ebp+var_18], 0 0040100D jmp short loc_401018 0040100F loc_40100F: 0040100F mov eax, [ebp+var_18] 00401012 add eax, 1 00401015 mov [ebp+var_18], eax 00401018 loc_401018: 00401018 cmp [ebp+var_18], 5 0040101C jge short loc_401037 0040101E mov ecx, [ebp+var_18] 00401021 mov edx, [ebp+var_18] 00401024 mov [ebp+ecx*4+var_14], edx ; LOCAL 00401028 mov eax, [ebp+var_18] 0040102B mov ecx, [ebp+var_18] 0040102E mov dword_40A000[ecx*4], eax ; GLOBAL 00401035 jmp short loc_40100F ``` In both cases `ecx` is used as the index, which is multiplied by 4 to account for the size of the elements. This is added onto the base address of the array to access the proper array element.