Dynamischer Code
-
Ich versuche Code sozusagen "on the fly" zu erzeugen und auszuführen, funktioniert nur nicht.
Edit:
Probleme gelöst//gcc with -masm=intel #include <stdio.h> #include <malloc.h> #include <stdint.h> #define CALL 0xE8 #define CALL_SIZE 5//1 byte for call and 4 byte for address #define JMP 0xE9 #define JMP_SIZE 5 void foo(){ puts("Hello World"); } uint8_t* mem = NULL; int main(){ if (mem == NULL){ //allocate some memory mem = (uint8_t*)malloc(CALL_SIZE+JMP_SIZE); //call foo mem[0] = CALL; *(uint32_t*)(mem + 1) = (uint32_t)foo - (uint32_t)mem - JMP_SIZE; //jmp to main mem[5] = JMP; *(uint32_t*)(mem + 6) = (uint32_t)main - (uint32_t)mem - JMP_SIZE - CALL_SIZE; } asm("mov eax, dword ptr [_mem]"); asm("jmp eax"); return 0; }
Eine wunderschöne nicht terminierende Schleife
Vielen Dank für die Hilfe
Edit:
Wenn man die entsprechenden opcodes hinzufügt kann man das ganze sogar zu ner Funktion casten.
-
Wenn du die Ziel-Offsets direkt reinschreiben willst solltest nicht relative Jumps/Calls sondern absolute Jumps/Calls nehmen
Far Jump:
EA xx xx xx xx yy yy
JMP FAR SEGMENT:OFFSET
x => 4 byte offset
y => 2 byte segment (Inhalt vom CodeSegment Register CS)Near Jump:
FF 25 78563412
=> JMP dword near 0x12345678Alternative wären relative Jumps zu verwenden, da musste allerdings die Anzahl an Bytes die übersprungen werden sollen angeben und kein absolutes Offset.
Bei Calls genau das gleiche.
Hol dir einfach mal nen Assembler und spiel n bisschen damit rumUnd ja, das gehört in Little Endian da rein
Die verschiedenen Formen von JMPs bzw CALLs gibts z Bsp hier:
http://siyobik.info/main/reference/instruction/JMP
http://siyobik.info/main/reference/instruction/CALLNormalerweise sollten aber die Intel Manuals vorgezogen werden
-
Du musst die entsprechende Page Attribute für mem setzen: VirtualProtect
Die relative call Adresse (E8!) berechnet sich nach: &foo - &mem[6]
Außerdem musst du die Rücksprungadresse auf den Stack puschen und diesen nach der Rückkehr korrigieren (c-call).
Es handelt sich um eine 32Bit Anwendung?BTW: FAR jumps werden nicht gebraucht.
-
upps: &mem[5]
-
masm schrieb:
Du musst die entsprechende Page Attribute für mem setzen: VirtualProtect
Muss ich das wirklich?
Jetzt geht es zumindest so, aber das könnte auch Zufall sein.
Allerdings kann man ja Speicher den man mittels malloc bekommen hat beschreiben und lesen, also würde ich vermuten, dass das nicht unbedingt nötig ist.masm schrieb:
Die relative call Adresse (E8!) berechnet sich nach: &foo - &mem[6]
Jo, so gehts
(Edit: +-1)
masm schrieb:
Außerdem musst du die Rücksprungadresse auf den Stack puschen und diesen nach der Rückkehr korrigieren (c-call).
Gut, wird der nächste Schritt sein
livinskull schrieb:
Wenn du die Ziel-Offsets direkt reinschreiben willst solltest nicht relative Jumps/Calls sondern absolute Jumps/Calls nehmen[/url]
Normalerweise sollten aber die Intel Manuals vorgezogen werden
Absolute jmps sind bestimmt eine gute Alternative, dann muss ich nicht so viel rumrechnen.
Probiere ich auch aus
-
EVIL_ENT schrieb:
masm schrieb:
Du musst die entsprechende Page Attribute für mem setzen: VirtualProtect
Muss ich das wirklich?
Ja, sollte man hinsichtlich DEP machen. Bei DLLs ist es zwingend, sofern diese von Prozessen geladen werden, die DEP unterstützen bzw. bei denen es aktiviert ist.
-
Falsches Forum,
#define xy hex // und dann auch noch unvollständig
ist mit Sicherheit kein Assembler
-
nachtfeuer schrieb:
Falsches Forum,
#define xy hex // und dann auch noch unvollständig
ist mit Sicherheit kein Assembler
Man kann sich auch anstellen...
Der Code ist offensichtlich beides und es werden wohl mehr Leute die Assembler kennen auch C können als andersherum.
Außerdem hätten mir Leute, die nur C/++ können bei meinem Problem wohl kaum weiter helfen können.Ist aber egal, ist alles gelöst.
-
EVIL_ENT schrieb:
Ist aber egal, ist alles gelöst.
Das ist aber nicht besonders wartbar. Du hast bisher nur zwei Opcodes verwendet, bei mehr wird es deutlich unübersichtlicher. Es gibt doch genug C/C++ Bibliotheken, die dir die Opcodes und Parameter generieren, mit denen kann man deutlich übersichtlicher arbeiten.
-
Falls es noch jemand interessiert, wie man es mit VirtualAlloc() macht, hier ein Beispiel:
#define SIZE (32u) unsigned char *p = NULL; DWORD old_protect = 0; p = VirtualAlloc(NULL, SIZE, MEM_COMMIT, PAGE_READWRITE); p[0] = 0x90u; p[1] = 0xC3u; VirtualProtect(p, SIZE, PAGE_EXECUTE, &old_protect); ((void (*)(void))p)();
so müsste es gehen... wer Fehler findet - bekommt von mir nichts
-
abc.w schrieb:
Falls es noch jemand interessiert, wie man es mit VirtualAlloc() macht, hier ein Beispiel
Das Beispiel macht mehr als Nötig ;-D
-
Mechanics schrieb:
Es gibt doch genug C/C++ Bibliotheken, die dir die Opcodes und Parameter generieren, mit denen kann man deutlich übersichtlicher arbeiten.
Schön, war mir neu
Hab mal versucht danach zu suchen, aber kenn wohl nicht die richtigen Keywords.
Das hier finde ich aber immer noch halbwegs lesbar.
(Edit: Ok, mit instructions die mehr als 1 Byte brauchen ist es etwas unhandlich, ich überleg mir was.)
Allerdings weiß ich nicht, ob ich einfach so ein globales array für meinen Code verwenden darf, oder ob ich das immer per VirtualAlloc machen sollte.#include <windows.h> #define NOP 0x90 #define CALL 0xE8 #define JMP 0xE9 #define PUSH_EBP 0x55 #define MOV 0x89 #define ESP_TO_EBP 0xE5 #define EBP_TO_ESP 0xEC #define POP_EBP 0x5D #define RET 0xC3 void foo(){ MessageBox(NULL, "Hello World!", "Success!", MB_OK); } BYTE code[12] = { //enter function PUSH_EBP, MOV, ESP_TO_EBP,//EDIT: this line is one instruction //call address CALL, 0, 0, 0, 0, //leave function MOV, EBP_TO_ESP,//EDIT: this line is one instruction POP_EBP, RET }; int main(){ DWORD dw = 0; VirtualProtect(code, sizeof(code), PAGE_EXECUTE_READWRITE, &dw); *(DWORD*)(code + 4) = (DWORD)foo - (DWORD)code - 1 - 4 - 3; void(*test)() = (void(*)())code; test(); return 0; }