diff --git a/.gitignore b/.gitignore index 9907c7f..3639e4d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ output/ temp/ *.pck *.hdiff -tools.zip \ No newline at end of file +tools.zip +__pycache__/ \ No newline at end of file diff --git a/extract.py b/extract.py index 990cd50..8c017ce 100644 --- a/extract.py +++ b/extract.py @@ -2,6 +2,7 @@ import os import shutil import zipfile import filecmp +import wavescan import subprocess from halo import Halo from progress.bar import PixelBar @@ -60,20 +61,10 @@ def main(): if alone: output_path = "wem" - # prepare args - args = [ - path("tools/quickbms/quickbms.exe"), - "-o", - "-Y", - path("tools/quickbms/wavescan.bms"), - path(f"temp/{file}"), - path(f"temp/{output_path}") - ] - # update spinner and call program spinner.text = f"[{curr}/{steps}] Extracting" spinner.start() - call(args) + wavescan.extract(path(f"temp/{file}"), path(f"temp/{output_path}")) spinner.stop() print(f"[{curr}/{steps}] Extracting") @@ -114,20 +105,10 @@ def main(): if not alone: curr += 1 - # prepare args - args = [ - path("tools/quickbms/quickbms.exe"), - "-o", - "-Y", - path("tools/quickbms/wavescan.bms"), - path(f"temp/{file}"), - path(f"temp/patched_decoded") - ] - # update spinner and call program spinner.text = f"[{curr}/{steps}] Extracting patch" spinner.start() - call(args) + wavescan.extract(path(f"temp/{file}"), path(f"temp/patched_decoded")) spinner.stop() print(f"[{curr}/{steps}] Extracting patch") diff --git a/filereader.py b/filereader.py index 1ea5943..dc5a8e4 100644 --- a/filereader.py +++ b/filereader.py @@ -3,16 +3,15 @@ import struct class FileReader: """ - Simplified byte file reader with buffer - Not particularly optimised, contains repetitive functions - In the scope of this project, not everything will be used either - + Simplified byte file reader with buffer, it's not particularly optimised but good enough + In the scope of this project, not everything will be used in here """ - def __init__(self, file, endianness: str): + + def __init__(self, file, endianness:str): self.stream = file self.endianness = endianness - def _read(self, mode:str, bufferLength:int, endianness=None) -> bytes: + def _read(self, mode:str, bufferLength:int, endianness:str=None) -> bytes: # endianness override if endianness is None: endianness = self.endianness @@ -22,31 +21,31 @@ class FileReader: return struct.unpack(f"{endianness}{mode}", bytearray(self.stream.read(bufferLength)))[0] # read methods - def ReadInt16(self, endianness=None) -> int: + def ReadInt16(self, endianness:str=None) -> int: return self._read("h", 2, endianness) - def ReadUInt16(self, endianness=None) -> int: + def ReadUInt16(self, endianness:str=None) -> int: return self._read("H", 2, endianness) - def ReadInt32(self, endianness=None) -> int: + def ReadInt32(self, endianness:str=None) -> int: return self._read("i", 4, endianness) - def ReadUInt32(self, endianness=None) -> int: + def ReadUInt32(self, endianness:str=None) -> int: return self._read("I", 4, endianness) - def ReadLong(self, endianness=None) -> int: + def ReadLong(self, endianness:str=None) -> int: return self._read("l", 4, endianness) - def ReadULong(self, endianness=None) -> int: + def ReadULong(self, endianness:str=None) -> int: return self._read("L", 4, endianness) - def ReadLongLong(self, endianness=None) -> int: + def ReadLongLong(self, endianness:str=None) -> int: return self._read("q", 8, endianness) - def ReadULongLong(self, endianness=None) -> int: + def ReadULongLong(self, endianness:str=None) -> int: return self._read("Q", 8, endianness) - def ReadBytes(self, length:int, endianness=None) -> bytes: + def ReadBytes(self, length:int, endianness:str=None) -> bytes: return self._read(f"{str(length)}s", int(length), endianness) # buffer utils diff --git a/tools/quickbms/quickbms.exe b/tools/quickbms/quickbms.exe deleted file mode 100644 index a7dc856..0000000 Binary files a/tools/quickbms/quickbms.exe and /dev/null differ diff --git a/tools/quickbms/quickbms.txt b/tools/quickbms/quickbms.txt deleted file mode 100644 index 93b4fff..0000000 --- a/tools/quickbms/quickbms.txt +++ /dev/null @@ -1,4676 +0,0 @@ -####################################################################### - - -QuickBMS -by Luigi Auriemma -e-mail: me@aluigi.org -web: aluigi.org -home: http://quickbms.com -help: http://zenhax.com - - -####################################################################### - - -1) Introduction -2) Usage -3) Reimporting the extracted files -4) How to create scripts (for developers only!) -5) Experimental input, output and other features -6) Notes -7) Support -8) Additional credits - - -####################################################################### - -=============== -1) Introduction -=============== - - -QuickBMS is a multiplatform extractor engine that can be programmed -through some simple instructions contained in textual scripts, it's -intended for extracting files and information from the archives of any -software and, moreover, games. - -The script language used in QuickBMS is an improvement of MexScript -documented here: http://wiki.xentax.com/index.php/BMS -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 most of 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 the extracted -files back in their original archives. - -The tool is open source under the GPL license and works on Windows, -Linux and MacOSX, on both little and big endian architectures like -Intel (littlen endian) and PPC (big endian). -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. - -The official homepage of QuickBMS with all the scripts I have -written from 2009 till now is (they are just links to the same -website): - - http://quickbms.com - \ http://quickbms.aluigi.org - \ http://aluigi.altervista.org/quickbms.htm - \ http://aluigi.zenhax.com/quickbms.htm (rarely updated) - -There is also an official forum where I provide support for Quickbms -and help with file formats, it's also a very good and friendly free -community for reverse engineering game files: - - https://zenhax.com - -QuickBMS is perfect for those works in which you need a quick way to -extract information from files and at the same time you would like to -reinject them back without writing a standalone tool to do both the -extraction and rebuilding jobs. -This is particularly useful if you have 100 different types of archives -to analyze (reverse engineering), parse and then sharing your tools -with your community. It's more easy to do that with some lines of text -that you can paste on a forum or pastebin rather than writing 100 -different standalone extraction tools plus other 100 standalone -rebuilders. - - ------------------------------------------------------------------------ - - -For Linux and MacOSX users there is a Makefile in the src folder, the -only requirements are openssl, zlib, bzip2 and lzo while the optional -components are ucl, mcrypt and tomcrypt (uncomment the commented line -near the end of the Makefile to enable them). -If your distro supports apt-get and you have problems during the usage -of "make", try the following: - - apt-get install gcc g++ zlib1g-dev libbz2-dev libssl-dev liblzo2-dev unicode - -In case of problems on 64bit versions of Linux, try also to append a -":i386" to the previous dependencies, like: - - apt-get install libssl-dev:i386 libbz2-dev:i386 liblzo2-dev:i386 - -MacOSX users need to read the simple instructions written in Makefile, -just few steps for being able to compile QuickBMS easily without -problems, anyway maybe try a make first because from version 0.8.1 it -was rewritten to work easily. -Updated static builds for Linux x86 and MacOSX are available on -http://aluigi.altervista.org/quickbms.htm#builds - -Feel free to contact me in case of problems or just post on -https://zenhax.com - - -####################################################################### - -======== -2) Usage -======== - - -Simple and quick: - -- double-click on quickbms.exe - -- select the script for the type of archive you want to extract, for - example zip.bms if it's a zip file. - -- select the input archive or multiple files. - you can also select a whole folder by entering in it and then typing - * (or "" on systems before Windows 7) in the "File name:" field, and - then select Open. - You can even use * to set wildcards, for example *.txt or *required_name* - or prefix*suffix - -- select the output folder where extracting the files. - you can specify any filename, it will be ignored because only the - current selected directory is taken - -- watch the progress status of the extraction and the final message - -That's the simple "GUI" usage but QuickBMS can do various other things -when launched from the console, in fact it supports many command-line -options for advanced users and for who writes the scripts. -You can view all the available options simply launching QuickBMS from -command-line ("cmd.exe" on Windows) without arguments. -The following is the current list of options: - - - Usage: quickbms.exe - [options] - - - [output_folder] - - Options: - -l list the files without extracting them - -f W filter the files to extract using the W wildcards separated by comma or - semicolon, example -f "*.mp3,*.txt;*myname*" - if the filter starts with ! it's considered an ignore filter - the filter can be also a text file containing filters - example: quickbms -f "*.mp3;!*.ogg" script.bms archive.dat output - example: quickbms -f myfilters_list.txt script.bms archive.dat - please use {} instead of * to avoid problems on Windows, you can also - use multiple -f if you feel more comfortable - -F W as above but works only with the files in the input folder (if used) - example: quickbms -F "*.dat" script.bms input_folder output_folder - -o if the output files already exist this option will overwrite them - automatically without asking the user confirmation - -k keep the current files if already exist without asking (skip all) - -K automatically rename the files if duplicates already exist - -r experimental reimport option that should work with many archives: - quickbms script.bms archive.pak output_folder - modify the needed files in output_folder and maybe remove the others - quickbms -w -r script.bms archive.pak output_folder - you must read section 3 of quickbms.txt before using this feature, - use -r -r to use the alternative reimport mode - -u check if there is a new version of QuickBMS available - -i generate an ISO9660 file instead of extracting every file, the name of - the ISO image will be the name of the input file or folder - -z 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 similar to -d but will not create the folder with the filename - -E 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 - #INPUT# placeholder which will be replaced by the name of the file - example: -S "lame -b 192 -t --quiet #INPUT#" - -Y automatically answer yes to any question - -O F redirect the output of all the extracted files to the file F - -s SF add a script file or command before the execution of the input script, - useful if an archive uses a different endianess or encryption and so on - SF can be a script or directly the bms instruction you want to execute - -. don't terminate QuickBMS if there is an error while parsing multiple - files (like wrong compression or small file), just continue with the - other files in the folder; useful also in rare cases in reimport mode - - Debug and experimental options: - -v verbose debug information, useful for verifying possible errors - -V alternative verbose output, useful for programmers - -q quiet, no *log output - -Q very quiet, no output except the Print command - -L F dump the offset/size/name of the files inside the file F - -x use the hexadecimal notation in myitoa (debug) - -0 no extraction of files, useful for testing a script without using space - -R needed for the programs that act as interface for QuickBMS and in batch - -a S pass arguments to the input script that will take the names - quickbms_arg1, quickbms_arg2, quickbms_arg3 and so on, note that they - handled as arguments so pay attentions to spaces and commas, eg: - -a "arg1 \"arg 2\", arg3" - -a arg1 -a "\"arg 2\"" -a arg3 - -H cool HTML hex viewer output, use it only with very small files! - -X cool hex viewer output on the console (support Less-like keys) - -9 toggle XDBG_ALLOC_ACTIVE (enabled) - -8 toggle XDBG_ALLOC_INDEX (enabled) - -7 toggle XDBG_ALLOC_VERBOSE (disabled) - -6 toggle XDBG_HEAPVALIDATE (disabled) - -3 execute an INT3 before each CallDll, compression and encryption - -I toggle variable names case sensitivity (case insensitive) - -M F experimental compare and merge feature that allows to compare the - extracted files with those located in the folder F, currently this - experimental option will create files of 0 bytes if they are not - different, so it's not simple to identify what files were written - -Z in reimport mode it will replace all the archived files with zeroes - -P CP set the default codepage to use, it can be a number or string - -T do not delete the TEMPORARY_FILE at the end of the process - -N decimal names for files without a name: 0.dat instead of 00000000.dat - -e ignore the compression errors and dump the (wrong) output data anyway - -J all the constant strings are considered Java/C escaped strings (cstring) - - Features and security activation options: - -w enable the write mode required to write physical input files with Put* - -C enable the usage of CallDll without asking permission - -n enable the usage of network sockets - -p enable the usage of processes - -A enable the usage of audio device - -g enable the usage of video graphic device - -m enable the usage of Windows messages - -G force the GUI mode on Windows, it's automatically enabled if you - double-click on the QuickBMS executable - - -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 -l -f "*.mp3" zip.bms myfile.zip - quickbms -l -f "{}.mp3;{}.ogg" zip.bms myfile.zip - quickbms -l -f "*.mp3;*.ogg,*filename*" zip.bms myfile.zip - quickbms -l -f file_containing_the_filters.txt zip.bms myfile.zip - -So -l for listing the files without extracting them, and -f for -filtering the archived files. Regarding the -f and -F options it's worth -to note that both * and {} are accepted as wildcards because the first -pattern may be interpreted by the Windows console (my suggestion is to -use ever {} to avoid problems). - -QuickBMS supports also a folder as input which means that with a single -command it's possible to unpack all the archives of a whole game -directly using QuickBMS. - -Imagine to use the zip.bms script with all the zip files located in the -Program Files folder: - - quickbms -F "*.zip" zip.bms "c:\Program Files (x86)" c:\output_folder - -Note: as said before, sometimes Windows doesn't like the * char even if - used between quotes, so in case of problems with "*.zip" you can - use {} instead of *, for example "{}.zip" - -Except for -l, -f, -F and maybe -o and -s options, the others are -intended for debugging, or they are special features or switches to -enable/disabe some internals, so they should be ignored by the common -users. - -If the extraction with a particular script is too slow or scanning a -folder takes too much memory and time try using the -9 option that -disables the memory protection. - -You can apply these options directly in a shortcut to quickbms.exe in -the Target field of its properties, so you can use the double-click -"GUI" method and all the command-line options you desire without -using the command-line. - -In the same quickbms.zip package you should find -also quickbms_4gb_files.exe (previously known as quickms64_test.exe) -that is an "experimental" version that uses 64bit numbers instead of -the original 32 bits: -- it supports archives and files bigger than 4 gigabytes -- it may have problems to work with "some" scripts -- it's a native 32bit application so it works on both Windows 32 and 64 -- it's experimental and so not much supported, problems like crashes - and incorrect math operations can happen often in some scripts - - ------------------------------------------------------------------------ - - -Advanced users could find useful also these specific options: - --d Automatically creates a folder with the name of the input file where - placing all the files, it's useful if you have many small archives - containing the same filenames and you need a way to separate the - extracted files without overwriting or renaming them. - --E If you have a bms script that simply reads a file format, you can - change the endianess of all its numeric fields on the fly by simply - using this option. - 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. - - - -IMPORTANT NOTE ABOUT "REIMPORT2" MODE -From version 0.8.2 QuickBMS started to implement an additional -alternative reimport mode enabled by using -r twice like: - - quickbms -w -r -r script.bms archive.pak output_folder -or - reimport2.bat - -This mode can be used with many formats and offers the following -advantages: -- no size limits with the imported files, the bigger files will be - inserted (appended) at the end of the archive -- the fields "offset", "size" and "compressed size" are rewritten by - matching the new imported file, that's useful with various - size-dependent compression algorithms like lz4 -The reimport2 method doesn't work if: -- the TOC is compressed or located on a MEMORY_FILE -- the TOC/magic is (relatively) located at the end of the archive -- the content is sequential, so there is no offset -- the 3 fields mentioned above are very different than those originally - read from the TOC, in this mode only one maximum "math" operation is - allowed on the variable which means that the following example works: - get OFFSET long ; math OFFSET * 0x800 ; log NAME OFFSET SIZE - while this example produces an incorrect OFFSET field: - get OFFSET long ; math OFFSET * 0x800 ; math OFFSET + BASE_OFF ; log NAME OFFSET SIZE - the same is valid for the size fields too, anyway note that "offset" - is rewritten only if the new file is bigger than the original -- the game strictly trusts the original size of the archive and ignores - data appended to it, for example some archives may have a field in - the TOC that specifies the size of the archive -- SLog is implemented but may not work with some archives -- the archive is subject to other limits described below, excluded the - advantages listed before - - ------------------------------------------------------------------------ - - -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. - zlib/deflate is particular slow because QuickBMS uses different - solutions to reduce the size as much as possible. - -- 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, universal 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 - -- SLog is a new command that has been recently added to QuickBMS for - dumping strings and texts, it works also in reimport mode but it's - very limited and prone to errors. I suggest to check the manual for - the SLog command (search slog in this text), but a generic universal - rule is: - - keep the length of the edited line of text the same as the original - -? 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. - -- the -Z option is a simple way to zero ALL the spaces of the archive - occupied by the original files, the result will be a sort of "empty" - archive. It "may" be useful for releasing the empty archive and the - files separately and then reinjecting them in reimport mode with the - option leaving out some unused files. Example: - - quickbms script.bms archive.ar output_folder - - quickbms -r -w -Z script.bms archive.ar output_folder - (the content of output_folder is completely ignored in -Z) - - remove videos from output_folders - - compress archive.ar and output_folder, give them to a friend - - quickbms -r -w script.bms archive.ar output_folder - - now archive.ar all the files but the videos - The behaviour of this feature may be changed in future depending by - the feedback of the users, currently there is no real usage for it. - - -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.com 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 -fields of an archive, so a field like a CRC doesn't matter while the -important fields to extract a file are ever the following: - -- 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. - From version 0.8.2 exists the -J option that considers all the - constant strings as escaped Java and C-like strings, so every string - is a cstring when you use such option - -- Both decimal and hexadecimal numbers are supported, hexadecimal is - adopted if the number starts with 0x so 1234 and 0x4d2 are the same. - -- Any operation made on fields bigger than 8 bits is controlled by the - global endianess, it means that any number and unicode field is - read in little endian by default otherwise it's valid the endianess - specified with the Endian command. - -- Comments can be used in C (// and /* */) and BMS syntax (#), for - example: - get DUMMY long # this is a comment - /* - this is a comment - */ - -- The FILENUM (file number) field in the commands is set as a constant, - it means that it cannot be modified at runtime using a variable, - examples: - get TMP string 0 # ok - get TMP string VAR # wrong - -- All the commands use variables for their arguments except those in - which it's specified that a constant number or a string (STRING) is - needed. For example the commands that use a C string (cstring) use - constant strings and not variables, except some cases like the - dictionary of ComType. - Note that this behaviour may change in future or may have been - already changed in some commands. - - -File numbers: - Every file opened in QuickBMS has a number assigned to it, if this - number is not specified it will be considered 0, the main input file. - The first opened file is the input archive to which is assigned the - number 0 (zero), the others must be opened with the Open command. - Negative numbers are considered MEMORY_FILEs, so -1 is MEMORY_FILE, - -2 MEMORY_FILE2 and so on. - -MEMORY_FILEs: - This is a particular type of temporary file which resides in memory - and works exactly like a normal temporary file. - It's extremely useful for doing many operations and you can use - multiple memory files: MEMORY_FILE, MEMORY_FILE2, MEMORY_FILE3 and so - on. - MEMORY_FILE and MEMORY_FILE1 are the same file. - . - If you need to work with chunked parts of a file to concatenate to - the memory file, you need to use the following trick: - . - putvarchr MEMORY_FILE FINAL_SIZE 0 # allocate memory internally in quickbms - log MEMORY_FILE 0 0 # create the file - . - The first instruction allocates the memory for containing the final - size of your chunks, and the second one is necessary for resetting - the memory file (current offset and size, not the allocated size). - If you need to create a MEMORY_FILE of 0x100 bytes set to zero to - use in CallDLL use the following - . - log MEMORY_FILE 0 0 # create the file - putvarchr MEMORY_FILE 0x100 0 # write 0x100+1 bytes set to zero - -TEMPORARY_FILE: - This additional file called TEMPORARY_FILE resides physically on the - target folder and has that exact name. - Although its "temporary" name, it's not deleted by the output folder - and QuickBMS will ask to remove it at the end of the extraction. - The file is created in any condition, even when it's used the -l (list) - option for listing the files, so it's perfect in certain situations - like when it's used a chunks based file system. - The difference with the MEMORY_FILE is only related to the amount of - memory available on the system because the previous file types uses - the RAM while this one uses the disk, so use it if you need to create - a temporary file bigger than 2 gigabytes. - . - For using the temporary file remember to use it like the following - example: - . - log TEMPORARY_FILE 0 0 # reset it in case it already exists (optional) - append # enables the append mode - ... - log TEMPORARY_FILE OFFSET SIZE - ... - append # disable the append mode - open "." TEMPORARY_FILE 1 # open the temporary file on the file number 1 - . - Note that from version 0.6.8, QuickBMS automatically overwrites this - file if it already exists. - - -The following is the list of types of variables supported, also know as -datatypes or types. -The list is ordered just like in defs.h: - - BYTE 8 bit, 0 to 0xff - - SHORT 16 bit (aka INT), 0 to 0xffff - - THREEBYTE 24 bit, 0 to 0xffffff - - LONG 32 bit, 0 to 0xffffffff - - LONGLONG fake 64 bit, so only 0 to 0xffffffff but Get takes 8 bytes - - STRING null delimited string (one byte for each char) - - ASIZE special type used to return the size of the opened file, - used only with the GET command - - FILENAME special type used to return the name of the opened file - like "myfile.zip", used only with the GET command - - BASENAME special type used to return the base name of the opened - file like "myfile", used only with the GET command - - FILEPATH the folder of the file, like "c:\path\folder" for - "c:\path\folder\file.txt" - - FULLBASENAME just like FULLNAME without extension - - EXTENSION special type used to return the extension of the opened - file like "zip", used only with the GET command - - UNICODE special type used for unicode utf16 strings, the - endianess of the utf16 is the same used globally in the - script (watch the Endian command), it's used also for - converting an unicode string to an ascii one: - Set ASCII_STRING UNICODE UNICODE_STRING - - unicode conversion is performed via Win32 API (CP_UTF8 - and CP_ACP in case of 0xfffd chars) while on Linux it - uses iconv, fallback on mbtowc and byte=short - - BINARY special type used for binary strings in C notation like - "\xff\x00\x12\x34", used mainly as a constant (cstring) - - LINE special type used for carriage return/line feed delimited - string (so any string ending with a 0x00, 0x0a or 0x0d), - from version 0.6 the tool supports also strings that - have no delimiter at the end of file - - FULLNAME full path of the file, in reality at the moment it returns - the same path used in the input filename - - CURRENT_FOLDER the path from which has been launched QuickBMS - - FILE_FOLDER the path of the loaded input file - - OUTPUT_FOLDER the extraction folder (the last argument of QuickBMS) - - INPUT_FOLDER same as above - - BMS_FOLDER the folder where is located the bms script - - ALLOC a type used only in the Set command for creating a variable - with a specific allocated size - - COMPRESSED a special type used for setting big strings and memory - files using a small amount of text, for using this type - you must take the original text/file, compress it with - zlib (you can use my packzip tool) and then encoding the - output file with base64 (you can use my bde64 tool) and - placing the result like the following: - set MEMORY_FILE compressed eNrtwbEJACAMBMBecIfvnMUxPuEJAe0UHN81LLzrbYKwDOjI96IN1cLveRfAGqYu - this type is very useful if you want to embed a dll inside - a script without wasting much space - - You can create this variable using the following script: - http://aluigi.org/bms/file_compressed_var.bms - - FLOAT 32 bit, 123.345 is read as 123 - - DOUBLE 64 bit, 123.345 is read as 123 - - LONGDOUBLE 96 bit, 123.345 is read as 123 - - VARIABLE read byte per byte till the byte is negative - - VARIABLE2 Unreal engine index numbers - - VARIANT VB/C++ variant type (http://en.wikipedia.org/wiki/Variant_type) - - BITS read a specific amount of bits, QuickBMS and the - language are byte based but the "bits" method works - very well - - TIME time_t Unix 32bit time - - TIME64 64bit time used as FILETIME on Windows - - CLSID ClassID like 00000000-0000-0001-0000-000000000000 - - IPV4 7f 00 00 01 = "127.0.0.1" - - IPV6 like 2001:0db8:85a3:0000:0000:8a2e:0370:7334 - - ASM x86 assembly - - VARIABLE3 used in various software - - SIGNED_BYTE 0x99 is read as 0xffffff99 - - SIGNED_SHORT 0x9999 is read as 0xffff9999 - - SIGNED_THREEBYTE - - SIGNED_LONG mainly useful in quickbms_4gb_files: - 0x99999999 is read as 0xffffffff0x99999999 - - VARIABLE4 used in Battlefield 3 (Frostbite engine) - - VARIABLE5 used in 7z archives - - UNKNOWN use it to ask the user to insert the content of the variable - - TCC a special type that compiles C text, currently experimental - and not officially supported - -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 - -QuickBMS supports also embedded text like the following: - - Set VAR string " - this is - a text with \"blah\" and 'blah' - and so on. - " - - -The following is the list of bms commands: - - -....................................................................... - -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: - -64 checks if the user is running quickbms_4gb_files.exe - -9 disable the safe memory allocator - -I makes the variables case sensitive - -. may be useful in reimport mode with data builders - -N decimal names: 00000000.dat -> 0.dat - -q quiet - -T keep the temporary file if generated - -d useful with some specific formats and scripts - -D useful with some specific formats and scripts - -e doesn't quit if compression fails - -J every string is considered a cstring (escaped string) - - Examples: - QuickBMSver 0.2.4 - QuickBMSver "0.5.14 -9" - QuickBMSver "-I -9" - - -....................................................................... - -FindLoc VAR TYPE STRING [FILENUM] [ERR_VALUE] [END_OFF] - - 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 "" - END_OFF Limit the scanning from the current offset till this - offset, if END_OFF is minor than the current offset then - the scanning will be backward - - Examples: - For - FindLoc OFFSET string "filename=" - ... - FindLoc OFFSET string "filename=" 0 "" - if OFFSET == "" - cleanexit - endif - - # scan backward - goto 0 0 SEEK_END - findloc OFFSET string "filename=" 0 "" 0 - Next - - -....................................................................... - -For [VAR] [OP] [VALUE] [COND] [VAR] -... -Next [VAR] [OP] [VALUE] - - A classical "for" cycle with initializers, conditions and - incrementers. - There is also the Break instruction available to break the cycle at - any moment and the Continue instruction for skipping the remaining - part of the cycle. - "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 cycle 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, - string, unicode and so on. - The tool automatically terminates when there is no data or partial - data to read at the end of the file. - - Arguments: - VAR Variable which will receive the read data - TYPE Check the description of the types explained before - FILENUM Number of the file associated to the archive (0) - - Examples: - Get OFFSET long - Get NAME string - - -....................................................................... - -GetDString VAR LENGTH [FILENUM] - - It reads a defined amount of data from the file and stores it in the - given variable. - It's useful with filenames and other strings that have a length - specified in a previous 8, 16 or 32 bit field. - - Arguments: - VAR Variable which will receive the read data - LENGTH Amount of bytes to read. - There is also an experimental method in which you can - specify the elements and the size of each element like - LENGTH*NUM, for example: - getdstring ARRAY NUMBERS*4 - FILENUM Number of the file associated to the 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 OFFSET - GoTo 0x100 - GoTo -4 # 4 bytes before the end of the file - GoTo SEEK_SET # like goto 0 - Goto SEEK_END # like goto 0 0 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). - - Arguments - FILENUM number of the file associated to the archive (0) - STRING string in C notation (cstring) - - Examples: - IDString "PK\x03\x04" - IDString " KAP" - IDString MEMORY_FILE "hello" - - -....................................................................... - -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 Name of the output file - OFFSET Position in the archive where is located the file - SIZE Amount of the data to extract - FILENUM Number of the file associated to the archive (0) - XSIZE Used with block encryptions, this value is the aligned - amount of data read from the disk, example for AES: - log NAME OFFSET 0x123 0 0x130 - clog NAME OFFSET 0x123 SIZE 0 0x130 - - 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 Name of the output file - OFFSET Position of the archive where is located the file - ZSIZE Size of the compressed data in the archive - SIZE Size of the uncompressed file, if you have specified - a "_compress" algorithm you can use SIZE equal to ZSIZE - because the tool will automatically calculate the - maximum amount of bytes taken for the compression - FILENUM Number of the file associated to the archive (0) - XSIZE Used with block encryptions like AES, just like Log - - 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! - For unsigned operations add an 'u' before OP. - The additional '=' you see in many scripts and in the examples is not - needed, programmers are used to add it when the first variable is both - input and output, like in C: var += 123;. - - Arguments - VAR Variable which acts as input and output - OP + sum - * multiplication - / division - - substraction - ^ xor - & and - | or - % modulus - ! negation of var2 (0 becomes 1 and any other value becomes 0) - ~ complement of var2 (like "xor 0xffffffff") - < shift left (also <<) - > shift right (also >>) - l rotate left (also <<<) - r rotate right (also >>>) - s byte swapping, 2 for reverseshort and 4 for reverselong - w bit swapping, reverse the amount of bits specified in var2 - = assign var2 to var1 - n negative value of var2 (like var1 = -var2) - a absolute value of var2 (-10 = 10 and 10 = 10) - v radix (also //) - p power (also **) - x alignment/padding, examples: - var1=0 var2=16 result=0 - var1=1 var2=16 result=16 - var1=16 var2=16 result=16 - var1=17 var2=16 result=32 - y round, like var1=(var1/var2)*var2, examples: - var1=0 var2=16 result=0 - var1=1 var2=16 result=0 - var1=16 var2=16 result=16 - var1=17 var2=16 result=16 - z common bitswapping (also <>): - var1=0xab var2=4 result=0xba - var1=0xabcd var2=4 result=0xdc - var1=0xabcd var2=8 result=0xcdab - reverselong swap of 32bit variable - reverseshort swap of 16bit variable - reverselonglong swap of 64bit variable - binary convert from binary to decimal - octal convert from octal to decimal - hex convert from hexadecimal to decimal (this is automatic, - use it only if VAR2 doesn't have a 0x prefix) - base* convert from base* to decimal, so base8 is octal, base2 - is binary, base16 is hex and so on - Add a 'u' before or after OP for forcing the usage of unsigned - operations useful with shift, divisions and possibly other - operations. - Any operation starting with a '?' will be considered a - verbose operator, for example ?add is the same of +. - QuickBMS supports also all the functions available in - math.h like ?sin, ?cos, ?atan and so on. Unfortunately it's not - possible to list them here, please check math_operations() and - old_set_math_operator() in cmd.c. - VAR Other input variable - - 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 Variable that acts as output - INSTR The full instruction - - Examples: - XMath VAR "1 + 2 - ((3 + 4) + VAR * VAR2)" - - -....................................................................... - -Open FOLDER NAME [FILENUM] [EXISTS] - - It opens a file, basically it assigns a file number/id to an existent - file that you want to use. - If NAME is '?': - - and FOLDER is FDDE the user must type the extension of the file to load, - the name is the same of the one currently open - - and FOLDER is FDSE the user must type the name of the file loaded from - the same folder - - the user must type the full name of the file to load - - 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" - - alloc: allocates memory, something like putvarchr VAR SIZE 0 - set VAR alloc 0x1234 - - filename: takes the filename part from a string (myfile.txt) - set NAME filename "c:\folder\myfile.txt" - - basename: takes the basename part from a string (myfile) - - extension: takes the extension part from a string (txt) - - unknown: the user is asked to insert the content of the variable - set VAR ? ? - - strlen: just a wrapper for the Strlen command - set NAMESZ strlen NAME - VAR 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 - considered a raw string, very useful for Long to - String conversions: - var2="0x44434241", result="ABCD" - + append, add - append the second string to the first one - - truncate, remove - if the second variable is a positive number the - string will be truncated at that amount of bytes - from the end: var1[len1 - num] = 0; - if the second variable is a negative number the - string will be truncated at that amount of bytes - from the beginning: var1[num] = 0; - otherwise will be removed all the occurrences of - the second string in the variable - ^ xor - xor the first string with the second one (looped if shorter) - < shl, shift_left - like strrchr/strrstr returning the part before it plus - the searched string: - var1="thisisastring", var2="is", result="thisis" - instead if it's a number will move the string of those - positions: - var1="thisisastring", var2="4", result="isastring" - var1="thisisastring", var2="-4", result="ring" - * mul, replicate - replicate the string for the number of times specified by the - 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 variable - just like strrchr/strrstr returning the part before - the searched string: - var1="thisisastring", var2="isa", result="this" - r reverse - reversed string, "abcd" -> "dcba" - b byte2hex - byte2hex of var2: var2="abc", result="616263" - B byte2hex_string - as above but uses the var2 as a null delimited string (strlen) - h hex2byte - hex2byte of var2: var2="616263", result="abc" - e encrypt, encryption - experimental encryption based on the Encryption command - E encrypt_string - as above but uses var2 as a null delimited string (strlen) - c compress, compression, comtype - experimental compression based on the ComType command - C compress_string - as above but uses var2 as a null delimited string (strlen) - u toupper - var2="hello", result="HELLO" - l tolower - var2="HELLO", result="hello" - R replace - replace chars: var1="helloworld", var2="world", var3="me", result="hellome" - p 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%" - P QuickBMS Print - same output of the Print command, for example: - string VAR P "hello %VAR1% test %VAR2|x%" - s sscanf - a sscanf-like experimental work-around, only for numeric 32bit values - string "123:456" s "%d:%d" VAR1 VAR2 - S split - it's like a sscanf for strings, both ' and " are handled as - quotes. - string ELEMENTS S "string1 \"string 2\" 'string3'" VAR1 VAR2 VAR3 - x cstring - convert a C string (cstring) to the relative string/binary - string VAR x \x78\x7a - f filter - filter the non alphanumeric chars by replacing them with '_' - m math, xmath - math and xmath operation just like those in the Encryption command - so #INPUT#+1 means that 0x01 will be added to each char of VAR - quick example: string VAR m "#INPUT#+1" # xmath if there is INPUT - string VAR m "+ 1" # math - w hex2uri - var2="%2fhello", result="/hello" - W uri2hex - var2="hello<>", result="hello%3c%3e" - t very basic html/xml tags remover, de_html - T html/xml formatter, one tag or text per line, easy_html - _ trim, removes spaces from the beginning and end of the string - J JSON formatter - X experimental parser for XML, JSON and other types of formats: - https://zenhax.com/viewtopic.php?t=4887&p=26349#p26349 - v CSV with allowed custom separators like "," or ",|;" - string ELEMENTS v "arg1,arg2, arg 3 , arg4" "," ARG1 ARG2 ARG3 ARG4 - Use an additional zero ("0") to return "" in case of errors like when - the operators that search strings can't find the pattern (in which case - will be returned the original string by default), this is very useful - while playing with strings, for example - "string VAR1 0strchr VAR2" will return "" if VAR2 is not found in VAR1 - (instead of leaving VAR1 unchanged), another example: String VAR1 0$ VAR2 - VAR The second variable or string - - 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 # VAR1/2 are the input - string FULLPATH s "c:\folder\%04x%04x.dat" VAR1 VAR2 # VAR1/2 are the 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 - > major, greater, above - != different, <> !== - == equal, = === strcmp stricmp strcasecmp - >= major/equal - <= minor/equal - & string: var2 is included in var1 (strstr) - number: logical AND - ^ string: equal - number: logical XOR - | number: logical OR - % number: modulus - / number: division - << number: shift left - >> number: shift right - ! number: negation, not - !! number: true, use it to know if VAR is non-zero - ~ number: complement - strncmp if "mystring" strncmp "myst" - ext compares the string after the last dot - basename compares the string before the last dot - filepath compares the part before the filenames, you - can force a folder without filename by appending - a slash: "c:\folder/" instead of "c:\folder" (that will be "c:") - any other operation supported by the Math command (valid - only for the numeric variables) - add a 'u' before COND for forcing the usage of unsigned - operations useful with shift, divisions and possibly other - operations, if the variables are strings then it will - perform an case sensitive comparison instead of the default - insensitive one - VAR Second part of the condition - - 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 Output variable - TYPE Only unicode is the alternative type, any other value - is just ignored because doesn't matter for this - operation - CHAR 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 Number of the file associated to the archive (0) - - 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/brute-forcer able - to guess the possible algorithm of an unknown raw compressed data - block by simply trying every decompressor on the input (do NOT use - it if you don't know what you are doing! this is NOT offzip!): - 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 customizations - like -1 for Tales of Vesperia - the default character of lzss is a space (0x20), but you can use 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 to 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 xcompress.lib - use DICT to specify a custom WindowSize and CompressionPartitionSize - like "131072 524288" - the algorithm automatically idenfities and extracts the LZXTDECODE - 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 Tales - darksector, a very basic algorithm used in the game Dark Sector - mszh, used in the LossLess Codec Library - un49g, used in the games of 49Games - unthandor, used in the old game Thandor - doomhuff, huffman used in doom, hexen, skulltag and other doom ports - the DICT field can be used to specify a custom HuffFreq table (256 float elements) - aplib - tzar_lzss, used in Tzar of HaemimontGames - DICT must contain the name of the variable with the algorithm - number to use, example: ComType tzar_lzss MYVAR - lzf, aka fastlz - clz77, the lz77 algorithm available on http://compressions.sourceforge.net/about.html - lzrw1 - dhuff, Huffman Decompression in LDS ("lossless datacompression sources" kit 1.1) - fin, from LDS - lzah (not tested) - lzh12, aka -lh4- - lzh13, aka -lh5- - grzip, aka GRZipII - ckrle, Chilkat RLE - quad, note that I removed the handling of the first 32bit number - containing the size of the uncompressed data - balz, note that I removed the handling of the first 9 bytes from - the files that contains ID and 64bit uncompressed size - deflate64 - shrink (not tested) - z-base-32 - base32hex - base32crockford - base32nintendo - base???, if ALGO starts with "base" then will be taken its - subsequent number (for example 32 if it's "base32") and - used for the conversion. the function supports ANY base - conversion from 2 to 256. - for bases larger than 64 will be used a char table starting - from byte 0x00 so base128 will have a charset from 0 to 0x7f - brieflz - paq6, raw data block - shcodec - hstest_hs_unpack (never tested, could be removed in future) - hstest_unpackc (never tested, could be removed in future) - sixpack (never tested) - ashford (never tested, could be removed in future) - jcalg - jam - lzhlib - srank - zzip - scpack - DICT supported (for the SCPACK_TABLE field) - rle3 - bpe2 - bcl_huf, Basic Compression Library - bcl_lz, Basic Compression Library - bcl_rice, Basic Compression Library - you must use DICT to specify the format (1 to 8) - bcl_rle, Basic Compression Library - bcl_sf, Basic Compression Library - scz - szip - ppmd, ppmd var.i rev.1 with ZIP specifics so 2 bytes of info followed by the compressed data - ppmdi_raw - ppmdg - ppmdg_raw, requires DICT "SASize MaxOrder" - ppmdh - ppmdh_raw, requires DICT "SASize MaxOrder" - ppmdj - ppmdj_raw, requires DICT "SASize MaxOrder CutOff" - sr3c - huffmanlib - sfastpacker, smart+simple mode - sfastpacker2, smart-mode only - dk2, RefPack used in Dungeon Keeper 2 and other Bullfrog/EA games - lz77wii, (use input size as output size in clog) - lz77wii_raw10, tag 0x10 lz77 - darkstone, lz77 compression used in the game DarkStone - sfl_block_chunked, as sfl_block with automatic handling of - the chunks if used - yuke_bpe, used in the PS2 games developed by Yuke - stalker_lza, used in STALKER, use the output size equal to - the compressed one (it's handled internally) - prs_8ing - puyo_cnx, raw compressed data from offset 0x10 - puyo_cxlz, raw compressed data from offset 0x8 - puyo_lz00, raw compressed data from offset 0x32 - puyo_lz01, raw compressed data from offset 0x10 - puyo_lzss, raw compressed data from offset 0x4 - puyo_onz, raw compressed data from offset 0x4 - puyo_prs - falcom - cpk, used by the CRI developers (LAYLA) - bzip2_file, exactly like bzip2 but it automatically calculates - the output size, so use ZSIZE ZSIZE in clog - lz77wii_raw11, tag 0x11 lzss - lz77wii_raw20, tag 0x20 huffman (not supported at the moment) - lz77wii_raw30, tag 0x30 rle - lz77wii_raw40 - pglz, postgresql compression (headerless) - UnPackSLZ - slz_01, used in tri-ace slz type 1 - slz_02, used in tri-ace slz type 2 - slz_03, used in tri-ace slz type 2 - lzhl - d3101 - squeeze - lzrw3 - tdcb_ahuff - tdcb_arith - tdcb_arith1 - tdcb_arith1e - tdcb_arithn - tdcb_compand - tdcb_huff - tdcb_lzss, dict for INDEX_BIT_COUNT, LENGTH_BIT_COUNT, DUMMY9, END_OF_STREAM - 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 or - 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%" - clog "output.dat" 0 ZSIZE ZSIZE # SIZE is not needed - CALLDLL: - exactly as above but allows to specify a calldll command - executed on input: "#INPUT#", "#INPUT_SIZE#", "#OUTPUT#", - "#OUTPUT_SIZE#" and %VAR%. - experimental - lz77_0 - lzbss - bpaq0 - lzpx, lzpxj - mar_rle - gdcm_rle - dict - rep - lzp (it's a preprocessor and not a real compression) - elias_delta - elias_gamma - elias_omega - packbits - darksector_nochunks, aka lzf or lzfx - enet - eduke32, lzwuncompress - xu4_rle - rvl, lemur int compression - lzfu, MS RTF - lzfu_raw - xu4_lzw, Ultima 4 - he3, without the HE3\x0d signature and output size - iris, Ultima Online algorithms - iris_huffman - iris_uo_huffman - ntfs - pdb - COMPRLIB_SPREAD - COMPRLIB_RLE1 - COMPRLIB_RLE2 - COMPRLIB_RLE3 - COMPRLIB_RLE4 - COMPRLIB_ARITH - COMPRLIB_SPLAY - cabextract, it may be the same lzx of mspack - mrci - hd2_01 - hd2_08 - hd2_01raw - rtl_lznt1 - rtl_xpress, looks not supported by XP/7 - rtl_xpress_huff, looks not supported by XP/7 - prs - sega_lz77 - saint_seya, used for GMI compression - ntcompress30 - ntcompress40 - yakuza, used by SEGA CS1 team - lz4 (the algorithm of lz4hc is the same) - snappy - lunar_lz1 to lz19 - lunar_rle1 to rle4 - goldensun - luminousarc - lzv1 - fastlzah, it should be identical to lzf and lzfx - 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, aka lzf or lzfx - puyo_lz10 - puyo_lz11 - nislzs - 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_bpe - 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 file - CT_HughesTransform - CT_LZ77 - CT_ELSCoder - CT_RefPack - qfs, same as dk2 - PXP - BOH - GRC - ZEN - LZHUFXR - FSE - FSE_RLE - ZSTD, automatically supports all the legacy algorithms - 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 - 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 - 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 it doesn't work at 100% - 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 - LZ5 - LZ5F - YALZ77 - LZKN1 - LZKN2 - LZKN3 - TFLZSS - SYNLZ1 - SYNLZ1b - SYNLZ1partial - SYNLZ2 - PPMZ2 - OPENDARK - DSLZSS - KOF, not working at 100% - KOF1, not working at 100% - RFPK - WP16 - LZ4_STREAM - OODLE - OODLE_LZH - OODLE_LZHLW - OODLE_LZNIB - OODLE_LZB16 - OODLE_LZBLW - OODLE_LZNA - OODLE_BitKnit - OODLE_LZA - OODLE_LZQ1, OODLE_kraken - OODLE_LZNIB2, OODLE_Mermaid - SEGS - OODLE_Selkie - OODLE_Akkorokamui - ALZ - REVELATION_ONLINE - ps_lz77 - lzfse - zle - KOF2, not working at 100% - KOF3, not working at 100% - HSQ - FACT5LZ - LZCAPTSU - TF3_RLE - WINIMPLODE - DZIP - DZIP_COMBUF, this is just a placeholder, doesn't really work - LBALZSS1X, the first implementation of LBALZSS1 (then fixed) - LBALZSS2X, the first implementation of LBALZSS2 (then fixed) - GHIREN - FALCOM_DIN, automatically parses the chunks - FALCOM_DIN1, just input->output - FALCOM_DIN0, mode 0 - FALCOM_DINX, mode X - GLZA - M99CODER - LZ4X - TAIKO - LZ77EA_970 - DRV3_SRD - RECET - LIZARD, it's just the new name/version of LZ5 - MICROVISION - DR12AE - MSPACK, requires parameters - KONAMIAC - WOLF0, just WOLF without header - ARTSTATION - LEVEL5 - ZENPXP, dict must contain 0, 1, 2, 3, 4, 0xd, 0xe or others supported - ZENPXP1, raw algo 1 of zenpxp - ZENPXP2, raw algo 2 of zenpxp - ZENPXP34, raw algo 3,4 of zenpxp - ZENPXPde, raw algo d,e of zenpxp - liblzs - SHREK - EA_MADDEN - - -------------------------------- - --- 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, only the current algorithm, no legacy - 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 - reimport mode changes only the data of the files). - if you want it to work you have to manually edit the - value from the archive, launch quickbms -V and search - something like the following: - . 00000eef get value 0x0000e548 4 - . 00000023 get column_name "FileSize" -1 - in that example you have to set the new value at - offset 0xeef, but note that the new compressed size - is not displayed by quickbms... yeah not easy - LZRW1KH_COMPRESS - BPE_COMPRESS - NRV2b_COMPRESS - NRV2d_COMPRESS - NRV2e_COMPRESS - LZSS0_COMPRESS - CLZW_COMPRESS - QUICKLZ_COMPRESS - ZOPFLI_ZLIB_COMPRESS - ZOPFLI_DEFLATE_COMPRESS - PKWARE_DCL_COMPRESS - LZ5_COMPRESS - YALZ77_COMPRESS - SYNLZ1_COMPRESS - SYNLZ2_COMPRESS - PPMZ2_COMPRESS - EA_JDLZ_COMPRESS - OODLE_COMPRESS - LZFSE_COMPRESS - M99CODER_COMPRESS - LZ4X_COMPRESS - YUKE_BPE_COMPRESS - LZO1A_COMPRESS - LZO1B_COMPRESS - LZO1C_COMPRESS - LZO1F_COMPRESS - LZO1Y_COMPRESS - LZO1Z_COMPRESS - LIZARD_COMPRESS - LIBLZS_COMPRESS - - *note: - you can find the updated list in the COMP_ enumeration - inside defs.h, they have also a number on their right - that is used to find the algorithm when using my - compressions scanner - - DICT an optional C string containing the bytes of the dictionary - (cstring) or particular parameters depending by the chosen - algorithm. - Note that DICT can be: - - a cstring - comtype algo "\x11\x22\x33" // static binary dictionary - - a variable for which, often, you must specify also a length - comtype algo DICT DICT_SIZE // variable dictionary - - -....................................................................... - -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 - endian set CURRENT_ENDIAN - - -....................................................................... - -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 - - Watch the previous arguments and examples. - - -....................................................................... - -FileCrypt SEQ [OFFSET] - - Experimental, it works only if has been already specified and - enabled the Encryption command and basically applies those - algorithms to the normal file reading operations. - Note that at the moment OFFSET is unused and SEQ can be only 1 for - activating it and "" to disable it ("" and NOT 0!). - Remember that the encryption algorithms usually work on blocks of - data so this command is probably useless. - - Full example: - get NAMESZ long - encryption xor "\x11\x22\x33\x44" - filecrypt 1 - getdstring NAME NAMESZ - filecrypt "" - encryption "" "" - - -....................................................................... - -Strlen VAR VAR [SIZE] - - It calculates the length of the second variable (as string) and - stores it in the first one. - The length is the amount of consecutive non-zero bytes, so it - doesn't work with unicode strings except if, maybe, SIZE is set. - Note that for practical reasons this command can be emulated also - using "set VAR strlen VAR". - - arguments - VAR Destination variable which will contain the length - VAR Variable of which calculating the length - SIZE set it to 1 to receive the size of the variable instead - of its NULL delimited lenght, may be useful in some - situations where you need to ignore the 0x00 bytes - - 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 Variable or memory file in which you want to put the - element - OFFSET Position of the output where placing the element, it can - be also negative in which case it will work from the end - of the variable (may not work in some conditions) - VAR Source variable which will contain the element to write, - it's also possible to store the address of the variable - which is sometimes useful with external DLLs - 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 - Math TMP ^= 0xff - PutVarChr MEMORY_FILE i TMP - Next i - - -....................................................................... - -Debug [MODE] - - Switch command that enables the -v option in real-time for a - specific portion of the script, used only for debugging. - - If MODE is specified and it's a positive number, QuickBMS will only - display the content of the variables read/written with the Get/Put - commands. This is very useful and cool for debugging file formats - and protocols in an easy way just like -V. - - If MODE is negative, it will disable the verbose mode. - - Examples: - debug # like -v - debug 0 # like -v - debug 1 # like -V - debug -1 # 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 - will be appended to the new one - 0 the new content will be appended to the current one - (default, just like without DIRECTION) - 1 the new content will overwrite the current one without - changing the file size if the new one is smaller, use - goto to set the offset where placing the new content - - 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), cycles and if_invert_delta_operation - xtea, use IVEC to specify custom delta, endian (0/1), cycles and if_invert_delta_operation - xxtea, use IVEC to specify custom delta, endian (0/1), cycles and if_invert_delta_operation - idea - swap, use the bytes to swap as key, it works just like - reverseshort and reverselong: encryption swap 2: 2211 -> 1122 - reverseshort, swap 2 - reverselong, swap 4 - math, exactly like the bms command plus the size of the numbers: - encryption math "^u= 0x11223344 1" 32 - encryption math "n #INPUT#" # decrypted = -encrypted - it means that this encryption can do tons of operations - including xor, rot, rotate and so on. - the "1" after the math operation means if we want to - respect the exact size of each element like a sort of - AND SIZE (default ignore). - ivec is the size of each element (8 bits default) - xmath, key is the operation to perform for each element - ivec is the size of each element (8 bits default) - use #INPUT# to identify the element read from the data: - encryption xmath "((#INPUT# + 1) << 2) + #INPUT#" 8 - random, pseudo random incrementer (Linear congruential - generator) xored with the input key contains a number - corresponding to the algorithms listed on - http://en.wikipedia.org/wiki/Linear%5Fcongruential%5Fgenerator#Parameters_in_common_use - (0 is the first one) plus other algorithms like - mersenne and so on. - the second parameter in the key is the seed. - the third one is the mask of bits of the key to use for - the operation. - ivec is the size of each element (8 bits default). - encryption random "0 0x12345678" - encryption random "0 0x12345678" 32 # 32bit values - encryption random "0 0x12345678 0x7fff0000" # value ^ ((key >> 16) & 0x7fff) - you must check the src\myenc.c source code to have the full list - xor - rot - rotate, an 8/16/32/64bit ror or any other bit as key, element size as ivec - reverse, flip the file from the end to the beginning - flip, flip the bits of the input file, reverse flip 8 - incremental, - encryption "incremental xor" 0 0x01 # 8bit xor incremented by 1 each time - encryption "incremental rot" 0x100 0x11223344 # 32bit rot starting from 0x100 incremented - # by 0x11223344 each time - charset, the substitution algorithm which uses a charset of 256 chars - charset2, as above but the substitution is inverted, very useful - twofish - cast5 - seed - serpent - ice - icecrypt, ICE algorithm with key implemented as in the - homonym program, the difference with "ice" is ONLY in - the key - rotor, added as experiment, ivec contains the number of - rotors (12) - ssc, Leverage SSC - wincrypt, aka cryptdecrypt or cryptencrypt - use the ivec field to specify the following fields - (only those you need, not all are necessary): - - the hashing algorithm - CryptCreateHash, you can find the key here - - the encryption algorithm - CryptDeriveKey - - the provider type - CryptAcquireContext - - Microsoft provider name, like MS_DEF_DH_SCHANNEL_PROV - - CryptDeriveKey flags, like CRYPT_CREATE_SALT - - CryptDecrypt flags, like CRYPT_OAEP - example: - encryption CryptDecrypt "mykey" "CALG_MD5 CALG_RC4 PROV_RSA_FULL" - encryption CryptDecrypt "1111" "CALG_MD5 CALG_RC4 PROV_RSA_FULL CRYPT_CREATE_SALT CRYPT_OAEP" - cryptunprotect, key is used to specify the entropy so the default is "" - zipcrypto, the first 12 bytes are the encryption header - set the ivec to 1 for automatically cutting the first 12 bytes - md_null, from OpenSSL (does nothing) - md2, from OpenSSL (not available) - md4, from OpenSSL - md5, from OpenSSL - sha, from OpenSSL - sha1, from OpenSSL - dss, from OpenSSL - dss1, from OpenSSL - ecdsa, from OpenSSL - sha224, from OpenSSL - sha256, from OpenSSL - sha384, from OpenSSL - sha512, from OpenSSL - mdc2, from OpenSSL - ripemd160, from OpenSSL - whirlpool, from OpenSSL - hmac ..., hmac plus an OpenSSL hash algorithm, it's an - encrypted hash so you must provide a key. example for - a hmac sha1 on the fly: - encryption "hmac sha1" "mykey" "mydata" - or - encryption "hmac sha1" "mykey" - log MEMORY_FILE 0 SIZE - print "%QUICKBMS_HEXHASH%" - enc_null, from OpenSSL (does nothing) - des_ecb, from OpenSSL - des_ede, from OpenSSL - des_ede3, from OpenSSL - des_ede_ecb, from OpenSSL - des_ede3_ecb, from OpenSSL - des_cfb64, from OpenSSL - des_cfb1, from OpenSSL - des_cfb8, from OpenSSL - des_ede_cfb64, from OpenSSL - des_ede_cfb1, from OpenSSL - des_ede_cfb8, from OpenSSL - des_ede3_cfb64, from OpenSSL - des_ede3_cfb1, from OpenSSL - des_ede3_cfb8, from OpenSSL - des_ofb, from OpenSSL - des_ede_ofb, from OpenSSL - des_ede3_ofb, from OpenSSL - des_cbc, from OpenSSL - des_ede_cbc, from OpenSSL - des_ede3_cbc, from OpenSSL - desx_cbc, from OpenSSL - dev_crypto_des_ede3_cbc, from OpenSSL - dev_crypto_rc4, from OpenSSL - dev_crypto_md5, from OpenSSL - rc4, from OpenSSL - rc4_40, from OpenSSL - idea_ecb, from OpenSSL - idea_cfb64, from OpenSSL - idea_ofb, from OpenSSL - idea_cbc, from OpenSSL - rc2_ecb, from OpenSSL - rc2_cbc, from OpenSSL - rc2_40_cbc, from OpenSSL - rc2_64_cbc, from OpenSSL - rc2_cfb64, from OpenSSL - rc2_ofb, from OpenSSL - bf_ecb, from OpenSSL (bf stands for blowfish) - the result is different than the "blowfish" type because - the other one uses big endian fields, try both - bf_cbc, from OpenSSL - bf_cfb64, from OpenSSL - bf_ofb, from OpenSSL - cast5_ecb, from OpenSSL - cast5_cbc, from OpenSSL - cast5_cfb64, from OpenSSL - cast5_ofb, from OpenSSL - rc5_32_12_16_cbc, from OpenSSL (not available) - rc5_32_12_16_ecb, from OpenSSL (not available) - rc5_32_12_16_cfb64, from OpenSSL (not available) - rc5_32_12_16_ofb, from OpenSSL (not available) - aes_128_ecb, from OpenSSL - aes_128_cbc, from OpenSSL - aes_128_cfb1, from OpenSSL - aes_128_cfb8, from OpenSSL - aes_128_cfb128, from OpenSSL - aes_128_ofb, from OpenSSL - aes_128_ctr, from OpenSSL - aes_192_ecb, from OpenSSL - aes_192_cbc, from OpenSSL - aes_192_cfb1, from OpenSSL - aes_192_cfb8, from OpenSSL - aes_192_cfb128, from OpenSSL - aes_192_ofb, from OpenSSL - aes_192_ctr, from OpenSSL - aes_256_ecb, from OpenSSL - aes_256_cbc, from OpenSSL - aes_256_cfb1, from OpenSSL - aes_256_cfb8, from OpenSSL - aes_256_cfb128, from OpenSSL - aes_256_ofb, from OpenSSL - aes_256_ctr, from OpenSSL - camellia_128_ecb, from OpenSSL - camellia_128_cbc, from OpenSSL - camellia_128_cfb1, from OpenSSL - camellia_128_cfb8, from OpenSSL - camellia_128_cfb128, from OpenSSL - camellia_128_ofb, from OpenSSL - camellia_192_ecb, from OpenSSL - camellia_192_cbc, from OpenSSL - camellia_192_cfb1, from OpenSSL - camellia_192_cfb8, from OpenSSL - camellia_192_cfb128, from OpenSSL - camellia_192_ofb, from OpenSSL - camellia_256_ecb, from OpenSSL - camellia_256_cbc, from OpenSSL - camellia_256_cfb1, from OpenSSL - camellia_256_cfb8, from OpenSSL - camellia_256_cfb128, from OpenSSL - camellia_256_ofb, from OpenSSL - seed_ecb, from OpenSSL - seed_cbc, from OpenSSL - seed_cfb128, from OpenSSL - seed_ofb, from OpenSSL - mcrypt blowfish - mcrypt des - mcrypt tripledes - mcrypt threeway - mcrypt gost - mcrypt safer-sk64 - mcrypt safer-sk128 - mcrypt cast-128 - mcrypt xtea - mcrypt rc2 - mcrypt twofish - mcrypt cast-256 - mcrypt saferplus - mcrypt loki97 - mcrypt serpent - mcrypt rijndael-128 - mcrypt rijndael-192 - mcrypt rijndael-256 - mcrypt enigma - mcrypt arcfour - mcrypt wake - note that for the algorithms supported by mcrypt you - can force their loading by preceeding ALGO with "mcrypt" - like "mcrypt_enigma" and you can decide also their mode - like "mcrypt_enigma_ecb" or "mcrypt_enigma_cbc", list: - cbc, ecb, cfb, ofb and nofb - 3way - skipjack - anubis - aria - crypton - frog - gost - lucifer - mars - misty1 - noekeon - seal - safer - kirk, used in PSP eboot encryption, use the ivec to specify - the keys/encryption (default is 1, refer to libkirk for - more information) - pc1, automatic 128/256 bit selection based on key length - blake224 - blake256 - blake384 - blake512 - bmw224 - bmw256 - bmw384 - bmw512 - cubehash224 - cubehash256 - cubehash384 - cubehash512 - echo224 - echo256 - echo384 - echo512 - fugue224 - fugue256 - fugue384 - fugue512 - groestl224 - groestl256 - groestl384 - groestl512 - hamsi224 - hamsi256 - hamsi384 - hamsi512 - haval128_3 - haval128_4 - haval128_5 - haval160_3 - haval160_4 - haval160_5 - haval192_3 - haval192_4 - haval192_5 - haval224_3 - haval224_4 - haval224_5 - haval256_3 - haval256_4 - haval256_5 - jh224 - jh256 - jh384 - jh512 - keccak224 - keccak256 - keccak384 - keccak512 - luffa224 - luffa256 - luffa384 - luffa512 - md2 - md4 - md5 - panama - 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] use key + or - to use operations - different than xor and the 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 (aka gladman cwc) - 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 - isaac - isaac_vernam - isaac_caesar - hsel - tomcrypt - modes: ecb, cfb, ofb, cbc, ctr, lrw, f8, xts, hmac, omac, pmac, - eax, ocb3, ocb, ccm, gcm, pelican, xcbc, f9, - 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-224, - 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 0x77073096) - - ivec contains: - - the size of the crc (8/16/32/64) - - 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 - for additional info: - http://aluigi.org/bms/quickbms_crc_engine.txt - for technical information about the operations check the - crc_calc function in crc.c, it's quite easy to understand - because it contains the simple operations performed in - each cycle. - note that some crc types use the polynomial value as - constant in each cycle - crc64 and 64bit crc work with quickbms_4gb_files.exe only - EXECUTE: - use KEY to specify the command to execute using #INPUT# - instead of the input filename and #OUTPUT# for the output - one, you can also specify a variable by using the %VAR% - notation. - IMPORTANT NOTE: do NOT use "encryption execute" if the - output will be bigger than the input, use Clog in that case! - example: - encryption EXECUTE "mycrypt.exe d #INPUT# #OUTPUT#" - another full example: - get SIZE asize - encryption EXECUTE "lame.exe -V 4 #INPUT# #OUTPUT#" - log "newfile.mp3" 0 SIZE - encryption EXECUTE "otherprog.exe #INPUT# #OUTPUT# %SIZE%" - log "newfile2.mp3" 0 SIZE - CALLDLL: - exactly as above except that the variables don't need to be - specified within '%' because calldll already handles them, - but don't worry because even if you do that the result - should not change, experimental: - encryption calldll "test.dll myfunction cdecl RET #INPUT# #INPUT_SIZE# MYVAR" - get SIZE asize - log "newfile.mp3" 0 SIZE - "" "", disable the encryption - KEY The key to use in C notation like "\x11\x22\x33\x44" or - "this is my key" (cstring) - This value can be also a variable or a memory file - set ALGO and KEY to "" for disabling the encryption - IVEC The ivec to use in C notation (cstring), an ivec is an - additional key used for increasing the security of - encryption algorithms that are usually defined as ECB - without ivec and CBC (and other names) with ivec - MODE 0 for decryption (default), 1 for forcing the encryption mode - if no ivec is used remember to place a "" at its place - KEYLEN Forces the usage of a certain length of the key, this one - has been introduced only for avoiding the problem of using - a variable as KEY containing zeroes in it and for the - non-block ciphers when you use KEY as a variable in which - a certain length is used and not strlen - - Examples: - Encryption aes "0123456789abcdef" "" 1 # encryption without ivec - Log MEMORY_FILE 0 SIZE - Encryption aes "0123456789abcdef" # decryption without ivec - Log "redecrypted_file.dat" 0 SIZE MEMORY_FILE - Encryption aes "\x12\x34\x56\x78" - set MEMORY_FILE binary "\x12\x34\x56\x78" - Encryption aes MEMORY_FILE - Encryption aes MY_VARIABLE - Encryption md5 "" - - -....................................................................... - -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 "this is the first line\nthis is the second line\n" - print "variable %VAR% and %VAR2%" - print "variable %VAR|h% and %VAR2|hex%" - print "variable %VAR|3% and %VAR2|4%" - print "variable %VAR|3h% and %VAR2|h4%" - print "variable %VAR|dump16%" - print "variable %VAR|dumpVARSZ%" - - -....................................................................... - -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 - - -....................................................................... - -SortArray ARRAY [ALL] - - Experimental sorting of the arrays in ascending order (like 0 to 99) - based on the values in ARRAY. - If ALL is a number different than zero, the sorting will affect ALL - the available arrays created till that moment, which means that - their positions will match those of the sorted array, so if the - array 0 was "1" "3" "2" and array 1 "hello" "test" "bye", with ALL - set to 1 you will have 1 2 3 and "hello" "bye" "test". - From QuickBMS 0.7.7 the sorting is unsigned, so -1 is handled as - 0xffffffff, the highest element of the array. - - Examples: - putarray 0 0 "zzz" - putarray 0 1 "aaa" - putarray 0 2 "bbb" - sortarray 0 - for i = 0 < 3 - getarray TMP 0 i - print "%TMP%" - next i - - -....................................................................... - -CallFunction NAME [KEEP_VAR] [ARG1] [ARG2] ... [ARGn] -StartFunction NAME -... -EndFunction - - Calling and declaration of a function identified by NAME where the - values of the variables are backed up till the termination of the - function when they are restored. - It works very well for recursive/nested archives like those used by - "The Void" and "Another Day". - If KEEP_VAR is not specified or zero, QuickBMS will make a backup - of the current values and the function will work on a copy, when - the function terminates the variables will be restored to their - backup. - If KEEP_VAR is set to 1, there will be no backup and any change - made in the function will remain when it terminates. - Do not use KEEP_VAR if you are working on a nested/recursive file - table, use it to 1 if you are creating a macro or a function - called many times to perform a task. - It's a good idea to place all the functions (from StartFunction - till EndFunction) at the end of the scripts. - It's also possible to pass optional arguments to the function, they - will have the name of the function plus ARGnumber, for example: - MYFUNCTION_ARG1 amd MYFUNCTION_ARG2. - Doesn't exist a return value at the moment but it's possible to - do it in other ways like saving the value in an array or on a - MEMORY_FILE. - - Arguments: - NAME Name assigned to the function - KEEP_VAR Set to 1 if you want to keep the content of the variables - without resetting them, in short words: - 0 = for recursive functions (default) - 1 = for normal functions that change variables, - this is faster and suggested in most cases - ARGs Arguments, they are seen inside the function as - "name of the function" + ARG + argument_number - - 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=size - heap:// every single allocated heap (slow!): NAME=address 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 - decompression/decryption functions located in executables and DLLs - avoiding the boring reverse engineering of all the functions. - It works with both real files and MEMORY_FILEs (even if they contain - dll data!). - Unfortunately this is not much possible with the functions got from - executables where are used static variables due to some technical - reasons, in fact it's not possible to relocate them in memory. - For example if the function uses the memory between 006c0000 and - 006d0000 it's highly possible that such range of memory is not - allocated or is already in use because the executable has not been - loaded (LoadLibrary) in its original address, that space is already - occupied. - There are no problems with the DLLs, they are made to be relocated. - You can even use a dll inside a MEMORY_FILE but be sure it's not - packed because it may not work. - And it's also possible to use a raw data containing maching - instructions, basically you can dump a function "as is" and putting - it in a MEMORY_FILE. - That means that the following situations are OK: - - raw dumped functions without references to API or static memory - - DLLs - - "maybe" some executables loaded as DLLs - - Arguments: - DLLNAME Name of the dll, executable, file or MEMORY_FILE where - is located the function, example "mylib.dll" - FUNC/OFF It can be the name of the function to import in which - case it must be exported by the dll/exe with a name - (pay attention to mangled names!) - Or the relative offset where is located the function, - remember that the relative offset is NOT the absolute - one but it's the offset related to the image base of - the exe/dll, so if normally the dll loads at offset - 10000000 and the function is at 10012345 then the - offset is 0x12345 - CONV Calling convention, please refer to calling_convention.h: - usercall: allows to set all the 6 x86 registers, any - argument after 6th will be pushed on the stack - cdecl: used by default in many C/C++ compiler - stdcall: aka winapi, used by default in Visual C - thiscall - msfastcall: Microsoft fastcall - fastcall: native fastcall - borland: the fastcall convention used by the Borland - compilers like Delphi - pascal - watcom - safecall - syscall - optlink - carion - tcc: use this type to compile the text of the input - memory file like a C source code - imagebase: returns the address where the code/dll is loaded - address: returns the address of the function in memory - RET The variable which will contain the value returned by - the function, use "" if there is no return value. - If you use *RET or &RET then the return value will be - copied in the RET variable as a string - [ARGS] All the arguments of the function, it's also possible - to use pointers to arguments if they are preceded by a - & or a * like &SIZE which means that the dll/code - receives the address of that variable and can modify - its content. It works only with numeric variables - - 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 SIZE - log "dump.dat" 0 SIZE MEMORY_FILE2 - - set MEMORY_FILE binary " - int foo(int n) - { - return n * 1234; - }; - " - calldll MEMORY_FILE "foo" "tcc" RET 100 - - -....................................................................... - -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 Destination variable that will contain the filename or - just a "" in case no name has been found (it will use - a particular variable called QUICKBMS_FILENAME). - If VAR is "" then you can use *log "" and the retrieved - filename will be automatically applied to the output - file. This behaviour has been thought to write scripts - easily without providing a NAME variable. - CRC This is the CRC field read from the file. - It must be a HEXADECIMAL value, decimal are no longer - supported by default. - Remember that quickbms.exe reads longlong as a 32bit - field, you must use quickbms_4gb_files.exe to read real - 64bit fields. - If necessary, in future will be supported also hash - algorithms. - LISTF The name of the file that contains the filenames, each - name must be on a new line. - QuickBMS automatically recognize if the entry is just - the name or contains also a pre-calculated crc, for - example: - path\folder\file.txt - 0x11223344 path\folder\file.txt - 287454020 path\folder\file.txt - # path\folder\file.txt - The list file will be automatically searched and loaded - from the input and output folders, till it's found. - The filenames located after a comment are good to use - the same bms script as a file list. - You can also specify a memory file, useful if you have - set it as compressed, set MEMORY_FILE10 compressed "..." - TYPE Currently only CRC is supported: - crc32 (default), crc8, crc16 and crc64 - POLY The polynomial value used to calculate the CRC tables - PARAM Both POLY and PARAM work in the same way you can set - the CRC in the Encryption command through KEY and IVEC, - so refer to that command for additional information and - example. - Anyway PARAM contains: - BITS, INIT, FINAL, TYPE, REVER and BITMASK_SIDE - If you are a developer and wants to have a full - understanding of what you can customize, please check - the crc_calc function in crc.c, it's very simple and - self explanatory. - - -....................................................................... - -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 the codepage, like utf8 or 950 and so on. - - Example for converting a string from JIS (932) to UTF8: - get NAME string # read it as a sequence of bytes - codepage 932 - set NAME to_unicode NAME # jis -> utf16 (unicode) - codepage "utf8" - set NAME unicode NAME # utf16 -> utf8 - - -....................................................................... - -SLog NAME OFFSET SIZE [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 - slog STRINGS_FILE -1 -1 long - endian big - #slog STRINGS_FILE -1 -1 unicode - slog STRINGS_FILE -1 0x18 unicode - slog STRINGS_FILE 0x2e -1 - - -....................................................................... - -NAME: # it works like the labels in C -Label NAME # it works like the labels in C -Break # used in cycles -Break NAME # it works like goto in C -Continue # used in cycles -Continue NAME # it works like goto in C - - Example: - print "000" - test: - print "AAA" - continue test2 - print "BBB" - label test2 # "test2:" or "label test2" is the same - print "CCC" - continue test - -....................................................................... - -QuickBMS can handle also some minimalistic and experimental C -structures like: - - debug 1 # needed to show the collected information - struct test { - int var1; - char var2; - char *mystring; - uint8_t data[10]; - } - -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 var1 = 0x11111111; - char var2 = 0x22; - char *mystring = "hello"; - uint8_t data[10] = OTHER_VAR; - } - -Maybe in future versions it could be improved but at the moment it's -tagged as an experimental and alternative feature only in case you -don't know the bms syntax or it takes time to convert a C struct in -bms language. - -Example of -s option, zlib decompression in one command-line without -using script files: - - quickbms.exe -s "comtype zlib ; get ZSIZE asize ; xmath SIZE \"ZSIZE * 10\" ; clog \"dump.dat\" 0 ZSIZE SIZE" "" input_file.dat output_folder - quickbms.exe -s "comtype gzip_compress ; get SIZE asize ; clog new.gz 0 SIZE SIZE" "" YOUR_INPUT_FILE - - -####################################################################### - -================================================ -5) Experimental input and output, other features -================================================ - - -A] Experimental input and output --------------------------------- - -From version 0.5.1 of QuickBMS I started to implement some alternative -input/output methods. -At the moment these alternatives cover the following operations: - -- Network socket operations specified by an URL like udp:// and tcp:// - so the tool can be used to send custom packets and data via TCP and - UDP to one or more network hosts. - Required command-line option: -n or -network - URL format: - tcp://host:port - tcp://host:port,ssl,force_new_socket - -- Process operations specified by an URL like process:// or memory:// - and allow to read and write the various processes running on the - system. - Required command-line option: -p or -process - URL format: - process://process_name - process://pid - process://pid:module_name - - Experimental debug mode available by adding "debug" after the - parameters: process://pid/debug - In this way the process will be debugged by QuickBMS and when - there is a breakpoint or an exception the process will be freezed - and all the registers dumped in variables with their names. - additionally QuickBMS will keep in memory all the INT3 you set - and automatically restore them when you want to continue the - execution. - You can find an example script here: - http://aluigi.org/bms/simraceway_getkey.bms - -- Audio operations specified by an URL like audio:// or wave:// - and allow to record audio from the default input device (like - microphone) and play. - Currently the "device" parameter is not used. - Required command-line option: -A or -audio - URL format: - audio://device,sample_rate,channels,bits - -- Video operations specified by an URL like video:// or graphic:// - and allow to grab the screen and display the images. - set window_name to null or none for using the whole screen in read - mode. - Required command-line option: -g or -video - URL format: - audio://window_name,width,height,bits - -- Windows messages specified by an URL like winmsg:// but at the moment - it's possible only to send messages and using 3 long numbers: - message, wparam and lparam. - Required command-line option: -m or -winmsg - URL format: - winmsg://window_name - - -I had this crazy idea in my mind for over one year and I decided to -implement it now just because it's completely crazy and can work only -if the user uses the needed options at command-line for security -reasons. - -After all QuickBMS implements a lot of algorithms so for me it's a lot -more comfortable to be able to use it for my tests with the network -data and I guess some modders could find useful the process operations -for dumping textures and other models directly from the memory. -Anyway keep in mind that this is all experimental stuff. - -The following is an example script for the network operations: - - log MEMORY_FILE 0 0 - put 0x11111111 long MEMORY_FILE - put 0x22222222 long MEMORY_FILE - put 0x33333333 long MEMORY_FILE - put "hello" string MEMORY_FILE - put 0x44444444 long MEMORY_FILE - get SIZE asize MEMORY_FILE - log "tcp://127.0.0.1:1234" 0 SIZE MEMORY_FILE - log "udp://localhost:1234" 0 SIZE MEMORY_FILE - -or - - log MEMORY_FILE 0 0 - put "GET / HTTP/1.0" line MEMORY_FILE - put "User-Agent: Mozilla" line MEMORY_FILE - put "Referer: http://localhost/test.htm" line MEMORY_FILE - put "" line MEMORY_FILE - get SIZE asize MEMORY_FILE - log "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. - - - -C] Modkit distribution of quickbms.exe --------------------------------------- - -In response to a request of a modder, I have decided to add a simple -feature to allow modders and modkits developers to embed a script in -quickbms.exe when they distribute it in their products, so the user -will not be asked to select the script. - -How to do it: - -- open quickbms.exe with a hex editor -- search the string "SET THIS BYTE X TO 0x00" -- replace the 'X' (0x58) with a NULL (0x00): - 53 45 54 20 54 48 49 53 20 42 59 54 45 20 58 20 SET THIS BYTE X - 53 45 54 20 54 48 49 53 20 42 59 54 45 20 00 20 SET THIS BYTE - -- 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. - * From version 0.3.12 I decided to implement the full verification of - the string to know if it's a number or a string, luckily there is - almost no loss of performances - -x (SOLVED!) - The following do NOT work because the QuickBMS variables are case INsensitive: - if SIGN == "test" # u== is the same - elif SIGN == "TeSt" - ... - set SIGN1 binary "test" - set SIGN2 binary "TeSt" - if SIGN == SIGN1 # u== is the same - elif SIGN == SIGN2 - ... - The only way to fix it would be to make quickbms case SENSITIVE, this - change should give no problems if you have written the scripts correctly - but exists a 1% of possible issues, currently I don't know what to do. - . - * From QuickBMS 0.5.31 you can use the -I option to force the case - sensitive mode on variable names - -x (SOLVED!) - set NAME string MEMORY_FILE - log NAME 0 0 - It produces no physical file because it's considered a MEMORY_FILE, it - happens because the dumping function receives "MEMORY_FILE" as output - file name. - At the moment there is no fix anyway it's a very very rare event - (never happened to find an archive containing a file with that name) - and so not a priority. - * Fixed in version 0.5.17 by checking if the name of the file is the - name of a variable or its content. - -x (SOLVED!) - Crash caused by HsSrv.dll. - The Asus Xonar and Unixonar drivers cause the crash of QuickBMS for the - following reason: HsSrv.dll is automatically injected in any process - and this dll checks all the allocated memory for the presence of a "MZ" - signature (the one used for the executables): - 1000B462 CALL DWORD PTR DS:[<&KERNEL32.VirtualQuery>] - 1000B468 TEST EAX,EAX - 1000B46A JBE SHORT 1000B4BE - 1000B46C CMP DWORD PTR SS:[EBP-24],1000 ; check if State is MEM_COMMIT - 1000B473 JNE SHORT 1000B48B - 1000B475 TEST WORD PTR SS:[EBP-20],0100 ; check if Protect contains PAGE_GUARD - 1000B47B JNZ SHORT 1000B48B - 1000B47D AND DWORD PTR SS:[EBP-4],00000000 - 1000B481 CMP WORD PTR DS:[ESI],5A4D ; check if the buffer starts with MZ - QuickBMS uses a particular memory protection mechanism that in the - recent versions switched from PAGE_GUARD to PAGE_NOACCESS, that's - why HsSrv.dll crashes: if Protect contains PAGE_GUARD then it skips the - MZ check but now it's PAGE_NOACCESS. - Using MEM_COMMIT | MEM_RESERVE doesn't help to skip the code with the - first check because VirtualQuery returns only MEM_COMMIT. - Asus should fix the bug by checking if Protect is set to a non-readable - flag, I have NOT contacted them. - Some possible solutions are the following: - - disable the GX mode (emulated EAX) of the Asus driver - - disable the Asus HookSupport Manager application (HsMgr.exe) - - start QuickBMS with the -9 option (create a shortcut) - - contact Asus! :) - Note that the problem seems to happen only when QuickBMS is launched - with the GUI (double-click) while it's calling the Windows API - GetOpenFileName. - * From version 0.5.25c I use PAGE_GUARD to avoid any problem with - buggy third party drivers. - -? When you assign a string to a variable pay attention to the backslash - char: \ - It's used as escape when parsing the bms script and a quoted string - is found, like "test". - The only limitation is caused by the presence of the same quote char - after the backslash so the following command is wrongly interpreted: - string VAR R "test1 and test2\" "/" - In that case the \" is interpreted as " without terminating the - handling of the quote string. - For that specific case there is no solution at the moment because - \\ is interpreted as \\ and not as \. - Consider that this is a very rare case and if you want to replace - the backslash with slashes it's enough to use: - string VAR R \ / - - -Other things to know or strange behaviors will be listed when I will -figure and remember them. - -A curiosity for who is crazy for the optimizations of the compilers: -the PPMD (ppmd var.i rev.1) algorithm compiled with -O3 (Gcc) is a lot -slower than if compiled with -O2 and a similar situation is valid also -for other algorithms. -With -Os the code is smaller (about 300kb the Windows exe of an old -quickbms version) but there is a loss of performances of max 15/20% -with some algorithms (like PPMD) and scripts with many get/putvarchr -and math operations. - - -####################################################################### - -========== -7) Support -========== - - -QuickBMS, like many of my projects, is fully supported by me and is -ever in active development for adding new encryption and compression -algorithms, adding new features, fixing bugs and other improvements. -I'm the first and biggest user of this tool, so I have a direct -interest in maintaining it. - -The latest version is available on the following website: - - http://quickbms.com - -RSS feeds available on my website so stay tuned for any update of -QuickBMS and my other tools: - - http://aluigi.org/rss.php - -Remember to contact me for any doubt or new idea regarding QuickBMS -by e-mail at me@aluigi.org or on the forum in this topic -http://zenhax.com/viewtopic.php?f=13&t=556 - -You are also invited to post your doubts, feedback and suggestions on -the official support forum called ZenHAX: http://zenhax.com -It's a community where the users can write about game research, file -format reversing, game internals and security. - -My old forum on http://forum.aluigi.org is no longer supported from -2011 but it contains some additional old information and examples. - -QuickBMS is a free project, no donations or money are accepted. -If you like it feel free to spread the word about it. -You may also like to make tutorials and videos, they are welcome so -more people can learn to use it. - -QuickBMS wants to be THE EXTRACTION TOOL for almost any game related -task so "help it to help yourself" :) - - -####################################################################### - -===================== -8) Additional credits -===================== - - -QuickBMS uses various public-domain code and code released under -GPL/LGPL or other open source and free licenses. - -Compression: -- zlib, inflateback9 (for deflate64) and blast of Jean-loup Gailly and - Mark Adler http://www.zlib.net -- LZO of Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ -- LZSS, LZARI, LZHUF of Haruhiko Okumura -- unlzx.c of Erik Meusel -- LZMA and LZMA2 of Igor Pavlov http://www.7-zip.org/sdk.html -- bzip2 of Julian Seward http://www.bzip.org -- ascii85 partially derived from http://www.stillhq.com/svn/trunk/ascii85/decode85.c -- libmspack of Stuart Caie http://www.cabextract.org.uk/libmspack/ -- lzjb from http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/zfs/lzjb.c -- iMatix SFL compression http://download.imatix.com/pub/ -- UCL of Markus F.X.J. Oberhumer http://www.oberhumer.com/opensource/lzo/ -- code from the uncompress utility of "The Regents of the University of California" -- Dynamic Markov Compression implementation of Gordon V. Cormack - http://plg1.cs.uwaterloo.ca/~ftp/dmc/dmc.c -- many algorithms from ScummVM http://scummvm.sourceforge.net -- bpe of Philip Gage http://www.csse.monash.edu.au/cluster/RJK/Compress/bpd.c -- QuickLZ of Lasse Mikkel Reinhold http://www.quicklz.com -- Quake 3 Huffman code of Id Software http://www.idsoftware.com -- mszh from the LossLess Codec Library -- Doom Huffman code from the Doom/Hexen source code -- aPLib of Jorgen Ibsen http://www.ibsensoftware.com/products_aPLib.html -- LZF of Marc Alexander Lehmann http://home.schmorp.de/marc/liblzf.html -- LZ77 of Arkadi Kagan http://compressions.sourceforge.net/about.html -- LZRW algorithms of Ross Williams http://www.ross.net/compression/ -- an Huffman implementation of Bill Demas on LDS -- the FIN algorithm (useless and very close to LZSS) on LDS -- LZAH/LZH12/13 of Dik T. Winter http://homepages.cwi.nl/~dik/english/ftp.html -- GRZipII/libGRZip of Grebnov Ilya (only the win32 code is linked to it) - because it's composed by many files and it's not a priority) -- rle of Chilkat Software http://www.chilkatsoft.com/chilkatdx/ck_rle.htm#source -- Quad of Ilia Muraviev http://quad.sourceforge.net -- Balz of Ilia Muraviev http://balz.sourceforge.net -- unshrink of Info-Zip http://www.info-zip.org/UnZip.html -- PPMd algorithms of Dmitry Shkarin http://compression.ru/ds/ -- BriefLZ of Jorgen Ibsen http://www.ibsensoftware.com/download.html -- PAQ6 of Matt Mahoney http://cs.fit.edu/~mmahoney/compression/paq.html#paq6 -- shcodec of Simakov Alexander http://webcenter.ru/~xander/ -- hstest of tom ehlert -- SixPack of Philip G. Gage -- ashford of Charles Ashford -- JCALG1 of Jeremy Collake http://www.bitsum.com/jcalg1.htm -- jam/unjam of W. Jiang -- lzhlib of Haruhiko Okumura and Kerwin F. Medina for the adaptation of the code -- Srank P M Fenwick http://www.cs.auckland.ac.nz/~peter-f/FTPfiles/srank.c -- Zziplib/Zzlib of Damien Debin http://damiendebin.net/archives/zzip/download.php#zzlib -- scpack of Philip Gage -- rle3 and bpe2: - http://musyozoku211.blog118.fc2.com/blog-entry-13.html - http://blog-imgs-17.fc2.com/m/u/s/musyozoku211/bpe2.txt - http://blog-imgs-17.fc2.com/m/u/s/musyozoku211/rle3.txt -- Basic Compression Library of Marcus Geelnard http://bcl.comli.eu -- SCZ of Carl Kindman http://scz-compress.sourceforge.net -- szip of HDF Group http://www.hdfgroup.org/doc_resource/SZIP/ -- sr3c of Kenneth Oksanen http://cessu.blogspot.com -- Huffman library of Douglas Ryan Richardson http://huffman.sourceforge.net -- SFastPacker of Aleksey Kuznetsov http://www.utilmind.com/delphi3.html -- lz77wii of Hector Martin http://wiibrew.org/wiki/Wii.py -- prs 8ing code posted by tpu http://forum.xentax.com/viewtopic.php?p=30387#p30387 -- puyo compressions of not.nmn and nickwor https://github.com/nickworonekin/puyotools -- falcom compression of http://www.geocities.jp/pokan_chan/ -- cpk of hcs http://hcs64.com/files/utf_tab04.zip -- DSDecmp/goldensun/luminousarc of Barubary http://code.google.com/p/dsdecmp/ -- pglz_decompress PostgreSQL Global Development Group http://www.postgresql.org/ -- SLZ: versions of Adisak Pochanayon and CUE -- LZH-Light of Sergey Ignatchenko ftp://66.77.27.238/sourcecode/cuj/1998/cujoct98.zip -- d3101 of Advanced Hardware Architectures/HP -- squeeze (R. Greenlaw, Amiga port by Rick Schaeffer ???) -- some algorithms of Mark Nelson & Jean-loup Gailly from The Data Compression Book -- Ed Ross Data Compression -- ilzr of Jose Renau Ardevol -- some code from the C User's Journal -- dmc by T.L. Yu -- 'Uses libLZR by BenHur' http://www.psp-programming.com/benhur/ -- lzs of Matthew Chapman http://www.rdesktop.org -- yaz0 of thakis (http://www.amnoid.de/gc/) -- RNC by Jon http://www.yoda.arachsys.com/dk/ - or a fork made by Simon Tatham -- PAK_explode of Cyril VOILA -- The KENS Project Development Team -- dragonballz by Geoffrey W. Curtis -- unstargun by Adam Nielsen / The_coder -- ntcompress from Nintendo Wii Revolution SDK -- crle of Arkadi Kagan http://compressions.sourceforge.net/about.html -- CTW by Frans Willems http://www.ele.tue.nl/ctw -- DACT by Roy Keene http://www.rkeene.org/oss/dact/ -- algorithms by Brendan G Bohannon http://bgb-sys.sourceforge.net -- lzpxj by Ilia Muraviev and Jan Ondrus http://sourceforge.net/projects/lzpx/ -- rle from ftp://ftp.elf.stuba.sk/pub/pc/pack/mar.rar -- rle from http://gdcm.sourceforge.net -- dict from http://freearc.org/download/research/dict.zip -- rep from http://freearc.org/download/research/rep.zip -- lzp by Dmitry Shkarin http://www.compression.ru/ds/lzp.rar -- kzip by Ken Silverman http://advsys.net/ken/utils.htm -- enet http://enet.bespin.org -- eduke32 http://eduke32.com -- xu4 - Ultima IV recreated http://sourceforge.net/projects/xu4/ -- Lemur http://www.lemurproject.org -- lzfu by Dave Smith and Carl Byington http://www.five-ten-sg.com/libpst/ -- he3 by Eric Prevoteau http://savannah.nongnu.org/projects/dctc/ -- Ultima Iris http://www.iris2.de http://ultimairis.sourceforge.net -- http://sourceforge.net/projects/linux-ntfs/ -- pdb2txt http://code.google.com/p/pdb2txt/ -- Comprlib http://sourceforge.net/projects/comprlib/ -- prs by Fuzziqer http://www.fuzziqersoftware.com/projects.html -- sega_lz77 converted from an ICE decompression tool developed by - scriptkiddie (XentaX's forum) -- saint_seya compression by MrAdults (Senor Casaroja's Noesis) - http://forum.xentax.com/viewtopic.php?p=52279#p52279 -- lz4 by Yann Collet https://github.com/Cyan4973/lz4 -- Snappy http://google.github.io/snappy/ -- Lunar compression dll by FuSoYa http://fusoya.eludevisibility.org -- lzv1 by Hermann Vogt -- FastLZ by Ariya Hidayat http://fastlz.org -- zax http://code.google.com/p/zax/ -- data-shrinker by fusiyuan http://code.google.com/p/data-shrinker/ -- mmini by Adam Ierymenko http://code.google.com/p/mmini/ -- clzw by Vladimir Antonenko http://code.google.com/p/clzw/ - http://sourceforge.net/projects/clzw/ -- lzham by Richard Geldreich https://github.com/richgel999/lzham_codec -- lpaq8 by Matt Mahoney http://www.cs.fit.edu/~mmahoney/compression/ -- sega_lzs2 by Treeki -- Core Online decompression by Ekey http://www.progamercity.net -- lzlib http://lzip.nongnu.org/lzip.html -- some compression tools from http://www.romhacking.net -- pucrunch by Pasi 'Albert' Ojala -- libzpaq by Matt Mahoney http://mattmahoney.net/dc/zpaq.html -- zyxel-revert http://git.kopf-tisch.de/?p=zyxel-revert -- Blosc https://github.com/Blosc/c-blosc -- Gipfeli by Jyrki Alakuijala https://github.com/google/gipfeli -- Crush by Ilya Muravyov http://sourceforge.net/projects/crush/ -- Yappy https://raw.github.com/richard-sim/Compression-Test-Suite/master/CompressionSuite/Yappy/yappy.cpp -- liblzg by Marcus Geelnard http://liblzg.bitsnbites.eu/ -- Doboz by Attila T. Afra https://bitbucket.org/attila_afra/doboz -- XPK http://www.jormas.com/~vesuri/xpk/ -- http://www.amiga-stuff.com/crunchers-download.html -- http://aminet.net/package/util/libs/ulib4271 -- PackFire by Neural http://www.pouet.net/prod.php?which=54840 -- Matt Mahoney for various compression algorithms -- http://blog-imgs-17.fc2.com/m/u/s/musyozoku211/bpe.txt -- CBPE by Izaya http://izaya.blog38.fc2.com/blog-entry-374.html -- Alba by xezz http://encode.ru/threads/1874-Alba?p=36612&viewfull=1#post36612 -- http://download.wcnews.com/files/documents/sourcecode/shadowforce/transfer/asommers/mfcapp_src/engine/compress/ -- QFS https://raw.githubusercontent.com/wouanagaine/SC4Mapper-2013/master/Modules/qfs.c -- Zen Studios decompression by Ekey http://www.progamercity.net -- OpenXRay https://github.com/OpenXRay/xray-16/blob/master/src/xrCore/LzHuf.cpp -- ZSTD https://github.com/Cyan4973/zstd -- AZO http://www.altools.com/ALTools/ALZip/Egg-format.aspx -- PowerPacker from libsidtune https://github.com/bithorder/sidplayer/blob/master/jni/libsidplay2/sidtune/PP20.cpp -- Nintendo DS/GBA compressions by CUE http://www.romhacking.net/utilities/826/ -- pclzfg http://www.embedded-os.de/en/pclzfg.shtml -- Heatshrink https://github.com/atomicobject/heatshrink -- TurboRLE https://github.com/powturbo/TurboRLE -- Smaz https://github.com/antirez/smaz -- lzfx http://code.google.com/p/lzfx/ -- Pithy https://github.com/johnezang/pithy -- libzling https://github.com/richox/libzling -- Density https://github.com/centaurean/density -- Brotli https://github.com/google/brotli -- code by Gerald Tamayo -- libbsc http://libbsc.com/ -- Shoco https://ed-von-schleck.github.io/shoco/ -- WFLZ https://github.com/ShaneWF/wflz -- FastAri https://github.com/davidcatt/FastARI -- Dicky https://github.com/jedisct1/Dicky -- Squish https://github.com/Bananattack/squish -- lzjody https://github.com/jbruchon/lzjody -- ms-compress https://github.com/coderforlife/ms-compress -- yay0dec by thakis http://www.amnoid.de/gc/ -- dmsdos http://cmp.felk.cvut.cz/~pisa/dmsdos/ -- iROLZ http://ezcodesample.com/rolz/rolz_article.html -- Mcomp http://msoftware.co.nz -- SimPE http://sims.ambertation.de/ -- Adam Nielsen for Camoto http://www.shikadi.net/camoto -- OpenKB http://openkb.sourceforge.net/ -- OpenTitus http://opentitus.sourceforge.net/ -- deLZW http://cnub.ddns.net/deLZW.ashx -- various pseudocode from http://www.shikadi.net/moddingwiki/Category:Compression_algorithms -- Ladislav Zezula for PKLib -- Marc Winterrowd http://nodling.nullneuron.net/ultima/ultima.html -- tkatchev https://bitbucket.org/tkatchev/yalz77 -- LZ5 https://github.com/inikep/lz5 -- various compression algorithms from Lab313 https://github.com/lab313ru -- LZSS http://www.metroid2002.com/retromodding/wiki/LZSS_Compression -- SynLZ https://raw.githubusercontent.com/synopse/mORMot/master/SynLZ.pas -- PPMZ2 http://www.cbloom.com/src/ppmz.html -- OpenDark http://sourceforge.net/projects/dark/ -- Oodle http://www.radgametools.com/oodle.htm (DLL from Warframe) -- jdlz recompressor http://encode.ru/threads/2417-Creating-A-Compressor-for-JDLZ?p=46247&viewfull=1#post46247 -- rfpk http://www.rockraidersunited.com/topic/6675-is-there-a-way-i-could-rip-files-of-lego-city-undercovers-disc/#comment-120442 -- wp16 http://romxhack.esforos.com/compresion-de-final-fantasy-1-de-psp-la-famosa-wp16-t44 -- Nisto https://github.com/Nisto/bio-tools/tree/master/bio0/alz-tool -- Ekey for Revelation Online / TianYu -- ps_lz77 by TheUkrainianBard http://zenhax.com/viewtopic.php?p=14313#p14313 -- lzfse https://github.com/lzfse/lzfse -- dzip https://www.madewithmarmalade.com/developer -- CSC https://github.com/fusiyuan2010/CSC -- Gundam Ghiren converted to C http://zenhax.com/viewtopic.php?p=18646#p18646 -- glza by Kennon Conrad http://encode.ru/threads/1909-Tree-alpha-v0-1-download?p=50293&viewfull=1#post50293 -- m99coder by Yuta Mori -- https://github.com/solaris573/taikotools -- https://github.com/nekomiko/recetunpack/blob/master/data_ext.c -- https://github.com/BlackDragonHunt/Danganronpa-Tools/blob/master/drv3/drv3_dec.py -- https://github.com/gildor2/UModel/blob/master/Unreal/UnCoreCompression.cpp -- https://forum.xentax.com/viewtopic.php?p=119352#p119352 -- https://encode.ru/threads/2772-Finding-custom-lzss-on-arcade-game-dat-file?p=52946&viewfull=1#post52946 -- liblzs by Craig McQueen https://github.com/cmcqueen/lzs-compression -- shrek decompression by ShrekBoards https://github.com/ShrekBoards/shrek-decompress - -Encryption: -- all the algorithms provided by OpenSSL http://www.openssl.org -- xtea from PolarSSL http://www.polarssl.org -- some encryption algorithms from GnuPG and libgcrypt http://www.gnupg.org -- ICE of Matthew Kwan http://www.darkside.com.au/ice/index.html -- Rotor module from the Python source code -- http://mcrypt.sourceforge.net -- all the various public algorithms implemented in version 0.4.1 like - 3way, anubis, gost, skipjack and so on -- libkirk of Draan http://code.google.com/p/kirk-engine/ -- PC1 Encryption Algorithm of Alexander Pukall http://membres.multimania.fr/pc1/ -- LibTomCrypt https://github.com/libtom/libtomcrypt -- LibTomMath https://github.com/libtom/libtommath -- 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/ -- TinyCC http://bellard.org/tcc/ - -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, it may be - 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 (/* */) - - -####################################################################### diff --git a/tools/quickbms/wavescan.bms b/tools/quickbms/wavescan.bms deleted file mode 100644 index adca049..0000000 --- a/tools/quickbms/wavescan.bms +++ /dev/null @@ -1,67 +0,0 @@ -# modified version to ignore filenames (and wav) -# -# scan data for wave files -# RIFF and RIFX header supported -# note: There are wave files with a wrong file size after RIFF/RIFX -# This script takes the stream size, adds the header size and writes the correct size after RIFF/RIFX -# (c) 2012-06-26 by AlphaTwentyThree -# -# future update plans: -# - option to also write data between found wave files to disk -# - option to automatically transform the file to a playable or at least decodable format - -for i = 1 # run through loop with count variable i - FindLoc OFFSET string "WAVE" 0 "" # search for "WAVE", save position as variable OFFSET - if OFFSET == "" # when nothing is found - cleanexit # the script exits (e.g. at end of file) - endif - math OFFSET -= 8 # jump to possible - goto OFFSET # RIFF/RIFX file start - getDstring IDENT 4 # read string of 4 bytes, save variable as IDENT - if IDENT == "RIFX" # differentiate between header possibilities - endian big # set endianness to big, if file has RIFX identifier - callfunction write 1 # see function section below - elif IDENT == "RIFF" # endianness stays little - callfunction write 1 # also run function - else # string "WAVE" found, but doesn't belong to wave file - set SIZE 0xc # do as if something with 0xc bytes was found to continue search from the right position - endif - set SEARCH OFFSET # set marker to position from where to search next - math SEARCH += SIZE # (that would be after the file that was found) - if SEARCH == FSIZE # in case the last found file ends with the main file, we exit - cleanexit - endif - goto SEARCH # if we haven't exited the script above, we set out cursor to after the last found file -next i - -startfunction write # function "write" starts here, is called when a wave file is found above - get NAME basename # save name without extension under variable NAME - string NAME += "_" # add underscore to the name - string NAME += i # add the loop variable to the name - goto OFFSET # set cursor to the beginning of the found file - get DUMMY long # RIFF/RIFX identifier, not needed - get DUMMY long # riff size, not needed - get DUMMY long # "WAVE", not needed, we arrive at the "fmt " section - for # loop search for the "data" section at the start of the stream (get the stream size from there) - getDstring AREA_NAME 4 # name of area in header - get AREA_SIZE long # size of area in header - savepos MYOFF # save position we are at - if AREA_NAME == "data" # when we arrive at the needed "data" area: - break # we exit the loop - else # otherwise: - math MYOFF += AREA_SIZE # not reached "data" area -> adjust cursor position... - goto MYOFF # ... and go there - endif - next # remember: the cursor is now directly at the stream start - set STREAMSIZE AREA_SIZE # the last AREA_SIZE is the size we need (size of the audio stream) - set HEADERSIZE MYOFF # - math HEADERSIZE -= OFFSET # calculate the size of the stream header (offset - offset = size) - set SIZE HEADERSIZE # - math SIZE += STREAMSIZE # calculate complete file size (header + stream = file) - log MEMORY_FILE OFFSET SIZE # write file to memory - math SIZE -= 8 # subtract 8 bytes to get the riff size - putVarChr MEMORY_FILE 4 SIZE long # write the correct riff size to the header inside the memory - string NAME += ".wem" # add extension to the name (the name could contain the name of the first marker if the file has markers) - math SIZE += 8 # add the subtracted 8 bytes again - log NAME 0 SIZE MEMORY_FILE # write file in memory to disk -endfunction # remember that we continue with our next i now! \ No newline at end of file diff --git a/wavescan.py b/wavescan.py index 71cd43e..1692c3e 100644 --- a/wavescan.py +++ b/wavescan.py @@ -1,16 +1,18 @@ # Custom rewrite of the Wwise AKPK packages extractor, original by Nicknine and bnnm # TODO: use extracted files id with the mapping table to restore file names -# TODO: make this script callable by the main one from filereader import FileReader import os -filename = "External0.pck" -cwd = os.getcwd() -reader = FileReader(open(filename, "rb"), "little") # defaults to little endian + +reader = None bank_version = 0 -def main(): + +def extract(input_file, output_folder): global bank_version + global reader + + reader = FileReader(open(input_file, "rb"), "little") # defaults to little endian # check file if reader.ReadBytes(4) != b"AKPK": @@ -50,7 +52,7 @@ def main(): # extract each sector for sector in sectors: - extract_sector(*sector[1:], endianness, lang_array, bank_version) + extract_sector(*sector[1:], endianness, lang_array, bank_version, output_folder) if sector[0] and bank_version == 0: if externals_sector_size == 0: @@ -109,7 +111,7 @@ def detect_bank_version(offset): reader.SetBufferPos(current) -def extract_sector(section_size, is_sounds, is_externals, ext, endianness, lang_array, bank_version, filter_bnk_only=0, filter_wem_only=0): +def extract_sector(section_size, is_sounds, is_externals, ext, endianness, lang_array, bank_version, output_folder, filter_bnk_only=0, filter_wem_only=0): # check sector validity if section_size == 0: return @@ -193,20 +195,18 @@ def extract_sector(section_size, is_sounds, is_externals, ext, endianness, lang_ if filter_wem_only == 1 and ext != "wem": continue - print(f"NAME - {name} | OFFSET - {offset} | SIZE - {size}") + # file infos + # print(f"NAME - {name} | OFFSET - {offset} | SIZE - {size}") # save file into disk current = reader.GetBufferPos() reader.SetBufferPos(offset) file_data = reader.ReadBytes(size) - os.makedirs(os.path.join(cwd, os.path.dirname(name)), exist_ok=True) + os.makedirs(output_folder, exist_ok=True) - with open(os.path.join(cwd, name), "wb+") as f: + with open(os.path.join(output_folder, os.path.basename(name)), "wb+") as f: f.write(file_data) f.close() reader.SetBufferPos(current) - -if __name__ == "__main__": - main()