├── COPYING ├── README.md ├── framework ├── Instrument.swf.template ├── Makefile ├── bparrow.png ├── config.json ├── dbtool.py ├── flash-icon.ico ├── index.html ├── logserver.py ├── misc.yara ├── monitor ├── proxy.py ├── recompile.py ├── replay ├── run_file.sh ├── run_live.sh ├── run_vm.sh └── unittest.swf ├── instrument ├── README.md ├── build_instrument.sh ├── build_testflash.sh ├── build_unittest.sh ├── instrument_package │ ├── Base64.as │ ├── Instrument.as │ └── Instrument.swf ├── simple │ ├── simple.as │ └── simple.swf ├── testflash │ ├── simple.swf │ ├── testflash.as │ ├── testflash.as.bak │ └── testflash.swf ├── testflash1 │ ├── testflash.swf │ ├── testflash1.as │ └── testflash1.swf └── testflash2 │ ├── BA.as │ ├── LDR.as │ ├── testflash1.swf │ ├── testflash1.swf.enc │ ├── testflash2.as │ ├── testflash2.as.bak │ └── testflash2.swf ├── reflash ├── LICENSE ├── RABCDasm │ ├── .gitignore │ ├── CHANGELOG.md │ ├── COPYING │ ├── README.md │ ├── abcexport.d │ ├── abcfile.d │ ├── abcreplace.d │ ├── asasm.hrc │ ├── asprogram.d │ ├── assembler.d │ ├── autodata.d │ ├── build_rabcdasm.d │ ├── common.d │ ├── deimos │ │ ├── lzma.d │ │ └── lzma_ │ │ │ ├── base.d │ │ │ ├── bcj.d │ │ │ ├── block.d │ │ │ ├── check.d │ │ │ ├── container.d │ │ │ ├── delta.d │ │ │ ├── filter.d │ │ │ ├── hardware.d │ │ │ ├── index.d │ │ │ ├── index_hash.d │ │ │ ├── lzma.d │ │ │ ├── stream_flags.d │ │ │ ├── version_.d │ │ │ └── vli.d │ ├── disassembler.d │ ├── lzma.d │ ├── murmurhash2a.d │ ├── rabcasm.d │ ├── rabcdasm.d │ ├── swf7zcompress.d │ ├── swfbinexport.d │ ├── swfbinreplace.d │ ├── swfdecompress.d │ ├── swffile.d │ ├── swflzmacompress.d │ └── zlibx.d ├── README.md ├── build_reflash.d ├── instrument.d ├── liblzma.lib └── reflash.d └── reflash_paper.pdf /framework/Instrument.swf.template: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/framework/Instrument.swf.template -------------------------------------------------------------------------------- /framework/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .DEFAULT_GOAL := all 3 | 4 | deps: 5 | sudo apt-get install automake libtool python-pip python-dev libffi-dev libssl-dev libtiff5-dev libjpeg8-dev zlib1g-dev libwebp-dev libxml2-dev libxslt1-dev 6 | sudo pip install setuptools --upgrade 7 | sudo pip install psutil 8 | sudo pip install yara-python 9 | sudo pip install mitmproxy==0.18.3 10 | 11 | reflash: 12 | cd ../reflash; rdmd build_reflash.d 13 | cd ../framework; ln -s ../reflash/reflash reflash 14 | chmod 755 proxy.py run_*.sh monitor replay 15 | 16 | all: reflash 17 | 18 | clean: 19 | rm -f ../reflash/reflash 20 | rm -f reflash 21 | rm -f *.pyc 22 | rm -rf dumps cadir 23 | 24 | -------------------------------------------------------------------------------- /framework/bparrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/framework/bparrow.png -------------------------------------------------------------------------------- /framework/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxyConfig":{ 3 | "flash_in": "Instrument.swf.template", 4 | "cadir": "cadir" 5 | }, 6 | "reflashConfig":{ 7 | "quiet":true, 8 | "opcodeHooks":[ 9 | "call.*", 10 | "init.*", 11 | ".etproperty", 12 | "construct.*" 13 | ] 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /framework/dbtool.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # 4 | # Tool for creating a Replay database 5 | # 6 | # 7 | 8 | 9 | import glob 10 | import sys 11 | import os 12 | import sqlite3 13 | import base64 14 | import pyamf 15 | import re 16 | import yara 17 | import binascii 18 | import tempfile 19 | import shutil 20 | from pyamf import amf3 21 | from optparse import OptionParser 22 | 23 | 24 | 25 | def insert_stackval(c, value_id, event_id, t, data, parent, level): 26 | datatype = type(data) 27 | bits = "" 28 | 29 | # XXX: bug in pyamf3 decoder? 30 | if level > 10: 31 | #print "Warning: AMF object recursion level exceeded" 32 | return value_id 33 | 34 | if datatype == pyamf.ASObject: 35 | amf_type = "Object" 36 | bits = "[]" 37 | elif datatype == pyamf.MixedArray: 38 | amf_type = "Object" 39 | bits = "[]" 40 | elif datatype == list: 41 | amf_type = "Array" 42 | bits = "[]" 43 | elif datatype == pyamf.amf3.ObjectVector: 44 | amf_type = "Vector" 45 | bits = "[]" 46 | elif datatype == pyamf.amf3.ByteArray: 47 | amf_type = "ByteArray" 48 | try: 49 | bits = data.read() 50 | except: 51 | bits = "" 52 | elif datatype == unicode: 53 | amf_type = "String" 54 | bits = data 55 | elif datatype == str: 56 | amf_type = "String" 57 | bits = data 58 | elif datatype == int: 59 | amf_type = "Integer" 60 | bits = str(data) 61 | elif datatype == float: 62 | amf_type = "Number" 63 | bits = str(data) 64 | elif datatype == bool: 65 | amf_type = "Boolean" 66 | bits = str(data) 67 | else: 68 | amf_type = "Undefined" 69 | bits = repr(data) 70 | if bits == "pyamf.Undefined": 71 | bits = "" 72 | 73 | c.execute("INSERT INTO stack_values (value_id, stack_event, type, amf_type, data, parent) VALUES (?,?,?,?,?,?);", 74 | (value_id, event_id, t, amf_type, bits, parent)) 75 | 76 | parent_id = value_id 77 | value_id = value_id + 1 78 | 79 | if amf_type == "Array": 80 | level = level + 1 81 | for d in data: 82 | value_id = insert_stackval(c, value_id, event_id, t, d, parent_id, level) 83 | 84 | if amf_type == "Vector": 85 | level = level + 1 86 | max = 256 87 | i = 0 88 | for d in data: 89 | if i >= max: 90 | print "Warning: max vector size exceeded (%d/%d)" % (max, len(data)) 91 | break 92 | value_id = insert_stackval(c, value_id, event_id, t, d, parent_id, level) 93 | i = i + 1 94 | 95 | if amf_type == "Object": 96 | level = level + 1 97 | for k,v in data.iteritems(): 98 | value_id = insert_stackval(c, value_id, event_id, t, k, parent_id, level) 99 | value_id = insert_stackval(c, value_id, event_id, t, v, value_id-1, level) 100 | 101 | #if dbtool.verbose == True: 102 | # print " ", value_id, t, amf_type, repr(bits)[:64] 103 | return value_id 104 | 105 | def parse_stacktrace(filename, c, e, v): 106 | 107 | event_id = e 108 | value_id = v 109 | 110 | with open(filename, "rb") as f: 111 | 112 | buf = f.read() 113 | 114 | pos = 0 115 | 116 | while True: 117 | context = amf3.Context() 118 | decoder = amf3.Decoder(buf[pos:], context) 119 | try: 120 | data = decoder.readElement() 121 | except pyamf.EOStream: 122 | #print "EOStream" 123 | break 124 | except IOError: # premature end of stream 125 | #print "IOError" 126 | break 127 | except Exception,e: 128 | print "Warning:", e, pos 129 | pos = pos + 1 130 | continue 131 | if not data: 132 | pos = pos + 1 133 | continue 134 | pos = pos + decoder.stream.tell() 135 | 136 | if type(data) != list: 137 | print "Warning: top level data not valid: ", type(data) 138 | continue 139 | 140 | l = len(data) 141 | name, session, method, opcode = data[0].split(":",4) 142 | c.execute("INSERT INTO stack_events (event_id,session_method,opcode) VALUES (?,?,?);", 143 | (event_id, "%s:%s" % (session, method), opcode)) 144 | 145 | #if dbtool.verbose: 146 | # print "\n", event_id, data[0] 147 | for i in range(0, (l-1)/2): 148 | t = data[(i*2)+1] 149 | a = data[(i*2)+2] 150 | #print event_id, t, data[0], repr(a)[:32] 151 | if type(a) != pyamf.amf3.ByteArray: 152 | print "Warning: top level data not valid: ", type(a) 153 | d = None 154 | else: 155 | try: 156 | d = amf3.Decoder(a).readElement() 157 | except: 158 | print "Warning: decoder failed @", data[0],t 159 | d = "" 160 | 161 | value_id = insert_stackval(c, value_id, event_id, t, d, -1, 0) 162 | 163 | event_id = event_id + 1 164 | 165 | return (event_id,value_id) 166 | 167 | def parse_disasm(dir, c): 168 | 169 | c.execute("CREATE TABLE methods (session_method text primary key, name text);") 170 | c.execute("CREATE TABLE opcodes (opcode_id int primary key, session_method text, opcode_index int, mnemonic text, args text);") 171 | 172 | opcode_id = 0 173 | for file in glob.glob(dir + "/s*.txt"): 174 | with open(file) as f: 175 | 176 | session = "" 177 | method = "" 178 | name = "" 179 | 180 | for line in f: 181 | # method start 182 | if line[:2] != " ": 183 | s = line.split(":") 184 | session = s[0] 185 | if re.search(session, "%d-%d"): continue 186 | method = s[1] 187 | if len(s) > 2: 188 | name = s[2] 189 | else: 190 | name = "%s_%s_corrupted" % (session,method) 191 | opcode_index = 0 192 | c.execute("INSERT INTO methods (session_method,name) VALUES (?,?);", ("%s:%s" % (session,method), name)) 193 | 194 | else: 195 | instruction = line[12:] 196 | sp = instruction.find(" ") 197 | op = "" 198 | args = "" 199 | if (sp != -1): 200 | op = instruction[:sp].strip() 201 | args = instruction[sp:].strip() 202 | else: 203 | op = instruction.strip() 204 | 205 | c.execute("INSERT INTO opcodes (opcode_id, session_method, opcode_index, mnemonic, args) VALUES (?,?,?,?,?);", 206 | (opcode_id, "%s:%s" % (session,method), opcode_index, op, args)) 207 | opcode_id = opcode_id + 1 208 | opcode_index = opcode_index + 1 209 | 210 | def runyara(yarafile, db, cb, dbconn=False): 211 | 212 | rules = yara.compile(filepath=yarafile) 213 | 214 | match_str = {} 215 | match_events = {} 216 | 217 | matches = rules.match(db) 218 | for m in matches: 219 | for s in m.strings: 220 | match_str[s[2]] = m.rule 221 | 222 | if len(match_str): 223 | if dbconn == False: 224 | conn = sqlite3.connect(db) 225 | else: 226 | conn = dbconn 227 | conn.text_factory = str 228 | 229 | for k,v in match_str.iteritems(): 230 | # 1. Search from stack_values 231 | c = conn.cursor() 232 | data = "%" + binascii.hexlify(k) + "%" 233 | c.execute("SELECT * from stack_values where hex(data) like ? or hex(type) like ?;", (data,data)) 234 | for row in c: 235 | if row[1] in match_events: 236 | match_events[row[1]][k] = True 237 | else: 238 | match_events[row[1]] = {k: True} 239 | 240 | # 2. Search from opcodes.args 241 | c = conn.cursor() 242 | data = "%" + binascii.hexlify(k) + "%" 243 | c.execute("SELECT * from opcodes where hex(args) like ?;", (data,)) 244 | for row in c: 245 | session_method = row[1] 246 | opcode = row[2] 247 | 248 | c = conn.cursor() 249 | c.execute("SELECT * from stack_events where session_method is ? and opcode is ?;", (session_method,opcode)) 250 | for r in c: 251 | if r[0] in match_events: 252 | match_events[r[0]][k] = True 253 | else: 254 | match_events[r[0]] = {k: True} 255 | 256 | for k,v in match_events.iteritems(): 257 | for x,y in v.iteritems(): 258 | cb(k, x, match_str[x]) 259 | 260 | if (dbconn == False): 261 | conn.close() 262 | 263 | 264 | def doyara(yarafile, db): 265 | print "Running yara, please wait..." 266 | 267 | tmp = tempfile.NamedTemporaryFile(delete=False) 268 | tmpname = tmp.name 269 | tmp.close() 270 | shutil.copy(db, tmpname) 271 | 272 | conn = sqlite3.connect(db) 273 | 274 | def cb(event, data, rule): 275 | print ("[%.8d] %s (rule: %s)" % (event, repr(data), rule)) 276 | 277 | runyara(yarafile, tmpname, cb, dbconn=conn) 278 | conn.close() 279 | os.remove(tmpname) 280 | 281 | 282 | def create(dir, out): 283 | 284 | logfiles = sorted(glob.glob(dir + "/log-*.dat")) 285 | if len(logfiles) == 0: 286 | return 0 287 | 288 | if os.path.exists(out): 289 | os.remove(out) 290 | 291 | conn = sqlite3.connect(out) 292 | conn.text_factory = str 293 | c = conn.cursor() 294 | 295 | parse_disasm(dir, c) 296 | 297 | c.execute("CREATE TABLE stack_events (event_id int primary key, session_method text, opcode int);") 298 | c.execute("CREATE TABLE stack_values (value_id int primary key, stack_event int, type text, amf_type text, data blob, parent int);") 299 | 300 | event_id = 0 301 | value_id = 0 302 | for lpath in logfiles: 303 | event_id,value_id = parse_stacktrace(lpath, c, event_id, value_id) 304 | 305 | conn.commit() 306 | conn.close() 307 | return 1 308 | 309 | def raw(db, out): 310 | print "Exporting raw data, please wait..." 311 | 312 | f = open(out, "wb") 313 | 314 | conn = sqlite3.connect(db) 315 | conn.text_factory = str 316 | 317 | c = conn.cursor() 318 | c.execute("SELECT * from stack_values;") 319 | for row in c: 320 | f.write(str(row[4])) 321 | 322 | c = conn.cursor() 323 | c.execute("SELECT * from opcodes;") 324 | for row in c: 325 | f.write(str(row[4])) 326 | 327 | f.close() 328 | 329 | conn.close() 330 | 331 | def pretty(db, out): 332 | print "Making it pretty, please wait..." 333 | 334 | currentMethod = "" 335 | 336 | if out == None: 337 | f = tempfile.NamedTemporaryFile() 338 | else: 339 | f = open(out, "wb") 340 | 341 | conn = sqlite3.connect(db) 342 | conn.text_factory = str 343 | 344 | c = conn.cursor() 345 | c.execute("SELECT * from stack_events;") 346 | for row in c: 347 | event_id, session_method, opcode = row[0],row[1],row[2] 348 | 349 | c = conn.cursor() 350 | c.execute("SELECT * from opcodes WHERE session_method is ? AND opcode_index is ?;", (session_method,opcode)) 351 | d = c.fetchone() 352 | mnemonic = d[3] 353 | args = d[4] 354 | 355 | if (mnemonic.find("call") != 0): 356 | continue 357 | 358 | c = conn.cursor() 359 | c.execute("SELECT * from methods WHERE session_method is ?;", (session_method,)) 360 | d = c.fetchone() 361 | method_name = d[1] 362 | if method_name != currentMethod: 363 | if currentMethod != "": 364 | f.write("}\n") 365 | f.write(method_name + ":\n{\n") 366 | currentMethod = method_name 367 | 368 | arg_a = args.split(',') 369 | arg_count = int(arg_a[len(arg_a)-1].strip()) 370 | 371 | if (arg_count == 0): 372 | continue 373 | 374 | # Function name 375 | if mnemonic == "call": 376 | mname = "(closure)" 377 | else: 378 | mname = "(%s)" % mnemonic[4:] 379 | 380 | is_multiname = args.find("Multiname") 381 | 382 | names = re.findall(r'"(.*?)"', args) 383 | for n in names: 384 | b = n.find("builtin") 385 | if b != -1: 386 | n = "AS_builtin" 387 | mname = mname + ":" + n 388 | if is_multiname == 0: 389 | break 390 | 391 | f.write(" [%.8d] %s\n (\n" % (event_id, mname)) 392 | 393 | # Handle arguments 394 | 395 | a = [] 396 | c = conn.cursor() 397 | c.execute("SELECT * from stack_values WHERE stack_event is ? and parent is ?;", (event_id,-1)) 398 | for row in c: 399 | a.append(row) 400 | 401 | i = 0 402 | for row in a: 403 | data = repr(row[4]) 404 | if len(data) > 48: 405 | data = data[:47] + "[...]" 406 | if (i < len(a)-arg_count): 407 | id = "obj:" 408 | else: 409 | id = "arg:" 410 | 411 | if row[3] == "Object" or row[3] == "Array" or row[3] == "Undefined": 412 | typeid = repr(row[2]) 413 | else: 414 | typeid = row[3] 415 | f.write(" %s%s:%s\n" % (id, typeid, data)) 416 | i = i + 1 417 | 418 | f.write(" )\n") 419 | 420 | if out == None: 421 | f.seek(0) 422 | print f.read() 423 | 424 | f.close() 425 | conn.close() 426 | 427 | 428 | 429 | def main(argv): 430 | opt_parser = OptionParser() 431 | opt_parser.add_option('-c', '--create', action = 'store_true', dest = 'create', help = 'Create a new database from Input dir') 432 | opt_parser.add_option('-r', '--raw', action = 'store_true', dest = 'raw', help = 'Export raw data from Input database') 433 | opt_parser.add_option('-p', '--pretty', action = 'store_true', dest = 'pretty', help = 'Export a pretty call trace from Input database') 434 | opt_parser.add_option('-i', '--input', dest = 'input', help = 'Input') 435 | opt_parser.add_option('-o', '--output', dest = 'output', help = 'Output') 436 | opt_parser.add_option('-y', '--yara', dest = 'yara', help = 'Run yara file') 437 | opt_parser.add_option('-v', '--verbose', action = 'store_true', dest = 'verbose', help = 'Be verbose') 438 | 439 | (options,args) = opt_parser.parse_args(argv) 440 | 441 | if options.create and options.input and options.output: 442 | if not create(options.input, options.output): 443 | print "Database not created, please check the directory \"%s\"" % options.input 444 | elif options.raw and options.input and options.output: 445 | raw(options.input, options.output) 446 | elif options.pretty and options.input: 447 | pretty(options.input, options.output) 448 | elif options.yara and options.input: 449 | doyara(options.yara, options.input) 450 | 451 | else: 452 | print "Don't know what to do!" 453 | 454 | if __name__ == "__main__": 455 | main(sys.argv[1:]) 456 | 457 | 458 | 459 | -------------------------------------------------------------------------------- /framework/flash-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/framework/flash-icon.ico -------------------------------------------------------------------------------- /framework/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 |

Alternative content -- Can contain any HTML: DIVs, IMGs, etc.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /framework/logserver.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | 4 | 5 | import os 6 | import sys 7 | import time 8 | import socket 9 | import threading 10 | import SocketServer 11 | 12 | 13 | 14 | class TCPConnection(SocketServer.BaseRequestHandler): 15 | 16 | def write_data(self, port, data): 17 | if port in self.log_files: 18 | self.log_files[port].write(data) 19 | else: 20 | self.log_files[port] = open(self.logdir + "/log-%d.dat" % port, "wb") 21 | self.log_files[port].write(data) 22 | self.log_cb("<< Flash trace data") 23 | 24 | def handle(self): 25 | #self.log_cb("<< New flash log connection") 26 | trace = False 27 | while True: 28 | try: 29 | self.data = self.request.recv(1024) 30 | if self.data: 31 | if self.data == '\x00': 32 | #self.log_cb("<< Flash policy file request") 33 | self.request.sendall("" + "\0") 34 | else: 35 | if self.data == "Trace": 36 | #self.log_cb("<< Flash trace data") 37 | trace = True 38 | #else: 39 | elif trace == True: 40 | self.write_data(self.client_address[1], self.data) 41 | 42 | self.request.sendall("ok\0") 43 | else: 44 | break 45 | except: 46 | self.request.close() 47 | return 48 | 49 | class LogServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 50 | daemon_threads = True 51 | allow_reuse_address = True 52 | 53 | def __init__(self, server_address, RequestHandlerClass): 54 | SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) 55 | 56 | def handle_timeout(self): 57 | self.timed_out = True 58 | 59 | def Sleeper(t, server): 60 | time.sleep(t) 61 | server.timed_out = True 62 | server.shutdown() 63 | 64 | def log_cb(string): 65 | print string 66 | sys.stdout.flush() 67 | 68 | def main(argv): 69 | 70 | if len(argv) != 3: 71 | print "Usage: logserver " 72 | sys.exit(1) 73 | 74 | ldir = argv[0] 75 | lport = argv[1] 76 | timeout = argv[2] 77 | 78 | print "Logserver listening on port " + lport 79 | sys.stdout.flush() 80 | 81 | # Run logserver until timeout (or ctrl+c) 82 | server = LogServer(('', int(lport)), TCPConnection) 83 | t = threading.Thread(target=Sleeper, args=(int(timeout), server)) 84 | t.daemon = True 85 | t.start() 86 | TCPConnection.log_files = {} 87 | TCPConnection.logdir = ldir 88 | TCPConnection.log_cb = staticmethod(log_cb) 89 | server.timed_out = False 90 | try: 91 | server.serve_forever() 92 | except KeyboardInterrupt: 93 | print "Stopped by KeyboardInterrupt" 94 | sys.stdout.flush() 95 | 96 | if server.timed_out == True: 97 | print "Stopped by timeout" 98 | sys.stdout.flush() 99 | 100 | for v in TCPConnection.log_files.itervalues(): 101 | v.close() 102 | 103 | server.server_close() 104 | 105 | if __name__ == "__main__": 106 | main(sys.argv[1:]) 107 | 108 | -------------------------------------------------------------------------------- /framework/misc.yara: -------------------------------------------------------------------------------- 1 | 2 | rule Unittest 3 | { 4 | strings: 5 | $s1 = "Hello Reflash!" 6 | 7 | condition: 8 | all of them 9 | } 10 | 11 | rule LoadBytes_MethodClosure 12 | { 13 | strings: 14 | $s1 = "builtin.as$0::MethodClosure:loadBytes" 15 | 16 | condition: 17 | all of them 18 | } 19 | 20 | rule ExternalInterface 21 | { 22 | strings: 23 | $s1 = "flash.external::ExternalInterface" 24 | 25 | condition: 26 | all of them 27 | } 28 | 29 | rule Embedded_SWF 30 | { 31 | strings: 32 | $s1 = "loadBytes" 33 | $f1 = "CWS" 34 | $f2 = "ZWS" 35 | 36 | condition: 37 | $s1 and ($f1 or $f2) 38 | } 39 | 40 | rule Capabilities_isDebugger 41 | { 42 | strings: 43 | $s1 = "flash.system::Capabilities" 44 | $s2 = "isDebugger" 45 | 46 | condition: 47 | all of them 48 | } 49 | 50 | rule RIG_EK_shellcode 51 | { 52 | strings: 53 | $b = {60 eb 11 58 b9 ?? ?? 00 00 49 80 34 08 ?? 85 c9 75 f7 ff e0 e8 ea ff ff ff} 54 | 55 | condition: 56 | all of them 57 | } 58 | 59 | 60 | rule Neutrino_EK_shellcode 61 | { 62 | strings: 63 | $b = {eb 12 58 31 c9 66 b9 ?? ?? 49 80 34 08 ?? 85 c9 75 f7 ff e0 e8 e9 ff ff ff} 64 | 65 | condition: 66 | all of them 67 | } 68 | 69 | rule Angler_EK_shellcode 70 | { 71 | strings: 72 | $a = "\xe8\x0d\x00\x00\x00CreateThread" 73 | $b = "\xe8\x14\x00\x00\x00WaitForSingleObject" 74 | $c = "\xe8\x0d\x00\x00\x00LoadLibraryA" 75 | $d = "\xe8\x0d\x00\x00\x00VirtualAlloc" 76 | $e = "\xe8\x17\x00\x00\x00CreateProcessInternalW" 77 | condition: 78 | all of them 79 | } 80 | 81 | 82 | rule Shellcode_API_resolver 83 | { 84 | strings: 85 | $a = {64 A1 30 00 00 00 53 8B 40 0C 55 56 8B 70 0C 57 89 4C 24 18} 86 | $b = {89 4C 24 18} 87 | $c = {8B ?? 10 78} 88 | $d = {89 ?? 24 10} 89 | $e = {C1 C9 0D} 90 | $f = {3C 61 0F BE C0 7C 03 83 C1 E0} 91 | 92 | condition: 93 | all of them 94 | } 95 | 96 | rule Shellcode_API_resolver_2 97 | { 98 | strings: 99 | $a={ E8 FF 00 00 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C 00 4C 6F 61 64 4C 69 62 72 61 72 79 41 00 56 69 72 74 75 61 6C 41 6C 6C 6F 63} 100 | condition: 101 | all of them 102 | } 103 | -------------------------------------------------------------------------------- /framework/recompile.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # 4 | # NOTE: this is a HACK, highly dependent on the structure of Instrument.as !! 5 | # If you need to modify Instrument more than this script does, well then you need to have Flex 6 | # installed and should us it instead. 7 | # 8 | 9 | import glob 10 | import sys 11 | import os 12 | import re 13 | import tempfile 14 | import shutil 15 | import fileinput 16 | import subprocess 17 | from optparse import OptionParser 18 | import re 19 | 20 | # Reflash executable 21 | reflash_cmd=os.path.normcase("./reflash") 22 | 23 | # Templates 24 | package_template="instrument_package" 25 | address_template="##IP_ADDRESS##" 26 | port_template="##PORT##" 27 | namespace_template="##NAMESPACE##" 28 | tag_template="##TAG##" 29 | trace_template="##TRACE##" 30 | version_template="##VERSION##" 31 | os_template="##OS##" 32 | player_template="##PLAYERTYPE##" 33 | 34 | def replace(s1, s2, filename): 35 | for line in fileinput.input(filename, inplace=True): 36 | print line.replace(s1, s2), 37 | 38 | return True 39 | 40 | def recompile(options): 41 | player = options.player 42 | os = options.os 43 | 44 | if options.version == "None": 45 | version = options.version 46 | else: 47 | scan = re.compile(r'([A-Z][A-Z][A-Z]) (\d+),(\d+),(\d+),(\d+)') 48 | result = scan.match(options.version) 49 | try: 50 | r = result.groups() 51 | except: 52 | if options.quiet == False: 53 | print "Error: incorrect version format (OS n,n,n,n)" 54 | return 0 55 | if ((r[0] == "WIN") or (r[0] == "MAC") or (r[0] == "LNX") or (r[0] == "AND")) and (int(r[1]) >= 9): 56 | version = r[0] + " " + r[1] + "," + r[2] + "," + r[3] + "," + r[4] 57 | else: 58 | if options.quiet == False: 59 | print "Error: incorrect version format (WIN|MAC|LNX|AND 9+,n,n,n)" 60 | return 0 61 | 62 | if options.quiet == False: 63 | print "address:", options.address 64 | if options.logport == "8888": 65 | print "port:", options.logport, "(default)" 66 | else: 67 | print "port:", options.logport 68 | if options.package == "instrument_package": 69 | print "package:", options.package, "(default)" 70 | else: 71 | print "package:", options.package 72 | if options.namespace == "NameSpace": 73 | print "namespace:", options.namespace, "(default)" 74 | else: 75 | print "namespace:", options.namespace 76 | if options.tag == "reflash": 77 | print "tag:", options.tag, "(default)" 78 | else: 79 | print "tag:", options.tag 80 | print "trace:", options.trace 81 | print "version:", version 82 | print "os:", os 83 | print "player:", player 84 | 85 | if options.trace == True: 86 | trace = "True" 87 | else: 88 | trace = "False" 89 | 90 | tmpdir = tempfile.mkdtemp() 91 | 92 | # reflash d --input Instrument.swf --dir tmpdir 93 | subprocess.call(reflash_cmd + " d --input " + options.flash_in + " --dir " + tmpdir, shell=True) 94 | 95 | replace(package_template, options.package, tmpdir + "/block-0/block-0.main.asasm") 96 | replace(package_template, options.package, tmpdir + "/block-0/instrument_package/Instrument.script.asasm") 97 | replace(package_template, options.package, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 98 | replace(address_template, options.address, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 99 | replace(port_template, options.logport, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 100 | replace(namespace_template, options.namespace, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 101 | replace(tag_template, options.tag, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 102 | replace(trace_template, trace, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 103 | replace(version_template, version, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 104 | replace(os_template, os, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 105 | replace(player_template, player, tmpdir + "/block-0/instrument_package/Instrument.class.asasm") 106 | replace(package_template, options.package, tmpdir + "/block-0/instrument_package/Base64.script.asasm") 107 | replace(package_template, options.package, tmpdir + "/block-0/instrument_package/Base64.class.asasm") 108 | 109 | # rename instrument_package -> package 110 | shutil.move(tmpdir + "/block-0/" + package_template, tmpdir + "/block-0/" + options.package) 111 | 112 | # reflash a --dir tmpdir --quiet 113 | subprocess.call(reflash_cmd + " a --dir " + tmpdir + " --quiet", shell=True) 114 | 115 | shutil.copyfile(tmpdir + "/tmp.swf", options.flash_out) 116 | shutil.rmtree(tmpdir) 117 | 118 | if options.quiet == False: 119 | print 'Done.' 120 | return 1 121 | 122 | def main(argv): 123 | opt_parser = OptionParser() 124 | opt_parser.add_option('-i', '--input', dest = 'flash_in', help = 'Instrument template file') 125 | opt_parser.add_option('-o', '--output', dest = 'flash_out', default="Instrument.swf", help = 'Output file (default="Instrument.swf")') 126 | opt_parser.add_option('-p', '--package', dest = 'package', default="instrument_package", help = 'Instrument package name (default="instrument_package")') 127 | opt_parser.add_option('-a', '--address', dest = 'address', default="127.0.0.1", help = 'Log server IP address (default=127.0.0.1)') 128 | opt_parser.add_option('-P', '--port', dest = 'logport', default="8888", help = 'Log server port (default=8888)') 129 | opt_parser.add_option('-n', '--namespace', dest = 'namespace', default="NameSpace", help = 'JavaScript namespace (default="NameSpace")') 130 | opt_parser.add_option('-t', '--tag', dest = 'tag', default="reflash", help = 'loadBytes identifier tag (default="reflash")') 131 | opt_parser.add_option('-T', '--trace', action = 'store_false', default=True, dest = 'trace', help = 'Do not send trace log (default=false)') 132 | opt_parser.add_option('-q', '--quiet', action = 'store_true', default=False, dest = 'quiet', help = 'Be quiet (default=False)') 133 | opt_parser.add_option('-v', '--version', dest = 'version', default="None", help = 'Fake version in format "OSS n,n,n,n" (default="None")') 134 | opt_parser.add_option('-O', '--os', dest = 'os', default="None", help = 'Fake OS version (default="None")') 135 | opt_parser.add_option('-L', '--player', dest = 'player', default="None", help = 'Fake player type (default="None")') 136 | 137 | (options,args) = opt_parser.parse_args(argv) 138 | 139 | if not options.flash_in: 140 | print "Please provide input file with --input" 141 | sys.exit(1) 142 | 143 | return recompile(options) 144 | 145 | 146 | if __name__ == "__main__": 147 | main(sys.argv[1:]) 148 | -------------------------------------------------------------------------------- /framework/run_file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$#" -lt 1 ]; then 4 | echo "Usage: run_file.sh " 5 | exit 1 6 | fi 7 | 8 | interface='eth0' 9 | 10 | dir=`mktemp -d` 11 | db=$1.db 12 | lp="index.html" 13 | ip_addr=`ifconfig $interface | sed -n 's/.*r:\(.*\) B.*/\1/p'` 14 | file=$1 15 | shift 1 16 | 17 | 18 | echo "dump dir: $dir, database: $db, landing page: $lp" 19 | echo "Now browse to http://www.example.com/index.html" 20 | ./proxy.py -i $file -l $lp -o $db -c config.json -d $dir -a $ip_addr -t 120 -y misc.yara "$@" 21 | 22 | 23 | -------------------------------------------------------------------------------- /framework/run_live.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | interface='eth0' 4 | 5 | ip_addr=`ifconfig $interface | sed -n 's/.*r:\(.*\) B.*/\1/p'` 6 | dir=`mktemp -d` 7 | 8 | ./proxy.py -o live.db -c config.json -d $dir -t 600000 -a $ip_addr "$@" 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /framework/run_vm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PROXY_IP="192.168.56.1" 4 | NODE_IP="192.168.56.2" 5 | NODE_PORT="5555" 6 | SELENIUM="selenium-server-standalone-3.0.0.jar" 7 | 8 | if [ "$#" -lt 1 ]; then 9 | echo "Usage: run_vm.sh [list|file|live]" 10 | exit 1 11 | fi 12 | command=$1 13 | if [ "$command" == "list" ]; then 14 | for i in `vboxmanage list vms | sed 's/\(.*\){\(.*\)}$/\2/g'`; do 15 | echo "VM UUID: $i" 16 | vboxmanage showvminfo $i | grep Name: 17 | echo 18 | done 19 | fi 20 | 21 | if [[ ( "$command" == "live" ) || ( "$command" == "file" ) ]]; then 22 | if [ "$#" -lt 4 ]; then 23 | echo "Usage: run_vm.sh $1 " 24 | exit 1 25 | fi 26 | machine=$2 27 | snapshot=$3 28 | resource=$4 29 | shift 4 30 | 31 | # Start Selenium hub 32 | nohup java -jar $SELENIUM -role hub > selenium.log 2>&1 & 33 | SELENIUM_PID=$! 34 | 35 | echo "Waiting for Selenium hub..." 36 | while ! nc -q 1 localhost 4444 /dev/null 2>&1 40 | vboxmanage startvm $machine --type headless 41 | echo "Waiting for Selenium node..." 42 | while ! nc -q 1 $NODE_IP $NODE_PORT /dev/null 2>&1 63 | kill $SELENIUM_PID 64 | 65 | fi 66 | -------------------------------------------------------------------------------- /framework/unittest.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/framework/unittest.swf -------------------------------------------------------------------------------- /instrument/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Reflash ActionScript instrumentation module 3 | 4 | If you need to modify the instrumentation module, please install [Apache flex](https://flex.apache.org/) and use the supplied `build_instrument.sh` for compiling. You need to have `mxmlc` in your __PATH__. 5 | -------------------------------------------------------------------------------- /instrument/build_instrument.sh: -------------------------------------------------------------------------------- 1 | 2 | mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. instrument_package/Instrument.as 3 | 4 | cp instrument_package/Instrument.swf ../framework/Instrument.swf.template 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /instrument/build_testflash.sh: -------------------------------------------------------------------------------- 1 | 2 | ~/apache-flex-sdk-4.15.0-bin/bin/mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. simple/simple.as 3 | 4 | cp simple/simple.swf testflash/ 5 | 6 | 7 | ~/apache-flex-sdk-4.15.0-bin/bin/mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash/testflash.as 8 | 9 | cp testflash/testflash.swf testflash1/ 10 | 11 | ~/apache-flex-sdk-4.15.0-bin/bin/mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash1/testflash1.as 12 | 13 | cp testflash1/testflash1.swf testflash2/ 14 | 15 | ~/apache-flex-sdk-4.15.0-bin/bin/mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash2/testflash2.as 16 | cp testflash2/testflash2.swf ../framework/unittest.swf 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /instrument/build_unittest.sh: -------------------------------------------------------------------------------- 1 | 2 | mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. simple/simple.as 3 | cp simple/simple.swf testflash/ 4 | 5 | mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash/testflash.as 6 | cp testflash/testflash.swf testflash1/ 7 | 8 | mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash1/testflash1.as 9 | cp testflash1/testflash1.swf testflash2/ 10 | 11 | mxmlc -omit-trace-statements=false -static-link-runtime-shared-libraries=true -compiler.source-path=. testflash2/testflash2.as 12 | cp testflash2/testflash2.swf ../framework/unittest.swf 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /instrument/instrument_package/Base64.as: -------------------------------------------------------------------------------- 1 | /* Base64 library for ActionScript 3.0. 2 | * Based on: Ma Bingyao code. 3 | * Optimized by: Jean-Philippe Auclair / jpauclair.wordpress.com 4 | * Copyright (C) 2007 Ma Bingyao 5 | * LastModified: Oct 26, 2009 6 | * This library is free. You can redistribute it and/or modify it. 7 | */ 8 | package instrument_package 9 | { 10 | import flash.utils.ByteArray; 11 | import instrument_package.Instrument; 12 | 13 | public class Base64 14 | { 15 | private static const _encodeChars:Vector. = InitEncoreChar(); 16 | private static const _decodeChars:Vector. = InitDecodeChar(); 17 | 18 | public function Base64() 19 | { 20 | } 21 | 22 | public static function encode(data:ByteArray):String 23 | { 24 | var out:ByteArray = new ByteArray(); 25 | //Presetting the length keep the memory smaller and optimize speed since there is no "grow" needed 26 | out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms 27 | var i:int = 0; 28 | var r:int = data.length % 3; 29 | var len:int = data.length - r; 30 | var c:int; //read (3) character AND write (4) characters 31 | 32 | while (i < len) 33 | { 34 | //Read 3 Characters (8bit * 3 = 24 bits) 35 | c = data[i++] << 16 | data[i++] << 8 | data[i++]; 36 | 37 | //Cannot optimize this to read int because of the positioning overhead. (as3 bytearray seek is slow) 38 | //Convert to 4 Characters (6 bit * 4 = 24 bits) 39 | c = (_encodeChars[c >>> 18] << 24) | (_encodeChars[c >>> 12 & 0x3f] << 16) | (_encodeChars[c >>> 6 & 0x3f] << 8 ) | _encodeChars[c & 0x3f]; 40 | 41 | //Optimization: On older and slower computer, do one write Int instead of 4 write byte: 1.5 to 0.71 ms 42 | out.writeInt(c); 43 | /* 44 | out.writeByte(_encodeChars[c >> 18] ); 45 | out.writeByte(_encodeChars[c >> 12 & 0x3f]); 46 | out.writeByte(_encodeChars[c >> 6 & 0x3f]); 47 | out.writeByte(_encodeChars[c & 0x3f]); 48 | */ 49 | } 50 | 51 | if (r == 1) //Need two "=" padding 52 | { 53 | //Read one char, write two chars, write padding 54 | c = data[i]; 55 | c = (_encodeChars[c >>> 2] << 24) | (_encodeChars[(c & 0x03) << 4] << 16) | 61 << 8 | 61; 56 | out.writeInt(c); 57 | } 58 | else if (r == 2) //Need one "=" padding 59 | { 60 | c = data[i++] << 8 | data[i]; 61 | c = (_encodeChars[c >>> 10] << 24) | (_encodeChars[c >>> 4 & 0x3f] << 16) | (_encodeChars[(c & 0x0f) << 2] << 8 ) | 61; 62 | out.writeInt(c); 63 | } 64 | 65 | out.position = 0; 66 | return out.readUTFBytes(out.length); 67 | } 68 | 69 | public static function decode(str:String):ByteArray 70 | { 71 | var c1:int; 72 | var c2:int; 73 | var c3:int; 74 | var c4:int; 75 | var i:int; 76 | var len:int; 77 | var out:ByteArray; 78 | len = str.length; 79 | i = 0; 80 | out = new ByteArray(); 81 | var byteString:ByteArray = new ByteArray(); 82 | byteString.writeUTFBytes(str); 83 | while (i < len) 84 | { 85 | //c1 86 | do 87 | { 88 | c1 = _decodeChars[byteString[i++]]; 89 | } while (i < len && c1 == -1); 90 | if (c1 == -1) break; 91 | 92 | //c2 93 | do 94 | { 95 | c2 = _decodeChars[byteString[i++]]; 96 | } while (i < len && c2 == -1); 97 | if (c2 == -1) break; 98 | 99 | out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4)); 100 | 101 | //c3 102 | do 103 | { 104 | c3 = byteString[i++]; 105 | if (c3 == 61) return out; 106 | 107 | c3 = _decodeChars[c3]; 108 | } while (i < len && c3 == -1); 109 | if (c3 == -1) break; 110 | 111 | out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2)); 112 | 113 | //c4 114 | do { 115 | c4 = byteString[i++]; 116 | if (c4 == 61) return out; 117 | 118 | c4 = _decodeChars[c4]; 119 | } while (i < len && c4 == -1); 120 | if (c4 == -1) break; 121 | 122 | out.writeByte(((c3 & 0x03) << 6) | c4); 123 | 124 | } 125 | return out; 126 | } 127 | 128 | public static function InitEncoreChar() : Vector. 129 | { 130 | var encodeChars:Vector. = new Vector.(); 131 | 132 | // We could push the number directly, but i think it's nice to see the characters (with no overhead on encode/decode) 133 | var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 134 | for (var i:int = 0; i < 64; i++) 135 | { 136 | encodeChars.push(chars.charCodeAt(i)); 137 | } 138 | /* 139 | encodeChars.push( 140 | 65, 66, 67, 68, 69, 70, 71, 72, 141 | 73, 74, 75, 76, 77, 78, 79, 80, 142 | 81, 82, 83, 84, 85, 86, 87, 88, 143 | 89, 90, 97, 98, 99, 100, 101, 102, 144 | 103, 104, 105, 106, 107, 108, 109, 110, 145 | 111, 112, 113, 114, 115, 116, 117, 118, 146 | 119, 120, 121, 122, 48, 49, 50, 51, 147 | 52, 53, 54, 55, 56, 57, 43, 47); 148 | */ 149 | return encodeChars; 150 | } 151 | 152 | public static function InitDecodeChar() : Vector. 153 | { 154 | var decodeChars:Vector. = new Vector.(); 155 | 156 | decodeChars.push(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 157 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 158 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 159 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, 160 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 161 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 162 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 163 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 164 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 165 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 166 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 167 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 168 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 171 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); 172 | return decodeChars; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /instrument/instrument_package/Instrument.as: -------------------------------------------------------------------------------- 1 | 2 | package instrument_package 3 | { 4 | import flash.display.*; 5 | import flash.text.*; 6 | import flash.utils.*; 7 | import flash.net.*; 8 | import flash.events.*; 9 | import flash.system.*; 10 | import flash.system.Security; 11 | import mx.utils.*; 12 | import flash.external.*; 13 | import instrument_package.*; 14 | import flash.net.LocalConnection; 15 | 16 | public class Instrument 17 | { 18 | public static var doTrace:String = "##TRACE##"; 19 | public static var logHost:String = "##IP_ADDRESS##"; 20 | public static var logPort:String = "##PORT##"; 21 | public static var fakeVersion:String = "##VERSION##"; 22 | public static var fakeOS:String = "##OS##"; 23 | public static var fakePlayerType:String = "##PLAYERTYPE##"; 24 | public static var logArray:ByteArray = null; 25 | public static var socket:Socket = null; 26 | public static var maxTrace:int = 5; // Enough for some string building etc. 27 | public static var traceDict:Dictionary = null; 28 | 29 | public static const CALL_CLOSURE:int = 1; 30 | public static const CALL_PROPVOID:int = 2; 31 | public static const CALL_SUPERVOID:int = 3; 32 | 33 | public static var flashVersion:String = Capabilities.version; 34 | public static var osVersion:String = Capabilities.os; 35 | public static var playerType:String = Capabilities.playerType; 36 | public static var flashServerString:String = Capabilities.serverString; 37 | 38 | public function Instrument() 39 | { 40 | } 41 | 42 | private static function InjectJs():void 43 | { 44 | var createNamespace_js :XML = 45 | 56 | 57 | var addFunction_js :XML = 58 | 93 | 94 | ExternalInterface.call(createNamespace_js); 95 | ExternalInterface.call(addFunction_js); 96 | } 97 | private static function Reflash(bytes:ByteArray):ByteArray 98 | { 99 | InjectJs(); 100 | var callFunction_js :XML = 101 | 109 | 110 | var encoded:String = Base64.encode(bytes); 111 | 112 | var ret:String = ExternalInterface.call(callFunction_js, encoded); 113 | 114 | if (ret != null) 115 | return Base64.decode(ret); 116 | else 117 | return null; 118 | } 119 | 120 | public static function connectHandler(e: Event): void 121 | { 122 | trace("connectHandler: " + e); 123 | socket.writeUTFBytes("Trace"); 124 | } 125 | public static function dataHandler(e: Event): void 126 | { 127 | trace("dataHandler: " + e); 128 | 129 | if ((logArray != null) && (logArray.length)) 130 | { 131 | trace("dataHandler: sending logArray, size: " + logArray.length); 132 | socket.writeBytes(logArray); 133 | socket.flush(); 134 | logArray = null; 135 | } 136 | else 137 | { 138 | trace("dataHandler: empty logArray"); 139 | } 140 | } 141 | public static function closeHandler(e: Event): void 142 | { 143 | trace("closeHandler: " + e); 144 | } 145 | public static function errorHandler(e: Event): void 146 | { 147 | trace("errorHandler: " + e); 148 | } 149 | public static function securityHandler(e: Event): void 150 | { 151 | trace("securityHandler: " + e); 152 | } 153 | 154 | public static function Trace(array:Array, call:String):void 155 | { 156 | if (doTrace != "True") 157 | { 158 | traceDict[call]++; 159 | return; 160 | } 161 | if (logArray == null) 162 | { 163 | logArray = new ByteArray(); 164 | } 165 | logArray.writeObject(array); 166 | 167 | if (!socket) 168 | { 169 | socket = new Socket(); 170 | socket.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler); 171 | socket.addEventListener(Event.CONNECT, connectHandler); 172 | socket.addEventListener(Event.CLOSE, closeHandler); 173 | socket.addEventListener(ErrorEvent.ERROR, errorHandler); 174 | socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityHandler); 175 | try { 176 | socket.timeout = 600000; 177 | } 178 | catch (error:Error) 179 | { 180 | trace(call + ": Error: cannot set socket.timeout: " + error.message); 181 | } 182 | socket.endian = Endian.BIG_ENDIAN; 183 | 184 | Security.allowDomain("*"); 185 | Security.loadPolicyFile("xmlsocket://" + logHost + ":" + logPort); 186 | 187 | socket.connect(logHost, parseInt(logPort, 10)); 188 | } 189 | traceDict[call]++; 190 | } 191 | 192 | // Try to figure out the function name 193 | public static function GetFunctionName(callee:Function, parent:Object):String 194 | { 195 | for each (var m:XML in describeType(parent)..method) 196 | { 197 | if (parent[m.@name] == callee) return m.@name; 198 | } 199 | return "(Private)"; 200 | } 201 | 202 | public static function IsFunction(callee:Function, parent:Object):Boolean 203 | { 204 | for each (var m:XML in describeType(parent)..method) 205 | { 206 | if (parent[m.@name] == callee) return true; 207 | } 208 | return false; 209 | } 210 | 211 | // Dump argument in AMF format 212 | public static function GetArgumentType(array:Array, index:int, max:int, call:String):String 213 | { 214 | var type:String = getQualifiedClassName(array[index]); 215 | if (type == "builtin.as$0::MethodClosure") 216 | { 217 | if (index < max-1) 218 | { 219 | type += ":" + GetFunctionName(array[index], array[index+1]); 220 | } 221 | else 222 | { 223 | type += ":(Unknown)"; 224 | } 225 | } 226 | return type; 227 | } 228 | 229 | public static function GetArguments(array:Array, call:String):Array 230 | { 231 | var len:int = array.length; 232 | var ret:Array = new Array((len*2)+1); 233 | 234 | ret[0] = call; 235 | for(var i:int = 0; i < len; i++) 236 | { 237 | var type:String = GetArgumentType(array, i, len, call); 238 | var ba:ByteArray = new ByteArray(); 239 | 240 | // Store only specific data types, otherwise we might run 241 | // into troubles with class getters 242 | if ((type == "String") || 243 | (type == "Number") || 244 | (type == "Boolean") || 245 | (type == "int") || 246 | (type == "uint") || 247 | (type == "Array") || // XXX: what if Array contains classes? 248 | (type == "Date") || 249 | (type.slice(0,6) == "flash.")) 250 | { 251 | try 252 | { 253 | ba.writeObject(array[i]); 254 | } 255 | catch (error:Error) 256 | { 257 | trace(call + ": Error: cannot write object: " + error.message); 258 | ba.writeObject(""); 259 | } 260 | } 261 | // Everything else: first try explicit coercing to ByteArray. 262 | // If it fails, just write "" 263 | else 264 | { 265 | try { 266 | ba.writeObject(array[i] as ByteArray); 267 | } 268 | catch (error:Error) 269 | { 270 | trace(call + ": Error: cannot coerce as ByteArray: " + error.message); 271 | ba.writeObject(""); 272 | } 273 | } 274 | ret[(i*2)+1] = type; 275 | ret[(i*2)+2] = ba; 276 | } 277 | return ret; 278 | } 279 | 280 | // XXX: note that also Capabilities.serverString needs to be handled: 281 | // URL-encode flashVersion, search for V=encoded(real), replace with 282 | // V=encoded(fake) 283 | public static function InstrumentGetProperty(obj:Object, prop:Object):Object 284 | { 285 | if ((fakeVersion == "None") && (fakeOS == "None") && (fakePlayerType == "None")) return prop; 286 | 287 | var cn:String = getQualifiedClassName(obj); 288 | 289 | if (cn == "flash.system::Capabilities") 290 | { 291 | if ((fakeVersion != "None") && (prop == flashVersion)) 292 | { 293 | return fakeVersion; 294 | } 295 | if ((fakeOS != "None") && (prop == osVersion)) 296 | { 297 | return fakeOS; 298 | } 299 | if ((fakePlayerType != "None") && (prop == playerType)) 300 | { 301 | return fakePlayerType; 302 | } 303 | } 304 | return prop; 305 | } 306 | 307 | public static function InstrumentMethodEntry(call:String, array:Array):void 308 | { 309 | // Check of the code has already been visited: 310 | if (traceDict == null) traceDict = new Dictionary(); 311 | if (traceDict[call] !== undefined) 312 | { 313 | if (traceDict[call] > maxTrace) 314 | { 315 | return; 316 | } 317 | } 318 | else 319 | { 320 | traceDict[call] = 1; 321 | } 322 | trace("InstrumentMethodEntry: " + call); 323 | Trace(GetArguments(array, call), call); 324 | } 325 | 326 | public static function InstrumentStack(call:String, argindex:uint, array:Array):Array 327 | { 328 | // Create new array for function arguments 329 | var len:int = array.length; 330 | var retArray:Array = new Array(len-argindex); 331 | 332 | // Check of the code has already been visited: 333 | if (traceDict == null) traceDict = new Dictionary(); 334 | if (traceDict[call] !== undefined) 335 | { 336 | if (traceDict[call] > maxTrace) 337 | { 338 | return retArray; 339 | } 340 | } 341 | else 342 | { 343 | traceDict[call] = 1; 344 | } 345 | 346 | trace("InstrumentStack: " + call); 347 | 348 | // Trace arguments 349 | Trace(GetArguments(array, call), call); 350 | 351 | // If no function arguments, just return 352 | if (len == argindex) 353 | return null; 354 | 355 | // Index for a possible Loader object 356 | var i_ldr:int = -1; 357 | 358 | var isThis:Boolean = false; 359 | var callType:int = -1; 360 | 361 | // Call closure 362 | if (call.slice(0, 5) == "call:") 363 | { 364 | callType = CALL_CLOSURE; 365 | i_ldr = 1; 366 | // false if MethodClosure is a reference to super class (getsuper) 367 | try 368 | { 369 | isThis = IsFunction(array[0], array[1]); 370 | } 371 | catch (error:Error) 372 | { 373 | trace(call + ": Error: " + error.message); 374 | isThis = false; 375 | } 376 | } 377 | // Other calls 378 | if (call.slice(0, 13) == "callpropvoid:") 379 | { 380 | callType = CALL_PROPVOID; 381 | i_ldr = 0; 382 | } 383 | if (call.slice(0, 14) == "callsupervoid:") 384 | { 385 | callType = CALL_SUPERVOID; 386 | i_ldr = 0; 387 | } 388 | 389 | if (i_ldr != -1) 390 | { 391 | var cl:String = "flash.display::Loader"; 392 | var sn:String = getQualifiedSuperclassName(array[i_ldr]); 393 | var cn:String = getQualifiedClassName(array[i_ldr]); 394 | 395 | // case 1: callsupervoid with flash.display::Loader superclass 396 | // case 2: closure call with MethodClosure not found from called object 397 | // case 3: all calls with flash.display::Loader as a called object 398 | 399 | if (((callType == CALL_SUPERVOID) && (sn == cl)) || 400 | ((callType == CALL_CLOSURE) && (sn == cl) && (isThis == false)) || 401 | ((callType != -1) && (cn == cl))) 402 | { 403 | var ret:ByteArray = null; 404 | try { 405 | ret = Reflash(array[argindex] as ByteArray); // SWF as first argument? 406 | 407 | } catch (e:Error) { 408 | trace("Reflash: " + e); 409 | } 410 | if (ret != null) 411 | { 412 | retArray[0] = ret; 413 | } 414 | } 415 | } 416 | 417 | // Reverse the array, so we just pop() to the original function 418 | return retArray.reverse(); 419 | } 420 | } 421 | } 422 | 423 | 424 | 425 | -------------------------------------------------------------------------------- /instrument/instrument_package/Instrument.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/instrument_package/Instrument.swf -------------------------------------------------------------------------------- /instrument/simple/simple.as: -------------------------------------------------------------------------------- 1 | 2 | package simple 3 | { 4 | import flash.display.Sprite; 5 | import flash.text.*; 6 | import flash.utils.*; 7 | 8 | public class simple extends Sprite 9 | { 10 | private var myTextBox:TextField = new TextField(); 11 | 12 | public function simple() 13 | { 14 | doit("Hello Reflash!"); 15 | } 16 | 17 | public function doit(arg:String):void 18 | { 19 | addChild(myTextBox); 20 | myTextBox.text = arg; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /instrument/simple/simple.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/simple/simple.swf -------------------------------------------------------------------------------- /instrument/testflash/simple.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash/simple.swf -------------------------------------------------------------------------------- /instrument/testflash/testflash.as: -------------------------------------------------------------------------------- 1 | package testflash 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | 11 | public class testflash extends Sprite 12 | { 13 | [Embed(source="\x73\x69\x6d\x70\x6c\x65\x2e\x73\x77\x66", mimeType="\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x6f\x63\x74\x65\x74\x2d\x73\x74\x72\x65\x61\x6d")] 14 | private static const _1IJqO:Class; 15 | 16 | 17 | private function _oghit(encrypted:String):String 18 | { 19 | var _TdPNU:String = ""; 20 | for (var _S4FeY:int = 0; _S4FeY < encrypted.length; _S4FeY++) 21 | { 22 | _TdPNU += String.fromCharCode(encrypted.charCodeAt(_S4FeY)^0x0a); 23 | } 24 | return _TdPNU; 25 | } 26 | 27 | 28 | public function testflash() 29 | { 30 | var _7xtAS:Namespace = new Namespace(_oghit("\x6c\x66\x6b\x79\x62\x24\x6e\x63\x79\x7a\x66\x6b\x73")); 31 | var _EU993:String = _oghit("\x46\x65\x6b\x6e\x6f\x78"); 32 | var _NfQt7:Object = new _7xtAS::[_EU993](); 33 | var _IxzJc:String = _oghit("\x66\x65\x6b\x6e\x48\x73\x7e\x6f\x79"); 34 | 35 | var _ovb9v:Object = new _1IJqO(); 36 | var _IQKj4:ByteArray = _ovb9v as ByteArray; 37 | 38 | _NfQt7[_IxzJc](_IQKj4); 39 | 40 | addChild(_NfQt7 as DisplayObject); 41 | 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /instrument/testflash/testflash.as.bak: -------------------------------------------------------------------------------- 1 | package testflash 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | 11 | public class testflash extends Sprite 12 | { 13 | [Embed(source="simple.swf", mimeType="application/octet-stream")] 14 | private static const DSs7dks:Class; 15 | 16 | 17 | private function fdsgsdgds(encrypted:String):String 18 | { 19 | var decrypted:String = ""; 20 | for (var i:int = 0; i < encrypted.length; i++) 21 | { 22 | decrypted += String.fromCharCode(encrypted.charCodeAt(i)^0x0a); 23 | } 24 | return decrypted; 25 | } 26 | 27 | 28 | public function testflash() 29 | { 30 | 31 | // Load embedded content 32 | var ns:Namespace = new Namespace(fdsgsdgds("lfkyb$ncyzfks")); 33 | var n:String = fdsgsdgds("Feknox"); 34 | var x:Object = new ns::[n](); 35 | var f:String = fdsgsdgds("feknHs~oy"); 36 | 37 | var swfObj:Object = new DSs7dks(); 38 | var u:ByteArray = swfObj as ByteArray; 39 | 40 | x[f](u); 41 | 42 | addChild(x as DisplayObject); 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /instrument/testflash/testflash.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash/testflash.swf -------------------------------------------------------------------------------- /instrument/testflash1/testflash.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash1/testflash.swf -------------------------------------------------------------------------------- /instrument/testflash1/testflash1.as: -------------------------------------------------------------------------------- 1 | package testflash1 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | 11 | public class testflash1 extends Sprite 12 | { 13 | [Embed(source="testflash.swf", mimeType="application/octet-stream")] 14 | private static const DSs7dks:Class; 15 | 16 | 17 | private function fdsgsdgds(encrypted:String):String 18 | { 19 | var decrypted:String = ""; 20 | for (var i:int = 0; i < encrypted.length; i++) 21 | { 22 | decrypted += String.fromCharCode(encrypted.charCodeAt(i)^0x0a); 23 | } 24 | return decrypted; 25 | } 26 | 27 | 28 | public function testflash1() 29 | { 30 | 31 | // Load embedded content 32 | var ns:Namespace = new Namespace(fdsgsdgds("lfkyb$ncyzfks")); 33 | var x:Object = new ns::Loader(); 34 | 35 | var swfObj:Object = new DSs7dks(); 36 | var u:ByteArray = swfObj as ByteArray; 37 | 38 | x.loadBytes(u); 39 | 40 | addChild(x as DisplayObject); 41 | 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /instrument/testflash1/testflash1.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash1/testflash1.swf -------------------------------------------------------------------------------- /instrument/testflash2/BA.as: -------------------------------------------------------------------------------- 1 | package testflash2 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | public class BA extends ByteArray 11 | { 12 | private var getst:String; 13 | public var stst:String; 14 | 15 | public function BA(gs:String) 16 | { 17 | getst = gs; 18 | stst = "stst"; 19 | super(); 20 | } 21 | 22 | public function get st():String 23 | { 24 | trace(getst); 25 | return getst; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /instrument/testflash2/LDR.as: -------------------------------------------------------------------------------- 1 | package testflash2 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | public class LDR extends Loader 11 | { 12 | private var fsdfsdf7s:String = "loadBytes"; 13 | public function LDR() 14 | { 15 | super(); 16 | } 17 | 18 | public override function loadBytes(bytes:ByteArray, context:LoaderContext = null): void 19 | { 20 | super[fsdfsdf7s](bytes, context); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /instrument/testflash2/testflash1.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash2/testflash1.swf -------------------------------------------------------------------------------- /instrument/testflash2/testflash1.swf.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash2/testflash1.swf.enc -------------------------------------------------------------------------------- /instrument/testflash2/testflash2.as: -------------------------------------------------------------------------------- 1 | package testflash2 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | 11 | public class testflash2 extends Sprite 12 | { 13 | [Embed(source="\x74\x65\x73\x74\x66\x6c\x61\x73\x68\x31\x2e\x73\x77\x66\x2e\x65\x6e\x63", mimeType="\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2f\x6f\x63\x74\x65\x74\x2d\x73\x74\x72\x65\x61\x6d")] 14 | private static const _TGD4S:Class; 15 | 16 | 17 | private function _Gk0YL(encrypted:ByteArray):BA 18 | { 19 | var _4C1jC:BA = new BA("test"); 20 | 21 | for (var _jzoze:int = 0; _jzoze < encrypted.length; _jzoze++) 22 | { 23 | var _nkTLW:int = encrypted.readByte(); 24 | _4C1jC.writeByte(_nkTLW^0x0a); 25 | } 26 | return _4C1jC; 27 | } 28 | 29 | 30 | public function testflash2() 31 | { 32 | var _Xu6i3:Loader = new LDR(); 33 | var _6nM5c:LoaderContext = new LoaderContext(); 34 | 35 | var _fpOTN:Object = new _TGD4S(); 36 | var _5RGjp:ByteArray = _fpOTN as ByteArray; 37 | var _PteJc:BA = _Gk0YL(_5RGjp); 38 | 39 | var a:Array = new Array(); 40 | a[0] = _PteJc; 41 | a[1] = "arraytest"; 42 | 43 | _Xu6i3["loadBytes"](a[0], _6nM5c); 44 | 45 | addChild(_Xu6i3); 46 | 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /instrument/testflash2/testflash2.as.bak: -------------------------------------------------------------------------------- 1 | package testflash2 2 | { 3 | import flash.display.*; 4 | import flash.text.*; 5 | import flash.utils.*; 6 | import flash.net.*; 7 | import flash.events.*; 8 | import flash.system.*; 9 | 10 | 11 | public class testflash2 extends Sprite 12 | { 13 | [Embed(source="testflash1.swf.enc", mimeType="application/octet-stream")] 14 | private static const DSs7dks:Class; 15 | 16 | 17 | private function decrypt(encrypted:ByteArray):ByteArray 18 | { 19 | var decrypted:ByteArray = new ByteArray(); 20 | 21 | for (var i:int = 0; i < encrypted.length; i++) 22 | { 23 | var byte:int = encrypted.readByte(); 24 | decrypted.writeByte(byte^0x0a); 25 | } 26 | return decrypted; 27 | } 28 | 29 | 30 | public function testflash2() 31 | { 32 | 33 | // Load embedded content 34 | var x:Loader = new Loader(); 35 | var y:LoaderContext = new LoaderContext(); 36 | 37 | var swfObj:Object = new DSs7dks(); 38 | var u:ByteArray = swfObj as ByteArray; 39 | var v:ByteArray = decrypt(u); 40 | 41 | x.loadBytes(v, y); 42 | 43 | addChild(x); 44 | 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /instrument/testflash2/testflash2.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/instrument/testflash2/testflash2.swf -------------------------------------------------------------------------------- /reflash/RABCDasm/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.dll 3 | *.pdb 4 | *.ilk 5 | *.exp 6 | *.lib 7 | *.suo 8 | 9 | /build_rabcdasm 10 | /rabcasm 11 | /rabcdasm 12 | /abcexport 13 | /abcreplace 14 | /swfbinexport 15 | /swfbinreplace 16 | /swfdecompress 17 | /swf7zcompress 18 | /swflzmacompress 19 | -------------------------------------------------------------------------------- /reflash/RABCDasm/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | RABCDAsm Changelog 2 | ================== 3 | 4 | RABCDAsm v1.18 (2016.01.16) 5 | --------------------------- 6 | 7 | * Fix disassembly of `pushbyte` instructions (the AVM specification 8 | incorrectly lists the argument as unsigned). 9 | * Bump `#version` directive of new disassemblies to 4: 10 | - Versions below 4 treat `pushbyte` as unsigned, and throw an exception if 11 | the argument is outside the range `0` ... `255`. 12 | - Versions 4 and above treat `pushbyte` as signed, and throw an exception 13 | if the argument is outside the range `-128` ... `127`. 14 | * Fix buffer reuse bugs when using macros 15 | * Dump floating-point numbers in hex notation if necessary to ensure precision 16 | * Cease emitting a number in a comment after opening `script` tags 17 | * Detect a known DMD bug in `build_rabcdasm` 18 | * Ignore invalid file size in header 19 | 20 | RABCDAsm v1.17 (2014.09.10) 21 | --------------------------- 22 | 23 | * Do not attempt to disassemble unreachable code 24 | * Improve handling of disassembly errors: 25 | methods will be partially disassembled as far as possible. 26 | * Fix LZMA errors with uncompressable data. 27 | 28 | RABCDAsm v1.16 (2014.04.21) 29 | --------------------------- 30 | 31 | * Fix handling of TypeName-kind Multinames with null parameters 32 | * Fix v1.15 regression in handling very long paths on Windows 33 | (DMD 2.066 is required when building from source for this to work) 34 | 35 | RABCDAsm v1.15 (2014.01.11) 36 | --------------------------- 37 | 38 | * Fix building on systems with a noexec `/tmp/` 39 | * Improve compatibility with 3rd-party players 40 | * Don't emit forward references in TypeName-kind Multinames 41 | * Improve performance and memory usage 42 | 43 | RABCDAsm v1.14 (2013.08.21) 44 | --------------------------- 45 | 46 | * Improved refid generation 47 | * Worked around liblzma dictionary size limitation, which prevented 48 | decompression of some LZMA-compressed files 49 | * Added an option to `swflzmacompress` to update the SWF version number 50 | * Added `finddef` instruction 51 | * Added unimplemented `{get|set|delete}propertylate` instructions 52 | * Documentation updates 53 | 54 | RABCDAsm v1.13 (2012.09.29) 55 | --------------------------- 56 | 57 | * Fixed handling of truncated SWF tags 58 | 59 | RABCDAsm v1.12 (2012.09.08) 60 | --------------------------- 61 | 62 | * Relaxed filename sanitization for names like "controller" 63 | * Added range validation for byte literals 64 | * Fixed LZMA support misdetection caused by stale rdmd cache 65 | * Added coerce_b, coerce_i and coerce_d opcodes 66 | * Fixed handling of recursively-nested function literals 67 | * Fixed handling of homonym non-private namespaces 68 | * #privatens directives are now ignored, and no longer generated 69 | * Improved refid generation 70 | * Bumped #version to 3 (v1.12 disassemblies are not backwards-compatible) 71 | * Documentation updates 72 | 73 | RABCDAsm v1.11 (2012.03.15) 74 | --------------------------- 75 | 76 | * Fixed v1.10 hierarchy flattening regression 77 | * Improved refid generation for protected namespaces 78 | * Improved handling of overflown signed integers 79 | * Fixed metadata handling (caused by error in ABC format specification) 80 | * Added #version directive (v1.11 disassemblies are not backwards-compatible) 81 | * Removed path length limitation on Windows 82 | * Improved filename sanitization 83 | * Updated asasm.hrc 84 | * Documentation updates 85 | 86 | RABCDAsm v1.10 (2012.02.29) 87 | --------------------------- 88 | 89 | * Fixed escaping of paths with empty segments 90 | 91 | RABCDAsm v1.9 (2012.02.07) 92 | -------------------------- 93 | 94 | * Added support for LZMA-compressed SWF files 95 | * Added swflzmacompress 96 | * Fixed undiscovered private namespaces in class interfaces 97 | * Fixed handling of overflown integers 98 | * Documentation updates 99 | 100 | RABCDAsm v1.8 (2011.07.06) 101 | -------------------------- 102 | 103 | * Fixed handling of orphan methods with multiple references 104 | * Treat out-of-bounds namespace/multiname indices as null 105 | * Documentation updates 106 | 107 | RABCDAsm v1.7 (2011.06.14) 108 | -------------------------- 109 | 110 | * Fixed handling of invalid UTF-8 in strings 111 | * Fixed handling of null namespaces and multinames 112 | * Fixed handling of exception info in corrupted method bodies 113 | * Fixed handling of orphan private namespaces 114 | * Fixed handling of out-of-bounds class/method indices 115 | * Disassembler now creates one file per class and script-level method 116 | * Disassembler now outputs blank lines after `si32` etc. instructions as well 117 | * `abcexport` now delimits the index with a dash in output filenames 118 | * Improved shortening of `double` literals 119 | * Documentation updates 120 | 121 | RABCDAsm v1.6 (2011.05.13) 122 | -------------------------- 123 | 124 | * Overhaul of the structure of disassembler-generated files 125 | * Private namespace names and `refid`s for nested classes are now generated 126 | from their referenced contexts 127 | * This also fixes problems caused by private namespaces being referenced 128 | in multiple distinct contexts 129 | * One `#include`d file per script instead of per class 130 | * Nested classes, script initializers and other script traits are now in 131 | the same file as their main class 132 | * Inline methods are now in separate files, placed according to their usage 133 | context 134 | * Private namespaces are sorted by their autogenerated names in the 135 | `.privatens.asasm` file 136 | * No syntax changes, output is backwards-compatible 137 | * Improved escaping of file names 138 | * Output correct opcode error locations 139 | * Disassembler will now refuse to overwrite files 140 | * `rabcdasm` will now always generate output in the same directory as the 141 | input file 142 | * Failure to decode a method body is now not a fatal error 143 | * Aggressively try to shorten double literals to their shortest representation 144 | * Added the `swfbinexport` and `swfbinreplace` utilities, to aid in 145 | manipulating contents of `DefineBinaryData` tags 146 | * The package can now be built using a simple, dedicated build tool 147 | * Documentation updates 148 | 149 | RABCDAsm v1.5 (2011.04.14) 150 | -------------------------- 151 | 152 | * Fixed v1.4 constant pool regression 153 | * Added support for memory-access and sign-extend opcodes 154 | * Speed optimizations 155 | * Documentation updates 156 | 157 | RABCDAsm v1.4 (2011.03.07) 158 | -------------------------- 159 | 160 | * Source code ported to D2 161 | * Add support for forward-references for TypeName-kind Multinames 162 | * Correctly order classes by dependencies (extends/implements) and reference 163 | count 164 | * Finish Metadata support 165 | * Documentation updates 166 | 167 | RABCDAsm v1.3 (2010.11.11) 168 | -------------------------- 169 | 170 | * Fixed double precision problem 171 | * This also fixes problems with illegal default values for function 172 | parameters (default values for integer parameters are stored as doubles, 173 | which might become out-of-range due to inadequate double precision) 174 | * Added Changelog 175 | * Documentation markdown fixes 176 | 177 | RABCDAsm v1.2 (2010.11.06) 178 | -------------------------- 179 | 180 | * Fixed ref generation for orphan objects which were only referenced by other 181 | orphans 182 | * Better error handling in `abcexport`; warn when no DoABC tags found 183 | * Documentation updates 184 | 185 | RABCDAsm v1.1 (2010.06.30) 186 | -------------------------- 187 | 188 | * Private namespaces are now referenced by auto-generated names 189 | * Use `:` to delimit namespace and name in QNames for consistency 190 | * Fixed relative include paths 191 | * Add optional byte offsets to labels, which allows lossless representation 192 | of jumps inside instructions and outside the function bounds 193 | * Documentation updates 194 | 195 | RABCDAsm v1.0 (2010.05.05) 196 | -------------------------- 197 | 198 | * Initial release. 199 | -------------------------------------------------------------------------------- /reflash/RABCDasm/abcexport.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module abcexport; 20 | 21 | import std.file; 22 | import std.path; 23 | import std.conv; 24 | import std.stdio; 25 | import swffile; 26 | 27 | void main(string[] args) 28 | { 29 | if (args.length == 1) 30 | throw new Exception("No file specified"); 31 | foreach (arg; args[1..$]) 32 | try 33 | { 34 | scope swf = SWFFile.read(cast(ubyte[])read(arg)); 35 | uint count = 0; 36 | foreach (ref tag; swf.tags) 37 | if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2)) 38 | { 39 | ubyte[] abc; 40 | if (tag.type == TagType.DoABC) 41 | abc = tag.data; 42 | else 43 | { 44 | auto p = tag.data.ptr+4; // skip flags 45 | while (*p++) {} // skip name 46 | abc = tag.data[p-tag.data.ptr..$]; 47 | } 48 | std.file.write(stripExtension(arg) ~ "-" ~ to!string(count++) ~ ".abc", abc); 49 | } 50 | if (count == 0) 51 | throw new Exception("No DoABC tags found"); 52 | } 53 | catch (Exception e) 54 | writefln("Error while processing %s: %s", arg, e); 55 | } 56 | -------------------------------------------------------------------------------- /reflash/RABCDasm/abcreplace.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module abcreplace; 20 | 21 | import std.file; 22 | import std.conv; 23 | import swffile; 24 | 25 | void main(string[] args) 26 | { 27 | if (args.length != 4) 28 | throw new Exception("Bad arguments. Usage: abcreplace file.swf index code.abc"); 29 | auto swf = SWFFile.read(cast(ubyte[])read(args[1])); 30 | auto index = to!uint(args[2]); 31 | uint count; 32 | foreach (ref tag; swf.tags) 33 | if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2) && count++ == index) 34 | { 35 | auto abc = cast(ubyte[])read(args[3]); 36 | if (tag.type == TagType.DoABC) 37 | tag.data = abc; 38 | else 39 | { 40 | auto p = tag.data.ptr+4; // skip flags 41 | while (*p++) {} // skip name 42 | tag.data = tag.data[0..p-tag.data.ptr] ~ abc; 43 | } 44 | tag.length = cast(uint)tag.data.length; 45 | write(args[1], swf.write()); 46 | return; 47 | } 48 | throw new Exception("Not enough DoABC tags in file"); 49 | } 50 | -------------------------------------------------------------------------------- /reflash/RABCDasm/asasm.hrc: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | 10 | ActionScript Assembler Syntax (RABCDAsm variant) 11 | 13 | ]]> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 374 | -------------------------------------------------------------------------------- /reflash/RABCDasm/autodata.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012, 2014 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module autodata; 20 | 21 | import murmurhash2a; 22 | import std.traits; 23 | public import std.conv; 24 | 25 | string addAutoField(string name, bool reverseSort = false) 26 | { 27 | return `mixin(typeof(handler).getMixin!(typeof(` ~ name ~ `), "` ~ name ~ `", ` ~ (reverseSort ? "true" : "false") ~`));`; 28 | } 29 | 30 | template AutoCompare() 31 | { 32 | static if (is(typeof(this)==class)) 33 | { 34 | alias typeof(this) _AutoDataTypeReference; 35 | alias Object _AutoDataOtherTypeReference; 36 | 37 | override hash_t toHash() const { try { return _AutoDataHash(); } catch(object.Exception e) { assert(0, e.msg); } } 38 | override bool opEquals(Object o) const { return _AutoDataEquals(o); } 39 | override int opCmp(Object o) const { return _AutoDataCmp(o); } 40 | } 41 | else // struct 42 | { 43 | alias const(typeof(this)*) _AutoDataTypeReference; 44 | alias const(typeof(this)*) _AutoDataOtherTypeReference; 45 | 46 | hash_t toHash() const { return _AutoDataHash(); } 47 | bool opEquals(ref const typeof(this) s) const { return _AutoDataEquals(&s); } 48 | int opCmp(ref const typeof(this) s) const { return _AutoDataCmp(&s); } 49 | } 50 | 51 | @trusted private hash_t _AutoDataHash() const 52 | { 53 | HashDataHandler handler; 54 | handler.hasher.Begin(); 55 | processData!(void, q{}, q{})(handler); 56 | return handler.hasher.End(); 57 | } 58 | 59 | private bool _AutoDataEquals(_AutoDataOtherTypeReference other) const 60 | { 61 | auto handler = EqualsDataHandler!_AutoDataTypeReference(cast(_AutoDataTypeReference) other); 62 | if (handler.other is null) 63 | return false; 64 | return processData!(bool, q{auto _AutoDataOther = handler.other;}, q{return true;})(handler); 65 | } 66 | 67 | private int _AutoDataCmp(_AutoDataOtherTypeReference other) const 68 | { 69 | auto handler = CmpDataHandler!_AutoDataTypeReference(cast(_AutoDataTypeReference) other); 70 | if (handler.other is null) 71 | return false; 72 | return processData!(int, q{auto _AutoDataOther = handler.other;}, "return 0;")(handler); 73 | } 74 | } 75 | 76 | template AutoToString() 77 | { 78 | static if (is(typeof(this)==class)) 79 | override string toString() const { return _AutoDataToString(); } 80 | else // struct 81 | string toString() const { return _AutoDataToString(); } 82 | 83 | string _AutoDataToString() const 84 | { 85 | ToStringDataHandler handler; 86 | return processData!(string, "string _AutoDataResult;", "return _AutoDataResult;")(handler); 87 | } 88 | } 89 | 90 | template ProcessAllData() 91 | { 92 | R processData(R, string prolog, string epilog, H)(ref H handler) const 93 | { 94 | mixin(prolog); 95 | foreach (i, T; this.tupleof) 96 | mixin(addAutoField(this.tupleof[i].stringof[5..$])); // remove "this." 97 | mixin(epilog); 98 | } 99 | } 100 | 101 | /// For data handlers that only need to look at the raw data (currently only HashDataHandler) 102 | template RawDataHandlerWrapper() 103 | { 104 | template getMixin(T, string name, bool reverseSort) 105 | { 106 | enum getMixin = getMixinRecursive!(T, "this." ~ name, ""); 107 | } 108 | 109 | template getMixinRecursive(T, string name, string loopDepth) 110 | { 111 | static if (is(T U : U[])) 112 | enum getMixinRecursive = 113 | "{ bool _AutoDataNullTest = " ~ name ~ " is null; " ~ getRawMixin!("&_AutoDataNullTest", "bool.sizeof") ~ "}" ~ 114 | (!hasAliasing!(U) ? 115 | getRawMixin!(name ~ ".ptr", name ~ ".length") 116 | : 117 | "foreach (ref _AutoDataArrayItem" ~ loopDepth ~ "; " ~ name ~ ") {" ~ getMixinRecursive!(U, "_AutoDataArrayItem" ~ loopDepth, loopDepth~"Item") ~ "}" 118 | ); 119 | else 120 | static if (!hasAliasing!(T)) 121 | enum getMixinRecursive = getRawMixin!("&" ~ name, name ~ ".sizeof"); 122 | else 123 | static if (is(T==struct)) 124 | enum getMixinRecursive = name ~ ".processData!(void, ``, ``)(handler);"; 125 | else 126 | static if (is(T==class)) 127 | enum getMixinRecursive = "if ("~name~" !is null) " ~ name ~ ".processData!(void, ``, ``)(handler);"; 128 | else 129 | static assert(0, "Don't know how to process type: " ~ T.stringof); 130 | } 131 | } 132 | 133 | struct HashDataHandler 134 | { 135 | mixin RawDataHandlerWrapper; 136 | 137 | MurmurHash2A hasher; 138 | 139 | template getRawMixin(string ptr, string len) 140 | { 141 | enum getRawMixin = "handler.hasher.Add(" ~ ptr ~ ", to!int(" ~ len ~ "));"; 142 | } 143 | } 144 | 145 | struct EqualsDataHandler(O) 146 | { 147 | O other; 148 | 149 | template nullCheck(T, string name) 150 | { 151 | static if (is(typeof(T.init is null))) 152 | enum nullCheck = "if ((this." ~ name ~ " is null) != (_AutoDataOther." ~ name ~ " is null)) return false;"; 153 | else 154 | enum nullCheck = ""; 155 | } 156 | 157 | template getMixin(T, string name, bool reverseSort) 158 | { 159 | enum getMixin = nullCheck!(T, name) ~ "if (this." ~ name ~ " != _AutoDataOther." ~ name ~ ") return false;"; 160 | } 161 | } 162 | 163 | struct CmpDataHandler(O) 164 | { 165 | O other; 166 | 167 | template getMixin(T, string name, bool reverseSort) 168 | { 169 | enum getMixin = getMixinComposite!(T, name, reverseSort).code; 170 | } 171 | 172 | template nullCheck(T, string name, string reverseStr) 173 | { 174 | static if (is(typeof(T.init is null))) 175 | enum nullCheck = " 176 | if (this."~name~" is null && _AutoDataOther."~name~" is null) 177 | { /* skip */ } 178 | else 179 | if (this."~name~" is null && _AutoDataOther."~name~" !is null) 180 | return " ~ reverseStr ~ "(-1); 181 | else 182 | if (this."~name~" !is null && _AutoDataOther."~name~" is null) 183 | return " ~ reverseStr ~ "( 1); 184 | else"; 185 | else 186 | enum nullCheck = ""; 187 | } 188 | 189 | template getMixinComposite(T, string name, bool reverseSort) 190 | { 191 | enum reverseStr = reverseSort ? "-" : ""; 192 | static if (is(T U : U[])) 193 | enum arrCode = "{ int _AutoDataCmp = cast(int)(this." ~ name ~ " !is null) - cast(int)(_AutoDataOther." ~ name ~ " !is null); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; 194 | else 195 | enum arrCode = ""; 196 | 197 | static if (is(T == string) && is(std.string.cmp)) 198 | enum dataCode = "{ int _AutoDataCmp = std.string.cmp(this." ~ name ~ ", _AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; 199 | else 200 | static if (is(T == int)) 201 | enum dataCode = "{ int _AutoDataCmp = this." ~ name ~ " - _AutoDataOther." ~ name ~ "; if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; // TODO: use long? 202 | else 203 | static if (is(typeof(T.opCmp))) 204 | enum dataCode = nullCheck!(T, name, reverseStr) 205 | ~ "{ int _AutoDataCmp = this." ~ name ~ ".opCmp(cast()_AutoDataOther." ~ name ~ "); if (_AutoDataCmp != 0) return " ~ reverseStr ~ "_AutoDataCmp; }"; 206 | else 207 | enum dataCode = "if (this." ~ name ~ " < _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "(-1);" ~ 208 | "if (this." ~ name ~ " > _AutoDataOther." ~ name ~ ") return " ~ reverseStr ~ "( 1);"; 209 | enum code = arrCode ~ dataCode; 210 | } 211 | } 212 | 213 | struct ToStringDataHandler 214 | { 215 | template getMixinSingle(T, string name) 216 | { 217 | /* 218 | enum getMixinSingle = " 219 | static if (is(typeof(_AutoDataResult ~= " ~ name ~ ".toString()))) 220 | _AutoDataResult ~= " ~ name ~ ".toString(); 221 | else 222 | _AutoDataResult ~= to!string(" ~ name ~ "); 223 | "; 224 | */ 225 | static if (is(typeof(T.init is null))) 226 | enum getMixinSingle = "_AutoDataResult ~= " ~ name ~ " ? to!string(" ~ name ~ ") : `null`;"; 227 | else 228 | enum getMixinSingle = "_AutoDataResult ~= to!string(" ~ name ~ ");"; 229 | } 230 | 231 | template getMixinBody(T, string name) 232 | { 233 | // TODO: arrays of arrays 234 | static if (is(T U : U[]) && !is(T : const(char)[])) 235 | { 236 | enum getMixinBody = " 237 | _AutoDataResult ~= ` [ `; 238 | foreach (_AutoDataArrayIndex, _AutoDataArrayItem; " ~ name ~ ") 239 | { 240 | if (_AutoDataArrayIndex) _AutoDataResult ~= ` , `; 241 | " ~ getMixinSingle!(U, "_AutoDataArrayItem") ~ " 242 | } 243 | _AutoDataResult ~= ` ] `; 244 | "; 245 | } 246 | else 247 | enum getMixinBody = getMixinSingle!(T, name); 248 | } 249 | 250 | template getMixin(T, string name, bool reverseSort) 251 | { 252 | enum getMixin = 253 | "_AutoDataResult ~= `" ~ name ~ " = `;" ~ 254 | getMixinBody!(T, name) ~ 255 | "_AutoDataResult ~= ` `;"; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /reflash/RABCDasm/build_rabcdasm.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012, 2013, 2016 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | /// A simple tool to build RABCDAsm in one command. 20 | /// You can use the DC and DCFLAGS environment variables to override the detected compiler and compilation flags. 21 | /// You can also pass program names or compilation options on the command-line to override the default ones. 22 | 23 | module build_rabcdasm; 24 | 25 | version(D_Version2) 26 | { /* All OK */ } 27 | else 28 | static assert(false, "Unsupported D version.\nThis software requires a D2 ( http://dlang.org/ ) compiler to build."); 29 | 30 | version(D_Version2): 31 | 32 | version(DigitalMars) 33 | const DEFAULT_COMPILER = "dmd"; 34 | else 35 | const DEFAULT_COMPILER = "gdmd"; 36 | 37 | const DEFAULT_FLAGS = "-O -inline"; 38 | const LZMA_FLAGS = ["-version=HAVE_LZMA"]; 39 | 40 | import std.exception; 41 | import std.file; 42 | import std.process; 43 | import std.stdio; 44 | import std.string; 45 | 46 | string compiler; 47 | string[] flags; 48 | 49 | void compile(string program) 50 | { 51 | stderr.writeln("* Building ", program); 52 | enforce(spawnProcess(["rdmd", "--build-only", "--compiler=" ~ compiler] ~ flags ~ program).wait() == 0, "Compilation of " ~ program ~ " failed"); 53 | } 54 | 55 | void test(string code, in string[] extraFlags=null) 56 | { 57 | const BASE = "build_rabcdasm_buildtest"; 58 | const FN = BASE ~ ".d"; 59 | std.file.write(FN, code); 60 | scope(exit) foreach (de; dirEntries(".", BASE ~ "*", SpanMode.shallow)) remove(de.name); 61 | enforce(spawnProcess(["rdmd", "--force", "--compiler=" ~ compiler, "-od."] ~ flags ~ extraFlags ~ FN).wait() == 0, "Test failed"); 62 | stderr.writeln(" >>> OK"); 63 | } 64 | 65 | void testBug(string description, int bugId, string code) 66 | { 67 | stderr.writefln("* Checking for compiler bug %d...", bugId); 68 | scope(failure) 69 | { 70 | stderr.writefln("Compiler bug detected: %s ( https://issues.dlang.org/show_bug.cgi?id=%d ).", description, bugId); 71 | stderr.writeln("Try again with a different D compiler, compiler version, or build flags (DCFLAGS environment variable)"); 72 | } 73 | test(code); 74 | } 75 | 76 | int main(string[] args) 77 | { 78 | try 79 | { 80 | auto programs = ["rabcasm", "rabcdasm", "abcexport", "abcreplace", "swfbinexport", "swfbinreplace", "swfdecompress", "swf7zcompress"]; 81 | 82 | compiler = environment.get("DC", DEFAULT_COMPILER); 83 | flags = environment.get("DCFLAGS", DEFAULT_FLAGS).split(" "); 84 | 85 | string[] optionArgs, programArgs; 86 | foreach (arg; args[1..$]) 87 | (arg.startsWith("-") ? optionArgs : programArgs) ~= arg; 88 | 89 | if (optionArgs.length) 90 | flags = optionArgs; 91 | if (programArgs.length) 92 | programs = programArgs; 93 | 94 | stderr.writeln("* Checking for working compiler..."); 95 | test(` 96 | void main() {} 97 | `); 98 | 99 | testBug("[REG 2.064] Wrong code with -O on x86_64 for char comparisons", 11508, ` 100 | import assembler; int main() { foreach (c; "_") if (!Assembler.isWordChar(c)) return 1; return 0; } 101 | `); 102 | testBug("[REG 2.069] Wrong double-to-string conversion with -O", 15861, ` 103 | import std.format; int main() { return format("%.18g", 4286853117.0) == "4286853117" ? 0 : 1; } 104 | `); 105 | 106 | bool haveLZMA; 107 | 108 | stderr.writeln("* Checking for LZMA..."); 109 | try 110 | { 111 | test(` 112 | import lzma, std.exception; 113 | void main() 114 | { 115 | LZMAHeader header; 116 | auto data = cast(immutable(ubyte)[])"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; 117 | auto cdata = lzmaCompress(data, &header); 118 | header.decompressedSize = data.length; 119 | auto ddata = lzmaDecompress(header, cdata); 120 | enforce(data == ddata); 121 | } 122 | `, LZMA_FLAGS); 123 | 124 | // Test succeeded 125 | haveLZMA = true; 126 | } 127 | catch (Exception e) 128 | stderr.writeln(" >>> LZMA not found, building without LZMA support."); 129 | 130 | if (haveLZMA) 131 | flags ~= LZMA_FLAGS; 132 | 133 | foreach (program; programs) 134 | compile(program); 135 | 136 | if (haveLZMA) 137 | compile("swflzmacompress"); 138 | 139 | return 0; 140 | } 141 | catch (Exception e) 142 | { 143 | stderr.writeln("Error: ", e.msg); 144 | return 1; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /reflash/RABCDasm/common.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, 2014 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module common; 20 | 21 | import std.array; 22 | import std.path; 23 | import std.stdio; 24 | import std.string; 25 | 26 | string longPath(string s) 27 | { 28 | version(Windows) 29 | { 30 | if (s.startsWith(`\\`)) 31 | return s; 32 | else 33 | return `\\?\` ~ s.absolutePath().buildNormalizedPath().replace(`/`, `\`); 34 | } 35 | else 36 | return s; 37 | } 38 | 39 | File openFile(string fn, string mode) 40 | { 41 | File f; 42 | static if (is(typeof(&f.windowsHandleOpen))) 43 | { 44 | import core.sys.windows.windows; 45 | 46 | import std.exception; 47 | import std.utf; 48 | import std.windows.syserror; 49 | 50 | string winMode; 51 | foreach (c; mode) 52 | switch (c) 53 | { 54 | case 'r': 55 | case 'w': 56 | case 'a': 57 | case '+': 58 | winMode ~= c; 59 | break; 60 | case 'b': 61 | case 't': 62 | break; 63 | default: 64 | assert(false, "Unknown character in mode"); 65 | } 66 | DWORD access, creation; 67 | bool append; 68 | switch (winMode) 69 | { 70 | case "r" : access = GENERIC_READ ; creation = OPEN_EXISTING; break; 71 | case "r+": access = GENERIC_READ | GENERIC_WRITE; creation = OPEN_EXISTING; break; 72 | case "w" : access = GENERIC_WRITE; creation = OPEN_ALWAYS ; break; 73 | case "w+": access = GENERIC_READ | GENERIC_WRITE; creation = OPEN_ALWAYS ; break; 74 | case "a" : access = GENERIC_WRITE; creation = OPEN_ALWAYS ; append = true; break; 75 | case "a+": assert(false, "Not implemented"); // requires two file pointers 76 | default: assert(false, "Bad file mode: " ~ mode); 77 | } 78 | 79 | auto pathW = toUTF16z(longPath(fn)); 80 | auto h = CreateFileW(pathW, access, FILE_SHARE_READ, null, creation, 0, HANDLE.init); 81 | enforce(h != INVALID_HANDLE_VALUE, "Failed to open file \"" ~ fn ~ "\": " ~ sysErrorString(GetLastError())); 82 | 83 | assert(!append, "'a' mode not implemented"); 84 | 85 | f.windowsHandleOpen(h, mode); 86 | } 87 | else 88 | f.open(fn, mode); 89 | return f; 90 | } 91 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file api/lzma.h 3 | * \brief The public API of liblzma data compression library 4 | * 5 | * liblzma is a public domain general-purpose data compression library with 6 | * a zlib-like API. The native file format is .xz, but also the old .lzma 7 | * format and raw (no headers) streams are supported. Multiple compression 8 | * algorithms (filters) are supported. Currently LZMA2 is the primary filter. 9 | * 10 | * liblzma is part of XZ Utils . XZ Utils includes 11 | * a gzip-like command line tool named xz and some other tools. XZ Utils 12 | * is developed and maintained by Lasse Collin. 13 | * 14 | * Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK 15 | * . 16 | * 17 | * The SHA-256 implementation is based on the public domain code found from 18 | * 7-Zip , which has a modified version of the public 19 | * domain SHA-256 code found from Crypto++ . 20 | * The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai. 21 | */ 22 | 23 | /* 24 | * Author: Lasse Collin 25 | * 26 | * This file has been put into the public domain. 27 | * You can do whatever you want with this file. 28 | */ 29 | 30 | module deimos.lzma; 31 | 32 | /*********** 33 | * nothrow * 34 | ***********/ 35 | 36 | /* 37 | * None of the functions in liblzma may throw an exception. Even 38 | * the functions that use callback functions won't throw exceptions, 39 | * because liblzma would break if a callback function threw an exception. 40 | */ 41 | //lzma_nothrow --> nothrow 42 | 43 | 44 | /******************** 45 | * GNU C extensions * 46 | ********************/ 47 | 48 | /* 49 | * GNU C extensions are used conditionally in the public API. It doesn't 50 | * break anything if these are sometimes enabled and sometimes not, only 51 | * affects warnings and optimizations. 52 | */ 53 | 54 | //lzma_attr_pure --> pure 55 | //lzma_attr_const --> const 56 | //lzma_attr_warn_unused_result --> n/a 57 | 58 | 59 | /************** 60 | * Subheaders * 61 | **************/ 62 | public import deimos.lzma_.version_; 63 | public import deimos.lzma_.base; 64 | public import deimos.lzma_.vli; 65 | public import deimos.lzma_.check; 66 | 67 | /* Filters */ 68 | public import deimos.lzma_.filter; 69 | public import deimos.lzma_.bcj; 70 | public import deimos.lzma_.delta; 71 | public import deimos.lzma_.lzma; 72 | 73 | /* Container formats */ 74 | public import deimos.lzma_.container; 75 | 76 | /* Advanced features */ 77 | public import deimos.lzma_.stream_flags; 78 | public import deimos.lzma_.block; 79 | public import deimos.lzma_.index; 80 | public import deimos.lzma_.index_hash; 81 | 82 | /* Hardware information */ 83 | public import deimos.lzma_.hardware; 84 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/bcj.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/bcj.h 3 | * \brief Branch/Call/Jump conversion filters 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.bcj; 16 | import deimos.lzma; 17 | 18 | extern(C): 19 | 20 | /* Filter IDs for lzma_filter.id */ 21 | 22 | enum LZMA_FILTER_X86 = 0x04UL; 23 | /**< 24 | * Filter for x86 binaries 25 | */ 26 | 27 | 28 | enum LZMA_FILTER_POWERPC = 0x05UL; 29 | /**< 30 | * Filter for Big endian PowerPC binaries 31 | */ 32 | 33 | enum LZMA_FILTER_IA64 = 0x06UL; 34 | /**< 35 | * Filter for IA-64 (Itanium) binaries. 36 | */ 37 | 38 | enum LZMA_FILTER_ARM = 0x07UL; 39 | /**< 40 | * Filter for ARM binaries. 41 | */ 42 | 43 | enum LZMA_FILTER_ARMTHUMB = 0x08UL; 44 | /**< 45 | * Filter for ARM-Thumb binaries. 46 | */ 47 | 48 | enum LZMA_FILTER_SPARC = 0x09UL; 49 | /**< 50 | * Filter for SPARC binaries. 51 | */ 52 | 53 | 54 | /** 55 | * \brief Options for BCJ filters 56 | * 57 | * The BCJ filters never change the size of the data. Specifying options 58 | * for them is optional: if pointer to options is NULL, default value is 59 | * used. You probably never need to specify options to BCJ filters, so just 60 | * set the options pointer to NULL and be happy. 61 | * 62 | * If options with non-default values have been specified when encoding, 63 | * the same options must also be specified when decoding. 64 | * 65 | * \note At the moment, none of the BCJ filters support 66 | * LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified, 67 | * LZMA_OPTIONS_ERROR will be returned. If there is need, 68 | * partial support for LZMA_SYNC_FLUSH can be added in future. 69 | * Partial means that flushing would be possible only at 70 | * offsets that are multiple of 2, 4, or 16 depending on 71 | * the filter, except x86 which cannot be made to support 72 | * LZMA_SYNC_FLUSH predictably. 73 | */ 74 | struct lzma_options_bcj 75 | { 76 | /** 77 | * \brief Start offset for conversions 78 | * 79 | * This setting is useful only when the same filter is used 80 | * _separately_ for multiple sections of the same executable file, 81 | * and the sections contain cross-section branch/call/jump 82 | * instructions. In that case it is beneficial to set the start 83 | * offset of the non-first sections so that the relative addresses 84 | * of the cross-section branch/call/jump instructions will use the 85 | * same absolute addresses as in the first section. 86 | * 87 | * When the pointer to options is NULL, the default value (zero) 88 | * is used. 89 | */ 90 | uint start_offset; 91 | } 92 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/check.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/check.h 3 | * \brief Integrity checks 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.check; 16 | import deimos.lzma; 17 | 18 | extern(C): 19 | 20 | /** 21 | * \brief Type of the integrity check (Check ID) 22 | * 23 | * The .xz format supports multiple types of checks that are calculated 24 | * from the uncompressed data. They vary in both speed and ability to 25 | * detect errors. 26 | */ 27 | enum lzma_check 28 | { 29 | LZMA_CHECK_NONE = 0, 30 | /**< 31 | * No Check is calculated. 32 | * 33 | * Size of the Check field: 0 bytes 34 | */ 35 | 36 | LZMA_CHECK_CRC32 = 1, 37 | /**< 38 | * CRC32 using the polynomial from the IEEE 802.3 standard 39 | * 40 | * Size of the Check field: 4 bytes 41 | */ 42 | 43 | LZMA_CHECK_CRC64 = 4, 44 | /**< 45 | * CRC64 using the polynomial from the ECMA-182 standard 46 | * 47 | * Size of the Check field: 8 bytes 48 | */ 49 | 50 | LZMA_CHECK_SHA256 = 10 51 | } 52 | 53 | 54 | /** 55 | * \brief Maximum valid Check ID 56 | * 57 | * The .xz file format specification specifies 16 Check IDs (0-15). Some 58 | * of them are only reserved, that is, no actual Check algorithm has been 59 | * assigned. When decoding, liblzma still accepts unknown Check IDs for 60 | * future compatibility. If a valid but unsupported Check ID is detected, 61 | * liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK, 62 | * LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h. 63 | */ 64 | enum LZMA_CHECK_ID_MAX = 15; 65 | 66 | 67 | /** 68 | * \brief Test if the given Check ID is supported 69 | * 70 | * Return true if the given Check ID is supported by this liblzma build. 71 | * Otherwise false is returned. It is safe to call this with a value that 72 | * is not in the range [0, 15]; in that case the return value is always false. 73 | * 74 | * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always 75 | * supported (even if liblzma is built with limited features). 76 | */ 77 | nothrow lzma_bool lzma_check_is_supported(lzma_check check); 78 | 79 | 80 | /** 81 | * \brief Get the size of the Check field with the given Check ID 82 | * 83 | * Although not all Check IDs have a check algorithm associated, the size of 84 | * every Check is already frozen. This function returns the size (in bytes) of 85 | * the Check field with the specified Check ID. The values are: 86 | * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 } 87 | * 88 | * If the argument is not in the range [0, 15], UINT32_MAX is returned. 89 | */ 90 | nothrow uint lzma_check_size(lzma_check check); 91 | 92 | 93 | /** 94 | * \brief Maximum size of a Check field 95 | */ 96 | enum LZMA_CHECK_SIZE_MAX = 64; 97 | 98 | 99 | /** 100 | * \brief Calculate CRC32 101 | * 102 | * Calculate CRC32 using the polynomial from the IEEE 802.3 standard. 103 | * 104 | * \param buf Pointer to the input buffer 105 | * \param size Size of the input buffer 106 | * \param crc Previously returned CRC value. This is used to 107 | * calculate the CRC of a big buffer in smaller chunks. 108 | * Set to zero when starting a new calculation. 109 | * 110 | * \return Updated CRC value, which can be passed to this function 111 | * again to continue CRC calculation. 112 | */ 113 | nothrow pure uint lzma_crc32( 114 | const(ubyte)* buf, size_t size, uint crc); 115 | 116 | 117 | /** 118 | * \brief Calculate CRC64 119 | * 120 | * Calculate CRC64 using the polynomial from the ECMA-182 standard. 121 | * 122 | * This function is used similarly to lzma_crc32(). See its documentation. 123 | */ 124 | nothrow pure ulong lzma_crc64( 125 | const(ubyte)* buf, size_t size, ulong crc); 126 | 127 | 128 | /* 129 | * SHA-256 functions are currently not exported to public API. 130 | * Contact Lasse Collin if you think it should be. 131 | */ 132 | 133 | 134 | /** 135 | * \brief Get the type of the integrity check 136 | * 137 | * This function can be called only immediately after lzma_code() has 138 | * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK. 139 | * Calling this function in any other situation has undefined behavior. 140 | */ 141 | nothrow lzma_check lzma_get_check(const lzma_stream *strm); 142 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/delta.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/delta.h 3 | * \brief Delta filter 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.delta; 16 | import deimos.lzma; 17 | 18 | extern(C): 19 | 20 | /** 21 | * \brief Filter ID 22 | * 23 | * Filter ID of the Delta filter. This is used as lzma_filter.id. 24 | */ 25 | enum LZMA_FILTER_DELTA = 0x03UL; 26 | 27 | 28 | /** 29 | * \brief Type of the delta calculation 30 | * 31 | * Currently only byte-wise delta is supported. Other possible types could 32 | * be, for example, delta of 16/32/64-bit little/big endian integers, but 33 | * these are not currently planned since byte-wise delta is almost as good. 34 | */ 35 | enum lzma_delta_type 36 | { 37 | LZMA_DELTA_TYPE_BYTE 38 | } 39 | 40 | 41 | /** 42 | * \brief Options for the Delta filter 43 | * 44 | * These options are needed by both encoder and decoder. 45 | */ 46 | struct lzma_options_delta 47 | { 48 | /** For now, this must always be LZMA_DELTA_TYPE_BYTE. */ 49 | lzma_delta_type type; 50 | 51 | /** 52 | * \brief Delta distance 53 | * 54 | * With the only currently supported type, LZMA_DELTA_TYPE_BYTE, 55 | * the distance is as bytes. 56 | * 57 | * Examples: 58 | * - 16-bit stereo audio: distance = 4 bytes 59 | * - 24-bit RGB image data: distance = 3 bytes 60 | */ 61 | uint dist; 62 | enum LZMA_DELTA_DIST_MIN = 1; 63 | enum LZMA_DELTA_DIST_MAX = 256; 64 | 65 | /* 66 | * Reserved space to allow possible future extensions without 67 | * breaking the ABI. You should not touch these, because the names 68 | * of these variables may change. These are and will never be used 69 | * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these 70 | * uninitialized. 71 | */ 72 | uint reserved_int1; 73 | uint reserved_int2; 74 | uint reserved_int3; 75 | uint reserved_int4; 76 | void *reserved_ptr1; 77 | void *reserved_ptr2; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/hardware.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/hardware.h 3 | * \brief Hardware information 4 | * 5 | * Since liblzma can consume a lot of system resources, it also provides 6 | * ways to limit the resource usage. Applications linking against liblzma 7 | * need to do the actual decisions how much resources to let liblzma to use. 8 | * To ease making these decisions, liblzma provides functions to find out 9 | * the relevant capabilities of the underlaying hardware. Currently there 10 | * is only a function to find out the amount of RAM, but in the future there 11 | * will be also a function to detect how many concurrent threads the system 12 | * can run. 13 | * 14 | * \note On some operating systems, these function may temporarily 15 | * load a shared library or open file descriptor(s) to find out 16 | * the requested hardware information. Unless the application 17 | * assumes that specific file descriptors are not touched by 18 | * other threads, this should have no effect on thread safety. 19 | * Possible operations involving file descriptors will restart 20 | * the syscalls if they return EINTR. 21 | */ 22 | 23 | /* 24 | * Author: Lasse Collin 25 | * 26 | * This file has been put into the public domain. 27 | * You can do whatever you want with this file. 28 | * 29 | * See ../lzma.h for information about liblzma as a whole. 30 | */ 31 | 32 | module deimos.lzma_.hardware; 33 | import deimos.lzma; 34 | 35 | extern(C): 36 | 37 | /** 38 | * \brief Get the total amount of physical memory (RAM) in bytes 39 | * 40 | * This function may be useful when determining a reasonable memory 41 | * usage limit for decompressing or how much memory it is OK to use 42 | * for compressing. 43 | * 44 | * \return On success, the total amount of physical memory in bytes 45 | * is returned. If the amount of RAM cannot be determined, 46 | * zero is returned. This can happen if an error occurs 47 | * or if there is no code in liblzma to detect the amount 48 | * of RAM on the specific operating system. 49 | */ 50 | nothrow ulong lzma_physmem(); 51 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/index_hash.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/index_hash.h 3 | * \brief Validate Index by using a hash function 4 | * 5 | * Hashing makes it possible to use constant amount of memory to validate 6 | * Index of arbitrary size. 7 | */ 8 | 9 | /* 10 | * Author: Lasse Collin 11 | * 12 | * This file has been put into the public domain. 13 | * You can do whatever you want with this file. 14 | * 15 | * See ../lzma.h for information about liblzma as a whole. 16 | */ 17 | 18 | module deimos.lzma_.index_hash; 19 | import deimos.lzma; 20 | 21 | extern(C): 22 | 23 | /** 24 | * \brief Opaque data type to hold the Index hash 25 | */ 26 | struct lzma_index_hash {}; 27 | 28 | 29 | /** 30 | * \brief Allocate and initialize a new lzma_index_hash structure 31 | * 32 | * If index_hash is NULL, a new lzma_index_hash structure is allocated, 33 | * initialized, and a pointer to it returned. If allocation fails, NULL 34 | * is returned. 35 | * 36 | * If index_hash is non-NULL, it is reinitialized and the same pointer 37 | * returned. In this case, return value cannot be NULL or a different 38 | * pointer than the index_hash that was given as an argument. 39 | */ 40 | nothrow lzma_index_hash * lzma_index_hash_init( 41 | lzma_index_hash *index_hash, lzma_allocator *allocator); 42 | 43 | 44 | /** 45 | * \brief Deallocate lzma_index_hash structure 46 | */ 47 | nothrow void lzma_index_hash_end( 48 | lzma_index_hash *index_hash, lzma_allocator *allocator); 49 | 50 | 51 | /** 52 | * \brief Add a new Record to an Index hash 53 | * 54 | * \param index Pointer to a lzma_index_hash structure 55 | * \param unpadded_size Unpadded Size of a Block 56 | * \param uncompressed_size Uncompressed Size of a Block 57 | * 58 | * \return - LZMA_OK 59 | * - LZMA_DATA_ERROR: Compressed or uncompressed size of the 60 | * Stream or size of the Index field would grow too big. 61 | * - LZMA_PROG_ERROR: Invalid arguments or this function is being 62 | * used when lzma_index_hash_decode() has already been used. 63 | */ 64 | nothrow lzma_ret lzma_index_hash_append(lzma_index_hash *index_hash, 65 | lzma_vli unpadded_size, lzma_vli uncompressed_size); 66 | 67 | 68 | /** 69 | * \brief Decode and validate the Index field 70 | * 71 | * After telling the sizes of all Blocks with lzma_index_hash_append(), 72 | * the actual Index field is decoded with this function. Specifically, 73 | * once decoding of the Index field has been started, no more Records 74 | * can be added using lzma_index_hash_append(). 75 | * 76 | * This function doesn't use lzma_stream structure to pass the input data. 77 | * Instead, the input buffer is specified using three arguments. This is 78 | * because it matches better the internal APIs of liblzma. 79 | * 80 | * \param index_hash Pointer to a lzma_index_hash structure 81 | * \param in Pointer to the beginning of the input buffer 82 | * \param in_pos in[*in_pos] is the next byte to process 83 | * \param in_size in[in_size] is the first byte not to process 84 | * 85 | * \return - LZMA_OK: So far good, but more input is needed. 86 | * - LZMA_STREAM_END: Index decoded successfully and it matches 87 | * the Records given with lzma_index_hash_append(). 88 | * - LZMA_DATA_ERROR: Index is corrupt or doesn't match the 89 | * information given with lzma_index_hash_append(). 90 | * - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size. 91 | * - LZMA_PROG_ERROR 92 | */ 93 | nothrow lzma_ret lzma_index_hash_decode(lzma_index_hash *index_hash, 94 | const ubyte *in_, size_t *in_pos, size_t in_size); 95 | 96 | 97 | /** 98 | * \brief Get the size of the Index field as bytes 99 | * 100 | * This is needed to verify the Backward Size field in the Stream Footer. 101 | */ 102 | nothrow pure lzma_vli lzma_index_hash_size( 103 | const lzma_index_hash *index_hash); 104 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/lzma.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/lzma.h 3 | * \brief LZMA1 and LZMA2 filters 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.lzma; 16 | import deimos.lzma; 17 | 18 | extern(C): 19 | 20 | 21 | /** 22 | * \brief LZMA1 Filter ID 23 | * 24 | * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils, 25 | * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from 26 | * accidentally using LZMA when they actually want LZMA2. 27 | * 28 | * LZMA1 shouldn't be used for new applications unless you _really_ know 29 | * what you are doing. LZMA2 is almost always a better choice. 30 | */ 31 | enum LZMA_FILTER_LZMA1 = 0x4000000000000001UL; 32 | 33 | /** 34 | * \brief LZMA2 Filter ID 35 | * 36 | * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds 37 | * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion 38 | * when trying to compress uncompressible data), possibility to change 39 | * lc/lp/pb in the middle of encoding, and some other internal improvements. 40 | */ 41 | enum LZMA_FILTER_LZMA2 = 0x21UL; 42 | 43 | 44 | /** 45 | * \brief Match finders 46 | * 47 | * Match finder has major effect on both speed and compression ratio. 48 | * Usually hash chains are faster than binary trees. 49 | * 50 | * If you will use LZMA_SYNC_FLUSH often, the hash chains may be a better 51 | * choice, because binary trees get much higher compression ratio penalty 52 | * with LZMA_SYNC_FLUSH. 53 | * 54 | * The memory usage formulas are only rough estimates, which are closest to 55 | * reality when dict_size is a power of two. The formulas are more complex 56 | * in reality, and can also change a little between liblzma versions. Use 57 | * lzma_raw_encoder_memusage() to get more accurate estimate of memory usage. 58 | */ 59 | enum lzma_match_finder 60 | { 61 | LZMA_MF_HC3 = 0x03, 62 | /**< 63 | * \brief Hash Chain with 2- and 3-byte hashing 64 | * 65 | * Minimum nice_len: 3 66 | * 67 | * Memory usage: 68 | * - dict_size <= 16 MiB: dict_size * 7.5 69 | * - dict_size > 16 MiB: dict_size * 5.5 + 64 MiB 70 | */ 71 | 72 | LZMA_MF_HC4 = 0x04, 73 | /**< 74 | * \brief Hash Chain with 2-, 3-, and 4-byte hashing 75 | * 76 | * Minimum nice_len: 4 77 | * 78 | * Memory usage: 79 | * - dict_size <= 32 MiB: dict_size * 7.5 80 | * - dict_size > 32 MiB: dict_size * 6.5 81 | */ 82 | 83 | LZMA_MF_BT2 = 0x12, 84 | /**< 85 | * \brief Binary Tree with 2-byte hashing 86 | * 87 | * Minimum nice_len: 2 88 | * 89 | * Memory usage: dict_size * 9.5 90 | */ 91 | 92 | LZMA_MF_BT3 = 0x13, 93 | /**< 94 | * \brief Binary Tree with 2- and 3-byte hashing 95 | * 96 | * Minimum nice_len: 3 97 | * 98 | * Memory usage: 99 | * - dict_size <= 16 MiB: dict_size * 11.5 100 | * - dict_size > 16 MiB: dict_size * 9.5 + 64 MiB 101 | */ 102 | 103 | LZMA_MF_BT4 = 0x14 104 | /**< 105 | * \brief Binary Tree with 2-, 3-, and 4-byte hashing 106 | * 107 | * Minimum nice_len: 4 108 | * 109 | * Memory usage: 110 | * - dict_size <= 32 MiB: dict_size * 11.5 111 | * - dict_size > 32 MiB: dict_size * 10.5 112 | */ 113 | } 114 | 115 | 116 | /** 117 | * \brief Test if given match finder is supported 118 | * 119 | * Return true if the given match finder is supported by this liblzma build. 120 | * Otherwise false is returned. It is safe to call this with a value that 121 | * isn't listed in lzma_match_finder enumeration; the return value will be 122 | * false. 123 | * 124 | * There is no way to list which match finders are available in this 125 | * particular liblzma version and build. It would be useless, because 126 | * a new match finder, which the application developer wasn't aware, 127 | * could require giving additional options to the encoder that the older 128 | * match finders don't need. 129 | */ 130 | nothrow lzma_bool lzma_mf_is_supported(lzma_match_finder match_finder); 131 | 132 | 133 | /** 134 | * \brief Compression modes 135 | * 136 | * This selects the function used to analyze the data produced by the match 137 | * finder. 138 | */ 139 | enum lzma_mode 140 | { 141 | LZMA_MODE_FAST = 1, 142 | /**< 143 | * \brief Fast compression 144 | * 145 | * Fast mode is usually at its best when combined with 146 | * a hash chain match finder. 147 | */ 148 | 149 | LZMA_MODE_NORMAL = 2 150 | /**< 151 | * \brief Normal compression 152 | * 153 | * This is usually notably slower than fast mode. Use this 154 | * together with binary tree match finders to expose the 155 | * full potential of the LZMA1 or LZMA2 encoder. 156 | */ 157 | } 158 | 159 | 160 | /** 161 | * \brief Test if given compression mode is supported 162 | * 163 | * Return true if the given compression mode is supported by this liblzma 164 | * build. Otherwise false is returned. It is safe to call this with a value 165 | * that isn't listed in lzma_mode enumeration; the return value will be false. 166 | * 167 | * There is no way to list which modes are available in this particular 168 | * liblzma version and build. It would be useless, because a new compression 169 | * mode, which the application developer wasn't aware, could require giving 170 | * additional options to the encoder that the older modes don't need. 171 | */ 172 | nothrow lzma_bool lzma_mode_is_supported(lzma_mode mode); 173 | 174 | 175 | /** 176 | * \brief Options specific to the LZMA1 and LZMA2 filters 177 | * 178 | * Since LZMA1 and LZMA2 share most of the code, it's simplest to share 179 | * the options structure too. For encoding, all but the reserved variables 180 | * need to be initialized unless specifically mentioned otherwise. 181 | * lzma_lzma_preset() can be used to get a good starting point. 182 | * 183 | * For raw decoding, both LZMA1 and LZMA2 need dict_size, preset_dict, and 184 | * preset_dict_size (if preset_dict != NULL). LZMA1 needs also lc, lp, and pb. 185 | */ 186 | struct lzma_options_lzma 187 | { 188 | /** 189 | * \brief Dictionary size in bytes 190 | * 191 | * Dictionary size indicates how many bytes of the recently processed 192 | * uncompressed data is kept in memory. One method to reduce size of 193 | * the uncompressed data is to store distance-length pairs, which 194 | * indicate what data to repeat from the dictionary buffer. Thus, 195 | * the bigger the dictionary, the better the compression ratio 196 | * usually is. 197 | * 198 | * Maximum size of the dictionary depends on multiple things: 199 | * - Memory usage limit 200 | * - Available address space (not a problem on 64-bit systems) 201 | * - Selected match finder (encoder only) 202 | * 203 | * Currently the maximum dictionary size for encoding is 1.5 GiB 204 | * (i.e. (UINT32_C(1) << 30) + (UINT32_C(1) << 29)) even on 64-bit 205 | * systems for certain match finder implementation reasons. In the 206 | * future, there may be match finders that support bigger 207 | * dictionaries. 208 | * 209 | * Decoder already supports dictionaries up to 4 GiB - 1 B (i.e. 210 | * UINT32_MAX), so increasing the maximum dictionary size of the 211 | * encoder won't cause problems for old decoders. 212 | * 213 | * Because extremely small dictionaries sizes would have unneeded 214 | * overhead in the decoder, the minimum dictionary size is 4096 bytes. 215 | * 216 | * \note When decoding, too big dictionary does no other harm 217 | * than wasting memory. 218 | */ 219 | uint dict_size; 220 | enum LZMA_DICT_SIZE_MIN = 4096U; 221 | enum LZMA_DICT_SIZE_DEFAULT = (1U << 23); 222 | 223 | /** 224 | * \brief Pointer to an initial dictionary 225 | * 226 | * It is possible to initialize the LZ77 history window using 227 | * a preset dictionary. It is useful when compressing many 228 | * similar, relatively small chunks of data independently from 229 | * each other. The preset dictionary should contain typical 230 | * strings that occur in the files being compressed. The most 231 | * probable strings should be near the end of the preset dictionary. 232 | * 233 | * This feature should be used only in special situations. For 234 | * now, it works correctly only with raw encoding and decoding. 235 | * Currently none of the container formats supported by 236 | * liblzma allow preset dictionary when decoding, thus if 237 | * you create a .xz or .lzma file with preset dictionary, it 238 | * cannot be decoded with the regular decoder functions. In the 239 | * future, the .xz format will likely get support for preset 240 | * dictionary though. 241 | */ 242 | const ubyte *preset_dict; 243 | 244 | /** 245 | * \brief Size of the preset dictionary 246 | * 247 | * Specifies the size of the preset dictionary. If the size is 248 | * bigger than dict_size, only the last dict_size bytes are 249 | * processed. 250 | * 251 | * This variable is read only when preset_dict is not NULL. 252 | * If preset_dict is not NULL but preset_dict_size is zero, 253 | * no preset dictionary is used (identical to only setting 254 | * preset_dict to NULL). 255 | */ 256 | uint preset_dict_size; 257 | 258 | /** 259 | * \brief Number of literal context bits 260 | * 261 | * How many of the highest bits of the previous uncompressed 262 | * eight-bit byte (also known as `literal') are taken into 263 | * account when predicting the bits of the next literal. 264 | * 265 | * E.g. in typical English text, an upper-case letter is 266 | * often followed by a lower-case letter, and a lower-case 267 | * letter is usually followed by another lower-case letter. 268 | * In the US-ASCII character set, the highest three bits are 010 269 | * for upper-case letters and 011 for lower-case letters. 270 | * When lc is at least 3, the literal coding can take advantage of 271 | * this property in the uncompressed data. 272 | * 273 | * There is a limit that applies to literal context bits and literal 274 | * position bits together: lc + lp <= 4. Without this limit the 275 | * decoding could become very slow, which could have security related 276 | * results in some cases like email servers doing virus scanning. 277 | * This limit also simplifies the internal implementation in liblzma. 278 | * 279 | * There may be LZMA1 streams that have lc + lp > 4 (maximum possible 280 | * lc would be 8). It is not possible to decode such streams with 281 | * liblzma. 282 | */ 283 | uint lc; 284 | enum LZMA_LCLP_MIN = 0; 285 | enum LZMA_LCLP_MAX = 4; 286 | enum LZMA_LC_DEFAULT = 3; 287 | 288 | /** 289 | * \brief Number of literal position bits 290 | * 291 | * lp affects what kind of alignment in the uncompressed data is 292 | * assumed when encoding literals. A literal is a single 8-bit byte. 293 | * See pb below for more information about alignment. 294 | */ 295 | uint lp; 296 | enum LZMA_LP_DEFAULT = 0; 297 | 298 | /** 299 | * \brief Number of position bits 300 | * 301 | * pb affects what kind of alignment in the uncompressed data is 302 | * assumed in general. The default means four-byte alignment 303 | * (2^ pb =2^2=4), which is often a good choice when there's 304 | * no better guess. 305 | * 306 | * When the aligment is known, setting pb accordingly may reduce 307 | * the file size a little. E.g. with text files having one-byte 308 | * alignment (US-ASCII, ISO-8859-*, UTF-8), setting pb=0 can 309 | * improve compression slightly. For UTF-16 text, pb=1 is a good 310 | * choice. If the alignment is an odd number like 3 bytes, pb=0 311 | * might be the best choice. 312 | * 313 | * Even though the assumed alignment can be adjusted with pb and 314 | * lp, LZMA1 and LZMA2 still slightly favor 16-byte alignment. 315 | * It might be worth taking into account when designing file formats 316 | * that are likely to be often compressed with LZMA1 or LZMA2. 317 | */ 318 | uint pb; 319 | enum LZMA_PB_MIN = 0; 320 | enum LZMA_PB_MAX = 4; 321 | enum LZMA_PB_DEFAULT = 2; 322 | 323 | /** Compression mode */ 324 | lzma_mode mode; 325 | 326 | /** 327 | * \brief Nice length of a match 328 | * 329 | * This determines how many bytes the encoder compares from the match 330 | * candidates when looking for the best match. Once a match of at 331 | * least nice_len bytes long is found, the encoder stops looking for 332 | * better candidates and encodes the match. (Naturally, if the found 333 | * match is actually longer than nice_len, the actual length is 334 | * encoded; it's not truncated to nice_len.) 335 | * 336 | * Bigger values usually increase the compression ratio and 337 | * compression time. For most files, 32 to 128 is a good value, 338 | * which gives very good compression ratio at good speed. 339 | * 340 | * The exact minimum value depends on the match finder. The maximum 341 | * is 273, which is the maximum length of a match that LZMA1 and 342 | * LZMA2 can encode. 343 | */ 344 | uint nice_len; 345 | 346 | /** Match finder ID */ 347 | lzma_match_finder mf; 348 | 349 | /** 350 | * \brief Maximum search depth in the match finder 351 | * 352 | * For every input byte, match finder searches through the hash chain 353 | * or binary tree in a loop, each iteration going one step deeper in 354 | * the chain or tree. The searching stops if 355 | * - a match of at least nice_len bytes long is found; 356 | * - all match candidates from the hash chain or binary tree have 357 | * been checked; or 358 | * - maximum search depth is reached. 359 | * 360 | * Maximum search depth is needed to prevent the match finder from 361 | * wasting too much time in case there are lots of short match 362 | * candidates. On the other hand, stopping the search before all 363 | * candidates have been checked can reduce compression ratio. 364 | * 365 | * Setting depth to zero tells liblzma to use an automatic default 366 | * value, that depends on the selected match finder and nice_len. 367 | * The default is in the range [4, 200] or so (it may vary between 368 | * liblzma versions). 369 | * 370 | * Using a bigger depth value than the default can increase 371 | * compression ratio in some cases. There is no strict maximum value, 372 | * but high values (thousands or millions) should be used with care: 373 | * the encoder could remain fast enough with typical input, but 374 | * malicious input could cause the match finder to slow down 375 | * dramatically, possibly creating a denial of service attack. 376 | */ 377 | uint depth; 378 | 379 | /* 380 | * Reserved space to allow possible future extensions without 381 | * breaking the ABI. You should not touch these, because the names 382 | * of these variables may change. These are and will never be used 383 | * with the currently supported options, so it is safe to leave these 384 | * uninitialized. 385 | */ 386 | uint reserved_int1; 387 | uint reserved_int2; 388 | uint reserved_int3; 389 | uint reserved_int4; 390 | uint reserved_int5; 391 | uint reserved_int6; 392 | uint reserved_int7; 393 | uint reserved_int8; 394 | lzma_reserved_enum reserved_enum1; 395 | lzma_reserved_enum reserved_enum2; 396 | lzma_reserved_enum reserved_enum3; 397 | lzma_reserved_enum reserved_enum4; 398 | void *reserved_ptr1; 399 | void *reserved_ptr2; 400 | 401 | } 402 | 403 | 404 | /** 405 | * \brief Set a compression preset to lzma_options_lzma structure 406 | * 407 | * 0 is the fastest and 9 is the slowest. These match the switches -0 .. -9 408 | * of the xz command line tool. In addition, it is possible to bitwise-or 409 | * flags to the preset. Currently only LZMA_PRESET_EXTREME is supported. 410 | * The flags are defined in container.h, because the flags are used also 411 | * with lzma_easy_encoder(). 412 | * 413 | * The preset values are subject to changes between liblzma versions. 414 | * 415 | * This function is available only if LZMA1 or LZMA2 encoder has been enabled 416 | * when building liblzma. 417 | * 418 | * \return On success, false is returned. If the preset is not 419 | * supported, true is returned. 420 | */ 421 | nothrow lzma_bool lzma_lzma_preset( 422 | lzma_options_lzma *options, uint preset); 423 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/stream_flags.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/stream_flags.h 3 | * \brief .xz Stream Header and Stream Footer encoder and decoder 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.stream_flags; 16 | import deimos.lzma; 17 | 18 | extern(C): 19 | 20 | 21 | /** 22 | * \brief Size of Stream Header and Stream Footer 23 | * 24 | * Stream Header and Stream Footer have the same size and they are not 25 | * going to change even if a newer version of the .xz file format is 26 | * developed in future. 27 | */ 28 | enum LZMA_STREAM_HEADER_SIZE = 12; 29 | 30 | 31 | /** 32 | * \brief Options for encoding/decoding Stream Header and Stream Footer 33 | */ 34 | struct lzma_stream_flags 35 | { 36 | /** 37 | * \brief Stream Flags format version 38 | * 39 | * To prevent API and ABI breakages if new features are needed in 40 | * Stream Header or Stream Footer, a version number is used to 41 | * indicate which fields in this structure are in use. For now, 42 | * version must always be zero. With non-zero version, the 43 | * lzma_stream_header_encode() and lzma_stream_footer_encode() 44 | * will return LZMA_OPTIONS_ERROR. 45 | * 46 | * lzma_stream_header_decode() and lzma_stream_footer_decode() 47 | * will always set this to the lowest value that supports all the 48 | * features indicated by the Stream Flags field. The application 49 | * must check that the version number set by the decoding functions 50 | * is supported by the application. Otherwise it is possible that 51 | * the application will decode the Stream incorrectly. 52 | */ 53 | uint version_; 54 | 55 | /** 56 | * \brief Backward Size 57 | * 58 | * Backward Size must be a multiple of four bytes. In this Stream 59 | * format version, Backward Size is the size of the Index field. 60 | * 61 | * Backward Size isn't actually part of the Stream Flags field, but 62 | * it is convenient to include in this structure anyway. Backward 63 | * Size is present only in the Stream Footer. There is no need to 64 | * initialize backward_size when encoding Stream Header. 65 | * 66 | * lzma_stream_header_decode() always sets backward_size to 67 | * LZMA_VLI_UNKNOWN so that it is convenient to use 68 | * lzma_stream_flags_compare() when both Stream Header and Stream 69 | * Footer have been decoded. 70 | */ 71 | lzma_vli backward_size; 72 | enum LZMA_BACKWARD_SIZE_MIN = 4; 73 | enum LZMA_BACKWARD_SIZE_MAX = (1UL << 34); 74 | 75 | /** 76 | * \brief Check ID 77 | * 78 | * This indicates the type of the integrity check calculated from 79 | * uncompressed data. 80 | */ 81 | lzma_check check; 82 | 83 | /* 84 | * Reserved space to allow possible future extensions without 85 | * breaking the ABI. You should not touch these, because the 86 | * names of these variables may change. 87 | * 88 | * (We will never be able to use all of these since Stream Flags 89 | * is just two bytes plus Backward Size of four bytes. But it's 90 | * nice to have the proper types when they are needed.) 91 | */ 92 | lzma_reserved_enum reserved_enum1; 93 | lzma_reserved_enum reserved_enum2; 94 | lzma_reserved_enum reserved_enum3; 95 | lzma_reserved_enum reserved_enum4; 96 | lzma_bool reserved_bool1; 97 | lzma_bool reserved_bool2; 98 | lzma_bool reserved_bool3; 99 | lzma_bool reserved_bool4; 100 | lzma_bool reserved_bool5; 101 | lzma_bool reserved_bool6; 102 | lzma_bool reserved_bool7; 103 | lzma_bool reserved_bool8; 104 | uint reserved_int1; 105 | uint reserved_int2; 106 | } 107 | 108 | 109 | /** 110 | * \brief Encode Stream Header 111 | * 112 | * \param options Stream Header options to be encoded. 113 | * options->backward_size is ignored and doesn't 114 | * need to be initialized. 115 | * \param out Beginning of the output buffer of 116 | * LZMA_STREAM_HEADER_SIZE bytes. 117 | * 118 | * \return - LZMA_OK: Encoding was successful. 119 | * - LZMA_OPTIONS_ERROR: options->version is not supported by 120 | * this liblzma version. 121 | * - LZMA_PROG_ERROR: Invalid options. 122 | */ 123 | nothrow lzma_ret lzma_stream_header_encode( 124 | const lzma_stream_flags *options, ubyte *out_); 125 | 126 | 127 | /** 128 | * \brief Encode Stream Footer 129 | * 130 | * \param options Stream Footer options to be encoded. 131 | * \param out Beginning of the output buffer of 132 | * LZMA_STREAM_HEADER_SIZE bytes. 133 | * 134 | * \return - LZMA_OK: Encoding was successful. 135 | * - LZMA_OPTIONS_ERROR: options->version is not supported by 136 | * this liblzma version. 137 | * - LZMA_PROG_ERROR: Invalid options. 138 | */ 139 | nothrow lzma_ret lzma_stream_footer_encode( 140 | const lzma_stream_flags *options, ubyte *out_); 141 | 142 | 143 | /** 144 | * \brief Decode Stream Header 145 | * 146 | * \param options Target for the decoded Stream Header options. 147 | * \param in Beginning of the input buffer of 148 | * LZMA_STREAM_HEADER_SIZE bytes. 149 | * 150 | * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to 151 | * help comparing Stream Flags from Stream Header and Stream Footer with 152 | * lzma_stream_flags_compare(). 153 | * 154 | * \return - LZMA_OK: Decoding was successful. 155 | * - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given 156 | * buffer cannot be Stream Header. 157 | * - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header 158 | * is corrupt. 159 | * - LZMA_OPTIONS_ERROR: Unsupported options are present 160 | * in the header. 161 | * 162 | * \note When decoding .xz files that contain multiple Streams, it may 163 | * make sense to print "file format not recognized" only if 164 | * decoding of the Stream Header of the _first_ Stream gives 165 | * LZMA_FORMAT_ERROR. If non-first Stream Header gives 166 | * LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is 167 | * probably more appropriate. 168 | * 169 | * For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if 170 | * LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode() 171 | * when decoding non-first Stream. 172 | */ 173 | nothrow lzma_ret lzma_stream_header_decode( 174 | lzma_stream_flags *options, const ubyte *in_); 175 | 176 | 177 | /** 178 | * \brief Decode Stream Footer 179 | * 180 | * \param options Target for the decoded Stream Header options. 181 | * \param in Beginning of the input buffer of 182 | * LZMA_STREAM_HEADER_SIZE bytes. 183 | * 184 | * \return - LZMA_OK: Decoding was successful. 185 | * - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given 186 | * buffer cannot be Stream Footer. 187 | * - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer 188 | * is corrupt. 189 | * - LZMA_OPTIONS_ERROR: Unsupported options are present 190 | * in Stream Footer. 191 | * 192 | * \note If Stream Header was already decoded successfully, but 193 | * decoding Stream Footer returns LZMA_FORMAT_ERROR, the 194 | * application should probably report some other error message 195 | * than "file format not recognized", since the file more likely 196 | * is corrupt (possibly truncated). Stream decoder in liblzma 197 | * uses LZMA_DATA_ERROR in this situation. 198 | */ 199 | nothrow lzma_ret lzma_stream_footer_decode( 200 | lzma_stream_flags *options, const ubyte *in_); 201 | 202 | 203 | /** 204 | * \brief Compare two lzma_stream_flags structures 205 | * 206 | * backward_size values are compared only if both are not 207 | * LZMA_VLI_UNKNOWN. 208 | * 209 | * \return - LZMA_OK: Both are equal. If either had backward_size set 210 | * to LZMA_VLI_UNKNOWN, backward_size values were not 211 | * compared or validated. 212 | * - LZMA_DATA_ERROR: The structures differ. 213 | * - LZMA_OPTIONS_ERROR: version in either structure is greater 214 | * than the maximum supported version (currently zero). 215 | * - LZMA_PROG_ERROR: Invalid value, e.g. invalid check or 216 | * backward_size. 217 | */ 218 | nothrow pure lzma_ret lzma_stream_flags_compare( 219 | const lzma_stream_flags *a, const lzma_stream_flags *b); 220 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/version_.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/version.h 3 | * \brief Version number 4 | */ 5 | 6 | /* 7 | * Author: Lasse Collin 8 | * 9 | * This file has been put into the public domain. 10 | * You can do whatever you want with this file. 11 | * 12 | * See ../lzma.h for information about liblzma as a whole. 13 | */ 14 | 15 | module deimos.lzma_.version_; 16 | import deimos.lzma; 17 | import std.conv; 18 | 19 | extern(C): 20 | 21 | /* 22 | * Version number split into components 23 | */ 24 | enum LZMA_VERSION_MAJOR = 5; 25 | enum LZMA_VERSION_MINOR = 0; 26 | enum LZMA_VERSION_PATCH = 3; 27 | enum LZMA_VERSION_STABILITY = LZMA_VERSION_STABILITY_STABLE; 28 | 29 | /* 30 | #ifndef LZMA_VERSION_COMMIT 31 | # define LZMA_VERSION_COMMIT "" 32 | #endif*/ 33 | enum LZMA_VERSION_COMMIT = ""; 34 | 35 | /* 36 | * Map symbolic stability levels to integers. 37 | */ 38 | enum LZMA_VERSION_STABILITY_ALPHA = 0; 39 | enum LZMA_VERSION_STABILITY_BETA = 1; 40 | enum LZMA_VERSION_STABILITY_STABLE = 2; 41 | 42 | 43 | /** 44 | * \brief Compile-time version number 45 | * 46 | * The version number is of format xyyyzzzs where 47 | * - x = major 48 | * - yyy = minor 49 | * - zzz = revision 50 | * - s indicates stability: 0 = alpha, 1 = beta, 2 = stable 51 | * 52 | * The same xyyyzzz triplet is never reused with different stability levels. 53 | * For example, if 5.1.0alpha has been released, there will never be 5.1.0beta 54 | * or 5.1.0 stable. 55 | * 56 | * \note The version number of liblzma has nothing to with 57 | * the version number of Igor Pavlov's LZMA SDK. 58 | */ 59 | enum LZMA_VERSION = (LZMA_VERSION_MAJOR * 10000000U 60 | + LZMA_VERSION_MINOR * 10000U 61 | + LZMA_VERSION_PATCH * 10U 62 | + LZMA_VERSION_STABILITY); 63 | 64 | 65 | /* 66 | * Macros to construct the compile-time version string 67 | */ 68 | static if(LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_ALPHA) 69 | enum LZMA_VERSION_STABILITY_STRING = "alpha"; 70 | else static if(LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_BETA) 71 | enum LZMA_VERSION_STABILITY_STRING = "beta"; 72 | else static if(LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_STABLE) 73 | enum LZMA_VERSION_STABILITY_STRING = ""; 74 | else 75 | static assert(false, "Incorrect LZMA_VERSION_STABILITY"); 76 | 77 | /** 78 | * \brief Compile-time version as a string 79 | * 80 | * This can be for example "4.999.5alpha", "4.999.8beta", or "5.0.0" (stable 81 | * versions don't have any "stable" suffix). In future, a snapshot built 82 | * from source code repository may include an additional suffix, for example 83 | * "4.999.8beta-21-g1d92". The commit ID won't be available in numeric form 84 | * in LZMA_VERSION macro. 85 | */ 86 | enum LZMA_VERSION_STRING = 87 | to!string(LZMA_VERSION_MAJOR) ~ "." ~ to!string(LZMA_VERSION_MINOR) ~ 88 | "." ~ to!string(LZMA_VERSION_PATCH) ~ LZMA_VERSION_STABILITY_STRING ~ 89 | LZMA_VERSION_COMMIT; 90 | 91 | 92 | /** 93 | * \brief Run-time version number as an integer 94 | * 95 | * Return the value of LZMA_VERSION macro at the compile time of liblzma. 96 | * This allows the application to compare if it was built against the same, 97 | * older, or newer version of liblzma that is currently running. 98 | */ 99 | nothrow uint lzma_version_number(); 100 | 101 | 102 | /** 103 | * \brief Run-time version as a string 104 | * 105 | * This function may be useful if you want to display which version of 106 | * liblzma your application is currently using. 107 | */ 108 | nothrow immutable(char)* lzma_version_string(); 109 | -------------------------------------------------------------------------------- /reflash/RABCDasm/deimos/lzma_/vli.d: -------------------------------------------------------------------------------- 1 | /** 2 | * \file lzma/vli.h 3 | * \brief Variable-length integer handling 4 | * 5 | * In the .xz format, most integers are encoded in a variable-length 6 | * representation, which is sometimes called little endian base-128 encoding. 7 | * This saves space when smaller values are more likely than bigger values. 8 | * 9 | * The encoding scheme encodes seven bits to every byte, using minimum 10 | * number of bytes required to represent the given value. Encodings that use 11 | * non-minimum number of bytes are invalid, thus every integer has exactly 12 | * one encoded representation. The maximum number of bits in a VLI is 63, 13 | * thus the vli argument must be less than or equal to UINT64_MAX / 2. You 14 | * should use LZMA_VLI_MAX for clarity. 15 | */ 16 | 17 | /* 18 | * Author: Lasse Collin 19 | * 20 | * This file has been put into the public domain. 21 | * You can do whatever you want with this file. 22 | * 23 | * See ../lzma.h for information about liblzma as a whole. 24 | */ 25 | 26 | module deimos.lzma_.vli; 27 | import deimos.lzma; 28 | 29 | extern(C): 30 | 31 | 32 | /** 33 | * \brief Maximum supported value of a variable-length integer 34 | */ 35 | enum LZMA_VLI_MAX = (ulong.max / 2); 36 | 37 | /** 38 | * \brief VLI value to denote that the value is unknown 39 | */ 40 | enum LZMA_VLI_UNKNOWN = ulong.max; 41 | 42 | /** 43 | * \brief Maximum supported encoded length of variable length integers 44 | */ 45 | enum LZMA_VLI_BYTES_MAX = 9; 46 | 47 | /** 48 | * \brief VLI constant suffix 49 | */ 50 | //#define LZMA_VLI_C(n) UINT64_C(n) 51 | 52 | 53 | /** 54 | * \brief Variable-length integer type 55 | * 56 | * Valid VLI values are in the range [0, LZMA_VLI_MAX]. Unknown value is 57 | * indicated with LZMA_VLI_UNKNOWN, which is the maximum value of the 58 | * underlaying integer type. 59 | * 60 | * lzma_vli will be uint64_t for the foreseeable future. If a bigger size 61 | * is needed in the future, it is guaranteed that 2 * LZMA_VLI_MAX will 62 | * not overflow lzma_vli. This simplifies integer overflow detection. 63 | */ 64 | alias ulong lzma_vli; 65 | 66 | 67 | /** 68 | * \brief Validate a variable-length integer 69 | * 70 | * This is useful to test that application has given acceptable values 71 | * for example in the uncompressed_size and compressed_size variables. 72 | * 73 | * \return True if the integer is representable as VLI or if it 74 | * indicates unknown value. 75 | */ 76 | bool lzma_vli_is_valid(lzma_vli vli) 77 | { 78 | return vli <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN; 79 | } 80 | 81 | 82 | /** 83 | * \brief Encode a variable-length integer 84 | * 85 | * This function has two modes: single-call and multi-call. Single-call mode 86 | * encodes the whole integer at once; it is an error if the output buffer is 87 | * too small. Multi-call mode saves the position in *vli_pos, and thus it is 88 | * possible to continue encoding if the buffer becomes full before the whole 89 | * integer has been encoded. 90 | * 91 | * \param vli Integer to be encoded 92 | * \param vli_pos How many VLI-encoded bytes have already been written 93 | * out. When starting to encode a new integer in 94 | * multi-call mode, *vli_pos must be set to zero. 95 | * To use single-call encoding, set vli_pos to NULL. 96 | * \param out Beginning of the output buffer 97 | * \param out_pos The next byte will be written to out[*out_pos]. 98 | * \param out_size Size of the out buffer; the first byte into 99 | * which no data is written to is out[out_size]. 100 | * 101 | * \return Slightly different return values are used in multi-call and 102 | * single-call modes. 103 | * 104 | * Single-call (vli_pos == NULL): 105 | * - LZMA_OK: Integer successfully encoded. 106 | * - LZMA_PROG_ERROR: Arguments are not sane. This can be due 107 | * to too little output space; single-call mode doesn't use 108 | * LZMA_BUF_ERROR, since the application should have checked 109 | * the encoded size with lzma_vli_size(). 110 | * 111 | * Multi-call (vli_pos != NULL): 112 | * - LZMA_OK: So far all OK, but the integer is not 113 | * completely written out yet. 114 | * - LZMA_STREAM_END: Integer successfully encoded. 115 | * - LZMA_BUF_ERROR: No output space was provided. 116 | * - LZMA_PROG_ERROR: Arguments are not sane. 117 | */ 118 | nothrow lzma_ret lzma_vli_encode(lzma_vli vli, size_t *vli_pos, 119 | ubyte* out_, size_t *out_pos, size_t out_size); 120 | 121 | 122 | /** 123 | * \brief Decode a variable-length integer 124 | * 125 | * Like lzma_vli_encode(), this function has single-call and multi-call modes. 126 | * 127 | * \param vli Pointer to decoded integer. The decoder will 128 | * initialize it to zero when *vli_pos == 0, so 129 | * application isn't required to initialize *vli. 130 | * \param vli_pos How many bytes have already been decoded. When 131 | * starting to decode a new integer in multi-call 132 | * mode, *vli_pos must be initialized to zero. To 133 | * use single-call decoding, set vli_pos to NULL. 134 | * \param in Beginning of the input buffer 135 | * \param in_pos The next byte will be read from in[*in_pos]. 136 | * \param in_size Size of the input buffer; the first byte that 137 | * won't be read is in[in_size]. 138 | * 139 | * \return Slightly different return values are used in multi-call and 140 | * single-call modes. 141 | * 142 | * Single-call (vli_pos == NULL): 143 | * - LZMA_OK: Integer successfully decoded. 144 | * - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting 145 | * the end of the input buffer before the whole integer was 146 | * decoded; providing no input at all will use LZMA_DATA_ERROR. 147 | * - LZMA_PROG_ERROR: Arguments are not sane. 148 | * 149 | * Multi-call (vli_pos != NULL): 150 | * - LZMA_OK: So far all OK, but the integer is not 151 | * completely decoded yet. 152 | * - LZMA_STREAM_END: Integer successfully decoded. 153 | * - LZMA_DATA_ERROR: Integer is corrupt. 154 | * - LZMA_BUF_ERROR: No input was provided. 155 | * - LZMA_PROG_ERROR: Arguments are not sane. 156 | */ 157 | nothrow lzma_ret lzma_vli_decode(lzma_vli *vli, size_t *vli_pos, 158 | const(ubyte)* in_, size_t *in_pos, size_t in_size); 159 | 160 | 161 | /** 162 | * \brief Get the number of bytes required to encode a VLI 163 | * 164 | * \return Number of bytes on success (1-9). If vli isn't valid, 165 | * zero is returned. 166 | */ 167 | nothrow pure uint lzma_vli_size(lzma_vli vli); 168 | -------------------------------------------------------------------------------- /reflash/RABCDasm/lzma.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012, 2013, 2014, 2016 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module lzma; 20 | 21 | version(HAVE_LZMA) {} else static assert(0, "LZMA is not available (HAVE_LZMA version is not defined)"); 22 | 23 | import deimos.lzma; 24 | import std.conv; 25 | import std.exception; 26 | import std.string : format; 27 | 28 | version (Windows) 29 | { pragma(lib, "liblzma"); } 30 | else 31 | { pragma(lib, "lzma"); } 32 | 33 | align(1) struct LZMAHeader 34 | { 35 | align(1): 36 | ubyte compressionParameters; 37 | uint dictionarySize; 38 | long decompressedSize = -1; 39 | } 40 | static assert(LZMAHeader.sizeof == 13); 41 | 42 | ubyte[] lzmaDecompress(LZMAHeader header, in ubyte[] compressedData) 43 | { 44 | lzma_stream strm; 45 | lzmaEnforce(lzma_alone_decoder(&strm, ulong.max), "lzma_alone_decoder"); 46 | scope(exit) lzma_end(&strm); 47 | 48 | auto outBuf = new ubyte[1024]; 49 | size_t pos = 0; 50 | 51 | void decompress(in ubyte[] chunk) 52 | { 53 | strm.next_in = chunk.ptr; 54 | strm.avail_in = chunk.length; 55 | 56 | again: 57 | strm.next_out = outBuf.ptr + pos; 58 | strm.avail_out = outBuf.length - pos; 59 | auto ret = lzma_code(&strm, lzma_action.LZMA_RUN); 60 | pos = strm.next_out - outBuf.ptr; 61 | 62 | if (ret == lzma_ret.LZMA_OK && strm.avail_in && !strm.avail_out) 63 | { 64 | outBuf.length = outBuf.length * 2; 65 | goto again; 66 | } 67 | lzmaEnforce!true(ret, "lzma_code (LZMA_RUN)"); 68 | enforce(strm.avail_in == 0, "Not all data was read"); 69 | } 70 | 71 | header.decompressedSize = -1; // Required as Flash uses End-of-Stream marker 72 | fixDictSize(header.dictionarySize); 73 | decompress(cast(ubyte[])(&header)[0..1]); 74 | decompress(compressedData); 75 | 76 | lzmaEnforce!true(lzma_code(&strm, lzma_action.LZMA_FINISH), "lzma_code (LZMA_FINISH)"); 77 | 78 | // enforce(strm.avail_out == 0, 79 | // "Decompressed size mismatch (expected %d/0x%X, got %d/0x%X)".format( 80 | // outBuf.length, outBuf.length, 81 | // outBuf.length - strm.avail_out, outBuf.length - strm.avail_out, 82 | // )); 83 | 84 | outBuf = outBuf[0..pos]; 85 | 86 | return outBuf; 87 | } 88 | 89 | ubyte[] lzmaCompress(in ubyte[] decompressedData, LZMAHeader* header) 90 | { 91 | lzma_options_lzma opts; 92 | enforce(lzma_lzma_preset(&opts, 9 | LZMA_PRESET_EXTREME) == false, "lzma_lzma_preset error"); 93 | 94 | lzma_stream strm; 95 | lzmaEnforce(lzma_alone_encoder(&strm, &opts), "lzma_alone_encoder"); 96 | scope(exit) lzma_end(&strm); 97 | 98 | auto outBuf = new ubyte[decompressedData.length * 11 / 10 + 1024]; 99 | strm.next_out = outBuf.ptr; 100 | strm.avail_out = outBuf.length; 101 | strm.next_in = decompressedData.ptr; 102 | strm.avail_in = decompressedData.length; 103 | lzmaEnforce(lzma_code(&strm, lzma_action.LZMA_RUN), "lzma_code (LZMA_RUN)"); 104 | enforce(strm.avail_in == 0, "Not all data was read"); 105 | enforce(strm.avail_out != 0, "Ran out of compression space"); 106 | 107 | lzmaEnforce!true(lzma_code(&strm, lzma_action.LZMA_FINISH), "lzma_code (LZMA_FINISH)"); 108 | 109 | *header = *cast(LZMAHeader*)outBuf.ptr; 110 | return outBuf[LZMAHeader.sizeof..to!size_t(strm.total_out)]; 111 | } 112 | 113 | private void lzmaEnforce(bool STREAM_END_OK=false)(lzma_ret v, string f) 114 | { 115 | if (v != lzma_ret.LZMA_OK && (!STREAM_END_OK || v != lzma_ret.LZMA_STREAM_END)) 116 | throw new Exception(text(f, " error: ", v)); 117 | } 118 | 119 | /// Work around an artificial lzma_alone_decoder limitation in liblzma 120 | /// which prevents it from accepting any streams with a dictionary size 121 | /// that is not 2^n or 2^n + 2^(n-1). 122 | /// See xz\src\liblzma\common\alone_decoder.c (git commit e7b424d267), line 87 123 | private void fixDictSize(ref uint d) 124 | { 125 | --d; 126 | d |= d >> 2; 127 | d |= d >> 3; 128 | d |= d >> 4; 129 | d |= d >> 8; 130 | d |= d >> 16; 131 | ++d; 132 | } 133 | -------------------------------------------------------------------------------- /reflash/RABCDasm/murmurhash2a.d: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // CMurmurHash2A, by Austin Appleby 3 | 4 | // This is a sample implementation of MurmurHash2A designed to work 5 | // incrementally. 6 | 7 | // Usage - 8 | 9 | // CMurmurHash2A hasher 10 | // hasher.Begin(seed); 11 | // hasher.Add(data1,size1); 12 | // hasher.Add(data2,size2); 13 | // ... 14 | // hasher.Add(dataN,sizeN); 15 | // uint hash = hasher.End() 16 | 17 | module murmurhash2a; 18 | 19 | import std.conv; 20 | 21 | struct MurmurHash2A 22 | { 23 | private static string mmix(string h, string k) { return "{ "~k~" *= m; "~k~" ^= "~k~" >> r; "~k~" *= m; "~h~" *= m; "~h~" ^= "~k~"; }"; } 24 | 25 | 26 | public: 27 | 28 | void Begin ( uint seed = 0 ) 29 | { 30 | m_hash = seed; 31 | m_tail = 0; 32 | m_count = 0; 33 | m_size = 0; 34 | } 35 | 36 | void Add ( const(void) * vdata, int len ) 37 | { 38 | ubyte * data = cast(ubyte*)vdata; 39 | m_size += len; 40 | 41 | MixTail(data,len); 42 | 43 | while(len >= 4) 44 | { 45 | uint k = *cast(uint*)data; 46 | 47 | mixin(mmix("m_hash","k")); 48 | 49 | data += 4; 50 | len -= 4; 51 | } 52 | 53 | MixTail(data,len); 54 | } 55 | 56 | uint End ( ) 57 | { 58 | mixin(mmix("m_hash","m_tail")); 59 | mixin(mmix("m_hash","m_size")); 60 | 61 | m_hash ^= m_hash >> 13; 62 | m_hash *= m; 63 | m_hash ^= m_hash >> 15; 64 | 65 | return m_hash; 66 | } 67 | 68 | // D-specific 69 | void Add(ref ubyte v) { Add(&v, v.sizeof); } 70 | void Add(ref int v) { Add(&v, v.sizeof); } 71 | void Add(ref uint v) { Add(&v, v.sizeof); } 72 | void Add(string s) { Add(s.ptr, to!uint(s.length)); } 73 | void Add(ubyte[] s) { Add(s.ptr, to!uint(s.length)); } 74 | 75 | private: 76 | 77 | static const uint m = 0x5bd1e995; 78 | static const int r = 24; 79 | 80 | void MixTail ( ref ubyte * data, ref int len ) 81 | { 82 | while( len && ((len<4) || m_count) ) 83 | { 84 | m_tail |= (*data++) << (m_count * 8); 85 | 86 | m_count++; 87 | len--; 88 | 89 | if(m_count == 4) 90 | { 91 | mixin(mmix("m_hash","m_tail")); 92 | m_tail = 0; 93 | m_count = 0; 94 | } 95 | } 96 | } 97 | 98 | uint m_hash; 99 | uint m_tail; 100 | uint m_count; 101 | uint m_size; 102 | }; 103 | -------------------------------------------------------------------------------- /reflash/RABCDasm/rabcasm.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module rabcasm; 20 | 21 | import std.file; 22 | import std.path; 23 | import abcfile; 24 | import asprogram; 25 | import assembler; 26 | 27 | void main(string[] args) 28 | { 29 | if (args.length == 1) 30 | throw new Exception("No arguments specified"); 31 | auto as = new ASProgram; 32 | auto assembler = new Assembler(as); 33 | foreach (arg; args[1..$]) 34 | { 35 | assembler.assemble(arg); 36 | } 37 | auto abc = as.toABC(); 38 | write(setExtension(args[1], "abc"), abc.write()); 39 | } 40 | -------------------------------------------------------------------------------- /reflash/RABCDasm/rabcdasm.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module rabcdasm; 20 | 21 | import std.file; 22 | import std.path; 23 | import abcfile; 24 | import asprogram; 25 | import disassembler; 26 | 27 | void main(string[] args) 28 | { 29 | if (args.length == 1) 30 | throw new Exception("No arguments specified"); 31 | foreach (arg; args[1..$]) 32 | { 33 | scope abc = ABCFile.read(cast(ubyte[])read(arg)); 34 | scope as = ASProgram.fromABC(abc); 35 | scope disassembler = new Disassembler(as, stripExtension(arg), stripExtension(baseName(arg))); 36 | disassembler.disassemble(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swf7zcompress.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2016 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swf7zcompress; 20 | 21 | import std.file; 22 | import std.process; 23 | import std.zlib; 24 | import swffile; 25 | import zlibx; 26 | 27 | ubyte[] gzip2zlib(ubyte[] data, uint adler) 28 | { 29 | enum 30 | { 31 | FTEXT = 1, 32 | FHCRC = 2, 33 | FEXTRA = 4, 34 | FNAME = 8, 35 | FCOMMENT = 16 36 | } 37 | 38 | if (data.length < 10 || data[0] != 0x1F || data[1] != 0x8B || data[2] != 0x08) 39 | throw new Exception("Bad or unsupported gzip format"); 40 | ubyte flags = data[3]; 41 | auto p = data.ptr; 42 | p += 10; // header size 43 | if (flags & (FHCRC | FEXTRA | FCOMMENT)) 44 | throw new Exception("Unsupported gzip flags"); 45 | if (flags & FNAME) 46 | while (*p++) {} 47 | 48 | ubyte[] chdr = [0x78, 0xDA]; // 11011010 49 | return chdr ~ data[p-data.ptr..data.length-8] ~ cast(ubyte[])[adler]; 50 | } 51 | 52 | void main(string[] args) 53 | { 54 | if (args.length == 1) 55 | throw new Exception("No file specified"); 56 | foreach (arg; args[1..$]) 57 | { 58 | auto swf = cast(ubyte[])read(arg); 59 | auto header = cast(SWFFile.Header*)swf.ptr; 60 | ubyte[] data; 61 | if (header.signature[0] == cast(ubyte)'C') 62 | data = exactUncompress(swf[8..$], header.fileLength-8); 63 | else 64 | if (header.signature[0] == cast(ubyte)'F') 65 | { 66 | data = swf[8..$]; 67 | header.signature[0] = cast(ubyte)'C'; 68 | } 69 | else 70 | throw new Exception("Unknown format"); 71 | if (header.fileLength != data.length + 8) 72 | throw new Exception("Incorrect file length in file header"); 73 | write(arg ~ ".tempdata", data); 74 | if (spawnProcess(["7z", "a", "-tgzip", "-mx=9", "-mfb=258", arg ~ ".tempdata.gz", arg ~ ".tempdata"]).wait() || !exists(arg ~ ".tempdata.gz")) 75 | throw new Exception("7-Zip failed"); 76 | remove(arg ~ ".tempdata"); 77 | auto gzipdata = cast(ubyte[])read(arg ~ ".tempdata.gz"); 78 | remove(arg ~ ".tempdata.gz"); 79 | auto zlibdata = gzip2zlib(gzipdata, adler32(0, data)); 80 | swf = swf[0..8] ~ zlibdata; 81 | write(arg, swf); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swfbinexport.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swfbinexport; 20 | 21 | import std.file; 22 | import std.path; 23 | import std.string; 24 | import std.stdio; 25 | import std.exception; 26 | import swffile; 27 | 28 | void main(string[] args) 29 | { 30 | if (args.length == 1) 31 | throw new Exception("No file specified"); 32 | foreach (arg; args[1..$]) 33 | try 34 | { 35 | scope swf = SWFFile.read(cast(ubyte[])read(arg)); 36 | bool found; 37 | foreach (ref tag; swf.tags) 38 | if (tag.type == TagType.DefineBinaryData) 39 | { 40 | found = true; 41 | enforce(tag.data.length >= 6); 42 | ushort id = *cast(short*)tag.data.ptr; 43 | ubyte[] bin = tag.data[6..$]; 44 | std.file.write(format("%s-%d.bin", stripExtension(arg), id), bin); 45 | } 46 | enforce(found, "No DefineBinaryData tags found"); 47 | } 48 | catch (Exception e) 49 | writefln("Error while processing %s: %s", arg, e); 50 | } 51 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swfbinreplace.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swfbinreplace; 20 | 21 | import std.file; 22 | import std.conv; 23 | import swffile; 24 | 25 | void main(string[] args) 26 | { 27 | if (args.length != 4) 28 | throw new Exception("Bad arguments. Usage: swfbinreplace file.swf id data.bin"); 29 | auto swf = SWFFile.read(cast(ubyte[])read(args[1])); 30 | auto id = to!ushort(args[2]); 31 | foreach (ref tag; swf.tags) 32 | if (tag.type == TagType.DefineBinaryData && tag.data.length >= 6 && *cast(short*)tag.data.ptr == id) 33 | { 34 | auto bin = cast(ubyte[])read(args[3]); 35 | tag.data = tag.data[0..6] ~ bin; 36 | tag.length = cast(uint)tag.data.length; 37 | write(args[1], swf.write()); 38 | return; 39 | } 40 | throw new Exception("DefineBinaryData tag with specified ID not found in file"); 41 | } 42 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swfdecompress.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swfdecompress; 20 | 21 | import std.file; 22 | import swffile; 23 | 24 | void main(string[] args) 25 | { 26 | if (args.length == 1) 27 | throw new Exception("No file specified"); 28 | foreach (arg; args[1..$]) 29 | { 30 | auto swf = SWFFile.read(cast(ubyte[])read(arg)); 31 | if (swf.header.signature[0] == cast(ubyte)'F') 32 | throw new Exception("Already uncompressed"); 33 | swf.header.signature[0] = cast(ubyte)'F'; // uncompressed 34 | write(arg, swf.write()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swffile.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012, 2016 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swffile; 20 | 21 | import std.conv; 22 | import std.exception; 23 | import std.string : format; 24 | import std.zlib; 25 | import zlibx; 26 | version (HAVE_LZMA) import lzma; 27 | 28 | /** 29 | * Implements a shallow representation of a .swf file. 30 | * Loading and saving a .swf file using this class should produce 31 | * output identical to the input (aside zlib compression differences). 32 | */ 33 | 34 | final class SWFFile 35 | { 36 | Header header; 37 | Rect frameSize; 38 | ushort frameRate, frameCount; 39 | Tag[] tags; 40 | 41 | align(1) struct Header 42 | { 43 | align(1): 44 | char[3] signature; 45 | ubyte ver; 46 | uint fileLength; 47 | static assert(Header.sizeof == 8); 48 | } 49 | 50 | align(1) struct LZMAHeader 51 | { 52 | align(1): 53 | uint compressedLength; 54 | ubyte compressionParameters; 55 | uint dictionarySize; 56 | static assert(LZMAHeader.sizeof == 9); 57 | } 58 | 59 | struct Rect 60 | { 61 | //int xMin, xMax, yMin, yMax; 62 | ubyte[] bytes; 63 | } 64 | 65 | struct Tag 66 | { 67 | ushort type; 68 | ubyte[] data; 69 | uint length; // may be >data.length if file is truncated 70 | bool forceLongLength; 71 | } 72 | 73 | static SWFFile read(ubyte[] data) 74 | { 75 | return (new SWFReader(data)).swf; 76 | } 77 | 78 | ubyte[] write() 79 | { 80 | return SWFWriter.write(this); 81 | } 82 | } 83 | 84 | private final class SWFReader 85 | { 86 | ubyte[] buf; 87 | size_t pos; 88 | SWFFile swf; 89 | 90 | this(ubyte[] data) 91 | { 92 | buf = data; 93 | swf = new SWFFile(); 94 | 95 | readRaw((&swf.header)[0..1]); 96 | enforce(swf.header.signature == "FWS" || swf.header.signature == "CWS" || swf.header.signature == "ZWS", "Invalid file signature"); 97 | if (swf.header.signature[0] == 'C') 98 | buf = buf[0..swf.header.sizeof] ~ exactUncompress(buf[swf.header.sizeof..$], swf.header.fileLength-swf.header.sizeof); 99 | else 100 | if (swf.header.signature[0] == 'Z') 101 | { 102 | version (HAVE_LZMA) 103 | { 104 | SWFFile.LZMAHeader lzHeader; 105 | readRaw((&lzHeader)[0..1]); 106 | 107 | lzma.LZMAHeader lzInfo; 108 | lzInfo.compressionParameters = lzHeader.compressionParameters; 109 | lzInfo.dictionarySize = lzHeader.dictionarySize; 110 | lzInfo.decompressedSize = swf.header.fileLength - swf.header.sizeof; 111 | 112 | enforce(swf.header.sizeof + lzHeader.sizeof + lzHeader.compressedLength == buf.length, "Trailing data in LZMA-compressed SWF file"); 113 | buf = buf[0..swf.header.sizeof] ~ lzmaDecompress(lzInfo, buf[swf.header.sizeof + lzHeader.sizeof .. $]); 114 | pos = swf.header.sizeof; 115 | } 116 | else 117 | enforce(false, "This version was built without LZMA support"); 118 | } 119 | //enforce(swf.header.fileLength == buf.length, 120 | // "Incorrect file length in file header (expected %d, got %d)" 121 | // .format(swf.header.fileLength , buf.length)); 122 | swf.frameSize = readRect(); 123 | swf.frameRate = readU16(); 124 | swf.frameCount = readU16(); 125 | 126 | while (pos < buf.length) 127 | swf.tags ~= readTag(); 128 | } 129 | 130 | void readRaw(void[] raw) 131 | { 132 | raw[] = buf[pos..pos+raw.length]; 133 | pos += raw.length; 134 | } 135 | 136 | /// May read less than len on EOF 137 | void[] readRaw(size_t len) 138 | { 139 | auto end = pos+len; 140 | auto data = buf[pos..end<$?end:$]; 141 | pos = end; 142 | return data; 143 | } 144 | 145 | version(LittleEndian) {} else static assert(0, "Big endian platforms not supported"); 146 | 147 | ushort readU16() 148 | { 149 | ushort r; 150 | readRaw((&r)[0..1]); 151 | return r; 152 | } 153 | 154 | uint readU32() 155 | { 156 | uint r; 157 | readRaw((&r)[0..1]); 158 | return r; 159 | } 160 | 161 | SWFFile.Rect readRect() 162 | { 163 | SWFFile.Rect r; 164 | ubyte b = buf[pos]; 165 | uint nbits = b >> 3; 166 | uint nbytes = ((5 + 4*nbits) + 7) / 8; 167 | r.bytes = cast(ubyte[])readRaw(nbytes); 168 | return r; 169 | } 170 | 171 | SWFFile.Tag readTag() 172 | { 173 | SWFFile.Tag t; 174 | ushort u = readU16(); 175 | t.type = cast(ushort)(u >> 6); 176 | uint length = u & 0x3F; 177 | if (length == 0x3F) 178 | { 179 | length = readU32(); 180 | if (length < 0x3F) 181 | t.forceLongLength = true; 182 | } 183 | t.length = length; 184 | t.data = cast(ubyte[])readRaw(length); 185 | return t; 186 | } 187 | } 188 | 189 | enum TagType 190 | { 191 | End = 0, 192 | ShowFrame = 1, 193 | DefineShape = 2, 194 | FreeCharacter = 3, 195 | PlaceObject = 4, 196 | RemoveObject = 5, 197 | DefineBits = 6, 198 | DefineButton = 7, 199 | JPEGTables = 8, 200 | SetBackgroundColor = 9, 201 | DefineFont = 10, 202 | DefineText = 11, 203 | DoAction = 12, 204 | DefineFontInfo = 13, 205 | DefineSound = 14, 206 | StartSound = 15, 207 | DefineButtonSound = 17, 208 | SoundStreamHead = 18, 209 | SoundStreamBlock = 19, 210 | DefineBitsLossless = 20, 211 | DefineBitsJPEG2 = 21, 212 | DefineShape2 = 22, 213 | DefineButtonCxform = 23, 214 | Protect = 24, 215 | PathsArePostScript = 25, 216 | PlaceObject2 = 26, 217 | RemoveObject2 = 28, 218 | DefineShape3 = 32, 219 | DefineText2 = 33, 220 | DefineButton2 = 34, 221 | DefineBitsJPEG3 = 35, 222 | DefineBitsLossless2 = 36, 223 | DefineSprite = 39, 224 | ProductInfo = 41, 225 | FrameLabel = 43, 226 | SoundStreamHead2 = 45, 227 | DefineMorphShape = 46, 228 | DefineFont2 = 48, 229 | DefineEditText = 37, 230 | ExportAssets = 56, 231 | ImportAssets = 57, 232 | EnableDebugger = 58, 233 | DoInitAction = 59, 234 | DefineVideoStream = 60, 235 | VideoFrame = 61, 236 | DefineFontInfo2 = 62, 237 | DebugID = 63, 238 | EnableDebugger2 = 64, 239 | ScriptLimits = 65, 240 | SetTabIndex = 66, 241 | FileAttributes = 69, 242 | PlaceObject3 = 70, 243 | ImportAssets2 = 71, 244 | DoABC = 72, 245 | DefineFontAlignZones = 73, 246 | CSMTextSettings = 74, 247 | DefineFont3 = 75, 248 | SymbolClass = 76, 249 | Metadata = 77, 250 | DefineScalingGrid = 78, 251 | DoABC2 = 82, 252 | DefineShape4 = 83, 253 | DefineMorphShape2 = 84, 254 | DefineSceneAndFrameLabelData = 86, 255 | DefineBinaryData = 87, 256 | DefineFontName = 88, 257 | DefineFont4 = 91 258 | } 259 | 260 | private final class SWFWriter 261 | { 262 | static ubyte[] write(SWFFile swf) 263 | { 264 | ubyte[] buf; 265 | 266 | buf ~= swf.frameSize.bytes; 267 | buf ~= toArray(swf.frameRate); 268 | buf ~= toArray(swf.frameCount); 269 | 270 | foreach (ref tag; swf.tags) 271 | { 272 | ushort u = cast(ushort)(tag.type << 6); 273 | if (tag.length < 0x3F && !tag.forceLongLength) 274 | { 275 | u |= tag.length; 276 | buf ~= toArray(u); 277 | } 278 | else 279 | { 280 | u |= 0x3F; 281 | buf ~= toArray(u); 282 | uint l = to!uint(tag.length); 283 | buf ~= toArray(l); 284 | } 285 | buf ~= tag.data; 286 | } 287 | 288 | swf.header.fileLength = to!uint(swf.header.sizeof + buf.length); 289 | if (swf.header.signature[0] == 'C') 290 | buf = cast(ubyte[])compress(buf, 9); 291 | else 292 | if (swf.header.signature[0] == 'Z') 293 | { 294 | version (HAVE_LZMA) 295 | { 296 | lzma.LZMAHeader lzInfo; 297 | buf = lzmaCompress(buf, &lzInfo); 298 | 299 | SWFFile.LZMAHeader lzHeader; 300 | lzHeader.compressionParameters = lzInfo.compressionParameters; 301 | lzHeader.dictionarySize = lzInfo.dictionarySize; 302 | lzHeader.compressedLength = to!uint(buf.length); 303 | 304 | buf = cast(ubyte[])(&lzHeader)[0..1] ~ buf; 305 | } 306 | else 307 | enforce(false, "This version was built without LZMA support"); 308 | } 309 | buf = toArray(swf.header) ~ buf; 310 | 311 | return buf; 312 | } 313 | 314 | static ubyte[] toArray(T)(ref T v) 315 | { 316 | return cast(ubyte[])(&v)[0..1]; 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /reflash/RABCDasm/swflzmacompress.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012, 2013 Vladimir Panteleev 3 | * This file is part of RABCDAsm. 4 | * 5 | * RABCDAsm is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * RABCDAsm is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with RABCDAsm. If not, see . 17 | */ 18 | 19 | module swflzmacompress; 20 | 21 | import std.exception; 22 | import std.file; 23 | import std.getopt; 24 | import std.string; 25 | import swffile; 26 | 27 | void main(string[] args) 28 | { 29 | bool force, updateVersion; 30 | getopt(args, 31 | "--force", &force, 32 | "--update-version", &updateVersion, 33 | ); 34 | 35 | if (args.length == 1) 36 | throw new Exception("No file specified"); 37 | enum MIN_LZMA_VER = 13; 38 | foreach (arg; args[1..$]) 39 | { 40 | auto swf = SWFFile.read(cast(ubyte[])read(arg)); 41 | enforce(swf.header.signature[0] != cast(ubyte)'Z', "Already LZMA-compressed"); 42 | if (swf.header.ver < MIN_LZMA_VER) 43 | { 44 | if (updateVersion) 45 | { 46 | if (swf.header.ver < 8 && !force) 47 | throw new Exception(format( 48 | "SWF version %d has different file format than version %d, " ~ 49 | "required for LZMA. Resulting file may not work. " ~ 50 | "Use --force to override and update version anyway.", 51 | swf.header.ver, MIN_LZMA_VER 52 | )); 53 | swf.header.ver = MIN_LZMA_VER; 54 | } 55 | else 56 | if (!force) 57 | throw new Exception(format( 58 | "SWF version %d is too old to support SWF LZMA compression, " ~ 59 | "which requires version %d. " ~ 60 | "Use --update-version to update the version number, " ~ 61 | "or --force to compress anyway without updating it.", 62 | swf.header.ver, MIN_LZMA_VER 63 | )); 64 | } 65 | swf.header.signature[0] = cast(ubyte)'Z'; // LZMA 66 | write(arg, swf.write()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /reflash/RABCDasm/zlibx.d: -------------------------------------------------------------------------------- 1 | /// This code is in the public domain. 2 | 3 | module zlibx; 4 | 5 | import std.string : format; 6 | import std.zlib, etc.c.zlib, std.conv; 7 | static import etc.c.zlib; 8 | alias std.zlib.Z_SYNC_FLUSH Z_SYNC_FLUSH; 9 | debug import std.stdio : stderr; 10 | 11 | /// Avoid bug(?) in D zlib implementation with 7zip-generated zlib streams 12 | ubyte[] exactUncompress(ubyte[] srcbuf, size_t destlen) 13 | { 14 | etc.c.zlib.z_stream zs; 15 | 16 | auto destbuf = new ubyte[destlen]; 17 | uint err; 18 | 19 | zs.next_in = srcbuf.ptr; 20 | zs.avail_in = to!uint(srcbuf.length); 21 | 22 | zs.next_out = destbuf.ptr; 23 | zs.avail_out = to!uint(destbuf.length); 24 | 25 | err = etc.c.zlib.inflateInit2(&zs, 15); 26 | if (err) 27 | { 28 | delete destbuf; 29 | throw new ZlibException(err); 30 | } 31 | 32 | while (true) 33 | { 34 | err = etc.c.zlib.inflate(&zs, Z_SYNC_FLUSH); 35 | if (err != Z_OK && err != Z_STREAM_END) 36 | { 37 | Lerr: 38 | delete destbuf; 39 | etc.c.zlib.inflateEnd(&zs); 40 | throw new ZlibException(err); 41 | } 42 | 43 | if (err == Z_STREAM_END) 44 | break; 45 | else 46 | if (zs.avail_out == 0) 47 | { 48 | debug stderr.writefln("Wrong uncompressed file length (read %d/%d bytes and wrote %d/%d bytes)", 49 | srcbuf .length - zs.avail_in , srcbuf .length, 50 | destlen - zs.avail_out, destlen); 51 | auto out_pos = zs.next_out - destbuf.ptr; 52 | destbuf.length = 1024 + destbuf.length * 2; 53 | zs.next_out = destbuf.ptr + out_pos; 54 | zs.avail_out = to!uint(destbuf.length - out_pos); 55 | continue; 56 | } 57 | else 58 | if (zs.avail_in == 0) 59 | { 60 | debug stderr.writefln("Unterminated Zlib stream (read %d/%d bytes and wrote %d/%d bytes)", 61 | srcbuf .length - zs.avail_in , srcbuf .length, 62 | destlen - zs.avail_out, destlen); 63 | break; 64 | } 65 | else 66 | throw new Exception(format("Unexpected zlib state (err=%d, avail_in == %d, avail_out = %d)", 67 | err, zs.avail_in , zs.avail_out)); 68 | } 69 | 70 | if (zs.avail_in != 0 || zs.avail_out != 0) 71 | debug stderr.writefln("Zlib stream incongruity (read %d/%d bytes and wrote %d/%d bytes)", 72 | srcbuf .length - zs.avail_in , srcbuf .length, 73 | destlen - zs.avail_out, destlen); 74 | 75 | err = etc.c.zlib.inflateEnd(&zs); 76 | if (err != Z_OK) 77 | goto Lerr; 78 | 79 | if (zs.avail_out != 0) 80 | debug stderr.writefln("Too little data in zlib stream: expected %d, got %d", destlen, destlen - zs.avail_out); 81 | 82 | return destbuf[0..$-zs.avail_out]; 83 | } 84 | -------------------------------------------------------------------------------- /reflash/README.md: -------------------------------------------------------------------------------- 1 | # Reflash - ActionScript instrumentation 2 | 3 | `reflash` is the core instrumentation tool in the Reflash framework. It links against the extraordinary [RABCDAsm](http://github.com/CyberShadow/RABCDAsm) library directly, so it is itself also written in the D-language. 4 | 5 | For more technical overview, please refer to [Reflash research paper](../reflash_paper.pdf). 6 | 7 | 8 | ## Basic usage 9 | 10 | Typically, `reflash` is run transparently in the context of Reflash framework proxy. For manual usage, run `reflash` without any command line option to get the help text: 11 | 12 | ```bash 13 | $ reflash 14 | 15 | Usage: reflash 16 | 17 | Commands (one required): 18 | i|instrument Instrument file defined with --input 19 | d|disassemble Disassemble file defined with --input 20 | a|assemble Assemble from directory defined with --dir 21 | 22 | Arguments: 23 | --input Input flash file. 24 | --inject Inject a flash file. 25 | --output Output flash file (default=.reflash) 26 | --dir Working directory (default=random tmp dir) 27 | --config Load configuration from JSON file (overrides cmdline) 28 | --stream Produce a stream disassembly 29 | --id Session id for stream disassembler 30 | --debug Be verbose and leave temporary files for further inspection. 31 | --quiet Be very quiet. 32 | -h|--help This message. 33 | 34 | ``` 35 | 36 | ### Instrument 37 | 38 | This is the most common mode of operation. You need to provide at least: 39 | 40 | - Input file with __--input__ 41 | - Injected SWF with __--inject__ (typically __Instrument.swf__ generated with `recompile`) 42 | - Configuration file with __--config__ describing the instrumentation hooks etc. (see __Configuration__ below) 43 | 44 | Internally, __instrument__ executes __disassemble__ and __assemble__ modes after instrumentation and merging the injected SWF. 45 | 46 | ### Disassemble 47 | 48 | This mode is sometimes needed to work with problematic files, but of course it can used as a generic flash disassembler. 49 | 50 | - Input file with __--input__ 51 | - Output directory with __--dir__ 52 | 53 | `reflash` writes a bunch of files to the directory __--dir__. All the SWF blocks in __input__ are written in subdirectories `block-0` .. `block-N` (usually just block-0). In subdirectories, the disasseblies are stored according to their AS hierarchy with file extension _.asasm_, for example: 54 | 55 | ```bash 56 | block-0/block-0.main.asasm 57 | block-0/mx/core/ByteArrayAsset.class.asasm 58 | ``` 59 | Disassemblies are ASCII files, so you can easily for example _grep_ them through. 60 | 61 | ### Assemble 62 | 63 | This mode takes a directory structure prepared by __disassemble__ mode and assembles it back to a valid SWF. 64 | 65 | - Output file with __--output__ 66 | - Input directory with __--dir__ 67 | 68 | 69 | ## Configuration 70 | 71 | `reflash` can be configured from command line and using a JSON configuration file. JSON file _always_ overrides command line. 72 | 73 | Settings related to `reflash` in configuration file: 74 | 75 | "reflashConfig": 76 | 77 | - "input" - input file 78 | - "output" - output file 79 | - "work_dir" - temporary working directory (relative for 'i'-mode, absolute for 'd' and 'a') 80 | - "inject" - instrument to inject 81 | - "inject_pkg" - instrument package name 82 | - "stream" - store stream disassembly to file 83 | - "id" - session identifier in stream disassembly 84 | - "quiet" - be quiet 85 | - "dbg" - produce debug output, keep temp files etc. 86 | - "opcodeHooks" - array of opcode hooks 87 | 88 | Most of these are self-evident or explained above, or in the Reflash main README.md. 89 | 90 | ### Stream disassembly file 91 | 92 | In __instrument__ mode, __Stream disassembly__ writes __all__ disassemblies to a single file in very streamlined format and stores it to the working directory. The purpose of this is to help database tool when associating stack trace to disassemblies. 93 | 94 | ### Session identifier 95 | 96 | This is just a simple textual prefix used internally for separating different sessions (individual SWF files in proxy "live"-mode). Typically, no need to touch this. 97 | 98 | ### Opcode hooks 99 | 100 | This is an array of regexp strings describing opcodes to hook. A very reasonable default set of hooks is in `config.json`: 101 | 102 | ```bash 103 | "opcodeHooks":[ 104 | "call.*", 105 | "init.*", 106 | ".etproperty", 107 | "construct.*" 108 | ] 109 | ``` 110 | 111 | More hooks mean more stack trace. Extreme case of instrumentation is to have a single catch-all regexp __".*"__. That makes flash execution very slow and doesn't really provide too much useful information in addition to the default settings. 112 | 113 | In order to activate all the useful features in `Instrument.swf`, it is adviced to have at least __"call.*"__ and __"getproperty"__. 114 | 115 | 116 | This is the list of supported opcodes: 117 | 118 | ```bash 119 | constructprop 120 | callproperty 121 | callproplex 122 | callsuper 123 | callsupervoid 124 | callpropvoid 125 | call 126 | callstatic 127 | callmethod 128 | construct 129 | constructsuper 130 | setlocal0 131 | setlocal1 132 | setlocal2 133 | setlocal3 134 | pop 135 | dup 136 | increment 137 | increment_i 138 | decrement 139 | decrement_i 140 | bitnot 141 | not 142 | negate 143 | negate_i 144 | setlocal 145 | add 146 | add_i 147 | swap 148 | bitand 149 | bitor 150 | bitxor 151 | modulo 152 | lshift 153 | rshift 154 | urshift 155 | multiply 156 | multiply_i 157 | subtract 158 | subtract_i 159 | divide 160 | initproperty 161 | setproperty 162 | getproperty 163 | 164 | ``` 165 | -------------------------------------------------------------------------------- /reflash/build_reflash.d: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010, 2011, 2012, 2013, 2016 Vladimir Panteleev 3 | * Copyright 2016, 2017 Jarkko Turkulainen 4 | * This file is part of reflash. 5 | * 6 | * reflash is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * reflash is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with reflash. If not, see . 18 | */ 19 | 20 | /// A simple tool to build reflash in one command. 21 | /// You can use the DC and DCFLAGS environment variables to override the detected compiler and compilation flags. 22 | /// You can also pass program names or compilation options on the command-line to override the default ones. 23 | 24 | module build_reflash; 25 | 26 | version(D_Version2) 27 | { /* All OK */ } 28 | else 29 | static assert(false, "Unsupported D version.\nThis software requires a D2 ( http://dlang.org/ ) compiler to build."); 30 | 31 | version(D_Version2): 32 | 33 | version(DigitalMars) 34 | const DEFAULT_COMPILER = "dmd"; 35 | else 36 | const DEFAULT_COMPILER = "gdmd"; 37 | 38 | const DEFAULT_FLAGS = "-inline -IRABCDasm"; 39 | const LZMA_FLAGS = ["-version=HAVE_LZMA"]; 40 | 41 | import std.exception; 42 | import std.file; 43 | import std.process; 44 | import std.stdio; 45 | import std.string; 46 | 47 | string compiler; 48 | string[] flags; 49 | 50 | void compile(string program) 51 | { 52 | stderr.writeln("* Building ", program); 53 | enforce(spawnProcess(["rdmd", "--build-only", "--compiler=" ~ compiler] ~ flags ~ program).wait() == 0, "Compilation of " ~ program ~ " failed"); 54 | } 55 | 56 | void test(string code, in string[] extraFlags=null) 57 | { 58 | const BASE = "build_rabcdasm_buildtest"; 59 | const FN = BASE ~ ".d"; 60 | std.file.write(FN, code); 61 | scope(exit) foreach (de; dirEntries(".", BASE ~ "*", SpanMode.shallow)) remove(de.name); 62 | enforce(spawnProcess(["rdmd", "--force", "--compiler=" ~ compiler, "-od."] ~ flags ~ extraFlags ~ FN).wait() == 0, "Test failed"); 63 | stderr.writeln(" >>> OK"); 64 | } 65 | 66 | void testBug(string description, int bugId, string code) 67 | { 68 | stderr.writefln("* Checking for compiler bug %d...", bugId); 69 | scope(failure) 70 | { 71 | stderr.writefln("Compiler bug detected: %s ( https://issues.dlang.org/show_bug.cgi?id=%d ).", description, bugId); 72 | stderr.writeln("Try again with a different D compiler, compiler version, or build flags (DCFLAGS environment variable)"); 73 | } 74 | test(code); 75 | } 76 | 77 | int main(string[] args) 78 | { 79 | try 80 | { 81 | auto programs = ["reflash"]; 82 | 83 | compiler = environment.get("DC", DEFAULT_COMPILER); 84 | flags = environment.get("DCFLAGS", DEFAULT_FLAGS).split(" "); 85 | 86 | string[] optionArgs, programArgs; 87 | foreach (arg; args[1..$]) 88 | (arg.startsWith("-") ? optionArgs : programArgs) ~= arg; 89 | 90 | if (optionArgs.length) 91 | flags = optionArgs; 92 | if (programArgs.length) 93 | programs = programArgs; 94 | 95 | stderr.writeln("* Checking for working compiler..."); 96 | test(` 97 | void main() {} 98 | `); 99 | 100 | testBug("[REG 2.064] Wrong code with -O on x86_64 for char comparisons", 11508, ` 101 | import assembler; int main() { foreach (c; "_") if (!Assembler.isWordChar(c)) return 1; return 0; } 102 | `); 103 | testBug("[REG 2.069] Wrong double-to-string conversion with -O", 15861, ` 104 | import std.format; int main() { return format("%.18g", 4286853117.0) == "4286853117" ? 0 : 1; } 105 | `); 106 | 107 | bool haveLZMA; 108 | 109 | stderr.writeln("* Checking for LZMA..."); 110 | try 111 | { 112 | test(` 113 | import lzma, std.exception; 114 | void main() 115 | { 116 | LZMAHeader header; 117 | auto data = cast(immutable(ubyte)[])"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; 118 | auto cdata = lzmaCompress(data, &header); 119 | header.decompressedSize = data.length; 120 | auto ddata = lzmaDecompress(header, cdata); 121 | enforce(data == ddata); 122 | } 123 | `, LZMA_FLAGS); 124 | 125 | // Test succeeded 126 | haveLZMA = true; 127 | } 128 | catch (Exception e) 129 | stderr.writeln(" >>> LZMA not found, building without LZMA support."); 130 | 131 | if (haveLZMA) 132 | flags ~= LZMA_FLAGS; 133 | 134 | foreach (program; programs) 135 | compile(program); 136 | 137 | return 0; 138 | } 139 | catch (Exception e) 140 | { 141 | stderr.writeln("Error: ", e.msg); 142 | return 1; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /reflash/liblzma.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/reflash/liblzma.lib -------------------------------------------------------------------------------- /reflash_paper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WithSecureOpenSource/reflash/56380dd1dc62cc3ff61ad4301a1308940ca08dde/reflash_paper.pdf --------------------------------------------------------------------------------