in the name of zero

April 26, 2006

elf magic again

Filed under: hermetic studies

the rundown basicly consists of the following:
1) make a shared library
2) make a program that calls it
3) inspect the shared object, like what happened before.
4) inspect the main program, like what happened before.

first comes the shared library (stephy.so) steppings. (i just love the word step!)

/** stephy. c - shared elf object file example
 *
 * gcc -fpic -shared -o stephy.so stephy.c -lc
 *
 * notes:
 *
 * -fpic
 *      implies poisition independent addressing
 * -c
 *      compile, don't link
 *
 * -shared
 *      produce a shared object that can be linked
 *  with other objects to form an executable.
 *
 * -lc
 *      link with the libc.a library
 *
 * 04/22/06 stephanie
 */
	
#include <stdio.h>
	
void banner(char *sentence)
{
        printf("%s\n", sentence);
}

the first thing i noticed from its disassembly is that it doesn’t have a PT_INTERP section. so a position independent, elf shared object file relies on another program to call the dynamic linker and finish its own relocations for itself to be integrated in the calling program. as with an executable elf object, a shared elf object also has a base address which is the lowest virtual address associated with the memory image of the program’s object file.

i focused on three parts of this shared object file. sections plt and got-plt and finally, void banner’s disassembly listing.

this is how the relevant section .plt looks like:

00000448 <printf@plt-0x10>:
 448:   ff b3 04 00 00 00       push   DWORD PTR [ebx+4]
 44e:   ff a3 08 00 00 00       jmp    DWORD PTR [ebx+8]
 454:   00 00                   add    BYTE PTR [eax],al
        ...
	
00000458 <printf@plt>:
 458:   ff a3 0c 00 00 00       jmp    DWORD PTR [ebx+12]
 45e:   68 00 00 00 00          push   0x0
 463:   e9 e0 ff ff ff          jmp    448 <_init+0x18>

we are examining a position independent object file. as one may have noticed, it has a different addressing mode over absolute procedure linkage table entries since ebx is added to an offset number. more on this as we go along.

then, verifying that the shared object’s global offset table entry zero still points to it’s dynamic section is sufficient i guess. the disassembly tells me that stephy.so’s got-plt table is located at address 0x16bc.

steph@gdb $ x/x 0x16bc
0x16bc <__JCR_LIST__+208>:      0x000015f0

i verfied that address 0x15f0 is indeed the shared object’s .dynamic section by using objdump.

steph@heaven ~/git/null/c/symbol-resolution $ objdump -d --section=.dynamic stephy.so
	
stephy.so:     file format elf32-i386
	
Disassembly of section .dynamic:
	
000015f0 < .dynamic>:
 — snip –

i moved further and tried to understand how the function void banner inside stephy.so is implemented, including how it refers to it’s own procedure linkage entry table entries, e.g. the local printf() function in the object file itself.

first comes the function disassembly.

steph@gdb $ disas banner
Dump of assembler code for function banner:
0x00000554 :  push   ebp
0x00000555 :  mov    ebp,esp
0x00000557 :  push   ebx
0x00000558 :  sub    esp,0x4
0x0000055b :  call   0x560 
0x00000560 : pop    ebx
0x00000561 : add    ebx,0x115c
0x00000567 : sub    esp,0x8
0x0000056a : push   DWORD PTR [ebp+8]
0x0000056d : lea    eax,[ebx-0x10e9]
0x00000573 : push   eax
0x00000574 : call   0x458

0x00000579 : add    esp,0x10
0x0000057c : mov    ebx,DWORD PTR [ebp-4]
0x0000057f : leave
0x00000580 : ret
0x00000581 : nop
0x00000582 : nop
0x00000583 : nop
End of assembler dump.

ahh, the first two instructions are familiar, - function prolog. saves the current frame pointer before assigning a new one. the thing that puzzled me was the instructions starting from banner+7 up to the call to printf@plt. here is how i understood it.

remember, we are taking a look at position independent code here, so these are just techniques to make ebx point to the right location - e.g. the global offset table before call printf@plt. i quote from the elf specification:

2. If the procedure linkage table is position-independent, the address
of the global offset table must reside in %ebx. Each shared object
file in the process image has its own procedure linkage table, and
control transfers to a procedure linkage table entry only from
within the same object file. Consequently, the calling function is
responsible for setting the global offset table base register
before calling the procedure linkage table entry.
and if you still remember, ebx is added to an offest in the procedure linkage entry illustation from before. this is how the flexibility of position independence works. of course, we still need to prove that ebx indeed points to the global offset table right? so lets step into the assembly listing in finer detail now, step by step instruction.

0x00000554 :  push   ebp
0x00000555 :  mov    ebp,esp

function prolog you guys. save the current frame pointer and make the stack pointer, the start address of the new frame.

0x00000557 :  push   ebx
0x00000558 :  sub    esp,0x4

save the old value of ebx. as to why it subs the esp by 4 bytes, i don’t know.

0x0000055b :  call   0x560 
0x00000560 : pop    ebx

ok. so these two instructions are pairs that are really important. the program needs to find the address of the global offset table relative to it’s address. the call instruction pushes the eip on the stack which happens to be the address of the pop ebx instruction after it. then the pop ebx instruction, retrieves the address that the call instruction pushed at the stack. ebx now therefore has the address holds it’s own address.

0x00000561 : add    ebx,0x115c

add the value 0x115c (4444 decimal) to the current address. why? well, let’s do some math. also, for this example, we will be using the absolute address of pop ebx which is 0x00000560. 0x0560 + 0x115c = 0x16bc

steph@gdb $ x/x 0x16bc
0x16bc <__jcr_list__ +208>:      0x000015f0

and if we take a look at address 0x16bc we would notice that it’s actually the first entry (entry zero) of the global offset table! how do we know? coz we already know the address of the our global offset table (from above).

ok, so ebx, how has the address of the global offset table that will evetually be used when the first call to printf@plt resolves. we move to the next set of instructions now.

0x00000567 : sub    esp,0x8
0x0000056a : push   DWORD PTR [ebp+8]

allocate space at the stack again and save the value of ebp+8 on the stack. more on this in a while.

0x0000056d : lea    eax,[ebx-0x10e9]
0x00000573 : push   eax
0x00000574 : call   0x458

again, some math, ebx = 0x16bc, which is consequently, the address of our global offset table. why subtract by 0x10e9? well, to get the address of section .rodata. if we take a look at void banner’s source, we see that it calls printf with two arguments, a “%s” string and a character pointer *sentence. then at last, it calls the procedure linkage table entry for printf which now works like a charm because we already have the address of the got in register ebx.

let’s just print the contents of address 0x10e9 for fun. we have our equation: 0x16bc - 0x1039 = 0x05d3.

steph@gdb $ x/s 0x05d3
0x5d3 <_fini +27>:        “%s\n”

ok! “%s\n” it is! the first argument to the printf() call inside void banner(). we move on.

0x00000579 : add    esp,0x10
0x0000057c : mov    ebx,DWORD PTR [ebp-4]

the banner now does some cleaning and restores ebx’s former value.

and finally, the function epilog.

0x0000057f : leave
0x00000580 : ret
0x00000581 : nop
0x00000582 : nop
0x00000583 : nop    

other than the added ebx register inside the plt definitions, the flow is the same as absolute procedure linkage entry. well, that’s it.

Comments »

The URI to TrackBack this entry is: http://gnurbs.blogsome.com/2006/04/26/elf-magic-again/trackback/

No comments yet.

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>


Get free blog up and running in minutes with Blogsome | Theme designs available here