Introduction
When I was nine years old, my uncle (who once caught a seven-foot hammerhead shark off a crowded Padre Island beach) taught me how to gut and clean a fish. It was a visual, hands-on introduction to the idea, pervasive in software development, that implementation details are messy. These days, I can hardly hear the word encapsulation without thinking about that fish. Anyone who's ever taken a biology class knows that one of the ways we learn how things (such as frogs) work is by dissecting them. Indeed, to analyze something is to take it apart; that's the root meaning of the word.
Anyway, today we're going to talk about how to gut (analyze) a different sort of fish.

I put the picture together in Photoshop, as a lark. Those of you who've read Exploiting Online Games: Cheating Massively Distributed Systems will recognize the four exploit vectors for modern client/server software: above, beneath, inside, and way outside. If you've been following the poker botting series, you've already played with some (basic, but hopefully illustrative) code that achieves a minor exploit along one vector or another. And of course, we use the word "exploit" but what we really mean is a reaffirmation of your basic electronic rights.
- The right to know exactly what a given third-party piece of software is doing on and to your machine.
- The right to run whatever software you like on your personal computer, provided it doesn't hurt or defraud someone.
- The right to aggressively defend your property and your privacy against an army of spyware, adware, and other classes of malware.
Most online gambling software (not just online poker; I mean the entire online money gaming industry) can technically be classified as spyware.
Spyware is computer software that is installed surreptitiously on a personal computer to intercept or take partial control over the user's interaction with the computer, without the user's informed consent.
These programs, operating without oversight under the broad umbrella of "game integrity", and propped up by draconian, completely unenforceable EULAs, scan and monitor your system for a hundred and one telltale clues. They install browser add-ons without your express permission. They scan your list of running processes. They perform full-text, key-by-key searches through your Registry. They touch foreign directories on the local filesystem. They take screenshots. And so forth.
Hello, Big Brother.
Whether or not these techniques are justified for fraud prevention and/or operational efficiency is a discussion we can have when the online gambling sites stop trying to sneak these techniques in through the electronic back door. Just because we mindlessly click the "I Accept" button on the software EULA does not give a fly-by-night, often dubiously legal online casino (which would quickly go bankrupt without our patronage) a carte blanche to do whatever the hell it pleases to your machine, across international waters no less.
Call me crazy, but I still believe in electronic privacy. And so should you.
Fighting Back
Today and in future installments we're going to talk about how to spy on the software that spies on you. In today's article, you'll find a handful of basic techniques, some of which you'll probably be familiar with. In future installments, we'll progress to full-on disassembly of online gaming client source code. We're interested in three things:
- How to figure out what kinds of data a given online poker/gambling client is reading or depositing on your machine.
- How to protect your privacy by hiding or obstructing access to this data.
- How to publicize this information so that it reaches the casual player.
The online gambling industry has proven repeatedly that it's not capable of regulating itself. Whether it's the Ultimate Bet and Absolute Poker super-user scandals, the seizing of player deposits (anyone remember PokerSpot?), the arrogance and dismissiveness of online gambling support staff, or the generally shoddy state of modern gambling software, the industry is due for a large and painful correction.
So without further ado, here are some basic "software reconaissance 101" techniques that every poker player, and certainly every poker programmer, should know about. Consider it self-protection.
Monitoring Your Local Filesystem
In How I Built a Working Online Poker Bot, Part 6: Guerilla-Style File Monitoring, we talked about how to build a simple Windows file monitor: a small application which tracks, in real time, the files opened, written, and read by a particular application (in our case, an online poker client application). That was useful from a poker botting perspective, because online poker clients typically write relevant game information to hand history files and log files. But this sort of thing is also useful from a privacy perspective: because of all the ways in which software applications violate your privacy, two of the most common are:
- By depositing cookies, unique IDs, and other identifying cruft on your hard drive.
- By scanning and perhaps opening the files present on your hard drive.
The only problem with the custom file monitoring approach is that it requires you to write some code. Not everybody is a programmer, and not every programmer has the time or the inclination to write code to investigate what may or may not be a privacy violation. So what we want is a free, easy to use, and robust tool that can monitor file accesses generically, for any application on the machine.
The freeware SysInternals Process Monitor, formerly known as FileMon, is just such a tool. Let's open up the Ultimate Bet and Full Tilt poker executables and see if we can turn up something interesting.
Well, okay. I'm cheating a bit. I've already blogged (just a few minutes ago) about ieSnare, a piece of pseudo-spyware which online poker sites use to track machine identities. So nothing new here. But the point is, when confronted with an unknown third-party application for which you have zero source code, one of the best things you can do is run it with file monitoring in place. You're looking for anything out of the ordinary. When you find something out of the ordinary, Google it. Then blog about it. Complain. Post it in the forums. Or leave me a comment and I'll blog about it. Or head over to pokerai.org and start up a thread.
It's that simple.
Viewing (and Modifying!) Embedded Resources with Visual Studio
Windows applications often ship with embedded resources: images, string tables, dialog layouts, icons, etc. An embedded resource is any resource which is placed inside a binary executable file such as an .EXE or a .DLL. Embedded resources are public. We can see a list of the resources embedded within a particular file by opening that file in an application that understands how to view embedded resources. One such application is Visual Studio. Let's open the Full Tilt poker client executable (FULLTILTPOKER.EXE) and see what we find.

The Full Tilt development team, following common practice, makes heavy use of embedded resources. We can see accelerators, dialogs, icons, a manifest, and a version resource. Let's open up one of the dialog resources. Specifically, let's open the Full Tilt Login dialog in the Visual Studio designer. We don't have access to the Full Tilt source code, but it doesn't matter. And Full Tilt would probably prefer we don't go mucking around with their resources, but there is nothing illegal or unethical about examining the software which runs on your machine.

Although there's no text (the text will be filled in at runtime), you can see two edit boxes; one for the user name and one for the password. The dark gray areas are custom controls. Let's right click one of these custom controls and pull up its properties. (Yes, we can edit these controls and their properties, even though we don't have the Full Tilt source code.)

The highlighted control is a custom control of class FTCSkinButton. That, of course, is a window class, not a C++ (or other language) class. This is the same information you'd get if you launched Full Tilt and pointed Spy++ at the above dialog, which looks like this at run time:

A little-known fact is that you can edit binary resources of any application, with or without the source code. Let's go in and rearrange the Full Tilt login dialog, just because we can. We'll move some controls around and (using Copy/Paste) add a new button at the top of the window:

We can then launch the Full Tilt software, and we'll see our modified version of the login dialog. This dialog is fully functional, though it looks a little cockeyed. We've changed the locations of some of the controls and added a couple new ones, but otherwise everything works the same.

This is a little bit of software sleight-of-hand, perhaps not too useful in the grand scheme of things, but illustrative. Now let's look at another application: the Cake poker client (CAKE.EXE).

Here we see some some other resources: string table, type library, RCDATA. Let's open the string table resource, which is a way of storing strings without "hard-coding" them into application source code.

If you've ever used printf, these strings should make sense. The %s and %d symbols are printf-style formatting flags, used when compositing a string. Which means that if we were to install a detour around the printf family of functions (there are several varieties on Windows), we'd expect our detour to be called with some of the above strings. Your mental gears should now be churning.
Snooping on Windows with Spy++
Windows applications typically display one or more windows—such as a "lobby" window, along with a dedicated window for each table. Spy++ allows you to spy on those windows in real time via a handy graphical interface. Simply drag the "Find Window" crosshairs around the screen, and the window beneath the tool will be highlighted.

There are several kinds of information you should be looking for when using this tool. First, Spy++ tells you whether or not a given on-screen widget—a button, a listbox, an image—is backed by an actual Windows window. In the following screenshot of the PokerStars cashier window, there are exactly seven windows: the dialog itself, and each of the buttons ("Buy Chips", "Cash Out", etc.) along the right.

For each window encountered, Spy++ will give you some basic information, such as the window's class, it's handle, the address of its window procedure, and so forth. If we drag the Find Window crosshairs to the "Buy Chips" button (a button many of you will be familiar with) we get the following:

We can see at a glance that this is not a standard Windows button. A standard Windows button is always of class "BUTTON" whereas PokerStars buttons are of class "PokerStarsButtonClass". In order to make sense out of this, of course, you need to understand what a window class is, and how you'd go about creating a custom window class in code. But for now, suffice to say that once you know a window's class name you can programmatically search for that window using APIs such as FindWindowEx.
That's pretty handy, but the real power of Spy++ has always been its ability to snoop on window message traffic in real time. In order to do that, let's point Spy++ at a PokerStars table window.

If you squint, you can see that PokerStars table windows are of class PokerStarsTableFrameClass. So again, we're dealing with a custom window class. In the Find Window dialog box, check the "Messages" radio button and hit OK to view window messages received by the PokerStars table window:

If you've worked with window messaging before, most of these messages will make sense to you. We can see WM_PAINT, WM_TIMER; all the usual suspects. But if you take a closer look you'll see several non-standard messages:

These messages are custom window messages which have a special meaning for the PokerStars application. The meaning of messages like WM_PAINT and WM_TIMER is standardized across all windows. But registered and user-defined messages can have any meaning whatsoever. Once you know that these messages are being sent, it's a simple matter to a) inject a DLL into the PokerStars address space and b) subclass the PokerStars table window so that you can c) take an in-depth look at these messages and their parameters in code.
That's really the value of Spy++. It's not that the tool gives you so much useful information in and of itself; but it gives you a basic navigational awareness of the windowing and messaging behavior of a particular piece of software, which knowledge you can then use to decide what sort of investigative code to write: which windows to subclass, which message pumps to spy on, and so forth.
Viewing DLL Dependencies
As software developers, and especially as developers of poker botting software, we're very interested in the dynamic link libraries (DLLs) loaded by a particular application. We can examine these DLLs to determine what libraries and subsystems the application relies on, and we can (perhaps) use that knowledge to replace these libraries with our own customized versions. Even if we're not interested in this sort of "trojan horse" approach, we still want to know what DLLs the application is loading, as a matter of principle. There are a number of tools you can use to do this. One of my favorites is the Dependency Walker (DEPENDS.EXE).
Let's use it to track the DLLs loaded by the Cake online poker client:

Nothing out of the ordinary here. Cake is using a standard set of operating system DLLs, and you'll see that most poker clients follow a similar pattern. But once in a while, you'll stumble across something interesting. To illustrate, let's crack open the Full Tilt poker executable (FULLTILTPOKER.EXE):

Will wonders never cease. You see, in addition to tracking DLL dependencies, the Dependency Walker also extracts functions exported by a particular binary. These are functions intended to be called by other EXEs and/or DLLs. Above, we see a list of functions provided by the Full Tilt poker client, most of them prefaced with "FTCG" which is probably short for "Full Tilt Client Something". And you can infer the likely purpose of many of these functions from the name. In fact, with a little detective work, you could try to call these functions yourself or, better yet, detour these functions such that whenever Full Tilt code attempts to call one of them, your own code is executed instead.
This information is publically available, using run-of-the-mill development tools, so here's the full list of functions:
- void FTCG_LastHand_Header(struct HFTCGAME__ *,struct HFTCG_LASTHAND__ *,unsigned long,unsigned long,int,void (*)(unsigned long,int,wchar_t *,unsigned long,long),long)
- int FTCG_TableEx_Submit_Accept(struct HFTCG_TABLEEX__ *,unsigned long,unsigned char)
- CentsFromString
- FTCG_BuyIn_Create
- FTCG_BuyIn_Destroy
- FTCG_BuyIn_HasEnoughFunds
- FTCG_BuyIn_Init
- FTCG_BuyIn_Submit
- FTCG_Casino_Create
- FTCG_Casino_DCS_AdvCurrent
- FTCG_Casino_DCS_AdvInterval
- FTCG_Casino_DCS_Create
- FTCG_Casino_DCS_Current
- FTCG_Casino_DCS_Current2
- FTCG_Casino_DCS_ExitScreenCurrent
- FTCG_Casino_DCS_GeoCountryIx
- FTCG_Casino_DCS_ProChat
- FTCG_Casino_DCS_PromoCurrent
- FTCG_Casino_Destroy
- FTCG_Casino_Get_LobbyIxNext
- FTCG_Casino_Get_LobbyIxToLobby
- FTCG_Casino_Get_PlayerIx
- FTCG_Casino_Get_Stat
- FTCG_Casino_IsBelongLobbyIx
- FTCG_Chat_AddText
- FTCG_Chat_ConvertType
- FTCG_Chat_Create
- FTCG_Chat_Destroy
- FTCG_Chat_Get_Line
- FTCG_Chat_Get_LineInfo
- FTCG_Chat_Get_NextEvent
- FTCG_Chat_Get_NextEvent2
- FTCG_Chat_Get_PlayerIx
- FTCG_Chat_Get_TableId
- FTCG_Chat_Get_TournSummary
- FTCG_Chat_IsDisplay
- FTCG_Chat_IsPlayerNoteAvail
- FTCG_Chat_Submit
- FTCG_Create
- FTCG_Data_Get_HappyHour
- FTCG_Data_Get_MixedGames
- FTCG_Data_IsMoneyGram
- FTCG_Destroy
- FTCG_FormatError
- FTCG_Format_Comma
- FTCG_Format_Game
- FTCG_Format_GameURL
- FTCG_Format_Money
- FTCG_Format_MoneyW
- FTCG_Format_TableTitle
- FTCG_GetGeoCountry_Tmp
- FTCG_GetGeoState_Tmp
- FTCG_Get_GeoCountry
- FTCG_Get_GeoState
- FTCG_Get_PlayerInfo
- FTCG_Get_VersionConnect
- FTCG_IsMessage
- FTCG_LastHand_AddHand
- FTCG_LastHand_Create
- FTCG_LastHand_Destroy
- FTCG_LastHand_Footer
- FTCG_LastHand_Get_CardState
- FTCG_LastHand_Get_Count
- FTCG_LastHand_Get_FirstHand
- FTCG_LastHand_Get_Hand
- FTCG_LastHand_Get_PlayerActive
- FTCG_LastHand_Get_PlayerId
- FTCG_LastHand_Get_Winners
- FTCG_LastHand_Output
- FTCG_Legacy_UpdateStamp
- FTCG_ListView_CmpLobbyMixed
- FTCG_ListView_CmpLobbyTables
- FTCG_ListView_CmpProChat
- FTCG_ListView_CmpSatellite
- FTCG_ListView_CmpSitNGo
- FTCG_ListView_CmpTablePlayers
- FTCG_ListView_CmpTablePlayers2
- FTCG_ListView_CmpTableWaiters
- FTCG_ListView_CmpTourn
- FTCG_ListView_CmpTournTablePlayers
- FTCG_ListView_CmpTournTables
- FTCG_ListView_LobbyMixed
- FTCG_ListView_LobbyTable
- FTCG_ListView_LobbyTourn
- FTCG_ListView_ProChat
- FTCG_ListView_TablePlayer
- FTCG_ListView_TableWaiter
- FTCG_ListView_TournPlayer
- FTCG_ListView_TournTable
- FTCG_ListView_TournWaiter
- FTCG_Lobby_Create
- FTCG_Lobby_Destroy
- FTCG_Lobby_GetCached_Table
- FTCG_Lobby_GetCached_TableNext
- FTCG_Lobby_GetCached_TableTitle
- FTCG_Lobby_GetCached_Tourn
- FTCG_Lobby_GetCached_TournDetail
- FTCG_Lobby_GetCached_TournID
- FTCG_Lobby_GetCached_TournInfo
- FTCG_Lobby_GetCached_TournNext
- FTCG_Lobby_Get_Tourn
- FTCG_Lobby_Get_TournClose
- FTCG_Lobby_Get_TournGameInfo
- FTCG_Lobby_Get_TournNext
- FTCG_Lobby_Get_TournState
- FTCG_Lobby_Get_TournSummary
- FTCG_Lobby_Get_TournTitle
- FTCG_Lobby_Get_TournTokenPrize
- FTCG_Lobby_IsLoaded
- FTCG_Lobby_IsTableProChat
- FTCG_Lobby_IsTableRingGame
- FTCG_Note_Get
- FTCG_Note_GetPlayer
- FTCG_Note_Init
- FTCG_Note_Set
- FTCG_Note_SetIgnoreChat
- FTCG_Note_Submit_Metrics
- FTCG_Playback_GetText
- FTCG_Playback_Update
- FTCG_Player_Create
- FTCG_Player_Decrypt
- FTCG_Player_Destroy
- FTCG_Player_Encrypt
- FTCG_Player_GetCached_Balance
- FTCG_Player_Get_Address
- FTCG_Player_Get_AffiliateInfo
- FTCG_Player_Get_Avatar
- FTCG_Player_Get_Balance
- FTCG_Player_Get_BonusHappyHour
- FTCG_Player_Get_Bonus_OptIn
- FTCG_Player_Get_BuyInPrefs
- FTCG_Player_Get_DepositBonuses
- FTCG_Player_Get_DisconnectTime
- FTCG_Player_Get_Email
- FTCG_Player_Get_Language
- FTCG_Player_Get_Login
- FTCG_Player_Get_LoginFailure
- FTCG_Player_Get_Name
- FTCG_Player_Get_OfferPlayer
- FTCG_Player_Get_OptIns
- FTCG_Player_Get_ParamsURL
- FTCG_Player_Get_PlayerIx
- FTCG_Player_Get_PromoURL
- FTCG_Player_Get_SecureURL
- FTCG_Player_Get_Tables
- FTCG_Player_Get_TournRegistered
- FTCG_Player_Get_Tournaments
- FTCG_Player_Get_TransferHistory
- FTCG_Player_Get_Transfers
- FTCG_Player_Get_UserName
- FTCG_Player_IsAddressValid
- FTCG_Player_IsAllowTournRegister
- FTCG_Player_IsCountryValid
- FTCG_Player_IsEmailVerified
- FTCG_Player_IsExcluded
- FTCG_Player_IsNameValid
- FTCG_Player_IsPhone
- FTCG_Player_IsRightAvailable
- FTCG_Player_IsStatusAvailable
- FTCG_Player_IsTournRegistered
- FTCG_Player_IsTransferPending
- FTCG_Player_Redeem_GetCommission
- FTCG_Player_Submit_Address
- FTCG_Player_Submit_AddressName
- FTCG_Player_Submit_Affiliate
- FTCG_Player_Submit_Avatar
- FTCG_Player_Submit_BonusOptIn
- FTCG_Player_Submit_BuyInPrefs
- FTCG_Player_Submit_Chat
- FTCG_Player_Submit_Create
- FTCG_Player_Submit_Data
- FTCG_Player_Submit_Deny
- FTCG_Player_Submit_Deposit
- FTCG_Player_Submit_Disconnect
- FTCG_Player_Submit_Email
- FTCG_Player_Submit_EmailNotification
- FTCG_Player_Submit_EmailRequest
- FTCG_Player_Submit_EmailVerify
- FTCG_Player_Submit_Exclude
- FTCG_Player_Submit_Find
- FTCG_Player_Submit_Language
- FTCG_Player_Submit_Login
- FTCG_Player_Submit_Password
- FTCG_Player_Submit_PasswordRequest
- FTCG_Player_Submit_PasswordReset
- FTCG_Player_Submit_PlayReload
- FTCG_Player_Submit_PlayerExists
- FTCG_Player_Submit_Redeem
- FTCG_Player_Submit_RemoveAllWaitlist
- FTCG_Player_Submit_Store_BuyProduct
- FTCG_Player_Submit_TableDecline
- FTCG_Player_Submit_Transfer
- FTCG_Player_Submit_WaitingListAdd
- FTCG_Player_Submit_WaitingListRemove
- FTCG_Player_Submit_Withdraw
- FTCG_Player_Submit_WithdrawVoid
- FTCG_ProChat_Create
- FTCG_ProChat_Destroy
- FTCG_ProChat_Get_Info
- FTCG_ProChat_Submit
- FTCG_ProChat_Submit_End
- FTCG_ProChat_Submit_Leave
- FTCG_ProChat_Submit_Return
- FTCG_ProChat_Submit_Start
- FTCG_ProChat_Submit_Topic
- FTCG_ProcessObjectMessage
- FTCG_Reload
- FTCG_Set_Language
- FTCG_Set_Notification
- FTCG_Start
- FTCG_Stat_GetData
- FTCG_Stat_GetGameHiLo
- FTCG_Stat_NotifySet
- FTCG_Stat_Reset
- FTCG_Stop
- FTCG_Submit_System_ClientTracking
- FTCG_Submit_System_IESnare
- FTCG_TableCheckHappyHour
- FTCG_TableCreate
- FTCG_TableDestroy
- FTCG_TableEx_Create
- FTCG_TableEx_Destroy
- FTCG_TableEx_GetCached_CommunityCards
- FTCG_TableEx_GetCached_HandInfo
- FTCG_TableEx_GetCached_HandPlayers
- FTCG_TableEx_GetCached_HappyHour
- FTCG_TableEx_GetCached_Info
- FTCG_TableEx_GetCached_IsPlayerPro
- FTCG_TableEx_GetCached_IsWaiterPro
- FTCG_TableEx_GetCached_Players
- FTCG_TableEx_GetCached_TablePlayerInfo
- FTCG_TableEx_GetCached_WaiterPlayerInfo
- FTCG_TableEx_GetCached_Waiters
- FTCG_TableEx_Get_TitleInfo
- FTCG_TableEx_Get_WaitListState
- FTCG_TableEx_Submit_Bet
- FTCG_TableEx_Submit_BuyIn
- FTCG_TableEx_Submit_Chat
- FTCG_TableEx_Submit_Emotion
- FTCG_TableEx_Submit_Fold
- FTCG_TableEx_Submit_Leave
- FTCG_TableEx_Submit_Muck
- FTCG_TableEx_Submit_RequestTime
- FTCG_TableEx_Submit_Return
- FTCG_TableEx_Submit_Show
- FTCG_TableEx_Submit_Sit
- FTCG_TableEx_Submit_Stand
- FTCG_TableFTM
- FTCG_Time_GetServerTime
- FTCG_Time_SetTimeDiffProc
- FTCG_Tourn_Create
- FTCG_Tourn_Destroy
- FTCG_Tourn_Get
- FTCG_Tourn_Get_AllPlayers
- FTCG_Tourn_Get_BuyIns
- FTCG_Tourn_Get_GameNameInfo
- FTCG_Tourn_Get_Level
- FTCG_Tourn_Get_Levels
- FTCG_Tourn_Get_Payouts
- FTCG_Tourn_Get_PlayerTable
- FTCG_Tourn_Get_PlayerWaitStatus
- FTCG_Tourn_Get_SngTimeLeft
- FTCG_Tourn_Get_StackInfo
- FTCG_Tourn_Get_State
- FTCG_Tourn_Get_TablePlayerInfo
- FTCG_Tourn_Get_TablePlayers
- FTCG_Tourn_Get_TournIxRef
- FTCG_Tourn_Get_Winner
- FTCG_Tourn_IsFreeroll
- FTCG_Tourn_IsPlayerPro
- FTCG_Tourn_IsRegistered
- FTCG_Tourn_IsTablePlayerPro
- FTCG_Tourn_IsTablePro
- FTCG_Tourn_IsTableValid
- FTCG_Tourn_IsTwoBlinds
- FTCG_Tourn_SetTable
- TCG_Tourn_Submit_BuyIn
- FTCG_Tourn_Submit_Rematch
- FTCG_Tourn_Submit_Withdraw
- FTCM_Browser_Attach
- FTCM_Browser_GetFormData
- FTCM_Browser_InsertHTML
- FTCM_Browser_InsertURL
- FTCM_Browser_Resize
- FTCM_Browser_UnAttach
- _WndProcHTML@16
Eureka! That's quite a laundry list. Maybe the Full Tilt development team will hide these exports at some point so we don't have to stare at them.
Monitoring Your System Registry
Whether you're a programmer or not, you've heard of the Windows Registry: a massive database of operating system and application data and metadata, used to store everything from COM object registrations to user settings. I am here to tell you that many applications (and online poker clients specifically) quite simply do not respect your privacy when it comes to the Registry. A software application can infer a LOT about you and your machine by examining the Registry, and yet, you'll find that companies, by and large, feel they have the right to do whatever sort of snooping your Registry they desire.
What you need is oversight: the ability to determine what data an application is reading from, and writing to, your Registry. If you've been following the botting series, you already know how to detour the Registry APIs and insert your own logging code to determine what registry keys are being read and written. But you needn't write code to do this; you can also use a tool like the SysInternals Process Monitor, formerly known as RegMon.
Let's open up the PokerStars executable (POKERSTARS.EXE) using the Process Monitor, and filter out everything except registry-related accesses:

Well, we can see that PokerStars is a busy bee. Indeed, if you run the registry monitor against five or six online poker clients, I think you'll be surprised at just how busy they are. What are they reading and to what end?
Viewing Embedded Strings with a Hex Editor
When you use string literals in code...
{
string encryptionPassword = "SuperSecretPassword";
encrypt_something(encryptionPassword);
}
...those string literals are (by default) embedded in the final executable (whether EXE or DLL) you produce, and can be read by anyone with a decent hex editor.
Now, there are a ton of hex editors available for Windows and other operating systems, and they all work roughly the same: by presenting an unobstructed view of the byte-by-byte data of a particular file (could be a data file, could be an executable file, could be a text file). Typically, you'll see the raw data presented in hexadecimal notation in one column, and in another column, you'll see what the data looks like when you try to interpret it as text character data. Note that some (most) numeric values have no printable character equivalents, and for these you'll see a dot or other symbol.
To illustrate, let's open up the PokerStars client (POKERSTARS.EXE) inside the freeware HEdit hex editor.

We can see various embedded strings, some of which leak implementation details. We notice a C++ source file, formathistory.cpp. We see various internal and external messages. We see various printf format specifiers, and so forth. There are no hard and fast rules about what to look for when you crack open a particular application in a hex editor. Typically, you'll be looking for strings which give you clues as to the application's implementation. With a little detective work you can also identify meaningful non-string data; but in order to do so, you'll probably have to perform some basic disassembly and/or instrumentation in order to figure out that X piece of data exists at Y memory location which corresponds to the Zth byte of the application's executable file. You can then go in and modify that particular byte and produce behavior which is different from what the original developers intended.
I'm not going to explain how to "crack" legitimate commercial software, but suffice to say this is where it begins: by understanding that software integrity is a myth, AT LEAST ON THE CLIENT SIDE. Every byte of every of every application is public, both on disk and later, when loaded into memory. You can't hide the underlying binary instructions from themselves. You can't hide the hard-coded strings, the resources, the data structures these instructions use. The best you can do is obfuscate.
Conclusion
Today we covered the easy stuff: the low-hanging fruit. Later we'll talk about disassembling, debugging, and full-on instrumentation of poker client software. We'll look at encrypted socket connections, and we'll look at how to hook client-side decryption/encryption routines, not that it will do us a whole lot of good. And as a bonus, we might even talk about how to figure out what those pesky browser add-ins (you know, the ones that have access to every web page you visit and every form you fill out including credit card forms) installed by the poker sites actually do.
Good luck in your own investigations of poker and gambling client software and remember, none of this is rocket science. There is absolutely nothing special about poker client software. In fact, poker client software can often be described as a sort of celebration of worst-practices software development: perpetually rushed, in an effort to get those features to market and start collecting that rake!!
Until next time...
Posted by James Devlin 69 comment(s)






