I know what you're planning. . . You are trying to make an AoB hack out of some flash games. Don't let me know. I hate keeping secrets for others :)
Some knowledge on ActionScript and general programming required and assumed.
Analyzing the SWF:
AS2.0(AVM1) Manual(legacy): Flash virtual machine - Flasm - Sourceforge
Note: The site above also provides a FREE command-line (Non-GUI) assembler/disassembler of Flash ActionScript bytecode (not sure if it works on AS3.0 as well) DOES NOT RECOVER ACTIONSCRIPT SOURCE
Note: Unfortunately, there is very little documentation about AVM1 on the Internet. Therefore you might want to experiment the instructions yourself using a debugger swf.
Debugger for Flasm developer: http://www.jurjans.lv/flash/flasm_debug.html
AS3.0(AVM2) Manual: [PDF] ActionScript Virtual Machine 2 Overview - Adobe
Sociodox - The Miner Adobe Flash/Air Debugger. . . OVERKILL!!
Unpacking SWF - http://blog.codestage.ru/2012/03/07/packed/ (read later)
Notes on using Sothink SWF Decompiler:
If you use Sothink SWF Decompiler, this is how you switch to ActionScript bytecode view (with AVM instructions)
(Click to enlarge image)
You should be presented with this view:
(Click to enlarge image)
Note that it does NOT show the correspondence between source code and raw data!! You have to rely on your own knowledge on this. (Search function helps a lot navigating through code)
N.B. When you switch views, the decompiler always brings you to the first line of the code. . .
OMFG! I have ZERO knowledge on ActionScript!
Suggested reading:
Essential ActionScript 3.0 by Colin Moock
ActionScript 3.0 is a huge upgrade to Flash's programming language. The enhancements to ActionScript's performance, feature set, ease of use, cleanliness, and sophistication are considerable. Essential ActionScript 3.0 focuses on the core language and object-oriented programming, along with the Flash Player API. Essential ActionScript has become the #1 resource for the Flash and ActionScript development community, and the reason is the author, Colin Moock. Many people even refer to it simply as "The Colin Moock book."
And for good reason: No one is better at turning ActionScript inside out, learning its nuances and capabilities, and then explaining everything in such an accessible way. Colin Moock is not just a talented programmer and technologist; he's also a gifted teacher.
Essential ActionScript 3.0 is a radically overhauled update to Essential ActionScript 2.0. True to its roots, the book once again focuses on the core language and object-oriented programming, but also adds a deep look at the centerpiece of Flash Player's new API: display programming. Enjoy hundreds of brand new pages covering exciting new language features, such as the DOM-based event architecture, E4X, and namespaces--all brimming with real-world sample code.
The ActionScript 3.0 revolution is here, and Essential ActionScript 3.0's steady hand is waiting to guide you through it.
Adobe Developer Library is a co-publishing partnership between O'Reilly Media and Adobe Systems, Inc. and is designed to produce the number one information resources for developers who use Adobe technologies. Created in 2006, the Adobe Developer Library is the official source for comprehensive learning solutions to help developers create expressive and interactive web applications that can reach virtually anyone on any platform. With top-notch books and innovative online resources covering the latest in rich Internet application development, the Adobe Developer Library offers expert training and in-depth resources, straight from the source.
ActionScript 2.0 Language Reference (NOT an AVM manual!!)
I know some programming language just not ActionScript:
Here is the essential stuff you need to know. (For AS2.0)
gotoAndPlay function
gotoAndPlay([scene:String], frame:Object) : VoidSends the playhead to the specified frame in a scene and plays from that frame. If no scene is specified, the playhead goes to the specified frame in the current scene. You can use the scene parameter only on the root Timeline, not within Timelines for movie clips or other objects in the document.TL;DR: gotoAndPlay(n) jumps to frame #n
stop function
stop() : Voideval function
eval(expression:Object) : Object eval(expression:String) : ObjectAccesses variables, properties, objects, or movie clips by name. If expression is a variable or a property, the value of the variable or property is returned. If expression is an object or movie clip, a reference to the object or movie clip is returned. If the element named in expression cannot be found, undefined is returned.
getTimer function
getTimer() : NumberReturns the number of milliseconds that have elapsed since the SWF file started playing.
Some games use this function to catch cheaters who are getting high scores in short gameplay time. . .
You can figure out the rest here. . .
ActionScript 2.0 Language Reference (Again, it's NOT an AVM manual!!)
Note: The following list may not be exhaustive!
AS2.0 Reference List:
Opcode | Instruction | Description |
0x00 | _end | Action Record End |
0x04 | NextFrame instruction | |
0x05 | PreviousFrame instruction | |
0x06 | Play instruction | |
0x07 | Stop instruction | |
0x08 | ToggleQuality instruction | |
0x09 | StopSounds instruction | |
0x0A | Add instruction | |
0x0B | _subtract | Subtract instruction |
0x0C | _multiply | Multiply instruction |
0x0D | _divide | Divide instruction |
0x0E | Equals instruction | |
0x0F | Less instruction | |
0x10 | _and | Logical And instruction |
0x11 | Logical Or instruction | |
0x12 | _not | Not instruction |
0x13 | StringEquals instruction | |
0x14 | StringLength instruction | |
0x15 | StringExtract instruction | |
0x17 | _pop | Pop instruction |
0x18 | _toInteger | ToInteger instruction |
0x1C | _getVariable | GetVariable instruction |
0x1D | _setVariable | SetVariable instruction |
0x20 | SetTarget2 instruction | |
0x21 | StringAdd instruction | |
0x22 | GetProperty instruction | |
0x23 | SetProperty instruction | |
0x24 | CloneSprite instruction | |
0x25 | RemoveSprite instruction | |
0x26 | Trace instruction | |
0x27 | StartDrag instruction | |
0x28 | EndDrag instruction | |
0x29 | StringLess instruction | |
0x2A | Throw instruction | |
0x2B | CastOp instruction | |
0x2C | Implements instruction | |
0x30 | _randomNumber | RandomNumber instruction |
0x31 | MBStringLength instruction | |
0x32 | CharToAscii instruction | |
0x33 | AsciiToChar instruction | |
0x34 | _getTime | GetTime instruction |
0x35 | MBStringExtract instruction | |
0x36 | MBCharToAscii instruction | |
0x37 | MBAsciiToChar instruction | |
0x3A | Delete instruction | |
0x3B | Delete2 instruction | |
0x3C | _var | DefineLocal instruction |
0x3D | _callFunction | CallFunction instruction |
0x3E | Return instruction | |
0x3F | Modulo instruction | |
0x40 | _new | NewObject instruction |
0x41 | DefineLocal2 instruction | |
0x42 | InitArray instruction | |
0x43 | InitObject instruction | |
0x44 | TypeOf instruction | |
0x45 | TargetPath instruction | |
0x46 | Enumerate instruction | |
0x47 | _add2 | Add2 instruction |
0x48 | _less2 | Less2 instruction |
0x49 | Equals2 instruction | |
0x4A | ToNumber instruction | |
0x4B | ToString instruction | |
0x4C | _dup | PushDuplicate instruction |
0x4D | StackSwap instruction | |
0x4E | _getMember | GetMember instruction |
0x4F | _setMember | SetMember instruction |
0x50 | _increment | Increment instruction |
0x51 | Decrement instruction | |
0x52 | _callMethod | CallMethod instruction |
0x53 | NewMethod instruction | |
0x54 | InstanceOf instruction | |
0x55 | Enumerate2 instruction | |
0x60 | Bitwise And instruction | |
0x61 | Bitwise Or instruction | |
0x62 | Bitwise Xor instruction | |
0x63 | Bitwise Left Shift instruction | |
0x64 | Signed Bitwise Right Shift instruction | |
0x65 | Unsigned Bitwise Right Shift instruction | |
0x66 | StrictEquals instruction | |
0x67 | _greater | Typed Greater Than instruction |
0x68 | String Greater Than instruction | |
0x69 | Extends instruction | |
0x81 | GotoFrame instruction | |
0x83 | GetURL instruction | |
0x87 | _storeRegister | StoreRegister instruction |
0x88 | _constantPool | ConstantPool instruction |
0x8A | WaitForFrame instruction | |
0x8B | SetTarget instruction | |
0x8C | GoToLabel instruction | |
0x8D | WaitForFrame2 instruction | |
0x8E | DefineFunction2 (block) instruction | |
0x94 | With instruction | |
0x96 | _push | Push instruction |
0x99 | _jump | Jump instruction (branch) |
0x9A | GetURL2 instruction | |
0x9B | _defineFunction | DefineFunction (block) instruction |
0x9D | _if | If instruction (conditional branch) |
0x9E | Call instruction | |
0x9F | GotoFrame2 instruction |
AS2.0 Examples:
AS Code | Instructions | Hex RawData | |||||||||||||||||||||||||||||||||||||||||||||||||
getTimer(); | _getTime | 34 | |||||||||||||||||||||||||||||||||||||||||||||||||
Data types and push:
Data Type register Flash virtual machine has 4 global registers which we refer as r:0, r:1, r:2, r:3 .Accessing global registers is faster than accessing variables. Inside of function2 (Flash Player >=6.0.65), and only there, up to 255 local registers exist — from r:0 to r:254 . Why not 256? In the function2 header, the number of local registers used in this function is stored in a byte.These are referred as register0, register1, register2, . . . as well as _loc0, _loc1, _loc2, _loc3, . . . Note on referencing variables in assembler: Most variable names are declared from start of the code block using _constantPool asan array. Say, the first variable is var0, then it would be declared in _constantPool as its first element, or (think _constantPool[0]) Example: _constantPool var0 var1 var2 var3 Here I have declared 4 variables. Say I want to perform operation with var2. Then it would be at index=2 (arrays start from index 0). Push type here would be 08, since 0<=index<=255. Otherwise it would be 09. Now for var2, index=2. Therefore we reference var2 as 08 02. Data Type double The way Flash store double value is a bit weird. . According to IEEE standard, a decimal should be represent hexadecimally as follows: 0.1 = 0x3FB999999999999A however Flash store it like this: 99 99 B9 3F 9A 99 99 99 So it is necessary to convert decimals from Flash format to IEEE format, or vice versa to carry out conversion easily. Start with the flash hex representation: 9999B93F9A999999 1. Divide the representation to first 4 bytes and last 4 bytes 9999B93F 9A999999 2. Now read the first 4 bytes from right to left, also applying this to last 4 bytes 3FB99999 9999999A 3. Then we have the IEEE representation of that decimal! 3FB999999999999A You can use this on-site tool to do the hex conversation for Flash double values:
Syntax: _push data0 data1 data2 . . . 96 <No. of bytes to push (WORD)> <push type of data0> <bytes of data0> <push type of data1> <bytes of data1> <push type of data2> <bytes of data2> . . . |
|||||||||||||||||||||||||||||||||||||||||||||||||||
random(100000); | _push 100000 _randomNumber |
96 05 00 07 a0 86 01 00 30 |
|||||||||||||||||||||||||||||||||||||||||||||||||
pointsWorth = random(8) + 1; | _push "pointsWorth" 8 _randomNumber _push 1 _add2 _setVariable |
96 07 00 08 08 07 08 00 00 00 30 96 05 00 07 01 00 00 00 47 1d |
|||||||||||||||||||||||||||||||||||||||||||||||||
points = pointsWorth + "k"; | _push "points" "pointsWorth" _getVariable _push "k" _add2 _setVariable |
96 04 00 08 09 08 08 1c 96 02 00 08 0a 47 1d |
|||||||||||||||||||||||||||||||||||||||||||||||||
The constant_pool is a variable length structure composed of integers, doubles, strings, namespaces, namespace sets, and multinames. These constants are referenced from other parts of the executive code block. Syntax: _constantPool data0 data1 data2 . . . 88 <No. of bytes to store (WORD)> <No. of constants to store> <push type of data0> <bytes of data0> <push type of data1> <bytes of data1> <push type of data2> <bytes of data2> . . . Hint: Strings are null(0x00)-terminated. An ASCII table would be handy! Online ASCII conversion tools: TextToHex: http://www.swingnote.com/tools/texttohex.php HexToText: http://www.string-functions.com/hex-string.aspx |
|||||||||||||||||||||||||||||||||||||||||||||||||||
_constantPool "glassBlueLit" "_parent" "bonusPath" "glass" "_root" "changeColour" "glassBlue" "bg" "pointsWorth" "points" "k" | 88 5c 00 0b 00 67 6c 61 73 73 42 6c 75 65 4c 69 74 00 5f 70 61 72 65 6e 74 00 62 6f 6e 75 73 50 61 74 68 00 67 6c 61 73 73 00 5f 72 6f 6f 74 00 63 68 61 6e 67 65 43 6f 6c 6f 75 72 00 67 6c 61 73 73 42 6c 75 65 00 62 67 00 70 6f 69 6e 74 73 57 6f 72 74 68 00 70 6f 69 6e 74 73 00 6b 00 | ||||||||||||||||||||||||||||||||||||||||||||||||||
_parent.spawnNewBall = true; | _push "_parent" _getVariable _push "spawnNewBall" true _setMember |
96 02 00 08 00 1c 96 04 00 08 01 05 01 4f |
|||||||||||||||||||||||||||||||||||||||||||||||||
_push var0 var1 Stack: . . . => . . ., var0, var1 _greater Stack: . . . => (var0 > var1) ? . . ., true : . . ., false _not Stack: . . ., boolN => . . ., !(boolN) _not Comment: 2 not instructions following each other cancel each other out. . . one of the stupid things about AS2.0 compiler, or it's trying to evaluate !(var0 <= var1) _if true goto #n Stack: . . ., boolN => . . . If boolN == true then goto #n otherwise continue executing the next instruction n is an arbitrary int Basically, if the "if" condition is not satisfied then the code within the if-statement is not executed (by jumping directly to the end of the statement) _push var0 var1 _subtract Stack: . . ., var0, var1 => . . ., (var0 - var1) _storeRegister 1 Stack: . . ., varN => . . ., varN (stack unchanged after instruction??) _loc1 := varN Comment: 1 is stored as byte _pop . . ., varN => . . . | |||||||||||||||||||||||||||||||||||||||||||||||||||
if (_loc1 <= 0){ _loc1 = -_loc1; } |
_push register1 0 _greater _not _not _if true goto #20 _push 0 register1 _subtract _storeRegister 1 _pop |
96 0b 00 04 01 06 00 00 00 00 00 00 00 00 67 12 12 9d 02 00 14 00 96 0b 00 06 00 00 00 00 00 00 00 00 04 01 0b 87 01 00 01 17 |
|||||||||||||||||||||||||||||||||||||||||||||||||
AS Code | Instructions | Hex RawData | |||||||||||||||||||||||||||||||||||||||||||||||||
AS3.0 Reference List:
Opcode | Instruction | Description |
0x02 | nop | Do nothing. (But you'll find this most useful!!) |
0x03 | throw | Throws an exception. |
0x04 | getsuper | Gets a property from a base class. |
0x05 | setsuper | Sets a property in a base class. |
0x06 | dxns | Sets the default XML namespace. |
0x07 | dxnslate | Sets the default XML namespace with a value determined at runtime. |
0x08 | kill | Kills a local register. |
0x09 | label | Do nothing. Used to indicate that this location is the target of a branch. |
0x0c | ifnlt | Branch if the first value is not less than the second value. |
0x0d | ifnle | Branch if the first value is not less than or equal to the second value. |
0x0e | ifngt | Branch if the first value is not greater than the second value. |
0x0f | infge | Branch if the first value is not greater than or equal to the second value. |
0x10 | jump | Unconditional branch. |
0x11 | iftrue | Branch if true. |
0x12 | iffalse | Branch if false. |
0x13 | ifeq | Branch if the first value is equal to the second value. |
0x14 | ifne | Branch if the first value is not equal to the second value. |
0x15 | iflt | Branch if the first value is less than the second value. |
0x16 | ifle | Branch if the first value is less than or equal to the second value. |
0x17 | ifgt | Branch if the first value is greater than the second value. |
0x18 | ifge | Branch if the first value is greater than or equal to the second value. |
0x19 | ifstricteq | Branch if the first value is equal to the second value. |
0x1a | ifstrictne | Branch if the first value is not equal to the second value. |
0x1b | lookupswitch | Jump to different locations based on an index. |
0x1c | pushwith | Push a with scope onto the scope stack. |
0x1d | popscope | Pop a scope off of the scope stack. |
0x1e | nextname | Get the name of the next property when iterating over an object. |
0x1f | hasnext | Determine if the given object has any more properties. |
0x20 | pushnull | Push null. |
0x21 | pushundefined | Push undefined. |
0x23 | nextvalue | Get the value of the next property when iterating over an object. |
0x24 | pushbyte | Push a byte value. |
0x25 | pushshort | Push a short value. |
0x26 | pushtrue | Push true. |
0x27 | pushfalse | Push false. |
0x28 | pushnan | Push NaN. |
0x29 | pop | Pop the top value from the stack. |
0x2a | dup | Duplicates the top value of the stack, and then pushes the duplicated value onto the stack. |
0x2b | swap | Swap the top two operands on the stack. |
0x2c | pushstring | Push a string value (from constant pool) onto the stack. |
0x2d | pushint | Push an int value (from constant pool) onto the stack. |
0x2e | pushuint | Push an unsigned int value (from constant pool) onto the stack. |
0x2f | pushdouble | Push a double value (from constant pool) onto the stack. |
0x30 | pushscope | Push an object onto the scope stack. |
0x31 | pushnamespace | Push a namespace. |
0x32 | hasnext2 | Determine if the given object has any more properties. (byRef) |
0x40 | newfunction | Create a new function object. |
0x41 | call | Call a closure. |
0x42 | construct | Construct an instance. |
0x43 | callmethod | Call a method identified by index in the object’s method table. |
0x44 | callstatic | Call a method identified by index in the abcFile method table. |
0x45 | callsuper | Call a method on a base class. |
0x46 | callproperty | Call a property. |
0x47 | returnvoid | Return from the currently executing method. This returns the value undefined. |
0x48 | returnvalue | Return a value from a method. |
0x49 | constructsuper | Construct an instance of the base class. |
0x4a | constructprop | Construct a property. |
0x4c | callproplex | Call a property. |
0x4e | callsupervoid | Call a method on a base class, discarding the return value. |
0x4f | callpropvoid | Call a property, discarding the return value. |
0x55 | newobject | Create a new object. |
0x56 | newarray | Create a new array. |
0x57 | newactivation | Create a new activation object. |
0x58 | newclass | Create a new class. |
0x59 | getdescendants | Get descendants. |
0x5a | newcatch | Create a new catch scope. |
0x5d | findpropstrict | Find a property. |
0x5e | findproperty | Search the scope stack for a property. |
0x60 | getlex | Find and get a property. |
0x61 | setproperty | Set a property. |
0x62 | getlocal | Get a local register. |
0x63 | setlocal | Set a local register. |
0x64 | getglobalscope | Gets the global scope. |
0x65 | getscopeobject | Get a scope object. |
0x66 | getproperty | Get a property. |
0x68 | initproperty | Initialize a property. |
0x6a | deleteproperty | Delete a property. |
0x6c | getslot | Get the value of a slot. |
0x6d | setslot | Set the value of a slot. |
0x6e | getglobalslot | Get the value of a slot on the global scope. |
0x6f | setglobalslot | Set the value of a slot on the global scope. |
0x70 | convert_s | Convert a value to a string. |
0x71 | esc_xelem | Escape an xml element. |
0x72 | esc_xattr | Escape an xml attribute. |
0x73 | convert_i | Convert a value to an integer. |
0x74 | convert_u | Convert a value to an unsigned integer. |
0x75 | convert_d | Convert a value to a double. |
0x76 | convert_b | Convert a value to a Boolean. |
0x77 | convert_o | Convert a value to an Object. |
0x78 | checkfilter | Check to make sure an object can have a filter operation performed on it. |
0x80 | coerce | Coerce a value to a specified type. |
0x82 | coerce_a | Coerce a value to the any type. |
0x85 | coerce_s | Coerce a value to a string. |
0x86 | astype | Return the same value, or null if not of the specified type. |
0x87 | astypelate | Return the same value, or null if not of the specified type. |
0x90 | negate | Negate a value. |
0x91 | increment | Increment a value. |
0x92 | inclocal | Increment a local register value. |
0x93 | decrement | Decrement a value. |
0x94 | declocal | Decrement a local register value. |
0x95 | typeof | Get the type name of a value. |
0x96 | not | Boolean negation. |
0x97 | bitnot | Bitwise not. |
0xa0 | add | Add two values. |
0xa1 | subtract | Subtract one value from another. |
0xa2 | multiply | Multiply two values. |
0xa3 | divide | Divide two values. |
0xa4 | modulo | Perform modulo division on two values. |
0xa5 | lshift | Bitwise left shift. |
0xa6 | rshift | Signed bitwise right shift. |
0xa7 | urshift | Unsigned bitwise right shift. |
0xa8 | bitand | Bitwise and. |
0xa9 | bitor | Bitwise or. |
0xaa | bitxor | Bitwise exclusive or. |
0xab | equals | Compare two values. |
0xac | strictequals | Compare two values strictly. |
0xad | lessthan | Determine if one value is less than another. |
0xae | lessequals | Determine if one value is less than or equal to another. |
0xaf | greaterequals | Determine if one value is greater than or equal to another. |
0xb1 | instanceof | Check the prototype chain of an object for the existence of a type. |
0xb2 | istype | Check whether an Object is of a certain type. |
0xb3 | istypelate | Check whether an Object is of a certain type. |
0xb4 | in | Determine whether an object has a named property. |
0xc0 | increment_i | Increment an integer value. |
0xc1 | decrement_i | Decrement an integer value. |
0xc2 | inclocal_i | Increment a local register value. |
0xc3 | declocal_i | Decrement a local register value. |
0xc4 | negate_i | Negate an integer value. |
0xc5 | add_i | Add two integer values. |
0xc6 | subtract_i | Subtract an integer value from another integer value. |
0xc7 | multiply_i | Multiply two integer values. |
0xd0 | getlocal_0 | Get the local register at index 0. |
0xd1 | getlocal_1 | Get the local register at index 1. |
0xd2 | getlocal_2 | Get the local register at index 2. |
0xd3 | getlocal_3 | Get the local register at index 3. |
0xd4 | setlocal_0 | Set the local register at index 0. |
0xd5 | setlocal_1 | Set the local register at index 1. |
0xd6 | setlocal_2 | Set the local register at index 2. |
0xd7 | setlocal_3 | Set the local register at index 3. |
0xef | debug | Debugging info. |
0xf0 | debugline | Debugging line number info. |
0xf1 | debugfile | Debugging line number info. |
AS3.0 Typename:
HEX Value | Type Name |
01 | undefined = "undefined" |
02 | null = "object" |
03 | Boolean = "Boolean" |
04 | Number | int | uint = "number" |
05 | String = "string" |
06 | Function = "function" |
07 | XML | XMLList = "xml" |
08 | Object = "object" |
You've come to the end! So here's a little gift for your effort reading all this:
Common techniques for making flash game AoB cheats:
1. Changing jump/if conditions
2. Changing the value of constants
3. Nop out a call using 0x02 AND nop out arguments to push onto stack
4. Change type of arithmetic operation
5. Change variable reference index
6. Unrandomize results by NOPping out the randomNumber instruction
Well, thx for the references!
ReplyDelete