Calls -

and how they make use of the stack

by Ignatz of stoicForce



Generals

This is a paper on calls and how a program uses the stack to pass variables to a call. this can be very useful especially for newbies. i don´t think that experienced crackers will get much out of it, but if you don´t know how a stack works, what a call does and how parameter are passed to a call then this could help you a lot.
Also i want to state that everyone is responsible for his actions. i will not be held responible for any illegal action you might use the knowlege provided here for. so lets get comfortable and enjoy.


Needed tools

All you need is i) some free soace in your brain and ii) a drink;
a longisland-icetea will do the job: 4 cl rum, 4 cl tequila, 4 cl whiskey, 4 cl wodka, some lemonjuice and then just fill it up with coke. it´s perfect.


Why calls?

I´m sure you already asked youself what is a call. what is it good for? imagine you impement a program and have to write text to the screen very often for example. then this text won´t be the same everytime but the routine, the code, to bring it on screen will be the same every time. so you would have to write the whole code over and over again for every message you have to put on screen. but there is a cheaper way. just write the code down once and give this piece of code a name, a reference, like "write_to_screen". then all you would have to do instead of writing all the code again and again is just calling the name, lets say the function or call "write_to_screen". but wait there is still another problem: we do have different messages, so there needs to be a variable like "msg" that holds the message we want to print out. and of course we have to pass this variable to the function. this would then look like this in high level language like C++:
write_to_screen(msg);
but what does it look like in assembler? it would look like this:
push msg
call write_to_screen
this example shows the two topics explained in this tutorial. what a call is and why you need to pass variables to a call. now you know what a call is good for and what it does. maybe you´re irritated by the push so the next thing we need to approach is the stack.


The stack

This is a structure that stroes values. these are always 4 byte (= 1 DWORD) long. it works LIFO (Last In First Out). this means a value that was recently put on the stack will be get of the stack first. there are only two commands to work with the stack. these are called push and pop. push puts a value on the stack and pop gets a value from the stack. so lets have a quick example.
push a		Stack= {a}
push b		Stack= {a,b}
push c		Stack= {a,b,c}
pop eax		Stack= {a,b} eax = c
pop ebx		Stack= {a} eax = c; ebx = b
push eax   	Stack= {a,c} eax = c; ebx = b
push 5		Stack= {a,c,5} eax = c; ebx = b
but push an d pop also do additional things. to understand that we must first have a look at e the register ESP (Stack Pointer. this register always points to the beginning of the stack. this means the last made entry. so if you push a value esp is being decreased by 4, if you pop a value esp is increased by 4. example:
ESP = 7E0000; EAX = 01020304
: ...
:7DFFF0 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
:7E0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
this is the initial state so the stack is filled with 78563421.

if you now push EAX then you will have the following.
ESP = ESP - 4 = 7DFFF0                      ESP points here
: ...                                       |
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
as you can see the stackpointer gets adjusted and
the value is written to the correct position.

pop ebx
you can now pop the value again
ESP = ESP + 4 = 7E0000		EBX = 01020304
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
        |
        ESP now points here.
        notice that the popped value is not changed.

of course you can also add or sub something from ESP.
lets see what happens if we add 1 to the ESP

ESP = ESP + 1 = 7E0001
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
           |
           ESP now points here.

lets now pop a value
pop EBX
ESP = ESP + 4 = 7E0005
:7DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:7E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
                       |
                       ESP now points here.
and EBX gets 00785634

by adding one we see that the stack gets "out of order" so you should only
add something multiplied by 4 to the ESP.
now you know how a stack works and what it does so lets take an inside look to calls.


Calls - the inside

As you have seen, the stack a an ideal place to store values. lets have another look at the little example we had before. With our new knowlege we can understand what happens and even show as a serious bug.
push msg              ; this won´t work because we can only push 4 bytes!
call write_to_screen  ; the call will then read the data off the stack
so we have to pass the address of the msg. we do this easily with the command lea eax, msg. AX now has the addres of msg. then we push the address with push eax. lets bloat this up and make eit rea´l so you can see what exaclty is going on.
data: EAX = 00000000
:00450000 31 32 33 34 35 36 37 38-39 30 00 00 00 00 00 00   1234567890......

stack: ESP = 007E0000
:007DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 04 03 02 01
:007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
this is all before the push

:00412l00 lea eax, msg  ; nothing changes exept for EAX is set to 00450000
:00412104 push eax	  ; data stays the same but the stack changes
              ; stack: ESP = 007DFFFC                         ............ address
              ; :007DFFF0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 45 00
              ; :007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
:00412105 call write_to_screen
              ; put the serial to the screen.
			  ; short break ---
:00412110 next instruction ...
what will the call do now? it will do one very important thing. it will automatically push the address of the next instruction on the stack. why does it do this? because it is a call not a jmp and after it has done what it had to do, the program should continue after the routine was called- that´s what a call is all about. so it stores the return address on the stack so the pc knows where to go afterwards. let´s see what the stack looks like after entering the call:
stack: ESP = 007DFFF8             ........... return-address pushed to stack
:007DFFF0 00 00 00 00 00 00 00 00-10 21 41 00 00 00 45 00
:007E0000 12 34 56 78 00 00 00 00-00 00 00 00 00 00 00 00
and the call will continue.
so whenever you enter a call you have the return address on top of the stack. there is only one thing left now: how does the call read the data from the stack?


Reading data from the stack

This is the most interesting part, and there are many ways to archieve this. the first possibility is to pop the returnvalue and store it somewhere and then pop all other data and push the returnaddress back. this of course is very complicated especially if you have too many values and a huge call. this will force you to save the values again on the stack because you can´t hold all the data an the registers. it might be ok for a small call with few parameters.
so what is the other way round? easy you just save the EBP (Base Pointer used to adress variables) by pushing it on the stack and then get the stackaddress into EBP by mov EBP, ESP. now you can address all variables EBP relative like mov eax , [EBP + 20]. this way you get a better grip of the stack. you can still use the stack normally in the call and just have to make sure that the returnvalue is on top of the stack and that you recalled EBP when you leave the call.
lets take a look at a simple example. i extracted this from MP3 CD Maker with Win32DASM:
beginning of the call
:004301A1 push ebp                    ; ebp is stored
:004301A2 mov ebp, esp                ; now ebp points at the  top of the stack
                                      ; you do not have to care for pushes and pops
                                      ; because you address the parameters EBP
                                      ; relative now
:004301A4 mov eax, dword ptr [ebp+08] ; this equals pop eax, pop eax but you´d
                                      ; lose the return address. ;(
:004301A7 push esi                    ; store another value..
.
. call routine unimportant.
. leaving the call
:004301FF pop esi                     ; restore  esi
:00430200 pop ebp                     ; restore the original base pointer
:00430201 ret                         ; now the returnaddress is on top of the stack

hint you might the see something like mov eax, [ebp+10]. now you can name the [ebp+10] variable because it will always point at the same value in the call. in a protection call with name and serial for example you could say [ebp+10] is the name and [ebp+14] is the serial. this makes programs and especially deadlistings lot easier to read.
with all this knowledge we shold know have a look at some live codesnippets extracted with Win32DASM.


Live snippets

I)

First example will be the call GetWindowText. to get a grip on it lets see what the MSDN says about it:
int GetWindowText( HWND hWnd, // handle to window or control with text LPTSTR lpString, // address of buffer for text int nMaxCount // maximum number of characters to copy ); If the function succeeds, the return value is the length, in characters, of the copied string, not including the terminating null character. (else it´s zero)
the returnvalue will get stored in EAX. and how about the tree parameters? (hWnd, lpString, nMaxCount). to see about this lets have a look at the deadlisting:
:00445273 push 00000020 ; nMaxXount
:00445275 push eax      ; address for string
:00445276 push edi      ; hWnd

* Reference To: USER32.GetWindowTextA, Ord:015Eh
          |
:00445277 Call dword ptr [0044C430]
see how the values are pushed on the stack? so when a program gets a serial and you want to know where it is stored, all you have to do is set a breakpoint at the second push and read the address in eax- thats it.

II)

The next example is a function from MP3CD Maker that upcases the name. to see if a call is likely to be associated with the protection, see what the parameters are by identifying what is pushed before the call. also check the results of the call by seeking which parameters were changed by the call and if it has a returnvalue.
:00421539 lea  eax, dword ptr [ebp-74] ; eax holds the address to the Name
:0042153C push eax                     ; the address is pushed on the stack
                                       ; and passed to the call
:0042153D call 0043BB82                ; only one parameter.
:00421542 add esp, 00000004            ; stack adjustment <-----------
                                                                     |
the beginning of the call:                                           |
:0042BF40 push ebp     ; using th EBP - relative method.             |
:0042BF41 mov ebp, esp ; you should know by now                      |
:0042BF43 push edi     ; edi and                                     |
:0042BF44 push esi     ; esi are pushed to stack                     |
-naming the variables:                                               |
:0043BB96 mov eax, dword ptr [ebp+08] ; you could name               |
                                      ; ebp+08 regName becs it holds |
                                      ; the value of the name in     |
                                      ; order to upcase it           |
-leave the all                                                       |
:0042C09C pop edi      ; but only edi gets popped                    |
:0042C09D leave        ; so there seems to be something wrong        |
:0042C09E ret          ; there needs to be an ------------------------
now we could even name the call here like "void RegNameToUpCase(char* Name)"
now you should be able to read a lot more assembler because the many commands between calls are just preparing the parameters for the next call.



Concluding remarks

Go and find out about calls and stacks yourself. try it. don´t waste time searching for the serial, set a breakpoint at the parameter before getwindowtexta. being able to identify parameters for a call will also enable you to "name" calls. also making deadlistings more readable.

of course any comments and critics are welcome. just mail me Ignatz or visit stoicForce


yours truly
Ignatz - Make cracking more enjoyable.