Log in

View Full Version : C++ calculate size of method


b3n
April 11th, 2007, 21:27
hello,

does anyone know if its possible to calculate the size of a method in c++ during runtime? i want to inject some of my c++ code into another application and from what i have read so far, i need to know the size of the method i want to inject. any ideas on this?

thanks.

LLXX
April 11th, 2007, 22:59
Subtract the ending address from the starting address?

b3n
April 11th, 2007, 23:15
yeah thats what i thought would work, but how do i obtain a pointer to the start or end of a method? i played a bit with inline asm which works as long as the methods are aligned one after the other in the executable but i dont know how to do it in plain c++.

Kayaker
April 11th, 2007, 23:33
Something like this maybe?
It's possible certain compiler options might shift the location of InjectedCode_End, so you'd be screwed I guess. I seem to remember an issue with debug vs release mode as well, so you'd have to check.

void __declspec( naked ) InjectedCode()
{
//
}

/***********************************************************

InjectedCode_End

A reference to calculate size of the above routine

***********************************************************/

void InjectedCode_End()
{

}



ULONG size = (unsigned char*)InjectedCode_End - (unsigned char*)InjectedCode;

fr33ke
April 12th, 2007, 03:53
I would recommend against doing this because whatever you come up with, it's going to be violation of standards. Function pointers simply cannot be casted. Let me quote C99:
Quote:
[Originally Posted by "C99 section 6.3.2.3"]Even with an explicit cast, it is invalid to convert a function pointer to an object pointer or a pointer to void, or vice versa.

So what you are doing is dependant on compiler quirks. If your compiler decides to rearrange your code, or treats the cast different than what you expected, your program will not work. Which leads me to the second point...

Even if you manage to copy the raw bytes of the function, it is probably not offset independant and it contains references to other parts of your program. The former might be fixed by applying relocations to your bytes. The latter is pretty much out of your hands, because every compiler can do as it likes. Visual C++ usually calls the security cookie functions at the begin and the end of every function for instance.

My conclusion is: if you want to inject code, use asm or inject a DLL.

_gd_
April 12th, 2007, 09:50
As Kayaker mentioned, using the address-of operator on functions presents a problem in msvc debug mode builds.
All function references are indirected by a jump stub.

I've recently been trying to hunt down the setting which controls this behaviour but I've had no luck.
Even when copying the release compiler settings into the debug section the result was the same.
So I strongly suspect that it's controlled by a linker setting.

My workaround was to put the function in a seperate masm source file.
Another option would be to hardcode markers into the function pro and epi-log.
And then doing a binary search for those markers to determine the start and length of the function.
Ie.:
Code:

struct args {
void* ptr;
void (__stdcall* pfn)(void*);
};
void __declspec(naked) __stdcall foo(void* bar) {
// Start marker
__asm __emit 0x11
__asm __emit 0x11
__asm __emit 0x11
__asm __emit 0x11

// Prolog code
// This is required if you want to access arguments
__asm push ebp
__asm mov ebp, esp

//
// Your code goes here.
// NOTE: You cannot use local variables since the compiler
// has not way of allocating space on the stack for them.
//
register args* pargs = reinterpret_cast<args*>(bar);
if (args && args->pfn) {
args->pfn(args->ptr);
}

// Epilog code
__asm pop ebp
// Pop the argument(s) on return
__asm retn 4

// End marker
__asm __emit 0x22
__asm __emit 0x22
__asm __emit 0x22
__asm __emit 0x22
}

Yet another possibility would be to detect the jump stubs and following them.
Depending on what you need, dll-injection might also be an option.

reverser
April 12th, 2007, 10:27
To get rid of jump stubs turn off incremental linking.

Maximus
April 12th, 2007, 11:09
if you are lucky, it might work _some time. but forget about.

Looks like you don't know the real madness behind C++ code generation.
Unless you write code in your method like "A=B+C;" (being them simple types!) your code will likely _not run.

C++ compilers can create at _any time temporary objects, call out-of-order destructor's and many other little incubus amenities -not talking about hidden functions ('cookies' and the like).

However, if you really wish to, you can add an asm meaningless sequence prepended by a 'ret' instruction. you can then scan forward at runtime and 'catch' your mark. It won't work if you declare any object type or if you use any object-class, as the compiler will likely generate hidden temporaries for you on many situations (you can avoid this, but that's out of post) which can be destroyed right after their usage -if u'r lucky- or at end of the function call -if you are unlucky.

Leave it be such idea, imho.

disavowed
April 14th, 2007, 01:21
See http://blogs.msdn.com/geffner/archive/2006/02/10/using-assembly-buffers-in-c-without-using-hex-strings.aspx