How does this function pointer work [duplicate] - c

In Demystifying the Execve Shellcode is explained a way to write an execve shellcode:
#include<stdio.h>
#include<string.h>
unsigned char code[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
What does the line int (*ret)() = (int(*)())code; do?

int (*ret)() = (int(*)())code;
~~~~~~~~~~~~ ~~~~~~~~~~~~~~
1 2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
It defines ret as a pointer to a function which has no parameter () and returns int. So, Those () indicates the definition of parameters of a function.
It's for casting code to a pointer to a function which has no parameter () and returns int.
Casts code as a function and assigns it to ret. After that you can call ret();.
unsigned char code[] = "\x31\xc0\x50\x68\x6e\x2f\...
It is a sequence of machine instructions represented by hex values. It will be injected to the code as a function.

(*(void(*)())shellcode)()
==
p = (void(*)()) shellcode;
(*p)();

Can this function pointer part be re-written in a simpler form?
I don't know if you think this is simpler, but maybe:
#include <stdio.h>
#include <string.h>
unsigned char code[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
typedef int(*shellcode_t)();
int main(int argc, char ** argv) {
printf("Shellcode Length: %ld\n", strlen(code));
shellcode_t ret = (shellcode_t)code;
ret();
}

The int line declares the ret() function, by pointing to the code[] array; in other words, the function is mapped to the code[] binary instructions.
The \x construct is a safe way to embed hexadecimal characters in a string. You could for instance replace “\x31” by “1” as the character code of “1” is 49, or hexadecimal 31.

Related

Calling function from dynamic library?

I'm experimenting with using dynamic libraries and C on Linux. The following code will print wrong ouput:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **arg)
{
void *dl = dlopen("./lib.so", RTLD_NOW);
if (!dl) {
fprintf(stderr, "ERROR: %s\n", dlerror());
exit(1);
}
char *ver = dlsym(dl, "show_version");
printf("%s\n", ver);
}
If I make the following change the output will be correct:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char **arg)
{
void *dl = dlopen("./lib.so", RTLD_NOW);
if (!dl) {
fprintf(stderr, "ERROR: %s\n", dlerror());
exit(1);
}
char *(*ver)() = dlsym(dl, "show_version");
printf("%s\n", ver());
}
I'm not sure what char *(*ver)() is doing and why it's needed? Can anyone explain?
dlsym(dl, "show_version") returns the address for the symbol show_version. Since show_version is a function, that is the address of the function.
char *ver = dlsym(…); puts that pointer in a char *, which is basically useless. The pointer to a function does not point to bytes that are useful to print. Then printf("%s\n", ver); says to print the bytes that ver points to as if they were a string. But the bytes there are (in a typical C implementation) machine code for the function. They are not the bytes of a character string you want to print.
char *(*ver)() = dlsym(…); defines ver to be a pointer to a function whose arguments are not specified and that returns a char *. To see this:
char something declares something to be a char.
char *something declares something to be a pointer to a char.
char *something() declares something to be a function whose arguments are not specified that returns a pointer to char.
char *(*something)() declares something to a pointer to such a function.
Then, in printf("%s\n", ver());, ver() calls this function. The char * it returns is passed to printf to be printed.
dlsym - obtain address of a symbol in a shared object or executable
This means that when you do dlsym(dl, "show_version"); you are not actually calling the function show_version in your shared library. You obtain the address of that function - which can be used to call the function over and over again.
To "decode" what char *(*ver)() means, you can use what is often called the Clockwise/Spiral Rule
+-----+
| V
char* (*ver) () ver is a
^ ^ | | pointer to
| | | | a function (taking no arguments)
| +-+ | returning char*
| |
+------------+
I assume the above matches the signature of the show_version function that you put in the shared library. Example:
// a function (taking no arguments), returning a char*
char *show_version(void) {
static char version[] = "1.0";
return version;
}
Using the same rule on your first attempt, char* ver:
char* ver
^ | ver is a
| | char*
+----+
You need a pointer to a function (with the correct signature) to be able to call the function and get the result you want. You can't call a char* and when you do printf("%s\n", ver); it'll just start reading the memory at the address (where your function is stored) until it finds a null terminator. You probably see just gibberish.
If you on the other hand have a proper function pointer, you can as you've noticed, call the function it points at with ver() and you get a char* in return which points at the string your dynamically loaded function returned.
You can also use function pointers in your programs without involving shared libraries.
#include <stdio.h>
long foo(short x, int y) {
return x + y;
}
int main() {
long(*foo_ptr)(short, int) = foo;
// foo_ptr is a pointer to a function taking (short, int) as
// arguments and returning a long
printf("%ld\n", foo(1, 2) ); // prints 3
printf("%ld\n", foo_ptr(1, 2) ); // also prints 3
}

Command line arguments in main

I've written a code that sums up integers brought in from the command line:
#include <stdio.h>
int main(int argc, int* argv[]) {
int i, s=0;
for (i=1;i<argc;i++)
s=s + *argv[i];
printf("Sum: %d\n", s);
return 0;
}
The best part is, it passes the gcc compiling process, but when I actually run it and insert the numbers, the result seems I somehow breached the range of int.
It seems that you are compiling your code in C89 mode in which s is taken as int by default by compiler. s is uninitialized therefore nothing good could be expected. If fact it will invoke undefined behavior.
Note that argv[i] is of char * type (change your main signature) and you need to convert it to int before adding it to s.
The 2nd argument of main should be either of type char** or of type char*[] and not int*[]. So, *argv[i] is of type char. Instead of getting each character, you can get each string(argv[i] which is of type char*) and then extract the number from it and assign it to a variable, say num. This can be done by using the sscanf function:
#include <stdio.h>
int main(int argc, char* argv[]) { //int changed to char here
int i, s=0,num;
for (i=1;i<argc;i++)
if(sscanf(argv[i],"%d",&num)) //if extraction was successful
s=s + num;
printf("Sum: %d\n", s);
return 0;
}
Assuming you have s initialized properly as shown below.
Along with this the prototype of your main() should be as shown below inorder to get the command line arguments.
int main(int argc, char **argv)
{
int s =0;
// Check for argc matches the required number of arguments */
for(i=1;i<argc;i++)
s=s + atoi(argv[i]); /* Use atoi() to convert your string to integer strtol() can also be used */
printf("%d\n",s);
return 0;
}
PS: Using uninitialized variables lead to undefined behvaior

Shellcode in C program

In Demystifying the Execve Shellcode is explained a way to write an execve shellcode:
#include<stdio.h>
#include<string.h>
unsigned char code[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
What does the line int (*ret)() = (int(*)())code; do?
int (*ret)() = (int(*)())code;
~~~~~~~~~~~~ ~~~~~~~~~~~~~~
1 2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3
It defines ret as a pointer to a function which has no parameter () and returns int. So, Those () indicates the definition of parameters of a function.
It's for casting code to a pointer to a function which has no parameter () and returns int.
Casts code as a function and assigns it to ret. After that you can call ret();.
unsigned char code[] = "\x31\xc0\x50\x68\x6e\x2f\...
It is a sequence of machine instructions represented by hex values. It will be injected to the code as a function.
(*(void(*)())shellcode)()
==
p = (void(*)()) shellcode;
(*p)();
Can this function pointer part be re-written in a simpler form?
I don't know if you think this is simpler, but maybe:
#include <stdio.h>
#include <string.h>
unsigned char code[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
typedef int(*shellcode_t)();
int main(int argc, char ** argv) {
printf("Shellcode Length: %ld\n", strlen(code));
shellcode_t ret = (shellcode_t)code;
ret();
}
The int line declares the ret() function, by pointing to the code[] array; in other words, the function is mapped to the code[] binary instructions.
The \x construct is a safe way to embed hexadecimal characters in a string. You could for instance replace “\x31” by “1” as the character code of “1” is 49, or hexadecimal 31.

Creating variable with String to pass as uchar*

I am writing a program that passes text to a library function.
This function expects the text parameter to be of type unsigned char*.
So how can I properly pass a String to that function? I fail at converting an existing char* to unsigned char* and writing a new value into an unsigned char* variable via strncpy also didn't work.
Edit:
Here is a small example:
That is the function I need to call:
int count (void *index, uchar *pattern, uint length, uint *numocc);
This is what I have in my code:
count(index,?argv[2]?, length, numocc);
You can do typecasting with (unsigned char*). I am posting a small example may be it help you(read comments):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(unsigned char* str){ // argument should be unsigned char*
printf("\n In side fun: %s\n", str);
}
int main(){
char* s = "your_name"; // s is char*
func((unsigned char*)s); // notice type casting
return 1;
}
and it works:
~$ gcc x.c -Wall
~$ ./a.out
In side fun: your_name
~$
EDIT:
count(index, (uchar*)argv[2], length, numocc);
^ typecast (uchar*)
uchar* may be a typedef ed in your code like:
typedef unsigned char* uchar*

Cannot return and assign char array to pointer in C

char *test = "hello";
test = change_test("world");
printf("%s",test);
char* change_test(char *n){
printf("change: %s",n);
return n;
}
im trying to pass a 'string' back to a char pointer using a function but get the following error:
assignment makes pointer from integer without a cast
what am i doing wrong?
A function used without forward declaration will be considered having signature int (...). You should either forward-declare it:
char* change_test(char*);
...
char* test = "hello";
// etc.
or just move the definition change_test before where you call it.
printf() prints the text to the console but does not change n. Use this code instead:
char *change_test(char *n) {
char *result = new char[256];
sprintf(result, "change: %s", n);
return result;
}
// Do not forget to call delete[] on the value returned from change_test
Also add the declaration of change_test() before calling it:
char *change_test(char *n);
You're converting an integer to a pointer somewhere. Your code is incomplete, but at a guess I'd say it's that you're not defining change_test() before you use it, so the C compiler guesses at its type (and assumes it returns an integer.) Declare change_test() before calling it, like so:
char *change_test(char *n);
thanks a bunch guys! didnt think i would have this problem solved by lunch. here is the final test class
/* standard libraries */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* change_test(char*);
int main(){
char *test = "hello";
test = change_test("world");
printf("%s",test);
return (EXIT_SUCCESS);
}
char* change_test(char *n){
return n;
}

Resources