copy code and execute

Ok so I want to learn what is the problem in the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
typedef int (*foo_ptr)(void);

static int foo()
{
return 20;
}
static void after_foo(){}

void main(int argc, char **argv)
{
size_t foo_size = (LPBYTE)after_foo - (LPBYTE)foo;

foo_ptr p_foo = (foo_ptr) VirtualAlloc(0, foo_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
CopyMemory(p_foo, &foo, foo_size);

int res = (*p_foo)();
}

Now it works perfectly as this but it crashes as soon as i insert printf("something") in the foo function. so the code that fails is the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef int (*foo_ptr)(void);

static int foo()
{
// this is the only modification
printf("test to print");
return 20;
}

static void after_foo(){}

void main(int argc, char **argv)
{
size_t foo_size = (LPBYTE)after_foo - (LPBYTE)foo;

foo_ptr p_foo = (foo_ptr) VirtualAlloc(0, foo_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
CopyMemory(p_foo, &foo, foo_size);

int res = (*p_foo)();
}


What i have noticed is that it crushes each time i insert a code that access the heap memory in the foo function. If i insert a code that allocates a heap it is not a problem (example int x; ). I think it is something with the static functions and their address translation (absolute vs relative)...

Any answer would be appreciated

P.S. Please note that i do not want to do some mallware code.. i mean i know how to inject the code in the address space of another process i just cant figure it out how to insert it in the address space of the same process...... I have done a data management component which i use to share data between processes (IPC). The data management component works on a File mapped memory and uses custom heap implementation over that memory (using offsets since the memory is mapped differently in each process) to store the data. Now i want to boost it to share not only data between processes but also a code. The idea is that i do not want to inject the code from another process instead to inject the code in a shared memory space then from another process to copy the function in the local memory space and execute it from there.

Example:
App1 -> store foo() in DM
App2 -> read foo() from DM
App2 -> write foo() in local memory space (with PAGE_EXECUTE_READWRITE protection flag set)
App2 -> execute foo()

* DM is already created and works fine with data
* I understand that foo must not call functions from libraries that are not loaded in App2

Uffff tooo long post... sorry Smile

regards
Nikola
Last edited on
closed account (S6k9GNh0)
Use code bbcode or I won't answer.
sorry, wasn't intentional. First time writing here and i also posted this on codeproject so i made simple copy/paste. Ill be careful the next time.

regards
Nikola
You don't check for NULL from VirtualAlloc.
Actually i debug this code its not something to use just trying. and there is no null after VirtualAlloc. The problem is after the execution
int res = (*p_foo)();
And only in the second case when i add printf in foo() or even just new int....

regards
It is possible that it only crashes in Debugging mode because the microsoft compiler throws in some extra code when certain function are used to check for stack corruption etc - and these maybe the problem.

Try running it in release mode - it will probably work.
Actually the first thing i tried was that and it doesnt work. I debugged in asm and realized that the problem is that instead of calling absolute addresses for functions it translates it to an relative address (which ofcourse when coppied out of the original function context is changed). So if anyone had similar problem or has any idea i would be happy to hear it.

thanks
Works for me.
Ok so this is what i mean.

this is the c++ code of the function foo
1
2
3
4
static void foo()
{
	aco(1,2);// this is some simple function that prints 21
}


In the original context of function the disassembled code looks like this:

1
2
3
4
5
6
7
004098B0  push        ebp  
004098B1  mov         ebp,esp 
004098B3  push        2    
004098B5  push        1    
004098B7  call        aco (409890h) 
0003000C  pop         ebp  
0003000D  ret    


And after i copy it in different region this is what it becomes

1
2
3
4
5
6
7
00030000  push        ebp  
00030001  mov         ebp,esp 
00030003  push        2    
00030005  push        1    
00030007  call        0002FFE0 
0003000C  pop         ebp  
0003000D  ret        


notice the bold lines - different - means only one thing: the jump (or call) for the aco function is done on the relative address of foo instead a direct jump to aco. After the function is copied that address is changed (normally - the relative address from one location is different than the relative address from another location)


Any ideas???!?!?

thanks again
Last edited on
I'll try that (but that isn't the code you actually posted);

guestgulkan (985) Nov 3, 2009 at 9:25pm
Works for me.


Do you use some compiler option for the address resolution or something?!?! I use default console application vs2008 with disable incremental linking (ofcourse its release mode)

I'll try that (but that isn't the code you actually posted);


you can try with the code i posted its the same (the second code) since its not a call to custom function but to printf .... result ... same problem
I'm using VC2008

I directly copied your second code (with the printf function) and paseted into the VC IDE and built
in release mode.

here is the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

#include <windows.h>
#include <stdio.h>

typedef int (*foo_ptr)(void);

static int foo()
{
// this is the only modification
printf("test to print");
return 20;
}

static void after_foo(){}

void main(int argc, char **argv)
{
size_t foo_size = (LPBYTE)after_foo - (LPBYTE)foo;

foo_ptr p_foo = (foo_ptr) VirtualAlloc(0, foo_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
CopyMemory(p_foo, &foo, foo_size);

int res = (*p_foo)();
}


here is the result;
C:\Documents and Settings\andy\My Documents\Programming\Projects\msvc\rubbish\Release>rubbish
test to print
C:\Documents and Settings\andy\My Documents\Programming\Projects\msvc\rubbish\Release>



Something you say does not make sense to me - why should anything change during the copy.
The copying should be a exact byte for byte copy at runtime.
ahmmm thanks a lot... i will definitely try with a new console app :)
The copying should be a exact byte for byte copy at runtime.

and that is exactly what i thought...

thanks again
Nikola
i tried it... new console ->paste the code ->and voila it works.....

appreciate it man a lot - i would have never tried it on a clean project if it didnt worked for you...

thank million times
Topic archived. No new replies allowed.