Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > C/C++
You last visited: Today at 13:46

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



x64 ASM mit C++ problem

Discussion on x64 ASM mit C++ problem within the C/C++ forum part of the Coders Den category.

Reply
 
Old   #1
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
x64 ASM mit C++ problem

Hallo.

Wie ihr sicherlich wissts lässt VisualStudio kein inline ASM zu wenn man x64-Bit Applikationen erstellt.

Ich habe dann ein bisschen rumgegoogelt und gefunden wie man in VS ASM mit x64 Code verbinden kann.
Soweit so gut, aber ich bekomme einen error und ich weiß nicht wieso

Die Errors sind als comment zu meinem Code aufgeschrieben:
Code:
.code
noReload proc
	mov [rax+98],1e ; Fehler	1	error A2048: nondigit in number
	mov eax,[rax+98]
	jmp 7FF95517C177 ; Fehler	2	error A2206: missing operator in expression
noReload endp
end
Ich hoffe um Hilfe den wenn ich ähnlichen Code in x86 inline ASM schreibe, bekomme ich solche Errors nicht..

Danke in vorraus!
XxharCs is offline  
Old 10/12/2014, 20:40   #2




 
Omdi's Avatar
 
elite*gold: 1
Join Date: Apr 2010
Posts: 13,772
Received Thanks: 15,036
0x vor bzw. 'h' hinter jede Nummer.

Btw.
Code:
jmp 7FF95517C177
Geht sowas überhaupt ôo?
Omdi is offline  
Old 10/12/2014, 20:51   #3
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
Ich habe etwas länger rumgegoogelt und rausgefunden das MASM64 irgendwie Base-10 nutzt statt Base-16.
Also sieht mein neuer Code so aus: (Trotzdem Compiler Error beim jmp, siehe unten wieso)
Code:
.code
noReload proc
	mov [rax+152], DWORD PTR 30
	mov eax, [rax+152]
        jmp 7FF95517C177h
noReload endp
end
Was ich ebenfalls durchlesen konnte ist das man keine direkten jmps machen kann wie im obrigen Beispiel.
Also versuche ich es mit Umwegen die aber das Programm/Spiel crashen.
Code:
.code
noReload proc
	mov [rax+152], DWORD PTR 30
	mov eax, [rax+152]
	mov rax, 7FF95517C177h
	jmp rax
noReload endp
end
Villt ist ja auch nur mein writeJmp Falsch
Code:
#define BYTECODE_JMP 0xE9
#define BYTECODE_NOP 0x90

void WDFuncs::writeJMP(BYTE* src, BYTE* dst, const int len)
{
	DWORD64 dwRelAddr;
	DWORD dwOldProtect;

	VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	dwRelAddr = (DWORD64)(dst - src) - 5;

	src[0] = BYTECODE_JMP;

	*((DWORD64*)(src + 0x1)) = dwRelAddr;

	for(DWORD64 c = 0x5; c < len; c++)
		*(src + c) = BYTECODE_NOP;

	VirtualProtect(src, len, dwOldProtect, &dwOldProtect);
}

void WDFuncs::EnableNoReload(bool enable)
{
	DWORD dwOldProtect;
	BYTE origBytes[] = {0x8B, 0x80, 0x98, 0x00, 0x00, 0x00};
	//BYTE hackBytes[] = {0xC7, 0x80, 0x98, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x8B, 0x80, 0x98, 0x00, 0x00, 0x00, 0xE9, 0x62, 0xC1, 0x56, 0x00};

	if(enable == true)
	{
		WDFuncs::writeJMP((BYTE*)0x7FF95517C171, (BYTE*)noReload, 6);
	}else
	{
		VirtualProtect((LPVOID)0x7FF95517C171, sizeof(origBytes), PAGE_EXECUTE_READWRITE, &dwOldProtect);
		RtlMoveMemory((LPVOID)0x7FF95517C171, origBytes, sizeof(origBytes));
		VirtualProtect((LPVOID)0x7FF95517C171, sizeof(origBytes), dwOldProtect, &dwOldProtect ); 
	}
}
Im header die noReload definition:
Code:
extern "C" void noReload();
Es ist zu beachten das mein Target eine x64 Anwendung ist.
XxharCs is offline  
Old 10/12/2014, 21:29   #4
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
falsch, falsch, falsch, guck dir bitte erstmal nen bissle den assembler code an, lern wie ein detour funktioniert und dann mach das ganze mal im debugger per hand, oder guck dir an wie der cheatengine autoassembler und dessen templates funktionieren.
Dr. Coxxy is offline  
Thanks
1 User
Old 10/12/2014, 21:41   #5
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
Im debugger per Hand funktioniert es. Bzw. ich besitze einen autoassembler template in CE, also hab ich eine Vorlage, aber dieses übersetzen klappt irgendwie nicht.

Ich bin nicht auf ein Detour richtig eingegangen, da ich ja eine Codecave erstellen möchte, und ich deshalb nur einen JMP zur Funktion mache und die Funktion dann springt dann wieder zurück.

Meinen alten Detour Code habe ich noch nicht ausprobiert:
Code:
void *DetourFunction (BYTE *src, const BYTE *dst, const int len)
{
    BYTE *jmp;
    DWORD dwback;
    DWORD jumpto, newjump;

    VirtualProtect(src,len,PAGE_READWRITE,&dwback);
    
    if(src[0] == 0xE9)
    {
        jmp = (BYTE*)malloc(10);
        jumpto = (*(DWORD*)(src+1))+((DWORD)src)+5;
        newjump = (jumpto-(DWORD)(jmp+5));
        jmp[0] = 0xE9;
       *(DWORD*)(jmp+1) = newjump;
        jmp += 5;
        jmp[0] = 0xE9;
       *(DWORD*)(jmp+1) = (DWORD)(src-jmp);
    }
    else
    {
        jmp = (BYTE*)malloc(5+len);
        memcpy(jmp,src,len);
        jmp += len;
        jmp[0] = 0xE9;
       *(DWORD*)(jmp+1) = (DWORD)(src+len-jmp)-5;
    }
    src[0] = 0xE9;
   *(DWORD*)(src+1) = (DWORD)(dst - src) - 5;

    for(int i = 5; i < len; i++)
        src[i] = 0x90;
    VirtualProtect(src,len,dwback,&dwback);
    return (jmp-len);
}
Edit: Mit meiner alten DetourFunktion funktioniert es teilweise, irgendwie hat er die Munition in die Hälfte geschnitten :/
Edit2: Was mich brainfuckt ist, wieso ich normales DWORD verwenden kann und nicht DWORD64 da ja die Anwendung x64-Bit ist und deshalb eine x64-Bit Addressierung hat
XxharCs is offline  
Old 10/12/2014, 22:08   #6
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
du kannst nicht einfach von 32bit nach 64bit alles übernehmen, das klappt so nicht.
benutz mal das ce autoassembler codecave template und guck dir mit dem debugger genau an, was ce da gemacht hat.
Dr. Coxxy is offline  
Old 10/12/2014, 22:17   #7
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
Das was der autoassembe macht, will ich ja im ASM machen, nur da ich MASM verwenden muss im VS, kann ich keinen direkten Address jmp aufrufen.

autoassemble-script
Code:
[ENABLE]
//
alloc(_noReload,128,"game.dll")
//
label(_noReload_exit)
label(_noReload_aob_jmp)
//
registersymbol(_noReload_aob_jmp)
//
aobscanmodule(_noReload_aob,game.dll,E8 B4 C0 03 01 48 85 C0 74 0C 8B 80 98 00 00 00) //"game.dll"+55C167

_noReload:
mov [rax+98],1e //30
mov eax,[rax+98]
jmp _noReload_exit

_noReload_aob+a: //"game.dll"+55C171
_noReload_aob_jmp:
jmp _noReload
db 90
_noReload_exit:

[DISABLE]
dealloc(_noReload)
_noReload_aob_jmp:
db 8B 80 98 00 00 00
unregistersymbol(_noReload_aob_jmp)
Und ursprünglich sollte ja mein code so aussehen:
(Im Base-10 grad geschrieben)
Code:
.code
noReload proc
	mov [rax+152], DWORD PTR 30
	mov eax, [rax+152]
	jmp 7FF95517C177h
noReload endp
end
Nur leider geht kein direkter call. Und wenn ich
Code:
mov rax, 7FF95517C177h
jmp rax
Verwende klappt es ca., die Munition wird ja gecuttet usw.
XxharCs is offline  
Old 10/12/2014, 23:22   #8
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
ok, ich umreiße eben kurz, was du falsch machst:
1. writejump schreibt einen e9 jump - unter 64bit ist das nur ein short jump -> springt maximal 32bit weit, du brauchst aber (wenn du es sauber machst) einen far jump - immediate jumps sind unter x86 relativ, und @ 64bit gibts keinen 64bit jump immediate - musst also über nen register springen.
2. in deiner no reload "funktion" in assembler hast du zuerst versucht nen immediate absolute jump zu machen, was aus obengenannten 2 gründen nicht geht, das hast du dann korrigiert - allerdings dabei aber rax überschrieben, wo zu dem zeitpunkt allerdings anscheinend etwas sinnvolles drinsteht (zmdst benutzt dus 2 zeilen drüber) -> crash.

Lösung:
writejmp neu für 64bit schreiben.
in deinem assembler entweder ein register nehmen was nicht benutzt wird, oder die registerwerte wieder herstellen.
Dr. Coxxy is offline  
Thanks
1 User
Old 10/13/2014, 08:24   #9
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
Ich bedanke mich, das klärt widderum viel auf!

Quote:
Originally Posted by Dr. Coxxy View Post
ok, ich umreiße eben kurz, was du falsch machst:
1. writejump schreibt einen e9 jump - unter 64bit ist das nur ein short jump -> springt maximal 32bit weit, du brauchst aber (wenn du es sauber machst) einen far jump - immediate jumps sind unter x86 relativ, und @ 64bit gibts keinen 64bit jump immediate - musst also über nen register springen.
Das hatte ich gefunden, es hieß auch das ein JMP im 64-Bit den Bytecode 0xFF verwendet, aber laut den ganzen gesammelten Informationen kam es mir dann so rüber, als würde dieser Fall nicht immer auftreten müssen(?)

Quote:
Originally Posted by Dr. Coxxy View Post
2. in deiner no reload "funktion" in assembler hast du zuerst versucht nen immediate absolute jump zu machen, was aus obengenannten 2 gründen nicht geht, das hast du dann korrigiert - allerdings dabei aber rax überschrieben, wo zu dem zeitpunkt allerdings anscheinend etwas sinnvolles drinsteht (zmdst benutzt dus 2 zeilen drüber) -> crash.

Lösung:
writejmp neu für 64bit schreiben.
in deinem assembler entweder ein register nehmen was nicht benutzt wird, oder die registerwerte wieder herstellen.
Werde mich an die korrektur setzen und dementsprechend melden!
XxharCs is offline  
Old 10/19/2014, 15:28   #10
 
XxharCs's Avatar
 
elite*gold: 34
Join Date: Apr 2011
Posts: 1,475
Received Thanks: 1,228
Sry für den doppelpost, aber ich denke jetzt darf ich es, sonst lösch ich den obrigen post

Mein kumpel und ich haben uns hingesetzt um jetzt den x64 jump zu machen, jedoch ist es broken irgendwie.. (Typ von hooken: mid function hook)

Ich hoffe jemand kann hier weiter aushelfen
(irgendwie schafft es der VirtualAlloc nicht immer)

Code:
const short MOV_R11_BYTES = 0xBB49;
const short PUSH_R11_BYTE = 0x5341;
const char RET_BYTE = 0xC3;

const int JMP_SMALL_LENGTH = 5;
const int JMP_BIG_LENGTH = 13;
smallJump
Code:
bool writeSmallJump(BYTE* src, BYTE* dst, const unsigned int length){
    
    if(length < JMP_SMALL_LENGTH)
        return false;

    DWORD dwOldProtect;

    VirtualProtect(src, length, PAGE_READWRITE, &dwOldProtect);
    
    src[0] = 0xE9;
    *(DWORD*)(src+1) = ((DWORD)dst - (DWORD)src - 5);

    VirtualProtect(src, length, PAGE_READWRITE, &dwOldProtect);

    return true;
}
bigJump
Code:
bool writeBigJump(BYTE* src, BYTE* dst, const unsigned int length){
    
    if(length < JMP_BIG_LENGTH)
        return false;

    DWORD oldProtect;
    VirtualProtect(src, length, PAGE_READWRITE, &oldProtect);
        
    int offset = 0;

    *(short*)(src + offset) = MOV_R11_BYTES;
    offset += 2;

    *(DWORD64*)(src + offset) = (DWORD64)dst;
    offset += sizeof(DWORD64);

    *(short*)(src + offset) = PUSH_R11_BYTE;
    offset += 2;

    *(char*)(src + offset) = RET_BYTE;
    offset += 1;

    VirtualProtect(src, length, oldProtect, &oldProtect);

    return true;
}
not working x64 jump lol
Code:
void writeNoWorkingX64Jump(BYTE* src, BYTE* dst, void** ret, const unsigned int length)
{
    if(length < JMP_SMALL_LENGTH){
        *ret = NULL;
        return;
    }

    const int totalLength = 13 + length + 13;
    //
    BYTE* trampoline = (BYTE*)malloc(totalLength);
    DWORD dwOldProt;
    BYTE* smallTrampoline = (BYTE*)VirtualAlloc((void*)src, JMP_BIG_LENGTH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    DWORD difference = (DWORD)((DWORD64)smallTrampoline - (DWORD64)src);

    if(difference > (DWORD)0xFFFFFFFF)
        MessageBox(0, "memory to far: DETOUR", 0,0);
            

    if(((DWORD64)trampoline & (DWORD64)smallTrampoline) == NULL){
        *ret = NULL;
        return;
    }
    

    //JMP to Hook
    //////////////////////////////////////////////////////////////
    writeBigJump(smallTrampoline, trampoline, JMP_BIG_LENGTH);
    writeBigJump(trampoline, dst, JMP_BIG_LENGTH);
    //////////////////////////////////////////////////////////////

    trampoline+=JMP_BIG_LENGTH;
    *ret = trampoline;

    //Save code
    memcpy(trampoline, (void*)src, length);
    trampoline += length;
    /////////////////////////////////


    writeBigJump(trampoline, src+length, JMP_BIG_LENGTH);

    writeSmallJump(src, smallTrampoline, length);

    for(int i = 12; i < length; i++)
        src[i] = 0x90;
}
All-in-one:
Code:
const short MOV_R11_BYTES = 0xBB49;
const short PUSH_R11_BYTE = 0x5341;
const char RET_BYTE = 0xC3;

const int JMP_SMALL_LENGTH = 5;
const int JMP_BIG_LENGTH = 13;

bool writeSmallJump(BYTE* src, BYTE* dst, const unsigned int length){
    
    if(length < JMP_SMALL_LENGTH)
        return false;

    DWORD dwOldProtect;

    VirtualProtect(src, length, PAGE_READWRITE, &dwOldProtect);
    
    src[0] = 0xE9;
    *(DWORD*)(src+1) = ((DWORD)dst - (DWORD)src - 5);

    VirtualProtect(src, length, PAGE_READWRITE, &dwOldProtect);

    return true;
}

bool writeBigJump(BYTE* src, BYTE* dst, const unsigned int length){
    
    if(length < JMP_BIG_LENGTH)
        return false;

    DWORD oldProtect;
    VirtualProtect(src, length, PAGE_READWRITE, &oldProtect);
        
    int offset = 0;

    *(short*)(src + offset) = MOV_R11_BYTES;
    offset += 2;

    *(DWORD64*)(src + offset) = (DWORD64)dst;
    offset += sizeof(DWORD64);

    *(short*)(src + offset) = PUSH_R11_BYTE;
    offset += 2;

    *(char*)(src + offset) = RET_BYTE;
    offset += 1;

    VirtualProtect(src, length, oldProtect, &oldProtect);

    return true;
}

void writeNoWorkingX64Jump(BYTE* src, BYTE* dst, void** ret, const unsigned int length)
{
    if(length < JMP_SMALL_LENGTH){
        *ret = NULL;
        return;
    }

    const int totalLength = 13 + length + 13;
    //
    BYTE* trampoline = (BYTE*)malloc(totalLength);
    DWORD dwOldProt;
    BYTE* smallTrampoline = (BYTE*)VirtualAlloc((void*)src, JMP_BIG_LENGTH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    DWORD difference = (DWORD)((DWORD64)smallTrampoline - (DWORD64)src);

    if(difference > (DWORD)0xFFFFFFFF)
        MessageBox(0, "memory to far: DETOUR", 0,0);
            

    if(((DWORD64)trampoline & (DWORD64)smallTrampoline) == NULL){
        *ret = NULL;
        return;
    }
    

    //JMP to Hook
    //////////////////////////////////////////////////////////////
    writeBigJump(smallTrampoline, trampoline, JMP_BIG_LENGTH);
    writeBigJump(trampoline, dst, JMP_BIG_LENGTH);
    //////////////////////////////////////////////////////////////

    trampoline+=JMP_BIG_LENGTH;
    *ret = trampoline;

    //Save code
    memcpy(trampoline, (void*)src, length);
    trampoline += length;
    /////////////////////////////////


    writeBigJump(trampoline, src+length, JMP_BIG_LENGTH);

    writeSmallJump(src, smallTrampoline, length);

    for(int i = 12; i < length; i++)
        src[i] = 0x90;
}
XxharCs is offline  
Old 10/19/2014, 16:41   #11
 
Dr. Coxxy's Avatar
 
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
Quote:
Code:
    BYTE* trampoline = (BYTE*)malloc(totalLength);
    DWORD dwOldProt;
    BYTE* smallTrampoline = (BYTE*)VirtualAlloc((void*)src, JMP_BIG_LENGTH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
warum einmal malloc und einmal virtualalloc?
außerdem brauchts execute rechte, entweder direkt bei virtualalloc angeben, oder per virtualprotect ändern.

Quote:
Code:
DWORD difference = (DWORD)((DWORD64)smallTrampoline - (DWORD64)src);

    if(difference > (DWORD)0xFFFFFFFF)
jetzt mal bitte ganz scharf nachdenken, ob ein DWORD größer als der größte wert in einem DWORD sein kann...

Quote:
Code:
if(((DWORD64)trampoline & (DWORD64)smallTrampoline) == NULL){
wat?

lass erstmal unnötigen mist wie das checken auf big/small jump weg, sondern nimm einfach erstmal immer big jumps, abstrahier noch nicht in funktionen (lohnt sich bei midfunction hooks eh kaum) und bekomm das ganze erstmal zum laufen.
danach kannste dich um feinheiten und optimierungen kümmern, das da ist aber erstmal spaghetticode, bei dem man kaum erkennen kann, was du da überhaupt probierst.
Dr. Coxxy is offline  
Reply




All times are GMT +1. The time now is 13:46.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.