Reverse Engineering for Beginners

(avery) #1
CHAPTER 3. HELLO, WORLD! CHAPTER 3. HELLO, WORLD!

11 .text:00000008 sw $fp, 0x20+var_8($sp)
12 ; set the FP (stack frame pointer):
13 .text:0000000C move $fp, $sp
14 ; set the GP:
15 .text:00000010 la $gp, __gnu_local_gp
16 .text:00000018 sw $gp, 0x20+var_10($sp)
17 ; load the address of the text string:
18 .text:0000001C lui $v0, (aHelloWorld >> 16) # "Hello, world!"
19 .text:00000020 addiu $a0, $v0, (aHelloWorld & 0xFFFF) # "Hello, world!"
20 ; load the address of puts() using the GP:
21 .text:00000024 lw $v0, (puts & 0xFFFF)($gp)
22 .text:00000028 or $at, $zero ; NOP
23 ; call puts():
24 .text:0000002C move $t9, $v0
25 .text:00000030 jalr $t9
26 .text:00000034 or $at, $zero ; NOP
27 ; restore the GP from local stack:
28 .text:00000038 lw $gp, 0x20+var_10($fp)
29 ; set register $2 ($V0) to zero:
30 .text:0000003C move $v0, $zero
31 ; function epilogue.
32 ; restore the SP:
33 .text:00000040 move $sp, $fp
34 ; restore the RA:
35 .text:00000044 lw $ra, 0x20+var_4($sp)
36 ; restore the FP:
37 .text:00000048 lw $fp, 0x20+var_8($sp)
38 .text:0000004C addiu $sp, 0x20
39 ; jump to the RA:
40 .text:00000050 jr $ra
41 .text:00000054 or $at, $zero ; NOP


Interestingly,IDArecognized the LUI/ADDIU instructions pair and coalesced them into one LA (“Load Address”) pseudoin-
struction at line 15. We may also see that this pseudoinstruction has a size of 8 bytes! This is a pseudoinstruction (or
macro) because it’s not a real MIPS instruction, but rather a handy name for an instruction pair.

Another thing is thatIDAdoesn’t recognizeNOPinstructions, so here they are at lines 22, 26 and 41. It isOR $AT, $ZERO.
Essentially, this instruction applies the OR operation to the contents of the $AT register with zero, which is, of course, an idle
instruction. MIPS, like many otherISAs, doesn’t have a separateNOPinstruction.

3.5.4 Role of the stack frame in this example.


The address of the text string is passed in the register. Why setup a local stack anyway? The reason for this lies in the
fact that the values of registersRAand GP have to be saved somewhere (becauseprintf()is called), and the local stack
is used for this purpose. If this was aleaf function, it would have been possible to get rid of the function prologue and
epilogue, for example:2.3 on page 5.

3.5.5 Optimizing GCC: load it into GDB.


Listing 3.22: sample GDB session
root@debian-mips:~# gcc hw.c -O3 -o hw
root@debian-mips:~# gdb hw
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mips-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/hw...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x400654
(gdb) run
Starting program: /root/hw
Free download pdf