Reverse Engineering for Beginners

(avery) #1

CHAPTER 46. VARIADIC FUNCTIONS CHAPTER 46. VARIADIC FUNCTIONS


_arith_mean PROC NEAR
mov eax, DWORD PTR _v$[esp-4] ; load 1st argument into sum
push esi
mov esi, 1 ; count=1
lea edx, DWORD PTR _v$[esp] ; address of the 1st argument
$L838:
mov ecx, DWORD PTR [edx+4] ; load next argument
add edx, 4 ; shift pointer to the next argument
cmp ecx, -1 ; is it -1?
je SHORT $L856 ; exit if so
add eax, ecx ; sum = sum + loaded argument
inc esi ; count++
jmp SHORT $L838
$L856:
; calculate quotient


cdq
idiv esi
pop esi
ret 0
_arith_mean ENDP


$SG851 DB '%d', 0aH, 00H


_main PROC NEAR
push -1
push 15
push 10
push 7
push 2
push 1
call _arith_mean
push eax
push OFFSET FLAT:$SG851 ; '%d'
call _printf
add esp, 32
ret 0
_main ENDP


The arguments, as we may see, are passed tomain()one-by-one. The first argument is pushed into the local stack as first.
The terminating value (− 1 ) is pushed last.


Thearith_mean()function takes the value of the first argument and stores it in thesumvariable. Then, it sets theEDX
register to the address of the second argument, takes the value from it, adds it tosum, and does this in an infinite loop, until
− 1 is found.


When it’s found, the sum is divided by the number of all values (excluding− 1 ) and thequotientis returned.


So, in other words, the function treats the stack fragment as an array of integer values of infinite length. Now we can
understand why thecdeclcalling convention forces us to push the first argument into the stack as last. Because otherwise,
it would not be possible to find the first argument, or, for printf-like functions, it would not be possible to find the address
of the format-string.


46.1.2 Register-based calling conventions


The observant reader may ask, what about calling conventions where the first few arguments are passed in registers? Let’s
see:


Listing 46.2: Optimizing MSVC 2012 x64

$SG3013 DB '%d', 0aH, 00H


v$ = 8
arith_mean PROC
mov DWORD PTR [rsp+8], ecx ; 1st argument
mov QWORD PTR [rsp+16], rdx ; 2nd argument
mov QWORD PTR [rsp+24], r8 ; 3rd argument
mov eax, ecx ; sum = 1st argument
lea rcx, QWORD PTR v$[rsp+8] ; pointer to the 2nd argument
mov QWORD PTR [rsp+32], r9 ; 4th argument

Free download pdf