5

I have located a function inside an executable which I'd like to call from my DLL. The address of it would be 0x0090DE00 according to OllyDbg. I've tried to call it directly:

luaL__openlib *f = ((luaL__openlib*)(module_handle  + 0x0090DE00));

but also with adding the base of the module handle to it as suggested here:

uint8_t * module_handle = (uint8_t *)GetModuleHandle(L"ForgedAlliance1.exe");

luaL__openlib *f = ((luaL__openlib*)(module_handle  + 0x0090DE00));

It appears that this is not working as I get access violation exceptions - it appears that the pointer is not valid.

So: How can I call this function by using its address?


I just inserted a simple RET instruction at 0x00C0B530. My code does now look as follows:

typedef void (*test) ();

EXTERN_DLL_EXPORT void initialize(lua_State *L)
{
    // Adding this should not be necessary. I get 0x00C0B530 from 
    // OllyDbg where the offset 0x00401000 is included
    uint8_t * module_handle = (uint8_t *)GetModuleHandle(L"ForgedAlliance1.exe");

    test *f = NULL;

    f = ((test*)(0x00C0B530));

    (*f)(); // Crashing 
}

What I don't quite understand is why I get a different address in the exception message:

Exception thrown at 0x909090C3 in ForgedAlliance1.exe: 0xC0000005: Access violation executing location 0x909090C3.


UPDATE: I just realized that 0x909090C3 is not just a pointer here, it is the code itself

90 | NOP
90 | NOP
90 | NOP
C3 | RETN

Seems I am messing something up with pointers. Why does it try to execute "location" 0x909090C3. That's not the location.

Community
  • 1
  • 1
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • 1
    When inspecting with olly, did you make sure the function isn't stored inside another module that `ForgedAlliance1.exe` uses and not exactly the executable itself? – Bauss Dec 12 '16 at 15:11
  • @Bauss Hm, I am a bit new to all this but I can tell you how I got the address: I just opened the executable file. As I debug through it I see that the starting address is `0x00401000`. So I am assuming that all I see in this particular window is my executable. Everytime I save some changes to the assembly code of the executable I am overwriting the executable `ForgedAlliance1.exe`. So as long as OllyDbg does not display other areas of my memory, the address should be correct and part of the executable. – Stefan Falk Dec 12 '16 at 15:15
  • 1
    Have you taken a look at this article? https://www.codeproject.com/articles/1045674/load-exe-as-dll-mission-possible – Alden Dec 12 '16 at 15:32
  • @Alden Does this imply I *have* to load the exe as dll or am I getting something wrong here? – Stefan Falk Dec 12 '16 at 15:37
  • `0x0090DE00` - this is `RVA` or `VA` ? you need `RVA`, and function no args ? – RbMm Dec 12 '16 at 15:42
  • I'm not as familiar with Windows, but in Linux when an executable or shared object is loaded the loader will not map the code to memory starting at 0x0 and instead will use an inconsistent offset, so if it is the same for Windows you cannot use a constant location for the function. It would probably be easier to try to use the system loading tools. – Alden Dec 12 '16 at 15:44
  • @RbMm If I inspect `0x0090DE00` in the debugger I see the values `0x909090C3` (see my **UPDATE** section) - so I guess it's a VA which points at the instructions `NOP NOP NOP RET` == `909090C3`. So maybe I just mess it up with the pointers here? – Stefan Falk Dec 12 '16 at 15:45
  • @Alden I am very certain that the address is correct since if I look at it in the debugger with a `void*` I can see that the instructions are there - the only thing missing is setting the `EIP` to it correctly apparently ^^ – Stefan Falk Dec 12 '16 at 15:46
  • @displayname - you need **RVA** - only this address is stable, while PE unchanged. – RbMm Dec 12 '16 at 15:47

1 Answers1

2

Alright, it was just a pointer mess-up. Sorry for that - did not write in C for quite a while. I did it right, basically, but the problem with

f = ((test*)(0x00C0B530));
(*f)();  

is, that (*f) is 0x909090C3 - the instructions inside the executable - and this is the address the program tries to jump to which is of course invalid.

So the trick was:

int test_addr = 0x00C0B530
f = ((test*)(&test_addr ));
(*f)();

I am sure this can be done a bit simpler but this is working now.

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378