Seite 3 von 3

Verfasst: 29.05.2008 23:47
von Helle
Möglicherweise kannste auch hiermit was anfangen:

Code: Alles auswählen

;Programm - Speicher - Betrachter
;Beispiel für WinMine (Windows XP)

;Structuren definieren
MBI.MEMORY_BASIC_INFORMATION
SysInfo.SYSTEM_INFO

GetSystemInfo_(SysInfo)      ;Ermittlung des für Programme zur Verfügung stehenden Speichers
MinAdr = SysInfo\lpMinimumApplicationAddress
MaxAdr = SysInfo\lpMaximumApplicationAddress
SystemDir$ = Space(#MAXBYTE) 
FileL = GetSystemDirectory_(SystemDir$, #MAXBYTE) 
WinMineDir$ = Left(SystemDir$, FileL) + "\winmine.exe" 
;Prgramm-Handle
hProgram = RunProgram(WinMineDir$, "", GetCurrentDirectory(), #PB_Program_Open) 
;damit die Programm-ID ermitteln; ist die, die auch der Task-Manager anzeigt (variabel!!!)
ProgID = ProgramID(hProgram) 
;jetzt das Ganze für Vollzugriff öffnen
ProcessHandle = OpenProcess_(#PROCESS_ALL_ACCESS, #False, ProgID)

AnfAdresse = MinAdr
Delay(1000)                  ;Windows etwas Zeit zum Speicher-Organisieren geben
While AnfAdresse < MaxAdr
  VirtualQueryEx_(ProcessHandle, AnfAdresse, MBI, SizeOf(MEMORY_BASIC_INFORMATION))
  Eigner = MBI\State
  Size = MBI\RegionSize
  Status = MBI\Protect
  If Eigner = #MEM_COMMIT And Status = #PAGE_READWRITE And AnfAdresse >= $1000000
    BaseAdr = MBI\BaseAddress
    EndAdr = BaseAdr + Size
    Break
  EndIf
  AnfAdresse + Size
  If AnfAdresse < 0          ;negativ!
    Break
  EndIf
Wend  

Laenge = (EndAdr - BaseAdr)
Buffer = AllocateMemory(Laenge)
BufferS = AllocateMemory(Laenge)

If Buffer = 0 Or BufferS = 0
  MessageRequester("Fehler !", "Der benötigte Speicher konnte nicht bereitgestellt werden !")
  End
EndIf

If OpenWindow(0, 0, 0, 630, 505, "Programm - Speicher - Betrachter", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ListIconGadget(0, 10, 10, 610, 485, "Adresse", 75, #PB_ListIcon_GridLines)
  
  For b = 1 To 16
    AddGadgetColumn(0, b, Hex(b-1), 32)
  Next
 
  ReadProcessMemory_(Processhandle, BaseAdr, Buffer, Laenge, 0)
  n = Laenge
  n >> 4
  n - 1
  For k = 0 To n
    For i = 0 To 15
      Test1$ + Chr(10) + RSet(Hex(PeekB(Buffer + z)), 2, "0")
      z + 1
    Next 
    AddGadgetItem(0, -1, Hex(BaseAdr + k << 4) + Test1$)
    Test1$ = "" 
  Next   
  SetActiveGadget(0)
 
  Repeat
    EventId = WindowEvent()  

    CopyMemory(Buffer, BufferS, Laenge)

    ReadProcessMemory_(Processhandle, BaseAdr, Buffer, Laenge, 0)
    z = 0
    n = Laenge-4
    n >> 4
    n - 1
    For k = 0 To n
      For i = 0 To 15
        If (PeekB(Buffer + z) & 255) <> (PeekB(BufferS + z) & 255)
          N$=RSet(Hex((PeekB(Buffer + z) & 255)), 2, "0") + "<"    ;"<" als Zeichen für verändert
          SetGadgetItemText(0, k, N$, i + 1)
        EndIf
        z + 1
      Next 
    Next   

    Delay(5) 
  Until EventId = #PB_Event_CloseWindow
EndIf
Gruß
Helle

Verfasst: 30.05.2008 01:01
von Thorium
Also ich nutze um Code in einem fremden Prozess zu patchen auch entweder die Datasection oder ich baue mir den Code erst in einem Buffer zusammen und übertrage ihn dann per WriteProcessMemory oder falls ich von einer injizierten DLL ausgehe per CopyMemory.

Was auch gut funktioniert und sehr schön zu warten ist: Einfach den Asm-Code als Asm-Code in den PureBasic-Code schreiben mit Labeln Anfang und Ende "markieren" und dann später per CopyMemory bzw. WriteProcessMemory zum patchen einsetzen. Da brauchst die Opcodes garnet als Hexwerte.

Wenn du dich tiefergehender mit Reversing beschäftigen möchtest, musst du dir unbedingt die Geschichte mit Pointern und Buffern nochmal genau anschauen. Gibts sicherlich Tutorials für. So wie ich das hier lese, hast du das nämlich nicht richtig verstanden.

Mal ein paar Beispiele:
DataSection
typischer Trainer-Code

Code: Alles auswählen

  InfiniteLifesCode:
  Data.b $90,$90,$90,$90,$90,$90
  UnInfiniteLifesCode:
  Data.b $81,$C3,$FF,$FF,$FF,$FF

Procedure InfinitLives()
  Define.l hProcess,BytesWritten

  hProcess = OpenTarget()
  If hProcess <> 0
    If InfinitLivesOn = 0
      WriteProcessMemory_(hProcess,$0040396A,?InfiniteLifesCode,6,@BytesWritten)
      InfinitLivesOn = 1
    Else
      WriteProcessMemory_(hProcess,$0040396A,?UnInfiniteLifesCode,6,@BytesWritten)
      InfinitLivesOn = 0
    EndIf
  EndIf
  
  CloseHandle_(hProcess)
EndProcedure
Code in Buffer zusammenbauen
Der Code hat zwar nix mit Trainern zu tun, aber ist ja nur ein Beispiel.

Code: Alles auswählen

  ;Speicher für die Codegenerierung allokieren
  CodeBuffer = AllocateMemory(22)

  ;Code generieren
  PokeB(CodeBuffer,$68) ;push
  Position + 1
  PokeL(CodeBuffer + Position,ThreadContext\Eip)
  Position + 4
  PokeB(CodeBuffer + Position,$9C) ;pushfd
  Position + 1
  PokeB(CodeBuffer + Position,$60) ;pushad
  Position + 1
  PokeB(CodeBuffer + Position,$68) ;push
  Position + 1
  PokeL(CodeBuffer + Position,FileNameAddr)
  Position + 4
  PokeB(CodeBuffer + Position,$B8) ;mov eax,const
  Position + 1
  PokeL(CodeBuffer + Position,LoadLibraryAAddr)
  Position + 4
  PokeW(CodeBuffer + Position,$D0FF) ;call eax
  Position + 2
  PokeB(CodeBuffer + Position,$61) ;popad
  Position + 1
  PokeB(CodeBuffer + Position,$9D) ;popfd
  Position + 1
  PokeB(CodeBuffer + Position,$C3) ;ret

  ;Code in den Zielprozess schreiben
  If WriteProcessMemory_(hTarget,CodeAddr,CodeBuffer,22,@BytesWritten) = 0
    VirtualFreeEx_(hTarget,FileNameAddr,0,#MEM_RELEASE)
    VirtualFreeEx_(hTarget,CodeAddr,0,#MEM_RELEASE)
    FreeMemory(CodeBuffer)
    ResumeThread_(hThread)
    CloseHandle_(hThread)
    CloseHandle_(hTarget)
    ProcedureReturn 0
  EndIf
Code einfach als Asm in PB
Der Code hat zwar nix mit Trainern zu tun, aber ist ja nur ein Beispiel.

Code: Alles auswählen

  ProcSize = ?SelfUnloadProcEnd - ?SelfUnloadProcStart
  NewProcAddr = VirtualAlloc_(0,ProcSize,#MEM_COMMIT | #MEM_RESERVE,#PAGE_EXECUTE_READWRITE)
  CopyMemory(?SelfUnloadProcStart,NewProcAddr,ProcSize)

  hSelfModule = GetModuleHandle_(SelfModuleName)
  hKernel32 = GetModuleHandle_("kernel32.dll")
  FreeLibraryAddr = GetProcAddress_(hKernel32,"FreeLibrary")
  ExitThreadAddr = GetProcAddress_(hKernel32,"ExitThread")

  SelfUnloadProcStart:
  !mov eax,dword[p.v_FreeLibraryAddr]
  !mov ebx,dword[p.v_hSelfModule]
  !push ebx
  !call eax
  !mov eax,dword[p.v_ExitThreadAddr]
  !xor ebx,ebx
  !push ebx
  !call eax
  SelfUnloadProcEnd:

Verfasst: 30.05.2008 02:03
von Kaeru Gaman
Thorium hat geschrieben:Einfach den Asm-Code als Asm-Code in den PureBasic-Code schreiben mit Labeln Anfang und Ende "markieren" und dann später per CopyMemory bzw. WriteProcessMemory zum patchen einsetzen.
:allright:
...in deinem Beispiel fehlt allerdings das End, um den ASM-code gegen Ausführung zu schützen...

Verfasst: 30.05.2008 14:55
von whitelion
wow, so viel hilfe und einsatzbereitschaft von euch hätte ich jetzt nicht erwartet :-) freue ich mich sehr drüber und werde mal anfange die tipps umzusetzen...
mir fällt es im moment am schwersten eure codes (besonders die schleifen) nachzuvollziehen, außerdem fehlt mir wohl noch grundwissen. ich hab nämlich keine ahnung was * und <> und >> bedeuten. den unterschied von buffern, data sectionen und deren aus meiner sicht tw. komplizierte bzw umständliche "befüllung" konnte ich auch nicht nicht ganz nachvollziehen. in meiner naiven art hab ich gedacht: "es gibt hex, dezimal und strings die man da reinpackt. warum befüllt man einen buffer nicht einfach mit auslesen einer datei oder angeben eines strings bzw einer belibig großen hex oder zahlenwerten?" ... wie auch immer. ich versuche erstmal das fehlende zusammen zu lesen und nerv dann weiter :-)

Verfasst: 30.05.2008 15:23
von ts-soft
whitelion hat geschrieben:warum befüllt man einen buffer nicht einfach mit auslesen einer datei

Code: Alles auswählen

*mem = AllocateMemory(10)
If *mem
  If ReadFile(0, "bla.dat")
    ReadData(0, *mem, MemorySize(*mem)
    CloseFile(0)
  EndIf
EndIf
whitelion hat geschrieben: oder angeben eines strings bzw einer belibig großen hex oder zahlenwerten?" ... wie auch immer. ich versuche erstmal das fehlende zusammen zu lesen und nerv dann weiter :-)
Bei Strings mußte natürlich vorher konvertieren, aber wozu Strings? Wozu
Hex, sind doch nur Darstellungsmittel.

Gruß
Thomas

Verfasst: 30.05.2008 15:48
von Kaeru Gaman
ts-soft hat geschrieben:Bei Strings mußte natürlich vorher konvertieren, aber wozu Strings?
Wozu Hex, sind doch nur Darstellungsmittel.
grünau!

genau genommen ist eine Hex-Zahl auch nur ein String.
ganz genau genommen ist jede ausgegebene zahl ein String.
nur dass dir eben der Debugger die umwandlung abnimmt,wenn du

Code: Alles auswählen

Debug Var
schreibst.
der Debugger führt dann selbsttätig

Code: Alles auswählen

Debug Str(Var)
aus.
wenn du die zahl mit text kombinieren willst, musst du es ja manuell machen

Code: Alles auswählen

Debug "Wert = " + Str(Var)
genausogut kannst du dann latürnich auch schreiben

Code: Alles auswählen

Debug "Hexwert = $" + Hex(Var)
...wenn du in einer datei 3.1415926535897932384626433832795 literal drinstehen hast,
musst du es auch als string einlesen und in eine double umwandeln,
bevor du den Wert einer numerischen Variable zuweisen kannst.

das ist nicht kompliziert, das ist sauber, weil nichts für die EDV tödlicher wäre,
als wenn die Maschine nach gutdünken Datentypen durcheinanderwerfen würde.

stell dir vor, eine Stadt hieße Addeba, aber der rechner gibt dir das als 11394746 aus.....
...oder bestell mal ein Flugticket nach elfmillionendreihundertvierundneunzigtausendsiebenhundertsechsundvierzig.