1.17 GOTO operator
Let's first understand what GOTO is in C quickly
It simply jumps to a specific place in the code without any condition or comparison or anything
The author started saying that theGOTO operator is often considered an anti-pattern, and the meaning of anti-pattern is a famous or widespread solution
But in reality, it's a bad solution and causes more problems than it solves
This is a simple example:
```c #includeint main() // program entry point; this is the main function where program execution begins { printf(“begin\n”); // print “begin” followed by a newline; this calls printf to output the string goto exit; // jump to the label ‘exit’; this performs an unconditional jump to the specified label printf(“skip me!\n”); // print “skip me!” followed by a newline; this call is skipped due to the goto exit: // label for the jump target; this is the point where execution jumps to printf(“end\n”); // print “end” followed by a newline; this calls printf to output the string };
<p>And this is what came out with MSVC 2012:</p><p>Listing 1.107: MSVC 2012</p>```assembly$SG2934 DB 'begin', 0aH, 00H ; define string "begin\n" in data segment; this allocates a null-terminated string$SG2936 DB 'skip me!', 0aH, 00H ; define string "skip me!\n" in data segment; this allocates a null-terminated string$SG2937 DB 'end', 0aH, 00H ; define string "end\n" in data segment; this allocates a null-terminated string_main PROC ; start of main procedure push ebp ; push EBP onto stack; save base pointer mov ebp, esp ; move ESP to EBP; set up base pointer push OFFSET $SG2934 ; 'begin' ; push address of "begin\n" onto stack call _printf ; call printf function add esp, 4 ; add 4 to ESP; clean up stack after call jmp SHORT $exit$3 ; jump to label $exit$3; unconditional jump push OFFSET $SG2936 ; 'skip me!' ; push address of "skip me!\n" (skipped code) call _printf ; call printf (skipped) add esp, 4 ; clean up stack (skipped)$exit$3: ; label for jump target push OFFSET $SG2937 ; 'end' ; push address of "end\n" call _printf ; call printf add esp, 4 ; clean up stack xor eax, eax ; XOR EAX with itself; set EAX to 0 (return value) pop ebp ; pop EBP; restore base pointer ret 0 ; return from function with 0_main ENDP ; end of main procedureThe goto instruction was simply transformed into a JMP instruction, which has the same effect:
An unconditional jump to another place.
The second printf() cannot be executed except by human intervention, either using a debugger or by patching the code
And this can be a simple and useful exercise in patching.
We open the resulting executable in x32dbg (he did it on Hiew but I will do it on x32dbg)
First, we compile the C code with this command:
```assembly cl /Od /Zi teest.c ; compile teest.c with optimization disabled (/Od) and debug info (/Zi); this command compiles the C file into an executable with debugging symbols ```
And run the exe file on x32dbg and go to main and set Breakpoint at the beginning of Main
The instruction that jmp 0x001071FF which is this
This is supposed to go to the function that goes to Exit
Now we will try to cancel the jmp operation so that it prints what's after it without going to Exit
And we will do this in two ways:
- We change the Assembly from
jmp 0x001071FFtoNOPby selecting it and pressing Space and changing it to Nop like this
And it will run the program normally and output like this
- We change the Hex value and we do as follows:
We select the jmp instruction then Right Click then Follow in dump then Selected Address
Then we see the value in Hex it will be like this
We change the value 07 to 00 which is the same as nop exactly
And we start doing F8 until ret
1.17.1 Dead code
The second printf() call is also called “dead code” in compiler terms.
And this means that this code will never be executed.
That's why, when you compile this example with optimizations enabled,
The compiler removes the dead code, and leaves no trace of it:
Listing 1.109: Optimizing MSVC 2012
```assembly $SG2981 DB 'begin', 0aH, 00H ; define "begin\n"; string constant $SG2983 DB 'skip me!', 0aH, 00H ; define "skip me!\n"; unused string constant $SG2984 DB 'end', 0aH, 00H ; define "end\n"; string constant _main PROC ; start of main push OFFSET $SG2981 ; 'begin' ; push "begin\n" call _printf ; call printf push OFFSET $SG2984 ; 'end' ; push "end\n" $exit$4: ; label (no jump here since optimized) call _printf ; call printf add esp, 8 ; clean up 8 bytes (two pushes) xor eax, eax ; set EAX to 0 ret 0 ; return 0 _main ENDP ; end of main ```But, the compiler forgot to remove the string "skip me!"
If this article helped you, please share it with others!
Some information may be outdated





