Introduction to Hacking Thick Clients: Part 2 – The Network

Introduction to Hacking Thick Clients is a series of blog posts that will outline many of the tools and methodologies used when performing thick client security assessments. In conjunction with these posts, NetSPI has released two vulnerable thick clients: BetaFast, a premier Betamax movie rental service, and Beta Bank, a premier finance application for the elite. Many examples in this series will be taken directly from these applications, which can be downloaded from the BetaFast GitHub repo. A brief overview is covered in a previous blog post.


  1. The GUI
  2. The Network
  3. The File System and Registry
  4. The Assemblies
  5. The API
  6. The Memory


In this post, we’ll cover network testing in thick client applications and how it’s performed on different architectures. BetaFast is written with a three-tier architecture.

  • Tier 1: The client displays and collects data.
  • Tier 2: Web requests are sent to a server where business logic is handled.
  • Tier 3: A database server modifies and retrieves data for the application server.

Beta Bank is written with a two-tier architecture.

  • Tier 1: The client displays and collects data.
  • Tier 2: A database server handles business logic and performs data queries and modifications for the client.

One-tier architecture also exists, but it’s not applicable to this blog post because the client, business logic, and data storage are all on the same system. There can be more than three tiers, but the same methods and tools outlined below will apply.



One of the first things I like to do when I begin a thick client application test is see what’s actually happening on the network. And to do that, I use a tool called Wireshark to capture and filter network traffic.


In this example, I’m testing the Beta Bank vulnerable application. With a proper capture filter in place, I’ll typically begin by just sort of doing things in the thick client. I’ll submit forms, navigate through the app, modify data, etc. Then, I’ll look through Wireshark for anything sensitive.

  • Is the database connection unencrypted?
  • Is sensitive data, such as social security numbers or medical information, transmitted in cleartext?

At one point, I authenticated to the application with the username “blogger.” Searching through the packet list in Wireshark, the name “blogger” appears in a Login procedure. The fact that this is even remotely legible means that the database connection is unencrypted, and anyone with access to this network is able to read this information just as easily. Thankfully, the password appears to be encrypted, so a hacker won’t be able to access my account.


Or will they?!

Any form of a password sent from a client, whether it’s cleartext, hashed, or encrypted, should be treated as the password itself. Sure, the password is encrypted. But knowing and sending this value to the server will authenticate this user to the application. There’s no additional defense provided by only obscuring a parameter value and not securely encrypting an entire transmission. Another value observed through wireshark is the output parameter for the Login procedure – GUID. In an authenticated portion of the application, the procedures accept a GUID as a parameter.


This is what we in the business call a “session ID.” Armed with only this value, an attacker will be able to perform authenticated actions as the blogger user as long as the session remains active.

But even that is making things more complicated than they need to be.

Echo Mirage

In this example, I am the harbinger of revolution –  a veteran of the computer who has had enough of the wealthy elite. While you were smelling the roses, I was sniffing the network. And I captured blogger’s username and encrypted password from that Login procedure.

Now, a tool like Echo Mirage comes in handy. Echo Mirage allows TCP traffic to be intercepted and modified. I can authenticate to the application with the username “blogger” and an arbitrary password, then intercept the packet containing the Login procedure.

Echo Mirage

The encrypted password can be changed to the value captured by Wireshark.

Echo Mirage

As soon as I send this request, I’m in. Let’s see how much money this big shot blogger has.


Hmmm. Perhaps this blogging thing is more of a hobby. Let’s see who else is banking with Beta Bank. Using the techniques from the previous post in the series, the Withdraw button can be enabled.


Wireshark shows that this function is sending a SQL query.


Echo Mirage can be used to directly modify the SQL statement. It can’t change the length of the packet, but the remaining SQL can be commented out.

Echo Mirage Sql

The server responds with the Users table. The account connecting to the database clearly has excessive privileges, but we now have info on every user.


There’s any number of attack vectors now. There’s still much to explore and modify in the database. But The_Chairman sounds very wealthy and very elite, and their encrypted password is practically begging to be used.


Hackers – 1

Wealthy Elite – 0



Burp Suite is perhaps the tool I use most on the job. It’s invaluable for any application assessment that deals with HTTP requests and responses. If you haven’t heard of it or used it, there are going to be far more interesting guides out there than this on how powerful the tool can be.

If a thick client is built on a three-tier architecture, the network portion of the test will essentially be the same as testing a web application. First order of business is proxying the traffic. In the proxy tab of Burp, set up a listener on and a port of choice.


Next, rather than proxying a browser through Burp, proxy the whole system.

Proxy E

There may be a lot of traffic that doesn’t belong to the application being tested. But this is the time for determining which requests are originating from the thick client. I only restrict the scope in Burp once I know the complete set of hosts the app is reaching out to. With BetaFast, I’ve determined the application is only sending requests to

Burp Cart

And now Burp can be used the same as in any web application test. Below, I sent a request to the Repeater tab and found SQL injection.

Burp Sql

Closing Remarks

A lot of important things happen over networks, so make sure not to focus only on the client when testing thick client applications! What could Beta Bank and BetaFast have done differently to protect their systems? Well, a good amount. But here are a few examples:

Beta Bank

  • Encrypt database connections – Encrypted connections hide sensitive data from wandering eyes on a network. They also ensure that traffic cannot be modified as long as the encryption is implemented securely.
  • Principle of least privilege – Since Beta Bank connects to the database as a highly-privileged user, an attacker has free rein of the database should an exploit be found. If the account connecting to the database had the least possible privilege, an attacker could not pivot beyond normal functionality.
  • Salted and hashed passwords – Encryption is by its nature reversible. This will be highlighted further in an upcoming entry in this series.
  • Authentication logic – The password being sent over the network should not be directly compared to the password stored in the database. Otherwise, the encrypted password doesn’t even need to be decrypted or a hashed password cracked. The password should be sent as-is in an encrypted transmission. The server then salts and hashes the password and compares the resultant value to the salted and hashed password stored in the database.


  • Input validation and parameterized queries – Unlike Beta Bank, it’s not an issue that traffic can be intercepted and modified. The issue is that vulnerabilities exist in the way the application server processes input. Anything sent from the client should be validated by the server, and SQL statements should have parameterized queries.

As always, be sure to check out our GitHub for copies of BetaFast and Beta Bank. And be sure to tune in for further guides on hacking thick client applications!


Introducing Burp Extractor

The Problem With Tokens and Scanning

Burp Suite’s cookie jar is an incredibly handy tool that makes a penetration tester’s life much easier in many situations. It makes for a no hassle way to reissue requests in Repeater as a different user, scan requests which were originally issued in a previous session, and other fun things. But what happens when you need to change more than just cookies? Sometimes an application requires an anti-CSRF token, an updated expiration time, or maybe a session is tracked in an Authorization header instead of cookies. Normally with Burp, this could cause a major headache and a match/replace might be used, or it could be worth struggling through setting up a macro.  Both methods requiring a good amount of manual intervention.

Burp Extractor as an Easy-to-Use Solution

Burp Extractor is intended to be a pain killer for these headaches. This extension allows penetration testers to select a string to extract from responses using a regular expression-based matching mechanism, and insert that string into any request with a similar matching mechanism, effectively making a cookie jar for whatever dynamic information the tester needs.

Using Burp Extractor

If a request requires a value from a response, right click on that request and select “Send to Extractor”. Then find a response where the client receives this value from, and select “Send to Extractor”.

Img B B A

Go to the Extractor tab to view a Comparer-like interface, and select the request and response needed, then click “Go”.

Img B B F

Within the newly created tab, highlight the content of the request which needs to be replaced, and the content of the response which contains the value to be inserted. Adjust the scope as necessary, and click “Turn Extractor on”.

Img B B Eeb

Once turned on, Extractor will look for occurrences of the regex listed in the request and response panels, and extract or insert data appropriately. It will also update the “Value to insert” field with the newest value extracted.

Check out the demonstration below to see an example usage of the extension, and grab the extension off GitHub! Hopefully this tool will help ease some pains when dealing with web apps that use tokens or authentication that Burp is not always well-equipped to cope with.

Example usage of Burp Extractor


DNS Tunneling with Burp Collaborator

DNS tunneling, in my opinion, is the niftiest data exfiltration method there is. For those not familiar, check out Section 3 from SANS’s “Detecting DNS Tunneling” whitepaper here.

Our Mobile Application Practice Lead, Aaron Yaeger, recently taught me how easy it is to use Burp Collaborator for DNS tunneling. Exfiltrating data like that was a bit time consuming to do manually, so I set out to automate this task for use in all environments. I automated this task by creating an extension for Burp Suite using the built-in Burp Collaborator API, with a private Burp Collaborator server to parse incoming DNS requests and recreate the tunneled data. The two main ways to use this extension are:

Environments with Burp Suite

In this magical and unlikely environment, the tester has access to Burp Suite on both ends and this extension is installed. In that case the tester goes to the extension on their local box, starts the listening Collaborator instance, and enters the Burp Collaborator address and the data to be exfiltrated on the compromised box’s Burp instance (for full instructions see here).

Environments with Bill and Linus

However, on most compromised boxes there is no Burp Suite, but a scripting engine is usually available (Powershell/Bash). For these environments, I have written Bash and Powershell scripts to tunnel data to Collaborator. These scripts will base32 encode, chunk, and perform DNS queries with the data. The execution chain for a tester looks like this:

  1. Copy over the tunneling script to the compromised box
  2. Click “Start Listening” on the DNS Tunnel extension on the box they want to exfiltrate data to (take note of the Collaborator server address)
  3. Start the script on the compromised box, copy in the Collaborator server address and filename to exfiltrate, and click go
  4. After the data is sent click “Poll now” on the receiving machine and the data will be present

A demo starting at step 2 is below (click to enlarge):

DNS tunneling extension demo

This is the closest to point-and-shoot that I’ve seen for DNS tunneling, which makes me hope it will give pen testers access to a tool that might have been harder for them to access in the past.  Another great alternative for tunneling is dnscat2, so definitely check that out to see if it fits your needs. Since I’m a big fan of blue teaming I’ll reference the article I posted at the beginning for Detecting DNS Tunneling by Greg Farnham. I should point out that this extension will only work with a private Burp Collaborator Server, as Burp Suite (rightly) doesn’t want their domain getting flagged as malicious when this extension sends hundreds of requests.


What is being released today is the 1st revision of this tool. Due to that, it means everything was done the way it popped into my head. If you think there are better ways things could be implemented please feel free to make a pull request or create an issue on Github.

You can download the tool at

Most penetration testers know the pain of trying to view and modify an unparsed JSON string.  For those that don’t, here’s a taste:

{"userId":1234,"username":"JakeReynolds","favorites":["Rubik's cubes","Doctor Who"],"dislikes":["Sushi","Vegetables"]}

When looking at thousands of these strings a day it is important for them to be well formatted and easily understandable. There currently exists a Burp Extension for beautifying JSON but it is written in Python, which requires Jython to be downloaded and added to Burp.  There were also some issues with Jython and that extension not being as dependable as hoped. Due to those reasons we ported that functionality to Java which is run natively by Burp.

Java makes this extension one-click install, with support from Google’s GSON parser. The source code can be found on our Github as well as PortSwigger’s Github which includes updated build instructions.

To install, simply go to Burp > Extender > BApp Store and select “JSON Beautifier”. The next time there is a JSON request in any of the Burp tabs there will be the option of “JSON Beautifier”. Any content modified in this tab will also be modified in the “Raw” tab.  An example is below:


Thanks for checking out our Burp Extension! If you would like any features added feel free to create an issue on Github.


Attacking JavaScript Web Service Proxies with Burp

JavaScript Web Service Proxies are an alternative to WSDL (Web Services Description Language) files for interacting with WCF Web Services. The proxy files function as a description of the web service methods, exposing the available service methods as well as their parameters. JavaScript Service Proxies, or JSWS (JavaScript Web Services) as I will be calling them for brevity’s sake, are a component of an AJAX framework and can typically be used in place of WSDLs for the same web services. JSWS uses JavaScript to model the descriptor file, and JSON in transit making it a good alternative to WSDL’s XML as JavaScript and JSON are heavily integrated into all browsers. The client side application will either load the JSWS upon need, or it may be embedded into the page. The JSWS contains JavaScript code that will instruct the browser in the creation of the JSON request. An example of one of these files can be seen below.

NewsSite.AdGroups.Advertisement=function() {
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
_get_path:function() {
 var p = this.get_path();
 if (p) return p;
 else return NewsSite.AdGroups.Advertisement._staticInstance.get_path();},
GetAds:function(SubsectionID,AdGroupID,Element,iCounter,succeededCallback, failedCallback, userContext) {
return this._invoke(this._get_path(), 'GetAds',false,{SubsectionID:SubsectionID,AdGroupID:AdGroupID,Element:Element,iCounter:iCounter},succeededCallback,failedCallback,userContext); }}
NewsSite.AdGroups.Advertisement._staticInstance = new NewsSite.AdGroups.Advertisement();
NewsSite.AdGroups.Advertisement.set_path = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_path(value); }
NewsSite.AdGroups.Advertisement.get_path = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_path(); }
NewsSite.AdGroups.Advertisement.set_timeout = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_timeout(value); }
NewsSite.AdGroups.Advertisement.get_timeout = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_timeout(); }
NewsSite.AdGroups.Advertisement.set_defaultUserContext = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_defaultUserContext(value); }
NewsSite.AdGroups.Advertisement.get_defaultUserContext = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_defaultUserContext(); }
NewsSite.AdGroups.Advertisement.set_defaultSucceededCallback = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_defaultSucceededCallback(value); }
NewsSite.AdGroups.Advertisement.get_defaultSucceededCallback = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_defaultSucceededCallback(); }
NewsSite.AdGroups.Advertisement.set_defaultFailedCallback = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_defaultFailedCallback(value); }
NewsSite.AdGroups.Advertisement.get_defaultFailedCallback = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_defaultFailedCallback(); }
NewsSite.AdGroups.Advertisement.set_enableJsonp = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_enableJsonp(value); }
NewsSite.AdGroups.Advertisement.get_enableJsonp = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_enableJsonp(); }
NewsSite.AdGroups.Advertisement.set_jsonpCallbackParameter = function(value) { NewsSite.AdGroups.Advertisement._staticInstance.set_jsonpCallbackParameter(value); }
NewsSite.AdGroups.Advertisement.get_jsonpCallbackParameter = function() { return NewsSite.AdGroups.Advertisement._staticInstance.get_jsonpCallbackParameter(); }
NewsSite.AdGroups.Advertisement.GetAds= function(SubsectionID,AdGroupID,Element,iCounter,onSuccess,onFailed,userContext) {NewsSite.AdGroups.Advertisement._staticInstance.GetAds(SubsectionID,AdGroupID,Element,iCounter,onSuccess,onFailed,userContext); }
var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;
if (typeof(NewsSite.AdGroups.AdGroupInfo) === 'undefined') {

After the file is loaded the subsequent request will be formatted in the following way.

Json Request

A side effect of this file instructing the browser in how the requests must be formatted is that it can also aid an attacker in enumerating web service methods and potential injection points. Before these can be used, it is important to understand when JSWS is in use, and how to identify it.

Identifying JSWS

There are multiple different ways to identify when these services are being used in an application. The application may request a JSWS file allowing it to be identified through proxy logs by looking for The application may also request the same file with the debug information, The jsdebug file will contain additional information about the datatypes of the parameters needed, and which parameters are required. Even if the application is not requesting the jsdebug file it is likely still available.

Alternatively, the application may be using the PageMethods technique, which means the JSWS will be embedded directly into the page.

This will typically be on an aspx page rather than asmx, but it could be present with any extension. This method can be identified by searching server responses for the ‘PageMethods’ string, or by inspecting proxy logs for the method calls (e.g.

The JSWS Extension

After identifying that this technology is being used an attacker is able craft all the request variations the web service will accept, but this takes time and can be quite tedious. After starting to see JSWS in assessments more often, I decided to create a Burp extension that would automate this process. The tool is modeled after Eric Gruber’s Wsdler, and functions in the same way. The JSWS extension can be downloaded from, and is available in the BApp store.

To use this tool, simply right click on the request or response containing the JSWS and click Parse JSWS. If the application is loading the JSWS file, the file should already be in the proxy logs.

Parse Jsws

It is recommended to parse the jsdebug file rather than the js file, as it will give the user more information about which types of parameters to tamper with.

If the application uses the PageMethods representation of JSWS, right click on the request or response containing the PageMethods code and click Parse JSWS.

The JSWS extension will then open a JSWS tab, as well as a subtab for the service just parsed. Under this tab are two panes, the top containing all available methods, and the bottom containing the JSON template.

Jsws Tab

From here the request can be handled as any JSON request, and can be sent to Repeater for manual testing, or Intruder and Scanner for automated testing.


The extension does not currently detect the presence of JSWS through passive scanning. This is being implemented and will be released in a future build. For any feature requests or bugs you may find please email me or create a ticket on Github.


Java Deserialization Attacks with Burp


This blog is about Java deserialization and the Java Serial Killer Burp extension. If you want to download the extension and skip past all of this, head to the Github page here.

The recent Java deserialization attack that was discovered has provided a large window of opportunity for penetration testers to gain access to the underlying systems that Java applications communicate with. For the majority of the applications we see, we can simply proxy the connection between the application and the server to view the serialized body of the HTTP request and HTTP response, assuming that HTTP is the protocol that is being used for communication. For this blog, HTTP is going to be assumed and to perform any type of proxying for HTTP, we will use Burp.

Burp Proxy

Here’s a simple example what a Burp proxied HTTP request with a serialized Java object in its body looks like:

Img D Ddaa

In this example we have a serialized object called State that is comprised of two Strings, capitol (spelled wrong in the example) and nicknames. From here, we can manipulate the request by sending it to the Repeater tab.

Generating Serialized Exploits

There are a few tools out there that will generate serialized Java objects that are able to exploit vulnerable software. I’m a big fan of Chris Frohoff’s ysoserial ( He has payload generators for nine exploitable software stacks at the time of me writing this.

Simply running the jar file with the payload type and command to execute will generate the serialized object for you. Just make sure you output it to a file:

java -jar ./ysoserial-0.0.4-all.jar CommonsCollections1 ‘ping’ > payload

We can then copy the serialized output into Burp using the paste from file context menu item:

Img D Ddbdea C

Which will result in the following:

Img D Ddd C

Generating Serialized Exploits in Burp

Ysoserial works well enough, but I like to optimize my exploitation steps whenever possible. This includes removing the need to go back and forth between the command line and Burp. So I created the Burp extension Java Serial Killer to perform the serialization for me. It essentially is a modified Repeater tab that uses the payload generation from ysoserial.

To use Java Serial Killer, right click on a POST request with a serialized Java object in the body and select the Send to Java Serial Killer item.

Img D Dddfa E

A new tab will appear in Burp with the request copied over into a new message editor window.

Java Deserialization Attacks With Burp

In the Java Serial Killer tab there are buttons for sending requests, serializing the body, selecting a payload type, and setting the command to run.

For an example, say we want to ping using the CommonsCollections1 payload type, because we know it is running Commons-Collections 3.1. We highlight the area we want the payload to replace, set the payload in the drop down menu, and then type the command we want and press the Serialize button. Pressing the little question mark button will also display the payload types and the software versions they are targeting if you need more information. After you highlight once, every subsequent button press of Serialize will update the payload in the request if you change the command, payload, or encoding.

Java Deserialization Attacks With Burp

We can also Base64 encode the payload by checking same named checkbox:

Java Deserialization Attacks With Burp

If we want to replace a specific parameter in a request with a payload we can do that too by highlighting it and pressing Serialize:

Java Deserialization Attacks With Burp

Java Deserialization Attacks With Burp

Most likely we will need to Base64 encode the payload as a parameter in xml:

Java Deserialization Attacks With Burp

As Chris Frohoff adds more payloads, I plan to update Java Serial Killer accordingly.


I submitted the plugin to the Burp app store and I don’t expect it to take too long to get approved, but if you want to try it out now, you can get it from our Github page ( You will need to be running Java 8 for it to work.


Debugging Burp Extensions

Burp is a very useful tool for just about any type of testing that involves HTTP. What makes it even better is the extension support that it offers. People can compliant the features that Burp has to offer with their own extensions to create a very powerful well-rounded application testing tool that is tailored to their needs. Sometimes, however, our extensions don’t work the way we want and require additional testing. In this blog post, I’m going to walk through how we can setup debugging in Burp and our IDE when we create Burp extensions. Essentially, we are just going to be setting up Java remote debugging. This should hopefully be a useful tutorial for people who are creating buggy Burp extensions and want to figure out why they aren’t working. This should also be especially helpful for first time Java developers who are not accustomed to Java’s debugging capabilities. This will not be a tutorial on creating Burp extensions. For help on that, I’ll refer you to the PortSwigger extender tutorials here.


Java SDK (1.7 or 1.8)

Java IDE (I prefer IntelliJ)

Burp Suite (latest free or pro edition)

Getting Started

To begin debugging extensions in Burp we first need an extension to debug. For this example, I’ll be using the Wsdler extension I created for parsing WSDL files. If you would like to follow along, the code for Wsdler is located here. We’ll pull this down from git using git clone.

C:UsersegruberRepositories>git clone
Cloning into ‘Wsdler’…
remote: Counting objects: 458, done.
remote: Total 458 (delta 0), reused 0 (delta 0), pack-reused 458
Receiving objects: 100% (458/458), 19.59 MiB | 221.00 KiB/s, done.
Resolving deltas: 100% (204/204), done.
Checking connectivity… done.

Next, we’ll open this up in our IDE. I’m using IntelliJ, but this can be accomplished using any Java IDE (I think). Select File > Open and navigate to the directory and press OK. IntelliJ should open the directory as a project in its workspace.

Img Fb Cd

Attaching the Debugger

Now that we have our Burp extension in IntelliJ, let’s configure our debugger. Unfortunately, we can’t just hit Run > Debug to start debugging.

Img Fc C E

Burp extensions are executed inside Burp. They are generally not standalone jar files with a main class. We can still debug them however with the Java’s remote debugging capability. This allows the debugger to attach to a Java process and send and receive debug information. To do this, select Edit Configurations from Run.

Img Fcd Ad

A Run/Debug Configurations window should appear.

Img Fcfd

Press the green plus sign and select Remote. You should see a window that looks like this:

Img Fd E F

This allows us to setup remote debugging against running processes. Name the configuration whatever you like, I use Burp. Leave all the configuration options set to the defaults unless you know what you’re doing. Next, copy the first command line string. The one that starts -agentlib. You need to add this as an argument to your Java process for the debugger to attach to it. When executed, Java will open up the port 5005 for remote debugging. This allows the debugger to send commands through that port to the JVM process. Press OK at the bottom of the window. You should now see your debug configuration under Run.

Img Fe C B

Now we need to start Burp with the command line argument from our debug configuration. Open up a command prompt and start Burp with the argument.

C:>java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar burpsuite_pro_v1.6.18.jar
Listening for transport dt_socket at address: 5005

The JVM should now be listening on port 5005, the port we specified in our configuration. Next, we’ll go back to our IDE and select Run > Debug Burp. The console window should pop up saying it is connected to the target VM.

Img Ffaa F B

Setting Breakpoints

Now that we have our debugger attached to Burp we can start setting breakpoints in our extension code. First, make sure your extension is actually loaded in Burp’s extender!

When setting breakpoints, try not to set them on method names themselves. This can slow down Burp considerably. Instead, set breakpoints on lines of code within the methods you want to debug. The first breakpoint I’m going to set is within the WSDL parsing method in my extension. We will pause execution at the point the response byte array is set.

Img Caf A

If everything is setup, go back to Burp and execute whatever is needed for you extension to be used. In this example, I will right click on the request I want to parse the WSDL from and select Parse WSDL.

Img A C E

Our debugger should pause on the breakpoint immediately and display the current frames and variables.

Img F F D

We can walk through the code by selecting the step buttons on the top of the debugging menu.

Img Df

Stepping over the response assignment should reveal the response variable in the variables section of the debug console. The debugger should also be on the next line of code.

Img Dceda E

We can go further and step inside functions, but I’ll leave that out for now.


Hopefully this little tutorial is somewhat helpful when trying to fix your Burp extensions through debugging. I know I have spent hours debugging my own extensions and the Java debugger is immensely more helpful than having System.out.println() statements everywhere.


Hacking High Scores in iOS GameCenter

I recently wrote a blog post about cracking email hashes from the iOS GameCenter application. During my research on the issue, I noticed that there were a number of games where users had insanely high scores. Lots of the users also had the exact same score (9,223,372,036,844,775,807) for each of the games that they played. Coincidentally this number is the largest possible signed integer value that you can have. It turns out that getting these high scores isn’t that hard to do.


In order to modify our scores, we will need to proxy our iOS traffic through Burp. In order to properly intercept the encrypted iOS traffic, you will also need to install the Portswigger certificate on your iOS device At this point, you will want your Burp listener to be on the same wireless network as your iOS device. You also need to have your Burp listener set to listen on all interfaces to allow your iOS device to proxy through it. The iOS proxy settings are fairly easy to set up. Just enter your Wi-Fi settings, tap on the blue and white arrow-in-a-circle (to the right of your SSID), and scroll down to your HTTP Proxy settings. Set the server IP to your Burp listener and set your port to the Burp listener port. Visit an https website on your iOS device to see if the Portswigger certificate is properly installed. If you don’t have any issues (or SSL warnings), you should be ready to go.

Modifying Scores

Once your iOS device is properly proxying traffic through your Burp listener, you will want to generate a score to post to GameCenter. For most games, this is not very hard to do. We will be using “Cut the Rope”as our example. Open up the first level, set Burp to intercept traffic, and complete the level (you cut one rope, it’s really easy). At this point you will see the “Level Complete” screen on your iOS device and the following request will come through Burp.

POST /WebObjects/GKGameStatsService.woa/wa/submitScores HTTP/1.1
User-Agent: gamed/ (iPhone4,1; 6.1.2; 10B146; GameKit-781.18)
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Accept: */*
Some-Cookies: have been removed to make this shorter
Content-Type: application/x-apple-plist
Connection: keep-alive
Proxy-Connection: keep-alive
x-gk-bundle-version: 2.1
Content-Length: 473
x-gk-bundle-id: com.chillingo.cuttherope
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">

If you are seeing other requests come through, just forward them and keep your eye out for the request for the “submitScores” page. Before forwarding the score on to Apple, you will want to modify the score. The highest possible value that you can submit is 9,223,372,036,844,775,807. Replace the “score-value” stored in the tags (bolded in the example) with 9223372036844775807 and forward the request. You should receive a “status 0” response from Apple and your score will be updated in GameCenter.



I don’t intend on modifying my high scores for each of my GameCenter games. I really don’t care that much about the scores, but some people do. Given Apple’s current model for GameCenter leaderboards, this may not be an easy fix. At a minimum, Apple may want to do some checking on these high scores to weed out any of the users that are maxing out their top scores. For now, I’m going to put the iPhone down and get some work done.


Hacking Web Services with Burp

WSDL (Web Services Description Language) files are XML formatted descriptions about the operations of web services between clients and servers. They contain possible requests along with the parameters an application uses to communicate with a web service. This is great for penetration testers because we can test and manipulate web services all we want using the information from WSDL files. One of the best tools to use for working with HTTP requests and responses for applications is Burp. The only downside with Burp is that it does not natively support parsing of WSDL files into requests that can be sent to a web service. A common work around has been to use a tool such as Soap-UI and proxy the requests to Burp for further manipulation. I’ve written a plugin for Burp that takes a WSDL request and parses out the operations that are associated with the targeted web service and creates SOAP requests which can then be sent to a web service. This plugin builds upon the work done by Tom Bujok and his soap-ws project which is essentially the WSDL parsing portion of Soap-UI without the UI.

The Wsdler plugin along with all the source is located at the Github repository here:

Wsdler Requirements

  1. Burp 1.5.01 or later
  2. Must be run from the command line

Starting Wsdler

The command to start Burp with the Wsdler plugin is as follows:
java -classpath Wsdler.jar;burp.jar burp.StartBurp

Sample Usage

Here we will intercept the request for a WSDL file belonging to an online store in Burp.

Img B Ce B E

After the request for the WSDL has been intercepted, right click on the request and select Parse WSDL.

 Img B Ce Aca

A new Wsdler tab will open with the parsed operations for the WSDL, along with the bindings and ports for each of the operations. Operations are synonymous with the requests that the application supports. There are two operations in this WSDL file, OrderItem and CheckStatus. Each of these operations has two bindings, for simplicity’s sake, bindings describe the format and protocol for each of the operations. The bindings for both of the operations are InstantOrderSoap and InstantOrderSoap12. The reason there are two bindings for each of the operations is because the WSDL file supports the creation of SOAP 1.1 and 1.2 requests. Finally, the ”Port” for each of the operations is essentially just the URL the request will be sent to. The full specification for each of the Objects in WSDL files can be read here:

 Img B Ce

The SOAP requests for the operations will be in the lower part of the Burp window. The parsing functionality will also automatically fill in the data type for each of the parameters in the WSDL operation. In this example, strings are filled in with parts of the Aeneid and integers are filled in with numbers.

The request that Wsdler creates is a standard Burp request, so it can be sent to any other Burp function that accepts requests (intruder, repeater, etc.).

Here the request is sent to intruder for further testing. Because the request is XML, Burp automatically identifies the parameters for intruder to use.

Img B Ceb D

Img B Cebcc B


Currently, the plugin only supports WSDL specification 1.1, but there is work on supporting 1.2 / 2.0. Also, I will be adding the option to specify your own strings and integers when the plugin automatically fills in the appropriate data type for each of the parameters in the parsed operations. If there are any bugs or features that you would like to see added, send me an email or create a ticket on Github.