|
You last visited: Today at 13:46
Advertisement
x64 ASM mit C++ problem
Discussion on x64 ASM mit C++ problem within the C/C++ forum part of the Coders Den category.
10/12/2014, 17:37
|
#1
|
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!
|
|
|
10/12/2014, 20:40
|
#2
|
elite*gold: 1
Join Date: Apr 2010
Posts: 13,772
Received Thanks: 15,036
|
0x vor bzw. 'h' hinter jede Nummer.
Btw.
Geht sowas überhaupt ôo?
|
|
|
10/12/2014, 20:51
|
#3
|
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.
|
|
|
10/12/2014, 21:29
|
#4
|
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.
|
|
|
10/12/2014, 21:41
|
#5
|
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
|
|
|
10/12/2014, 22:08
|
#6
|
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.
|
|
|
10/12/2014, 22:17
|
#7
|
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.
|
|
|
10/12/2014, 23:22
|
#8
|
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.
|
|
|
10/13/2014, 08:24
|
#9
|
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
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
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!
|
|
|
10/19/2014, 15:28
|
#10
|
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;
}
|
|
|
10/19/2014, 16:41
|
#11
|
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.
|
|
|
All times are GMT +1. The time now is 13:46.
|
|