3

With the Visual C++ compiler, it is possible to create a DLL file, that can imitate another DLL file and redirect all function calls to the original DLL. Here is an article with a tool that can generate Visual C++ code automatically.

The generated function-stubs work (tested) and look like this:

extern "C" __declspec(naked) void __stdcall __E__0__()
{
    __asm
    {
        jmp p[0]; // p[0] = GetProcAddress(hL,"AcceptEx");
    }
}

Now I want to do the same thing with MinGW/GCC instead of MSVC.

__declspec(naked) isn't supported by GCC on i386, so we need another way. As suggested here, I could override functions by writing assembly code in the global scope. Here's my code that should do the trick:

__asm__
(
    "jmp *%0"
    : /* empty output list */
    : "r" (pointer_to_original_function) /* p[0] in the example above */
);

My snippet uses GCC's extended ASM. But unfortunatelly this is only allowed inside of functions, not in the global scope!

So... how do I do that? My next approach would be to try it without extended ASM, but how do I get the pointer address in assembly then?

Here i'm trying to get it from a global variable, but it segfaults at repace_this_stub():

#include <stdio.h>

void try_to_jump_to_me()
{
    printf("you made the jump\n");
}

void* target_pointer = try_to_jump_to_me;

__asm__ (
    "replace_this_stub:"
    "jmp target_pointer"
);
void replace_this_stub();


int main(int argc, char** argv)
{   
    printf("starting in main. \n");

    replace_this_stub();

    printf("back in main?\n");

}
Community
  • 1
  • 1
John Smith
  • 33
  • 6
  • Presumably the pointer is in some global variable ... so just use its name. – Jester May 08 '15 at 22:35
  • I'm not so good at assembly, could you give me an example code? I guess __asm__("jmp global_variable"); won't work -- also I'd like to use some sort of array if possible, because there are usually lots of functions – John Smith May 08 '15 at 22:39

1 Answers1

2

If the pointer is in a global variable, you can just use its name. Be sure to apply any name mangling. Also put your code in the applicable code section and give it a name. Sample code:

#include <stdio.h>

void* p = printf;

asm(
    ".section .text\n\t"
    "proxy: jmp *p\n\t"
    ".previous\n\t");
extern void proxy();
int main()
{
    proxy("Hello world!\n");
    return 0;
}

If you want to use an array, just add the appropriate displacement. Extended sample:

#include <stdio.h>
#include <string.h>

void* p[] = { printf, strcpy };
#define str(x) #x
#define PROXY(name, index) asm( \
    ".section .text\n\t" \
    str(proxy_##name) ": jmp *p + " str(index) " * 4\n\t" \
    ".previous\n\t"); \
    extern void proxy_##name()

PROXY(printf, 0);
PROXY(strcpy, 1);

int main()
{
    char buf[128];
    proxy_strcpy(buf, "Hello world!\n");
    proxy_printf(buf);
    return 0;
}
Jester
  • 56,577
  • 4
  • 81
  • 125
  • 1
    awesome! I was researching this for hours, you have really saved me a lot of time! I'd give you an upvote, but I don't have enough reputation yet. – John Smith May 08 '15 at 23:06
  • Also when compiling on x86_64 for testing, one needs to replace the 4 with 8 in the assembly line, because pointers have twice the size there. It works! :) – John Smith May 09 '15 at 08:45