ExecuteMemory()

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

ExecuteMemory()

Beitrag von cxAlex »

Angeregt durch den Code von Helle aus diesem Thread habe ich eine allgemeine Procedure geschrieben um ASM - Code aus dem Speicher auszuführen. Das sollte z.B. enorm schnelle Eval() - Proceduren oder JIT - Compiler ermöglichen.

Code: Alles auswählen

; Führt Assemblercode aus dem Speicher aus und gib den Inhalt von EAX zurück
Procedure ExecuteMemory(Code, Size)
  Protected vCode, RtVar
  vCode = VirtualAllocEx_(GetCurrentProcess_(), #Null, Size + SizeOf(Byte), #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
  CopyMemory(Code, vCode, Size)
  PokeB(vCode + Size, $C3); !RET
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    !call qword[p.v_vCode]
  CompilerElse
    !call dword[p.v_vCode]
  CompilerEndIf
  !Mov dword[p.v_RtVar], EAX
  VirtualFreeEx_(GetCurrentProcess_(), vCode, Size + SizeOf(Byte), #MEM_DECOMMIT)
  ProcedureReturn RtVar
EndProcedure

Debug ExecuteMemory(?Code1, ?Code2-?Code1)

DataSection
  Code1:
  Data.b $B8, $FF, $00, $00, $00 ; !MOV EAX, 255
  Code2:
EndDataSection
Gruß, Alex
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Interessant, haette nicht gedacht dass das so einfach geht :allright:
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Warum so kompliziert? In dem Thread stand doch schon dass es das rüberkopieren garnicht braucht.

Code: Alles auswählen

; Führt Assemblercode in (!) dem Speicher aus und gib den Inhalt von EAX zurück
Procedure ExecuteMemory(Code, Size)
  Protected RtVar, OldProtect, Dummy
  ; vCode = VirtualAllocEx_(GetCurrentProcess_(), #Null, Size + SizeOf(Byte), #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
  
  If VirtualProtect_(Code, Size, #PAGE_EXECUTE_READWRITE, @OldProtect)
    PokeB(Code + Size-1, $C3); !RET
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
      ! CALL qword [p.v_Code]
    CompilerElse
      ! CALL dword [p.v_Code]
    CompilerEndIf
      ! MOV dword [p.v_RtVar], eax
    VirtualProtect_(Code, Size, OldProtect, Dummy)
  EndIf
  
  ProcedureReturn RtVar
EndProcedure

Debug ExecuteMemory(?Code1, ?Code2-?Code1)

DataSection
  Code1:
  Data.b $B8, $FF, $00, $00, $00, 0 ; !MOV EAX, 255  (+ Ein leeres Byte (man könnte auch !RET selber reinschreiben) )
  Code2:
EndDataSection
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Beitrag von Josef Sniatecki »

:shock: Habe nicht gedacht, dass man einfach so einen Speicherblock ausführen kann. Bis jetzt kannte ich nur Jumps auf variable Labels.
Thx für die Codes. Wenn ich ASM könnte, dann würde ich sie gut verwenden
können. :wink:
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Josef Sniatecki hat geschrieben::shock: Habe nicht gedacht, dass man einfach so einen Speicherblock ausführen kann.
Naja, der reguläre Code muss ja auch im Speicher liegen. :wink: Alles was man machen muss ist die Speicherregion in der der Code liegt als Executable flagen, falls sie das nicht sowieso schon ist.

Auf älteren Systemen funktioniert das sogar ohne das es als Executable markiert ist. Aber seid dem VX-Bit geht das hardwareseitig nicht mehr und ab XP (wenn ich mich nicht irre) gibt es auch eine softwareseitige Prüfung ob der Code ausgeführt werden darf.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Und wie Flag ich jetzt eine Exe im Speicher als Executable und führe sie aus?

Bitte keine Verweis auf die nicht funktionierenden Codes hier im Forum, die
kenne ich.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

ts-soft hat geschrieben:Und wie Flag ich jetzt eine Exe im Speicher als Executable und führe sie aus?

Bitte keine Verweis auf die nicht funktionierenden Codes hier im Forum, die
kenne ich.
Das funktioniert nicht so ohne weiteres ne ganze .exe auszuführen. Jede .exe hat eine Image Base. Das ist die Adresse an die sie im Speicher geladen wird. Nun gibt es Anweisungen in der .exe die absolute Adressen beinhalten und von dieser Image Base ausgehen. Läd man die .exe einfach so in den Speicher, werden diese Anweisungen in die Scheiße greifen. ^^
Das lässt sich aber lösen. Für diesen Fall gibt die sogenannten Relocations. Das sind Informationen über diese Anweisungen mit absoluten Adressen. Man kann die Infos auslesen und die Relocations anwenden. Heisst man ändert die Anweisungen auf die neuen Adressen ab. Allerdings müssen die Relocationinfos nicht in der .exe enthalten sein. Da eine regulär geladene .exe immer an ihre Image Base geladen wird. Viele .exe Packer und Optimierer entfernen die Relocationinfos aus der .exe.

Das zweite Problem sind die Imports von DLL-Funktionen. Die müssen alle initialisiert werden. Es gibt eine Import Table in der .exe auf die der Code der .exe zugreift um DLL-Funktionen aufzurufen. Beim regulären starten einer .exe initialisiert der PE-Loader von Windows die Import Table. Also läd alle benötigten DLL's und trägt die Funktionsadressen in die Import Table ein. Das müsste man auch per Hand machen.

Dann sollte das funktionieren.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten