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.

4 Responses to “Calling a function of another program”

  1. car Says:

    Wow, thank you for posting this, I was trying to do it for hours! It Works! :)

  2. the7th Says:

    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

  3. NetGhost03 Says:

    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 ?

  4. Virus Ecks Says:

    Good Tut .. good job
    i would love to see you making a bigger tutorial that includes it all !

Leave a Reply