Jump to content
Tuts 4 You

Any Tutorials For Calling Functions?


GNIREENIGNE

Recommended Posts

GNIREENIGNE
Posted

Does anyone know of any good tutorials that show you how to properly call a function (e.g. satisfy all of the parameters of the call, stack allocation and cleanup etc.)? I've noticed a few items in some popular debuggers that might be used for this purpose, but I'm not sure about it.

Thanks.

crystalboy
Posted

The question in my opinion is not so much clear, give more details.  

Which functions do you need to call?

Which programming language do you want to use?

  • Like 1
GNIREENIGNE
Posted

Thanks for replying.

I am asking about calling functions in assembly x86 and x64. I know the calling conventions are different, but I'm not sure about the rest.

Thanks, again.

crystalboy
Posted

My best suggestion is to read Modern X86 Assembly Language Programming by Daniel Kusswurm. (you can find it on the web)

It is a great book to clarify the concept that you miss.

As i know no one did tutorials on that topic so the best.

Hope it helps :)

 

  • Like 1
GNIREENIGNE
Posted

Thank you. I will certainly take a look at it. :)

GNIREENIGNE
Posted

Thank you. I will read through that, for sure.

If anyone has any tutorials for specifically calling functions using x32/x64dgb, immunity or olly etc., please let me know.

Thanks!

GNIREENIGNE
Posted

Just a quick update, for anyone that is interested and/or can provide some additional information on this topic...

I skimmed through the book on modern x86 assembly, and, although very thorough, it doesn't actually provide what I am looking for.

Additionally, the webpage that outlines the different calling conventions does just that - outlines the various calling conventions. Although helpful, it too does not actually provide the information that I need.

I have scoured the web only to find various articles and videos explaining the stack and how stack data is stored and layered for various purposes, including calling parameters etc....most of which, are not strictly assembly examples, but examples for assembly to C, C to assembly et al.. There does not actually seem to be any tutorial, anywhere, that shows you how to call a function using strictly assembly, using a live, practical example via x32/64dbg, ollydbg, immunity or other.

That said, hopefully someone can create one because I can't seem to figure this out.

Thanks.

Posted

If you know how various calling conventions work, you have all the information you need. You know how to pass parameters, how to call the function, how the result is returned and how clean up stack. That's it, there's nothing else to be learned.

So, where exactly are you stuck? Example program, big pictures and looong explanation of what you did and what's not working would certainly help.

  • Like 2
GNIREENIGNE
Posted (edited)

Thanks for responding, kao.

I have a very basic understanding of what it entails, but how to properly apply it is the difficult part. I spent a great deal of time yesterday trying to call a function, using various different approaches, but I was really just guessing the entire time as far as what to push on to the stack and so forth.

For example, I would set a breakpoint on a call that was getting executed constantly. I would examine the values for the various registers and try to mov/push those values back on to the stack (since I was trying to execute the call using my own, separate thread that was not part of the module). Everything that I tried did not work. I just need to understand how to determine what to do and in what order. If I can understand the 'what', then I can understand the 'how' and the 'why', it would really help.

I can try again and provide more information with pictures and so forth, if you like.

I appreciate any help on the matter.

Thanks.

EDIT:

So, for yesterday's example, I used an SNES emulator (snesgt.exe v0.230 beta 6) to speed up the process, with Super Mario Kart (USA) rom. Here are the CRC/Hash values for the emulator and rom:

EMULATOR:
CRC32  -  9DFDB072
MD5  -  3A9D2E93B9C438B99813D3D403CD2B57
SHA-1  -  16263C9934A494E1223BB2CE6EE0F7621C6FAF10

 

ROM:
CRC32  -  CD80DB86
MD5  -  7F25CE5A283D902694C52FB1152FA61A
SHA-1  -  47E103D8398CF5B7CBB42B95DF3A3C270691163B

I used Cheat Engine 6.5.1 to inject my code, using the built-in createthread feature. I wrote a custom script for that (see below for one example).

Attached is an image of the breakpoint.

Here is an example of one of my attempts:
 

[ENABLE]
alloc(cave,248)
createthread(cave)

cave:
sub esp,12
mov esi,0285A1D0
mov edi,0285FF08
mov ebx,0
mov ebp,68
call snesgt.exe+12D30
add esp,12
ret

[DISABLE]
dealloc(cave)

Here is another example, of a failed attempt (I can provide many more):
 

[ENABLE]
alloc(cave,248)
createthread(cave)

cave:
sub esp,4
mov ecx,051100A8
push ecx
call snesgt.exe+12D30
pop ecx
add esp,4
ret

[DISABLE]
dealloc(cave)

5-31-2016 1-38-46 AM.png

Edited by GNIREENIGNE
  • Like 1
Posted (edited)

I'm not using SNES emulators or CheatEngine, so I can't comment if you're using it correctly or not. And it would help a lot, if you could show disassembly of that function you're calling. But even without that I can tell you immediately:

1) based on the disassembly you provided, I am *guessing* that the software was written in Delphi/Pascal and functions use Borland's register calling convention. You can see that ECX register was used at the very start of function (snesgt.exe+1F170) and ECX was assigned right before call (snesgt.exe+1F19D). Your code doesn't do that.

2) what's the point of "sub esp, 12" and "add esp, 12" in your code? You're not using the stack and it looks like the function you're calling is not using it either.

3) you have some "magic" values in ESI/EDI registers. If the code you're calling doesn't use them, don't set them. If code is using them, they are very likely to change on each run, so you should find them in process memory somehow.

 

And few general issues that may or may not be real issues, depending on CheatEngine's behavior:

1) thread procedures should end with "ret 4" (unless CheatEngine's injector is really forgiving). Reason - freshly created thread gets one parameter on stack, and it should clean it up: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686736(v=vs.85).aspx

2) your code is messing up ebp, ebx, esi and edi registers. Again, unless CheatEngine is really forgiving, you code should never do that. All calling conventions require you to save most of the registers.

 

EDIT: and how using cheatengine is relevant to calling function from Olly/Immunity/x64dbg? :)

Edited by kao
  • Like 2
GNIREENIGNE
Posted

Thanks for replying, kao.

When you say 'show dissassembly', what are you referring to, exactly?

Attached is a screenshot of another break (showing the stack options), at the same location, but during a different session. I have also attached a screenshot of the full stack, using the esp+ parameters.

I have tried, in previous attempts, to push and mov every value from the registers before calling, and popping them after the call, but that also didn't work.

As far as ret4, I do not believe that is required with CE, as all of the examples that I have seen do not show them that way. I cannot confirm any of the other details regarding CE.

I apologize for not understanding most of this.

Thanks, again.

 

5-31-2016 2-16-13 AM.png

5-31-2016 2-16-36 AM.png

GNIREENIGNE
Posted (edited)
31 minutes ago, kao said:

EDIT: and how using cheatengine is relevant to calling function from Olly/Immunity/x64dbg? :)

It's not. It's was I use mostly these days, but any program will do. CE makes it a lot easier for code injection. Other than that, it really doesn't matter which program we use, as the idea is basically the same. Tell me your preference, and we can use that. :)

EDIT:

For that matter, we can use any example file to test on, as well. Whatever is easier. I appreciate you taking the time to help me.

EDIT#2:

Here are more screenshots (from x32dbg):

5-31-2016 2-46-14 AM.png

5-31-2016 2-46-28 AM.png

Edited by GNIREENIGNE
Posted

OK, let's start learning with something extra simple.

Attached is a very simple test executable. At address 401270 is a method which shows message box. Method takes no parameters, so the calling convention is not really important. It also doesn't use any variables from the process.
Run the process and inject code that calls this method. Once you manage to do that, I'll create a new executable, making it more difficult each step.

step1.zip

  • Like 3
Posted

Given that ECX is being populated before the call, it makes it more likely to be __thiscall (class member call), where ECX is holding the object pointer and the call is to a class function. 

As long as you are giving the proper parameters, it should handle the call fine. Keep in mind if that call requires other internal bits to be constructed and such, those will need to be done as well. For example if you are calling a member function that internally tries to use a block of memory that isn't allocated yet, you are going to crash.

Take this for example:

.text:101E1643                 push    0               ; char
.text:101E1645                 push    1               ; char
.text:101E1647                 push    offset aMenuOlstat ; "menu    olstat  "
.text:101E164C                 mov     ecx, offset unk_105D8FB0
.text:101E1651                 call    sub_10155D20

There are 4 arguments to this __thiscall function. The first being the class object moved into ECX, then the others are pushed onto the stack. In C++ this would look like this:

auto func = (int(__thiscall *)(void* pThis, const char*, char, char))sub_10155D20;

In C++ I can call this function from an injected DLL doing this:

auto argument1 = "menu    olstat  ";
auto argument2 = 1;
auto argument3 = 0;    

auto funcPointer = (DWORD)::GetModuleHandle("Game.dll") + 0x155D20;
auto func = (int(__thiscall *)(void* pThis, const char*, char, char))funcPointer;
auto funcThis = (LPVOID)((DWORD)::GetModuleHandle("Game.dll") + 0x5D8FB0);

func(funcThis, argument1, argument2, argument3);

In your Cheat Engine script, since you are injecting a thread, you don't need to have any type of prologue/epilogue code. You can just call the function directly with the proper arguments. In your first Cheat Engine post, it looks like you only have 1 argument to push (eax's value) then move the proper value into ECX and make the call.

  • Like 2
Posted

Here is another example written in C++, this is a basic app that makes a class call to show a message:


/**
 * __thiscall example by atom0s [atom0s@live.com]
 */

#include <Windows.h>

/**
 * Basic Class Example
 */
class BasicClass
{
public:
    BasicClass(void) { }
    ~BasicClass(void) { }

    /**
     * Example call demonstrating the __thiscall convention.
     *
     * @param {bool} retValue                       The value for this function to return.
     * @param {const char*} msg                     The message to display.
     * @param {const char*} title                   The title of the message to display.
     * @returns {bool}                              User defined return from the first argument.
     */
    bool ExampleCall(bool retValue, const char* msg, const char* title)
    {
        ::MessageBox(HWND_DESKTOP, msg, title, MB_OK);
        return retValue;
    }
};

// Create an instance of our basic class..
// This is done outside of the main call to prevent stack usage.
auto b = new BasicClass();

/**
 * Application entrypoint.
 *
 * @param {int} argc                                The number of arguments passed to this application.
 * @param {char* []} argv                           The arguments passed to this application at startup.
 */
int __cdecl main(int argc, char* argv[])
{
    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);

    while (true)
    {
        // Allow F1 to exit the loop..
        if (::GetAsyncKeyState(VK_F1) & 1)
            break;

        // Allow F2 to show our message..
        if (::GetAsyncKeyState(VK_F2) & 1)
            b->ExampleCall(true, "Hello world!", "Title here!");

        // Sleep to not kill the CPU..
        ::Sleep(10);
    }

    // Cleanup our class object..
    if (b)
        delete b;
    b = nullptr;

    return ERROR_SUCCESS;
}

In OllyDbg/IDA you can see how this is called when F2 is pressed here:

.text:004010F1 loc_4010F1:                             ; CODE XREF: sub_4010D0+1Dj
.text:004010F1                 push    71h             ; vKey
.text:004010F3                 call    ds:GetAsyncKeyState
.text:004010F9                 movsx   edx, ax
.text:004010FC                 and     edx, 1
.text:004010FF                 jz      short loc_401118
.text:00401101                 push    offset Caption  ; "Title here!"
.text:00401106                 push    offset Text     ; "Hello world!"
.text:0040110B                 push    1               ; char
.text:0040110D                 mov     ecx, dword_4033F4
.text:00401113                 call    sub_4010A0

In my test app, I have the function take 3 arguments, a boolean, and two strings. Compiled this requires ECX be filled with the class object. Running the application we can force call this function with our own parameters via Cheat Engine's autoassembler like this:

[ENABLE]
alloc(cave, 1024)
alloc(appname, 1024)
alloc(str1, 1024)
alloc(str2, 1024)
createthread(cave)

appname:
  db 'ClassCallExample.exe',0
str1:
  db 'This is my custom message!',0
str2:
  db 'Title',0

cave:
  push appname            // push the application name
  call GetModuleHandleA   // obtain the applications base address
  mov edx, eax            // store this base for call usage
  add eax, 33F4           // offset the base to the 'this' object for the class call
  add edx, 10A0           // offset the base to the function call
  push str2               // push the title
  push str1               // push the message
  push 1                  // push the return value (bool argument)
  mov ecx, [eax]          // obtain the 'this' object for the function call
  call edx                // call the function
  ret                     // return

[DISABLE]
dealloc(cave)
dealloc(appname)
dealloc(str1)
dealloc(str2)

Sadly, Cheat Engine's autoassembler has some limitations on how it can handle strings within opcodes, so we can't do simple things like "call "ClassCallExample.exe" + 10A0" to make the code cleaner. This is much easier to do in another language though like C++ if you inject a DLL etc. since you can do direct casting and so on.

ClassCallExample.rar

  • Like 2
GNIREENIGNE
Posted

Thanks, guys.

Some of this is over my head, but some of it actually makes sense. Please give me some time to go over everything and I will report back as soon as I can.

By the way, atom0s, getting the base address of the module is not necessary with CE if module addressing is viable for the target process, right?

Thanks.

GNIREENIGNE
Posted (edited)
2 hours ago, kao said:

OK, let's start learning with something extra simple.

Alright, so I've managed to call that function easily enough. Thanks!

Here is my solution, using CE:
 

[ENABLE]
alloc(cave,48)
createthread(cave)

cave:
push 0
push 402021
push 402014
push 0
call 4012d2
ret

[DISABLE]

EDIT:

atom0s:

I cannot seem to run ClassCallExample.exe. I receive the following error (see attachment). I tried running in compatibility mode for WinXP SP3 and as admin, but that didn't work. I also tried downloading Visual C++ 2015 redis (x64)...I could not find an (x86) version - but that didn't work, either. I actually have the dll on my computer, so I copied it to the temporary folder where the exe is being stored and tried again...but now I'm receiving another error saying that the application was unable to start correctly (0xc0000007b).

 

5-31-2016 7-16-27 AM.png

By the way, I keep trying to call the function from the SNES emulator, but I'm still doing something wrong. Here is an example of my latest attempt:
 

[ENABLE]
alloc(cave,248)
createthread(cave)

cave:
push eax
push ecx
mov eax,6
mov ecx,04FC00A8
call snesgt.exe+12D30
pop ecx
pop eax
ret

[DISABLE]
dealloc(cave)

 

Edited by GNIREENIGNE
Posted

That's not exactly right. You're not calling that function, you're copying the entire code of that function. Feel the difference? :) 

Spoiler

You would need only 2 lines in your cave - "call 401270" and "ret"

 

Here's step 2. Now function at address 401270 uses stdcall calling convention and takes some parameters. Your task it to call it with correct parameters, so that message box is shown.

step2.zip

  • Like 1
GNIREENIGNE
Posted

Oh...I see now! Thanks!

By the way, I solved the SNES emulator call (yay):
 

[ENABLE]
alloc(cave,248)
createthread(cave)

cave:
push eax
mov ecx,[snesgt.exe+115110]
call snesgt.exe+12D30
pop eax
ret

[DISABLE]

I will work on step2 when I get back from breakfast. Thanks, everyone!

GNIREENIGNE
Posted
5 hours ago, kao said:

Here's step 2. Now function at address 401270 uses stdcall calling convention and takes some parameters. Your task it to call it with correct parameters, so that message box is shown.
 

These tutorials are really neat, kao. Thanks for helping me with this. Solving step2 only required me to change 1 byte from my first solution:
 

[ENABLE]
alloc(cave,48)
createthread(cave)

cave:
push 0
push 402021
push 402014
push 0
call 4012DE
ret

[DISABLE]

It works. I hope it's right. :)

Posted
7 hours ago, GNIREENIGNE said:

atom0s:

I cannot seem to run ClassCallExample.exe. I receive the following error (see attachment). I tried running in compatibility mode for WinXP SP3 and as admin, but that didn't work. I also tried downloading Visual C++ 2015 redis (x64)...I could not find an (x86) version - but that didn't work, either. I actually have the dll on my computer, so I copied it to the temporary folder where the exe is being stored and tried again...but now I'm receiving another error saying that the application was unable to start correctly (0xc0000007b).

 

That means you are missing the runtime for it. It uses Visual Studio 2015 (C++) which you can snag the runtime for here:

https://www.microsoft.com/en-us/download/details.aspx?id=51682

(This is done in 32bit so you only need the 32bit version  (x86) but you can install both for any future app you run into that uses it.)

  • Like 1
Posted
7 hours ago, GNIREENIGNE said:

Thanks, guys.

Some of this is over my head, but some of it actually makes sense. Please give me some time to go over everything and I will report back as soon as I can.

By the way, atom0s, getting the base address of the module is not necessary with CE if module addressing is viable for the target process, right?

Thanks.

 

Supposed to be that way but my CE does not seem to like me using the module name(s) in autoassembler scripts. May just need to update it since I haven't in a while.

  • Like 1
GNIREENIGNE
Posted
19 minutes ago, atom0s said:

 

That means you are missing the runtime for it. It uses Visual Studio 2015 (C++) which you can snag the runtime for here:

https://www.microsoft.com/en-us/download/details.aspx?id=51682

That fixed it. Thanks! I actually visited that site earlier, but quickly closed it because I thought it was a redirect for windows 10.

I will take a look at your example later. I will report back. Thanks, again.

Regarding the module addressing in AA scripts...yeah, you may need to update. The way you showed it in your example helped me learn something new, though. :)

GNIREENIGNE
Posted (edited)
[ENABLE]
alloc(cave,48)
createthread(cave)

cave:
push classcallexample.exe+2190
push classcallexample.exe+219c
push 1
mov ecx,[classcallexample.exe+33f4]
call classcallexample.exe+10a0
ret

[DISABLE]

Here is my solution. It seems to work!

Edited by GNIREENIGNE

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...