Reverse Engineering for Beginners

(avery) #1

CHAPTER 7. SCANF() CHAPTER 7. SCANF()


; get a word from memory:
.text:004006E8 lw $a1, x
; value of x is now in $a1.
.text:004006EC la $t9, printf
.text:004006F0 lui $a0, 0x40
.text:004006F4 jalr $t9 ; printf
.text:004006F8 la $a0, aYouEnteredD___ # "You entered %d...\n"
.text:004006FC lw $ra, 0x20+var_4($sp)
.text:00400700 move $v0, $zero
.text:00400704 lw $s0, 0x20+var_8($sp)
.text:00400708 jr $ra
.text:0040070C addiu $sp, 0x20


...


.data:00410920 .globl x
.data:00410920 x: .word 0xA


Why not .sdata? Perhaps that this depends on some GCC option? Nevertheless, nowxis in .data, which is a general memory
area, and we can take a look how to work with variables there.


The variable’s address must be formed using a pair of instructions. In our case those are LUI (“Load Upper Immediate”) and
ADDIU (“Add Immediate Unsigned Word”).


Here is also the objdump listing for close inspection:


Listing 7.11: Optimizing GCC 4.4.5 (objdump)

004006a0

:
4006a0: 3c1c0042 lui gp,0x42
4006a4: 27bdffe0 addiu sp,sp,-32
4006a8: 279c8930 addiu gp,gp,-30416
4006ac: afbf001c sw ra,28(sp)
4006b0: afb00018 sw s0,24(sp)
4006b4: afbc0010 sw gp,16(sp)
4006b8: 8f998034 lw t9,-32716(gp)
4006bc: 3c040040 lui a0,0x40
4006c0: 0320f809 jalr t9
4006c4: 248408d0 addiu a0,a0,2256
4006c8: 8fbc0010 lw gp,16(sp)
; prepare high part of x address:
4006cc: 3c100041 lui s0,0x41
4006d0: 8f998038 lw t9,-32712(gp)
4006d4: 3c040040 lui a0,0x40
; add low part of x address:
4006d8: 26050920 addiu a1,s0,2336
; now address of x is in $a1.
4006dc: 0320f809 jalr t9
4006e0: 248408dc addiu a0,a0,2268
4006e4: 8fbc0010 lw gp,16(sp)
; high part of x address is still in $s0.
; add low part to it and load a word from memory:
4006e8: 8e050920 lw a1,2336(s0)
; value of x is now in $a1.
4006ec: 8f99803c lw t9,-32708(gp)
4006f0: 3c040040 lui a0,0x40
4006f4: 0320f809 jalr t9
4006f8: 248408e0 addiu a0,a0,2272
4006fc: 8fbf001c lw ra,28(sp)
400700: 00001021 move v0,zero
400704: 8fb00018 lw s0,24(sp)
400708: 03e00008 jr ra
40070c: 27bd0020 addiu sp,sp,32


We see that the address is formed using LUI and ADDIU, but the high part of address is still in the $S0 register, and it is
possible to encode the offset in a LW (“Load Word”) instruction, so one single LW is enough to load a value from the variable
and pass it toprintf().


Registers holding temporary data are prefixed with T-, but here we also see some prefixed with S-, the contents of which is
need to be preserved before use in other functions (i.e., “saved”). That is why the value of $S0 was set at address 0x4006cc
and was used again at address 0x4006e8, after thescanf()call. Thescanf()function does not change its value.

Free download pdf