Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Thursday, August 29, 2013

Basic SWF Bytecode modification (AVM2/AS3) tutorial

I decided I would write up a basic SWF modification tutorial, and explain the basics of SWF modification, AoBs, ect.
I'm gonna go into some serious detail in this tutorial, so be prepared.

Before you start doing any extreme SWF hacks, you're gonna need a pretty good understanding of how SWFs work. Luckily, there are a lot of tools out there nowadays that allow you to take apart a SWF and see it's juicy innards.

There are some things you will need to know

A SWF file always starts with a SWF header, containing compression information, SWF filesize, frame count, frame rate and stage size.
You don't need to know too much about the SWF header, but it is useful to note that all uncompressed SWF files start with "FWS" and all compressed SWF files start with "CWS".
Another thing to note is if the file size in the SWF header is wrong the SWF will most likely not load.
This limitation stops you from being able to increase a SWFs size in memory after it is loaded (however, even if it didn't, forcibly increasing a SWFs size in memory could create a whole lot of problems).
It also means if you increase or decrease the SWFs size when hex editing and don't update the SWF size in the SWF header, the SWF will almost certainly not load.

A SWF is made up of many AVM2 tags. Tags can contain many different things, such as images, shapes, data, actionscript bytecode. If you want to have a look at the tags in a SWF, the tool SWFWire Inspector will disassemble AVM2 tags. Most of the time however, the only tags you will need to care about are the ABC (Actionscript Bytecode) tags.

An ABC tag contains AVM2 ABC bytecode  (sometimes just referred to as AVM2 bytecode or ABC bytecode) which contains class definitions, methods, variables, basically all the compiled code.
There can be more than one ABC tag in a SWF. This generally happens if a SWF uses a code library. The code library is often held in a separate ABC tag from the SWFs main code.

ABC code is stack based. You should be familiar with how stacks work in programming. It's nothing particularly difficult. There's a stack. and ABC instructions access it. That's about all there is to it.

Now to the actual tutorial part.


Part 1: Reverse engineering

I'm going to cover SWF bytecode modification using an AVM2 ABC disassembler, hex editor and decompiler. There are other "better" ways of modifying SWFs, but learning how to hex-edit SWFs is pretty much SWF hacking 101. Everything else follows on from it. Thus, even though there are better ways of doing this, it is an extremely good idea to learn this method before learning the others.

In this tutorial, we'll do a score hack. There's many different ways we could do this. we could increase the score gained from picking up a money item, we could increase the starting score, we could teleport the money object to the player or any number of other ways.

I'll try and cover several different approaches to several different types of score hacks. There are many correct ways of approaching this problem.

For those of you who don't know, unhackable is the name of a simple game engine I use for tutorials, examples and proof-of-concepts. The name "unhackable" comes from the fact I originally made it to test AS2/3 anti-hack code. It's basically the simplest game you could make. I've written about 5 different versions of the unhackable engine, this tutorial will be for the unprotected OOP version of unhackable, which you can find here.

Open up the unhackable SWF in FFDec or another similar decompiler.

We'll start with a little reverse-engineering. SWF reverse engineering almost deserves a tutorial of it's own, but it's the kind of thing that you can only really get good at with practice.
This example SWF isn't very complicated, so there's nothing too deep here. For starters, take a look at the names of the classes:


Obvious classes of interest include Money, Player and ScoreKeeper. The document class is also usually useful (Found by going tools -> go to document class). In this case, the document class is named Unhackable.

So, for starters, take a look at Unhackable.


It's good to note that the player, money and score variables are private. This isn't so important for bytecode modification, but if you were to hack it via loader or overrider, it would be relevant.
Most of this code is useless to us.
Lines of interest for us include:

From the Unhackable constructor:
      this.player=new Player(int(Math.random()*300)+50,int(Math.random()*200)+50);  
      this.money=new Money(int(Math.random()*300)+50,int(Math.random()*200)+50);  

From the gameLoop function:
      this.money.dealWithPlayer(this.player.playerX,this.player.playerY);  

If you take a peek into the Player and Money classes, you'll see they pass their constructor arguments on to their super class Thing, which uses  them to set their position, so in actual fact these lines just create a new Player and Money object with random position. The only thing you could accomplish by changing these two lines is changing the player and money starting position, so it  turns out these two lines are not so helpful.

I'll get to the money.dealWithPlayer line in a minute.
So, for the moment let's move on to the Money class

.

Now, we get to some interesting stuff. But first, it's good to notice Money has a super class Thing. It's usually worth taking a quick look in the super classes as there's usually useful stuff in them. This tutorial is getting pretty long, so I'll skip the Thing class. There's nothing particularly important that isn't self-explanatory in there anyway, but you should definitely take a look at it. I'm not going to cover the Player class either since it's long and doesn't need to be reversed for the score hack, but it also extends Thing.

The dealWithPlayer function takes two ints. If we look up the code in the Unhackable class, we see that those ints are the players x and y position. It then compares the players x and y to it's own x and y boundaries, and if the player is within it's boundaries (meaning the player and the money objects are colliding) the money randomizes it's position and calls the addMoney function.

From this point, we have enough information to perform several score hacks.
We could modify the Money class and remove the if statements checking the players position so the player is always colliding with the money.
We could modify the Money class by making it not randomize it's position when the player touches it, or even make it teleport to and follow the player.
We could modify the Unhackable class so that it passes the Money's  position to the dealWithPlayer function instead of the Players since the money is always "colliding" with itself.

But for now, let's move on to the ScoreKeeper class. There may well be a simpler score hack waiting for us in it.


Look at that juicy addMoney function.
There are two obvious hacks you could do here. You could change the line:
gameScore=gameScore+1;
to something like:
gameScore=gameScore+100;
or you could modify the static initializer.
The static initializer is the function that's called to initialize the static class.
It's not normally shown in the decompiler, but the code that sets gameScore to zero and the code that sets score to a new TextField are both in the static initializer.
We'll get to the static initializer in a second. First, we'll create our first AoB and make a simple score hack that gives you 100x more score via hex editing.

Part 2: A simple hack

Click the "view hex" (button with green on it) in the top-left corner of the bytecode window.
Click somewhere inside the code for the addMoney function, you should see some ABC bytecode and commented out green hex codes in the bytecode window.


Don't get too scared of the bytecode. It's not as nice to read as AS3, but you'll get used to it after a while. Practice makes perfect.
You definitely don't need to understand all those ABC codes. You can find a list of all ABC bytecodes and what they do here. I recommend looking some up just to get the hang of things

Anyway, what we want to do is change the +1 to be +100. This is done by changing the "pushbyte 1" opcode to be "pushbyte 100".
So, first we need to create a "find" AoB. this is simply done by taking the hex codes of a bunch of subsequent instructions around the byte we want to change.
Usually a hex string of 8 bytes or so is enough, but on some larger games longer strings are needed.
Let's take the hex from line 1 to line 15
d0 30 5e 1c 60 1c 24 01 a0  61 1c 60 1d
Now we need to make a hack AoB.
The opcode we want to change is the "pushbyte 1" opcode, which has the hex "24 01"
If you look it up in the AVM2 instruction list in the link above I gave above you will see the pushbyte instruction has the opcode 0x24 and is followed by an argument which is the signed byte to push onto the stack.
If you don't understand half of that above sentence, that's ok. Long story short, by changing "24 01" to "24 64" (0x64 = 100) we will change "pushbyte 1" to "pushbyte 100" and change the line:
gameScore=gameScore+1;
to:
gameScore=gameScore+100;
Therefore, our hack AoB is
d0 30 5e 1c 60 1c 24 64 a0  61 1c 60 1d
(the only difference between the hack AoB and the original is "24 01" being changed to "24 64")

Firstly, the SWF needs to be decompressed. You can get a SWF decompresser here. Drag a SWF onto the decompresser to decompress it.
Once the SWF has been decompressed, open the SWF in your favorite hex editor. I'm using HxD.
You should see the SWF file starts with the text "FWS" (hex: 46 57 53). This is the "magic number" for an uncompressed SWF as I mentioned earlier. All uncompressed SWFs start with these bytes.

Use the find and replace function in your hex editor to find the "find" AoB:
d0 30 5e 1c 24 01 a0  61 1c 60 1d
and replace with the hack AoB:
d0 30 5e 1c 24 64 a0  61 1c 60 1d
Save that and you should see your score goes up by 100 instead of one each time you get the money.

If it works, congratulations! If it doesn't, try again!

For the purposes of this tutorial, I have changed one of the lines in this class to make it easier to hack.
The line:
gameScore=gameScore+1
was originally
gameScore++
This may seem like a pointless modification, but both lines compile into different bytecode, and "++" is harder to hack via hex editing than "+=".

Long story short, it changes the lines:
pushbyte 01
add
to be
increment
since increment is a one-byte opcode, this means you cannot make a simple AoB to modify it to add 100, since you would have to fit 3 bytes of instructions in 1 byte, which is impossible. You would have to update the file size in the header, which is messy and not-so-straightforward to do.
Instead, in this case the easiest hack would be to simply change the starting score.
In order to do this, you will have to modify the static initializer I mentioned earlier.

Part 3: Modifying a static initializer

Go to the ScoreKeeper class in FFDec if you aren't already there.
To access the static initializer, click on "class intitalizer" in the traits window in the bottom left corner.


 

the line we want to change is the one setting gameScore to 0, so we will modify the pushByte 0 to be a pushByte 100 making us to start with 100 score.
Do the same as before, use line 1 to line 13 for the "find" AoB:
d0 30 5e 1c 24 00 61 1c 5e 1d 5d 1e
and change 24 00 to 24 64 like before for the hack AoB
d0 30 5e 1c 24 64 61 1c 5e 1d 5d 1e
Open the decompressed SWF up with your hex editor, find and replace, save and you should start with 100 score.

That concludes the easy part of this tutorial. For the next part, we're gonna do something more complicated. To start with, we're going to modify the dealWithPlayer function on the Money class so that the money thinks it's always touching the player.

Part 4: The NOP instruction

Go to the Money class in FFDec, and make sure you re-enable decompilation.
What we're going to do is replace the code for the if statements with NOP opcodes (0x02).
A NOP or No-OPeration opcode is an opcode that does nothing. It simply fills space and gets skipped over. Replacing a piece of code with NOPs effectively removes the code, and by removing the if statements, the code for gaining money will always be run.


The bytecode in the function should be in the same approximate order as the AS3 code.
If statements in bytecode are done using conditional jumps (iffalse, ifne, ect). These basically check the top item(s) on the stack, and skip to some instruction if conditions are met.
In order to not mess up the stack, we have to remove the conditional jumps and all the code related to them, meaning we need to replace all the ABC code for those lines with NOPs.
Luckily, the code is all in one place at the beginning.
The last conditional marks the end of the if statements. you will find it on line 60 of the commented ABC. The start of the if statement code is line 5 of the commented ABC code.

therefore, we have to NOP out everything from line 5 to line 60.
Here's the before AoB:
d1 60 10 24 0a a0 ad 2a 12 08 00 00 29 d1 60 10 24 0a a1 af 12 4c 00 00 d2 60 11 24 0a a0 ad 2a 12 08 00 00 29 d2 60 11 24 0a a1 af 12 34 00 00
And here's the hack AoB:
02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
Hex edit that into the swf, open and you should see your score going up from doing nothing, and the money rapidly randomizing it's position as you automatically pick it up.

this hack could also be performed by just NOPing out the branches and using POP (0x29) to remove any leftover elements on the stack.
e.g using the hack AoB:
d1 60 10 24 0a a0 ad 2a 02 02 02 29 29 d1 60 10 24 0a a1 af 02 02 02 29 d2 60 11 24 0a a0 ad 2a 02 02 02 29 29 d2 60 11 24 0a a1 af 02 02 02 29
In the above AoB each iffalse (12 XX XX XX) was changed to NOPs followed by a pop (02 02 02 29)
This stops the jump from happening and removes the item on the stack that would have been tested by the if. If you wanted to make the code in the if statement never run (i.e make the jump always occur), you could either NOP the code inside the if statement out or replace the conditional jump with an unconditional jump (For example, changing 12 XX XX XX to 11 XX XX XX). There are more ways to do this, but these techniques will work as well as any other.

That's enough on NOPing. Let's move on to an advanced modification involving writing some actual bytecode.
Don't worry, this is still going to be relatively simple. We're gonna make it so the money teleports to and follows the player instead of randomizing it's position when we pick it up.

Part 5: Intermediate bytecode modification

Open up an unmodified Unhackable SWF in FFDec, and go to the dealWithPlayer function in the Money class.
Take the moment to remember that the arguments passed to the function where the players X and Y position.

Long story short, we want to change the lines
               drawX=int(Math.random()*300)+50;
               drawY=int(Math.random()*200)+50;
to be
               drawX=param1;
               drawY=param2;
The code for these lines starts directly after the last iffalse on line 61 of the commented ABC code.
It ends on line 100 where drawY is set.
If you haven't realized yet, ABC bytecode tends to be in reverse order of the AS3 code. Not always, but a lot of the time. For example, the leftmost (or first) part of the bottom line of AS3 code is setting drawY, where as the last line of ABC bytecode is the line that sets it.
This should make sense if you think about it in terms of the order of operations. If you were to execute this line, the first thing you would do is go inside all the brackets. You would get the random number, multiply it by 200, convert the result to an integer, add 50 then set drawY by the result. This is exactly how the AVM2 runs this bytecode, however due to how the commands work, the objects have to be placed on the stack in a specific order for these to be calculated properly. This is because only the top element of the stack can be accessed.
For example, the first code that's run for this line is:
findproperty m[16]"drawX"
this is because the last line is
initproperty m[16]"drawX"
which takes two items off the stack:
the value
the property
in that order. this means before the calculations can begin, the property has to be added to the stack so that the items are in the right order for the last instruction.

Why is all this important, you ask?
because a lot of the time ABC instructions won't operate the way your intuition tells you they do, and they tend to have to be in obscure orders to operate properly. This is one of the reasons bytecode is so painful to work with. you might have to add an instruction 20 opcodes above the one that needs it in order for it to work properly.

Now that we've got all that out of the way, let's make a "find" AoB for this code from lines 63 to 98 (the first and last code from these lines don't need changing so aren't apart of the AoB):
5d 03 60 20 46 21 00 25 ac 02 a2 46 03 01 24 32 a0 68 10 5e 11 5d 03 60 20 46 21 00 25 c8 01 a2 46 03 01 24 32 a0
What we're gonna do is replace all the code between the first:
findpropstrict m[3]"int"
and the first:
add
(lines 63-78)
with NOPs and getlocal1 (the local register containing the first parameter)
Quick piece of information: local registers act like temporary variables that only exist inside a function
We will also replace the code in the next line the same, changing the lines 83-98 to be NOPs and getlocal2 (same as local1 but with second parameter)
This gives us the hack AoB:
02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 d1 68 10 5e 11 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 d2
We can clean that up and make it look prettier by moving all the NOPs to one end:
d1 68 10 5e 11 d2 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
hex edit that into your SWF, and it should work. Touch the money to make it start following you.

Part 6: AoB memory editing

You may have heard the term AoB before in relation to modifying a SWF while it's running after it has been loaded into memory using a memory editor such as Cheat Engine.

The AoB codes we've created are the same as ones that would be used with software such as cheat engine. However, there's some things you need to understand about AoB modification via memory editing before you can start making hacks using it.

The Actionscript Virtual Machine uses something called a JIT Compiler (Just-In-Time Compiler). The JIT compiler compiles the SWF into machine code to be run on the CPU. The JIT compiler doesn't compile a function until it's first run, but once it's compiled the SWF bytecode for that function never gets accessed again. Therefore, memory-based AoB modifications have to be done BEFORE the JIT compiler is run and therefore BEFORE the function is first called.
Usually this means they have to be applied in the game's menu before starting the game, or in worse cases before the game starts to run.
In our case, all the AoBs we've made are for functions that are run when the game first starts, thus they cannot be used for memory-based AoB hacks.

After note:

Since I had to modify the Unhackable SWF several times while making this tutorial, there is a chance that some of the bytecode and AoBs are wrong. Here's hoping that's not the case, but it's totally possible. If you find something wrong, leave a comment.

If you're wondering what to learn next, I'd recommend  playing around with some proper ABC bytecode editing software, such as Yogda, RABCDASM or even the bytecode editor in FFDec.
For further reading, I'd recommend skimming through some of Adobe's SWF Specification.

More specifically, I'd recommend any beginner learn a bit about the constants table. Yogda is especially useful for that.

Hopefully this tutorial is cohesive. I tried to make it as in-detail as possible since all the other SWF modification tutorials I've seen have been pretty terrible.

Lastly, I'd really appreciate some feedback on this tutorial, such as whether it was useful or not, whether it was detailed enough or too detailed, ect.

Friday, July 5, 2013

An Introduction to SWF Obfuscation

I keep running into people who need a good explanation of obfuscation. Since it's a pretty difficult subject to go into any detail in, I thought I should do a post about it so I don't have to spend half an hour explaining it to people every time someone wants to learn more about it.

So, what is obfuscation in general?
Obfuscation is the art of making code, compiled or otherwise, unreadable. In programming, it's generally used to make code harder to decompile, disassemble and reverse-engineer.

There are two main forms of obfuscation used on SWFs. Name obfuscation, and Bytecode obfuscation. Normally, the two are used together, and SWFs that only use one are quite rare.

Name obfuscation is simple. Take the names of every class, variable and function and change it to some randomly generated junk.
For example, if you had a class named "player", it might be renamed to "d+.{8]R0%9r".
This makes it difficult to easily identify what classes/functions/properties do what.
Name obfuscation is impossible to reverse. The best you can do is change it to something like class1, class2, class3... function1, function2, function3... ect. Or alternatively, you can reverse engineer the classes and manually re-name them as you figure out what they do, but that is incredibly time consuming, impossible to automate and you still won't end up "reversing" the obfuscation as such, just giving useful labels to the obfuscated classes.

Two lines of  AS3 with compiled AVM2 Actionscript Bytecode
Bytecode obfuscation is a much more complicated subject.
There are many forms of bytecode obfuscation. Some add junk code, some add extra code branches, some restructure the code. There's a crapload of different ways to do bytecode obfuscation.
In order to understand bytecode obfuscation, you have to understand the difference between AS3 and AVM2 Actionscript bytecode. A SWF does not contain any AS3 code in it, but rather a compiled lower-level language. Comparing the code in a SWF to AS3 is like comparing Assembly to C++ (google them if you want).
This difference in languages means that you could in theory have AVM2 Bytecode that has no equivalent in AS3. Bytecode obfuscators use principals like this to their advantage.
They can crash decompilers by adding invalid code to the SWF that in practice, will never be run, and the decompiler will be unable to decompile the code, since the obfuscated AVM2 code in the SWF has no AS equivalent.
Over the years, bytecode obfuscation has gotten more and more advanced. Back in the day, you could remove it with a hex editor if you knew what to search and replace for. Nowadays, it takes complex programs purpose-written to take out specific obfuscation algorithms to remove such defenses.

Apart from completely thwarting the use of decompilers, bytecode obfuscation has another use. By adding lots of junk bytecode and restructuring the bytecode, it makes it much harder to reverse-engineer the disassembled code. This, coupled with name obfuscation can make it near impossible for most hackers to make hacks and reverse engineer the SWF in general. As you can see above, two lines of AS came out to be about 15 lines of AVM2 ABC  Bytecode. It is not uncommon for an obfuscated class to contain well over a thousand lines of such code, barely readable even without obfuscation.

However, most if not all bytecode obfuscation is theoretically removable. That being said, it's almost always impractically difficult to do so.

So, how do we actually deal with obfuscated SWFs, you ask?
The Free and open-source decompiler JPEXS FFDec has some very good deobfuscation routines in it. If that doesn't work:
My biggest piece of advice would be to look for useful unobfuscated strings. Name obfuscation does not obfuscate all strings. names and packages of Adobe classes tend to stay unobfuscated. So do events a lot of the time. you can always go through the strings constant pool (using Yogda or another bytecode editor). Finding unobfuscated strings can quite often allow you to figure out what's what, and a lot of the time it's pretty much the only option you have.
Another piece of advice is don't tackle obfuscated SWFs until you are very confidant with working in bytecode. It's not easy. Even the best hackers tend to dread dealing with obfuscated games.

I would also recommend using a variable scanner if you can, however there are not many (if any?) good AS3 var scanners (there's my shitty one, and AS3Watson), since they really only started being publicly released a year ago, and I don't think there's a single tutorial on the internet on AS3 var scanning. I'll probably make one some time, but not for a while.

I could have written more. Maybe I'll do another post, or a series of posts on obfuscation in the future. There's heaps to write about, and I only scratched the surface on most of the things I mentioned.

Hopefully this is readable and makes sense. I'm pretty exhausted right now.

Thursday, April 4, 2013

Manatee SWF Decrypter V3

Funny story, I was gonna release this a week ago, but my laptop charger broke as I was typing this out. I was hoping to get a release out before the end of the month, but nonetheless here's V3 of my decryptor!Those of you who were paying attention will probably be wondering why there's no V2.
Here's a little explanation:
The V1 method simply loaded the SWF and scanned it for loaders.
The V2 method (which I didn't finish because I discovered the superior V3 method while working on it) functioned by overriding the Loader class in a loaded SWF. some of you may have realized by now that Adobe classes cannot normally be overrided, but with a little black magic, you can do the equivalent.
The V3 method works by using the debug version of flash player and editing mm.cfg to load the SWF alongside the target SWF, and a little black magic.
The V3 method is much harder to detect and defend against than the V1 and V2 methods and less buggy since it doesn't utilize the Loader class to load the game.

Installation
Download and install the flash content debug player on this page
Download this SWF (it's also on the downloads page) and move it to:

C:/ManateeUniversalDecryptorV3.swf

open (or create and open if it doesn't exist):

%userprofile%/mm.cfg

in notepad or equivalent and add the line:

 PreloadSwf=C:/ManateeUniversalDecryptorV3.swf  

to your mm.cfg file.
A helpful hint if you start getting annoyed with all the errors is to add the following line to your mm.cfg

 SuppressDebuggerExceptionDialogs=1  

and then use  the "silent" mode (which I will mention later).

Usage
Once Manatee SWF Decrypter has been installed, it will be automatically injected into any game running in the debug player. So, to use it you just open the game in the debug player you installed. (eg, if you install the Firefox debug plugin, open the game in Firefox to inject the decrypter into it)
Manatee SWF Decrypter V3 is controlled entirely with the numpad.
There are two output modes: normal mode and the slightly ironically named silent mode.
Normal mode outputs messages by throwing errors, and silent mode outputs messages by beeping.
Numpad 1 enters silent mode, and numpad 2 enters normal mode.
Numpad 5 is a kind of "hello world" button that in normal mode simply tells you that the decryptor is connected. In silent mode, a single "beep" shows that the decryptor is connected.
Numpad 3 tells you if there's remaining SWFs to be dumped. in normal mode it throws an error telling you exactly how many SWFs are left for dumping. in silent mode, 3 beeps means 1 or more SWFs remaining, and 9 beeps means there are no SWFs remaining.
Numpad 0 dumps remaining SWFs. In normal mode, it tells you how many SWFs are remaining when the SWF finishes saving. In silent mode when the SWF has finished dumping you get 3 beeps if one or more SWF is remaining to be dumped or 9 beeps if no SWFs remain to be dumped.

Rule of thumb for silent mode:
1 beep = the decryptor is connected
3 beeps = 1+ SWFs remaining
9 beeps = 0 SWFs remaining

Currently, the only major bug is sometimes the AVM2 garbage collector destroys the ByteArray the SWF is held in before you get a chance to dump it.
It doesn't usually happen to "important" SWFs though, so fixing that bug is pretty low priority for me.

Tuesday, January 29, 2013

BPE Pre-Alpha V1.2

With this release comes good news and bad news.
The bad news is my prehook system doesn't work, so I'm going to have to find a new way of adding IP hooks. I've looked at several alternatives and found that I could quite easily make a cross-platform hook for Linux/Mac, but Windows doesn't like letting anyone do any low-ish level network hacks.
The good news is that PEW support has been added, which is a pretty big thing.
I've actually fixed the multiple server hook bug this time - connections now go to where they're meant to go.
I've also done a little more work on the GUI, adding the ability to actually remove port hooks and plugins.
It also no longer saves which hooks you were using. Now that Workspaces  are implemented, it no longer needs to.

I'll update the Wiki with some documentation on Workspace files since to load plugins you have to edit the Workspace file via text editor.

I'd also like to point out that now Workspace files have been implemented, BPE is much more friendly towards having complete game hacks released on it since all an end-user needs to do to use a properly set up plugin-based hack is double click a Workspace file.

Feel free to spread this around.
People should use this.

DOWNLOAD

Changelog:

*BPE Pre-Alpha V1.2 (PEPAPI V1.1) (PEWVer 1.0)
  - added PEW/Workspace support
    - added "resetWorkspace", "hookServer", "hookPort" and "loadPlugin" Workspace commands
  - added save & load workspace buttons
    - save function saves server hooks and plugin hooks but not plugin configuration
  - GUI improvements
    - added ability to unload plugins via "Plugin Options" menu
    - added ability to unhook ports via "Port Options" menu
  - fixed bug where BPE would sometimes not close properly and hang in memory
  - BPE now removes server hooks on close, use workspaces to save them
  - made BPE the default file opener for .pew files (secretly done in V1.1)
  - fixed bug where if more than one server was hooked all connections were routed to the first server in the list
  - cleaned up shit tons of code

Thursday, December 20, 2012

Flash AS3 Class overriding template and tutorial

The biggest problem with class overriding I have found so far is that large classes can take a lot of work to "fix" to work with class overriding. So, I have created a template for class overriding that can make this process a vast amount easier.
It certainly has it's limitations, but where it works, it works well.
To be able to use it properly, you need to have a pretty good understanding of how it works.
I'll start with a quick overview of how it works, don't worry too much if you don't understand it properly yet:

A custom loader dynamically generates a SWF containing a single "nullified" class that has no methods or properties and uses class overriding to nullify the document class in an instance of the game SWF (this instance is used solely for accessing the original, unmodified classes in the game).


Template classes use the proxy extends hack to pretend to "extend" the original class in the game. e.g. if you were overriding the class "Money", the template does this by using the proxy hack to pretend to extend the original "Money" class held in the nullified instance of the SWF loaded by the custom loader.

Classes are overridden by extending the BasicOverrider class that is included in the template. This class and the custom loader do all the hard work for you. Any public methods and variables can now be modified, without having to "fix" any code you're not working with.

Here's a nice little visual explanation for the loader:



With any luck, you now have a decent understanding of how the loader works.
so, onto how the template extender works:



If you need more information, you can take a peek at it's source.

Now, hopefully you understand it's limitations. It cannot access private/protected vars and requires a little work to fix type casting problems (Note: a lot of the time this isn't a problem) due to the nature of how it functions.

Now, here's the mini-tutorial and template download link:
You'll need this SWF and the OverriderLoader template for this tutorial.
I will assume you know everything covered in this tutorial.

Setting up the template is really easy.
The SWF name is "Unhackable.swf" and if you open it up with a decompiler, it'll tell you the document class  is "Unhackable".
open up the Overrider class and change:

 loader.load("SWF NAME HERE.swf","DocumentClassNameHere");  

to:

 loader.load("unhackable.swf","Unhackable");  

Next, we need to fix the stage access problem. Unfortunately, template overriding doesn't work on the document class (because it gets nullified so you can load the other classes without running code), so we'll need to use the old method. We'll use the same code we wrote up in the last tutorial. Chuck this code in a new class called "Unhackable":

 package   
 {  
      import flash.utils.*;  
      import flash.display.*;  
      import flash.events.*;  
      public class Unhackable extends MovieClip  
      {  
           private var Player:Class = getDefinitionByName("UnhackableEngine.Player") as Class;  
           private var Money:Class = getDefinitionByName("UnhackableEngine.Money") as Class;  
           private var ScoreKeeper:Class = getDefinitionByName("UnhackableEngine.ScoreKeeper") as Class;  
           private var player:Object;  
           private var money:Object;  
           private var score:Object;  
           public function Unhackable()  
           {  
                this.addEventListener(Event.ADDED_TO_STAGE,addToStage);  
                return;  
           }  
           private function addToStage(e:Event)  
           {  
                this.player = new Player(int(Math.random() * 300) + 50,int(Math.random() * 200) + 50);  
                this.money = new Money(int(Math.random() * 300) + 50,int(Math.random() * 200) + 50);  
                this.score = new ScoreKeeper();  
                addChild(this.score as DisplayObject);  
                addChild(this.money as DisplayObject);  
                addChild(this.player as DisplayObject);  
                stage.addEventListener(Event.ENTER_FRAME, this.gameLoop);  
           }// end function  
           private function gameLoop(event:Event)  
           {  
                this.money.dealWithPlayer(this.player.playerX, this.player.playerY);  
                this.player.doMove();  
                return;  
           }// end function  
      }  
 }  

Now that that problem's solved, we can get on to using the template for something useful.

We'll make each money pickup give you 100 score.
Now, if you remember, the actual score variable is private, which means that template overriding can't touch it. however, the static "addMoney" method is public and can thus be edited.

So, let's start with a basic overrider template class, then.
Create a new class in the package "UnhackableEngine" called "ScoreKeeper" and give it this code:

 package UnhackableEngine {  
      import OverriderLoaderUtils.BasicOverrider;  
      import flash.utils.*;  
      public class ScoreKeeper extends BasicOverrider {  
           public function ScoreKeeper() {  
                super(getQualifiedClassName(this));  
                origObject = new origClass();  
           }  
           static function addMoney()  
           {  
                origClass.addMoney();  
           }  
      }  
 }  

This is just a basic overrider template class with a wrapper function for the addMoney static method (as all static methods need wrapper functions when using the template). Our goal right now is to get it to compile with this.

So, lets add the line

 var scoreKeeper:ScoreKeeper;  

to our Overrider class to make it all compile together and see what errors we get.
You'll get an error telling you it doesn't want to be added as a child. We've been here before, haven't we? last tutorial?
Change:

 addChild(this.score as DisplayObject);  

to:

 addChild(this.score.origObject as DisplayObject);  

in your Overrider class to make it quit it's bitching. Compile, and it should be happy.

Now all we need to do to make money add 100 score is go to our ScoreKeeper class and change:

           static function addMoney()  
           {  
                origClass.addMoney();  
           }  

to:

           static function addMoney()  
           {  
                for(var i:int = 0;i<100;i++){  
                     origClass.addMoney();  
                }  
           }  

Compile, and you're done!

Here's the finished source code for the tutorial.


Oh, and if you're wondering how to fix static variables, you do something like this:

           static function get varName():Object  
           {  
                return origClass.varName();  
           }  
           static function set varName(value:Object):Void  
           {  
                origClass.varName = value;  
           }  

Where varName is the name of the variable.

The pros of using the template:
- no need to fix any non-static functions
- static functions only need to be redirected, so fixing is much simpler compared to the old method

The cons of using the template
- doesn't work on the document class
- doesn't work on private/protected vars/methods
- type casting is still a problem

Monday, October 8, 2012

BPE Plugin Writing Tutorial #1 (Writing your first plugin)

So, I thought it was about damn time I wrote a tutorial on writing plugins for BPE (Mostly because currently I'm the only person who knows how).
Firstly, I've been updating the Wiki, so hopefully between this tutorial and the Wiki, there should be enough information for people to start writing plugins.
 and now the tutorial:

Writing your first plugin.

So, we're  gonna make a nice, simple plugin that simply outputs everything happening on the servers/ports being listened to.
It'll do the following:
Properly set up it's window
Output all sent/recieved packets
Output when connections are opened/closed

Now, let me explain a little about the hook system BPE uses. there are two kinds of hooks:
Hooks called by BPE, and
Hooks called by the plugin.

Hooks called by BPE are utilized by creating a public function in the document class of the plugin.
eg:

 public function sendPacketHook(packet:ByteArray,socketID:int):ByteArray  
 {  
     output.appendText("["+socketID+"] Sent:"+packet+"\n")  
     return packet;  
 }  

That above code would be called every time a packet is sent by the client. the variable "packet" contains the payload (data) from the packet in the form of a ByteArray. socketID is an integer containing the ID of the socket. The function returns the unmodified packet, so no modification is made.

Hooks called by the plugin are utilized by creating a public Function variable in the document class of the plugin, and then calling that variable/Function when you need to.
eg:

 public var updateWindow:Function;  
 public function someFunction():void  
 {  
     updateWindow(550,400,"Debug");  as
     return;
 }  

That above code (when someFunction is called) will scale the size of the window so that the stage is 550 pixels wide and 400 pixels high, then set the plugins window title to say "Debug".

Also note that all used hooks must be specified in the .pep file that goes with the plugin (more on that later, though).

Anyways, I hope that's enough explanation for understanding the hooking system for now. let's get on to making the actual plugin!
I'm going to assume you know your way around Flash and know a little AS3 at this point.
So, create a new AS3 project and a document class called "BPEDebugPlugin".
now, we're gonna be using ByteArray's (for the sent and received data) and TextFields (for the output), so go ahead and add these lines to the includes:

     import flash.text.TextField;  
     import flash.utils.ByteArray;  

Now, we're gonna need to declare a couple variables in the class.
Firstly, since we want to set the window size and title, we want to use the updateWindow hook, so we need to add a Function variable with the name updateWindow.
Secondly, we want a TextField that we can write our outputted data to.
so, add these lines to your class variable declarations

         public var updateWindow:Function;  
         private var output:TextField = new TextField();  

we're gonna make use of the finishPluginSetup hook. this simple hook function is called after your plugins hooks have been set up and your plugin has been added to the stage. it basically tells you it is now safe to use hooks and access the stage.
Chuck this code right after the end of your constructor function:

         public function finishPluginSetup()  
         {  
             updateWindow(550,400,"Debug");  
             output.x = 20;  
             output.y = 20;  
             output.width = 510;  
             output.height = 360;  
             output.background = true;  
             output.backgroundColor = 0xAAAAAA;  
             output.text = "Output\n";  
             this.addChild(output);  
         }  

As stated before, this function will be called once, when BPE has added it to the stage and set up all it's hooks. it calls the updateWindow hook and changes the window size and label. it will then set up the output TextField for use.

Now, let's get to the actually useful hooks. We'll start with the send and receive hooks, since they're super-similar, and quite simple.

         public function recievePacketHook(packet:ByteArray,socketID:int):ByteArray  
         {  
             output.appendText("["+socketID+"] Recieved:"+packet+"\n")  
             return packet;  
         }  
         public function sendPacketHook(packet:ByteArray,socketID:int):ByteArray  
         {  
             output.appendText("["+socketID+"] Sent:"+packet+"\n")  
             return packet;  
         }  

These functions will be called by BPE every time a packet is sent by the client or received by the client. packet is the ByteArray containing the data payload of the packet, and socketID is the ID number for the socket. We'll output the data being sent in the packet.
This is probably a good time to introduce you to BPE's socket ID system. each socket that connects to BPE is given an ID to make them easy to keep track of.
The first socket to connect is given the ID 0
the second 1
the third 2
ect.
The functions then output the sent/recieved data along with the socket ID.
The ByteArray returned by these functions is then run through any remaining plugins and either sent to the client or server depending on whether the packet is being received or sent.
Since we're returning the same, unmodified ByteArray that was the input of the function, the packet is left untouched. if you return an empty ByteArray, the packet is dropped.

Onto the socketOpen and socketClose hooks.

         public function socketOpenHook(socketID:int,address:String,port:int):void  
         {  
             output.appendText("["+socketID+"] Connected to:"+address+":"+port+"\n")  
             return;  
         }  

The socketOpenHook is run every time a socket connects to BPE. it gives you the new socket's ID, the address it's attempting to connect to and the port on which it's attempting to connect to. We'll output the address and port on the server it's attempting to connect to.

Next is the socketCloseHook.

           public function socketCloseHook(socketID:int,closeSocket:Boolean):Boolean  
           {  
                output.appendText("["+socketID+"] Disconnected, "+closeSocket+"\n")  
                return closeSocket;  
           }  

The socketCloseHook is called when the server disconnects the client. The Boolean closeSocket tells you whether BPE plans on disconnecting the client. if true, the socket is to be disconnected, if false, the socket connected to the client will stay connected. We'll return the closeSocket value given to us to let the other plugins or BPE decide what to do with the socket connected to the client.

Now, compile that sucker and we're up to creating the .pep file to load our plugin.

PEP files are like an external header for the plugin. it tells BPE everything it needs to know to run your plugin.
I created a simple little tool making it easy to generate the .pep file for your plugin. you can get it here or on the downloads page.
Open the PEP Builder up (do it in your browser if you have to).
For plugin name, type "BPEDebug".
For SWF Filename, write the name of your SWF (mine is "BPEDebug.swf")
and we need to tick the box next to each hook we used
tick the box next to hookUpdateWindow, hookFinishPluginSetup, hookRecievePacket, hookSendPacket, hookSocketOpen and hookSocketClose.
Once you've done that, click the "Save PEP File" button, and save it to the same location as your plugin SWF.

You're done!
Load your plugin with BPE, hook a server and port (web servers are the easiest for testing),  and if it works, give yourself a pat on the back.
If it doesn't work, try again or  leave a comment.

Here's a link to my finished source.

Friday, September 14, 2012

BPE Pre-Alpha V1.1

It's finally here!
BPE Pre-Alpha V1.1 and HTTPlugin are done.
I'm tired from programming and testing, so I'm not gonna write much.
Read the readme if you want more.

Find HTTPlugin and the latest version of BPE on the Downloads page.
get BPE Pre-Alpha V1.1 here.

I'm gonna spend any upcoming spare time to write tutorials and update the wiki.

Changelog:
 - changed updateWindowHook
 - added socket ID system
   - updated sendPacketHook
   - updated recievePacketHook
 - added forceRecieveHook
 - added forceSendHook
 - added forceCloseHook
 - added socketOpenHook
 - added socketCloseHook
 - removed PEPAPI V1 support, mostly
 - attempted to make work on Linux and Mac (untested)
 - GUI improvements
   - added "Server Options" window
   - added "Plugin Options" window (incomplete)
   - added "Port Options" window (incomplete)
 - fixed bugs
   - possibly fixed the "multiple hooked servers" bug? (not sure how, might be black magic. the bug should theoretically still be there, but tests indicate it's fixed)
   - fixed problem with data not being sent when a connection was still being fowarded
   - misc other bugs

If I get a Mac tester, I'll try and get Linux and Mac support into the next release.

Tuesday, July 17, 2012

BPE Pre-Alpha V1.0

Here it finally is!
The first public release of my packet editor!

Currently, it comes with no plugins and is windows only, so it will only be useful to those who can program in AS3.
I'm going to be posting tutorials on using and writing plugins for it in the near future, so stay tuned!
In the meantime, you can download the source for a simple Stick Arena Dimensions plugin I made and edit that to work for whatever uses you have.
To use the plugin, hook these servers:
ballistick1.xgenstudios.com
ballistick2.xgenstudios.com
ballistick3.xgenstudios.com
ballistick4.xgenstudios.com
ballistick5.xgenstudios.com
ballistick6.xgenstudios.com
ballistick7.xgenstudios.com
ballistick8.xgenstudios.com
ballistick9.xgenstudios.com  

Or add this to your hosts file:

127.0.0.2 ballistick1.xgenstudios.com #CoreHook IP 67.19.138.234
127.0.0.2 ballistick2.xgenstudios.com #CoreHook IP 67.19.138.235
127.0.0.2 ballistick3.xgenstudios.com #CoreHook IP 67.19.138.236
127.0.0.2 ballistick4.xgenstudios.com #CoreHook IP 74.86.43.8
127.0.0.2 ballistick5.xgenstudios.com #CoreHook IP 74.86.43.9
127.0.0.2 ballistick6.xgenstudios.com #CoreHook IP 74.86.43.10
127.0.0.2 ballistick7.xgenstudios.com #CoreHook IP 74.86.3.220
127.0.0.2 ballistick8.xgenstudios.com #CoreHook IP 74.86.3.221
127.0.0.2 ballistick9.xgenstudios.com #CoreHook IP 74.86.3.222


And hook port 1138.


Currently, you have to manually remove server hooks by editing your hosts file (C:\windows\system32\drivers\etc\hosts).


Anyway, here's the download link for the packet editor.


Current features:
Working plugin system
Working hooking system
Loads previous server hooks when it opens
Probably undetected by most/all current games and anti-cheat systems 


Current known bugs:
Too many to list...


Also: Android has been added to the list of OS's I plan to develop my packet editor for. Support will probably be added for it during Beta.
Linux (and possibly Mac) support will hopefully be added in the next few releases. 

I've also updated the downloads page with BPE and the plugin.

Monday, May 14, 2012

Sitelocked SWF Loader


I just finished my SWF sitelock tool for loading sitelocked swfs offline.
This project is the precursor to the packet editor I'm going to make (vast quantities of this projects code can be recycled into my packet editor).
This loader should be able to load ~95% of sitelocked games. it has one or two limitations though:

It's currently windows only (I might make a linux option in the future. wouldn't be too hard. mac would be possible too).
Generally speaking, it can only load games held in a single .swf file. and it tends to break multiplayer games. Both of those are fixable, but it's probably not worth the effort.

Anyways, here's how you use it:

if for example, you wanted to load a sitelocked swf  offline from www.example.com/folder/test.swf you would set "Server" to "www.example.com"  and "Path" to "/folder/test.swf"
after you've set that up, just drag-and-drop the swf onto the loader to load it.

Note: most games only need to be loaded from the correct server and you can usually leave Path blank.

Here's a picture of me loading an unmodified, sitelocked Stick RPG Complete while not connected to the internet:

Note that Path doesn't actually have to be set to anything, I just did that to show it worked.

Download my SWF Sitelock Tool here:
Download

Also, it's an AIR application, so you need AIR installed to run it.

Tuesday, April 10, 2012

Universal SWF Decrypter

I made a Universal SWF Decrypter based on the method/code I posted the other day.
you can find the windows binary here or on my downloads page.
It should work on all swf encryptions that use an AS3 loader. which means it should work on ALL mochicrypt games. and probably on all other SWF encryptions, too.

*edit*
Go Here for the new Universal SWF Decryptor V3

Thursday, April 5, 2012

Decrypting AS3 SWF's

Today, I found a massive flaw in Mochicrypt and probably all AS3 encryption methods. I'm sure others already know about it, but I'll post it anyway.
Firstly, let me start by explaining how these encryptions work:
The swf is encrypted and stored (generally in the decryptor/loader).
The encrypted swf is decrypted and turned into a byteArray
The decrypted byteArray is loaded using the Loader.loadBytes() method.
The Loader is added to the stage.

and, as it turns out, getting the unencrypted swf from the loader is incredibly easy.
there's this usefull as3 class called "LoaderInfo" that will solve all our problems.
in fact, Loader.contentLoaderInfo.bytes contains the byteArray for the loaded swf.
so, what we can do is load the decrypter, scan the stage's children for Loader objects, find the one for the decrypted swf and dump it's data.

Here's a working example I made for Bloons TD 5:
 package   
 {  
     import flash.display.*;  
     import flash.net.*;  
     import flash.events.*;  
     public class BTD5Decryptor extends MovieClip  
     {  
         private var ldr:Loader = new Loader();  
         private var swf:Object;  
         public function BTD5Decryptor()  
         {  
             ldr.load(new URLRequest("btd5.swf"));  
             ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);  
             addChild(ldr);  
             stage.addEventListener(KeyboardEvent.KEY_DOWN, doKeys);  
         }  
         private function onComplete(evt:Event):void  
         {  
             var ldrInfo:LoaderInfo = evt.target as LoaderInfo;  
             swf = ldrInfo.content;  
         }  
         private function doKeys(e:KeyboardEvent)  
         {  
             if (e.keyCode == 96)  
             {  
                 var file:FileReference = new FileReference();  
                 file.save((swf.getChildAt(1) as Loader).contentLoaderInfo.bytes,"unencrypted.swf");  
             }  
         }  
     }  
 }  

To use it, place the Bloons TD 5 swf in it's folder (make sure it's called "btd5.swf"), open the decrypter, wait for the game to load and then press numpad 0 to save the decrypted swf.

Here's a link to the compiled version of the decrypter (same as the code above):
http://www.mediafire.com/?lfk94ox5ge9i85k

Also note that the above code and decrypter may work on more/all mochicrypt swfs/loaders. I've only tested it on Bloons TD 5's mochicrypt loader as that's what it's made for, but it may very well work on all mochicrypt loaders.
*edit*
it only works on some, not all. I'll release a universal SWF decrypter I've made later today.

Friday, March 23, 2012

Getting around SecurityError #2070

So, today I started playing with some SWF loading code in Flash Builder, and I ran into a common sandbox problem.
You get Error #2070 when a loaded swf in another directory tries to access the stage.
I couldn't get around it by using Security.allowDomain("*") either, because it was an AIR application.
So, to get around this problem I decided instead of directly loading the file using Loader.load() I'd load it by loading the file into a byteArray and useing Loader.loadBytes() instead. and guess what? it works.
It completely gets around the sandbox issue.
Have some code:

 private function loadSwfFromUrl(url:String):void{  
      var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);  
      var ldr:Loader = new Loader();  
      var swf:ByteArray = new ByteArray();  
      var fs:FileStream = new FileStream();  
      fs.open(new File(url), FileMode.READ);  
      fs.readBytes(swf);  
      fs.close();  
      context.allowCodeImport = true;  
      ldr.loadBytes(swf,context);  
      stage.addChild(ldr);  
 }  

There's probably a better, simpler way to get around this sandbox issue, but at least this works.

Saturday, March 17, 2012

Universal Flash Variable Scanner

So, I had an idea for a universal swf variable scanner.
one that works on AVM1 (AS1/AS2) and AVM2 (AS3) swf's.

The main problem you face when attempting to create such a thing is that AVM1 swf's and AVM2 swf's have separate sandboxes.
AVM2 loaders CAN get and set variables in loaded AVM2 swf's.
AVM2 loaders CANNOT get and set variables in loaded AVM1 swf's.
However, there are ways to get around this.

You could theoretically make a universal scanner made up of an AVM2 loader and scanner and an AVM1 loader and scanner.

for scanning AVM2 swf's there is no problem:
AVM2 Master swf loads AVM2 movie and scans it.

But for AVM1 swf's, you have to get around sandbox issues.
My idea works like so:
AVM2 Master swf loads AVM1 Scanner.
AVM1 Scanner loads AVM1 movie.
AVM1 Scanner communicates with AVM2 Master swf using LocalConnection.
AVM1 Scanner scans AVM1 movie.


If you were smart, you could probably remove the need for communication between the AVM1 and AVM2 scanner parts and have them functioning pretty much completely independantly.