1.Test: 957624744 Taktzyklen
2.Test: 995284260 Taktzyklen
Loops: 1000000000
SUB vs. DEC
Aber ich könnte den Code (wie in deinem Beispiel) in einen Speicherbereich kopieren und dort verändern?Helle hat geschrieben:[...] Den Code während der Laufzeit zu verändern geht im Ring3-Modus (normaler Windows-Modus) nicht. Es gibt zwar spezielle Befehle (z.B.MOV mit Opcode $8E) dafür, aber die laufen nur im Ring0-Modus.
-
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
Naja, ich meinte ja auch so wie in Helles Code, was wohl auch geht, und genau das ist was ich gesucht habe.Kaeru Gaman hat geschrieben:... dann kannst du ihn aber nicht mehr ausführen...![]()
Speicherbereich in Anwendungsprogrammen, also mit "niedrigen" Berechtigungen, kann entweder beschrieben oder ausgeführt werden, nicht beides.
Code: Alles auswählen
Global Mem.i = 1024 ; Speicher reservieren, hier 1 KB
Global CodeMem.i ; Speicheraddresse
Global EAX.l = 0 ; Speicherinhalt eax
CodeMem = VirtualAllocEx_(GetCurrentProcess_(), #Null, Mem, #MEM_COMMIT, #PAGE_EXECUTE_READWRITE)
CopyMemory(?Code_Anfang, CodeMem, ?Code_Ende - ?Code_Anfang)
! call [v_CodeMem] ; Code im Speicher ausführen
MessageRequester("Ausgabe 1", "EAX = " + Str(EAX))
PokeL(CodeMem + 1, 5) ; Da ! MOV eax, 5 = B8:05:00:00:00
! call [v_CodeMem] ; Code im Speicher erneut ausführen
MessageRequester("Ausgabe 2", "EAX = " + Str(EAX))
VirtualFreeEx_(GetCurrentProcess_(), CodeMem, Mem, #MEM_DECOMMIT)
End
Code_Anfang:
! MOV eax, 2
! MOV [v_EAX], eax
! RET
Code_Ende:
Interessant...
Würde sich der Code eignen um ASM - Code von einen JIT - Compiler dynamisch auszuführen?
Würde sich der Code eignen um ASM - Code von einen JIT - Compiler dynamisch auszuführen?
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster
PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Seid wann das denn? Ist das ne Vista-Geschichte?Kaeru Gaman hat geschrieben:... dann kannst du ihn aber nicht mehr ausführen...![]()
Speicherbereich in Anwendungsprogrammen, also mit "niedrigen" Berechtigungen, kann entweder beschrieben oder ausgeführt werden, nicht beides.
Unter XP und drunnter geht das. Man muss lediglich die Zugriffsrechte der Speicherregion ändern, mit der WinAPI-Funktion VirtualProtect. Wenn es das eigene Programm ist, kann man sich das auch sparen, indem man dem Linker verklickert das die Codesection Writable sein soll. Das Flag lässt sich auch später noch in der fertigen .exe setzen. Dann brauch man die Zugriffsrechte garnicht wärend der Laufzeit ändern.
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!

Weißt du eventuell wie? Wäre recht praktisch (wobei einfach während der laufzeit natürlich auch ginge.Thorium hat geschrieben:[...] Wenn es das eigene Programm ist, kann man sich das auch sparen, indem man dem Linker verklickert das die Codesection Writable sein soll. Das Flag lässt sich auch später noch in der fertigen .exe setzen. Dann brauch man die Zugriffsrechte garnicht wärend der Laufzeit ändern.
Und @Kaeru: Meintest du jetzt in einem normalen mit PB erstellten Speicherbereich, oder geht es unter vista nicht? (msdn sagt darüber jedenfalls nichts)
- NicTheQuick
- Ein Admin
- Beiträge: 8809
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
Mal kurz eine andere Frage. Nicht ganz Offtopic, aber so halb:
Könnte man so eine Eval-Funktion schreiben, die einen String-Ausdruck parst, in
Maschinencode übersetzt und dann direkt mit voller Geschwindigkeit wie eine zuvor
kompilierte Funktion ausführt?
Natürlich kann man nicht direkt in Maschinencode übersetzen, aber man könnte ja zuvor alle
Funktionen, die Eval verstehen soll, in eine Art DataSection vorkompilieren und sie später
dann so zusammensetzen, wie sie gebraucht werden. So muss man sich nicht um die
Rechnerarchitektur Gedanken machen.
Könnte man so eine Eval-Funktion schreiben, die einen String-Ausdruck parst, in
Maschinencode übersetzt und dann direkt mit voller Geschwindigkeit wie eine zuvor
kompilierte Funktion ausführt?
Natürlich kann man nicht direkt in Maschinencode übersetzen, aber man könnte ja zuvor alle
Funktionen, die Eval verstehen soll, in eine Art DataSection vorkompilieren und sie später
dann so zusammensetzen, wie sie gebraucht werden. So muss man sich nicht um die
Rechnerarchitektur Gedanken machen.
Ja, weis ich.Batze hat geschrieben:Weißt du eventuell wie? Wäre recht praktisch (wobei einfach während der laufzeit natürlich auch ginge.Thorium hat geschrieben:[...] Wenn es das eigene Programm ist, kann man sich das auch sparen, indem man dem Linker verklickert das die Codesection Writable sein soll. Das Flag lässt sich auch später noch in der fertigen .exe setzen. Dann brauch man die Zugriffsrechte garnicht wärend der Laufzeit ändern.

Hier ein Code, hab ich grad aus einem meiner Projekte rausgeschnippelt. Man kann das ganze auch stark verkürzen aber ich denke mal ist ganz interessant es so lang zu lassen. Funktioniert nur mit 32Bit PE-Executables. Es für 64Bit anzupassen ist nicht viel Aufwand.
Das Programm ermittelt die Entry Code Section, der Bereich in dem der PB-Code liegt, und setzt da das entsprechende Flag. Dann wird die ganze .exe als neue Datei gespeichert. Ich habs jetzt nicht groß getestet, sollte aber funktionieren.
Code: Alles auswählen
;/-----------------------------------\
;| Make Code Section Writable |
;| |
;| Version 1.00 |
;| Stand: 09.05.2009 |
;| |
;| by Thorium |
;| PureBasic 4.30 Code |
;\-----------------------------------/
EnableExplicit
#IMAGE_DOS_HEADER = $5A4D
#IMAGE_NT_SIGNATURE = $00004550
#IMAGE_FILE_EXECUTABLE_IMAGE = $2
#IMAGE_FILE_DLL = $2000
#IMAGE_FILE_MACHINE_I386 = $14C
#IMAGE_FILE_MACHINE_I486 = $14D
#IMAGE_FILE_MACHINE_I586 = $14E
#IMAGE_FILE_MACHINE_IA64 = $200
#IMAGE_FILE_MACHINE_AMD64 = $8664
#IMAGE_FILE_MACHINE_ALPHA = $184
#IMAGE_FILE_MACHINE_ARM = $1C0
#IMAGE_FILE_MACHINE_ALPHA64 = $284
#IMAGE_FILE_MACHINE_M68K = $268
#IMAGE_FILE_MACHINE_MIPS16 = $266
#IMAGE_FILE_MACHINE_MIPSFPU = $366
#IMAGE_FILE_MACHINE_MIPSFPU16 = $466
#IMAGE_FILE_MACHINE_POWERPC = $1F0
#IMAGE_FILE_MACHINE_R3000_BE = $160
#IMAGE_FILE_MACHINE_R3000 = $162
#IMAGE_FILE_MACHINE_R4000 = $166
#IMAGE_FILE_MACHINE_R10000 = $168
#IMAGE_FILE_MACHINE_SH3 = $1A2
#IMAGE_FILE_MACHINE_SH4 = $1A6
#IMAGE_FILE_MACHINE_THUMB = $1C2
#IMAGE_NT_OPTIONAL_HDR32_MAGIC = $10B
#IMAGE_NT_OPTIONAL_HDR64_MAGIC = $20B
#IMAGE_ROM_OPTIONAL_HDR_MAGIC = $107
#IMAGE_SCN_MEM_WRITE = $80000000
#IMAGE_SUBSYSTEM_NATIVE = 1
#IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
#IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
#IMAGE_SUBSYSTEM_OS2_CUI = 5
#IMAGE_SUBSYSTEM_POSIX_CUI = 7
#IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9
#IMAGE_SUBSYSTEM_EFI_APPLICATION = 10
#IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11
#IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12
#IMAGE_SUBSYSTEM_EFI_ROM = 13
#IMAGE_SUBSYSTEM_XBOX = 14
#IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
#IMAGE_ORDINAL_FLAG32 = $80000000
Structure IMAGE_OPTIONAL_HEADER32
MajorLinkerVersion.b
MinorLinkerVersion.b
SizeOfCode.l
SizeOfInitializedData.l
SizeOfUninitializedData.l
AddressOfEntryPoint.l
BaseOfCode.l
BaseOfData.l
ImageBase.l
SectionAlignment.l
FileAlignment.l
MajorOperatingSystemVersion.w
MinorOperatingSystemVersion.w
MajorImageVersion.w
MinorImageVersion.w
MajorSubsystemVersion.w
MinorSubsystemVersion.w
Win32VersionValue.l
SizeOfImage.l
SizeOfHeaders.l
CheckSum.l
Subsystem.w
DllCharacteristics.w
SizeOfStackReserve.l
SizeOfStackCommit.l
SizeOfHeapReserve.l
SizeOfHeapCommit.l
LoaderFlags.l
NumberOfRvaAndSizes.l
EndStructure
Structure IMAGE_OPTIONAL_HEADER64
MajorLinkerVersion.b
MinorLinkerVersion.b
SizeOfCode.l
SizeOfInitializedData.l
SizeOfUninitializedData.l
AddressOfEntryPoint.l
BaseOfCode.l
BaseOfData.l
ImageBase.q
SectionAlignment.l
FileAlignment.l
MajorOperatingSystemVersion.w
MinorOperatingSystemVersion.w
MajorImageVersion.w
MinorImageVersion.w
MajorSubsystemVersion.w
MinorSubsystemVersion.w
Win32VersionValue.l
SizeOfImage.l
SizeOfHeaders.l
CheckSum.l
Subsystem.w
DllCharacteristics.w
SizeOfStackReserve.q
SizeOfStackCommit.q
SizeOfHeapReserve.q
SizeOfHeapCommit.q
LoaderFlags.l
NumberOfRvaAndSizes.l
EndStructure
Structure IMAGE_SECTION_HEADER
Name.s{8}
VirtualSize.l
VirtualAddress.l
SizeOfRawData.l
PointerToRawData.l
PointerToRelocations.l
PointerToLinenumbers.l
NumberOfRelocations.w
NumberOfLinenumbers.w
Characteristics.l
EndStructure
Procedure Exit()
Define.s KeyPressed
PrintN("")
PrintN("Press any key to end program.")
Repeat
Delay(20)
KeyPressed = Inkey()
If KeyPressed <> Chr(0)
End
EndIf
ForEver
End
EndProcedure
Procedure NoPE()
PrintN("")
PrintN("Error: File is no PE (Portable Executable).")
Exit()
EndProcedure
Define.s PEFileName,KeyPressed
Define.i FileLen, OrigFileBuffer, NewFileBuffer, NtHeaderOffset, ImageFormat, i, CodeSectionIndex, Position
Define.IMAGE_FILE_HEADER NtFileHeader
Define.IMAGE_OPTIONAL_HEADER32 NtOptionalHeader32
Define.IMAGE_OPTIONAL_HEADER64 NtOptionalHeader64
Dim NtDataDirectory.IMAGE_DATA_DIRECTORY(0)
Dim SectionHeader.IMAGE_SECTION_HEADER(0)
OpenConsole()
ConsoleTitle("Make Code Section Writable")
PrintN("Make Code Section Writable")
PrintN("")
Print("Input filename: ")
PEFileName = Input()
If ReadFile(1,PEFileName) = 0
PrintN("Error: Can't open file.")
Else
;Länge der Datei prüfen
FileLen = Lof(1)
If FileLen < 512
NoPE()
EndIf
;einlesen der Datei
PrintN("")
PrintN("loading file...")
OrigFileBuffer = AllocateMemory(FileLen)
ReadData(1,OrigFileBuffer,FileLen)
CloseFile(1)
PrintN("done")
;analysieren der Datei
PrintN("")
PrintN("analysing file...")
;ist es eine DOS-EXE?
If PeekW(OrigFileBuffer) <> #IMAGE_DOS_HEADER
NoPE()
EndIf
;Offset des NT-Headers auslesen
NtHeaderOffset = PeekL(OrigFileBuffer + 60)
If NtHeaderOffset > FileLen - 4
NoPE()
EndIf
;ist es eine PE-EXE?
If PeekL(OrigFileBuffer + NtHeaderOffset) <> #IMAGE_NT_SIGNATURE
NoPE()
EndIf
;einlesen des NT-File-Headers
CopyMemory(OrigFileBuffer + NtHeaderOffset + 4,NtFileHeader,SizeOf(IMAGE_FILE_HEADER))
;ist Datei eine DLL?
If NtFileHeader\Characteristics & #IMAGE_FILE_DLL = #IMAGE_FILE_DLL
PrintN("")
PrintN("File is a DLL.")
EndIf
;ist die Datei ein stand alone executable?
If NtFileHeader\Characteristics & #IMAGE_FILE_EXECUTABLE_IMAGE = #IMAGE_FILE_EXECUTABLE_IMAGE
PrintN("File is a stand alone executable.")
EndIf
;für welche CPU ist die Datei vorgesehen?
Print("CPU executable was compiled for: ")
Select $0000FFFF & NtFileHeader\Machine
Case #IMAGE_FILE_MACHINE_I386
PrintN("80386 (386er)")
Case #IMAGE_FILE_MACHINE_I486
PrintN("80486 (486er)")
Case #IMAGE_FILE_MACHINE_I586
PrintN("80586 (Pentium)")
Case #IMAGE_FILE_MACHINE_IA64
PrintN("IA64 (Intel 64bit)")
Case #IMAGE_FILE_MACHINE_AMD64
PrintN("AMD64 or EM64T (AMD 64bit)")
Case #IMAGE_FILE_MACHINE_ALPHA
PrintN("Alpha AXP")
Case #IMAGE_FILE_MACHINE_ALPHA64
PrintN("Alpha AXP 64bit")
Case #IMAGE_FILE_MACHINE_ARM
PrintN("ARM")
Case #IMAGE_FILE_MACHINE_M68K
PrintN("Motorola 68000 series")
Case #IMAGE_FILE_MACHINE_MIPS16
PrintN("MIPS16")
Case #IMAGE_FILE_MACHINE_MIPSFPU
PrintN("MIPS with FPU")
Case #IMAGE_FILE_MACHINE_MIPSFPU16
PrintN("MIPS16 with FPU")
Case #IMAGE_FILE_MACHINE_POWERPC
PrintN("Power PC")
Case #IMAGE_FILE_MACHINE_R3000_BE
PrintN("R3000 processor, big endian")
Case #IMAGE_FILE_MACHINE_R3000
PrintN("R3000 processor, little endian")
Case #IMAGE_FILE_MACHINE_R4000
PrintN("R4000 processor")
Case #IMAGE_FILE_MACHINE_R10000
PrintN("R10000 processor")
Case #IMAGE_FILE_MACHINE_SH3
PrintN("SH3")
Case #IMAGE_FILE_MACHINE_SH4
PrintN("SH4")
Case #IMAGE_FILE_MACHINE_THUMB
PrintN("Thumb")
Default
PrintN("unknown")
EndSelect
;um was für ein Image handelt es sich?
Select PeekW(OrigFileBuffer + NtHeaderOffset + 4 + SizeOf(IMAGE_FILE_HEADER))
Case #IMAGE_ROM_OPTIONAL_HDR_MAGIC
PrintN("image state: ROM")
Case #IMAGE_NT_OPTIONAL_HDR32_MAGIC
PrintN("image state: 32bit")
ImageFormat = 1
Case #IMAGE_NT_OPTIONAL_HDR64_MAGIC
PrintN("image state: 64bit")
ImageFormat = 2
EndSelect
Select ImageFormat
Case 1 ;32bit image
;Optinal Header einlesen
CopyMemory(OrigFileBuffer + NtHeaderOffset + 6 + SizeOf(IMAGE_FILE_HEADER),NtOptionalHeader32,SizeOf(IMAGE_OPTIONAL_HEADER32))
;um welches Subsystem handelt es sich?
Print("subsystem: ")
Select NtOptionalHeader32\Subsystem
Case #IMAGE_SUBSYSTEM_NATIVE
PrintN("native")
Case #IMAGE_SUBSYSTEM_WINDOWS_GUI
PrintN("Windows GUI")
Case #IMAGE_SUBSYSTEM_WINDOWS_CUI
PrintN("Windows CUI")
Case #IMAGE_SUBSYSTEM_OS2_CUI
PrintN("OS2 CUI")
Case #IMAGE_SUBSYSTEM_POSIX_CUI
PrintN("Posix CUI")
Case #IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
PrintN("Windows CE GUI")
Case #IMAGE_SUBSYSTEM_EFI_APPLICATION
PrintN("EFI Application")
Case #IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
PrintN("EFI Boot Service Driver")
Case #IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
PrintN("EFI Runtime Driver")
Case #IMAGE_SUBSYSTEM_EFI_ROM
PrintN("EFI ROM")
Case #IMAGE_SUBSYSTEM_XBOX
PrintN("Xbox")
Case #IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
PrintN("Windows Boot Application")
Default
PrintN("unknown")
EndSelect
;Data Directory einlesen
ReDim NtDataDirectory.IMAGE_DATA_DIRECTORY(NtOptionalHeader32\NumberOfRvaAndSizes - 1)
For i = 0 To NtOptionalHeader32\NumberOfRvaAndSizes - 1
NtDataDirectory(i)\VirtualAddress = PeekL(OrigFileBuffer + NtHeaderOffset + 6 + SizeOf(IMAGE_FILE_HEADER) + SizeOf(IMAGE_OPTIONAL_HEADER32) + (i * 8))
NtDataDirectory(i)\Size = PeekL(OrigFileBuffer + NtHeaderOffset + 10 + SizeOf(IMAGE_FILE_HEADER) + SizeOf(IMAGE_OPTIONAL_HEADER32) + (i * 8))
Next
;Section Header einlesen
ReDim SectionHeader.IMAGE_SECTION_HEADER(NtFileHeader\NumberOfSections - 1)
For i = 0 To NtFileHeader\NumberOfSections - 1
CopyMemory(OrigFileBuffer + NtHeaderOffset + 6 + SizeOf(IMAGE_FILE_HEADER) + SizeOf(IMAGE_OPTIONAL_HEADER32) + (8 * NtOptionalHeader32\NumberOfRvaAndSizes) + (i * SizeOf(IMAGE_SECTION_HEADER)),SectionHeader(i),SizeOf(IMAGE_SECTION_HEADER))
Next
Print("sections in executable:")
For i = 0 To NtFileHeader\NumberOfSections - 1
Print(" " + SectionHeader(i)\Name)
Next
PrintN("")
;Codesection identifizieren
CodeSectionIndex = -1
For i = 0 To NtFileHeader\NumberOfSections - 1
If NtOptionalHeader32\AddressOfEntryPoint => SectionHeader(i)\VirtualAddress And NtOptionalHeader32\AddressOfEntryPoint < SectionHeader(i)\VirtualAddress + SectionHeader(i)\SizeOfRawData
CodeSectionIndex = i
Break
EndIf
Next
If CodeSectionIndex = -1
PrintN("")
PrintN("Entry code section not found!")
Exit()
EndIf
PrintN("entry code section: " + SectionHeader(CodeSectionIndex)\Name)
;ist die Codesection schreibbar?
If SectionHeader(CodeSectionIndex)\Characteristics & #IMAGE_SCN_MEM_WRITE <> #IMAGE_SCN_MEM_WRITE
PrintN("The entry code section is not writable.")
PrintN("Entry code section will be writable in new EXE.")
SectionHeader(CodeSectionIndex)\Characteristics | #IMAGE_SCN_MEM_WRITE
Else
PrintN("The entry code section is writable.")
EndIf
;Code Section Charakteristika setzen
PokeL(OrigFileBuffer + NtHeaderOffset + 6 + SizeOf(IMAGE_FILE_HEADER) + SizeOf(IMAGE_OPTIONAL_HEADER32) + (8 * NtOptionalHeader32\NumberOfRvaAndSizes) + (CodeSectionIndex * SizeOf(IMAGE_SECTION_HEADER)) + 36,SectionHeader(CodeSectionIndex)\Characteristics)
Case 2 ;64bit image
PrintN("Sorry, no 64bit image support.")
EndSelect
;neues executable speichern
PrintN("")
PrintN("saving new executable...")
If Len(PEFileName) > 4
PEFileName = Left(PEFileName,Len(PEFileName) - 4) + "_Writable.exe"
Else
PEFileName = PEFileName + "_Writable.exe"
EndIf
PrintN("filename: " + PEFileName)
If CreateFile(1,PEFileName) = 0
PrintN("")
PrintN("Error: Can't create file!")
Exit()
EndIf
WriteData(1,OrigFileBuffer,FileLen)
CloseFile(1)
EndIf
PrintN("")
PrintN("Press any key to end program.")
Repeat
Delay(20)
KeyPressed = Inkey()
If KeyPressed <> Chr(0)
End
EndIf
ForEver
End
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke!
