How Anonymous Are The Party Poker Anonymous Tables?

How Anonymous Are The Party Poker Anonymous Tables?

Over the past year or so there seems to have been a growing movement for anonymous heads up tables, and currently they are offered by Party Poker, IPoker, OnGame and some other poker sites.

Just how anonymous are these tables and have the poker sites properly implemented this feature? Were anonymous tables not implemented correctly, a few players could bypass the restrictions and gain a very unfair edge of their opposition.

Over a year ago the following post showed up on twoplustwo regarding PTR apparently being able to track who is playing on anonymous tables. Apparently the issue was fixed sometime in March, but knowing online poker “security”, we figured it wouldn’t hurt to take a second look. Unfortunately after around 4 hours of investigation it was clear that the “anonymous” tables don’t live up to their name and it’s not difficult for someone who knows what they are doing to find out player’s screen-names.

We have emailed Party Poker about this exploit and will post our future correspondence with them. At this point in time we are not going to open-source or give away exactly how we get past it, but this is something that we feel Party Poker should fix. Right now Party Poker anonymous tables are only anonymous when nobody tries to bypass the restrictions – not a safe assumption when money is at stake.

Nothing to see here!

Pay no attention to the man behind the curtain…he’s anonymous…really…

So there is your answer, Party Poker anonymous tables are not really very anonymous after all. We’ll be investigating other sites in the future – Party Poker is probably not the only one that hasn’t implemented anonymous tables properly.

Warning! Computer Programmer Jargon Ahead!

So how could a player go about writing a program like this? Currently all the data is being sent from the server to the client so an attacker really has their pick of the options, and we’ll be talking about each of these.

  • Manipulating the Client
  • Reading the Information from Memory
  • Monitoring Client-Server Traffic

This first article will be a fairly shallow look at each of these techniques. If there is sufficient interest shown we’ll write further blog posts elaborating different techniques / general client reverse engineering. That being said, if you have experience with reversing binaries with IDA Pro you probably could come to these conclusions yourself after some investigation.

Manipulating the Client

One of the issues with how Party Poker handles anonymous tables is that the logic throughout the client in numerous places looks like:

if ( pokerTable.isAnonymous() )
 {
 //Display the neutered version of a table, Player 1 & Player 2 etc.
 DisplayAnonymousTable();
 }
 else
 {
 //Display a table normally
 DisplayNormalTable();
 }

This kind of control logic should not be in the hands of the poker client. Novice software crackers can take a statement like this and remove the anonymous check thus turning every table into

DisplayNormalTable();

Alternatively one could modify the program so that whatever logic determines pokerTable.isAnonymous() returns false. This is essentially how the program we demoed in our video works.

Either of these effects can be implemented by injecting a DLL into the the Party Poker process and then hooking the right functions. Anyone interested in being able to write code that does something like this should have a look around google with search terms like “detours hooking a function” or “c++ function hook”. Coding the Wheel also has written some excellent material describing some examples of API hooking (http://www.codingthewheel.com/archives/how-i-built-a-working-online-poker-bot-6). It is worth noting that only using API hooking will require some additional creativity to have the same effect as function hooking.

We’ll wait a bit before giving away additional details for finding these if statements. We’d like to give Party Poker the benefit of the doubt, and say they might try to fix this before we give away the exact details of what function to hook. That being said, if you know your way around IDA Pro or OllyDbg these if statements aren’t terribly hard to find.

Reading the Information from Memory

Even if Party Poker used a more clever mechanism to prevent anonymous tables from being de-anonymized, the real player names are still stored in the program’s memory. Basic Win32 calls like ReadProcessMemory (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680553(v=vs.85).aspx) make it trivial for a program to sneak a peek at the 0s and 1s of anything running on the same machine. FreePHG uses this sort of technique in order to read hands in progress and write them to disk. The very brief description of how this works is that a program reads the process memory and then uses patterns / known static addresses to find data structures in the memory which determine table state.

If you take a memory analysis program like Memory Hacking Software and use it to open a running Party Poker application, you’re going to be looking at a ton of random garbage. Once you have a general idea of what you’re looking for, however, you can start making educated searches around the client memory looking for a representation of a table in memory (look for things like table names, player names, etc.). There’s a lot more to talk about here with regards to pointers, structures, arrays, how different compilers allocate memory, and a ton of other details, but we’ll save that for another blog post. In a very very simplified nutshell (really, this isn’t remotely close to what Party memory looks like, but it should give you an idea) here’s a basic picture of what you can find in Party Poker:

Nothing to see here!

There are two key things to take away from this:

1) Tables ALWAYS have the relevant player data filled in somewhere in memory. Even if a table is anonymous, the proper player name is floating around somewhere waiting to be read, and you CAN find this information if you know where to look.

2) The Table object in memory simply has a flag which is set to 1 when the table is anonymous, and 0 when it’s not. This is the only major difference between an anonymous table and a normal table. Nothing is hidden, encrypted, changed, or obfuscated.

If you’re going to try reading the memory looking for tables based on this information alone you’re going to have a very long journey ahead of you. Exploring around GameTable.dll in the PartyPoker folder with a binary analysis program of some sort (IDA Pro) is going to save you a great deal of time.

Monitoring Client-Server Traffic

Now let’s say that Party Poker has actively eradicated every place in memory where it stores a player name – they use some sort of crazy memory shifting technique where nothing stays in place for any reasonable amount of time and the memory is un-mappable. (This isn’t really possible, but let’s pretend it is.) There’s still a fundamental flaw in how Party Poker handles anonymous tables: anonymous players aren’t obfuscated by the server in client-server communications. This is at the root of why the other attacks listed are possible – the real player names and ids are still used for identifying who performs actions in game communications.

Let’s pretend that Mike and Jeff are playing at Heads Up Anonymous Table #12415. In a proper anonymous setup the Party Poker servers would have some sort of mapping so that they know who Player 1 at Anonymous Heads Up Table #12415 is. Then communication could look something like:

Player 1 @ Anon Table #12415 bets $13.37.
Player 2 @ Anon Table #12415 folds.

The party servers would know that “Player 1 @ Anon Table #12415” is Mike, and “Player 2 @ Anon Table #12415” is Jeff, but neither Mike or Jeff would know who the other player is by examining the socket traffic. As things stand right now the communication is more like:

PartyPokerCommunication 300x105 PartyPokerCommunication

The real player’s name is in the traffic from the Party Server to the poker client. In this situation Jeff could examine the messages his machine had been sent, see that the bet was from Mike, and then use a host of tools to help him make a decision.

This kind of information can be captured or examined by using a man in the middle proxy (partially detailed, with some good details about SSL at http://www.criticalsecurity.net/index.php/topic/30089-decrypting-a-wireshark-capture-with-ssl-traffic/) or by just hooking the ssl_write/ssl_read functions in the program so you can tell what the client is sending/receiving before they have been encrypted. Alternatively there is software for this kind of listening like oSpy (http://code.google.com/p/ospy/).

Of course this doesn’t really address the additional work needed to reverse the actual protocol – which is no easy task. The general rule of thumb with security, however, is that you want the effort of breaking the security to outweigh the benefits. When we’re talking about online poker where the slightest edge could be worth serious money at higher stakes, it has to be expected that someone might try an attack like this.

Conclusions

We’re only really scratching the surface of how a properly determined coder can turn a bug into a possibly game changing advantage. We’ll be discussing these sorts of techniques in more detail in future blog posts along with releasing information and tools that players can use to help protect themselves from clients which go above and beyond reasonable means to stop attackers. Would love to here your thoughts in the comments below.

hhSmithy is the leader in hand history subscription sales. We offer Party Poker, PokerStars, Merge Gaming, iPoker, and OnGame hand histories in both bulk orders and subscriptions. We price match everyone out there and provide the best support to our customers. Buy poker hand histories today.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>