SUB vs. DEC

Fragen zu allen anderen Programmiersprachen.
Andesdaf
Moderator
Beiträge: 2673
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

ich mach auch mit:
1.Test: 957624744 Taktzyklen
2.Test: 995284260 Taktzyklen
Loops: 1000000000
Win11 x64 | PB 6.20
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

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.
Aber ich könnte den Code (wie in deinem Beispiel) in einen Speicherbereich kopieren und dort verändern?
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

... dann kannst du ihn aber nicht mehr ausführen... :mrgreen:

Speicherbereich in Anwendungsprogrammen, also mit "niedrigen" Berechtigungen, kann entweder beschrieben oder ausgeführt werden, nicht beides.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Kaeru Gaman hat geschrieben:... dann kannst du ihn aber nicht mehr ausführen... :mrgreen:

Speicherbereich in Anwendungsprogrammen, also mit "niedrigen" Berechtigungen, kann entweder beschrieben oder ausgeführt werden, nicht beides.
Naja, ich meinte ja auch so wie in Helles Code, was wohl auch geht, und genau das ist was ich gesucht habe.

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:
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Interessant...

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

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

Ich vermute sowas ginge damit, ja. Ich habe da bescheidenere Wünsche, ich will einfach nur meinen Code schneller machen (wobei ich versucht bin einen Bilderzeichencode damit zu machen, der mir eine Grafik in ASM-Code konvertiert ;) )
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Kaeru Gaman hat geschrieben:... dann kannst du ihn aber nicht mehr ausführen... :mrgreen:

Speicherbereich in Anwendungsprogrammen, also mit "niedrigen" Berechtigungen, kann entweder beschrieben oder ausgeführt werden, nicht beides.
Seid wann das denn? Ist das ne Vista-Geschichte?
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! Bild
Benutzeravatar
Batze
Beiträge: 1492
Registriert: 03.06.2005 21:58
Wohnort: Berlin
Kontaktdaten:

Beitrag von Batze »

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.
Weißt du eventuell wie? Wäre recht praktisch (wobei einfach während der laufzeit natürlich auch ginge.

Und @Kaeru: Meintest du jetzt in einem normalen mit PB erstellten Speicherbereich, oder geht es unter vista nicht? (msdn sagt darüber jedenfalls nichts)
Hier sind meine Codes (aber die Seite geht gerade nicht):
http://www.basicpure.de.vu
Benutzeravatar
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

Beitrag von NicTheQuick »

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.
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

Batze hat geschrieben:
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.
Weißt du eventuell wie? Wäre recht praktisch (wobei einfach während der laufzeit natürlich auch ginge.
Ja, weis ich. :)

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! Bild
Antworten