I need to hook a __usercall function in particular I need to read only the first parameter:

char __usercall sub_4F3E6D@<al>(char *Src@<ecx>, int a2@<edx>, int a3, int a4, char a5, char a6, char a7, char a8, int a9)
  int v9; // edi
  char v10; // bl
  char *v11; // esi
  unsigned __int8 v12; // al
  signed int v13; // edx
  int v14; // eax
  signed int v15; // eax
  signed int v16; // edi
  char *v17; // eax
  char *v18; // esi
  float v20; // xmm1_4
  size_t v21; // ST04_4
  float v22; // [esp+18h] [ebp-A8h]
  int v23; // [esp+1Ch] [ebp-A4h]
  char v24; // [esp+24h] [ebp-9Ch]
  int v25; // [esp+2Ch] [ebp-94h]
  char Dst; // [esp+40h] [ebp-80h]
  int v27; // [esp+98h] [ebp-28h]
  int v28; // [esp+9Ch] [ebp-24h]
  float v29; // [esp+ACh] [ebp-14h]
  float v30; // [esp+B0h] [ebp-10h]

  v9 = a2;
  v10 = 0;
  v11 = Src;
  v23 = a2;
  if ( a9 )
    *(_DWORD *)a9 = 0;
  if ( !dword_897628 || !Src || !*Src )
    return 0;
  if ( a6 )
    v12 = *((_BYTE *)dword_8CF880 + 2232);
  else if ( a7 )
    v12 = *((_BYTE *)dword_8CF880 + 2234);
    v12 = a8 ? *((_BYTE *)dword_8CF880 + 2233) : *((_BYTE *)dword_8CF880 + 2252);
  v22 = (float)v12 * 0.0099999998;
  if ( v22 < 0.0099999998 && a2 != 1481317962 )
    return 0;
  if ( sub_4F4463(a2, 0) )
    return 0;
  memset(&Dst, 0, 0x78u);
  sub_410BA2(&Dst, 3);
  if ( a6 )
    v28 = 9;
  else if ( a7 )
    v27 |= 4u;
  else if ( !a8 )
    v27 |= 0x40000u;
  v13 = 1;
  if ( a5 || a6 )
    v14 = v27 | 1;
    v27 |= 1u;
    if ( a6 )
      v27 = v14 | 8;
  if ( *(float *)&a3 > 0.0099999998 )
    sub_4F0812(&Dst, 1);
  sub_4F0855(&Dst, v13);
  v27 |= 0x40u;
  *(_DWORD *)a4 = 0;
  v30 = fminf(fmaxf(v22, 0.0), 1.0);
  v29 = v30;
  v15 = v25;
  if ( a5 )
    v15 = 1;
  v25 = v15;
  v16 = v9 == 1481317962 ? 2147483646 : sub_4F353D(&v24, 0);
  if ( !(unsigned __int8)sub_4F349C(v16) )
    return 0;
  v17 = sub_4F1BBB(v11, v23, 0, (int)&Dst);
  v18 = v17;
  if ( !v17 )
    return 0;
  if ( dword_897628 )
    v10 = sub_4F11D7(v17, &v24);
  if ( !v10 )
    return 0;
  if ( v18[34] )
    v20 = 9999.0;
    v20 = (float)*(signed int *)(*((_DWORD *)v18 + 3) + 172) / (float)*(unsigned int *)(*((_DWORD *)v18 + 3) + 156);
  *(float *)a4 = v20;
  v21 = dword_897634;
  *((_DWORD *)v18 + 5) = v16;
  qsort(dword_897650, v21, 4u, sub_4F37D5);
  if ( a9 )
    *(_DWORD *)a9 = *(_DWORD *)v18;
  return 1;

here the assemply:

.text:004F3E6D ; =============== S U B R O U T I N E =======================================
.text:004F3E6D ; Attributes: bp-based frame
.text:004F3E6D ; int __usercall sub_4F3E6D@<eax>(char *Src@<ecx>, int, int, char, char, char, char, int)
.text:004F3E6D sub_4F3E6D      proc near               ; CODE XREF: StartAudio2D(char const * const,float,float,float,bool,bool)+3B↑p
.text:004F3E6D                                         ; sub_4EDCE9+14E↑p ...
.text:004F3E6D var_B0          = dword ptr -0B0h
.text:004F3E6D var_AC          = dword ptr -0ACh
.text:004F3E6D var_A8          = dword ptr -0A8h
.text:004F3E6D var_A4          = dword ptr -0A4h
.text:004F3E6D var_A0          = dword ptr -0A0h
.text:004F3E6D var_9C          = byte ptr -9Ch
.text:004F3E6D var_94          = dword ptr -94h
.text:004F3E6D Dst             = byte ptr -80h
.text:004F3E6D var_28          = dword ptr -28h
.text:004F3E6D var_24          = dword ptr -24h
.text:004F3E6D var_14          = dword ptr -14h
.text:004F3E6D var_10          = dword ptr -10h
.text:004F3E6D var_4           = dword ptr -4
.text:004F3E6D arg_0           = dword ptr  8
.text:004F3E6D arg_4           = dword ptr  0Ch
.text:004F3E6D arg_8           = byte ptr  10h
.text:004F3E6D arg_C           = byte ptr  14h
.text:004F3E6D arg_10          = byte ptr  18h
.text:004F3E6D arg_14          = byte ptr  1Ch
.text:004F3E6D arg_18          = dword ptr  20h
.text:004F3E6D                 push    ebp
.text:004F3E6E                 mov     ebp, esp
.text:004F3E70                 and     esp, 0FFFFFFF8h
.text:004F3E73                 sub     esp, 0B4h
.text:004F3E79                 mov     eax, ___security_cookie
.text:004F3E7E                 xor     eax, esp
.text:004F3E80                 mov     [esp+0B4h+var_4], eax
.text:004F3E87                 mov     eax, [ebp+arg_4]
.text:004F3E8A                 push    ebx
.text:004F3E8B                 push    esi
.text:004F3E8C                 push    edi
.text:004F3E8D                 mov     [esp+0C0h+var_B0], eax
.text:004F3E91                 mov     edi, edx
.text:004F3E93                 mov     eax, [ebp+arg_18]
.text:004F3E96                 xor     ebx, ebx
.text:004F3E98                 movss   [esp+0C0h+var_AC], xmm3
.text:004F3E9E                 mov     esi, ecx
.text:004F3EA0                 mov     [esp+0C0h+var_A4], edi
.text:004F3EA4                 mov     [esp+0C0h+var_A0], eax
.text:004F3EA8                 test    eax, eax
.text:004F3EAA                 jz      short loc_4F3EAE
.text:004F3EAC                 mov     [eax], ebx
.text:004F3EAE loc_4F3EAE:                             ; CODE XREF: sub_4F3E6D+3D↑j
.text:004F3EAE                 cmp     dword_897628, ebx
.text:004F3EB4                 jz      loc_4F4093
.text:004F3EBA                 test    esi, esi
.text:004F3EBC                 jz      loc_4F4093
.text:004F3EC2                 cmp     [esi], bl
.text:004F3EC4                 jz      loc_4F4093
.text:004F3ECA                 mov     eax, dword_8CF880
.text:004F3ECF                 cmp     [ebp+arg_C], bl
.text:004F3ED2                 jz      short loc_4F3EDC
.text:004F3ED4                 mov     al, [eax+8B8h]
.text:004F3EDA                 jmp     short loc_4F3EFC
.text:004F3EDC ; ---------------------------------------------------------------------------
.text:004F3EDC loc_4F3EDC:                             ; CODE XREF: sub_4F3E6D+65↑j
.text:004F3EDC                 cmp     [ebp+arg_10], bl
.text:004F3EDF                 jz      short loc_4F3EE9
.text:004F3EE1                 mov     al, [eax+8BAh]
.text:004F3EE7                 jmp     short loc_4F3EFC
.text:004F3EE9 ; ---------------------------------------------------------------------------
.text:004F3EE9 loc_4F3EE9:                             ; CODE XREF: sub_4F3E6D+72↑j
.text:004F3EE9                 cmp     [ebp+arg_14], bl
.text:004F3EEC                 jz      short loc_4F3EF6
.text:004F3EEE                 mov     al, [eax+8B9h]
.text:004F3EF4                 jmp     short loc_4F3EFC
.text:004F3EF6 ; ---------------------------------------------------------------------------
.text:004F3EF6 loc_4F3EF6:                             ; CODE XREF: sub_4F3E6D+7F↑j
.text:004F3EF6                 mov     al, [eax+8CCh]
.text:004F3EFC loc_4F3EFC:                             ; CODE XREF: sub_4F3E6D+6D↑j
.text:004F3EFC                                         ; sub_4F3E6D+7A↑j ...
.text:004F3EFC                 movss   xmm1, ds:dword_82A2D8
.text:004F3F04                 movzx   eax, al
.text:004F3F07                 movd    xmm0, eax
.text:004F3F0B                 cvtdq2ps xmm0, xmm0
.text:004F3F0E                 mulss   xmm0, xmm1
.text:004F3F12                 comiss  xmm1, xmm0
.text:004F3F15                 movss   [esp+0C0h+var_A8], xmm0
.text:004F3F1B                 jbe     short loc_4F3F29
.text:004F3F1D                 cmp     edi, 584B1E4Ah
.text:004F3F23                 jnz     loc_4F4093
.text:004F3F29 loc_4F3F29:                             ; CODE XREF: sub_4F3E6D+AE↑j
.text:004F3F29                 xor     edx, edx
.text:004F3F2B                 mov     ecx, edi
.text:004F3F2D                 call    sub_4F4463
.text:004F3F32                 test    eax, eax
.text:004F3F34                 jnz     loc_4F4093
.text:004F3F3A                 push    78h             ; Size
.text:004F3F3C                 lea     eax, [esp+0C4h+Dst]
.text:004F3F40                 push    ebx             ; Val
.text:004F3F41                 push    eax             ; Dst
.text:004F3F42                 call    memset
.text:004F3F47                 add     esp, 0Ch
.text:004F3F4A                 lea     ecx, [esp+0C0h+Dst] ; Dst
.text:004F3F4E                 push    3               ; int
.text:004F3F50                 call    sub_410BA2
.text:004F3F55                 mov     cl, [ebp+arg_C]
.text:004F3F58                 test    cl, cl
.text:004F3F5A                 jz      short loc_4F3F69
.text:004F3F5C                 mov     [esp+0C0h+var_24], 9
.text:004F3F67                 jmp     short loc_4F3F88
.text:004F3F69 ; ---------------------------------------------------------------------------
.text:004F3F69 loc_4F3F69:                             ; CODE XREF: sub_4F3E6D+ED↑j
.text:004F3F69                 cmp     [ebp+arg_10], bl
.text:004F3F6C                 jz      short loc_4F3F78
.text:004F3F6E                 or      [esp+0C0h+var_28], 4
.text:004F3F76                 jmp     short loc_4F3F88
.text:004F3F78 ; ---------------------------------------------------------------------------
.text:004F3F78 loc_4F3F78:                             ; CODE XREF: sub_4F3E6D+FF↑j
.text:004F3F78                 cmp     [ebp+arg_14], bl
.text:004F3F7B                 jnz     short loc_4F3F88
.text:004F3F7D                 or      [esp+0C0h+var_28], 40000h
.text:004F3F88 loc_4F3F88:                             ; CODE XREF: sub_4F3E6D+FA↑j
.text:004F3F88                                         ; sub_4F3E6D+109↑j ...
.text:004F3F88                 xor     edx, edx
.text:004F3F8A                 inc     edx
.text:004F3F8B                 cmp     [ebp+arg_8], bl
.text:004F3F8E                 jnz     short loc_4F3F94
.text:004F3F90                 test    cl, cl
.text:004F3F92                 jz      short loc_4F3FB2
.text:004F3F94 loc_4F3F94:                             ; CODE XREF: sub_4F3E6D+121↑j
.text:004F3F94                 mov     eax, [esp+0C0h+var_28]
.text:004F3F9B                 or      eax, edx
.text:004F3F9D                 mov     [esp+0C0h+var_28], eax
.text:004F3FA4                 test    cl, cl
.text:004F3FA6                 jz      short loc_4F3FB2
.text:004F3FA8                 or      eax, 8
.text:004F3FAB                 mov     [esp+0C0h+var_28], eax
.text:004F3FB2 loc_4F3FB2:                             ; CODE XREF: sub_4F3E6D+125↑j
.text:004F3FB2                                         ; sub_4F3E6D+139↑j
.text:004F3FB2                 movss   xmm1, [ebp+arg_0]
.text:004F3FB7                 comiss  xmm1, ds:dword_82A2D8
.text:004F3FBE                 jbe     short loc_4F3FC9
.text:004F3FC0                 lea     ecx, [esp+0C0h+Dst]
.text:004F3FC4                 call    sub_4F0812
.text:004F3FC9 loc_4F3FC9:                             ; CODE XREF: sub_4F3E6D+151↑j
.text:004F3FC9                 movss   xmm1, [esp+0C0h+var_AC]
.text:004F3FCF                 lea     ecx, [esp+0C0h+Dst]
.text:004F3FD3                 call    sub_4F0855
.text:004F3FD8                 movss   xmm0, [esp+0C0h+var_A8]
.text:004F3FDE                 lea     ecx, [esp+0C0h+var_9C]
.text:004F3FE2                 maxss   xmm0, ds:dword_82A218
.text:004F3FEA                 mov     eax, [esp+0C0h+var_B0]
.text:004F3FEE                 or      [esp+0C0h+var_28], 40h
.text:004F3FF6                 minss   xmm0, ds:dword_82A46C
.text:004F3FFE                 and     [eax], ebx
.text:004F4000                 movss   [esp+0C0h+var_10], xmm0
.text:004F4009                 movss   [esp+0C0h+var_14], xmm0
.text:004F4012                 call    sub_410B78
.text:004F4017                 cmp     [ebp+arg_8], bl
.text:004F401A                 mov     eax, [esp+0C0h+var_94]
.text:004F401E                 push    1
.text:004F4020                 pop     ecx
.text:004F4021                 cmovnz  eax, ecx
.text:004F4024                 mov     [esp+0C0h+var_94], eax
.text:004F4028                 cmp     edi, 584B1E4Ah
.text:004F402E                 jnz     short loc_4F4037
.text:004F4030                 mov     edi, 7FFFFFFEh
.text:004F4035                 jmp     short loc_4F404F
.text:004F4037 ; ---------------------------------------------------------------------------
.text:004F4037 loc_4F4037:                             ; CODE XREF: sub_4F3E6D+1C1↑j
.text:004F4037                 lea     eax, [esp+0C0h+var_9C]
.text:004F403B                 mov     ecx, offset unk_59D561C
.text:004F4040                 push    ebx
.text:004F4041                 push    eax
.text:004F4042                 lea     edx, [esp+0C8h+Dst]
.text:004F4046                 call    sub_4F353D
.text:004F404B                 pop     ecx
.text:004F404C                 pop     ecx
.text:004F404D                 mov     edi, eax
.text:004F404F loc_4F404F:                             ; CODE XREF: sub_4F3E6D+1C8↑j
.text:004F404F                 mov     ecx, edi
.text:004F4051                 call    sub_4F349C
.text:004F4056                 test    al, al
.text:004F4058                 jz      short loc_4F4093
.text:004F405A                 mov     edx, [esp+0C0h+var_A4]
.text:004F405E                 lea     eax, [esp+0C0h+Dst]
.text:004F4062                 push    eax             ; int
.text:004F4063                 push    ebx             ; int
.text:004F4064                 mov     ecx, esi        ; Src
.text:004F4066                 call    sub_4F1BBB
.text:004F406B                 mov     esi, eax
.text:004F406D                 pop     ecx
.text:004F406E                 pop     ecx
.text:004F406F                 test    esi, esi
.text:004F4071                 jz      short loc_4F4093
.text:004F4073                 cmp     dword_897628, ebx
.text:004F4079                 jz      short loc_4F4088
.text:004F407B                 lea     edx, [esp+0C0h+var_9C]
.text:004F407F                 mov     ecx, esi
.text:004F4081                 call    sub_4F11D7
.text:004F4086                 mov     bl, al
.text:004F4088 loc_4F4088:                             ; CODE XREF: sub_4F3E6D+20C↑j
.text:004F4088                 test    bl, bl
.text:004F408A                 jnz     short loc_4F40AA
.text:004F408C                 mov     ecx, esi
.text:004F408E                 call    sub_4F3A95
.text:004F4093 loc_4F4093:                             ; CODE XREF: sub_4F3E6D+47↑j
.text:004F4093                                         ; sub_4F3E6D+4F↑j ...
.text:004F4093                 xor     al, al
.text:004F4095 loc_4F4095:                             ; CODE XREF: sub_4F3E6D+2B2↓j
.text:004F4095                 mov     ecx, [esp+0C0h+var_4]
.text:004F409C                 pop     edi
.text:004F409D                 pop     esi
.text:004F409E                 pop     ebx
.text:004F409F                 xor     ecx, esp
.text:004F40A1                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:004F40A6                 mov     esp, ebp
.text:004F40A8                 pop     ebp
.text:004F40A9                 retn
.text:004F40AA ; ---------------------------------------------------------------------------
.text:004F40AA loc_4F40AA:                             ; CODE XREF: sub_4F3E6D+21D↑j
.text:004F40AA                 cmp     byte ptr [esi+22h], 0
.text:004F40AE                 jnz     short loc_4F40E2
.text:004F40B0                 mov     eax, [esi+0Ch]
.text:004F40B3                 movd    xmm1, dword ptr [eax+0ACh]
.text:004F40BB                 mov     eax, [eax+9Ch]
.text:004F40C1                 cvtdq2ps xmm1, xmm1
.text:004F40C4                 movd    xmm0, eax
.text:004F40C8                 cvtdq2pd xmm0, xmm0
.text:004F40CC                 shr     eax, 1Fh
.text:004F40CF                 addsd   xmm0, ds:qword_82C2D0[eax*8]
.text:004F40D8                 cvtpd2ps xmm0, xmm0
.text:004F40DC                 divss   xmm1, xmm0
.text:004F40E0                 jmp     short loc_4F40EA
.text:004F40E2 ; ---------------------------------------------------------------------------
.text:004F40E2 loc_4F40E2:                             ; CODE XREF: sub_4F3E6D+241↑j
.text:004F40E2                 movss   xmm1, ds:dword_82A910
.text:004F40EA loc_4F40EA:                             ; CODE XREF: sub_4F3E6D+273↑j
.text:004F40EA                 mov     eax, [esp+0C0h+var_B0]
.text:004F40EE                 push    offset sub_4F37D5 ; PtFuncCompare
.text:004F40F3                 push    4               ; SizeOfElements
.text:004F40F5                 movss   dword ptr [eax], xmm1
.text:004F40F9                 push    dword_897634    ; NumOfElements
.text:004F40FF                 mov     [esi+14h], edi
.text:004F4102                 push    offset dword_897650 ; Base
.text:004F4107                 call    ds:qsort
.text:004F410D                 mov     edx, [esp+0D0h+var_A0]
.text:004F4111                 add     esp, 10h
.text:004F4114                 test    edx, edx
.text:004F4116                 jz      short loc_4F411C
.text:004F4118                 mov     ecx, [esi]
.text:004F411A                 mov     [edx], ecx
.text:004F411C loc_4F411C:                             ; CODE XREF: sub_4F3E6D+2A9↑j
.text:004F411C                 xor     eax, eax
.text:004F411E                 inc     eax
.text:004F411F                 jmp     loc_4F4095
.text:004F411F sub_4F3E6D      endp

here there is one xref of this function:

int v6; // eax
  int v8; // [esp+1Ch] [ebp-8h]
  int v9; // [esp+20h] [ebp-4h]

  v9 = 0;
  v6 = sub_73A34B(a1, 0);
  sub_4F3E6D((char *)a1, v6, SLODWORD(a4), (int)&v9, a5, a6, 0, 0, (int)&v8);

I don't have experience in assembly I have tried with this code:

// char __usercall sub_4F3E6D@<al>(char *Src@<ecx>, int a2@<edx>, int a3, int a4, char a5, char a6, char a7, char a8, int a9)
    typedef char(__fastcall *HookFile) (char* src, int a2, int a3, int a4, char a5, char a6, char a7, char a8, int a9);
    __declspec(naked) char HookSoundFileSub(char* src, int a2, int a3, int a4, char a5, char a6, char a7, char a8, int a9)
        HookFile originalFunction = (HookFile)AddressOfHookSoundFunction; // 0x4F4463
        __asm {
            mov ecx, src
            mov edx, a2
            call AddressOfHookSoundFunction
        // Apply  my code
        // std::string FileName;
        // FileName = SC::To_String(src);
        // .....
        return originalFunction(src, a2,a3,a4,a5,a6,a7,a8,a9);

   // DetourAttach(&(LPVOID&)AddressOfHookSoundFunction, &HookSoundFileSub);

but not compile becouse naked function seem not allow to add code apart the assembly.

Can you help me please ?

  • thank you, the compiler don't accept __cdecl or __stdcall in naked function. I have removed it and crash. Becouse this is a DLL the debug is not easy however I can see that crash inside "CallOriginalFunction" (I don't known the exact point). Any suggests ? Nov 17, 2020 at 13:44
  • apart the crash I confirm that the char pointer "src" inside this function return the file name as I expected. I hope is possible find a solution. Nov 17, 2020 at 13:56

1 Answer 1


As your question indicates, you need to move all of the non-assembly code out of the naked function. Although I've never actually used Detours before -- I wrote my own hooking library -- what I would do would be to write a little stub that allowed me to call the __usercall function with an ordinary calling convention.

Be careful with the calling conventions. It will be easy to mess up the stack corrections, causing a crash. Debugging stuff like this is part of the job when you get into binary hooking. If you experience crashes, set a breakpoint at the beginning and end of all assembly sequences, and write down the value of esp at each of those points.

Something like this:

// Here's your hook, the ASM part. It just redirects execution to the _C function below
// Note I removed the first two arguments, the ones in registers
__declspec(naked) __cdecl char HookSoundFileSub_ASM(int a3, int a4, char a5, char a6, char a7, char a8, int a9)
    __asm {
        push a9
        push a8
        push a7
        push a6
        push a5
        push a4
        push a3
        push edx // a2 in edx
        push ecx // src in ecx
        call HookSoundFileStub_C
        ret // Don't need to correct the stack here

// Here's your hook, the C part. Do whatever you want in here
char __stdcall HookSoundFileStub_C(char* src, int a2, int a3, int a4, char a5, char a6, char a7, char a8, int a9)
    // Your original hook code
    // Apply  my code
    // std::string FileName;
    // FileName = SC::To_String(src);
    // Call the original function
    return CallOriginalFunction(src, a2, a3, a4, a5, a6, a7, a8, a9);

// We moved this outside of the naked function
DWORD AddressOfHookSoundFunction = 0x4F4463;

// This just allows us to call the original function from C code
__declspec(naked) __stdcall char CallOriginalFunction(char* src, int a2, int a3, int a4, char a5, char a6, char a7, char a8, int a9)
    __asm {
        mov ecx, src
        mov edx, a2
        push a9
        push a8
        push a7
        push a6
        push a5
        push a4
        push a3
        mov eax, AddressOfHookSoundFunction
        call eax
        add esp, 1ch // Target doesn't clear the stack, so do that
        retn 24h // Also clear the arguments passed to this function

// DetourAttach(&(LPVOID&)AddressOfHookSoundFunction, &HookSoundFileSub_ASM);

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.