Search code examples
cassemblycode-injectionshellcode

Calling x86 local function using shellcode


I would like to use redirect the flow to a local function and then returning to the original one using a shellcode.
I defined two simple functions and use objdump to get their assembly code:

// unsigned char *g_code = "\x55\x48\x89\xe5\xb8\x2a\x00\x00\x00\x5d\xc3";
int g() {
    return 42;
}

// unsigned char *f_code_original = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x89\x45\xfc\xb8\x2a\x00\x00\x00\xc9\xc3";
int f() {
    int x = g();
    return 42;
}

In a different file, I have a function that I want to call between the two instructions of f:

void redirect() {
    FILE *out = fopen("redirect.txt", "w");
    fprintf(out, "REDIRECT WORKED");
    fclose(out);
}

For that I use the following code, compiled with -fPIC -fno-stack-protector -z execstack:

void f_func() {
    unsigned char *f_code_original = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x89\x45\xfc\xb8\x2a\x00\x00\x00\xc9\xc3";
    unsigned char f_code_modified[] = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\x00\x00\x00\x00\xe8\xfb\xfe\xff\xff\xb8\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x89\x45\xfc\x8b\x45\xfc\xc9\xc3";

    int value = 0;

    int (*f)() = (int (*)())f_code_modified;
    value = f();

    printf("%d\n", value);
}

If I use the original code of f (as I got it from objdump) it works. I wanted to modify it in order to call my redirect function, then resume the current execution.

Assembly code (for f_code_modified):

0:  55                      push   ebp
1:  48                      dec    eax
2:  89 e5                   mov    ebp,esp
4:  48                      dec    eax
5:  83 ec 10                sub    esp,0x10
8:  b8 00 00 00 00          mov    eax,0x0       <==
d:  e8 fb fe ff ff          call   0xffffff0d    <==
12: b8 00 00 00 00          mov    eax,0x0
17: e8 00 00 00 00          call   0x1c
1c: 89 45 fc                mov    DWORD PTR [ebp-0x4],eax
1f: 8b 45 fc                mov    eax,DWORD PTR [ebp-0x4]
22: c9                      leave
23: c3                      ret 

This looks similar if I make the calls directly from main (int x = g(); redirect(); return 42;), but I think that the call instruction at d: e8 .. .. .. .. is relative the current instruction pointer.

If I run the program like this it gives segmentation fault.

Question: Is there a way I can find the current instruction pointer at runtime, then write the shellcode as \xe8\x??\x??\x??\x?? to call the function redirect? What do I have to modify? I have already tried with -fPIC and getting the address of redirect (using &), but it doesn't work.


Solution

  • Following Peter Cordes comment, you could embed the absolute address of the target function into the shellcode.

    To find function address redirect(), I'm using nm, so the command is :

    % nm <binary> | grep redirect

    Output : 080484bb T redirect

    So, I rewrite your shellcode to modify, something adding redirect() function address :

    test_shellcode :

    push ebp
    dec eax
    mov ebp,esp
    dec eax
    sub esp,0x10
    mov eax,0x080484bb    ; redirect() function address
    call eax
    mov dword [ebp-0x4],eax
    mov eax,dword [ebp-0x4]
    leave
    ret
    

    test_shellcode2 :

    push ebp
    dec eax
    mov ebp,esp
    dec eax
    sub esp,0x10
    mov eax,0x80484bb    ; redirect() function address
    call eax
    mov eax,0x0
    call 0x1c
    mov dword [ebp-0x4],eax
    mov eax,dword [ebp-0x4]
    leave
    ret
    

    Here, I modified your code :

    #include <stdio.h>
    #include <string.h>
    
    void redirect() {
        FILE *out = fopen("redirect.txt", "w");
        fprintf(out, "REDIRECT WORKED");
        fclose(out);
    }
    
    void f_func() {
    //    unsigned char *f_code_original = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x89\x45\xfc\xb8\x2a\x00\x00\x00\xc9\xc3";
    //    unsigned char f_code_modified[] = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\x00\x00\x00\x00\xe8\xbb\x84\x04\x08\xb8\x00\x00\x00\x00\xe8\x00\x00\x00\x00\x89\x45\xfc\x8b\x45\xfc\xc9\xc3";
    
    // Here shellcode, I wrote :
    
        unsigned char *test_shellcode = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\xbb\x84\x04\x08\xff\xd0\x89\x45\xfc\x8b\x45\xfc\xc9\xc3";
    
    //    unsigned char *test_shellcode2 = "\x55\x48\x89\xe5\x48\x83\xec\x10\xb8\xbb\x84\x04\x08\xff\xd0\xb8\x00\x00\x00\x00\xe8\xa3\x7f\xfb\xf7\x89\x45\xfc\x8b\x45\xfc\xc9\xc3";
    
        int value = 0;
    
        int (*f)() = (int (*)())test_shellcode;
        value = f();
    
        printf("%d\n", value);
    }
    
    int main(int argc, char **argv) {
        f_func();
    }
    

    Compile with -fPIC -fno-stack-protector -z execstack, so yeah it's work. This is for example I'm using test_shellcode :

    % ls -l
    total 16
    -rwxrwxr-x 1 febri febri 7548 Jan  1 08:40 shell
    -rw-rw-r-- 1 febri febri 1075 Jan  1 08:39 shell.c
    drwxrwxr-x 2 febri febri 4096 Jan  1 08:16 shellcode
    % ./shell
    0
    % ls -l  
    total 20
    -rw-rw-r-- 1 febri febri   15 Jan  1 08:41 redirect.txt
    -rwxrwxr-x 1 febri febri 7548 Jan  1 08:40 shell
    -rw-rw-r-- 1 febri febri 1075 Jan  1 08:39 shell.c
    drwxrwxr-x 2 febri febri 4096 Jan  1 08:16 shellcode
    % cat redirect.txt
    REDIRECT WORKED
    

    But, if I'm using test_shellcode2, I get Segmentation fault, but It's work :

    % ls -l
    total 16
    -rwxrwxr-x 1 febri febri 7548 Jan  1 08:46 shell
    -rw-rw-r-- 1 febri febri 1076 Jan  1 08:46 shell.c
    drwxrwxr-x 2 febri febri 4096 Jan  1 08:16 shellcode
    % ./shell
    [1]    7465 segmentation fault (core dumped)  ./shell
    % ls -l
    total 20
    -rw-rw-r-- 1 febri febri   15 Jan  1 08:46 redirect.txt
    -rwxrwxr-x 1 febri febri 7548 Jan  1 08:46 shell
    -rw-rw-r-- 1 febri febri 1076 Jan  1 08:46 shell.c
    drwxrwxr-x 2 febri febri 4096 Jan  1 08:16 shellcode
    % cat redirect.txt
    REDIRECT WORKED                                                                                                                                                  %