Finish initial RE on bytecode, every opcode is now accounted for.

This commit is contained in:
Jennifer Taylor 2021-04-14 01:07:01 +00:00
parent 79b31c7fa2
commit 142ee31d56
2 changed files with 60 additions and 2 deletions

View File

@ -315,7 +315,7 @@ class SWF(TrackedCoverage, VerboseOutput):
self.vprint(f"{prefix} {lineno}: {action_name} Flags: {hex(function_flags)}, Name: {funcname}, ByteCode Offset: {hex(bytecode_offset)}, ByteCode Length: {hex(bytecode_count)}")
# TODO: Need to do something with this parsed function bytecode.
function = self.__parse_bytecode(datachunk[offset_ptr:(offset_ptr + bytecode_count)], string_offsets=string_offsets, prefix=prefix + " ")
function = self.__parse_bytecode(datachunk[offset_ptr:(offset_ptr + bytecode_count)], string_offsets=string_offsets, prefix=prefix + " ") # NOQA
self.vprint(f"{prefix} END_{action_name}")
offset_ptr += bytecode_count
@ -452,6 +452,19 @@ class SWF(TrackedCoverage, VerboseOutput):
obj_count -= 1
self.vprint(f"{prefix} END_{action_name}")
elif opcode == AP2Action.INIT_REGISTER:
obj_count = struct.unpack(">B", datachunk[(offset_ptr + 1):(offset_ptr + 2)])[0]
offset_ptr += 2
self.vprint(f"{prefix} {lineno}: {action_name}")
while obj_count > 0:
register_no = struct.unpack(">B", datachunk[offset_ptr:(offset_ptr + 1)])[0]
offset_ptr += 1
obj_count -= 1
self.vprint(f"{prefix} REGISTER NO: {register_no}")
self.vprint(f"{prefix} END_{action_name}")
elif opcode == AP2Action.STORE_REGISTER:
obj_count = struct.unpack(">B", datachunk[(offset_ptr + 1):(offset_ptr + 2)])[0]
offset_ptr += 2
@ -517,11 +530,25 @@ class SWF(TrackedCoverage, VerboseOutput):
# to be absolute instead of relative.
jump_offset += offset_ptr - start_offset
self.vprint(f"{prefix} {lineno}: {action_name} Offset: {jump_offset}")
elif opcode == AP2Action.WITH:
skip_offset = struct.unpack(">H", datachunk[(offset_ptr + 1):(offset_ptr + 3)])[0]
offset_ptr += 3
# TODO: I have absolutely no idea what the data which exists in the bytecode buffer at this point
# represents...
unknown_data = datachunk[offset_ptr:(offset_ptr + skip_offset)] # NOQA
offset_ptr += skip_offset
self.vprint(f"{prefix} {lineno}: {action_name} Unknown Data Length: {skip_offset}")
elif opcode == AP2Action.ADD_NUM_VARIABLE:
amount_to_add = struct.unpack(">B", datachunk[(offset_ptr + 1):(offset_ptr + 2)])[0]
offset_ptr += 2
self.vprint(f"{prefix} {lineno}: {action_name} Add Value: {amount_to_add}")
elif opcode == AP2Action.GET_URL2:
action = struct.unpack(">B", datachunk[(offset_ptr + 1):(offset_ptr + 2)])[0]
offset_ptr += 2
self.vprint(f"{prefix} {lineno}: {action_name} URL Action: {action >> 6}")
elif opcode == AP2Action.START_DRAG:
constraint = struct.unpack(">b", datachunk[(offset_ptr + 1):(offset_ptr + 2)])[0]
offset_ptr += 2

View File

@ -299,6 +299,8 @@ class AP2Action:
# Takes the top of the stack and duplicates the object before pushing that object to the stack.
PUSH_DUPLICATE = 44
# Swaps the position of the two two objects on the stack. If there isn't enough to swap, does
# nothing.
STACK_SWAP = 45
# Get a member value and place it on the stack.
@ -317,8 +319,15 @@ class AP2Action:
# stack for the number of params, and then that many values from the stack as function parameters.
CALL_METHOD = 50
# Takes at least 3 objects on the stack, the third being the number of parameters, the second being
# the object to add a method to and the first being the member name.
NEW_METHOD = 51
# Takes two objects, pops them off the stack and adds a boolean object to the stack set to true
# if one is an instance of the other or false otherwise.
INSTANCEOF = 52
# Enumerates some sort of object into a variable on the top of the stack.
ENUMERATE2 = 53
# Pop two values from the stack, bitwise and them, push the result.
@ -346,6 +355,8 @@ class AP2Action:
# the second or not.
GREATER = 61
# Pops two objects off the stack and does some sort of OOP with them, the first being the superclass
# and the second being the subclass.
EXTENDS = 62
# Pop a value from the stack and store it in a register specified by the opcode param. Also push
@ -356,6 +367,12 @@ class AP2Action:
# as parameters, and uses that to read the next N bytes of bytecode as the function definition.
DEFINE_FUNCTION2 = 64
# Grabs a 16 bit offset pointer as the opcode param, then skips bytecode processing forward
# that many bytes, passing the skipped bytes as pointer data to a function that adds it to the
# stack as a pointer type, and then adds a copy of the top of the stack before the pointer as a
# second new stack entry. Strangely enough, if the object on the top of the stack doesn't meet
# some criteria, the skipped bytes are processed as bytecode. I am not sure what the hell is going
# on here.
WITH = 66
# Push an object onto the stack. Creates objects based on the bytecode parameters and pushes
@ -365,6 +382,9 @@ class AP2Action:
# Unconditional jump based on bytecode value.
JUMP = 68
# Gets a single 8-bit integer as an opcode param, take the top two bits of that param as the
# action to take. Looks like it is similar to SWF GET_URL2 action. Supported actions are 0,
# 2 and 3. It pops two objects from the stack to perform against.
GET_URL2 = 69
# Pops a value from the stack, jumps to offset from opcode params if value is truthy.
@ -375,6 +395,8 @@ class AP2Action:
# in opcode params.
GOTO_FRAME2 = 71
# Pops the top of the stack, uses that to get a target, pushes a pointer to that target on
# the stack.
GET_TARGET = 72
# Given a subtype of check and a positive offset to jump to on true, perform a conditional check.
@ -385,6 +407,9 @@ class AP2Action:
# Similar to STORE_REGISTER but does not preserve the value on the stack afterwards.
STORE_REGISTER2 = 74
# Take one opcode parameter for the number of registers to in it, and then one opcode parameter
# per the number of registers param as the register number to init, initializing that register
# as an "Undefined" object.
INIT_REGISTER = 75
# Similar to ADD_NUM_VARIABLE, but operating on a register number instead of the stack. Takes
@ -447,7 +472,7 @@ class AP2Action:
cls.DECREMENT: 'DECREMENT',
cls.CALL_METHOD: 'CALL_METHOD',
cls.NEW_METHOD: 'NEW_METHOD',
cls.INSTANCEOF: 'INSTANCEOF',
cls.INSTANCEOF: 'INSTANCE,OF',
cls.ENUMERATE2: 'ENUMERATE2',
cls.BIT_AND: 'BIT_AND',
cls.BIT_OR: 'BIT_OR',
@ -505,10 +530,13 @@ class AP2Action:
cls.REMOVE_SPRITE,
cls.TRACE,
cls.TYPEOF,
cls.INSTANCEOF,
cls.TARGET_PATH,
cls.ENUMERATE2,
cls.THROW,
cls.CAST_OP,
cls.IMPLEMENTS_OP,
cls.STACK_SWAP,
cls.GET_TIME,
cls.RETURN,
cls.POP,
@ -516,6 +544,7 @@ class AP2Action:
cls.DELETE,
cls.DELETE2,
cls.NEW_OBJECT,
cls.EXTENDS,
cls.INIT_ARRAY,
cls.INIT_OBJECT,
cls.END_DRAG,
@ -529,10 +558,12 @@ class AP2Action:
cls.SET_MEMBER,
cls.GET_PROPERTY,
cls.SET_PROPERTY,
cls.NEW_METHOD,
cls.CALL_METHOD,
cls.CALL_FUNCTION,
cls.TO_NUMBER,
cls.TO_STRING,
cls.GET_TARGET,
}