C++ - Executing code on the stack

Questions about programming languages and debugging
Post Reply
User avatar
Gogeta70
^_^
^_^
Posts: 3275
Joined: 25 Jun 2005, 16:00
18

C++ - Executing code on the stack

Post by Gogeta70 »

Hey dudes. I was playing around with this idea and came up with this little bit of code. This allows you to copy a function to the stack and execute it from there. Compiler optimizations must be disabled for this to work because you can't declare your main function as volatile (volatile disables compiler optimizations on that function)

Here's the code:

Code: Select all

#include <iostream>
#include <cstdio>

using namespace std;

volatile void tFunc(int (*_printf)(const char*,...))
{
	_printf("You got here!");
}

int main(int argc, char* argv[])
{
	unsigned int fsize;
	unsigned int mv, tv;
	
	mv = reinterpret_cast<unsigned int>(main);
	tv = reinterpret_cast<unsigned int>(tFunc);
	
	fsize = mv - tv;
	
	int (*_printf)(const char*, ...);
	void (*_tFunc)(int (*)(const char*, ...));
	_printf = printf;
	
	unsigned char buff[256];
	unsigned char* cpy = (unsigned char*) tFunc;
	
	for(unsigned int i = 0; i < fsize; i++)
	{
		buff[i] = cpy[i];
	}
	
	_tFunc = (void(*)(int(*)(const char*, ...))) buff;
	
	_tFunc(_printf);
	
	return 0;
}
¯\_(ツ)_/¯ It works on my machine...

User avatar
maboroshi
Dr. Mab
Dr. Mab
Posts: 1624
Joined: 28 Aug 2005, 16:00
18

Re: C++ - Executing code on the stack

Post by maboroshi »

Wait your executing code on the stack?

That's pretty cool what purpose would it serve though, I guess some cpus won't allow this as they have a protected mode?

Whats your idea behind this?

*cheers

Maboroshi

User avatar
Gogeta70
^_^
^_^
Posts: 3275
Joined: 25 Jun 2005, 16:00
18

Re: C++ - Executing code on the stack

Post by Gogeta70 »

Protected mode shouldn't matter whether the cpu is in protected mode or real mode. here's kinda what's happening in asm:

ecx = size in bytes of function
ebx = pointer to first byte of function
edx = counter for bytes read/written, starts at 0

start addr = 0xFACEF00D
mov [esp+edx], [ebx+edx]
inc edx
cmp ecx, edx
jne 0xFACEF00D

(My knowledge of asm is mostly from doing stuff in ollydbg, so an actual asm coder will probably cringe...)

As you can see, it's simply writing data to the stack and executing it. It's really no different than pushing data onto the stack except that the stack pointer isn't incremented this way.

As for the purpose, writing code this way would make it very hard to crack. Imagine writing a registration check function to the stack - it would be nearly impossible to find in a debugger like ollydbg.
¯\_(ツ)_/¯ It works on my machine...

User avatar
Gogeta70
^_^
^_^
Posts: 3275
Joined: 25 Jun 2005, 16:00
18

Re: C++ - Executing code on the stack

Post by Gogeta70 »

Just to clarify (because my asm example wasn't that good), here's the actual disassembly of the main points of the program:

tFunc function:

Code: Select all

00401318    .  55                PUSH EBP
00401319    .  89E5              MOV EBP,ESP
0040131B    .  83EC 08           SUB ESP,8
0040131E    .  8B45 08           MOV EAX,DWORD PTR SS:[EBP+8]
00401321    .  C745 08 24F04600  MOV DWORD PTR SS:[EBP+8],CinTest.0046F024                                           ;  ASCII "You got here!"
00401328    .  C9                LEAVE
00401329    .- FFE0              JMP EAX
main function:

Code: Select all

0040132C   /$  55                PUSH EBP
0040132D   |.  89E5              MOV EBP,ESP
0040132F   |.  83E4 F0           AND ESP,FFFFFFF0
00401332   |.  56                PUSH ESI
00401333   |.  53                PUSH EBX
00401334   |.  81EC 18010000     SUB ESP,118
0040133A   |.  E8 31200100       CALL CinTest.00413370
0040133F   |.  BA 18134000       MOV EDX,CinTest.00401318
00401344   |.  BE 2C134000       MOV ESI,CinTest.0040132C                                                            ;  Entry address
00401349   |.  29D6              SUB ESI,EDX      ; Subtract start of main function address from start of tFunc address - ESI becomes size of tFunc
0040134B   |.  74 27             JE SHORT CinTest.00401374
0040134D   |.  31C0              XOR EAX,EAX ; Here it's clearing eax to use as a counter
0040134F   |.  8D5C24 10         LEA EBX,DWORD PTR SS:[ESP+10] ; Copying the stack pointer
00401353   |.  90                NOP ; No operation...
00401354   |>  8A0A              /MOV CL,BYTE PTR DS:[EDX] ; EDX is the func ptr, copying byte from function to low byte of ECX
00401356   |.  880C03            |MOV BYTE PTR DS:[EBX+EAX],CL ; Copying function byte to stack
00401359   |.  40                |INC EAX ; Increment counter
0040135A   |.  42                |INC EDX                                                                            ;  Increment function pointer
0040135B   |.  39F0              |CMP EAX,ESI ; Compare counter to esi (esi = size of tFunc function)
0040135D   |.^ 75 F5             \JNZ SHORT CinTest.00401354
0040135F   |>  C70424 C0C64100   MOV DWORD PTR SS:[ESP],<JMP.&msvcrt.printf>
00401366   |.  FFD3              CALL EBX
00401368   |.  31C0              XOR EAX,EAX
0040136A   |.  81C4 18010000     ADD ESP,118
00401370   |.  5B                POP EBX                                                                             ;  CinTest.004010B6
00401371   |.  5E                POP ESI                                                                             ;  CinTest.004010B6
00401372   |.  C9                LEAVE
00401373   |.  C3                RETN
00401374   |>  8D5C24 10         LEA EBX,DWORD PTR SS:[ESP+10]
00401378   \.^ EB E5             JMP SHORT CinTest.0040135F
Hope this helps ^_^
¯\_(ツ)_/¯ It works on my machine...

Post Reply