Calling a function of another program
This tutorial is a few years old. Please don’t ask for any source code because I don’t have any as I don’t do this kind of stuff anymore.
What is this tutorial about?
In this tutorial I want to show you how to call a function of another program or game and how to get the address of this function. The tutorial is written for people who have little to no assembly knowledge.
Requirements
For this tutorial you need to know how to inject a dll into a process. If you don’t know it, there are many tutorials about that (just google for them) or you can simply download an injector and read about how it works later. There are also plenty of websites and forums that deal with game hacking and things like that which can be very helpful.
You will also need a disassembler. I use ollydbg that you can download here for free.
Finding the address of the function
This is definitely the hardest part. For this tutorial I chose the game Ragnarok Online and the function I want to call is the one to write text into the chat. Either open up ollydbg and load the exe of the game there or start the game and attach ollydbg to it.
It should look like this:
Press F9 to start the game.
So I know that when I open a shop the following lines are always written into the chat:
In ollydbg right click and select Search for->All referenced text strings.
Search for the string that is written into the chat and double click it.
If you are not sure that the piece of code you found is called when you open the shop then you could right click on the address and set a breakpoint there.
This time it is so obvious that it isn’t needed.
Let’s have a look at the code:
004A455A |. 68 5CE96400 PUSH rag.0064E95C 004A455F |. 50 PUSH EAX 004A4560 |. E8 134C1600 CALL rag.00609178 004A4565 |. 83C4 08 ADD ESP,8 004A4568 |. 8D8D 50FEFFFF LEA ECX,DWORD PTR SS:[EBP-1B0] 004A456E |. 6A 00 PUSH 0 004A4570 |. 68 FFFF9600 PUSH 96FFFF 004A4575 |. 51 PUSH ECX 004A4576 |. 6A 01 PUSH 1 004A4578 |. B9 70806900 MOV ECX,rag.00698070 004A457D |. E8 2E7D0100 CALL rag.004BC2B0 004A4582 |. EB 20 JMP SHORT rag.004A45A4
In case you aren’t familiar with this: the first row is the address, the second the opcode and the third the assembler commands.
For those who hardly know any assembly like me I will try to explain what the lines of code do. At 004A455A the string at memory address 0064E95C is added to the stack. The next line adds the value of EAX to the stack. This is done to pass them to the function that is called at 004A4560. In assembly the parameters are added to the stack in reversed order.
C++: MyFunction(arg1, arg2); ASM: PUSH arg2 PUSH arg1 CALL MyFunction
So we basically have a function here that takes two parameters, the second one being the string that is written into the chat:
SomeFunction(parameter1, "text");
Let’s have a look at another piece of code:
004A452B |. 50 PUSH EAX 004A452C |. 68 98E96400 PUSH rag.0064E998 ; ASCII "Current Zeny : %s Z" 004A4531 |. 51 PUSH ECX 004A4532 |. E8 414C1600 CALL rag.00609178 004A4537 |. 83C4 20 ADD ESP,20 004A453A |. 8D95 50FEFFFF LEA EDX,DWORD PTR SS:[EBP-1B0] 004A4540 |. B9 70806900 MOV ECX,rag.00698070 004A4545 |. 6A 00 PUSH 0 004A4547 |. 68 FFFF7800 PUSH 78FFFF 004A454C |. 52 PUSH EDX 004A454D |. 6A 01 PUSH 1 004A454F |. E8 5C7D0100 CALL rag.004BC2B0 004A4554 |. 8D85 50FEFFFF LEA EAX,DWORD PTR SS:[EBP-1B0]
Again the function at 00609178 is called. By having a look at the PUSHes we see that 3 parameters are passed. So we know that the function can take a variable number of parameters. I set a breakpoint at 004A4532 and open a shop. In the Registers part of ollydbg I see that EAX has the value of ASCII 500.
So the code in C++ should look like this.
char* s1 = "Current Zeny : %s Z"; char* s2 = "500"; SomeFunction(parameter1, s1, s2);
Doesn’t this look familiar to you? Yes, it looks like the function sprintf().
Desc: Write formatted data to a string Buffer: Storage location for output Format: Format-control string Argument: Optional arguments Return: Number of bytes stored in buffer
Now we know that the function 00609178 is not the one we search for but formats the string that is written into the chat.
We skip the next 3 lines of code and see that starting at 004A4545 4 values are added to the stack and a function is called after that.
Function(1, EDX, 0x78FFFF, 0);
You can right click on CALL rag.004BC2B0, select Follow and set a breakpoint there. Unfortunately the debugger stops there every frame, so if it is the function to add text to the chat it has to serve some other purpose as well. Let’s check the parameters. What’s the value of EDX? A few lines before at 004A453A we see
004A453A |. 8D95 50FEFFFF LEA EDX,DWORD PTR SS:[EBP-1B0]
This command loads the address of EBP-1B0 into EDX. We need to know the value of EBP to get the address. Set a breakpoint on that command and open a shop. The debugger stops at that line.
At the registers part you see that EBP has a value of 0012FA28. We subtract 1B0 and get the value 12F878 which is the address of the string “Current Zeny : 500 Z”.
Now we know that EDX points to the string which is written into the chat window and we have all parameters of the function.
AddChat(1, "text", 0x78FFFF, 0);
Let’s call the function in our injected DLL. You could do this in C++ only; I did it with assembly because it was less work. This is how your function could look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 | void AddChat (char *text) { void *pChat = (void*)0x004BC2B0; __asm { mov ecx, text push 0 push 0x96FFFF push ecx push 1 call [pChat] } } |
Let’s test it to see if it works. Ingame I call AddChat ("test"); and the game crashes… huh? Ok, this time I start the game with my dll injected but also attach ollydbg to it. Again I crash the game with my code but this time ollydbg stops at the line of code that is responsible for the crash:
004BC6E9 8B11 MOV EDX,DWORD PTR DS:[ECX]
The address is 004BC6E9 so it’s in the function we call starting at 004BC2B0. In Ollydbg we can see that ECX has a value of 00000020. Now the error message: Access violation when reading [00000020]. Of course, 00000020 doesn’t exist. ECX for some reason has a wrong value.
We could follow the code backwards and see where the value comes from but I preferred to compare my code with the one in Ragnarok. The only difference I see is that line:
004A4540 |. B9 70806900 MOV ECX,rag.00698070
The function we call must somehow work with the value of ECX and because we don’t set it to the correct value it crashes.
So we add the line to our code:
1 2 3 4 5 6 7 8 9 10 11 12 | void *pChat = (void*)0x004BC2B0; void *pSomething = (void*)0x00698070; __asm { mov ecx, text push 0 push 0x96FFFF push ecx push 1 mov ecx, [pSomething] call [pChat] } |
The value for ECX is not static so we need to get it from 00698070 as well. Let’s see if it works now:
As you can see it works! :-)
Thanks for reading my tutorial.
Credits go to many people from the game-deception forums where I learned much of this.





August 6th, 2008 at 9:22 pm
Wow, thank you for posting this, I was trying to do it for hours! It Works! :)
March 11th, 2009 at 7:24 pm
hi, i’m impressed form your tutorials.. i found a strange ragnarok server with a crazy protection.. they use a dll with 3 or 4 unknown function… that funcions won’t leave me to debug the executable and decrypts packet..i’m looking for some help for understand how that protection work
April 25th, 2009 at 5:05 pm
Nice Tutorial. But what if the game use TLS ? I’ve tried it in a game, to call a function, but it crashes, beacause the game uses TLS . How to deal with it ?
June 29th, 2009 at 7:36 pm
Good Tut .. good job
i would love to see you making a bigger tutorial that includes it all !