Search This Blog

Monday, August 3, 2009

Never Say Codes are Static

Running Code from Stack/Heap

To make sure we understand this i will try to give as much as details as much possible.

Introduction

An Executable file is a collection of sections which stores information of the code, this may be

We can easily see the code runs from text Section which will be present in the Read only data format, We can summarize
this

1) Text Section – Read Only
2) Data Section – Read/Write
3) BSS Section – Read and Write – This is empty Section the ELF File only has information about the size of the Section, there is no data in this section so we see the section type as NOBITS
When the exe is executed the kernel allocates a process space to the executable with basic sections

1) Text
2) Stack
3) Heap
4) Data Section
5) Environment

We will concentrate to execute a code from stack.

The code starts execution from text section depending on the Loader which starts executing from a fixed address, For most
of the ELF Linked executable it starts with _start, which also calls some more initializers, we can understand them as
constructors. More about ELF Format can be read from www.skyfree.org/linux/references/ELF_Format.pdf

We will start with a very basic code
This C File Runs from the text section. We will try to edit this file to make some code run from stack.
Code Runnig from Heap/Stack:

#include
void Demo(void)
{
printf("He llo this is vijay \n");
re turn;
}
int main()
{
Demo();
re turn 0;
}
1 #include
2 #include
3 #include
4
5
6 void Demo(int (*_printf)(const char *, ...))
7 {
8 _printf("He llo this is Vijay \n");
9 re turn;
10 }
11
12 int main(int arg c, char *arg v[])
13 {
14 const char *buff;
15 int a=0;
16 int (*_printf)(const char *, ...) = printf;
17 int (* _main)(int, char **) = &main;
18 void (*_Demo)(int (*)(const char *, ...)) = &Demo;
19
20 unsig ned int func_le n = (unsig ned int )_main - (unsig ned int)_Demo;
21
22 buff = (const char *)malloc(func_len);
23
24 memcpy(( void *)buff, _Demo, func_len);
25
26
27 _Demo = (void (*) (int (*) (const char *, ...))) &buff[0];
28
29 _Demo(_printf);
30 return 0;


Algorithm:
1) Take the reference address of the Function to be copied in the stack.
2) Take the reference address of main
3) Get the size of function to be copied
4) Allocate this memory in the heap.
5) Copy the offcode of the instruction on the Heap/Stack
For Using Stack Instead of Heap, change the line number 14
< const char *buff;
> const chat buff[200]; Appropriate for the code to be copied
At line number 22, Comment it
6) This should be sufficient for the compiling the code, without any warning.

Verify:
Now, Running this with objdump we get, we will see the code has been copied in the heap memory.


$ objdump -dS SmC_code > test.asm
08048404 :
#include
void Demo(int (*_printf)(const char *, ...))
{
8048404: 55 push %ebp
8048405: 89 e5 mov %esp,%ebp
8048407: 83 ec 08 sub $0x8,%esp
_printf("Hello this is Vijay \n");
804840a: c7 04 24 50 85 04 08 movl $0x8048550,(%esp)
8048411: ff 55 08 call *0x8(%ebp)
return;
}
8048414: c9 leave
8048415: c3 ret
08048416
:
int main(int argc, char *argv[])
{
8048416: 8d 4c 24 04 lea 0x4(%esp),%ecx
804841a: 83 e4 f0 and $0xfffffff0,%esp
804841d: ff 71 fc pushl 0xfffffffc(%ecx)
8048420: 55 push %ebp
8048421: 89 e5 mov %esp,%ebp
8048423: 83 ec 18 sub $0x18,%esp
8048426: 89 4d f4 mov %ecx,0xfffffff4(%ebp)
8048429: 89 5d f8 mov %ebx,0xfffffff8(%ebp)
804842c: 89 75 fc mov %esi,0xfffffffc(%ebp)
const char *buff;
int a=0;
int (*_printf)(const char *, ...) = printf;
int (* _main)(int, char **) = &main;
void (*_Demo)(int (*)(const char *, ...)) = &Demo;
unsigned int func_len = (unsigned int )_main - (unsigned int)_Demo;
804842f: bb 16 84 04 08 mov $0x8048416,%ebx
8048434: 81 eb 04 84 04 08 sub $0x8048404,%ebx
buff = (const char *)malloc(func_len);
804843a: 89 1c 24 mov %ebx,(%esp)
804843d: e8 da fe ff ff call 804831c
8048442: 89 c6 mov %eax,%esi
memcpy(( void *)buff, _Demo, func_len);
8048444: 89 5c 24 08 mov %ebx,0x8(%esp)
8048448: c7 44 24 04 04 84 04 movl $0x8048404,0x4(%esp)
804844f: 08
8048450: 89 04 24 mov %eax,(%esp)
8048453: e8 a4 fe ff ff call 80482fc
/*
for (; a < func_len; a++)
{
buff[a] = ((char *) _Demo)[a];
}
*/
_Demo = (void (*) (int (*) (const char *, ...))) &buff[0];
_Demo(_printf);
8048458: c7 04 24 0c 83 04 08 movl $0x804830c,(%esp)
804845f: ff d6 call *%esi
return 0;
}
8048461: b8 00 00 00 00 mov $0x0,%eax
8048466: 8b 4d f4 mov 0xfffffff4(%ebp),%ecx
8048469: 8b 5d f8 mov 0xfffffff8(%ebp),%ebx
804846c: 8b 75 fc mov 0xfffffffc(%ebp),%esi
804846f: 89 ec mov %ebp,%esp
8048471: 5d pop %ebp
8048472: 8d 61 fc lea 0xfffffffc(%ecx),%esp
8048475: c3 ret
8048476: 90 nop
8048477: 90 nop
8048478: 90 nop
8048479: 90 nop
804847a: 90 nop
804847b: 90 nop
804847c: 90 nop
804847d: 90 nop
804847e: 90 nop
804847f: 90 nop

Running:
Now Finally Running the executable
[vijay@localhost tmp]$ vim slfmdfy_code.asm
[vijay@localhost tmp]$ ./slfmdfy_code
Hello this is Vijay

Conclusion:
We are able to run the code from Stack/Heap. This example will help for applications like
1) Speeding applications – We have lesser cache misses
2) Security – Exploits, Key Generators.
3) Implementing Encryption engine where we do not want to give the encryption code in the text section, this makes
it difficult to reverse engineer the assembly code.
4) Also, MPS(Multi Processor System), Different Arch CPU are present registers of the co-processor are io-mapped
with the main processor memory region, we can make the co-processor run from stack code.

References:
1) How to write Shared Libraries: Ulrich Drepper
2) Executable and Linkable Format (ELF)
3) Kernel Source Tree – 2.6.20.1
4) www.google.com

Can reach me at vijayendra dot suman at gmail.com / vijayendra dot s at samsung.com/ skype-Id – vijayendra.suman
This document is only for open source.

You can Find a copy here
https://docs.google.com/fileview?id=0B6FKJ7nzzC9eMDZmOTExYWEtNWE2NS00NDA3LTkyZGUtMTk0MTA3NzhlNTMx&hl=en