Seite 2 von 2

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 01:16
von freak
Fluid Byte hat geschrieben:Zwei Fragen:

1.) Wie bekomme ich die Adresse des TIB ohne das FS-Register?
2.) Der ASM-Code ist so nicht 64Bit kompatibel. Korrekt?
zu 1.) Dazu ist mir kein anderer Weg bekannt.
zu 2.) Korrekt. Unter x64 läuft das über das GS-Register, und alle Offsets müssen natürlich angepasst werden, aber generell geht das da auch irgendwie.

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 01:27
von Thorium
Fluid Byte hat geschrieben:Klingt sehr interessant. Auch wenn ich natürlich Kosten/Nutzen abwäge und sowas für die meisten Projekte nicht in Frage kommt
hätte ich Lust mich damit mit mal näher zu befassen. Gibt es da entsprechende Tutorials oder eine Art Crashkurs um das Ganze mal
besser zu veranschaulichen?
Ich kenne keine hab mich aber auch nie intensiv damit beschäftigt.

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 02:50
von freak
Fluid Byte hat geschrieben:Klingt sehr interessant. Auch wenn ich natürlich Kosten/Nutzen abwäge und sowas für die meisten Projekte nicht in Frage kommt
hätte ich Lust mich damit mit mal näher zu befassen. Gibt es da entsprechende Tutorials oder eine Art Crashkurs um das Ganze mal
besser zu veranschaulichen?
Da steckt nicht besonders viel dahinter: Du musst dir nur überlegen, wie dein Bytecode aussehen soll (Instruktionen und ihre Parameter) und dann besteht der Interpreter für die Virtuelle Maschine einfach daraus den Bytecode zu lesen und die entsprechenden Instruktionen auszuführen.

Kleines Beispiel:

Code: Alles auswählen

Enumeration
  #ILiteral ; argument: 1-byte literal  
  
  #IPush    ; no arguments
  #IPop  
  #IAdd
  #ISub
  #IMul
  #IDiv
EndEnumeration

Procedure Interpreter(*Code.BYTE, *CodeEnd)
  Protected Dim Stack(50)
  Protected Index = 0
  Protected Accumulator = 0  
  
  While *Code < *CodeEnd
    Select *Code\b
    
      Case #ILiteral
        Accumulator = PeekB(*Code+1)
        *Code + 2
      
      Case #IPush
        If Index = 50
          Debug "Stack overflow"
          Break
        EndIf
        
        Index + 1
        Stack(Index) = Accumulator      
        *Code + 1
        
      Case #IPop
        If Index = 0
          Debug "Stack underflow"
          Break
        EndIf      
      
        Accumulator = Stack(Index)
        Index - 1              
        *Code + 1        
      
      Case #IAdd
        Accumulator = Stack(Index) + Accumulator
        Index - 1
        *Code + 1

      Case #ISub
        Accumulator = Stack(Index) - Accumulator
        Index - 1
        *Code + 1
        
      Case #IMul
        Accumulator = Stack(Index) * Accumulator
        Index - 1
        *Code + 1
        
      Case #IDiv
        Accumulator = Stack(Index) / Accumulator
        Index - 1
        *Code + 1        
    
      Default
        Debug "Invalid Instruction"
        Break
    
    EndSelect
  Wend
  
  ProcedureReturn Accumulator
EndProcedure



Debug Interpreter(?Code1, ?CodeEnd1)
Debug Interpreter(?Code2, ?CodeEnd2)



DataSection
  
  ; Code: (((5 * 7) + (10 - 3)) * 2) = 84
  ;
  Code1:
    Data.b #ILiteral, 5
    Data.b #IPush
    Data.b #ILiteral, 7
    Data.b #IMul
    Data.b #IPush
    Data.b #ILiteral, 10
    Data.b #IPush
    Data.b #ILiteral, 3
    Data.b #ISub
    Data.b #IAdd
    Data.b #IPush
    Data.b #ILiteral, 2
    Data.b #IMul
  CodeEnd1:

  ; Code: 2^5 = 32
  Code2:
    Data.b #ILiteral, 2
    Data.b #IPush
    Data.b #ILiteral, 2
    Data.b #IMul
    Data.b #IPush
    Data.b #ILiteral, 2
    Data.b #IMul
    Data.b #IPush
    Data.b #ILiteral, 2
    Data.b #IMul
    Data.b #IPush
    Data.b #ILiteral, 2
    Data.b #IMul
  CodeEnd2:

EndDataSection
Der ByteCode besteht aus 1-byte für die Instruktion, und noch ein weiteres Parameter für #ILiteral, alle anderen Instruktionen haben keine Parameter in ByteCode. Damit kann der Interpreter einfach ein Select auf dem aktuellen code-byte machen um die aktuelle Instruktion zu ermitteln. Die Architektur der mini-VM ist eine Akkumulator-Maschine, das heißt ein Parameter für eine Instruktion wie #IAdd ist immer das Akkumulator-Register und da landet auch das Ergebnis. Weitere Parameter kommen von dem Stack. Man kann hier jede Architektur nachbauen die man will, ich habe diese verwendet weil sie einen sehr minimalen ByteCode braucht und schnell umzusetzen ist.

Das Beispiel macht natürlich noch nicht besonders viel, aber wenn man noch ein paar mehr Instruktionen einbaut wie zum Beispiel Sprünge und bedingte Sprünge dann kann man schnell kleine Funktionen in dem ByteCode schreiben. Vom Kern her ist das eigentlich echt keine große Sache, es kommt halt drauf an wie weit man die Sache treiben will. Wenn man das Ganze komfortabel nutzen will braucht man schon einen Assembler/Disassember dazu, wenn nicht sogar gleich einen Compiler der den ByteCode erzeugt.

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 08:31
von Rings
nur zur vollständigkeit,
der code für x86 (inline asm einschalten):

Code: Alles auswählen

Procedure  IsDebuggerPresent()
  v=0
  !MOV eax, [fs:$18];
  !MOV eax, [eax+$30];
  !MOVZX eax, byte [eax+2];
  MOV v,eax
  ProcedureReturn v
EndProcedure;

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 18:33
von Blackskyliner
Hey, freak!
:)

Würdest du das nochmal in Tipps und Tricks posten, damit das nicht in den Weiten der normalen Thread unter geht?
Denn es ist einfach einfach und "very neat" :)

Re: ASM: hardcoded IsDebuggerPresent()

Verfasst: 06.07.2010 20:26
von Fluid Byte
freak hat geschrieben:Da steckt nicht besonders viel dahinter: Du musst dir nur überlegen, wie dein Bytecode aussehen soll (Instruktionen und ihre Parameter) und dann besteht der Interpreter für die Virtuelle Maschine einfach daraus den Bytecode zu lesen und die entsprechenden Instruktionen auszuführen
Mittels deiner Erläuterungen und dem anschaulichen Demo-Quelltext habe selbst ich das Grundprinzip jetzt verstanden. <)

Nun werde ich das Beispiel modifizieren und kontinuierlich erweitern bis ich das Gefühl habe es in einem schützenswerten
Projekt einzusetzen. Vielen Dank also fürs Beispiel und die hilfreichen Infos.

@Rings:
Exzellent. Funktioniert einwandfrei.