Professional Documents
Culture Documents
QuickBMS
by Luigi Auriemma
e-mail: me@aluigi.org
web:
aluigi.org
home: http://quickbms.aluigi.org
help: http://zenhax.com
#######################################################################
1)
2)
3)
4)
5)
6)
7)
8)
Introduction
Usage
Reimporting the extracted files
How to create scripts (for developers only!)
Experimental input, output and other features
Notes
Support
Additional credits
#######################################################################
===============
1) Introduction
===============
QuickBMS is a multiplatform extractor engine that can be programmed
through some simple textual scripts, it's intended for extracting files
and information from the archives of any program and moreover games.
The script language from which QuickBMS is derived is MexScript
documented here: http://wiki.xentax.com/index.php/BMS
So QuickBMS is FULLY compatible with that original syntax and all the
scripts that were created here:
http://forum.xentax.com/viewtopic.php?t=1086
QuickBMS supports also the WCX plugins of Total Commander:
http://www.totalcmd.net/directory/packer.html
http://www.ghisler.com/plugins.htm
I improved the original BMS language for:
- removing some implied fields, like the file number in some commands
- adding new commands, like Encryption
- adding new behaviors and features, like negative GoTo
These improvements allow QuickBMS to work with tons of simple and
complex formats and even doing things like modifying files, creating
new files with headers, converting files and reimporting files back in
their original archives.
The tool is open source under the GPL license and works on both Windows
and Linux and on both little and big endian architectures like Intel
and PPC.
Basically it means that you can distribute the original quickbms.exe
file as you desire but reusing its source code or modifying it may
require you to adopt the same open source license.
-F W
-o
-k
-r
s
-u
-i
-z
the ISO image will be the name of the input file or folder
exactly as above but generate a ZIP file
Advanced options:
-d
automatically create an additional output folder with the name of the
input folder and file processed, eg. models/mychar/mychar.arc/FILES,
-d works also if input and output folders are the same (rename folder
)
-D
-E
similar to -d but will not create the folder with the filename
experimental option for automatically reversing the endianess of any
file simply reading it field by field (so each get will produce a put
)
-c
quick list of the basic BMS commands and some notes about this tool
-S CMD execute the command CMD on each file extracted, you must specify the
Debug
-v
-V
-q
-Q
-L F
-x
-0
-R
-a S
ce
-H
-X
-9
-8
-7
-6
-3
-I
-M F
Remember that the script and the input archive/folder are ever REQUIRED
and they must be specified at the end of the command-line.
The following is an example for listing all the mp3 files from the input
archive:
quickbms
quickbms
quickbms
quickbms
-l
-l
-l
-l
-f
-f
-f
-f
For example if you have a "get SIZE long" a 32bit number will be
read as usual and additionally it will be reversed (0x11223344 to
0x44332211 or viceversa) and placed at the same location.
Remember that you need to specify also the -w option with physical
files, alternatively you can save the whole file in a memory file
and then dumping it so that -w is not necessary.
With this option is really trivial to convert the endianess of files
between different platforms, like Xbox 360 and PC.
#######################################################################
==================================
3) Reimporting the extracted files
==================================
QuickBMS is mainly an extraction tool, but it supports also the -r
option that converts the tool in a simple reimporter/reinjector and so
it may be useful for modding or translating a game.
The idea consists of being able to reimport ("injecting back") the
modified files in the original archives without touching a single line
of the script, just reusing the same bms scripts that already exist!
----------------------------------------------------------------------Using this feature is really trivial and the following is a
step-by-step example:
- Make a backup copy of the original archive!
- Extract the files or only those you want to modify (-f option) as you
do normally via the GUI (double-click on quickbms.exe) OR via
command-line like the following example:
quickbms script.bms archive.pak output_folder
- Modify the extracted files leaving their size unchanged or smaller
than before.
I suggest to delete the files that have not been modified so that the
reimporting process will be faster and safer. In the folder leave
only the files you modified.
Remember that their size must be smaller or equal than the original!
- Reimport the files in the archive via the GUI by clicking on the
file called "reimport.bat" OR via command-line:
quickbms -w -r script.bms archive.pak output_folder
- Test the game with the modified archive
Remember that you can use the GUI for the reimporting procedure, just
click on "reimport.bat" found in the quickbms package, it contains the
command: quickbms.exe -G -w -r.
----------------------------------------------------------------------Another example:
- First step, use QuickBMS as usual:
archive.pak -> file1.txt
-> file2.dat
-> file3.jpg
- Second step:
- delete file1.txt and file2.dat
- modify file3.jpg, for example adding a "smile" in it
- save file3.jpg and be sure that it's size is SMALLER or EQUAL than
the original
- Third step, use the reimport.bat file provided in quickbms and select
the SAME file and output folder you selected in the first step:
archive.pak <- file1.txt (doesn't exist so it's not reimported)
<- file2.dat (doesn't exist so it's not reimported)
<- file3.jpg (successfully reimported)
----------------------------------------------------------------------Some important notes about this particular reimporting process:
- you CANNOT increase the size of the files you want to reimport, so
the new files must be smaller or equal than the original ones.
- the reimport process of compressed files may be slower in some cases,
for example with zlib, deflate, lzma and few others that are optimized
to use less space as possible at cost of CPU and time.
- for the maximum compatibility within the thousands of available file
formats I decided to not use tricks for modifying the original
size and compressed_size values.
for example imagine those formats that use encrypted information
tables or MEMORY_FILEs for such tables or that use things like
"math SIZE *= 0x800".
the reimport process must be generic and without work-arounds.
- the script is just the same for both extraction and reimporting, it
means that many of the scripts written by me and the other users
already work, cool!
- the reimporting of compressed files is perfectly possible because
the tool automatically switches to the relative compression algorithm
if available (for example deflate -> deflate_compress), if an
algorithm is not available in recompress mode then the reimporting
will fail
? if the original archive uses complex encryptions that require the
usage of MEMORY_FILEs to perform temporary decryption, then it's NOT
supported and the same is valid for chunked content (like those
scripts that use the command Append)
From version 0.6.6, QuickBMS has an experimental mode for reimporting
chunked files, it works very well with files saved directly to disk
and less well with those that use MEMORY_FILEs (most of my scripts).
In my opinion this feature is great but don't expect too much, with
some scripts you can have success but many others may not work.
- FileXor, FileRot, Encryption and Filecrypt should work correctly
- things like CRCs and hashes can't be supported
- it's possible to reimport also the nameless files (log "" OFFSET SIZE)
the tool will automatically check for files in the folder with the
same number so if the file was saved as 00000014.xml it will be
reimported perfectly.
- the reimport mode doesn't work if you renamed the files with the same
name during the extraction (for example using the 'r' choice), in
this case there is no way for the tool to know the correct file to
reimport and will reimport only the one with the same original name.
Please note that often the games are able to load the extracted files
directly from their installation folder, sometimes directly maybe by
just removing the original archive and other times by launching the
game with specific command-line arguments.
The reimport feature of QuickBMS has already allowed to slightly mod
and translate various games, but it's meant as a quick or temporary
solution till a proper stand-alone rebuilder tool is written by the
community of the target game, due to the better benefits coming from a
complete and specific solution.
But if nobody is going to write a stand-alone rebuilder for a specific
game, then the reimport feature of QuickBMS is a great and immediately
available solution.
#######################################################################
===============================================
4) How to create scripts (for developers only!)
===============================================
Originally the tool was created just for myself to be able to write
quick extractors for simple archives immediately without writing a new
tool, but QuickBMS revealed to be a powerful tool that I use for many
tasks, including the parsing of some protocols and much more.
So, how to write these scripts?
Well I guess that giving a look at http://wiki.xentax.com/index.php/BMS
is a good first step to understand at least the basis of this language
originally written by Mike Zuurman (alias Mr.Mouse of XeNTaX) in the
far 1997.
Then it's good to take a look at the various examples provided on
http://quickbms.aluigi.org and http://zenhax.com
A programming knowledge and background is not required but it's very
useful for understanding the "logic" of the scripts and some terms.
What is really necessary is the full knowledge of the format to
implement: reverse engineering is ever useful for figuring the needed
fields.
Luckily in the extraction process it's not needed to know all the
filename
offset
size
optional compressed size if the file is compressed
If you don't have filename and size, it's not a problem. What's really
necessary is knowing at least of the offsets of the files.
If you check my scripts you can notice the name DUMMY assigned to the
fields that are not useful for the extraction.
Note that I will try to keep the following documentation updated as
much as I can, and also in sync with what happens inside QuickBMS for
each command.
The source code of the tool is not easy to understand so I hope that
this documentation may be useful and complete.
The fields between [] are optional fields.
--A quick and limited list of available commands is available when
QuickBMS is launched with the -c option.
The following are some important notes about the QuickBMS environment:
- Everything is considered a variable except if it starts with a number
in which case it's considered a numeric constant, so when in this
document I talk about VAR, STRING and other types of data I refer
EVER to both variables and constants because they are EXACTLY the
SAME thing inside the tool.
- All the commands and the names of the variables are case INsensitive
so "get OFFSET long" is the same as "GeT oFfSeT lOnG".
- Everything works with signed 32 bit numbers (-2147483648 to
2147483647) so QuickBMS may not work well with files over 2 gigabytes
but it can seek on files of 4 gigabytes without problems.
Consider the following limits:
- max 4gb size for archives
- max 2gb size for the archived files
You can try quickbms_4gb_files.exe for working with bigger archives.
- The constant strings depends by the context of the command, in fact
in some commands they are handled as strings in C notation like
"\x12\x34\\hello\"bye\0", in this case you must know how this
representation works.
This is a solution for using binary data inside the textual script.
The keyword is "C language escape characters" or escape sequences,
they are very simple, take a look here:
http://msdn.microsoft.com/en-us/library/h21280bw%28VS.80%29.aspx
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1.1.html
ONLY some commands support this C string notation for the escape
characters, a quick way to find them is searching the keyword
"(cstring)" without quotes in this document.
- Both decimal and hexadecimal numbers are supported, hexadecimal is
adopted if the number starts with 0x so 1234 and 0x4d2 are the same.
8 bit, 0 to 0xff
SHORT
THREEBYTE
24 bit, 0 to 0xffffff
LONG
32 bit, 0 to 0xffffffff
LONGLONG
STRING
ASIZE
FILENAME
BASENAME
FILEPATH
FULLBASENAME
EXTENSION
UNICODE
LINE
FULLNAME
OUTPUT_FOLDER
INPUT_FOLDER
same as above
COMPRESSED
pe)
FLOAT
DOUBLE
LONGDOUBLE
VARIABLE
VARIABLE2
VARIANT
BITS
TIME
TIME64
CLSID
IPV4
7f 00 00 01 = "127.0.0.1"
IPV6
like 2001:0db8:85a3:0000:0000:8a2e:0370:7334
ASM
x86 assembly
VARIABLE3
SIGNED_BYTE
SIGNED_SHORT
SIGNED_THREEBYTE
SIGNED_LONG
VARIABLE4
VARIABLE5
used in 7z archives
UNKNOWN
Just for the record, the original MexScript probably contained some
types of variables that have never been used and for which it's unknown
what they should represent: PURETEXT, PURENUMBER, TEXTORNUMBER and
FILENUMBER.
QuickBMS supports also the "experimental" multidimensional arrays
inside the variables, for example:
for i = 0 < 10
get VAR[i] long
for j = 0 < 5
get VAR2[i][j] long
next j
next i
But it's possible to access that variable ONLY by specifying the
original name and index, so:
print "%VAR[0]%"
# fail!
math i = 0
print "%VAR[i]%"
# ok
.......................................................................
QuickBMSver VERSION
Checks if the current version of QuickBMS is enough recent to
support the script. It's used rarely, mainly for scripts created
after the introduction of a new feature or an important fix.
Arguments:
VERSION Oldest version of QuickBMS for which was created the script,
it's just the version displayed at runtime by the tool.
It's also possible to add some options that are suggested
by the script to the user for enabling them at runtime,
currently are supported:
-9 disable the safe memory allocator
-I makes the variables case sensitive
-64 checks if the user is running quickbms_4gb_files.exe
Examples:
QuickBMSver 0.2.4
QuickBMSver "0.5.14 -9"
QuickBMSver "-I -9"
.......................................................................
FindLoc VAR TYPE STRING [FILENUM] [ERR_VALUE]
It finds the first occurrence of a given string or number from the
current offset of the archive, just by scanning it byte per byte.
It's used in those cases when the format of the archive is not known
or it's a particular text file.
Arguments:
VAR
The variable which will receive the offset of the occurrence
TYPE
Type of the data we want to search, currently supported:
- string and binary, they are handled as the same
- unicode, the search will be performed as utf16 with the
data stored using the current endianess
- numeric type (byte, short, long ...), you will search a
number stored using the current global endianess
STRING
This value must be a number if TYPE is a numeric type,
otherwise it must be a string in C notation (cstring)
FILENUM Number of the file associated to the archive (0)
ERR_VALUE By default FindLoc terminates the script if no string
is found but if ERR_VALUE is specified this value will
be assigned to this value without terminating when there are
no other occurrences, the best usage is ERR_VALUE set to ""
Examples:
For
FindLoc OFFSET string "filename="
...
FindLoc OFFSET string "filename=" 0 ""
if OFFSET == ""
cleanexit
endif
Next
.......................................................................
For [VAR] [OP] [VALUE] [COND] [VAR]
...
Next [VAR] [OP] [VALUE]
A classical "for" loop with initializers, conditions and
incrementers.
There is also the Break instruction available to break the loop at
any moment but note that it's not suggested in presence of multiple
For because in some rare cases it may not work correctly.
"For" allows to perform an initial operation on a variable and to
perform a check in each cycle to ensure a particular condition.
"Next" is the command which delimits the loop and at the same time
increments the given variable if specified.
It's also possible to use a math operation in Next so that you can
increment, decrement or perform any other operation at the end of
each cycle.
All the parameters are optionals and must be inserted in the
specific order, so if there is no initialization you must use
something like the following:
For OFFSET = OFFSET < 1000
For the record, there is also a "Prev" variant of the Next command,
it performs the decrement of the variable.
Arguments:
VAR
Variable on which is performed the first math operation
and is checked for the condition
OP
Any of the available Math operators (check Math)
VALUE
Value to assign to the variable or part of the math operation
COND
Condition (check the If command)
VAR
Second part of the condition
Examples:
For i = 0 < FILES
...
next i
For
# do what you want here, this is an endless loop
Next
For VAR1 = VAR1 != VAR2
# this is exactly the same of using while(VAR1 != VAR2) {...} in C
Next VAR2 /= 3
For OFFSET = OFFSET != ARCHIVE_SIZE
...
Savepos OFFSET
if OFFSET > 100
break
endif
Next
.......................................................................
Get VAR TYPE [FILENUM]
It reads strings and numbers from the file, it's also the most used
command.
It supports many types of input and are the same already seen at the
beginning of this section of the documentation like byte, short, long,
data
in which you can
each element like
archive (0)
Examples:
GetDString NAME NAME_LENGTH
GetDString NAME 0x100
getdstring ARRAY ELEMENTS*4
.......................................................................
GoTo OFFSET [FILENUM] [TYPE]
It changes the current position in the file, just like fseek in C.
Arguments:
OFFSET
Position to reach.
The offset "SEEK_SET" is offset 0.
The offset "SEEK_END" is the end of file.
If it's a constant negative it will be considered
the amount of bytes from the end of the file, so
a negative variable is just considered as unsigned
32bit.
The offset depends also by the TYPE field.
FILENUM number of the file associated to the archive (0)
TYPE
- SEEK_SET, the absolute offset (default)
- SEEK_CUR, the relative offset from the current position
- SEEK_END, the amount of bytes from the end, must be
negative or OFFSET will be converted to negative
Examples:
GoTo
GoTo
GoTo
GoTo
Goto
OFFSET
0x100
-4
SEEK_SET
SEEK_END
.......................................................................
IDString [FILENUM] STRING
It terminates the program if the magic/signature at the current
position of the file differs than the provided string.
If the string doesn't match and it's 4 bytes long QuickBMS will
automatically swap it and perform the comparison again, if this time
it matches then the endianess will be changed making most of the
scripts written for an architecture (for example PC) virtually
compatible with others (for example Xbox360).
Pay attention to the FILENUM/VAR order different than other commands
(it's a fault of the original BMS syntax), anyway QuickBMS will try
to fix the order in case you invert them.
Arguments
FILENUM
STRING
Examples:
IDString
IDString
IDString
IDString
.......................................................................
Log NAME OFFSET SIZE [FILENUM] [XSIZE]
It extracts the file, this operation doesn't affect the current
position of the input file.
The content of the extracted file can be decrypted automatically
using the Encryption command.
If NAME is set to an empty string like "", QuickBMS will assign a
sequential hexadecimal value and will try to guess the extension
based on the content of the file.
The extension will be automatically guesses and appended also to
all the files that terminate with a dot or an asterisk like ".",
"*" or ".*" or if they point to folders like "folder/".
NAME can be also a special file like those that will be seen later,
for example a socket, a process, an audio device and so on (in
this case the user must have authorized the usage of the special
files via command-line for using them).
The filename will be automatically cleaned for dumping the file
without problems.
NAME can be also a MEMORY_FILE or a TEMPORARY_FILE.
If a file with the same name already exists, QuickBMS will ask
what action to take, the suggested one is the 'r' choice that
will allow to automatically rename all the files with the same
name without overwriting them.
If you have used the Append command, the data will be appended to
the existent file with the same name.
Log and Clog share the same code, so the compression is the only
difference.
Arguments:
NAME
OFFSET
SIZE
FILENUM
XSIZE
Examples:
Log NAME OFFSET SIZE
Log "dump.dat" 0 SIZE
Log "" 0 SIZE
Log "folder/name.*" 0 SIZE
.......................................................................
Clog NAME OFFSET ZSIZE SIZE [FILENUM] [XSIZE]
It extracts the file by decompressing it in real-time, this
operation doesn't affect the current position of the input file.
The decompression algorithm used in the operation is decided by the
ComType command (zlib by default).
The content of the extracted file can be decrypted automatically
using the Encryption command.
For additional information please refer to the Log command.
Arguments:
NAME
OFFSET
ZSIZE
SIZE
FILENUM
XSIZE
Examples:
Clog NAME OFFSET ZSIZE SIZE
Clog "dump.dat" 0 ZSIZE 10000000 # with some compression algorithms
# the file will have the real size
# while others will set it to 10000000
.......................................................................
Math VAR OP VAR
Mathematical operation between the two variables with the result
placed in the first one.
Note that due to compatibility all the operations are performed using
signed 32 bit numbers by default.
This makes the difference with some operation like the shift or the
divisions, so pay attention!
VAR
Examples:
Math SIZE * 0x100
Math OFFSET << 2
Math OFFSET u<< 2
Math TMP = SIZE
Math TMP ~ TMP
Math TMP n TMP
Math TMP2 a TMP
Math SIZE u/ 5
Math RADIX v 2
.......................................................................
XMath VAR INSTR
Multiple mathematical operations in one line, just a way to avoid
the limitations of the original Math command.
Currently this command is just an experiment and supports only the
most simple operators named with a non-alphanumeric character and
applied to unsigned numbers:
~ ! < > & ^ | * / % - +
<<< shift left
>>> shift right
** power
// root
&& alignment
<> common bit swapping
%% percentage ("VAR %% 15" will return the 15% of VAR)
This command is directly derived from my calcc tool:
http://aluigi.org/mytoolz.htm#calcc
Please note that XMath is a lot slower than Math.
Do NOT use the unsigned labels or the additional '=' you use with the
Math command because they are NOT supported since all operations
are unsigned in XMath, so:
xmath TMP "TMP u<<= 5"
is WRONG
xmath TMP "TMP << 5"
is CORRECT
Arguments
VAR
INSTR
Examples:
XMath VAR "1 + 2 - ((3 + 4) + VAR * VAR2)"
.......................................................................
Open FOLDER NAME [FILENUM] [EXISTS]
It opens a file, basically it
file that you want to use.
If NAME is '?':
- and FOLDER is FDDE the user
the name is the same of the
- and FOLDER is FDSE the user
the same folder
- the user must type the full
Arguments:
FOLDER
FDDE, means that you want to open the file in the same
location of the input one which has the extension
provided with NAME, so FDDE is for the extension only
FDSE, it will consider NAME as a file located in the
same folder of the input file (very useful)
any other value is considered the folder where is located
the file to load so use "." for the current output
folder
NAME
Read above, NAME can be also a ? in which case QuickBMS
will ask the user to insert the name of the file to open
manually
if NAME is "" then will be performed a flush operation
that could be useful (or not?) only in write mode (debug)
FILENUM Number of the file associated to the archive (0)
EXISTS
If the file doesn't exist this variable will be set to
0 or 1 if it exists. by default QuickBMS terminates
with an error if the file doesn't exist.
Examples:
Open FDDE DAT 0
Open FDDE IDX 1
Open FDSE "myfile.zip"
Open "." TEMPORARY_FILE 1
.......................................................................
SavePos VAR [FILENUM]
Current position of the file, like ftell in C.
Arguments:
VAR
Variable which will contain the offset
FILENUM Number of the file associated to the archive (0)
Examples:
SavePos OFFSET
.......................................................................
Set VAR [TYPE] VAR
Command for assigning a constant or a variable to another variable
with the possibility of changing its type, utf8 to unicode and vice
versa.
Arguments:
VAR
Output variable or memory file
TYPE
In general the type is not much important because in
QuickBMS there is almost no difference between numbers
and strings, anyway the following are the special types:
- unicode, unicode to utf8, endian dependent
set NAME unicode NAME
- to_unicode, utf8 to unicode, endian dependent
set NAME to_unicode NAME
- binary, C notation (cstring)
set MEMORY_FILE binary "\x11\x22\x00hello"
VAR
set VAR ? ?
- strlen: just a wrapper for the Strlen command
set NAMESZ strlen NAME
Variable or constant to assign
Examples:
Set i long 0
Set TMP long SIZE
Set TMPNAME NAME
Set MEMORY_FILE binary "\x12\x34\x56\x78"
Set ASCII_VAR unicode UNICODE_VAR # from unicode to string
Set VAR ? ? # the user will be prompted to insert his content
.......................................................................
Do
...
While VAR COND VAR
A not so useful type of cycle where the check of the condition is
performed at the end of the cycle... really rarely used.
If you need a C-like "while(...) {...}" use the For command.
Arguments:
VAR
first part of the condition
COND
condition, check the If command below for additional info
VAR
second part of the condition
Examples:
Do
...
While OFFSET < MAX_OFFSET
.......................................................................
String VAR OP VAR
The equivalent of the Math command for the strings.
The first variable can be an input and output or only an output
depending by the operator.
You can use also a textual OP, this value is the one in the first
line of the operator you see below (for example "equal" is '=').
The string searching operators are quite confusing because the tool
didn't have this feature and they were implemented in the String
command later as experimental features.
Arguments:
VAR
Input and output variable
OP
= equal, copy
just a copy, but if var2 is a number it will be
+
-
^
<
&
|
$
!
>
second variable
var1="hello", var2=5, result:"hellohellohellohellohello"
if it's a string it acts as strchr/strstr returning the part
before it plus the searched string:
var1="thisisastring", var2="is", result="this"
mod
if the second variable is a positive number
cut the variable at the position obtained by the modulus
of its length and the number in the second variable
while if it'a string it acts like strchr/strstr returning
the data before the result
var1="thisisastring", var2="is", result="th"
strchr, strstr
first occurrence
var1="thisisastring", var2="isa", result="isastring"
strchrx, strstrx
first occurrence + var2 length
var1="thisisastring", var2="isa", result="string"
strrchr, strrstr
last occurrence plus searched string
var1="thisisastring", var2="isa", result="isastring"
strrchrx, strrstrx
last occurrence + var2 length
var1="thisisastring", var2="isa", result="string"
shr, shift_right
if the second variable is a number:
var1="thisisastring", var2="4", result="thisisast"
otherwise the string is searched from the END of the variabl
b
B
n)
h
e
E
c
C
u
l
R
hex2byte
hex2byte of var2: var2="616263", result="abc"
encrypt, encryption
experimental encryption based on the Encryption command
encrypt_string
as above but uses var2 as a null delimited string (strlen)
compress, compression, comtype
experimental compression based on the ComType command
compress_string
as above but uses var2 as a null delimited string (strlen)
toupper
var2="hello", result="HELLO"
tolower
var2="HELLO", result="hello"
replace
replace chars: var1="helloworld", var2="world", var3="me", r
esult="hellome"
p
P
s
printf, sprintf
a printf-like experimental work-around
the format for float (f) and double (g) works only
for one element, so:
get VAR_LONG long
String TMP p "%10.10f" VAR_LONG # no VAR2 or VAR3
print "%TMP%"
QuickBMS Print
same output of the Print command, for example:
string VAR P "hello %VAR1% test %VAR2|x%"
sscanf
a sscanf-like experimental work-around, only for numeric 32b
it values
S
VAR3
x
f
m
cstring
convert a C string (cstring) to the relative string/binary
string VAR x \x78\x7a
filter
filter the non alphanumeric chars by replacing them with '_'
math, xmath
math and xmath operation just like those in the Encryption c
ommand
so #INPUT#+1 means that 0x01 will be added to each char of V
AR
quick example: string VAR m "#INPUT#+1"
# xmath if there
is INPUT
string VAR m "+ 1"
# math
hex2uri
var2="%2fhello", result="/hello"
W uri2hex
var2="hello<>", result="hello%3c%3e"
Use an additional zero ("0") to return "" in case of errors like
w
when
the operators that search strings can't find the pattern (in whi
ch case
will be returned the original string by default), this is very u
seful
while playing with strings, for example
"string VAR1 0strchr VAR2" will return "" if VAR2 is not found i
n VAR1
(instead of leaving VAR1 unchanged), another example: String VAR
1 0$ VAR2
VAR
Examples:
string FULLPATH + NAME
string FULLPATH + \
string NAME - ".zip"
string NAME - 4
string PATH R "." "/"
string FULLPATH p "c:\folder\%04x%04x.dat" VAR1 VAR2
input
string FULLPATH s "c:\folder\%04x%04x.dat" VAR1 VAR2
output
.......................................................................
CleanExit
Terminates the script, it's possible also to use just Exit.
.......................................................................
If VAR COND VAR [...]
...
[Elif VAR COND VAR]
...
[Else]
...
EndIf
It checks various conditions and performs the needed operation when
the condition is verified, in short:
- If is ever the first condition
- Elif is another condition and can be used endless times
- Else is the operation to do when no conditions are met, the last one
- EndIf delimits the If command statement
It's also possible to use multiple conditions (max 3 or 4) like:
if VAR1 < VAR2 && VAR3 > VAR4
elif VAR1 != 0 || VAR2 != 0
The 'u' added before the condition forces an unsigned comparison
with numbers and a case sensitive comparison with strings.
The condition is considered for both strings and numbers, for more
technical details it's necessary to check the check_condition()
function in the cmd.c source code.
Arguments:
VAR
First part of the condition
COND
Valid for both strings and numbers:
< minor, lower, below
>
!=
==
>=
<=
&
VAR
Examples:
If NAME != ""
...
Endif
If MASK & 1
Elif MASK & 2
Elif MASK & 4
Elif MASK & 8
Else
Endif
.......................................................................
GetCT VAR TYPE CHAR [FILENUM]
It reads a string till the reaching of the CHAR delimiter.
arguments
VAR
TYPE
CHAR
Output variable
Only unicode is the alternative type, any other value
is just ignored because doesn't matter for this
operation
The delimiter character as 8bit number, if this number
is negative QuickBMS will convert it to positive and
read till the current byte is the same (so it's like
a way to skip the same byte in a file)
FILENUM
Examples:
GetCT NAME string 0x0a
GetCT NAME string 0x3b
set DELIMITER_BYTE long 0x0a
GetCT NAME string DELIMITER_BYTE
GetCT NAME unicode 0x0a
.......................................................................
ComType ALGO [DICT] [DICT_SIZE]
It selects a specific compression algorithm to use with the Clog
command.
It's also possible to choose a number as ALGO, this is a feature
coming from my project for a compression scanner able to guess
the possible algorithm of an unknown compressed data block:
http://aluigi.org/bms/comtype_scan2.bat
http://aluigi.org/bms/comtype_scan2.bms
comtype_scan2.bat comtype_scan2.bms input_file output_folder
comtype_scan2.bat comtype_scan2.bms input_file output_folder uncompressed_
size
Note that some algorithms may work only on Windows.
if ALGO is "?", the user is prompted to type the desired algorithm.
Arguments:
ALGO
copy, simple copy that useful in some rare cases with
data encrypted with block ciphers like AES and blowfish
so use comtype copy and encryption
zlib, RFC1950 (aka windowbit 15, the data starts with a 'x')
DICT supported
if DICT starts with "Z_FULL_FLUSH" inflate/deflate will use Z_
FULL_FLUSH
deflate, RFC1951 (aka windowbit -15) used for example in the ZIP
files
DICT supported
if DICT starts with "Z_FULL_FLUSH" inflate/deflate will use Z_
FULL_FLUSH
lzo1a till lzo2a, LZO (remember that the most used is lzo1x)
DICT supported
lzss, with default configuration (dictionary of 4096 bytes)
this particular algorithm can be fully configured setting the
EI, EJ and P fields plus another number rarely used:
EI, EJ, P, rless, init_chr
for setting them it's enough to use a DICT equal to something
like "12 4 2" which means EI:12 (N:4096), EJ:4 (F:18), P:2
use a negative init_chr for different window slide customizati
ons
like -1 for Tales of Vesperia
the default character of lzss is a space (0x20), but you can u
se the
ALGO lzss0 or the dictionary "12 4 2 2 0" to use 0x00
lzx, used by the old (aka jurassic) unlzx tool and on Amiga
gzip, automatic handling of the gzip data
remember that in this case the uncompressed size is
ignored and calculated automatically so in CLog use
ZSIZE ZSIZE
pkware, the algorithm also known as blast/explode/implode/DCL
lzma, 5 bytes + lzma (in some cases you may need to use ZSIZE +
5)
lzma86head, 5 bytes + 8 bytes (size) + lzma
lzma86dec, 1 byte + 5 bytes + lzma (in some cases you may need t
o use ZSIZE + 5)
lzma86dechead, 1 byte + 5 bytes + 8 bytes (size) + lzma
lzmaefs, the format implemented in ZIP
bzip2
XMemDecompress, (aka xmemlzx) Xbox 360 LZX algorithm of xcompres
s.lib
use DICT to specify a custom WindowSize and CompressionPartiti
onSize
like "131072 524288"
the algorithm automatically idenfities and extracts the LZXTDE
CODE
and LZXNATIVE files generated by xbcompress.exe (0x0FF512ED /
0x0FF512EE)
hex, from "01234567" to 4 bytes: 0x01 0x23 0x45 0x67
base64, from "aGVsbG8=" to "hello", supports also the Gamespy
and URL chars
uudecode
ascii85
yenc
COM_LZW_Decompress, used in Vietcong
milestone_lzw, the lzw algorithm used in the Milestone games
lzxcab, lzx algorithm used to handle the cab files (libmspack 21
0)
lzxchm, lzx algorithm used to handle the chm files (libmspack 16
2)
rlew, 16 bit RLE algorithm used in AIM Racing
lzjb, a compression used in a file system for *nix
sfl_block, expand_block from iMatix Standard Function Library
sfl_rle, expand_rle from iMatix Standard Function Library
sfl_nulls, expand_nulls from iMatix Standard Function Library
sfl_bits, expand_bits from iMatix Standard Function Library
lzma2, 1 bytes + lzma2
lzma2_86head, 1 bytes + 8 bytes (size) + lzma2
lzma2_86dec, 1 byte + 1 bytes + lzma2
lzma2_86dechead, 1 byte + 1 bytes + 8 bytes (size) + lzma2
nrv2b, UCL
nrv2d, UCL
nrv2e, UCL
huffboh, an unrecognized compression used in the Asura engine
uncompress, the lzw algorithm used in the compress utility
(the lzw data starts from offset 3 of the .Z files)
dmc, Dynamic Markov Compression (DMC)
lzhuf, aka LZH/LHA
lzari
rle7
rle0
rle
rlea, another generic rle decompressor
use DICT to choose the escape char
bpe, byte pair encoding
quicklz
q3huff, Adaptive Huffman algorithm used in the Quake 3 engine
unmeng, algorithm used in DreamKiller
lz2k, algorithm used in various games developed by Traveller's T
ales
darksector, a very basic algorithm used in the game Dark Sector
tdcb_lzw12
tdcb_lzw15v
tdcb_silence
rdc
ilzr
dmc2
diffcomp
lzr
lzs (aka mppc)
lzs_big (aka mppc_big)
mohlzss
mohrle
yaz0 (aka szs)
byte2hex
un434a
xxdecode
pack, the one supported in gzip
unzip_dynamic, automatic zlib/deflate and output size, cool but
keep in mind that while zlib is almost error free due to the
checksum at its end, deflate doesn't guarantee a valid output
so, even if it uncompress the data, it may be invalid.
use zlib_noerror if you are 100% sure that the input is zlib o
r
non compressed, and deflate_noerror for deflate
zlib_noerror, as zlib but doesn't quit in case of errors and
automatically allocates the output buffer
deflate_noerror, as above but for deflate
ppmdh
ppmdh_raw
rnc
rnc_raw
pak_explode, alone in the dark
KENS_Nemesis
KENS_Kosinski
KENS_Kosinski_moduled
KENS_Enigma
KENS_Saxman
dragonballz (STPZ/0DCS/0LCS/STPK archives, Spyke developers?)
NitroSDK (nitroCompLib)
zdaemon, like doomhuff but different freq table
skulltag, like doomhuff but different freq table
msf, headerless lzma same as lzma_0
stargunner
ntcompress
crle
ctw
DACT_DELTA
DACT_MZLIB2
DACT_MZLIB
DACT_RLE
DACT_SNIBBLE
DACT_TEXT
DACT_TEXTRLE
EXECUTE:
use DICT to specify the command to execute using #INPUT#
instead of the input filename and #OUTPUT# for the output
one and the various variables like you do for the Print
command, example:
comtype EXECUTE "ctw.exe d #INPUT# #OUTPUT#"
comtype EXECUTE "ctw.exe d #INPUT# %NAME%"
lzv1
fastlzah, it should be identical to lzf
zax
shrinker
mmini_huffman
mmini_lz1
mmini
clzw
lzham, use the dictionary to specify the following fields:
m_dict_size_log2, m_table_update_rate, m_decompress_flags,
m_table_max_update_interval, m_table_update_interval_slow_rate
otherwise it will try to brute force the first 3 fields
lpaq8
sega_lzs2, automatic handling of CM/lzs2 and decompressed size
wolf
coreonline
mszip, "CK" included (from libmspack)
qtm, (from libmspack)
mslzss, (from libmspack)
mslzss1, (from libmspack)
mslzss2, (from libmspack)
kwaj, mslzh (from libmspack)
lzlib (lzip)
dflt
lzma_dynamic, automatic output size and automatic scanning of
any supported flag, so it should blindly work against any
compressed lzma input.
if it's not compressed, the input will be copied on the output
.
another difference with "lzma" is that lzma returns an error
if the input buffer doesn't have other compressed bytes
(LZMA_STATUS_NEEDS_MORE_INPUT) while lzma_dynamic gives the ok
,
this is useful with some rare cases like Far Cry 3 (fat2_fat3.
bms)
lzma2_dynamic, automatic output size
lzma2_efs
lzxcab_delta
lzxchm_delta
ffce
SCUMMVM1 -> SCUMMVM53 many algorithms used in Scummvm
lzs_unzip, PSP_Nanoha
legend_of_mana
dizzy
edl1
edl2
dungeon_kid
frontmission2
rleinc1
rleinc2
evolution
unknown1 -> unknown19
blackdesert
blackdesert_raw
pucrunch
zpaq
zyxel_lzs
blosc
gipfeli
crush
yappy
lzg
doboz
tornado
xpksqsh
amiga_unsquash
amiga_bytekiller
amiga_flashspeed
amiga_iamice
amiga_iamatm
amiga_isc1p
amiga_isc2p
amiga_isc3p
amiga_upcomp
amiga_uphd
amiga_bytekiller3
amiga_bytekiller2
amiga_crunchmania17b
amiga_powerpacker
amiga_stonecracker2
amiga_stonecracker3
amiga_stonecracker4
amiga_crunchmaster
amiga_crunchmania
amiga_crunchmaniah
amiga_crunchomatic
amiga_discovery
amiga_lightpack
amiga_mastercruncher
amiga_maxpacker
amiga_megacruncher
amiga_packit
amiga_spikecruncher
amiga_tetrapack
amiga_timedecrunch
amiga_tryit
amiga_tuc
amiga_turbosqueezer61
amiga_turbosqueezer80
amiga_turtlesmasher
amiga_dms
amiga_packfire
alba_bpe5
alba_bpe2
flzp
sr2
sr3
bpe2v3
bpe_alt1
bpe_alt2
cbpe
scpack0
LZMA_0, those with the '0' (zero) at the end are headerless,
use the dictionary to specify the dictionary size IF necessary
LZMA_86HEAD0
LZMA_86DEC0
LZMA_86DECHEAD0
LZMA_EFS0
LZMA2_0
LZMA2_86HEAD0
LZMA2_86DEC0
LZMA2_86DECHEAD0
LZMA2_EFS0
lzovl
NITROSDK_DIFF8
NITROSDK_DIFF16
NITROSDK_HUFF8
NITROSDK_HUFF16
NITROSDK_LZ
NITROSDK_RL
qcmp
sparse
stormhuff
gzip_strict, gzip without autoguessing the presence of crc32 and
isize at the end, use this if the file is a real 100% gzip fil
e
CT_HughesTransform
CT_LZ77
CT_ELSCoder
CT_RefPack
qfs, same as dk2
PXP
BOH
GRC
ZEN
LZHUFXR
FSE
FSE_RLE
ZSTD
CSC
RNCb
RNCb_RAW
RNCc_RAW
AZO
PP20
DS_BLZ
DS_HUF
DS_LZE
DS_LZS
DS_LZX
DS_RLE
FAB
LZ4F
PCLZFG
LZOO
DELZC
DEHUFF
HEATSHRINK
MRLE
SMAZ
LZFX
PITHY
ZLING
DENSITY
BROTLI
RLE32
RLE35
BSC
SHOCO
WFLZ
FARI
RLE_ORCOM
DICKY
SQUISH
LZNT1
//
XPRESS
//
XPRESS_HUFF //
LZJODY
NEPTUNIA
SMAZ
LZFX
PITHY
ZLING
DENSITY
BROTLI
RLE32
RLE35
BSC
SHOCO
WFLZ
FASTARI
RLE_ORCOM
DICKY
SQUISH
LZNT1
XPRESS
XPRESS_HUFF
LZJODY
TRLE
SRLE
MRLE
LUNAR_LZ19
JCH
LZRW1KH
LZSS0
LHA_lz5
LHA_lzs
LHA_lh1
LHA_lh4
LHA_lh5
LHA_lh6
LHA_lh7
LHA_lhx
LHA_pm1
LHA_pm2
SQX1, currently
MDIP_ARAD
MDIP_ARST
MDIP_DELTA
MDIP_FREQ
MDIP_HUFFMAN
MDIP_CANONICAL
MDIP_LZSS
MDIP_LZW
MDIP_RICE
MDIP_RLE
MDIP_VPACKBITS
bizarre
bizarre_skip
lzssx
ash
YAY0
DSTACKER
DSTACKER_SD3
DSTACKER_SD4
DBLSPACE
DBLSPACE_JM
XREFPACK, just another dk2/refpack
XREFPACK0, as above but without handling of header
qcmp2, UFG::qDecompressLZ probably the same of qcmp
deflatex, deflate used in Aeriagames pkg.idx
zlibx, as above but skips the first 2 bytes
lzrw1a
lzrw2
lzrw3a
lzrw5
LEGO_IXS
mcomp, libmcomp / MCMQ / MCMP
mcomp0, rolz
mcomp1, rolz3 (or deflate fast on mcomp.exe)
mcomp2, lz
mcomp3, deflate
mcomp4, deflate64
mcomp5, bzip2
mcomp6, ppmdj
mcomp7, sl
mcomp8, sm
mcomp9, dmc
mcomp10, ??? (10,11,12,18,19,20 are all the same function)
mcomp13, fpw1
mcomp14, fpw2
mcomp15, fpw3
mcomp16, fpw4
mcomp17, pwcm
irolz
irolz2
uclpack
ace
ea_comp
ea_huff
ea_jdlz
tornado_byte
tornado_bit
tornado_huf
tornado_ari
lbalzss1
lbalzss2
dbpf, Maxis DBPF
TITUS_LZW
TITUS_HUFFMAN
KB_LZW
KB_DOSLZW
CARMACK
MBASH
DDAVE
GOT
SKYROADS
ZONE66
EXEPACK
DE_LZW
JJRLE
K13RLE
SFRLC
WESTWOOD1
WESTWOOD3
WESTWOOD3b
WESTWOOD40
WESTWOOD80
PKWARE_DCL
TERSE
TERSE_SPACK_RAW
TERSE_PACK_RAW
REDUCE1
REDUCE2
REDUCE3
REDUCE4
LZW_ENGINE, requires the following parameters:
- initial codeword length (in bits)
- maximum codeword length (in bits)
- first valid codeword
- EOF codeword is first codeword
- reset codeword is shared with EOF
- flags (check src/compression/filter-lzw.h)
LZW_BASH
LZW_EPFS
LZW_STELLAR7
ULTIMA6
---------------------------------- recompression algorithms ---------------------------------zlib_compress
deflate_compress
lzo1_compress
lzo1x_compress
lzo2a_compress
xmemlzx_compress
bzip2_compress
gzip_compress
lzss_compress
sfl_block_compress
sfl_rle_compress
sfl_nulls_compress
sfl_bits_compress
lzf_compress
brieflz_compress
jcalg_compress
bcl_huf_compress
bcl_lz_compress
bcl_rice_compress
bcl_rle_compress
bcl_sf_compress
szip_compress
huffmanlib_compress
lzma_compress
lzma_86head_compress
lzma_86dec_compress
lzma_86dechead_compress
lzma_efs_compress
falcom_compress
kzip_zlib_compress
kzip_deflate_compress
prs_compress
rnc_compress
lz4_compress
sfl_block_chunked_compress
snappy_compress
zpaq_compress
blosc_compress
gipfeli_compress
yappy_compress
lzg_compress
doboz_compress
nitrosdk_compress
hex_compress
base64_compress
lzma2_compress
lzma2_86head_compress
lzma2_86dec_compress
lzma2_86dechead_compress
lzma2_efs_compress
lzma_0_compress
lzma2_0_compress
stormhuff_compress
CT_HughesTransform_compress
CT_LZ77_compress
CT_ELSCoder_compress
CT_RefPack_compress
dk2_compress
qfs_compress, same as dk2_compress
LZHUFXR_COMPRESS
FSE_COMPRESS
ZSTD_COMPRESS
DS_BLZ_COMPRESS
DS_HUF_COMPRESS
DS_LZE_COMPRESS
DS_LZS_COMPRESS
DS_LZX_COMPRESS
DS_RLE_COMPRESS
HEATSHRINK_COMPRESS
SMAZ_COMPRESS
LZFX_COMPRESS
PITHY_COMPRESS
ZLING_COMPRESS
DENSITY_COMPRESS
BSC_COMPRESS
SHOCO_COMPRESS
WFLZ_COMPRESS
FASTARI_COMPRESS
DICKY_COMPRESS
SQUISH_COMPRESS
LZHL_COMPRESS
LZHAM_COMPRESS
TRLE_COMPRESS
SRLE_COMPRESS
MRLE_COMPRESS
CPK_COMPRESS, note that in reimport mode it may not work
because the decompression is size-dependent so the
compressed size will probably change but the value
will not be modified in the original archive (the
.......................................................................
ReverseShort VAR
Classical swap that inverts a 16bit variable from 0x2211 to 0x1122
and vice versa.
Arguments:
VAR
variable to flip
.......................................................................
ReverseLong VAR
Classical swap that inverts a 32bit variable from 0x44332211 to
0x11223344 and vice versa.
Arguments:
VAR
variable to flip
.......................................................................
ReverseLongLong VAR
Classical swap that inverts a 32bit variable from 0x8877665544332211
to 0x1122334455667788 and vice versa.
This command works only with quickbms_4gb_files.exe
Arguments:
VAR
variable to flip
.......................................................................
Endian TYPE [VAR]
It changes the current global endianess of the read/written data,
the default one is little endian.
Arguments:
TYPE
- little, intel
endianess where 0x11223344 is stored as 44 33 22 11
- big, network
endianess where 0x11223344 is stored as 11 22 33 44
- swap, change, invert
change endianess, if it was big now will be little
- guess
followed by a 32bit number. The function swaps the number
and compares it with the original one so if the number
is 0x04000000 then the swapped one will be 0x4 and the
tool will change the global endianess and the one of
the variable
- guess16
followed by a 16bit number
- guess64
followed by a 64bit number
- guess24
followed by a 24bit number
- save, store
stores the current endian in VAR: 1 for big and 0 for little
Examples:
print "little endian"
endian big
print "big endian"
endian little
print "little endian"
endian change
print "little->big endian"
endian guess 0x04000000
print "guess endian"
endian save CURRENT_ENDIAN
if CURRENT_ENDIAN == 0
print "little endian"
else
print "big endian"
endif
.......................................................................
FileXOR SEQ [OFFSET]
Any read operation (Get, *Log and so on) on any file will perform
also the xoring of the read data with the numbers contained in the
given string or in the given variable.
The OFFSET field by default is zero which means that if the data
must be xored with more than one byte (a "xor key") the first byte
of the key is the first byte at OFFSET which is 0 by default
(beginning of the file).
Recap: the FileXOR command works with ANY file access.
Arguments:
SEQ
Sequence of space-separated 8bit numbers, it can be a:
- sequence of bytes separated by space like 0x12 or
"0x12 0x34 0x56" or directly a C hex string like
"\x12\x34\x56" (NOT a C notation!)
- a numeric variable like MYXORKEY
- a string that doesn't start with numbers, '\' or '-'
Currently it's not possible to use a key in string mode
and use the Encryption command for doing it, so if you
have a string convert it to a numeric sequence first or
be sure that it doesn't start with the chars shown above.
Set it to 0 or "" for disabling the xor
Note that SEQ can be also a 32bit signed number like
filexor 0x11223344 but the size is decided by value so
0x00000022 is 8 bit and not 32, while -0x20 is considered
8bit and 0x80112233 a 32bit.
OFFSET
Needed only for the xor key offset.
If the archive is xored with a xor key from its beginning
(so first byte of the archive xored with the first one
of the key) this argument is usually not necessary
Instead if only the file to extract is xored, this
argument must have the same offset of the file (so
just reuse the same OFFSET used in Log)
Examples:
filexor 0xff
filexor -0x20
filexor 0x1122
# 32bit
filexor -0x1122 # 32bit
filexor "0x12 0x34 123 255"
filexor MYXORBYTE
saepos OFFSET
filexor "0x12 0x34 123 255" OFFSET
filexor "\x12\x34\x7b\xff"
Log NAME OFFSET SIZE
.......................................................................
FileRot SEQ [OFFSET]
Exactly as for FileXOR but it performs a sum operation.
For example if SEQ is 0x01 and the file contains "hello" it will
become "ifmmp" while if SEQ is -1 or 0xff it will become "gdkkn".
-1 and 0xff are the same because it's a 8 bit number while
0x100 or -0x100 are considered 32bit.
Recap: the FileRot command works with ANY file access
examples
strlen NAME_LENGTH NAME
strlen NAMESZ NAME
strlen RAW_NAMESZ NAME 1
.......................................................................
GetVarChr VAR VAR OFFSET [TYPE]
A particular and sometimes very useful command which works exactly
like accessing an array of elements contained in the second variable,
for example a string or a memory file.
It can be compared to C as: var1 = var2[offset];
This simple and effective method allows the manipulation of strings
and variables for creating custom headers (like a DDS) and moreover
for performing operations on a piece of the memory, like a custom
encryption algorithm.
Some real examples are my Deer Hunter 2004/2005 scripts.
Arguments:
VAR
Destination variable which will contain the read element
VAR
Variable or memory file from which you want to get the
element
OFFSET
Position of the second variable where taking the element
TYPE
Type of the element to read and assign to the first
variable, if not specified it's a BYTE so a 8bit number.
You can specify most of the available datatypes like
short, long, longlong and so on
Examples:
For i = 0 < SIZE
GetVarChr TMP MEMORY_FILE i
GetVarChr TMP MEMORY_FILE i long
# GetVarChr TMP MEMORY_FILE i string
Next i
.......................................................................
PutVarChr VAR OFFSET VAR [TYPE]
The "write-mode" alternative of the previous command which allows
to perform various complex operations with custom algorithms (like
in my Deer Hunter 2004/2005 scripts).
It can be compared to C as: var1[offset] = var2;
Note that PutVarChr can be also used as an allocator of memory that
is often useful in the implementation of custom decompression
algorithms or, moreover, for pre-allocating a MEMORY_FILE for
storing chunks. This is useful to avoid wasting time and memory
with the incremental allocation, remember only to use the command
"Log MEMORY_FILE 0 0" after it for resetting the position of the
MEMORY_FILE.
arguments
VAR
OFFSET
VAR
TYPE
Examples:
For i = 0 < SIZE
GetVarChr TMP MEMORY_FILE i
Math TMP ^= 0xff
PutVarChr MEMORY_FILE i TMP
Next i
.......................................................................
Debug [MODE]
#
#
#
#
like -v
like -v
like -V
disable -v/V
.......................................................................
Padding VAR [FILENUM] [BASE_OFF]
When called it performs an automatic GoTo to the next position of
the file skipping the aligned data.
Imagine to have a file where it's used an alignment of 4 bytes and
your current file offset is 0x39, if you use Padding 4 the offset
will be automatically changed to 0x3c.
By default the padding is referred to the beginning of the file
(offset 0).
Arguments:
VAR
Size of the alignment, for example 4 or 16 and so on
FILENUM Number of the file associated to the archive (0)
BASE_OFF base offset from which must be calculated the padding (0)
Examples:
Get NAME string
Padding 4
get OFFSET long
.......................................................................
Append [DIRECTION]
Command to enable the append mode in the *Log commands, so if the
output filename already exists it will not be overwritten, the new
content will be concatenated (appended) to the existent one.
Note that with real files (not memory files) the user may be prompted
before writing the output file if it already existed before the
running of the script.
Note that the reimport mode may not work correctly when you use a
combo of MEMORY_FILE and Append (like I usually do in my scripts),
so the direct and more simple Log to file + Append is suggested.
Arguments:
DIRECTION This is a new optional argument that allows to specify
where placing the new content:
-1 a negative value means that the new content will be
placed before the current file, so the old content
0
1
Examples:
append
Log "dump.dat" 0 0x10
Log "dump.dat" 0x10 0x100
The following is a particular example for allocating a MEMORY_FILE
and using it instead of TEMPORARY_FILE saving space on the disk and
performances:
math TMP = CHUNKS
math TMP *= 0x8000
log MEMORY_FILE 0 0
putvarchr MEMORY_FILE TMP 0 # improves the speed with pre-allocation
log MEMORY_FILE 0 0
# reset the position and size of the file
append
for i = 0 < CHUNKS
...
clog MEMORY_FILE OFFSET ZSIZE 0x8000
next i
append
get SIZE asize MEMORY_FILE
.......................................................................
Encryption ALGO KEY [IVEC] [MODE] [KEYLEN]
One of the most interesting commands which allows to set a
decryption algorithm used for the Log and CLog command.
QuickBMS supports also the hashing algorithms of OpenSSL, the
binary hash will be placed in the variable QUICKBMS_HASH while the
hexadecimal hash in QUICKBMS_HEXHASH (capital letters) and
QUICKBMS_HEXHASHL (low).
Note that the hashing algorithms don't need a key, but you can use
that field for performing a direct hash operation on the provided
key without using the log command, eg: encryption sha1 "mystring".
You can also specify the size in case it's a binary variable, eg:
encryption md5 "mystring" "" 0 8.
For the HMAC hash algorithm you must use the IVEC field, anyway
remember that this feature is just optional.
Arguments:
ALGO
aes, Rijndael
blowfish, you should try also bf_ecb if the result is
not the expected one
des
3des-112
3des-168
rc4
tea, use IVEC to specify custom delta, sum, endian (0/1) and cyc
les
xtea, use IVEC to specify custom delta, endian (0/1) and cycles
xxtea, use IVEC to specify custom delta, endian (0/1) and cycles
idea
radiogatun32
radiogatun64
ripemd
ripemd128
ripemd160
sha0
sha1
sha224
sha256
sha384
sha512
shabal192
shabal224
shabal256
shabal384
shabal512
shavite224
shavite256
shavite384
shavite512
simd224
simd256
simd384
simd512
skein224
skein256
skein384
skein512
tiger
tiger2
whirlpool
whirlpool0
whirlpool1
sph
mpq
rc6
xor_prev
< data[i] ^= data[i - 1]
erations
different than xor and t
he value to
use for the last byte, "
^ 0x8e"
xor_prev2 < data[i] ^= data[i + 1]
"
xor_next
> data[i] ^= data[i - 1]
"
xor_next2 > data[i] ^= data[i + 1]
"
PKCS5_PBKDF2_HMAC, example PKCS5_PBKDF2_HMAC_sha1
BytesToKey, example "BytesToKey_sha1 aes"
ZIP_AES followed by 128, 192 or 256
rsa
rsa_tomcrypt
modpow, just a simple RSA BN_mod_exp performed on chunks of 256
bytes
modpow_zed
abc
achterbahn
achterbahn128
cryptmt
dicing
dragon
edon80
ffcsr8
fubuki
grain
grain128
hc128
hc256
hermes128
hermes80
lex
mag
mickey
mickey128
mir1
mosquito
moustique
nls
polarbear
pomaranch
py
rabbit
salsa20
sfinks
sosemanuk
sss
trivium
tsc3
tsc4
wg
yamb
aes_ige
aes_bi_ige
aes_heat, used in the game Heat Online
tomcrypt
modes: ecb, cfb, ofb, cbc, ctr, lrw, f8, xts
encryptions: blowfish, rc5, rc6, rc2, saferp, safer_k64,
safer_k128, safer_sk64, safer_sk128, rijndael, aes,
rijndael_enc, aes_enc, xtea, twofish, des, des3, cast5,
noekeon, skipjack, khazad, anubis, kseed, kasumi, camellia
hashing: multi2, chc, whirlpool, sha512, sha512-256, sha512-22
4,
sha384, sha256, sha224, sha1, md5, md4, md2, tiger, rmd128,
rmd160, rmd256, rmd320
example: Encryption "tomcrypt rijndael ecb" "0123456789abcdef"
crc, a complete and powerful checksum function that can
be fully configured:
- key is the polynomial (use "" for the default crc32 0x770730
96)
- ivec contains:
- the size of the crc (8/16/32)
- the initial value (like -1)
- the final xor value (-1, the complement)
- the type (various supported)
- the reverse mode during the generation of the table
- the bitmask_side (0 or 1 where 1 is the most used one)
default values: 0xedb88320 32 -1 -1 0 0 1
if you need the classical crc16 (0xc0c1) use:
encryption crc 0xa001 "16 0 0 0 0 1"
or
encryption crc "" 16
the result is placed in the variable QUICKBMS_CRC
Print MESSAGE
It prints a string in C notation with the values of the variables if
their names are specified between '%' chars.
It's also possible to specify the maximum amount of bytes to
visualize (or a variable containing such value) and if they must be
displayed in hex or dump mode specifying some flags after a '|' like
in the examples:
- x/h/hex: hexadecimal numbers and chars
- dump:
hexadecimal dump, left in hexadecimal and right in chars
- number: amount of bytes to show
- var:
variable containing the amount of bytes to show
Arguments:
MESSAGE C notation string, each %VAR% word is converted to its
value (cstring)
Examples:
print "the variable OFFSET of the file %FILENAME% has the value %OFFSET|x%
"
print
print
print
print
print
print
print
.......................................................................
GetArray VAR ARRAY VAR_IDX
and
PutArray ARRAY VAR_IDX VAR
Experimental commands to store variables in bidimensional arrays.
They work on a dynamic array where it's possible to store the
variables. Something like a temporary place or a stack.
It's highly suggested to pre-allocate the array if you know the
max value, example: PutArray 0 FILES 0
If the array index (VAR_IDX) is negative like -1:
- getarray will take the element located at that position from the
end of the array, so "getarray VAR 0 -1" will take the last
element while "getarray VAR 0 -2" will take the one before
- putarray will ever append the element at the end of the array,
currently there is no difference if you use VAR_IDX -1, -2, -1000
Examples:
PutArray 0 0 FIRST_VAR
PutArray 0 1 SECOND_VAR
GetArray FIRST_VAR 0 0
GetArray SECOND_VAR 0 1
for i = 0 < FILES
putarray 0 -1 VAR
next i
.......................................................................
Examples:
http://aluigi.org/bms/thevoid.bms
http://aluigi.org/bms/fear.bms
.......................................................................
ScanDir PATH NAME SIZE [FILTER]
Function without a real usage, it simply scans the PATH folder and
fills the NAME and SIZE variables with the name and the size of
each file found.
At the moment this function doesn't have a purpose so ignore it.
If you want to filter the scanned files located in the folder you
specified as input, use the -F option of quickbms (I tell this
information because some users may think to "wrongly" use this
command for that purpose).
Arguments:
PATH
Must be ".", the current folder
There are also some "experimental" values not meant for
normal usage, with optional file number after "://"
(for example heap://10 will work on the file number 10):
process:// processes on the system: NAME=process SIZE=pid
module:// modules in the opened process: NAME=address SIZE
=size
memory:// allocated blocks of memory: NAME=address SIZE=si
ze
heap://
every single allocated heap (slow!): NAME=addres
s SIZE=size
NAME
Output variable which receives the name of the file, it
will be "" when there are no other files
SIZE
Output variable which receives the size of the file, it
will be -1 when there are no other files
FILTER
Same job as -F, this filter is valid only if -F wasn't
specified
Examples:
For
ScanDir "." NAME SIZE
if NAME == ""
cleanexit
endif
Next
...
For
ScanDir "." NAME SIZE "*.jpg"
if NAME == ""
cleanexit
endif
Next
.......................................................................
CallDLL DLLNAME FUNC/OFF CONV RET [ARG1] [ARG2] ... [ARGn]
This is the command which allows to use plugins inside QuickBMS.
The idea came from the possibility of using the custom
Examples:
idstring LZ2K
get SIZE long
get ZSIZE long
log MEMORY_FILE 0xc ZSIZE
putvarchr MEMORY_FILE2 SIZE 0 # like malloc
#calldll "TransformersDemo.exe" 0x263c50 cdecl "" MEMORY_FILE MEMORY_FILE2
ZSIZE SIZE
# 00663C50
calldll "unlzk.dll" "unlz2k" cdecl SIZE MEMORY_FILE MEMORY_FILE2 ZSIZE SIZ
E
log "dump.dat" 0 SIZE MEMORY_FILE2
.......................................................................
Put VAR TYPE [FILENUM]
...
PutDString VAR LENGTH [FILENUM]
...
PutCT VAR TYPE CHAR [FILENUM]
...
These commands are EXACTLY like the Get* functions except for the
fact that they perform write operations.
For using these commands on a physical file (so MEMORY_FILEs
excluded) the user MUST use the -w option at runtime, that's
necessary for both technical and security reasons.
If you want to write a string without the NULL delimiter use:
putct "your_string" string -1
.......................................................................
GetBits VAR BITS [FILENUM]
This is an experimental function for reading bits from the files.
When you use a GoTo function or change the current offset of the
file with a Get* command, the variable containing the bit position
(basically the amount of bits read from the previously byte taken
from the file) will be reset to 0.
Note that the function is 100% endian compatible so the result
changes if you choose the little or big endian mode, remember it in
case the results don't match what you expected.
Arguments:
VAR
Destination variable, can be a number if the bits are
from 0 to 32 or a string for bigger sizes
BITS
Number of bits to read
FILENUM Number of the file associated to the archive (0)
.......................................................................
PutBits VAR BITS [FILENUM]
Write mode, same format as GetBits
.......................................................................
Include FILENAME
This command loads another script in the current one, it can be
useful if you have many general functions and you want to avoid to
copy&paste them in any new script.
You can place it in any part of your script.
include "general.bms"
->
load the part of the current script till "include"
load general.bms
load the remaining part of the current script after "include"
.......................................................................
NameCRC VAR CRC [LISTFILE] [TYPE] [POLYNOMIAL] [PARAMETERS]
It's not rare to have archives containing files without names, just
a crc (checksum) calculated on the original filename to identify it.
The NameCRC command exists just in these situations, where you have
a file containing a list of filenames (maybe collected with a
debugger or via hooking) and you want to assign them to the output
files.
What this command does is just loading the names in LISTFILE,
calculating some checksums on them using the provided crc
parameters, and compare the CRC field read in the archive with the
calculated ones.
When a crc matches the one in the database, the original filename
is moved in the VAR variable.
Note that QuickBMS will automatically calculate various CRC for the
same filename, by using only slash or backslahs, or all the chars
to lower or upper case, by removing any "\/.:" char from the
beginning of the name and so on. This is necessary to grant the
catching of the right filename in any situation.
The feature is very fast and the "database" is not so big, so you
will notice almost no performance issues while using this command.
The function must be used before the *log operations and it can be
used as initializer at the beginning of the script and then with
only the first mandatory arguments to retrieve the filenames
matching the provided crc, for example:
namecrc DUMMY 0 "names.list" 32
...
get NAME_CRC long
namecrc NAME NAME_CRC
log NAME OFFSET SIZE
Or you can just use it with all the arguments:
...
get NAME_CRC long
namecrc NAME NAME_CRC "names.list" 32
log NAME OFFSET SIZE
Arguments
VAR
CRC
LISTF
TYPE
POLY
PARAM
.......................................................................
Codepage VAR
Allows to specify a codepage/charset (number or name) for the unicode
operations like "getdstring VAR2 SIZE ; Set VAR1 unicode VAR2".
Currently it works only on Windows and the full list of codepages
is available at:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%
29.aspx
Arguments
VAR
.......................................................................
SLog NAME OFFSET ZSIZE [TYPE] [FILENUM]
This command allows to export strings to an output file and being
able to reimport them later with reimport.bat.
The reimporting feature of this command has the same limitations of
the global one, so you cannot reimport strings that are longer than
the original.
Currently QuickBMS will simply tell you that the new string is longer
without interrupting the importing so pay attention.
The space between the end of the new and old string will be filled
with zeroes but this behaviour "may" be changed in future to avoid
situations in which there are sequential NULL delimited strings and
using zeroes will causes problems in the software that reads the
file. Anyway in these situations you can just insert the spaces by
yourself in the new string.
The dumped strings are handles as C strings, basically the '\' char
(backslash) is an escape that allows you to specify any byte you
desire, the \r and \n you will see are just the 0x0d and 0x0a bytes
that allow to insert the whole multiline string in one line.
Each line is an exported string.
Notepad++ highly suggested.
Small tip: Use INS (the replace character) mode of your text editor
for editing the string file to reimport so that you will have no
problems with longer new strings.
The SLog function is new so any feedback and suggestion is highly
appreciated.
Arguments:
NAME
Name of the output file. It will be created from scratch
the first time and then will be used in append mode from
the second line on. Automatic, simple and error-proof.
The output file is just in UTF-8 with Windows line feeds
("\r\n") and the conversion of unicode strings is performed
by QuickBMS automatically with the codepage in use
OFFSET The offset where is located the string you want to dump.
>=0 works just like the other *log commands and dumps
the string located at that OFFSET, it doesn't change
the current offset
<0 dumps the string at the current offset and updates it,
so it advances in the file
SIZE
>=0 it works just like the Getdstring command allowing
you to dump a string of a certain amount of bytes
<0 just like the Get command
TYPE
This is the type of data to read just like the Get
command, if not specified it's considered String. You can
dump most of the types and even the non-string ones so if
you use the Long type you will have the decimal value easy
to edit inside the output file
FILENUM the input file
Examples:
# the test file is available here http://aluigi.org/bms/slog_test.dat
set STRINGS_FILE string "strings.txt"
slog STRINGS_FILE -1 0xb string
slog STRINGS_FILE -1 -1
These operations are all converted to Get* commands while they are
converted in Put* if there is a '=' after them, like:
debug 1
struct test
int
char
char
uint8_t
}
{
var1 = 0x11111111;
var2 = 0x22;
*mystring = "hello";
data[10] = OTHER_VAR;
MEMORY_FILE 0 0
0x11111111 long MEMORY_FILE
0x22222222 long MEMORY_FILE
0x33333333 long MEMORY_FILE
"hello" string MEMORY_FILE
0x44444444 long MEMORY_FILE
SIZE asize MEMORY_FILE
"tcp://127.0.0.1:1234" 0 SIZE MEMORY_FILE
"udp://localhost:1234" 0 SIZE MEMORY_FILE
or
log
put
put
put
put
get
log
MEMORY_FILE 0 0
"GET / HTTP/1.0" line MEMORY_FILE
"User-Agent: Mozilla" line MEMORY_FILE
"Referer: http://localhost/test.htm" line MEMORY_FILE
"" line MEMORY_FILE
SIZE asize MEMORY_FILE
"tcp://127.0.0.1:80" 0 SIZE MEMORY_FILE
Command-line:
quickbms -n script.bms "" ""
While the following is a simple HTTP download that can be used with
quickbms -n script.bms "tcp://aluigi.org:80" "" > output.htm
get HOST filename
string HOST p= "Host: %s" HOST
put "GET / HTTP/1.1" line
put HOST line
put "User-Agent: Mozilla" line
put "Connection: close" line
put "" line
for
get DATA line
print "%DATA%"
next
Funny example that inverts the colors of the first notepad window:
set NAME string "video://notepad"
open "" NAME
get SIZE asize
filexor 0xff
log NAME 0 SIZE
Launch notepad and then run:
quickbms -g script.bms "" ""
How to close Firefox:
put 18 long # WM_QUIT
put 0 long
# wParam
put 0 long
# lParam
quickbms -m script.bms "winmsg://firefox" ""
In future I could decide to add other operations and I'm interested in
any other idea.
B] Other features
----------------Other experimental features are the support of most of the commands
used in templates of WinHEX:
http://www.x-ways.net/winhex/templates/index.html
Usually these templates work immediately while sometimes it's necessary
only to separate some arguments manually like "arg1""arg2" to
"arg1" "arg2".
QuickBMS has also the great feature of dumping an HTML file with the
parsed format highlighted through the option -H.
This is a very cool feature that can help many people and doesn't
require additional modifications, just use the original BMS scripts as
usual.
Unfortunately the generated HTML file is not optimized yet and so it
takes lot of memory and CPU to be loaded.
The QuickBMS process supports some return code numbers used when the
tool terminates due to a success or a fail, you can find the list at
the beginning of src\defs.h.
QUICKBMS_OK (success) is ever 0 while QUICKBMS_ERROR_* are referred to
problems.
- upx.exe -9 quickbms.exe
- copy /b quickbms.exe + script.bms
output.exe
That's all, anyway if you want to use the "classical" way and being
able to specify options, input file and output folder, it's better to
use the BAT solution with the -G option for the GUI mode:
EXTRACT.BAT:
quickbms.exe -G OPTIONS SCRIPT INPUT OUTPUT
#######################################################################
========
6) Notes
========
The following are some exceptions in the usage of QuickBMS.
They are not real bugs, rather they are things that can't work (at
least at the moment) due to the very flexible nature of the tool or
things that it's useful or interesting to know:
? (partially solved)
Number and strings, due to the usage of the optimizations the following
script will NOT result in "mytest46600x12349999999999", the result will
be "mytest4660-1717986919":
set NAME string "mytest"
set NUM long 0x1234
string NAME += NUM
print "%NAME%"
set NUM string "0x12349999999999"
string NAME += NUM
print "%NAME%"
This is a good compromise because the previous situation is very very
"rare" and in any case can be bypassed using multiple "string NAME += chr"
and the gain in performance is incredible for the multiple in-script
operations, so this is the best solution.
Additionally you can use the printf-like string command and the binary
type with Set:
set NAME string "mytest"
set NUM1 long 0x1234
set NUM2 binary "0x12349999999999"
string NAME p= "%s0x%x%s" NAME NUM1 NUM2
print "%NAME%"
- Any Clog operation with a compressed or uncompressed size minor/equal
than zero produces a file with a zero size, but this is not a problem
of the tool because it's the perfectly logical behavior in these
situations.
If it's necessary to use a compression which gets the SIZE value
automatically (like base64 or stalker_lza) is enough to specify the
compressed size as uncompressed size:
clog NAME OFFSET ZSIZE ZSIZE
or
clog NAME OFFSET ZSIZE 1
- The tool has been created to be 100% compatible with the original
MexScript language and its syntax/logic, so I tried to add not many
new commands and, if possible, providing an alternative using
the original set of commands (for example the Strlen command and
"Set VAR strlen VAR").
I tried also to maintain the logic of the program (for example
encryptions and compressions applied in the file operations only).
So if something looks complex or senseless, it has been made for
matching the original structure and logic of the scripting language.
- QuickBMS grants compatibility with the original MexScript language
that implements also some static and partially undocumented variables
like:
EXTRCNT, BytesRead, NotEOF, SOF, EOF
If you are writing a script for QuickBMS try to avoid these variable
names except if you really need and know what they do.
- QuickBMS uses many third party code and, even if I tried to adjust
them a bit where possible, unfortunately many of these external
functions were a disaster or missed any security requirement.
That's the reason why the comtype scanning feature causes so many
crashes with invalid data.
From version 0.5.5 I added a particular type of allocation management
that allows a better debugging of the code and at the same time
protects the heap from contiguous buffer overflow and underflow
(so it can do nothing against "buff[0x11223344] = 'a').
It's not a solution but at least helps me a lot and limits the
problems caused by third party non-safe code.
The only protection of the stack is provided by the
-fstack-protector-all compiler option of Gcc.
- Security:
It's hard to make the tool completely safe, anyway the following are
some notes and solutions:
- allocated memory set as read/write only with guarded page before and
after the buffer, they act like a "cage" that delimits the buffer
- usage of Gcc -fstack-protector-all
- the user is EVER prompted of activating dangerous features like the
usage of dlls and the calling of external executables
- some checks to avoid the problems caused by the big redundant code
of which QuickBMS is full (unfortunately, sorry for that)
- keep in mind that QuickBMS is mainly a testing tool in which I
preferred to insert strange and particular features rather than
making it "secure" for any user, it's the responsibility of the user
to use only trusted scripts and paying attention to the warnings
displayed by the tool
- The EXECUTE mode of ComType and Encryption will grant compatibility
with any compression and encryption tool (command-line) based on
algorithms not yet supported by QuickBMS, and at the same time avoids
the rush of trying to implement "everything" as soon as possible.
I used system() for this command just because I want that it's
compatible with any possible program included those which require
input from stdin and output to console (stdout).
Example: "file.exe < #INPUT# > #OUTPUT#"
? (partially solved)
All the extracted files are loaded completely in memory before being
dumped for various technical reasons, so if the file to dump has a
size of 800 megabytes this is the same size which will be allocated
in memory or even double or more if the file must be decompressed, so
it's good to have a good amount of free RAM when handling big archives
or at least a good virtual memory/swap space.
This mechanism is not used for files that don't require encryption
and compression in which case the operation is performed 1:1 using
a temporary buffer of only 1 megabyte.
x (SOLVED!)
Log "123.txt" OFFSET SIZE
It creates the file 123 and not 123.txt, this happens because "123.txt"
is considered a constant number due to the rule that everything
starting with a number (or a '-') is handled as a constant number.
This behavior didn't happen with the previous versions of the tool
because wasn't used the number optimization which saves tons of CPU
cycles in some scripts.
libmcrypt http://sourceforge.net/projects/mcrypt/files/Libmcrypt/
sphlib http://www.saphir2.com/sphlib/
cityhash https://code.google.com/p/cityhash/
xxhash https://github.com/Cyan4973/xxHash
qLibc https://github.com/wolkykim/qlibc
StormLib https://github.com/ladislav-zezula/StormLib
Others:
- MemoryModule of Joachim Bauch https://github.com/fancycode/MemoryModule
- various signatures from http://mark0.net/soft-trid-e.html
- various signatures from http://toorcon.techpathways.com/uploads/headersig.txt
- Ollydbg disasm library http://www.ollydbg.de
- optional BeaEngine dissassembler library http://www.beaengine.org
(maybe will be used in future, not now)
- uthash and utlist http://troydhanson.github.io/uthash/
Notes:
- Some (many?) of the original codes have been modified a bit to make
them usable in QuickBMS for the memory2memory (aka in-memory)
decompression and for other possible fixes or for decreasing the
amount of code, for example removing the compression routine leaving
only the decompression one.
Note that I avoided to make this third-party code more secure because
it's not the job of QuickBMS, so almost all the code (except some
rare cases) has been used "as-is", the only security protections come
from the general protection mechanisms adopted in QuickBMS like my
own heap handling and -fstack-protector-all.
- The files/libraries which have been modified have the header
"// modified by Luigi Auriemma" which is meant just to show that it's
not the 100% original code and it must be NOT considered like a
credit.
I claim nothing about them, the original license and authors are
still untouched.
- If the files have been modified or don't have the original license
information (may happen only with small functions that didn't contain
a license header in origin) please follow the provided links for more
details.
- Almost all the algorithms implemented here have been selected by me
because they:
- have been used
- "may" have been used
- it has been claimed to have been used
in real software and games, or they are enough known and famous to
deserve their implementation in QuickBMS.
Personally I prefer to have many algorithms implemented also to help
my compression and encryption scanners: comtype_scan2.bat/bms and
encryption_scan.bat/bms).
- Tell me if I forgot someone or something in this section, my memory
and level of attention are quite ridiculous so it's highly possible
that some credits are not complete.
And tell me also if it's necessary to include other files or comments
inside these third-party files or about them.
I included the list to the original websites as additional reference
also for having more information about their license in case the
included files don't have it in their comments (/* */)
#######################################################################