Memory Debugging or a “Universal Game Trainer” with Python and ptrace
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: debugging, Development, Linux, ptrace, Python
Dynamic Loading of SDL
If you want to use the SDL library (or any other library for that matter) in your programs, you normally would just link with the library, for instance by -lSDL (GCC). Sometimes however, it would be more flexible to dynamically load the library at runtime. With dynamic loading, if your application supports alternative libraries (e.g.: GLUT SFML as an replacement for SDL), it can discover and use available libraries at runtime. The system your program is running on, just needs one of those libraries installed and can switch them without the need to recompile your program. This technique is probably most commonly used to load plugins into programs at runtime.
Theres a helpful Wikipedia article about Dynamic loading, they even describe how to load the SDL library in their examples. Besides that, theres an old discussion about that at lists.libsdl.org and an article at eaten by a grue (when good libraries go bad). However I didn’t find a complete example implementation for this, so I’m trying to create one with this article, although I’m not a very experienced C++ programmer.
The first thing to do is to load the library file, on POSIX/UNIX systems we do this with dlopen(), on windows we use LoadLibrary() and for closing dlclose() and FreeLibrary() respectively. The following code snippet for open/closing the library should work on both Linux and Windows systems:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #ifdef _WIN32 #include <windows.h> #else #include <dlfcn.h> #endif // [...] #ifdef _WIN32 HMODULE libhandle; libhandle = LoadLibrary("SDL.dll"); #else void *libhandle; libhandle = dlopen("libSDL.so", RTLD_LAZY); #endif // ... dlsym() and GetProcAddress() calls ... #ifdef _WIN32 FreeLibrary(libhandle); #else dlclose(libhandle); #endif |
You need to link your programs to the dl library for this to work (such as -ldl in gcc).
The returned handle can be used to retrieve symbol addresses and then to convert them to function pointers. Theres dlsym() on POSIX and GetProcAddress() on Windows machines. The following code does that cross-platform for SDL_SetVideoMode():
1 2 3 4 5 6 7 8 | SDL_Surface * (*p_SDL_SetVideoMode)(int, int, int, Uint32); #ifdef _WIN32 p_SDL_SetVideoMode = (SDL_Surface * (*)(int, int, int, Uint32)) GetProcAddress(libhandle, "SDL_SetVideoMode"); #else p_SDL_SetVideoMode = (SDL_Surface * (*)(int, int, int, Uint32)) dlsym(libhandle, "SDL_SetVideoMode"); #endif |
You need to look at the header files (/usr/include/SDL/SDL_video.h) for the exact declaration (return and parameter types).
Theres a problem here, when casting from an void pointer that is returned by dlsym() to a function pointer which is prohibited by the C/C++ ISO standards. I’m using a simple explicit (C-style) cast here and in practice, I not even encountered a warning with modern compilers.
Johan Petersson has written an article (When standards collide: the problem with dlsym) about that problem in Scatter/Gather thoughts, I want to quote:
You probably noticed that I omitted the C-style cast from my earlier example. Alas, most C and C++ compilers will allow the conversion when you use a C-style cast. You may not even get a warning, even though it’s prohibited in ISO C as well as ISO C++. This kind of conversion is a common compiler extension. So common, in fact, that many people don’t realize it’s not in the standards.
The article is from 2004, I don’t know if the current C/C++ standards had changed any of that.
In the last code snippet theres an redundancy that can be resolved by using a typedef instead:
1 2 3 4 5 6 7 | typedef SDL_Surface * (*Type_SDL_SetVideoMode)(int, int, int, Uint32); Type_SDL_SetVideoMode p_SDL_SetVideoMode; #ifdef _WIN32 p_SDL_SetVideoMode = (Type_SDL_SetVideoMode) GetProcAddress(libhandle, "SDL_SetVideoMode"); #else p_SDL_SetVideoMode = (Type_SDL_SetVideoMode) dlsym(libhandle, "SDL_SetVideoMode"); #endif |
Thats everything you need to call that function: (p_SDL_SetVideoMode)(...); The major problem here is that SDL has over 200 functions that “must” be declared and addressed this way. I’ve written a ruby script for Linux that does that for the SDL headers within /usr/include/SDL, at first it reads the symbol names directly from the libSDL.so shared library utilizing nm, then it parses the header files for the function declarations found by nm and generates the code for the pointer declaration and explicit casts (/dlsym calls) automatically.
I’ve created some example code that defines an abstract class DLLoader and an implementation DLLoaderSDL that includes an struct with the automatically generated function pointers etc. The test program loads the library and shows a SDL window for 3 seconds.
I’ve tested the program with GCC 4.5.0 (Linux), GCC 3.4.5 (Windows MinGW) and CL 14.0 (Windows VC++). I also added Makefiles for each of those compiler suites.
JavaScript: onMouseMove Google Translation
I wanted to implement a JavaScript onMouseMove Event, that translates the word under the mouse pointer with the Google Translator. I want to share the following solution.
I split this into the following two separate problems:
First: Detect word for an onMouseMove Event
The onMouseMove Event can listen on any Element for mouse movements. To detect the word under the mouse pointers position, I utilize the W3C(DOM-2) specified Range Object.
Most modern browsers support the Range object, but the event.rangeParent Attribute seems to be only supported by Firefox. Currently I’ve no cross-browser solution for this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | /** * Apply offset to range and extract a single character at position. * * range -- the range object effected * originalOffsetStart, originalOffsetEnd -- Start offsetStart and offsetEnd * offset -- the relative offset to apply */ function getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, offset) { var character = ' '; try { range.setStart(range.startContainer, originalOffsetStart + offset); range.setEnd(range.startContainer, originalOffsetEnd + offset); character = range.toString()[0]; range.setStart(range.startContainer, originalOffsetStart - offset); range.setEnd(range.startContainer, originalOffsetEnd - offset); } catch (e) {} return character; } /** * Returns a single word for the given event. */ function getEventWord(evt) { if (!evt.rangeParent || !document.createRange) { return ''; } var range = document.createRange(); range.setStart(evt.rangeParent, evt.rangeOffset); range.setEnd(evt.rangeParent, evt.rangeOffset); // the word ends when this characters appears var stop_character_pattern = /^[\W]$/m; // this "overwrites" some characters from the above pattern var ignore_stop_character_pattern = /^['|\-]$/; // I assume startOffset == endOffset so set 1 character selection ... var originalOffsetStart = range.startOffset; var originalOffsetEnd = range.startOffset + 1; try { // test: range.setStart(range.startContainer, originalOffsetStart); range.setEnd(range.startContainer, originalOffsetEnd); } catch (e) { // out of bounds originalOffsetStart -= 1; originalOffsetEnd -= 1; range.setStart(range.startContainer, originalOffsetStart); range.setEnd(range.startContainer, originalOffsetEnd); } // First Step: Find left end of word: var leftCharacterPos = 0; var iChar = ''; for (var iOffStart = 0; iOffStart <= originalOffsetStart; iOffStart++) { iChar = getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, -1 * iOffStart); leftCharacterPos = iOffStart; if (stop_character_pattern.test(iChar) && !ignore_stop_character_pattern.test(iChar)) { // remove the stop character! leftCharacterPos -= 1; break; } } leftCharacterPos = originalOffsetStart - leftCharacterPos; // Last Step: Find right end of word: var rightCharacterPos = 0; for (iOffStart = 0; true; iOffStart++) { iChar = getRangeCharacter(range, originalOffsetStart, originalOffsetEnd, iOffStart); if (stop_character_pattern.test(iChar) && !ignore_stop_character_pattern.test(iChar)) { rightCharacterPos = iOffStart - 1; break; } } rightCharacterPos = originalOffsetEnd + rightCharacterPos; try { range.setStart(range.startContainer, leftCharacterPos); range.setEnd(range.startContainer, rightCharacterPos); } catch (e1) { range.detach(); return ''; } var retWord = range.toString(); range.detach(); return retWord; } |
Second: Translate Text with Google Translator
This is very easy because Google provides an very easy to use Ajax API for this (attend the possible google user tracking!):
1 | <script type="text/javascript" src="http://www.google.com/jsapi"></script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | // read onMoveTranslate() var last_word = null; var timeout = null; var word_cache = []; /** * Translate text For onmousemove events. */ function onMoveTranslate(event) { // get element the translation should appear in: var translation = document.getElementById('translation'); var word = getEventWord(event); if (!word || word == '') { return; } if (typeof(word_cache[word]) !== 'undefined') { translation.innerHTML = word_cache[word]; //+" (cached)"; return; } if (word != last_word) { if (timeout) { window.clearTimeout(timeout); } translation.innerHTML = 'Translating ... ' + word; timeout = window.setTimeout(function(){ google.language.translate(word, 'en', 'de', function(result) { if (!result.error) { translation.innerHTML = result.translation; word_cache[word] = result.translation; } }); }, 800); } last_word = word; } google.load("language", "1"); |
At last I assign the onMouseMove Event to the onMoveTranslate() function:
1 | <div id="content" onmousemove="onMoveTranslate(event);"> |
Here is an full Example for this.
Tagged: Development, Event, JavaScript, onMouseMove
mtget: ZDF Mediathek Download/Stream
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
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: mediathek, Python, web scraping
Content Extraction Algorithmen: Density/CCB
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.
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
Zensursula: Teil 2 – Cleanfeed, DNS, DPI
Die mit Lügen und Erpressung der Provider gegen alle Vernunft durchgepeitschte, grundgesetzwidrige unkontrollierbare deutsche Zensurinfrastruktur wird gerade vom “zuständigen” BKA in aller Heimlichkeit geplant und wird genauso heimlich von den Providern implementiert werden. Das die erstmals angedachten DNS-Sperren vollständig wirkungslos sind, darüber sind sich wohl alle einig, genauso eindeutig ist es wohl das die DNS-Sperren nur den Einstieg hin zur Schaffung eines ausgefeilten Zensursystems mit Vorbild der Great Firewall of China sein wird. Schon jetzt vermuten einige das ein Cleanfeed Modell nach britischen Vorbild geplant ist.
Die Befristung auf 3 Jahre hilft natürlich auch nicht, entweder nach 3 Jahren stellt sich heraus, das es nur wenig gegen “Kinderpornographie” geholfen hat, dann muss noch mehr und tief greifender gesperrt werden, oder die Verbrechensstatistik (die im übrigen ohnehin vom BKA “erstellt” wird) geht zurück, dann war es ein Erfolg und muss genauso weitergeführt werden.

Cleanfeed - Bildquelle: Wikimedia Commons
Das Cleanfeed System wird von Providern in England eingesetzt um z.B.: bestimmte Wikipedia Artikel zu blockieren. Welche wahrscheinlich regimekritischen Seiten noch so alles gesperrt werden weiß man natürlich nicht, da die geheimen Listen(der IWF), natürlich nicht unabhängig kontrolliert werden. Cleanfeed filtert nach der IP und URL, was durch eine Kombination aus konventionellen IP-Filtern und Proxy-Servern ermöglicht wird. Zunächst wird der Traffic nur nach IP-Adressen gefiltert, bestimmte Verbindungen werden schon hier blockiert, andernfalls wird der fragwürdige Traffic durch ein Arsenal an transparenten Proxy-Servern geleitet(Man-in-the-middle-Angriff auf HTTP) die mit einer Blacklist ausgerüstet bestimmte URLs blockieren.
In China z.B. wird noch einen Schritt weiter gegangen, so wird jedes IP-Paket von DPI-Hardware genau untersucht, enthält es unerwünschte Suchbegriffe oder Inhalte wird von dem zensierenden Backbone TCP-RST-Pakete gesendet, die so die fragliche TCP-Verbindung sofort beendet. So implementiert die chinesische Suchmaschine Baidu dies bereits auf Server-Seite. Wer auf Baidu.com nach “Falun Gong” sucht, dessen Verbindung wird für einige Minuten gesperrt.
Beim Deep Packet Inspection wird jedes vorbeikommende Paket auseinandergenommen, so kann beispielsweise festgestellt werden ob es sich um eine HTTP Verbindung handelt und welche URL angefordert wird oder welche Daten gesendet werden. Das allein ist natürlich ein krasser verstoß gegen die Netzneutralität sowie gegen jedes noch so aufgeweichtes Fernmeldegeheimnis. Zum Vergleich, das wäre wie wenn die Post jeden Brief unbemerkt öffnet und nach bestimmten Stichworten durchsucht. Wenn es schon unbedingt DPI seien muss, dann wenigstens Open Source, dachten sich wahrscheinlich die Entwickler des OpenDPI Projektes
Im letzten Zensursula-Artikel habe ich mich mit den DNS-Filtern beschäftigt, insbesondere wie man einen eigenen DNS-Cache-Server betreibt der die Zensur über DNS verhindert. Wie erwähnt handelt es sich dabei nur um den Einstieg, die Einführung von Cleanfeed/DPI kann die Zensur wieder akut werden lassen, selbst mit eigenem DNS-Server. Wie es technisch geht hat jüngst Vodafone in ihrem UMTS Netz gezeigt, sie fangen jede Anfrage über Port 53 ab und leiten sie an ihre eigenen DNS-Server weiter.
Das Einzige wirksame Mittel gegen diese fortgeschrittenen Zensur Bemühungen, ist es den eigenen Traffic möglichst zu verschleiern, im einfacheren Fall seinen Traffic verschlüsselt über Rechner im Ausland zu leiten, bspw. über HTTP oder Socks4/5-Proxy-Server. Die Meisten Zensur-Regime sperren deshalb ebenfalls bekannte Ausländische Proxy bzw. Anonymisierungs-Dienste(Socks, VPN-Dienstleister oder Tor-Nodes) auf IP-Ebene.
Mittlerweile gibt es eine ganze Flut von VPN-Providern die bezahlte Zugänge zu Ausländischen VPN-Servern bereitstellen, Ivacy war hier auch schon Thema. Explizit erwähnen will ich hier außerdem Perfect-Privacy die zwar etwas teurer sind, aber dafür sehr schnell und Zugriff zu über 20 weltweit verteilten Servern bieten.
Auf FileShareFreak und Daten-Speicherung.de gibt es Listen von VPN-Providern. Wem es statt einer Zensur zu umgehen, um wirkliche Anonymität geht, reichen diese Anbieter nicht aus. Nur ein Onion Routing kann wirkliche Anonymität gewährleisten, z.B.: Tor oder JAP/JonDo. Diese haben natürlich den Nachteil, extrem Langsam und unzuverlässig zu sein. Daneben gibt es mit Xerobank einen Bezahl-Anbieter für schnelles Onion Routing.
Update: Auf ZDNet gibt es einen guten Artikel darüber, wie weit die DPI-Manipulationen bei den UMTS-Anbietern, wie Vodafone mittlerweile gehen. (via Netzpolitik)
Tagged: Networking, privacy, security, vpn