Page 1 sur 1

Désassemblage dynamique

Publié : dim. 08/mars/2009 15:27
par Ollivier
Je poste ce code qui désassemble le code machine en instruction assembleur de manière dynamique.

Code : Tout sélectionner

;{ Données du programme enfant }
DataSection
Data.S "Error.I = 1"
Data.S "If OpenConsole()"
Data.S "If ExamineAssembly(?CodeStart, ?CodeEnd):"
Data.S "If NextInstruction()"
Data.S "BaseAdress.I = InstructionAddress()"
Data.S "PrintN(InstructionString() )"
Data.S "Input()"
Data.S "Error = 0"
Data.S "EndIf"
Data.S "EndIf"
Data.S "CloseConsole()"
Data.S "EndIf"
Data.S "End Error"
Data.S "CodeStart:"
Data.S "CodeEnd:"
Data.S ""
EndDataSection
;}

Global Dim TrustLine.S(31)

#Home = #PB_Compiler_Home

Structure OpString
   TrustFileName.S
   Value.S
   CplProg.I   
   TrustLineQty.I
   CodeOp.I[63]
   CodeQty.I
EndStructure

Procedure.S CplInput(St.S)
   Protected I.I
   Protected Result.S
   Result = UCase(St)
   Result = ReplaceString(Result, ";", Chr(9) )
   ProcedureReturn Result
EndProcedure

Procedure ReadTrust(*C.OpString) ; one time !
   Protected St.S
   With *C
      Repeat
         Read.S St
         If St <> ""
            TrustLine(\TrustLineQty) = St
            \TrustLineQty + 1
         EndIf
      Until St = ""
   EndWith
EndProcedure

Procedure PreStoreTrust(*C.OpString, St.S) ; Etape A
   Protected I.I
   With *C
      \CodeQty = CountString(St, ".") + 1
      For I = 0 To CountString(St, ".")     
         \CodeOp[I] = Val(StringField(St, I + 1, ".") )
      Next I
   EndWith
EndProcedure

Procedure StoreTrust(*C.OpString) ; Etape B
   Protected I.I
   With *C
      CreateFile(0, #Home + \TrustFileName + ".pb")
         For I = 0 To \TrustLineQty - 2
            WriteStringN(0, TrustLine(I) )
         Next I
         For I = 0 To \CodeQty - 1
            WriteStringN(0, "! DB " + Str(\CodeOp[I] ) )
         Next I
         WriteStringN(0, TrustLine(\TrustLineQty - 1) )
      CloseFile(0)
   EndWith
EndProcedure

Procedure CompileTrust(*C.OpString)
   With *C
      WriteProgramStringN(\CplProg, CplInput("SOURCE;" + #Home + \TrustFileName + ".pb") )
      WriteProgramStringN(\CplProg, CplInput("TARGET;" + #Home + \TrustFileName + ".EXE") )
      WriteProgramStringN(\CplProg, "COMPILE")
      ReadProgramString(\CplProg)
   EndWith
EndProcedure

Procedure.I ExecTrust(*C.OpString) ;

   Protected Result.I
   With *C
      Trust = RunProgram(#Home + \TrustFileName + ".EXE", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
      \Value = ReadProgramString(Trust)
      WriteProgramStringN(Trust, " ")
      While ProgramRunning(Trust)
         Delay(16)
      Wend
      Result = ProgramExitCode(Trust)
      CloseProgram(Trust)
   EndWith
   ProcedureReturn Result.I

EndProcedure

Procedure RecordTrust(*C.OpString) ;
   With *C
      Debug \Value
   EndWith
EndProcedure

Procedure CplOpen(*C.OpString)
   Protected St.S
   With *C
      \CplProg = RunProgram(#PB_Compiler_Home+"\Compilers\pbcompiler", "/STANDBY", "", #PB_Program_Open|#PB_Program_Read|#PB_Program_Write|#PB_Program_Hide)
      If \CplProg
         Repeat
            Delay(15)
            St = ReadProgramString(\CplProg)
         Until St = "READY"
      Else
         MessageRequester("/!\", "Code 3")
      EndIf
   EndWith
EndProcedure

Procedure CplClose(*C.OpString)
   With *C
      WriteProgramStringN(\CplProg, "END")
      While ProgramRunning(\CplProg)
         Delay(100)
      Wend
      If ProgramExitCode(\CplProg) <> 0
         MessageRequester("/!\", "Code 2")
      EndIf
      CloseProgram(\CplProg)
   EndWith
EndProcedure

Procedure.S DisAsm(*C.OpString, St.S)
   Protected Result.S
   With *C
      Delay(500)
      PreStoreTrust(*C, St) ; CodeChaîne >> CodeNum
      StoreTrust(*C) ; CodeNum >> FichPB
      CompileTrust(*C) ; FichPB >> FichEXE
      ExecTrust(*C) ; FichEXE >> CodeOp
;   RecordTrust(Op) ; CodeOp >> Enregistrement
      Result = \Value
   EndWith
   ProcedureReturn Result
EndProcedure

Procedure Main()

   Protected Op.OpString
   Protected St.S
   
   Op\TrustFileName = "Temp"
   ReadTrust(Op)
   
   CplOpen(Op)   
      OpenConsole()
      Repeat         
         PrintN(" ")
         PrintN("Saisissez un code machine. Puis validez avec la touche [Entree].")
         PrintN("Le code doit etre en decimal.")
         PrintN("Le code est ecrit octet apres octet, separe d'un point.")
         PrintN("Exemple: 0.0 (Ici, le code machine se compose de 2 octets chacun etant egal a zero.")
         St = Input()
         If St = ""
            Break
         Else
            Print("Le code machine de " + St + " est : ")
            PrintN(UCase(DisAsm(Op, St) ) )
            Print("Appuyez sur [Entree] pour continuer...")
            Input()
         EndIf
      ForEver
      CloseConsole()
   CplClose(Op)
   
EndProcedure

   Main() 

Publié : sam. 04/avr./2009 10:15
par Fig
Ca marche super bien, mais je n'ai pas compris comment :?

Publié : mar. 14/avr./2009 14:12
par Ollivier
Regarde la procédure DisAsm(). Elle contient plein de commentaires étape par étape. ça te donne une idée de la gymnastique effectuée (utilisation du compilateur, des pipes, de la bibliothèque de désassemblage, etc...).

Ollivier

Publié : mar. 14/avr./2009 15:19
par djes
On voit qu'Ollivier code beaucoup! C'est un très beau programme, fait par un programmeur très talentueux.

Publié : mar. 14/avr./2009 21:34
par Ollivier
Moi je ne suis pas talentueux et je ne mérite rien! Ce sont les auteurs de la bibliothèque OnError qui méritent d'être remerciés depuis 2003 (année de création de la lib) : Siegfried Rings et Sebastian Lackner.

Quelque part, même si techniquement c'est une gymnastique complexe, je n'ai créé qu'une "porte" qui mène à l'une des nombreuses utilisations offertes par la librairie OnError.

Si j'avais dû me coltiner tout le jeux, je n'en serais encore qu'au tiers ou à la moitiée: c'est très complexe. L'EXE résultant fait 100Ko à vide!!

Ollivier

Publié : mar. 14/avr./2009 22:43
par djes
Je n'ai jamais utilisé cette lib, merci pour l'info. Notre "petit" langage" ne cessera jamais de m'étonner. C'est du bonheur!