├── 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 |
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
--------------------------------------------------------------------------------