Reverse Engineering for Beginners

(avery) #1

CHAPTER 46. VARIADIC FUNCTIONS CHAPTER 46. VARIADIC FUNCTIONS


mov edx, DWORD PTR [rcx] ; load 2nd argument
mov r8d, 1 ; count=1
cmp edx, -1 ; 2nd argument is -1?
je SHORT $LN8@arith_mean ; exit if so
$LL3@arith_mean:
add eax, edx ; sum = sum + loaded argument
mov edx, DWORD PTR [rcx+8] ; load next argument
lea rcx, QWORD PTR [rcx+8] ; shift pointer to point to the argument after next
inc r8d ; count++
cmp edx, -1 ; is loaded argument -1?
jne SHORT $LL3@arith_mean ; go to loop begin if its not'
$LN8@arith_mean:
; calculate quotient
cdq
idiv r8d
ret 0
arith_mean ENDP


main PROC
sub rsp, 56
mov edx, 2
mov DWORD PTR [rsp+40], -1
mov DWORD PTR [rsp+32], 15
lea r9d, QWORD PTR [rdx+8]
lea r8d, QWORD PTR [rdx+5]
lea ecx, QWORD PTR [rdx-1]
call arith_mean
lea rcx, OFFSET FLAT:$SG3013
mov edx, eax
call printf
xor eax, eax
add rsp, 56
ret 0
main ENDP


We see that the first 4 arguments are passed in the registers and two more—in the stack. Thearith_mean()function first
places these 4 arguments into theShadow Spaceand then treats theShadow Spaceand stack behind it as a single continuous
array!


What about GCC? Things are slightly clumsier here, because now the function is divided in two parts: the first part saves the
registers into the “red zone”, processes that space, and the second part of the function processes the stack:


Listing 46.3: Optimizing GCC 4.9.1 x64

arith_mean:
lea rax, [rsp+8]
; save 6 input registers in "red zone" in the local stack
mov QWORD PTR [rsp-40], rsi
mov QWORD PTR [rsp-32], rdx
mov QWORD PTR [rsp-16], r8
mov QWORD PTR [rsp-24], rcx
mov esi, 8
mov QWORD PTR [rsp-64], rax
lea rax, [rsp-48]
mov QWORD PTR [rsp-8], r9
mov DWORD PTR [rsp-72], 8
lea rdx, [rsp+8]
mov r8d, 1
mov QWORD PTR [rsp-56], rax
jmp .L5
.L7:
; work out saved arguments
lea rax, [rsp-48]
mov ecx, esi
add esi, 8
add rcx, rax
mov ecx, DWORD PTR [rcx]
cmp ecx, -1
je .L4
.L8:
add edi, ecx

Free download pdf