Reverse Engineering for Beginners

(avery) #1

CHAPTER 20. LINEAR CONGRUENTIAL GENERATOR CHAPTER 20. LINEAR CONGRUENTIAL GENERATOR


; store $a0 to rand_state:
lui $v0, (rand_state >> 16)
jr $ra
sw $a0, rand_state
my_rand:
; load rand_state to $v0:
lui $v1, (rand_state >> 16)
lw $v0, rand_state
or $at, $zero ; load delay slot
; multiplicate rand_state in $v0 by 1664525 (RNG_a):
sll $a1, $v0, 2
sll $a0, $v0, 4
addu $a0, $a1, $a0
sll $a1, $a0, 6
subu $a0, $a1, $a0
addu $a0, $v0
sll $a1, $a0, 5
addu $a0, $a1
sll $a0, 3
addu $v0, $a0, $v0
sll $a0, $v0, 2
addu $v0, $a0
; add 1013904223 (RNG_c)
; the LI instruction is coalesced by IDA from LUI and ORI
li $a0, 0x3C6EF35F
addu $v0, $a0
; store to rand_state:
sw $v0, (rand_state & 0xFFFF)($v1)
jr $ra
andi $v0, 0x7FFF ; branch delay slot


Wow, here we see only one constant (0x3C6EF35F or 1013904223). Where is the other one (1664525)?


It seems that multiplication by 1664525 is done by just using shifts and additions! Let’s check this assumption:


#define RNG_a 1664525


int f (int a)
{
return a*RNG_a;
}


Listing 20.6: Optimizing GCC 4.4.5 (IDA)

f:
sll $v1, $a0, 2
sll $v0, $a0, 4
addu $v0, $v1, $v0
sll $v1, $v0, 6
subu $v0, $v1, $v0
addu $v0, $a0
sll $v1, $v0, 5
addu $v0, $v1
sll $v0, 3
addu $a0, $v0, $a0
sll $v0, $a0, 2
jr $ra
addu $v0, $a0, $v0 ; branch delay slot


Indeed!


20.4.1 MIPS relocations


We will also focus on how such operations as load from memory and store to memory actually work. The listings here are
produced by IDA, which hides some details.


We’ll run objdump twice: to get a disassembled listing and also relocations list:

Free download pdf