** If anything is unclear, I'm sorry. The code isn't great cos i hacked it together this afternoon just a PoC. Enjoy! **
I dunno if anyone has posted anything about using a code cave to run functions in Wow instead of injecting a DLL, but I'm going to now.
First, for those that don't know what a code cave is:
It is somewhere in a remote process' memory where you put your own code, maybe some space that isn't used or some space that you allocate with VirtualAllocEx and free with VirtualFreeEx 
You can insert code in to this space and then run it!
After you insert your code you can pause the current thread, change the instruction pointer to where your code is, then resume the thread. This will run your code.
Of course, if you jump to some code that uses registers/flags and you don't restore them bad things will happen. The easiest way to do that is just to push them on the stack at the start of the injected code and pop them off at the end.
Also you'll probably want to return to where the thread was before your code ran, so you'll need to push the return address on to the stack first.
Code:
push 0xDEADBABE // Placeholder for the return address
pushfd // Save the flags and registers
pushad
//-- Something useful goes here :)
popad // Restore the registers and flags
popfd
ret // Return control to the hijacked thread
Something like that would be a good start.
So... HOWTO:
Here's what i did:
- Find the target Window Handle
- Find the main thread ID
- Open the process PID
- Open the thread
- Allocate space for the code
- Make any changes to the "to-be-injected" code (return address, etc.)
- Write the code to the allocated space
- Pause the thread
- Update the instruction pointer to point the allocated space
- Resume the thread
- Wait a bit for the code to run
- De-allocate the memory allocated for the code
- Have a beer
In you code you could call a function or whatever, but you won't be able to get any return values... unless you allocate some space for the result and have you code write that result to that known location and then read it later. So in addition to the above you must:
- Allocate space for the result
- Edit your code to write to the allocated location
- Read the result after the thread is resumed
I have produced some code (in C++) that will do all of this, it can be found here: Nopaste - Wow CodeCave.
It calls the CompareUnitFaction function to get the reaction of one unit's faction to another.
It doesn't do anything fancy and the Unit 1 and Unit 2 base addresses are hardcoded in. But if you don't know how to find them this really isn't for you 
*
Credit here to kynox and Shynd for info about CompareUnitFaction
Finding the functions and working out the arguments takes some time and a good disassembler/debugger, personally I like IDA (cos I can do other things - mega drive hehe) 
*
The CompareUnitFaction (as it's being called) function takes two arguments, a pointer to the current Unit and a pointer to the second Unit. The current Unit is in the register ECX and the second Unit is pushed on to the stack. In my code it is called by doing:
Code:
push 0xDEADBABE // Place holder for Unit2
mov ecx, 0xDEADBABE // Place holder for Unit1
mov eax, 0x005D4AB0 // Offset for the CompareUnitFaction function
call eax
This will run and return the faction's reaction to you in EAX, I used this code to right that value in to memory where it could be read:
Code:
mov ebx, 0xDEADBABE // Offset to read result from :)
mov dword ptr [ebx], eax
In the program the place holders are replaced with memcpy after the memory protection has been changed.
injectCode is the function with the asm in it :
void __declspec(naked) injectCode(void){ _asm { ... } }
naked means no prologue or epilogue
Code:
// Return address
memcpy((LPVOID)((DWORD)injectCode + 0x01), &oldIP, 4);
// Unit2 base address
memcpy((LPVOID)((DWORD)injectCode + 0x08), &dwUnit2, 4);
// Unit1 base address
memcpy((LPVOID)((DWORD)injectCode + 0x0D), &dwUnit1, 4);
// Result address
memcpy((LPVOID)((DWORD)injectCode + 0x19), &dwResutlAddress, 4);
OK, think that covers everything. I have NOT tested this on a live server only on an emulated server so I dunno if you'll get disconnected or whatever. I didn't on the emulated server i was on (OpenAscent TRUNK r334/Release-Win-X86).
If i have missed anything or you have any question I will try to answer them as best I can 
Edit: Here is an output from the program very verbose hehe
Code:
[?] PID: 2980
[?] TID: 3012
[?] HWND: 0x00460816
[?] Handle: 0x7A4
[?] Code to inject: 0x00401000 - 0x00401030 (0x00000030)
[?] Thread Paused...
[?] Old Instruction Pointer : 0x7C90EB94
[?] Enabled modify for inject-code...OK!
[?] Updating return address (0x00401001 -> 0x7C90EB94)...OK
[?] Updating Unit2 address (0x00401008 -> 0x1070D0F0)...OK
[?] Updating Unit1 address (0x0040100D -> 0x105F8008)...OK
[?] Updating result address (0x00401018 -> 0x08FD0000)...OK
[?] Writing code stub to 0x01710000...pass.
[?] Updating the thread context...pass.
[?] Thread Resumed at 0x01710000...done!
[?] GetFactionHostility(0x105F8008, 0x1070D0F0) = 0x00000004
[?] Closing thread...done
[?] Freeing memory...done.
[?] Closing process...done.