c++ inline asm jnz & jz not working

11/07/2016 16:19 znoeen#1
Hello, i have a very strange bug in visual studio.

PHP Code:
DWORD dwNoReload;
DWORD dwNoReloadJump;
DWORD dwNoReloadOffset;
DWORD dwNoReloadOG;

 
__declspec(naked) void __stdcall ASM_NoReloadFunction()
{
    
/*_:00518EB9                 test    byte ptr [edi+1047Ch], 10h
    ___:00518EC0                 jz      loc_519040
    ___:00518EC6                 mov     esi, [ebp+arg_4]*/

    
__asm
    
{
        
cmp byte ptr[NoReload], 0x00;                    //Compairs int noreload with 0
        
je disabled;                                    //If equal (so disabled) jump to disabled
        
jmp[dwNoReloadJump];                            //Jump over original code

    
disabled:
        
test byte ptr[edi + dwNoReloadOffset], 0x10;    //original instruction
        
jz dwNoReloadOG;                                //original instruction (line 47)
        
jmp[dwNoReloadJump];                            //Jump back to original code
    
}
} 
PHP Code:
Error    C2415    improper operand type    Weaponbinder    c:\Functions.h    47 
I tried with mulitple compiler settings. Also with /arch (msdn recommands this with this error). But still no result in a working code. Does anyone know why i can't use jz or jnz in c++?
11/07/2016 18:48 florian0#2
Not really a bug, more a beginners error :)

All conditional jump instructions are relative to their location.

Code:
0x000000 33 C0    xor eax, eax
0x000002 85 C0    test eax, eax
0x000004 74 FE    jz 0x4
This code will loop forever. It will always jump 0xFE bytes far, which is -2 bytes in decimal. So the jz will always land on the jz instruction.

Lets come back to your code: You're instructing the compiler to calculate a JMP instruction from a variable. On pure semantic, this is a valid idea since all assemblers accept JX <absolute address> or <label> rather than <relative offset>. But this only works, if you know where in the code your JMP instruction will be placed AND where the JMPs target instruction will be placed. You'll need the relative offsets aka. the distance between these two locations.

Having the target location in a variable is simply not assembleable.
12/08/2016 01:29 bloodx#3
this works also.

DWORD dwNoReloadJump = 0x123456;
PHP Code:
jmp dwNoReloadJump; 
12/08/2016 03:19 warfley#4
I don't know if this fixes your problem, but you should never use DWORD type for pointer. On x64 architecture pointer have a size of 64 bit, DWORD holds only 32 bit. You could use the uintptr_t type, it's an unsigned integer of exactly the size of a pointer regardless of architecture.
12/08/2016 06:38 Dr. Coxxy#5
you cant use inline asm @ 64bit with msvc anyway ;)
12/08/2016 23:34 _asm#6
why use inline assembler in the first place when you have the functionality to use C++ aka function pointers...?
12/09/2016 10:15 florian0#7
Quote:
Originally Posted by _asm View Post
why use inline assembler in the first place when you have the functionality to use C++ aka function pointers...?
How would you solve that code snipped above with plain c++? (Really interested, not trolling).
12/09/2016 16:53 _asm#8
Quote:
Originally Posted by florian0 View Post
How would you solve that code snipped above with plain c++? (Really interested, not trolling).
From what I can tell by looking at the code, the function he is trying to hook doesn't require any function arguments. So instead of rebuilding the code section in inline assembler before it's hooked and modified, he could simply use a function pointer pointing to the function before it's hooked and return it in a custom callback with his desired modified variables or function calls (obviously with the same arguments)
e.g. Microsoft Detours, PolyHook, MologieDetours...

I have no idea how the function template might look like or what calling convention is used, but taking a look with IDA or similiar disassemblers should give you the answer.