I am trying to call a function generated by Hex-Rays by injecting a DLL, but have so far only managed to crash the process.

This is the code generated by Hex-Rays

int __usercall sub_54C3A0@<eax>(int a1@<esi>, void *a2@<ecx>)
  char *v2; // eax@1
  char *v3; // edx@1
  char v4; // cl@2
  int result; // eax@4
  char v6[84]; // [sp+0h] [bp-58h]@1

  dword_81D7CC = 1;
  v2 = (char *)sub_431620(55);
  v3 = (char *)(v6 - v2);
    v4 = *v2;
    v2[(_DWORD)v3] = *v2;
  while ( v4 );
  sub_4330E0(*(_DWORD *)v6);
  dword_81D7CC = 0;
  result = 0;
  if ( v6[0] )
    dword_81DAE0 = 0;
    if ( sub_54C480(100, a1) || dword_81DAE0 || sub_54C480(75, a1) || dword_81DAE0 || sub_54C480(50, a1) )
      result = 1;
  return result;

And this is my code

static DWORD hook_address = 0x54C3A0;
__declspec(naked) int hook()
    __asm {
        push esi // a1
        push ecx // a2
        call hook_address
        retn 4

What would the correct wrapper look like, and why?

  • It should be mov esi, a1 , mov ecx, a2. Note that usercall is not actually any calling convention. It is a way of representing unknown/custom calling conventions. See this answer.
    – 0xec
    Commented Oct 11, 2015 at 16:11
  • I tried that, still get access violation. Commented Oct 11, 2015 at 17:41
  • Do it like this: mov esi, a1, mov ecx, a2, call hook_address, ret. Using retn 4 clears 4 bytes from the stack, but usercalls don't need it because their arguments are in registers, not in the stack.
    – rev
    Commented Oct 11, 2015 at 21:11
  • That worked. Also, the address was wrong all the time. After running the program from IDA the addresses updated. No wonder I got access violations all over the place. Commented Oct 12, 2015 at 11:00
  • 1
    @AcidShout can you write your comment as an answer so that this question can be marked answered, and also help others in future?
    – tmr232
    Commented Oct 13, 2015 at 5:56

1 Answer 1


Your hook is wrong because retn 4 is for __stdcalls, not __usercalls, and because you must move arguments to registers, not push them. Do it like this:

mov esi, a1
mov ecx, a2
call hook_address

retn 4 would clean 4 bytes from the stack, but you didn't push anything, so it's not correct, which is why you use ret instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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