I saw this code today in some fb profile, and was not able to understand what is and how this is working:-
(*(void(*)()) shellcode)()
Can someone please explain me, what does above code mean ?
Full Code Snippet Below :-
#include <stdio.h>
#include <string.h>
char *shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
int main(void)
{
fprintf(stdout,"Length: %d\n",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}
It is a cast to a function pointer (with no returned result and no arguments). I prefer using typedef to define signature of such functions:
typedef void plainsig_t(void);
then simply code
(*(plainsig_t*)shellcode) ();
For function pointers, you don't need to dereference them, so it is shorter to just code:
((plainsig_t*) shellcode) ();
which basically calls the function whose machine code is located inside shellcode memory zone.
BTW, this is not strictly portable C. In principle, there is no guarantee that you can cast a data pointer to a function pointer. (On some weird processors -e.g. embedded microcontrollers, DSP, 1970s era computers-, code and data sit in different address spaces, or have different pointer sizes, etc....). But most common processors and ABI (x86-64/Linux, ARM/Android, ....) have the same address space for code and for data and accept casting function pointers to data pointers and vice versa.
This is one place that C and C++ differ.
In C it means a pointer to a function returning void and taking an unspecified number of arguments of unspecified types.
In C++ it means a pointer to a function returning void and taking no argument.
The expression as a whole takes the address of shellcode, casts it to a pointer to function type, then invokes the function -- i.e., executes the op-codes in that string.
void(*)() means "a pointer to a void function that takes no arguments." The line
(*(void(*)()) shellcode)();
is casting shellcode to such a function pointer, dereferencing the pointer (not actually necessary), and then calling the function.
It's a function pointer. Type specifiers match declarations; so a function void f() has type void(); and a pointer to a function void (*pf)() has type void(*)().
Note that, as with function declarations, it has slightly different meanings in C and C++. In C, the empty parentheses mean it has an unspecified number of parameters, while in C++ it means it has no parameters. However, that doesn't affect the meaning of the code.
This code reinterprets an array as a function and attempts to call it. Presumably, the array contains machine code to print a message, or format your hard drive, or something. On most modern platforms, this will cause a protection fault since the static data is (hopefully) not executable by default.
In C a variable is declared as int foo;
, to declare a function we use int foo( ); It means that the return type of the function is int. To declare a pointer we use *foo.
In the expression (*(void(*)())0)() we can see that
Assuming that the variable fp is a function pointer, we can use (*fp)( ); to call the function, because fp is a function pointer, and *fp is the function pointed to by the pointer, so (*fp)( ); can call the function.
Suppose fp is a pointer to a non-return value type, then the way to call it is void (*fp)( ), then the type of the fp variable is void (*)( ).
If we were to cast this type to a constant shellcode, then we use ( void (*)() ) shellcode.
Now that the shellcode is cast to the type, in order to call the shellcode we use
( ( void (*)() ) shellcode )();
Note: We can use typedef to replace the type name of the above expression
For example: typedef void (*ff)( ); Therefore, the way to call a function can be written as:
(*(ff) shellcode ) ( );
from : https://www.codetd.com/en/article/14043929
Related
I have two pieces of code: The first, inside a C++ program, is where I load and call a function from an external test_lib.so:
typedef void *(*init_t)(); // init_t is ptr to fcn returning a void*
typedef void (*work_t)(void *); // work_t is ptr to fcn taking a void*
void *lib = dlopen("test_lib.so", RTLD_NOW);
init_t init_fcn = dlsym(lib, "test_fcn");
work_t work_fcn = dlsym(lib, "work_fcn");
void *data = init_fcn();
work_fcn(data);
The second piece of code is the one that compiles to test_lib.so:
struct Data {
// ...
};
extern "C" {
void *init_fcn() {
Data *data = new Data; // generate a new Data*...
return data; // ...and return it as void*
}
void work_fcn(void *data) { // take a void*...
static_cast<Data *>(data)->blabla(); // ...and treat it as Data*
static_cast<Data *>(data)->bleble();
}
}
Now, the first piece of code doesn't need to know what Data is, it just passes the pointer around, so it's a void*. But the library, which works directly with data's methods and members, needs to know, so it must convert the void*s to Data*s.
But the interface between the two pieces of code is just some functions with pointer arguments and/or return types. I could just keep the void* in the client, and change every instance of void* in the library to Data*. I did that, and everything works fine (my system is Linux/GCC 6.2.1).
My question is: was I lucky, or is this guaranteed to work everywhere? If I'm not mistaken, the result of calling some f(Data*) with a void* argument is just as if called reinterpret_cast<Data*> on the void* --- and that couldn't possibly be dangerous. Right?
EDIT: No, simply making the Data type transparent to the client code won't work. The client code calls many libraries through the same API, but each library might have its own implementation. For the client, Data could be anything.
Calling any function through the wrong function type is automatically undefined behavior. From C++ Standard draft n4604 (roughly C++17) [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined. Except that converting a prvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are function types) and back to its original type yields the original pointer value, the
result of such a pointer conversion is unspecified.
Calling any function through a function pointer type with the wrong linkage is also undefined behavior. Your typedefs don't use "C" linkage, ergo UB. From draft n4604 section [expr.call]:
Calling a function through an expression whose function type has a language linkage that is different from the language linkage of the function type of the called function’s definition is undefined.
Besides that point, different pointer types are not required to have the same representation. (cv-qualified) void* can hold any object pointer, but its alignment restrictions are the same as char* (that is, no restriction) and as a result, it's not necessarily representation compatible with other object pointer types and may not even be the same size. (And most definitely, object pointers, function pointers, and the variations on pointer-to-member are frequently different sizes on real-world systems.)
While this is likely to work in practice, C doesn't guarantee this behavior.
There are two problems:
Different pointer types can have different sizes and representations. On such an implementation going to void * and back involves an actual conversion at runtime, not just a cast to make the compiler happy. See http://c-faq.com/null/machexamp.html for a list of examples, e.g. "The old HP 3000 series uses a different addressing scheme for byte addresses than for word addresses; like several of the machines above it therefore uses different representations for char * and void * pointers than for other pointers."
Different pointer types can use different calling conventions. For example, an implementation might pass void * on the stack but other pointers in registers. C doesn't define an ABI, so this is legal.
That said, you're using dlsym, which is a POSIX function. I don't know if POSIX imposes additional requirements that make this code portable (to all POSIX systems).
On the other hand, why don't you use Data * everywhere? On the client side you can just do
struct Data;
to leave the type opaque. This fulfills your original requirements (the client can't mess with the internals of Data because it doesn't know what it is, it can only pass pointers around), but also makes the interface a bit safer: You can't accidentally pass the wrong pointer type to it, which would be silently accepted by something taking void *.
You can make it cleaner by using opaque structure definitions. See the second half of the accepted answer here:
Why should we typedef a struct so often in C?
Thus the caller is handling pointers to a defined type, but cannot see inside what is being pointed at. The implementation has the actual struct definition, and can work with it. No more casting is required.
The outcome of the following macro is clear:
#define CRASH() do {\
*(int *)(uintptr_t)0xbbadbeef = 0;\
((void(*)())0)();\
} while (false)
My question is, what does the line
((void(*)())0)();
break down to, in English? For example, "this is a function that returns a pointer to a...."
It looks like it casts 0 as a function pointer (with the signature that it takes not parameters and has void return type) and then invokes it.
( ( void(*)() ) 0 ) ();
/* cast..*/ /* fn pointer signature */ /*..cast 0 */ /* invocation */
Which is another way to say that it's trying to invoke (call) a function that's expected to be located in memory at address 0x00000000 - which is guaranteed to be an invalid address.
Cast 0 to a pointer to a void function that takes can be called with no parameters (the (void(*)())0 part of the expression)
Call that function through a pointer with an empty parameter list (the () part after it).
EDIT 1: Edited in response to Cristoph's comment.
It casts a NULL pointer to a method taking no parameters and returning void, and attempts to call this method.
Needless to say, it crashes, so the name CRASH suits it very well.
It casts 0 to a function pointer, where the function takes no argument and returns void, then tries to call this function. It basically dereferences a null pointer.
It casts 0 to a pointer to a function, then attempts to call that function. Which will cause a segfault and crash.
Edit: way too much competition for these questions. Upvotes all round, and I'm going to bed :)
It means “treating NULL pointer as pointer to void function(), call function()”.
It takes the value zero, and casts it to a function pointer that doesn't return anything (void).
Presumably, the purpose is that when you call this "function", it calls address zero, which should indeed crash the application.
For me it is simpler to translate to a different C++, rather than directly to english:
typedef void (void_func_t)(); // type of a function taking no arguments
// and returning void
typedef void_fnct_t* void_func_ptr; // pointer to such a function
static_cast<void_func_ptr>(0)(); // call that function
// ((void_func_ptr)0)(); // pure C equivalent cast
if fp is a pointer to a function, *fp is the function itself, so(fp)()is the way to invoke it. ANSI C permits this to be abbreviated as fp(), bu keep in mind that it is only an abbreviation. -------C traps an pitfalls.
( ( void()() )0 ) () is the avvreviation of ( ( void()() )0 )()
I have a template member function with this signature:
template<typename T> void sync(void (*work)(T*), T context);
It can be called with a pointer to a function that accepts an argument of type T*. context is passed to that function. The implementation is this:
template<typename T> void queue::sync(void (*work)(T*), T context) {
dispatch_sync_f(_c_queue, static_cast<void*>(&context),
reinterpret_cast<dispatch_function_t>(work));
}
It uses reinterpret_cast<> and it works. The problem is that the standard doesn't define it very well and it is very dangerous. How can I get rid of this? I tried static_cast but that gave me a compiler error:
static_cast from void (*)(std::__1::basic_string<char> *) to dispatch_function_t (aka void (*)(void *)) is not allowed.
dispatch_function_t is a C type and is the same as void (*)(void*).
I'm not sure I was clear enough. What dispatch_sync_f does is it calls a given callback function and passes the given context parameter to that callback function. (It does that on another thread, although that is out of the scope of this question.)
The reason this is not supported by static_cast is because it is
potentially unsafe. While a std::string* will convert implicitely to
a void*, the two are not the same thing. The correct solution is to
provide a simple wrapper class to your function, which takes a void*,
and static_casts it back to the desired type, and pass the address of
this wrapper function to your function. (In practice, on modern
machines, you'll get away with the reinterpret_cast, since all
pointers to data have the same size and format. Whether you want to cut
corners like this is up to you—but there are cases where it's
justified. I'm just not convinced that this is one of them, given the
simple work-around.)
EDIT: One additional point: you say that dispatch_function_t is a C type. If this is the case, the actual type if probably extern "C" void (*)(void*), and you can only initialize it with functions that have "C" linkage. (Again, you're likely to get away with it, but I've used compilers where the calling conventions were different for "C" and "C++".)
I guess, you are not only casting work to dispatch_function_t, but calling it through dispatch_function_t pointer, aren't you? Such cast itself is valid according to standard, but all you can do with a casted pointer is cast it back to original type. Still your approach should work with most compilers and platforms. If you'd like to implement it so it's more standard conforming you can make a wrapper for your context and work function like this:
template <typename T>
struct meta_context_t
{
T *context;
void (*work)(T*);
};
template <typename T>
void thunk(void *context)
{
meta_context_t<T> *meta_context = static_cast<meta_context_t<T> *>(context);
meta_context->work(meta_context->context);
}
template<typename T> void queue::sync(void (*work)(T*), T context) {
meta_context_t<T> meta_context =
{
&context,
work
};
dispatch_sync_f(_c_queue, static_cast<void*>(&meta_context),
thunk<T>);
}
I can't believe this works or you have a rather narrow definition of "this works" (e.g. you found one particular setup where it seems to do what you think it should do). I'm not clear what dispatch_sync_f() does but I think it is suspicious that it gets a pointer to the local variable context as parameter. Assuming this variable outlives the use of this pointer, there is still a subtle problem which won't get you on most platforms but does get you on some:
C and C++ calling conventions can be different. That is, you cannot cast a pointer to a C++ function to a pointer to a C function and hope for this to be callable. The fix to this problem - and your original question - is, of course, an extra level of indirection: don't dispatch to the function you get as argument but rather dispatch to a C function (i.e. a C++ function declared as extern "C") which takes its own context holding both the original context and the original function and calls the original function. The only [explicit] cast needed is the static_cast<>() restoring a pointer to your internal context from the void*.
Since you seem to implement a template you might need to use another indirection to get rid of this type: I don't thing function templates can be declared extern "C". So you would need to restore the original type somehow e.g. using a base class and a virtual function or something like std::function<void()> holding a readily callable function object doing this conversion (a pointer to this object would be your context).
I believe the cast to/from these two function pointer types is fine:
void(*)(void*)
void(*)(T*)
The problem is that you can't actually use the pointer that you have so cast. It's legal only to cast back to the original type (and those casts are reinterpret_cast, because these are unrelated types). From your code, I can't see how your actual callback function is defined. Why can't you accept a dispatch_function_t as your parameter for queue::sync, rather than casting it?
reinterpret_cast is guaranteed to work when converting from a type T * to void * and back. It is, however, not acceptable to cast from or to a pointer to a base or derived class of T.
The type of work needs to be dispatch_function_t in this case, and the first order of business in that function needs to be the cast from void * to T *. Implicitly casting the argument by using a different argument type and casting the function type is not allowed.
Rationale: the standard allows different pointer representations for different types, as long as all pointer types can be converted to void * and back, so void * is the "most precise" pointer type. A conforming implementation is allowed to clear the bottom-order bits of an uint32_t * if sizeof(uint32_t) > sizeof(char) (i.e. sizeof(uint32_t) > 1) or even shift the pointer value if the machine instructions can utilize these pointers more effectively; on a machine with tagged or shifted pointer values the reinterpret_cast is not necessarily a no-op and needs to be written explicitly.
Normal pointers can be stored using a generic void*. e.g.
void* arr[10];
arr[0] = pChar;
arr[1] = pINt;
arr[2] = pA;
Sometime back, I came across a discussion that, void* may not be capable enough to store a function pointer without data-loss in all platforms (say 64-bit and more). I am not sure about this fact though.
If that's true, then what is the most portable way to store a collection of function pointers ?
[Note: This question doesn't satisfactorily answer this.]
Edit: I will be storing this function pointers with an index. There is a typecasting associated with every index whenever this collection is accessed. As of now, I am interested only to make an array or vector of it.]
You can convert a function pointer to another function pointer of any function type and back without loss.
So as long as when you make the call through the function pointer you typecast it back to the correct type first, you can store all of your function pointers in something like:
typedef void (*fcn_ptr)(void); // 'generic' function pointer
fcn_ptr arr[10];
A pointer to a function can be converted to a pointer to a function of a different type with a reinterpret_cast. If you convert it back to the original type you are guaranteed to get the original value back so you can then use it to call the function. (ISO/IEC 14882:2003 5.2.10 [expr.reinterpret.cast] / 6)
You now only need to select an arbitrary function pointer type for your array. void(*)() is a common choice.
E.g.
int main()
{
int a( int, double );
void b( const char * );
void (*array[])() = { reinterpret_cast<void(*)()>(a)
, reinterpret_cast<void(*)()>(b) };
int test = reinterpret_cast< int(*)( int, double) >( array[0] )( 5, 0.5 );
reinterpret_cast< void(*)( const char* ) >( array[1] )( "Hello, world!" );
}
Naturally, you've lost a lot of type safety and you will have undefined behavior if you call a function through a pointer to a function of a different type.
Use a union of your function pointer types, this works in both C and C++ and assures sufficient storage for the pointers (which are likely the same size, still...)
There are a few things that make up a function pointer's type.
the memory address of the code
the argument signature
the linkage/name mangling
the calling convention
for member functions, some other stuff too
If these features aren't uniform across your function pointers then you can't sensibly store them in the same container.
You can, however bind different aspects into a std::function which is a callable object that only requires the argument signature and return type to be uniform.
It may be a good time to re-think the problem in terms of virtual functions. Does this mishmash of function pointers have a coherent interface that you can express? If not, then you're doomed anyway :-)
RE: Hasturkun, you can store heterogeneous function pointers in unions, yes, they're just POD, but you will also need to store information about what type of pointer it is so that you can choose the correct member to call. Two problems with this:
there is a per-item overhead,
you have to manually check that you're using the right one consistently all the time, this is a burden with nonlocal effects -- it's a spreading poison.
Far better to have one container per type, it will clarify the code and make it safer. Or, use a proxy such as std::function to make them all have the same type.
I am trying to understand what this means, the code I am looking at has
in .h
typedef void (*MCB)();
static MCB m_process;
in .C
MCB Modes::m_process = NULL;
And sometimes when I do
m_process();
I get segmentations fault, it's probably because the memory was freed, how can I debug when it gets freed?
It defines a pointer-to-function type. The functions return void, and the argument list is unspecified because the question is (currently, but possibly erroneously) tagged C; if it were tagged C++, then the function would take no arguments at all. To make it a function that takes no arguments (in C), you'd use:
typedef void (*MCB)(void);
This is one of the areas where there is a significant difference between C, which does not - yet - require all functions to be prototyped before being defined or used, and C++, which does.
It introduces a function pointer type, pointing to a function returning nothing (void), not taking any parameters and naming the new type MCB.
Let's take an example
typedef void (*pt2fn)(int);
Here, we are defining a type pt2fn. Variables of this type point to functions, that take an integer as argument and does not return any value.
pt2fn kk;
Here, kk is a variable of type pt2fn, which can point to any function that takes in an integer as input and does not return any value.
Reference:https://cs.nyu.edu/courses/spring12/CSCI-GA.3033-014/Assignment1/function_pointers.html
The typedef defines MCB as the type of a pointer to a function that takes no arguments, and returns void.
Note that MCB Modes::m_process = NULL; is C++, not C. Also, in C, the typedef should really be typedef void (*MCB)(void);.
I'm not sure what you mean by "the memory was freed". You have a static pointer to a function; a function cannot be freed. At most, your pointer has been reset somewhere. Just debug with a memory watch on m_process.
It's a function pointer. You get a SEGMENTATION FAULT because you are trying to make a call to a function which address is invalid (NULL).
According to your specific sample, the function should return no value (void) and should receive no parameters ().
This should work:
void a()
{
printf("Hello!");
}
int main(int arcg, char** argv)
{
m_process = a;
m_process(); /* indirect call to "a" function, */
// Hello!
}
Function pointers are commonly used for some form of event handling in C. It's not its only use though...