digital inflation

I spent most of the morning retiring an old Compaq Presario server; it’s perhaps fifteen years old. It was in with some things in storage and I thought I’d get rid of it since the hardware wasn’t even compatible with an Ubuntu server install attempt.

Less Was More

I realize in going through the motions of archiving all my many coding projects from years ago just how much bloat we’ve taken into our computers and our computer languages these days. I think the laptop I’m on right now has 8GB of RAM and this NT 4.0 Server only had 384MB of RAM, running instances of IIS, SQL Server, NT Server, WINS, DNS Server as well as a VSS server. It also hosted QuickBooks Pro 99, Adobe Photoshop 5.0 LE and Visual Studio. Come to think of it, it also easily ran my own NT services, custom-made IIS ISAPI filters and custom SQL Server extended stored procedures that I’d written. It had Microsoft Office, Adobe Acrobat and Illustrator, Flash-development tools by Macromedia.

It ran all this on 384MB of memory.  And those fifteen prolific years’ worth of accumulated everything only resulted in about 4GB of storage, perhaps the equivalent of a mere three movies on my laptop now. I almost have to laugh as I store it on a terabyte external drive.

Digital Inflation

graph

Seriously, though, what have we gained by making everything so heavy? I recall being able to accomplish anything I needed to do in that older version of Adobe Photoshop and using a fraction of that 384MB of memory. Just now, it took Adobe Photoshop CC about five minutes to load up so that I could paste this graphic in and start to work on it. I select the Spot Healing tool and begin clicking.  One, two, three… and then I wait as the tool freezes up and I have to wait for the spinning cursor to resolve itself. I then Step Backward to remove the garbage that the tool added and try to repeat, only this time slower. This sucks. I know that older version from over ten years ago didn’t do this.

So now, every day we get faster and faster microprocessors with multiple cores. But that Windows 10 upgrade from this year demanded that we have no less than 4GB of RAM just to install it. Why?

The answer is that we’re under a form of inflation that’s taken over the digital world. The same resources we had last year just aren’t good enough.

Back in this post I suggested that open source projects are suffering from this bloat, too. Big companies like Google believe that programs have to be big to be good. I disagree. Sometimes quality and project size are in direct opposition with each other. The more code you have, the more code that could be potentially bad.

Who Do We Blame?

Is it the microprocessor manufacturers who are behind this? I don’t think so. How about the operating system makers like Microsoft and Apple? Probably. I do know that .Net is a huge, bloated layer of code that’s supposed to be Microsoft’s version of Java. But the reason for both Java and .Net is to write machine-independent code. And since nobody really writes .Net code to run on an Apple computer or on a Unix box then what’s the point?

And now that .Net has seen its heyday Microsoft is ready to do the “new, new thing” which is to chase Apple’s app-based iTunes-delivered store. So we as consumers picked up this thick layer of code in the form of .Net which honestly does little for us. And yet most of the software written for a Windows-based computer has to use this foundation. No wonder it takes so much to do so little.

I’d like to blame Adobe’s bloat on all the code which is designed to permission their new subscription-based model. Try to buy Adobe Acrobat now and you’re left with the choice of paying $500 or something like $20-per-month. Neither option is worth it, in my humble opinion. Much of that startup lag I mentioned before could be the client app talking to mothership Adobe to see if my licensing this month is paid.

Predictions

Honestly, the pendulum has to swing back the other way. Consumers will reject subscription-based pricing models, will turn in greater numbers to open source operating systems and desktop tools and eventually the big players will come back with their apologies and revised ideas about how to win back their former customers.

In earlier times you couldn’t expect an average computer person to use a command line interface. But younger computer users are trained in public school and they’re not so timid. Strangely enough, Microsoft is turning to a similar mechanism to do advanced things in their software using PowerShell commands. And there is even an option to install their server software without a GUI environment at all… like a UNIX server, if you think about it.

The original IBM PC didn’t have a Windows interface since that didn’t come until many years later. The very popular (free) Ubuntu server software now does the same. You’d be surprised how much work the computer can do when it’s not unnecessarily displaying graphics.

I believe that we’ll eventually build simpler interfaces. The Windows 10 “Metro” menu and those of smartphones now are visually simpler if you think about it. They’re essentially flat squares that you can push with your finger rather than the fussy-little, 3D-styled buttons from twenty years ago in Windows 95.

Hardware like Google Glass may remove the need for such specialized interfaces. Since this hardware doesn’t include a keyboard your ability to interact with the interface is limited to pointing your head toward a spot on the screen and holding it until it’s selected. When they add voice commands to this interface we’ll see yet another revolution in how we expect software to behave. Hopefully we’ll get to the point where there are no more buttons to push—all commands would be accomplished verbally in your own language of choice.

Back to simpler interfaces, however, must we have all the visual candy? Could we not focus on the work to be done, the spoken commands to trigger that work and remove everything else but the text-based status? On today’s hardware we could do that now if we really wanted to. But since companies like Apple/Microsoft/Google want their store-like delivery model we’ll likely not get what we want unless we build it ourselves.

Advertisements

trial version annoyances

I had a quick-and-dirty task to do today at work:  I wanted to write a very simple program which would split an Adobe PDF document into its individual pages. It didn’t sound like a difficult thing to accomplish, to be honest. By the end of the day, however, I find myself in hacker mode, putting much more effort into doing an end-run around someone’s idea of security.

split-pdf

Options

Of course, this is relatively easy on OS X in the Automator utility. You can create a service, associate it with a folder, say, and then drag/drop a PDF into that folder. Done.

But this needed to be for Windows-based computers and I had a preference to do this in C# within Visual Studio if there wasn’t an easier way of doing it otherwise. Researching a bit I confirmed that there weren’t any native tools within Windows which would take care of this. Next, I then looked for free libraries or similar. This search turned up:

  1. iText (ruled since it’s just a .Net wrapper over Java)
  2. PdfBox.net (ruled out since it’s just a .Net wrapper over Java)
  3. Spire.pdf
  4. Aspose.pdf

And yet, each of these seems to expect money from me in order to build a solution. Granted, somebody probably put a lot of effort into these libraries. I remember myself creating a very nice one-pass XML-to-PDF compiler perhaps ten years ago and was very fond of it. Perhaps it was that experience that led me to the solution I chose: I decided to use Aspose.pdf and then programmatically render their trial-version watermark void.

You might be thinking, “why don’t you just pay for the library?” That’s a good question. The people who wrote Aspose.net expect me to minimally pay $799 per year just to be a developer. And then, presumably, each client would also need to pay this amount for a licensed DLL. They have seven even higher pricing tiers into the many-thousand area. Given the need to simply split a PDF file, I don’t see the value.

The Difficulty of Starting From Scratch

Granted, I could begin from scratch and write a PDF “tree-walker”, find the pages, iterating through them to re-create the content page by page. Since I understand the underlying storage method in a PDF file this could be done in under a month. I could then build this into my own library and charge money for it, presumably cutting the knees out from under these players in the market space.

That said, splitting a PDF file isn’t an $800 problem nor is it a one-man-month problem. A program which splits a PDF file should cost about… $10 tops.

The Problem With the Trial Version of Aspose.pdf-generated PDFs

Unfortunately, the trial version of the Aspose.pdf library places an obtrusive watermark at the top of each page.

AsposeWatermark
Example output of the  trial version of the Aspose library

 

 

Programmatically-Removing Watermarks From PDFs

So then, I researched to see if there were any available/free methods of removing watermarks from PDF files. There doesn’t appear to be. I would need to write it myself.

One challenge is the problem is patching a binary file in-place with C#. To be honest, I expected the .Net framework to have something like this but that doesn’t appear to be the case. In addition to hacking the PDF object code I would need to write a rudimentary binary search-and-replace routine for C#.

Hacking the PDF File

It’s good to be familiar with the object storage model for PDF files in order to understand what approach I then took.

A typical PDF file includes many objects and a table at the end which is essentially a table of contents for those objects. If you’re familiar with a Rich Text Format (RTF) file, then it’s much like this except for the catalog at the end.

It’s that catalog at the end that provides the first challenge, when editing a binary PDF file you can’t change the size of an object or move it. Doing so would break the catalog.

The second biggest challenge when editing a binary PDF file is the frequent use of inline compression/encoding. You can’t easily find the actual object that you’d like to overwrite. And yet, with a simple PDF file you can accomplish this by using a hexadecimal editor and iteratively change one character per object until you “break” the object in question, that pesky watermark.

AsposePDF.png
Typical PDF file contents

 

 

The Achilles Heal of Watermark-based Prevention

So now, what would it take to nuke that watermark? One method would be to find the object, physically remove the entire object from the file and remove its reference from the catalog. And yet, then I’d need to update the file offsets for half of the other objects within the file itself.

Inside the body of the PDF file each of these compressed-content objects includes the key to its own demise:  FlateDecode. This is the protocol for compressing the included text within an object and I believe it’s the ZLib (Limpel-Ziv) compression at work. And that usually includes an Adler-32 checksum at the end of it. Replace even a single byte of that compressed stream—presumably without updating the checksum—and that object content is broken.

But what does Adobe Reader do with a broken object? It silently swallows it without displaying it, which is exactly what we want to do here! Replace even a single encoded byte in that unwanted watermark and it’s effectively gone.

“Replace even a single encoded byte in that unwanted watermark and it’s effectively gone.”

So the hack then was a few lines of code. As I mentioned before, I used a trial-and-error method of temporarily editing one compressed section of PDF after another until I’d broken the watermark. At this point, I then determined that the text for my target search was “xœ}OM” or more simply “}OM”. Confirming that the watermark included the only occurrence in the file of this combination of characters allowed me to do a binary comparison and replacement.

// Above this was the Aspose sample code to write each page
// to a file. I inserted this code on a per-page basis to
// then modify that newly-created PDF file.

// This is our own code to find/replace their watermark
string fileToModify = pdfDocument.FileName.Substring(
	0, pdfDocument.FileName.IndexOf('.')
	) + "_p" + pageCount + ".pdf";
string fileModified = pdfDocument.FileName.Substring(
	0, pdfDocument.FileName.IndexOf('.')
	) + "_p" + pageCount + "_no-watermark.pdf";
using (var reader = new BinaryReader(
	new FileStream(fileToModify, FileMode.Open)))
	{
	using (var writer = new BinaryWriter(
		new FileStream(fileModified, FileMode.Create)))
		{
		byte[] buffer = new byte[1024];
		int count;
		while ((count = reader.Read(buffer, 0, buffer.Length)) != 0) {
			// Now look for our sequence
			for (int j = 0; j < (count - 3); j++) {
				if (	buffer[j] == '}' &&
					buffer[j + 1] == 'O' &&
					buffer[j + 2] == 'M')
					{
					buffer[j] =     0x31; // 1
					buffer[j+1] =   0x32; // 2
					buffer[j+2] =   0x33; // 3
					}
				}
			// Optionally having patched in place,
			// write to the destination file
			writer.Write(buffer, 0, count);
			// Empty out our buffer for another run
			for (int i = 0; i < buffer.Length; i++) {
				buffer[i] = 0x00;
			}
		}
	}

I’m sure there are prettier ways of searching a buffer but this was easy enough. Note that I only actually need to change, say, the first character at “buffer[j]” which is sufficient to break that checksum mechanism.

And the rest, as we say, is history.

AsposeWatermarkGone
Same example, after breaking the watermark

You might ask why I’d post about such things. I do it for the sake of my own curiosity and I assume that others like you are curious as well. Just as little kids build sand castles and then smash them to bits we bigger kids like to build security and then smash that as well. One of the reasons why this is good practice is that it teaches us what is “good enough” security and what is “better” security. Just because you think something is secure because you can’t think of a way around it, that doesn’t mean that some other clever person can’t work their magic.

apple: hiding the truth

One business dictionary defines transparency as “a lack of hidden agendas or conditions, accompanied by the availability of full information required for collaboration, cooperation and collective decision-making”. Perhaps Apple could do well by re-reading that statement and the two emails that they sent me this week, in reverse order (since it’s funnier that way).

Screen Shot 2016-07-16 at 8.23.54 PMScreen Shot 2016-07-16 at 8.23.01 PM

My New (Used) iPhone 5

I’d recently purchased a used iPhone 5 from a co-worker. He’d indicated that it had a problem with phone calls and had decided to upgrade to the latest phone Apple makes. So he was left with the iPhone 5 and I offered to buy it from him on the cheap since I do phone development and I knew that I could put it to good use.

Fast-forward a few weeks and I decided that my Android-based phone was really churning through the battery at a fair rate (compared to the iPhone) and so I thought I’d get a cellphone plan switch. I paid a few months in advance without thinking twice about it only to find that later when I’d gotten home, the iPhone 5’s microphone and speakers all worked great except during a phone call. Obviously, the phone had a problem of some kind.

Apple’s Support Forum

Here is the Apple support thread, in case you wanted to read along. It looks like countless people are having the same problem with their phones, too. At first I read all these and realized that nobody really knew what was going on with their phones. Like me, they were stuck with a mostly-useless piece of hardware with respect to making or receiving calls.

I took it to the cellphone carrier vendor and left it with him for an hour or two. He reset the phone and upgraded the firmware or similar but was unable to help out.

Someone on youtube had indicated that they’d thoroughly cleaned the microphone and speaker holes so of course I gave this a try. It didn’t help, of course.

I verified that all three speakers and the microphone all worked with other apps. I deduced that there might be a connectivity issue.

Inside the iPhone

Given that I have the proper tools for such a task, I decided to take it apart. Apple uses a pair of tiny “Pentalobe security screws” (Apple’s nomenclature) to secure the case of the iPhone series. I guess they think that the market won’t just make the appropriate screwdrivers and sell them to the public.

Once inside, I re-seated the various connections that could have caused the problem. I then re-tested but the problem still persisted. On a hunch I decided to twist the phone along its length and this immediately allowed the phone portion to work!

The Underlying Cause

Everything inside a phone like this is necessarily tiny and modular. As such, Apple relies upon each module to make an electrical ground connection against the outside of the case. A little twist and that connection is lost.

Another compounding problem is the nature of batteries of the type used in cellphones. They are prone to swelling and contracting over time and with each charging cycle. Apple appears to know all about this. In fact, it’s as if they’ve compensated inside the phone by allowing a fair amount of expansion room for the battery itself. One could suggest that there’s too much space since the sparcity inside just promotes more flexibility and this leads to losing electrical ground in those components I spoke about earlier.

The Fix

It occurred to me that a 3″x5″ card could be cut to fit and placed inside the iPhone’s body and should tighten everything enough so that those electrical connections would be made. Luckily, this was exactly what it wanted.

Letting the Community Know

As a good net citizen I decided to let others know what they could do to fix their own failing iPhones. I posted on that same Apple Support thread only to see that they don’t want you to know this.

Took my iPhone’s rear case off (carefully) and removed/replaced the three connectors that attach the screen itself, verifying absolutely that they were fully re-seated.  Then when putting everything back together I inserted a 3″x5″ index card (cut first to a 2-1/8″x3-1/2″ rectangle and then trimmed a portion from both long sides so that the outer snaps would clear it).

The thickness of the card is enough to tighten up everything inside so that all the connections mate up always.  It now works perfectly.  I have to think that the problem is due to occasional twisting of the phone along its length.  Old computer motherboards had the same problem, btw.

What I should have added to this on the Apple Support forum (but I can say this now) is that it appears that there is a systemic problem in the iPhone series with respect to electrical grounding.

Apple’s Response

Apple promptly deleted my post, citing that it contained “questionable advice”. Note that Apple themselves provide no advice for these users.

The problem here is that a good percentage of these users have no recourse but to purchase a new iPhone 6 ($550-$650). Apple decided that it’s in their best interest to hide a working fix to their older phones.

What Apple Should Have Done

Apple should have read the post, researched whether or not there was any validity in the claim and then should have posted something on the order of, “We are researching the issue and caution users that to open their phone would be to void the warranty. If we determine that there is an electrical grounding problem and you have registered your phone with us then we will contact you for a service call”.

If they had done something like this then they would have earned all our respect. The choice they made, however, just proves that Apple—for all their friendliness in their advertisements—are just a big corporation who doesn’t believe in transparency with their customers.

let the wars begin

Oh, the fun.  Microsoft and Google seem to be at odds these days or so it would seem. It’s like a cold war is going on just beneath the surface.

Google Domains freezes in IE

The new Beta Google Domains website is Google throwing their hat into the ring of the annual US$500M domain registration market. Given their programming clout, they could create almost any kind of website and support any kind of browser. And of course the entire administrative interface on Google Domains crashes spectacularly if you use Internet Explorer. I would suggest that this is “by design”.

Outlook in Office 365 marks @google.com as junkmail

I kid you not. Right out of the box with a fresh installation of Office 365 today on a Windows 10 computer I see that the only inbound email is in the Junkmail folder and it’s from Google Domains’ notifier.

hacking agar.io, part 2

This would be the second post in a series. You might want to read the first in the series if you haven’t already done so. Here, I continue with the work related to redirecting the game’s server traffic to my own website so that I can discover the interface.

DNS server

I first install Dnsmasq on my MacBook, add a single entry to its /etc/hosts file to redirect traffic for m.agar.io to my MacBook’s private IP address. Starting up Dnsmasq I then have a DNS server which will redirect game traffic to my own website. Make sure that the program is running by entering ps aux|grep dnsmasq|grep -v grep. You should see an entry for this program.

It’s probably a good idea to test your DNS server to verify that it returns the expected information.

nslookup
> server myip
> m.agar.io.
> exit

After entering the third line above you should see a DNS lookup which returns your server’s private IP address.

Our website

In my ~/sites folder, I run the following command to use Express to generate a generic website: express agar. As is usual for Express, I change into the newly-created agar directory and then run npm install to bring in the dependencies. Since the default installation binds to an upper TCP port and we want the standard port 80 instead, I then edit the bin/www file in this folder and replace the port number 3000 with 80 on a single line.

Note that Node.js, the underlying program that serves up an Express website, will not be able to bind to port 80 since it’s reserved unless I’m running as the root user. If your own user is setup to run the su command then you should be able to start this website with the command su npm start in the agar folder. Otherwise, you’ll have to run just su to become the root user, navigate back into your user folder area to find this folder and then just run npm start instead.

It’s probably a good idea to test the website by bringing up Safari and entering the address http://myip/ (substituting my private IP address) to see if it works.

Configuring the iPad

At this step, I’ll need to tell the iPad’s Wi-Fi configuration to use my own DNS server first and then the existing set of DNS servers next. You’ll find this under Settings -> Wi-Fi -> select the i button next to your own connected Wi-Fi network -> DHCP -> DNS -> prepend your own server’s private IP address and a comma at the beginning of the list.

This is the initial preparation for redirecting the game traffic to your own website. Note that the Node.js website while running will write to its log file and this will be our method of discovering the interface for Agar.io.

Discovery phase

By now attempting to play the Agar.io game on the iPad, it makes requests to what it thinks is the server. Only these requests are now being sent to my website instead. As each attempt is logged as a failure on my own website, I then make this call manually in another computer to the actual Agar.io website to see what it’s supposed to return.

For example, the game makes a request to the game server’s interface with just /info as the URL.

/info returns:

{"regions":{
  "CN-China":{"avgPlayersPerServer":368.5,"avgPlayersPerRealm":147.4,"numPlayers":737,"numServers":5,"numRealms":5},
  "US-Atlanta":{"avgPlayersPerServer":445.1034482758621,"avgPlayersPerRealm":203.2755905511811,"numPlayers":25816,"numServers":267,"numRealms":127},
  "EU-London":{"avgPlayersPerServer":430.6,"avgPlayersPerRealm":191.37777777777777,"numPlayers":8612,"numServers":179,"numRealms":45},
  "SG-Singapore":{"avgPlayersPerServer":546.0,"avgPlayersPerRealm":136.5,"numPlayers":1092,"numServers":9,"numRealms":8},
  "Unknown":{"numPlayers":0,"numServers":0,"numRealms":0},
  "BR-Brazil":{"avgPlayersPerServer":333.3220338983051,"avgPlayersPerRealm":200.6734693877551,"numPlayers":19666,"numServers":181,"numRealms":98},
  "RU-Russia":{"avgPlayersPerServer":473.25,"avgPlayersPerRealm":145.6153846153846,"numPlayers":1893,"numServers":45,"numRealms":13},
  "JP-Tokyo":{"avgPlayersPerServer":460.0,"avgPlayersPerRealm":172.5,"numPlayers":1380,"numServers":8,"numRealms":8},
  "TK-Turkey":{"avgPlayersPerServer":287.14285714285717,"avgPlayersPerRealm":154.6153846153846,"numPlayers":2010,"numServers":30,"numRealms":13}
  },
  "totals":{"numPlayers":61206,"numServers":724,"numEnabledServers":317,"numRealms":317}
}

As you can see, this is a fair bit of information. The format is known as json in case it’s not familiar to you. As of my writing this, there appear to be over 61,000 players in the game right now and well over 700 servers with almost half of those enabled. So this would be why it’s difficult to get a simultaneous FFA game with your friends—the odds are against you.

Without further ado, here are the other queries which I discovered.

/ returns:

37.187.171.110:1523
8QJP8

This appears to be your issued server and port on the first line and what is likely its instance alias from whichever cloud-based company they’re using.

/getLatestID returns:

131

I know, not very impressive. But it appears to be the highest user ID for your issued server.

/findServer returns:

{"ip":"151.80.98.52:1516","token":"86JYH"}

Another json response, this appears to also be issuing you a server and port. It’s possible that the first home query is asked at the beginning of the game and then /findServer is called each time your die in the game.

So far, this appears to be everything I’ve learned from this redirection technique.

Status

At this point, I now have the game interface which the Agar.io app uses to communicate with the server. It likely makes more requests but that’s good for now. I could have enough to go on in order to work up something so that multiple iOS people could join the same FFA game, for example, since we know this issuing mechanism.

hacking agar.io

In an earlier post I described an addictive game called Agar.io, an interactive eat-or-be-eaten game involving graphical dots. In this series of posts, I’ll be attempting to hack the game to see what I can get away with.

Agar-top

Define:  hacking

I suppose there are several ways of interpreting the term hack here. In the movies, some character will “hack the mainframe” or some other nonsense. And we’re also familiar with someone who attempts to use techniques to hack a website, perhaps injecting SQL code into an innocent-looking HTML form. Here, I refer to one of the original uses of the word, to hack away at a problem until it is solved. I’m interested in the game itself, how it talks to the server and I’d like to go to school on their efforts. As a coder of smartphones myself I’d call that part of the learning curve.

Goals

Ultimately, I would like to learn how the game works behind-the-scenes. I do have some secondary goals though. It would be interesting to see if it is in fact possible to edit an existing iOS app and have it still work and all without the original coder’s digital certificate. If successful, I think the first order of business would be to remove the ads you might see during game play. Another personal goal would be to allow multiple friends on iOS devices to play the FFA (free-for-all) mode of the game with each other; this could be made possible with a proxy server, I’d propose.

The platform

Currently, I play the Agar.io game on an iPad II since I prefer the interface over a browser-based version that’s available. So I will be attempting to hack the Apple store app ultimately.

This may turn out to be impossible since an app that runs on iOS is supposed to be digitally signed to prevent tampering. And yet this is what I intend to do, nonetheless. I’ll be testing that assertion to see if a hacked app will still work.

Concepts

Here, I’ll discuss some of the concepts of the approaches I’ll take.

  • Patching:  Patching is an old-school technique in which binary code, for example, is edited in place with a script. Individual characters or code is replaced in the original to create a new file. The patch program itself works together with another program called diff, used to calculate the differences between two files.
  • DNS:  This service is responsible for looking up a name like m.agar.io and replacing it with an IP address.
  • Redirection:  Using your own DNS server so that you can redirect requests to your own website instead of the intended one.
  • iOS app:  An iOS app might seem a little daunting if you’re not a coder. It’s actually a collection or manifest of files all rolled up into one .ipa file. I think it’s safe to say that the app was written in Apple’s Xcode using a computer language like Objective-C or Swift.
  • Ad-based add-ons:  It’s clear that Agar.io has many opportunities to display ads within the game itself. The programming interface to these (for the Agar.io developer) is almost always JavaScript-based.
  • Tethering:  Connecting a smartphone—or the iPad in this case—to a computer to allow for interaction (like development testing) to occur.

Throughout this series of posts keep in mind that if I’m indicating a command, it’s often being done on a MacBook with OS X 10.11.5 El Capitan at a shell prompt. Otherwise, I could be referring to something I’m doing on an iPad II with iOS 9.3.2 installed.

DNS server

I’ll be using the Dnsmasq easy-to-implement DNS server for redirecting Agar.io’s server requests to my own website. I’ll then configure my iPad to use this server first when doing DNS lookups.

Discovery website

And since I’m familiar with Node.js and Express I’ll be using this to mockup a website for those redirected app requests. When the iPad makes a request to what it thinks is the Agar.io website, I will see that request in my website’s logs.

This could be technically called a man-in-the-middle technique since I could then have my own website forward the request to Agar.io’s actual server and then answer the iPad with that response, adjusting it if I wanted to. I guess technically you could also call this a proxy approach.

Binary editor

I’ll likely also use Hex Fiend at least minimally to find the location within the main program app where I’ll be patching the code.

Installing a modified app

Normally, you would download an app directly to our iPad straight from the Apple iTunes store. Technically, I suppose, I could have taken advantage of the redirection concept from before to steer the iPad to my own website to deliver the edited content but it’s not that difficult. There appears to be a mechanism so that you can download iOS applications on an OS X computer and then, while tethered, install them remotely using iTunes. This actually allows us to use a MacBook in this case to snag the code package itself and to start all the fun. We’ll be taking advantage of this in order to then try to push a modified app package to the iPad.

If you’re on a standard OS X computer and you get the Agar.io app, it won’t seemingly do anything after the download; you’re not presented with the usual Open button after it has downloaded. It does, however, get silently copied to your hard drive under your user folder in /Users/username/Music/iTunes/iTunes Media/Mobile Applications. Having downloaded it, you should find a file called Agar.io 1.3.0.ipa which is the app (collection) itself.

Expanding the app

From here, you might not know that an .ipa file is little more than a .zip file. I’d suggest copying the Agar.io app file somewhere else (like creating a folder called AgarIO) and then open a shell so that you can decompress it.

MacBook:AgarIO$ unzip "Agar.io 1.3.0.ipa"

This command then will decompress the collection of files for you.

What’s inside the .ipa file

There are a lot of files inside this package, just like you’d find with most store apps. The first I’ll discuss is iTunesMetadata.plist which is perhaps the most aggravating of all. A .plist file is like a database for a coder, it usually stores configuration options. Opening it with TextEdit then shows me that this is the file responsible for knowing who downloaded it (myself) and how I’m then authorized to use it. I’m sure there’s a similar mechanism inside any music file you download from iTunes to prevent you from playing it on an unauthorized device. So in other words, I couldn’t just patch the Agar.io application and then make it available for download for others. Each person interested in this would need to go through the motions themselves.

Next, there is a META-INF folder which contains two files. I haven’t fully investigated them yet but the first is com.apple.FixedZipMetadata.bin which appears to again be a compressed collection of files. And the second is com.apple.ZipMetadata.plist. It appears to have some indication of how the actual program was zipped up into an .ipa file.

The final folder is Payload which includes what appears to be a single file, Agar.io. Or, is it a single file? Knowing what I do about making iOS apps, it’s actually another compressed file. In Finder, you’ll want to rename this Agar.io file to Agar.zip, for example. Back in your shell, then unzip it as you did before to expand its contents.

What’s inside the Payload file

So now we’re getting down to the actual programming itself. Everything we have seen up until now is just a wrapper so that iTunes and Apple can provision an app to you and just your device(s).

Surprisingly, there are a total of 1,111 .png graphic files inside. Most seem to represent the many skins that you’ll see in the game. There are 153 .plist files which are used to store anything from advertisement configuration information, to promotions, to language localization information and collections of available skins by category. With respect to my goals, I’m not really interested in these. And there is a single .db file for the Vundle advertising platform.

There is a folder called _CodeSignature which appears to include hashes of the collection of graphics, presumably to prevent them from being edited perhaps.

There are 65 .ccbi files which appear to be another form of .plist files. There are 15 .json files which appear to have different localized versions.

Finally, there is agar.io which is the actual program file itself. I’ll save the actual editing for a follow-up post to this one.

Status

That’s a good start so far. We’ve downloaded the Agar.io app and performed two decompression steps to get at the actual executable itself. Next, I think I’ll switch gears and build the discovery website and DNS server so that I can get at the app’s server interface.

Update

Skip to the final post in this six-part series if you’re looking for the code. Enjoy!