2

I'm trying to create a bot for a game called "Mech Warrior Online". I've just completed my DLL injector which I want to use as mean to call function from the MWO client such as (fire, move, look around, etc...).

My problem is that I'm not great at reverse engineering, I'm trying hard to learn with tutorials, but I haven't found a particular one which addresses my problem.

So here goes, by using IDA and looking at strings, I've found this: Strings window

Fire1 through Fire6 are most likely related to shooting weapons group 1-6. So if I click on it I get this; The function responsible for a bunch of stuff !

Now this function looks very interesting, seems to control the power on/off of the mech, jumpjets, turning, throttle, weapons firing etc.

My problem is that I'd like to call this function to fire the weapons, but I can't seem to figure out how. I did some tutorials where I was able to inject my dll and call functions remotely via exports. But this function is very complex (in my opinion). Here's a look inside:

int __stdcall sub_37FC7C90(int a1)
{
  int result; // eax@5
  int v2; // edx@5
  int v3; // [sp+14h] [bp-4h]@2

  int result; // eax@5

  int v2; // edx@5
  int v3; // [sp+14h] [bp-4h]@2

  if ( !(dword_38CB3580 & 1) )
  {
    dword_38CB3580 |= 1u;
    dword_38CB33F8 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 1;
    dword_38CB33E8 = (int)"Enabled";
    dword_38CB33EC = 0;
    dword_38CB33F0 = (int)szAgent;
    dword_38CB33F4 = 0;


(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB33FC,
      &v3);


(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3410 = (unsigned int)&unk_389BAF54 | 1;
    v3 = 0;
    dword_38CB3400 = (int)"Throttle";
    dword_38CB3404 = 0;
    dword_38CB3408 = (int)szAgent;
    dword_38CB340C = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BAF54 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3414,
      &v3);
(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BAF54 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3428 = (unsigned int)&unk_389BAF54 | 1;
    v3 = 0;
    dword_38CB3418 = (int)"Turn";
    dword_38CB341C = 0;
    dword_38CB3420 = (int)szAgent;
    dword_38CB3424 = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BAF54 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB342C,
      &v3);
(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BAF54 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3440 = (unsigned int)&unk_389BB168 | 1;
    v3 = 0;
    dword_38CB3430 = (int)"TurnTarget";
    dword_38CB3434 = 0;
    dword_38CB3438 = (int)szAgent;
    dword_38CB343C = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BB168 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3444,
      &v3);
(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BB168 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3458 = (unsigned int)&unk_389BB168 | 1;
    v3 = 0;
    dword_38CB3448 = (int)"LookTarget";
    dword_38CB344C = 0;
    dword_38CB3450 = (int)szAgent;
    dword_38CB3454 = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BB168 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB345C,
      &v3);
(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BB168 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3470 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB3460 = (int)"JumpJet";
    dword_38CB3464 = 0;
    dword_38CB3468 = (int)szAgent;
    dword_38CB346C = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3474,
      &v3);
(*(void (__cdecl **)(int *))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3488 = (int)&unk_389BAE60;
    dword_38CB3478 = (int)"PowerOn";
    dword_38CB347C = 0;
    dword_38CB3480 = (int)szAgent;
    dword_38CB3484 = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 12))(&unk_38CB348C, &v3);
(*(void (__cdecl **)(int *))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB34A0 = (int)&unk_389BAE60;
    dword_38CB3490 = (int)"PowerOff";
    dword_38CB3494 = 0;
    dword_38CB3498 = (int)szAgent;
    dword_38CB349C = 0;
(*(void (__cdecl **)(_UNKNOWN *, int *))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 12))(&unk_38CB34A4, &v3);
(*(void (__cdecl **)(int *))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB34B8 = (int)&unk_389BAE60;
    dword_38CB34A8 = (int)"TogglePower";
    dword_38CB34AC = 0;
    dword_38CB34B0 = (int)szAgent;
    dword_38CB34B4 = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 12))(&unk_38CB34BC, &v3);
(*(void (__cdecl **)(_DWORD))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB34D0 = (int)&unk_389BAE60;
    dword_38CB34C0 = (int)"ToggleWeaponDoors";
    dword_38CB34C4 = 0;
    dword_38CB34C8 = (int)szAgent;
    dword_38CB34CC = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 12))(&unk_38CB34D4, &v3);
(*(void (__cdecl **)(_DWORD))(((unsigned int)&unk_389BAE60 & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB34E8 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB34D8 = (int)"Fire1";
    dword_38CB34DC = 0;
    dword_38CB34E0 = (int)szAgent;
    dword_38CB34E4 = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB34EC,
      &v3);
(*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3500 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB34F0 = (int)"Fire2";
    dword_38CB34F4 = 0;
    dword_38CB34F8 = (int)szAgent;
    dword_38CB34FC = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3504,
      &v3);
(*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3518 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB3508 = (int)"Fire3";
    dword_38CB350C = 0;
    dword_38CB3510 = (int)szAgent;
    dword_38CB3514 = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB351C,
      &v3);
(*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3530 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB3520 = (int)"Fire4";
    dword_38CB3524 = 0;
    dword_38CB3528 = (int)szAgent;
    dword_38CB352C = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3534,
      &v3);
(*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3548 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB3538 = (int)"Fire5";
    dword_38CB353C = 0;
    dword_38CB3540 = (int)szAgent;
    dword_38CB3544 = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB354C,
      &v3);
(*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3560 = (unsigned int)&unk_389BAE80 | 1;
    LOBYTE(v3) = 0;
    dword_38CB3550 = (int)"Fire6";
    dword_38CB3554 = 0;
    dword_38CB3558 = (int)szAgent;
    dword_38CB355C = 0;
(*(void (__cdecl **)(_UNKNOWN *, _DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 0xC))(
      &unk_38CB3564,
      &v3);
    (*(void (__cdecl **)(_DWORD))((((unsigned int)&unk_389BAE80 | 1) & 0xFFFFFFFC) + 4))(&v3);
    dword_38CB3568 = 0;
    dword_38CB356C = 0;
    dword_38CB3570 = 0;
    dword_38CB3574 = 0;
    dword_38CB357C = 0;
    dword_38CB3578 = (int)&unk_389BAEA0;
    atexit(sub_386F1FC0);
  }
  if ( !(dword_38CB3580 & 2) )
  {
    dword_38CB3580 |= 2u;
    dword_38CB33D4 = 0;
    dword_38CB33D8 = 0;
    dword_38CB33DC = 0;
    dword_38CB33E0 = 0;
  }
  result = a1;
  v2 = *(_DWORD *)(a1 + 8);
  *(_DWORD *)(a1 + 12) = szAgent;
  *(_DWORD *)a1 = &dword_38CB33E8;
  *(_DWORD *)(a1 + 4) = &dword_38CB33D4;
  *(_DWORD *)(a1 + 8) = v2 & 0xFFFFF01F | 0x11;
  return result;
}

I'm sorry, I know it's very messy, but the function is pretty big.

Anybody could tell me how to call let's say Fire1 from my DLL? I really have no idea how to do it at this point. I know I'm totally over my head, but I'd like to learn!

Thx to anyone willing to lend a hand! Cheers

  • That function is an object constructor. It doesn't "control the power on/off of the mech, jumpjets, turning, throttle, weapons firing etc.", nor will calling it "fire the weapons". – Jason Geffner Feb 22 '16 at 17:54
  • Hey thx for the quick reply. So could I use this to find the function which triggers firing ? Or it's pretty useless. Thx again. – TheTurp Feb 22 '16 at 18:29
  • 1
    You can call a function like this. The answer is for __usercalls, but it's very easily adaptable to __stdcalls. – rev Feb 23 '16 at 23:05
1

This function initializes an global object, if it's not already initialized, and returns it to the caller.

It seems that object has an array of a structure, and that structure describes what you consider actions the player can take. It looks like part of the initialization is setting a callable function to each structure instance.

Here are the few things i think you can do next:

  1. Understand those functions initialized with each action structure. I would recommend you set a breakpoint on each of those functions and see that it's actually triggered once the player performs that action, to validate that function is indeed involved in the action.

  2. Find all references to the object's range of addresses and understand the usage of that object.

  3. Ditch those strings (as they're usually not easily related to the actions themselves in games) and instead follow key presses, like explained in this answer.

This question could also be useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.