• RSS
  • Twitter
  • FaceBook

Security Forums

Log in

FAQ | Search | Usergroups | Profile | Register | RSS | Posting Guidelines | Recent Posts

[Column] Coding Corner - 01 - Function Pointers

Users browsing this topic:0 Security Fans, 0 Stealth Security Fans
Registered Security Fans: None
Post new topic   Reply to topic   Printer-friendly version    Networking/Security Forums Index -> News // Columns // Articles

View previous topic :: View next topic  
Author Message
Stormhawk
Trusted SF Member
Trusted SF Member


Joined: 26 Aug 2003
Posts: 31
Location: Warwickshire, England, UK

Offline

PostPosted: Mon Dec 12, 2005 12:11 am    Post subject: [Column] Coding Corner - 01 - Function Pointers Reply with quote

Coding Corner 1: Function Pointers

There have been a number of threads in the Programming and More forum on Security-Forums Dot Com ( https://www.security-forums.com ) recently dealing with the topic of pointers. One of the most confusing aspects of pointer use is the function pointer, seen recently in test programs for shellcode ( notably, threads https://www.security-forums.com/forum/viewtopic.php?t=35424 and https://www.security-forums.com/forum/viewtopic.php?t=35693 ).

Pointer Basics

A pointer is basically an unsigned long integer (on x86 architectures, a pointer is generally a 32 bit unsigned integer) which stores a memory address. That could be the address of another integer (in which case, you'd have a pointer to an integer, or int *), a character, an array (strictly, an array is a pointer to the first element of the array) or to some other data structure in memory. All a pointer is, is something that stores the memory address of the first byte of some data that is located elsewhere in memory.

In order to manipulate pointers, one must realise that there are two types of operation, operations involving the pointer value – that is, the address itself – and operations involving the value pointed to – that is, the contents of memory at that address. In the first instance, consider listing 1.

Code:

/* LISTING 1 */
char myString[5];
char* cp = &myString[0]; /* Note: myString and &myString[0] are equivalent */
cp = cp + 1;


In this listing, we create a character array called myString, consisting of 5 characters. We create a pointer to the character array (incidentally, an array name is essentially a pointer to its first element, so &myString[0] is the same as just saying myString. The value of the variable cp is now the numeric memory address of the beginning of myString. We can then manipulate this address just like any other integer, in this case, we'll add one. This has the effect of making cp now contain the memory address of myString[1], we have skipped forward an item in the myString array.

The second type of operation deals with the stuff that is being pointed to. In order to achieve this, we must dereference the pointer, which is done using the * operator. This tells the compiler that we're interested in the value stored in the memory location whose address is given by the pointer's value, as opposed to the pointer's value itself. An example is in listing 2, which uses a pointer to change an integers value.

Code:

/* LISTING 2 */
int x = 6;
int* ip = &x;
*ip = 3;
/* x is now == 3 */
/* ip still contains the memory address of x */


Pointers have many uses, most of which are beyond the scope of this article. Here, we will concentrate on function pointers.

What Is A Function?

A function is basically just a piece of code which can be executed. This code is stored in memory, and so there is a memory address associated with the first byte of a segment of code which would be considered a function. In the normal function call procedure, the CPU simply jumps to this location in memory, reads instructions, and executes them (okay, its a little more complicated than that, there are instruction pointer registers, caches, and all sorts of intricate details, but this isn't a hardware or assembler article, so we'll ignore that stuff).

And Function Pointers?

As I said above, a pointer is just an integer which stores a memory address of some data. The instructions which make up a function are just another form of data, and you can create a pointer that stores the address of the first byte of a function. This has the special property that you can now call that, as though it were an ordinary function, and the code will be executed. If we have an array of bytes, which can be interpreted by the processor as a sequence of instructions, then as far as the processor is concerned, this is a function, and provided we generate a suitable pointer, it can be “called” and executed. This forms the basis for most shellcode testing programs.

A function pointer has a specific syntax, just like a pointer to an integer has to be declared as int*, a pointer to a function must be declared. Since functions are fairly complex entities, which can take multiple arguments, of any type, and return a value of any type, the function pointer syntax must provide for all such situations.

In general, a function pointer is of the form in listing 3.

Code:

/* LISTING 3 */
return_type (*pointer_name)([argument_type [, ...]]);

As an example, we'll define a simple function that takes no arguments, and returns nothing, and then create a pointer to it. This is shown in listing 4.

Code:

/* LISTING 4 */

#include <stdio.h>

void PrintHello()
{
   printf(“Hello!\n”);
}

int main()
{
   void (*ph)();
   ph = PrintHello;
   ph();
   return 0;
}


Listing 4 is a complete program demonstrating function pointers. Here, we create a function whose return type is void (note the void in the function pointer declaration), and takes no arguments (note the empty brackets in the function pointer declaration – technically we could also use void here to indicate a lack of passed arguments, which explicitly states that the function can take no arguments). Before we can use our function pointer as though it were a function, we must assign some value to it, the address of the function we want it to point to.

A function's name is, as with an array, basically a pointer to the first byte of the function. As such, we can assign using the ph = PrintHello; line. Note that it was PrintHello, not PrintHello(). The () indicates a function call, and in this case, we'd be assigning the returned value from PrintHello() to the pointer ph, and as PrintHello() does not return a value, the compiler would likely complain. Use () only where you wish to actually call a function (execute it), and the function name only, when you are referring to its address in memory. Note, however, that in declaring the initial function pointer, it is necessary to put in the (), even if the function takes no arguments, as that is the syntax that tells C we're creating a function pointer!

When we want to use a function pointer, we can execute it as though it were an ordinary function, by using the () function call operator. Note that, if fp is a function pointer, (*fp)(); and fp(); are identical in behaviour - dereferencing is implicit in a function call through a function pointer.

A More Complex Function Pointer

Let us now consider the function system(), which allows us to execute a command on the shell, from inside a C program. For some reason, we wish to create a pointer to this, and then call system() through this pointer. This example is not as contrived as it seems – most menu systems operate through the use of function pointers. We're looking at listing 5, here.

Code:

/* LISTING 5 */
#include <stdlib.h>

/* N.B. system() is - int system(const char *string); */

int main()
{
   int (*sys)(const char*) = system;
   int result = sys(“/bin/bash”);
   return 0;
}


Here, we've combined pointer declaration with initialisation, creating a pointer called sys, which points to a function taking a const char* and returning an int. Then, on the same line, we've set its value to be the address of a function called system, which is a standard library function declared inside the <stdlib.h> header file, and defined somewhere in the C library code. We've then used sys – the function pointer – to call system, with an argument of “/bin/bash”, and we're storing its returned value into an int called result.

The Shellcode Test Program

Finally, we're ready to examine a shellcode test program. I've presented one here in full generality, with no working (or, for that matter, unworking) shellcode. You'll need to fill that in yourself. Listing 6 is the one you want to be looking at, here.

Code:

/* LISTING 6 */

char shellcode[] = “... put your shellcode in here ...”;

int main()
{
   void(*sc)() = ( void(*)() ) shellcode;
   sc();
   return 0;
}


It should, now, be easy to understand exactly what this program does, but don't worry – I'm going to explain it anyway!

First, we're creating a global variable called shellcode, which is basically just a sequence of bytes. This is where you'd put your carefully crafted shellcode to be tested. Next, inside the main() function, we've created a function pointer which takes no arguments and returns nothing, and assigned the memory address of shellcode to it (after a suitable cast, so the compiler doesn't complain that the two types are incompatible).

We then call sc(), which runs the instructions within shellcode as though they were an ordinary function in the program. Just for good measure, and again because some compilers complain, we've included a return 0; at the end. Unless your shellcode is smart enough to jump back into the program, the return 0; will never actually get executed, but since we're being pedantic, we'll include it so we don't get warnings when we compile our test program!

Finally

A few closing words to wrap up this article. Most importantly, discussion of these topics and similar can be found on Security-Forums Dot Com, in the threads linked to at the beginning of this article. Last, but by no means least, the code presented in this article is hereby donated to the public domain. Feel free to do with it whatever you want, if you think you can use it, do so. Certainly, the shellcode test program follows a fairly basic structure common to a huge number of shellcode tests out there online. Readers familiar with Google will be able to find a vast array of information on this topic and other related areas of programming and security. Security-Forums Dot Com, in particular, contains a wealth of information on the topic of exploits and shellcode, and the members are always happy to help out with any questions or problems.


Andrew J. Bennieston
December 1st, 2005.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   

Post new topic   Reply to topic   Printer-friendly version    Networking/Security Forums Index -> News // Columns // Articles All times are GMT + 2 Hours
Page 1 of 1


 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Community Area

Log in | Register