Archive for the ‘Python’ Category

Memory Debugging or a “Universal Game Trainer” with Python and ptrace

by apoc · juli 26 2010 · leave a comment

Reading and writing other process memory can have many different purposes: besides debugging, this technique is probably most frequently known to be used by game trainers, to alter different values of a running game (like the value of health or money).

Most (if not all) of the game trainers available, are developed for Windows and only for a specific game, but there are some universal trainers, that could be used to locate and change values in memory of any game or application and with kcheat and Tursiops there are some solutions for Linux.
I’ve developed a proof of concept to locate and change any byte value using python and the ptrace bindings. ptrace is a Unix system call for controlling other processes, it is for instance used by the gdb debugger.

The following code creates a debugging instance and attaches the other process by PID:

from ptrace.debugger.debugger import PtraceDebugger
 
dbg = PtraceDebugger()
process = dbg.addProcess(1234, False)

Now the process instance can be used to inspect and manipulate the process. To manipulate the memory it is important to know the virtual memory mappings (‘areas’) of the process:

from ptrace.debugger.memory_mapping import readProcessMappings
 
memory_mapping = readProcessMappings(process)

Now the list contains MemoryMapping instances, describing the virtual memory areas of the process. We are interested in their location and permission (Quickref: mapping.start, mapping.end, mapping.permissions). The trainer should only be searching within memory mappings with “rw” permissions.

Last but not least, the reading and writing from/to memory methods:

value = process.readBytes(0x11223344, 1) # this reads 1 byte
process.writeBytes(0x11223344, value) # writes len(value) bytes

After that you can close the debugger instance by:

dbg.quit()

I encountered some difficulties with closing/detaching the debugging process, it seems that the process is only really detached if the script is terminated, as a workaround I forked the memory search process, to circumvent that in my proof of concept trainer.

That’s it! If you’re interested, you can checkout my proof of concept for a universal game trainer: pycheat.py (GPLv3) It can locate and change byte values (char) in other processes memory:

% python pycheat.py 8169
pycheat: universal game trainer v0.1
process id: 8169
highest address: 0xffffff
 
searching for address by byte value: 23
search memory area[0x00DB8000-0x00DC0000] address[0x00DBD989] value[0x17 (023)]    
 
found 5926 occurrences, change value to: 33
search memory area[0x00DB8000-0x00DC0000] address[0x00DBFD88] value[0x21 (033)]    
 
found 1 occurrence! correct address for this value is 0x00C4335A
change value in memory at 0x00C4335A to: 99
done.

First you enter the known value, the trainer is searching it inside the memory, chances are high, that there are many occurrences of it, so you change the value inside the game and repeat the search with the new one. After ~2-4 iterations the correct location should be found and you can manipulate it.

edit: smaller changes

Tagged: , , , ,

mtget: ZDF Mediathek Download/Stream

by apoc · dezember 21 2009 · 4 comments

Nachdem die ZDF Mediathek nun ihr lang erwartetes relaunch ‘feiern’ kann, habe ich mich daran gemacht mtget zu überarbeiten. Die neue, für Linux Anwender besonders interessante, “HTML Version”, macht, da ohne Flash, die ZDF Mediathek nun erstmals halbwegs benutzbar. =)

Die asx-Links fürs mms streaming werden jetzt auch nicht mehr versteckt, so im großen und ganzen also ein ziemlicher Fortschritt. Für die Nerds unter euch die dennoch gern eine Shell-Lösung hätten, pflege ich mtget trotzdem weiter.
Bei der Gelegenheit habe ich mtget in Python komplett neu geschrieben. Version 0.5 kommt ohne zusätzliche Libraries aus, es müssen lediglich Python(bei mir läuft 2.6) sowie die in CMD_STREAM und CMD_DOWNLOAD eingetragenen Programme(per default: mplayer) installiert sein. In der neuen Version werden erstmals Kanäle erkannt und können im interaktiven Modus(-i) ausgewählt werden, andernfalls wird ihnen automatisch gefolgt und die Einträge abgespielt. Anders als die vorigen Versionen lädt 0.5 nur die mms-Streams. mtget.py:

mtget.py: Interaktive Auswahl der Videos und Kanäle

mtget.py: Interaktive Auswahl der Videos und Kanäle

ZDF Mediathek Download/Streaming Skript
v0.5 <apoc@sixserv.org> http://apoc.sixserv.org/
Stand: 2009-12-20

Syntax: ./mtget.py <URL/ID> [OPTIONS]
  <URL/ID>                   mediathek video/kanal url oder id
  -1                         qualitaet DSL 1000
  -2                         qualitaet DSL 2000 (Standard)
  -m, --mode <d/s>           download(d) oder streaming(s)
  -d, --dir <directory>      das verzeichnis wohin gespeichert werden soll(.)
  -t, --title                benutzt nicht den stream dateinamen sondern titel
  -s, --search <topic>       suche in der mediathek
  -l, --maxr <max>           wieviele ergebnisse verarbeiten(suche/kategorie)
  -c, --ignore-channel       ignoriert kanaele
      --no-colors            deaktiviert die kursiv und fettschrift
  -i                         interaktiv, auswahl der zu spielenden videos
  -v                         erweiterte ausgabe, zu debugging zwecken
  -h, --help                 zeigt diese hilfe

Mir sind übrigens noch zwei weitere Projekte bekannt die ebenfalls Mediathek streaming bieten: mtscrape und zdfmediathk.

Für Vorschläge, Bugreports und alles andere hinterlasst mir ein Kommentar oder schreibt eine eMail an apoc@sixserv.org!

Tagged: , ,

Content Extraction Algorithmen: Density/CCB

by apoc · november 9 2009 · leave a comment

Im Artikel, “Web scraping mit Ruby/Mechanize” zeigte ich wie man Webseiten von einem Ruby Skript laden lässt und definierte Inhalte daraus extrahieren kann. Diese Verfahren, z.B.: Regular expression, XPath oder CSS Selektoren, funktionieren nur für Seiten deren Struktur während der Implementierung bekannt sind. Diesmal allerdings geht es um Algorithmen die den Hauptinhalt(z.B. den Text einer Nachricht) von jeder beliebigen Seite erkennen und extrahieren können. Diese Möglichkeit ist vor allem für Suchmaschinen/Datamining oder für Anwendungen die die Lesbarkeit erhöhen wollen, z.B. für kleine Bildschirme(Handhelds) oder Screen Reader, interessant.

Auch wenn es ein recht neues Forschungsfeld der Informatik ist, gibt es schon einige Veröffentlichungen zu dem Thema. Für den Einstieg am Interessantesten ist wohl die Dissertation von Thomas Gottron, “Content Extraction: Identifiying the Main Content in HTML Documents“, die einen Überblick über die Algorithmen gibt, eine Möglichkeit der Evaluation beschreibt und einige neue Algorithmen einführt. Das erfolgversprechendste dieser Verfahren, der CCB(Content Code Blurring) Algorithmus ist auch Thema dieses Artikels.

Einen weiteren interessanten Ansatz liefern Arias Moreno, Deschacht und Moens in Ihrem Paper “Language Independent Content Extraction from Web Pages” deren Verfahren(Density) hier auch besprochen wird.

Natürlich kann man von keinem der Algorithmen Perfektion erwarten, dafür sind die Webseiten zu unterschiedlich strukturiert. Auch will ich nicht vergessen zu erwähnen das diese Algorithmen nur auf Seiten mit klar erkennbarem Hauptinhalt(Main Content) funktionieren, Weblogs z.B. verwirren so gut wie alle Verfahren die darauf Basieren die höchste “Text Konzentration” auf einer Seite zu finden, da die Kommentare unter dem Artikel nicht selten wesentlich umfangreicher als der Hauptinhalt sind(z.B. Slashdot).

Content Code Blurring (Python Skript / Modul)

Der CCB Algorithmus von Thomas Gottron stellt ein Verfahren dar, um die Teile einer HTML-Seite zu identifizieren die aus viel Text und nur wenigen Tags besteht. Dazu wird die Seite in eine Sequenz aus Tokens oder Zeichen aufgeteilt: Die TCCB Variante teilt die Sequenz in Tokens aus Tags oder Wörtern ein, sonst werden Zeichen unterschieden die sich innerhalb(Code) oder außerhalb(Inhalt/Content) eines Tags befinden. Der so entstandene Content Code Vektor(CCV) speichert für jeden Code ein 0 und für jeden Inhalt eine 1.

Jetzt wird der CCV verwischt(Blurring) dazu wird ein Gaussian Blur Filter verwendet, der im Prinzip einer Gaussian Distribution/Normal Distribution entspricht. Anders gesagt werden die Inhalts(1)-Elemente des CCV auf ihre Nachbar-Elemente verstreut oder verwischt. Dieser Vorgang wird n-mal wiederholt oder bis sich der Prozess normalisiert hat(wobei ich es leider nicht geschafft habe das zu implementieren(kA. woran das liegt, GERNE FEEDBACK!)). Meine Beispielimplementierung kann ein Diagramm des CCV “plotten”:

Dieser Plot zeigt, dass man schon auf der richtigen Spur ist. Klar erkennbare Spitze wo der Hauptinhalt liegt.

Dieser Plot zeigt, dass man schon auf der richtigen Spur ist. Klar erkennbare Spitze wo der Hauptinhalt liegt.

Am Ende werden die Teile des CCV welche über einen bestimmten Schwellwert liegen mit ziemlicher Sicherheit zum Hauptinhalt der Seite gehören. (Im Diagramm sehr leicht zu erkennen.)

Der CCB Algorithmus funktioniert sehr gut und gilt als einer der besten Algorithmen für Content Extraction überhaupt. Ein Nachteil besteht darin das Teile der Seite die ebenfalls viel Text enthalten mitunter zum Hauptinhalt gezählt werden, auch wenn sich diese Bereiche weit entfernt vom eigentlichen Inhalt befinden.

Density (Ruby Beispiel)

Der Density Algorithmus von Arias Moreno, Deschacht und Moens folgt einem ähnlichen Ansatz, die HTML-Seite wird durch einen (möglichst robusten) XML-Parser geparsed. Dann wird jeder (XML-)Node des Dokuments der Text enthält an den letzten String eines Arrays angehängt. Handelt es sich bei dem Node um einen HTML-Tag der die Struktur des Dokuments verändert(z.B. p, table, br, div, h1-6, li usw.) wird das Array um einen leeren String erweitert.

Wurde dieses Array fertig erstellt, wird ein Algorithmus angewandt, der den Bereich mit der größten Textdichte im Array zu bestimmen versucht(siehe Paper). Am Ende wird das Array nur noch sortiert und das Ergebnis steht als Plaintext fest.

Density arbeitet in der Praxis sehr gut, jedoch wird das Ergebnis sehr stark von den beiden Parametern beeinflusst, die den Algorithmus zum erkennen des Bereichs einstellen(besonders wieviele Absätze am Stück erkannt werden).

Update: Ich habe eine Implementierung für Density in Ruby eingefügt, er versucht den Hauptinhalt dieses Artikels zu extrahieren :)

Tagged: , , ,