Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
#!/usr/bin/env python
__description__ = 'ZIP dump utility'
__author__ = 'Didier Stevens'
__version__ = '0.0.21'
__date__ = '2020/11/21'
"""
Source code put in public domain by Didier Stevens, no Copyright
https://DidierStevens.com
Use at your own risk
History:
2014/02/01: start
2014/04/30: added timestamp
2014/10/07: added magic values and metadata; added option dumpall, hexdumpall and asciidumpall
2014/10/09: refactoring, added option extra
2014/10/13: fixed whitespace counter bug; -o bug
2014/10/26: refactoring
2014/11/09: added option -p
2014/12/21: 0.0.2: Added YARA support; added decoders
2015/01/08: 0.0.3: Added support for multiple YARA rule files
2015/02/09: Added option yarastrings
2015/06/08: Fix HexAsciiDump
2015/07/21: filename = '*'
2015/09/12: if the ZIP file contains a single ZIP file, then the contained ZIP file is dumped; added --cut
2015/09/13: added option -r and -z
2015/09/22: added --man
2015/09/29: bug fixes
2015/11/17: added support for :-number in --cut option; added -E option
2016/05/26: refactoring and man
2016/05/29: continue man, updated cut option
2016/11/15: 0.0.4: Added support ZIP comment
2016/11/16: added Unique bytes
2017/01/29: 0.0.5: added # for option extra
2017/05/02: 0.0.6: added options --passwordfile and --passwordfilestop
2017/05/20: 0.0.7: added internal password list
2017/05/21: 0.0.8: added extra exception DictionaryAttack
2017/07/02: 0.0.9: added # support for option -y
2017/07/11: 0.0.10: added option --yarastringsraw
2017/07/18: 0.0.11: added #s# and #q# support for option -y
2018/06/25: 0.0.12: added option -t
2018/07/01: 0.0.13: added option --jsonoutput
2018/07/07: 0.0.14: updated to version 2 of jsonoutput
2018/12/15: 0.0.15: updated help
2019/12/26: 0.0.16: added option -f and started Python 3 support
2019/12/27: continue
2020/01/05: 0.0.17: temporary bugfix in ZIPFind for reversed ZIP files
2020/04/05: handle incomplete EOCD record
2020/04/13: 0.0.18 added option info
2020/04/29: 0.0.19 added support for AES with pyzipper
2020/07/23: 0.0.20 added PK record data descriptor (PK 07 08)
2020/08/16: 0.0.21 Python 3 fixes
2020/10/21: Python 3 fix in cBinaryFile
2020/11/21: Python 3 fix extra info
Todo:
"""
import optparse
import hashlib
import signal
import sys
import os
import string
import math
import binascii
import re
import textwrap
import operator
import time
import gzip
import zlib
import codecs
import json
import struct
try:
import pyzipper as zipfile
except ImportError:
import zipfile
try:
import yara
except:
pass
if sys.version_info[0] >= 3:
from io import StringIO
else:
from cStringIO import StringIO
if sys.version_info[0] >= 3:
from io import BytesIO as DataIO
else:
from cStringIO import StringIO as DataIO
QUOTE = '"'
def PrintManual():
manual = '''
Manual:
zipdump is a tool to analyze ZIP files.
It uses built-in Python module zipfile, unless module pyzipper is installed. Module pyzipper adds AES support, and can be installed with pip (Python 3 only).
The ZIP file can be provided as an argument, via stdin (piping) and it may also be contained in a (password protected) ZIP file.
When providing zipdump with a file to analyze, it will report on the content of the ZIP file, like in this example:
C:\Demo>zipdump.py example.zip
Index Filename Encrypted Timestamp
1 Dialog42.exe 0 2012-02-25 12:08:26
2 readme.txt 0 2015-11-24 19:40:12
The first column, Index, is an index that zipdump assigns to each file inside the ZIP file. You can use it with option -s (select) to select a file for further analysis.
Filename is the filename of the contained file.
Encrypted is a flag indicating if the file is encrypted (1) or not (0).
And the last column (Timestamp) is the timestamp of the file inside the archive.
Option -s takes the index number or the filename to select a file.
By default, the separator used to delimit columns is the space character. When the default separator is used, padding is added to lign up the columns. Another separator character can be selected with option -S. No padding is used when the separator is provided (even if it is the space character).
C:\Demo>zipdump.py -S ; example.zip
Index;Filename;Encrypted;Timestamp;
1;Dialog42.exe;0;2012-02-25 12:08:26;
2;readme.txt;0;2015-11-24 19:40:12;
When a file is selected, the properties of this file are displayed:
C:\Demo>zipdump.py -s 1 example.zip
Index Filename Encrypted Timestamp
1 Dialog42.exe 0 2012-02-25 12:08:26
The content of the selected file can also be dumped.
Use option -x to perform an hexdump:
C:\Demo>zipdump.py -s 1 -x example.zip
4D 5A 50 00 02 00 00 00 04 00 0F 00 FF FF 00 00
B8 00 00 00 00 00 00 00 40 00 1A 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...
Use option -a to perform an ascii/hexdump:
C:\Demo>zipdump.py -s 1 -a example.zip
00000000: 4D 5A 50 00 02 00 00 00 04 00 0F 00 FF FF 00 00 MZP.............
00000010: B8 00 00 00 00 00 00 00 40 00 1A 00 00 00 00 00 +.......@.......
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
...
Use option -d to perform a raw dump:
C:\Demo>zipdump.py -s 2 -d example.zip
test
A raw dump is useful to pipe the output into another command:
C:\Demo>zipdump.py -s 1 -d example.zip | pecheck.py
PE check for '':
Entropy: 6.425034 (Min=0.0, Max=8.0)
MD5 hash: 9b7f8260724e2cb643ad0729ec995b40
...
If the dump needs to be processed by a string codec, like utf16, use option -t instead of -d and provide the codec:
C:\Demo>zipdump.py -s 1 -t utf16 example.zip
You can also provide a Python string expression, like .decode('utf16').encode('utf8'). Remark that this uses the Python eval function with untrusted input, so be careful, it can be used for code injection.
When options -x, -a or -d are used without selecting a file (option -s), the first file in the ZIP file is selected and dumped.
When options -X, -A or -D are used without selecting a file (option -s), all files in the ZIP file are selected and dumped.
The output produced by zipdump.py can de written to a file with option -o.
If the ZIP file is password protected, zipdump.py will try with password 'infected'. Option -p can be used to provide a different password to open the ZIP file. To provide a list of passwords to try,
use option -P with the name of the file containing passwords to try (dictionary attack). This file can be a text file or a gzip compressed text file. The password file is completely read into memory before the dictionary attack is executed.
After the dictionary attack, the selected commands (via other options) are executed.
Example:
C:\Demo>zipdump.py -P passwords.txt -s 1 -a password-protected.zip
00000000: 73 65 63 72 65 74 20 74 65 78 74 secret text
To perform just a dictionary attack, without additional commands, use option --passwordfilestop. This option will produce progress output, like this:
C:\Demo>zipdump.py --passwordfilestop rockyou.txt.gz secret.zip
Passwords: 10000 0.07% p/s: 7727 ETC: 2017/05/01 20:18:50
Passwords: 20000 0.14% p/s: 7883 ETC: 2017/05/01 20:18:13
Passwords: 30000 0.21% p/s: 7947 ETC: 2017/05/01 20:17:58
Passwords: 40000 0.28% p/s: 7964 ETC: 2017/05/01 20:17:54
Password: loveyoubaby
zipdump also has an internal password list (a few thousand passwords), that can be used by providing filename . (a single dot) to options -P and --passwordfilestop.
Example:
C:\Demo>zipdump.py --passwordfilestop . secret.zip
Password: letmein
If the ZIP file contains a single ZIP file, the contained ZIP file will be considered to be the ZIP file to analyze. To prevent this, use option -r. Option -r handles the contained ZIP file as a regular file.
Option -z can be used to include the name of the zipfile in the report:
C:\Demo>zipdump.py -z -S ; example.zip
Index;Zipfilename;Filename;Encrypted;Timestamp;
1;example.zip;Dialog42.exe;0;2012-02-25 12:08:26;
2;example.zip;readme.txt;0;2015-11-24 19:40:12;
This can be useful when reports of many ZIP files are merged together.
Option -e extends the amount of information reported:
C:\Demo>zipdump.py -e example.zip
Index Filename Encrypted Timestamp MD5 Filesize Entropy Unique bytes Magic HEX Magic ASCII Null bytes Control bytes Whitespace bytes Printable bytes High bytes
1 Dialog42.exe 0 2012-02-25 12:08:26 9b7f8260724e2cb643ad0729ec995b40 58120 6.42503434625 256 4d5a5000 MZP. 13014 6403 1678 19366 17659
2 readme.txt 0 2015-11-24 19:40:12 098f6bcd4621d373cade4e832627b4f6 4 1.5 3 74657374 test 0 0 0 4 0
Columns MD5, Filesize and Entropy should be self-explanatory.
Unique bytes counts the number of unique, different byte values contained in the file.
The Magic columns (HEX and ASCII) report the first 4 bytes of the file.
The remaining columns provide more statistical data about the contained file. They count the number of bytes of a particular type found inside the contained file. The byte types are: null bytes, control bytes, whitespace, printable bytes and high bytes.
If you need other data than displayed by option -e, use option -E (extra). This option takes a parameter describing the extra data that needs to be calculated and displayed for each file. The following variables are defined:
%INDEX%: the index of the file
%ZIPFILENAME%: the filename of the ZIP container
%FILENAME%: the filename of the contained file
%ENCRYPTED%: encrypted indicator
%TIMESTAMP%: timestamp
%LENGTH%': the length of the file
%MD5%: calculates MD5 hash
%SHA1%: calculates SHA1 hash
%SHA256%: calculates SHA256 hash
%ENTROPY%: calculates entropy
%HEADHEX%: display first 20 bytes of the file as hexadecimal
%HEADASCII%: display first 20 bytes of the file as ASCII
%TAILHEX%: display last 20 bytes of the file as hexadecimal
%TAILASCII%: display last 20 bytes of the file as ASCII
%HISTOGRAM%: calculates a histogram
this is the prevalence of each byte value (0x00 through 0xFF)
at least 3 numbers are displayed separated by a comma:
number of values with a prevalence > 0
minimum values with a prevalence > 0
maximum values with a prevalence > 0
each value with a prevalence > 0
%BYTESTATS%: calculates byte statistics
byte statistics are 5 numbers separated by a comma:
number of NULL bytes
number of control bytes
number of whitespace bytes
number of printable bytes
number of high bytes
Example adding the SHA256 hash to the report:
C:\Demo>zipdump.py -E "%SHA256%" example.zip
Index Filename Encrypted Timestamp
1 Dialog42.exe 0 2012-02-25 12:08:26 0a391054e50a4808553466263c9c3b63e895be02c957dbb957da3ba96670cf34
2 readme.txt 0 2015-11-24 19:40:12 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
The parameter for -E may contain other text than the variables, which will be printed. Escape characters \\n and \\t are supported.
Example displaying the MD5 and SHA256 hash per file, separated by a - character:
C:\Demo>zipdump.py -E "%MD5%-%SHA256%" example.zip
Index Filename Encrypted Timestamp
1 Dialog42.exe 0 2012-02-25 12:08:26 9b7f8260724e2cb643ad0729ec995b40-0a391054e50a4808553466263c9c3b63e895be02c957dbb957da3ba96670cf34
2 readme.txt 0 2015-11-24 19:40:12 098f6bcd4621d373cade4e832627b4f6-9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
If the extra parameter starts with !, then it replaces the complete output line (in stead of being appended to the output line).
Example:
C:\Demo>zipdump.py -E "!%FILENAME%;%SHA256%" example.zip
Dialog42.exe;0a391054e50a4808553466263c9c3b63e895be02c957dbb957da3ba96670cf34
readme.txt;9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
If the extra parameter starts with #, then it produces a summary of output.
Example:
C:\Demo>zipdump.py -E "#%HEADASCII%;%HEADHEX%" Book1.xlsm
1: --..............;d0cf11e0a1b11ae10000000000000000
1: <xml xmlns:v="ur;3c786d6c20786d6c6e733a763d227572
12: <?xml version="1;3c3f786d6c2076657273696f6e3d2231
To include extra data with each use of zipdump, define environment variable ZIPDUMP_EXTRA with the parameter that should be passed to -E. When environment variable ZIPDUMP_EXTRA is defined, option -E can be ommited. When option -E is used together with environment variable ZIPDUMP_EXTRA, the parameter of option -E is used and the environment variable is ignored.
zipdump supports YARA rules. Installation of the YARA Python module is not mandatory if you don't use YARA rules.
You provide the YARA rules with option -y. You can provide one file with YARA rules, an at-file (@file containing the filenames of the YARA files) or a directory. In case of a directory, all files inside the directory are read as YARA files.
Or you can provide the YARA rule with the option value if it starts with # (literal), #s# (string), #q# (quote), #h# (hexadecimal) or #b# (base64). Example: -y "#rule demo {strings: $a=\"demo\" condition: $a}"
Using #s#demo will instruct zipdump to generate a rule to search for string demo (rule string {strings: $a = "demo" ascii wide nocase condition: $a) and use that rule.
All files inside the ZIP file are scanned with the provided YARA rules, you can not use option -s to select an individual file.
Example:
C:\Demo>zipdump.py -y contains_pe_file.yara example.zip
Index Filename Decoder YARA namespace YARA rule
1 Dialog42.exe contains_pe_file.yara Contains_PE_File
In this example, you use YARA rule contains_pe_file.yara to find PE files (executables) inside ZIP files. The rule triggered for file 1, because it contains an EXE file.
If you want more information about what was detected by the YARA rule, use option --yarastrings like in this example:
C:\Demo>zipdump.py -y contains_pe_file.yara --yarastrings example.zip
Index Filename Decoder YARA namespace YARA rule
1 Dialog42.exe contains_pe_file.yara Contains_PE_File 000000 $a 4d5a 'MZ'
Use option --yarastringsraw to see only the matched strings, and nothing more.
YARA rule contains_pe_file detects PE files by finding string MZ followed by string PE at the correct offset (AddressOfNewExeHeader).
The rule looks like this:
rule Contains_PE_File
{
meta:
author = "Didier Stevens (https://DidierStevens.com)"
description = "Detect a PE file inside a byte sequence"
method = "Find string MZ followed by string PE at the correct offset (AddressOfNewExeHeader)"
strings:
$a = "MZ"
condition:
for any i in (1..#a): (uint32(@a[i] + uint32(@a[i] + 0x3C)) == 0x00004550)
}
To deal with encoded files, zipdump supports decoders. A decoder is a type of plugin, that will bruteforce a type of encoding on each file. For example, decoder_xor1 will encode each file via XOR and a key of 1 byte. So effectively, 256 different encodings of the file will be scanned by the YARA rules. 256 encodings because: XOR key 0x00, XOR key 0x01, XOR key 0x02, ..., XOR key 0xFF
Here is an example:
C:\Demo>zipdump.py -y contains_pe_file.yara -C decoder_xor1 example.zip
Index Filename Decoder YARA namespace YARA rule
1 Dialog42.exe contains_pe_file.yara Contains_PE_File
3 Dialog42.exe.XORx14 XOR 1 byte key 0x14 contains_pe_file.yara Contains_PE_File
The YARA rule triggers on file 3. It contains a PE file encoded via XORing each byte with key 0x14.
You can specify more than one decoder separated by a comma ,.
C:\Demo>zipdump.py -y contains_pe_file.yara -C decoder_xor1,decoder_rol1,decoder_add1 example.zip
Some decoders take options, to be provided with option --decoderoptions.
Use option -v to have verbose error messages when debugging your decoders.
With option -j, zipdump will output the content of the ZIP file as a JSON object that can be piped into other tools that support this JSON format.
When a file contains more than one ZIP file, option -f (find) can be used to detect this and select distinct ZIP files.
We will use double.zip, it is a PoC ZIP file: it is the concatenation of 2 ZIP files, the first ZIP file contains a single text file, the second ZIP file contains a single EXE file.
When zipdump is used to analyse this file, only the second ZIP file (e.g. last) is analyzed:
C:\Demo>zipdump.py double.zip
Index Filename Encrypted Timestamp
1 Dialog42.exe 0 2012-02-25 12:08:26
To detect the presence of multiple ZIP files, use option -f with value list (or letter l, initial of list), like this:
C:\Demo>zipdump.py -f list double.zip
0x00000000 PK0304 fil b'file.txt'
0x000002bf PK0102 dir b'file.txt'
1 0x00000319 PK0506 end
0x0000032f PK0304 fil b'Dialog42.exe'
0x000078ef PK0102 dir b'Dialog42.exe'
2 0x0000794d PK0506 end
Option "-f list" lists all PK records it finds of the following type:
PK0304 local file header
PK0102 central directory header
PK0506 end of central directory
The presence of more than one "end of central directory" record indicates the presence of multiple ZIP files. Compare the result above for double.zip with a single ZIP file:
C:\Demo>zipdump.py -f list example.zip
0x00000000 PK0304 fil b'Dialog42.exe'
0x000075c0 PK0102 dir b'Dialog42.exe'
1 0x0000761e PK0506 end
Every "end of central directory" record is prefixed by an index, that can be used to select that particular ZIP file for further analysis, using option -f like this (option "-f 1", index number 1):
C:\Demo>zipdump.py -f 1 double.zip
Index Filename Encrypted Timestamp
1 file.txt 0 2019-12-03 22:55:46
Option -f can be combined with all other zipdump options, to further analyze the selected ZIP file. Example:
C:\Demo>zipdump.py -f 1 -s 1 -a double.zip | head
00000000: 50 6F 72 74 74 69 74 6F 72 20 6C 75 63 74 75 73 Porttitor luctus
00000010: 20 72 69 73 75 73 20 6E 69 73 69 20 6F 64 69 6F risus nisi odio
00000020: 20 73 63 65 6C 65 72 69 73 71 75 65 20 70 6F 73 scelerisque pos
00000030: 75 65 72 65 20 6E 75 6C 6C 61 20 65 6C 65 69 66 uere nulla eleif
00000040: 65 6E 64 20 63 6F 6E 73 65 63 74 65 74 75 72 20 end consectetur
00000050: 6E 69 73 6C 20 74 65 6D 70 6F 72 20 73 61 67 69 nisl tempor sagi
00000060: 74 74 69 73 20 63 75 72 73 75 73 20 65 67 65 73 ttis cursus eges
00000070: 74 61 73 20 64 6F 6E 65 63 20 6E 61 74 6F 71 75 tas donec natoqu
00000080: 65 20 64 69 67 6E 69 73 73 69 6D 20 65 74 20 6A e dignissim et j
00000090: 75 73 74 6F 20 74 69 6E 63 69 64 75 6E 74 20 75 usto tincidunt u
Option -i can be used together with option -f to provide info about the selected end-of-central-directory record (in stead of analyzing the ZIP file). Example:
C:\Demo>zipdump.py -f 1 -i sample.vir
EOCD (End Of Central Directory) record: PK\\x05\\x06
Disk number field: 0
Start disk number field: 0
Entries on disk field: 15
Entries in directory field: 15
Directory size field: 975
Directory offset field: 87903 (0x0001575f)
Incomplete comment length field, missing 1 byte(s)
00000000: 00
If data precedes the first record, or succeeds the last record, an entry with index p (prefix) and/or index s (suffix) will be included in the list of records:
C:\Demo>zipdump.py -f list prefix-double.zip
p 0x00000000 data 0:58120l
0x0000e308 PK0304 fil b'file.txt'
0x0000e5c7 PK0102 dir b'file.txt'
1 0x0000e621 PK0506 end
0x0000e637 PK0304 fil b'Dialog42.exe'
0x00015bf7 PK0102 dir b'Dialog42.exe'
2 0x00015c55 PK0506 end
C:\Demo>zipdump.py -f list double-suffix.zip
0x00000000 PK0304 fil b'file.txt'
0x000002bf PK0102 dir b'file.txt'
1 0x00000319 PK0506 end
0x0000032f PK0304 fil b'Dialog42.exe'
0x000078ef PK0102 dir b'Dialog42.exe'
2 0x0000794d PK0506 end
s 0x00007963 data 31075:58120l
When p or s is selected with option -f, the selected data is dumped according to the dump flags (-d, -a, -x, -t).
Option -c (--cut) allows for the partial selection of a file. Use this option to "cut out" part of the file.
The --cut option takes an argument to specify which section of bytes to select from the file. This argument is composed of 2 terms separated by a colon (:), like this:
termA:termB
termA and termB can be:
- nothing (an empty string)
- a positive decimal number; example: 10
- an hexadecimal number (to be preceded by 0x); example: 0x10
- a case sensitive string to search for (surrounded by square brackets and single quotes); example: ['MZ']
- an hexadecimal string to search for (surrounded by square brackets); example: [d0cf11e0]
If termA is nothing, then the cut section of bytes starts with the byte at position 0.
If termA is a number, then the cut section of bytes starts with the byte at the position given by the number (first byte has index 0).
If termA is a string to search for, then the cut section of bytes starts with the byte at the position where the string is first found. If the string is not found, the cut is empty (0 bytes).
If termB is nothing, then the cut section of bytes ends with the last byte.
If termB is a number, then the cut section of bytes ends with the byte at the position given by the number (first byte has index 0).
When termB is a number, it can have suffix letter l. This indicates that the number is a length (number of bytes), and not a position.
termB can also be a negative number (decimal or hexademical): in that case the position is counted from the end of the file. For example, :-5 selects the complete file except the last 5 bytes.
If termB is a string to search for, then the cut section of bytes ends with the last byte at the position where the string is first found. If the string is not found, the cut is empty (0 bytes).
No checks are made to assure that the position specified by termA is lower than the position specified by termB. This is left up to the user.
Search string expressions (ASCII and hexadecimal) can be followed by an instance (a number equal to 1 or greater) to indicate which instance needs to be taken. For example, ['ABC']2 will search for the second instance of string 'ABC'. If this instance is not found, then nothing is selected.
Search string expressions (ASCII and hexadecimal) can be followed by an offset (+ or - a number) to add (or substract) an offset to the found instance. For example, ['ABC']+3 will search for the first instance of string 'ABC' and then select the bytes after ABC (+ 3).
Finally, search string expressions (ASCII and hexadecimal) can be followed by an instance and an offset.
Examples:
This argument can be used to dump the first 256 bytes of a PE file located inside the file: ['MZ']:0x100l
This argument can be used to dump the OLE file located inside the file: [d0cf11e0]:
When this option is not used, the complete file is selected.
'''
for line in manual.split('\n'):
print(textwrap.fill(line, 78))
#Convert 2 Bytes If Python 3
def C2BIP3(string):
if sys.version_info[0] > 2:
if type(string) == bytes:
return string
else:
return bytes([ord(x) for x in string])
else:
return string
def P23Ord(value):
if type(value) == int:
return value
else:
return ord(value)
def P23Chr(value):
if type(value) == int:
return chr(value)
else:
return value
def FixPipe():
try:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
except:
pass
def ToString(value):
if type(value) == type(''):
return value
else:
return str(value)
def Quote(value, separator, quote):
value = ToString(value)
if separator in value:
return quote + value + quote
else:
return value
def FormatTime(epoch=None):
if epoch == None:
epoch = time.time()
return '%04d/%02d/%02d %02d:%02d:%02d' % time.localtime(epoch)[0:6]
def MakeCSVLine(row, separator, quote):
return separator.join([Quote(value, separator, quote) for value in row])
def Print(line, f):
if f == None:
print(line)
else:
f.write(line +'\n')
dumplinelength = 16
# CIC: Call If Callable
def CIC(expression):
if callable(expression):
return expression()
else:
return expression
# IFF: IF Function
def IFF(expression, valueTrue, valueFalse):
if expression:
return CIC(valueTrue)
else:
return CIC(valueFalse)
def File2Strings(filename):
try:
if os.path.splitext(filename)[1].lower() == '.gz':
f = gzip.GzipFile(filename, 'rb')
else:
f = open(filename, 'r')
except:
return None
try:
return map(lambda line:line.rstrip('\n\r'), f.readlines())
except:
return None
finally:
f.close()
def ProcessAt(argument):
if argument.startswith('@'):
strings = File2Strings(argument[1:])
if strings == None:
raise Exception('Error reading %s' % argument)
else:
return strings
else:
return [argument]
def CreateZipFileObject(arg1, arg2):
if 'AESZipFile' in dir(zipfile):
return zipfile.AESZipFile(arg1, arg2)
else:
return zipfile.ZipFile(arg1, arg2)
def YARACompile(ruledata):
if ruledata.startswith('#'):
if ruledata.startswith('#h#'):
rule = binascii.a2b_hex(ruledata[3:])
elif ruledata.startswith('#b#'):
rule = binascii.a2b_base64(ruledata[3:])
elif ruledata.startswith('#s#'):
rule = 'rule string {strings: $a = "%s" ascii wide nocase condition: $a}' % ruledata[3:]
elif ruledata.startswith('#q#'):
rule = ruledata[3:].replace("'", '"')
else:
rule = ruledata[1:]
return yara.compile(source=rule)
else:
dFilepaths = {}
if os.path.isdir(ruledata):
for root, dirs, files in os.walk(ruledata):
for file in files:
filename = os.path.join(root, file)
dFilepaths[filename] = filename
else:
for filename in ProcessAt(ruledata):
dFilepaths[filename] = filename
return yara.compile(filepaths=dFilepaths)
class cDump():
def __init__(self, data, prefix='', offset=0, dumplinelength=16):
self.data = data
self.prefix = prefix
self.offset = offset
self.dumplinelength = dumplinelength
def HexDump(self):
oDumpStream = self.cDumpStream(self.prefix)
hexDump = ''
for i, b in enumerate(self.data):
if i % self.dumplinelength == 0 and hexDump != '':
oDumpStream.Addline(hexDump)
hexDump = ''
hexDump += IFF(hexDump == '', '', ' ') + '%02X' % self.C2IIP2(b)
oDumpStream.Addline(hexDump)
return oDumpStream.Content()
def CombineHexAscii(self, hexDump, asciiDump):
if hexDump == '':
return ''
countSpaces = 3 * (self.dumplinelength - len(asciiDump))
if len(asciiDump) <= self.dumplinelength / 2:
countSpaces += 1
return hexDump + ' ' + (' ' * countSpaces) + asciiDump
def HexAsciiDump(self):
oDumpStream = self.cDumpStream(self.prefix)
hexDump = ''
asciiDump = ''
for i, b in enumerate(self.data):
b = self.C2IIP2(b)
if i % self.dumplinelength == 0:
if hexDump != '':
oDumpStream.Addline(self.CombineHexAscii(hexDump, asciiDump))
hexDump = '%08X:' % (i + self.offset)
asciiDump = ''
if i % self.dumplinelength == self.dumplinelength / 2:
hexDump += ' '
hexDump += ' %02X' % b
asciiDump += IFF(b >= 32 and b < 127, chr(b), '.')
oDumpStream.Addline(self.CombineHexAscii(hexDump, asciiDump))
return oDumpStream.Content()
def Base64Dump(self, nowhitespace=False):
encoded = binascii.b2a_base64(self.data)
if nowhitespace:
return encoded
oDumpStream = self.cDumpStream(self.prefix)
length = 64
for i in range(0, len(encoded), length):
oDumpStream.Addline(encoded[0+i:length+i])
return oDumpStream.Content()
class cDumpStream():
def __init__(self, prefix=''):
self.oStringIO = StringIO()
self.prefix = prefix
def Addline(self, line):
if line != '':
self.oStringIO.write(self.prefix + line + '\n')
def Content(self):
return self.oStringIO.getvalue()
@staticmethod
def C2IIP2(data):
if sys.version_info[0] > 2:
return data
else:
return ord(data)
def HexDump(data):
return cDump(data, dumplinelength=dumplinelength).HexDump()
def HexAsciiDump(data):
return cDump(data, dumplinelength=dumplinelength).HexAsciiDump()
def Translate(expression):
try:
codecs.lookup(expression)
command = '.decode("%s")' % expression
except LookupError:
command = expression
return lambda x: eval('x' + command)
#-BEGINCODE cBinaryFile------------------------------------------------------------------------------
#import random
#import binascii
#import zipfile
#import gzip
#import sys
#if sys.version_info[0] >= 3:
# from io import BytesIO as DataIO
#else:
# from cStringIO import StringIO as DataIO
def LoremIpsumSentence(minimum, maximum):
words = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'etiam', 'tortor', 'metus', 'cursus', 'sed', 'sollicitudin', 'ac', 'sagittis', 'eget', 'massa', 'praesent', 'sem', 'fermentum', 'dignissim', 'in', 'vel', 'augue', 'scelerisque', 'auctor', 'libero', 'nam', 'a', 'gravida', 'odio', 'duis', 'vestibulum', 'vulputate', 'quam', 'nec', 'cras', 'nibh', 'feugiat', 'ut', 'vitae', 'ornare', 'justo', 'orci', 'varius', 'natoque', 'penatibus', 'et', 'magnis', 'dis', 'parturient', 'montes', 'nascetur', 'ridiculus', 'mus', 'curabitur', 'nisl', 'egestas', 'urna', 'iaculis', 'lectus', 'maecenas', 'ultrices', 'velit', 'eu', 'porta', 'hac', 'habitasse', 'platea', 'dictumst', 'integer', 'id', 'commodo', 'mauris', 'interdum', 'malesuada', 'fames', 'ante', 'primis', 'faucibus', 'accumsan', 'pharetra', 'aliquam', 'nunc', 'at', 'est', 'non', 'leo', 'nulla', 'sodales', 'porttitor', 'facilisis', 'aenean', 'condimentum', 'rutrum', 'facilisi', 'tincidunt', 'laoreet', 'ultricies', 'neque', 'diam', 'euismod', 'consequat', 'tempor', 'elementum', 'lobortis', 'erat', 'ligula', 'risus', 'donec', 'phasellus', 'quisque', 'vivamus', 'pellentesque', 'tristique', 'venenatis', 'purus', 'mi', 'dictum', 'posuere', 'fringilla', 'quis', 'magna', 'pretium', 'felis', 'pulvinar', 'lacinia', 'proin', 'viverra', 'lacus', 'suscipit', 'aliquet', 'dui', 'molestie', 'dapibus', 'mollis', 'suspendisse', 'sapien', 'blandit', 'morbi', 'tellus', 'enim', 'maximus', 'semper', 'arcu', 'bibendum', 'convallis', 'hendrerit', 'imperdiet', 'finibus', 'fusce', 'congue', 'ullamcorper', 'placerat', 'nullam', 'eros', 'habitant', 'senectus', 'netus', 'turpis', 'luctus', 'volutpat', 'rhoncus', 'mattis', 'nisi', 'ex', 'tempus', 'eleifend', 'vehicula', 'class', 'aptent', 'taciti', 'sociosqu', 'ad', 'litora', 'torquent', 'per', 'conubia', 'nostra', 'inceptos', 'himenaeos']
sample = random.sample(words, random.randint(minimum, maximum))
sample[0] = sample[0].capitalize()
return ' '.join(sample) + '.'
def LoremIpsum(sentences):
return ' '.join([LoremIpsumSentence(15, 30) for i in range(sentences)])
STATE_START = 0
STATE_IDENTIFIER = 1
STATE_STRING = 2
STATE_SPECIAL_CHAR = 3
STATE_ERROR = 4
FUNCTIONNAME_REPEAT = 'repeat'
FUNCTIONNAME_RANDOM = 'random'
FUNCTIONNAME_CHR = 'chr'
FUNCTIONNAME_LOREMIPSUM = 'loremipsum'
def Tokenize(expression):
result = []
token = ''
state = STATE_START
while expression != '':
char = expression[0]
expression = expression[1:]
if char == "'":
if state == STATE_START:
state = STATE_STRING
elif state == STATE_IDENTIFIER:
result.append([STATE_IDENTIFIER, token])
state = STATE_STRING
token = ''
elif state == STATE_STRING:
result.append([STATE_STRING, token])
state = STATE_START
token = ''
elif char >= '0' and char <= '9' or char.lower() >= 'a' and char.lower() <= 'z':
if state == STATE_START:
token = char
state = STATE_IDENTIFIER
else:
token += char
elif char == ' ':
if state == STATE_IDENTIFIER:
result.append([STATE_IDENTIFIER, token])
token = ''
state = STATE_START
elif state == STATE_STRING:
token += char
else:
if state == STATE_IDENTIFIER:
result.append([STATE_IDENTIFIER, token])
token = ''
state = STATE_START
result.append([STATE_SPECIAL_CHAR, char])
elif state == STATE_STRING:
token += char
else:
result.append([STATE_SPECIAL_CHAR, char])
token = ''
if state == STATE_IDENTIFIER:
result.append([state, token])
elif state == STATE_STRING:
result = [[STATE_ERROR, 'Error: string not closed', token]]
return result
def ParseFunction(tokens):
if len(tokens) == 0:
print('Parsing error')
return None, tokens
if tokens[0][0] == STATE_STRING or tokens[0][0] == STATE_IDENTIFIER and tokens[0][1].startswith('0x'):
return [[FUNCTIONNAME_REPEAT, [[STATE_IDENTIFIER, '1'], tokens[0]]], tokens[1:]]
if tokens[0][0] != STATE_IDENTIFIER:
print('Parsing error')
return None, tokens
function = tokens[0][1]
tokens = tokens[1:]
if len(tokens) == 0:
print('Parsing error')
return None, tokens
if tokens[0][0] != STATE_SPECIAL_CHAR or tokens[0][1] != '(':
print('Parsing error')
return None, tokens
tokens = tokens[1:]
if len(tokens) == 0:
print('Parsing error')
return None, tokens
arguments = []
while True:
if tokens[0][0] != STATE_IDENTIFIER and tokens[0][0] != STATE_STRING:
print('Parsing error')
return None, tokens
arguments.append(tokens[0])
tokens = tokens[1:]
if len(tokens) == 0:
print('Parsing error')
return None, tokens
if tokens[0][0] != STATE_SPECIAL_CHAR or (tokens[0][1] != ',' and tokens[0][1] != ')'):
print('Parsing error')
return None, tokens
if tokens[0][0] == STATE_SPECIAL_CHAR and tokens[0][1] == ')':
tokens = tokens[1:]
break
tokens = tokens[1:]
if len(tokens) == 0:
print('Parsing error')
return None, tokens
return [[function, arguments], tokens]
def Parse(expression):
tokens = Tokenize(expression)
if len(tokens) == 0:
print('Parsing error')
return None
if tokens[0][0] == STATE_ERROR:
print(tokens[0][1])
print(tokens[0][2])
print(expression)
return None
functioncalls = []
while True:
functioncall, tokens = ParseFunction(tokens)
if functioncall == None:
return None
functioncalls.append(functioncall)
if len(tokens) == 0:
return functioncalls
if tokens[0][0] != STATE_SPECIAL_CHAR or tokens[0][1] != '+':
print('Parsing error')
return None
tokens = tokens[1:]
def InterpretInteger(token):
if token[0] != STATE_IDENTIFIER:
return None
try:
return int(token[1])
except:
return None
def Hex2Bytes(hexadecimal):
if len(hexadecimal) % 2 == 1:
hexadecimal = '0' + hexadecimal
try:
return binascii.a2b_hex(hexadecimal)
except:
return None
def InterpretHexInteger(token):
if token[0] != STATE_IDENTIFIER:
return None
if not token[1].startswith('0x'):
return None
bytes = Hex2Bytes(token[1][2:])
if bytes == None:
return None
integer = 0
for byte in bytes:
integer = integer * 0x100 + C2IIP2(byte)
return integer
def InterpretNumber(token):
number = InterpretInteger(token)
if number == None:
return InterpretHexInteger(token)
else:
return number
def InterpretBytes(token):
if token[0] == STATE_STRING:
return token[1]
if token[0] != STATE_IDENTIFIER:
return None
if not token[1].startswith('0x'):
return None
return Hex2Bytes(token[1][2:])
def CheckFunction(functionname, arguments, countarguments, maxcountarguments=None):
if maxcountarguments == None:
if countarguments == 0 and len(arguments) != 0:
print('Error: function %s takes no arguments, %d are given' % (functionname, len(arguments)))
return True
if countarguments == 1 and len(arguments) != 1:
print('Error: function %s takes 1 argument, %d are given' % (functionname, len(arguments)))
return True
if countarguments != len(arguments):
print('Error: function %s takes %d arguments, %d are given' % (functionname, countarguments, len(arguments)))
return True
else:
if len(arguments) < countarguments or len(arguments) > maxcountarguments:
print('Error: function %s takes between %d and %d arguments, %d are given' % (functionname, countarguments, maxcountarguments, len(arguments)))
return True
return False
def CheckNumber(argument, minimum=None, maximum=None):
number = InterpretNumber(argument)
if number == None:
print('Error: argument should be a number: %s' % argument[1])
return None
if minimum != None and number < minimum:
print('Error: argument should be minimum %d: %d' % (minimum, number))
return None
if maximum != None and number > maximum:
print('Error: argument should be maximum %d: %d' % (maximum, number))
return None
return number
def Interpret(expression):
functioncalls = Parse(expression)
if functioncalls == None:
return None
decoded = ''
for functioncall in functioncalls:
functionname, arguments = functioncall
if functionname == FUNCTIONNAME_REPEAT:
if CheckFunction(functionname, arguments, 2):
return None
number = CheckNumber(arguments[0], minimum=1)
if number == None:
return None
bytes = InterpretBytes(arguments[1])
if bytes == None:
print('Error: argument should be a byte sequence: %s' % arguments[1][1])
return None
decoded += number * bytes
elif functionname == FUNCTIONNAME_RANDOM:
if CheckFunction(functionname, arguments, 1):
return None
number = CheckNumber(arguments[0], minimum=1)
if number == None:
return None
decoded += ''.join([chr(random.randint(0, 255)) for x in range(number)])
elif functionname == FUNCTIONNAME_LOREMIPSUM:
if CheckFunction(functionname, arguments, 1):
return None
number = CheckNumber(arguments[0], minimum=1)
if number == None:
return None
decoded += LoremIpsum(number)
elif functionname == FUNCTIONNAME_CHR:
if CheckFunction(functionname, arguments, 1, 2):
return None
number = CheckNumber(arguments[0], minimum=0, maximum=255)
if number == None:
return None
if len(arguments) == 1:
decoded += chr(number)
else:
number2 = CheckNumber(arguments[1], minimum=0, maximum=255)
if number2 == None:
return None
if number < number2:
decoded += ''.join([chr(n) for n in range(number, number2 + 1)])
else:
decoded += ''.join([chr(n) for n in range(number, number2 - 1, -1)])
else:
print('Error: unknown function: %s' % functionname)
return None
return decoded
FCH_FILENAME = 0
FCH_DATA = 1
FCH_ERROR = 2
def FilenameCheckHash(filename, literalfilename):
if literalfilename:
return FCH_FILENAME, filename
elif filename.startswith('#h#'):
result = Hex2Bytes(filename[3:])
if result == None:
return FCH_ERROR, 'hexadecimal'
else:
return FCH_DATA, result
elif filename.startswith('#b#'):
try:
return FCH_DATA, binascii.a2b_base64(filename[3:])
except:
return FCH_ERROR, 'base64'
elif filename.startswith('#e#'):
result = Interpret(filename[3:])
if result == None:
return FCH_ERROR, 'expression'
else:
return FCH_DATA, result
elif filename.startswith('#'):
return FCH_DATA, C2BIP3(filename[1:])
else:
return FCH_FILENAME, filename
def AnalyzeFileError(filename):
PrintError('Error opening file %s' % filename)
PrintError(sys.exc_info()[1])
try:
if not os.path.exists(filename):
PrintError('The file does not exist')
elif os.path.isdir(filename):
PrintError('The file is a directory')
elif not os.path.isfile(filename):
PrintError('The file is not a regular file')
except:
pass
class cBinaryFile:
def __init__(self, filename, zippassword='infected', noextraction=False, literalfilename=False):
self.filename = filename
self.zippassword = zippassword
self.noextraction = noextraction
self.literalfilename = literalfilename
self.oZipfile = None
self.extracted = False
self.fIn = None
fch, data = FilenameCheckHash(self.filename, self.literalfilename)
if fch == FCH_ERROR:
line = 'Error %s parsing filename: %s' % (data, self.filename)
raise Exception(line)
try:
if self.filename == '':
if sys.platform == 'win32':
import msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
self.fIn = sys.stdin
elif fch == FCH_DATA:
self.fIn = DataIO(data)
elif not self.noextraction and self.filename.lower().endswith('.zip'):
self.oZipfile = CreateZipFileObject(self.filename, 'r')
if len(self.oZipfile.infolist()) == 1:
self.fIn = self.oZipfile.open(self.oZipfile.infolist()[0], 'r', C2BIP3(self.zippassword))
self.extracted = True
else:
self.oZipfile.close()
self.oZipfile = None
self.fIn = open(self.filename, 'rb')
elif not self.noextraction and self.filename.lower().endswith('.gz'):
self.fIn = gzip.GzipFile(self.filename, 'rb')
self.extracted = True
else:
self.fIn = open(self.filename, 'rb')
except:
AnalyzeFileError(self.filename)
raise
def close(self):
if self.fIn != sys.stdin and self.fIn != None:
self.fIn.close()
if self.oZipfile != None:
self.oZipfile.close()
def read(self, size=None):
try:
fRead = self.fIn.buffer
except:
fRead = self.fIn
if size == None:
return fRead.read()
else:
return fRead.read(size)
def Data(self):
data = self.read()
self.close()
return data
#-ENDCODE cBinaryFile--------------------------------------------------------------------------------
#Fix for http://bugs.python.org/issue11395
def StdoutWriteChunked(data):
if sys.version_info[0] > 2:
sys.stdout.buffer.write(C2BIP3(data))
else:
while data != '':
sys.stdout.write(data[0:10000])
try:
sys.stdout.flush()
except IOError:
return
data = data[10000:]
def Magic(data):
magicPrintable = ''
magicHex = ''
for iter in range(4):
if len(data) >= iter + 1:
if P23Ord(data[iter]) >= 0x20 and P23Ord(data[iter]) < 0x7F:
magicPrintable += P23Chr(data[iter])
else:
magicPrintable += '.'
magicHex += '%02x' % P23Ord(data[iter])
return magicPrintable, magicHex
def CalculateByteStatistics(dPrevalence):
sumValues = sum(dPrevalence.values())
countNullByte = dPrevalence[0]
countControlBytes = 0
countWhitespaceBytes = 0
countUniqueBytes = 0
for iter in range(1, 0x21):
if chr(iter) in string.whitespace:
countWhitespaceBytes += dPrevalence[iter]
else:
countControlBytes += dPrevalence[iter]
countControlBytes += dPrevalence[0x7F]
countPrintableBytes = 0
for iter in range(0x21, 0x7F):
countPrintableBytes += dPrevalence[iter]
countHighBytes = 0
for iter in range(0x80, 0x100):
countHighBytes += dPrevalence[iter]
entropy = 0.0
for iter in range(0x100):
if dPrevalence[iter] > 0:
prevalence = float(dPrevalence[iter]) / float(sumValues)
entropy += - prevalence * math.log(prevalence, 2)
countUniqueBytes += 1
return sumValues, entropy, countUniqueBytes, countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes
def CalculateFileMetaData(data):
dPrevalence = {}
for iter in range(256):
dPrevalence[iter] = 0
for char in data:
dPrevalence[P23Ord(char)] += 1
fileSize, entropy, countUniqueBytes, countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes = CalculateByteStatistics(dPrevalence)
magicPrintable, magicHex = Magic(data[0:4])
return hashlib.md5(data).hexdigest(), magicPrintable, magicHex, fileSize, entropy, countUniqueBytes, countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes
def AddDecoder(cClass):
global decoders
decoders.append(cClass)
class cDecoderParent():
pass
def LoadDecoders(decoders, decoderdir, verbose):
if decoders == '':
return
if decoderdir == '':
scriptPath = GetScriptPath()
else:
scriptPath = decoderdir
for decoder in sum(map(ProcessAt, decoders.split(',')), []):
try:
if not decoder.lower().endswith('.py'):
decoder += '.py'
if os.path.dirname(decoder) == '':
if not os.path.exists(decoder):
scriptDecoder = os.path.join(scriptPath, decoder)
if os.path.exists(scriptDecoder):
decoder = scriptDecoder
exec(open(decoder, 'r').read(), globals(), globals())
except Exception as e:
print('Error loading decoder: %s' % decoder)
if verbose:
raise e
class cIdentity(cDecoderParent):
name = 'Identity function decoder'
def __init__(self, stream, options):
self.stream = stream
self.options = options
self.available = True
def Available(self):
return self.available
def Decode(self):
self.available = False
return self.stream
def Name(self):
return ''
def DecodeFunction(decoders, options, stream):
if decoders == []:
return stream
return decoders[0](stream, options.decoderoptions).Decode()
CUTTERM_NOTHING = 0
CUTTERM_POSITION = 1
CUTTERM_FIND = 2
CUTTERM_LENGTH = 3
def Replace(string, dReplacements):
if string in dReplacements:
return dReplacements[string]
else:
return string
def ParseCutTerm(argument):
if argument == '':
return CUTTERM_NOTHING, None, ''
oMatch = re.match(r'\-?0x([0-9a-f]+)', argument, re.I)
if oMatch == None:
oMatch = re.match(r'\-?(\d+)', argument)
else:
value = int(oMatch.group(1), 16)
if argument.startswith('-'):
value = -value
return CUTTERM_POSITION, value, argument[len(oMatch.group(0)):]
if oMatch == None:
oMatch = re.match(r'\[([0-9a-f]+)\](\d+)?([+-]\d+)?', argument, re.I)
else:
value = int(oMatch.group(1))
if argument.startswith('-'):
value = -value
return CUTTERM_POSITION, value, argument[len(oMatch.group(0)):]
if oMatch == None:
oMatch = re.match(r"\[\'(.+?)\'\](\d+)?([+-]\d+)?", argument)
else:
if len(oMatch.group(1)) % 2 == 1:
raise Exception("Uneven length hexadecimal string")
else:
return CUTTERM_FIND, (binascii.a2b_hex(oMatch.group(1)), int(Replace(oMatch.group(2), {None: '1'})), int(Replace(oMatch.group(3), {None: '0'}))), argument[len(oMatch.group(0)):]
if oMatch == None:
return None, None, argument
else:
return CUTTERM_FIND, (oMatch.group(1), int(Replace(oMatch.group(2), {None: '1'})), int(Replace(oMatch.group(3), {None: '0'}))), argument[len(oMatch.group(0)):]
def ParseCutArgument(argument):
type, value, remainder = ParseCutTerm(argument.strip())
if type == CUTTERM_NOTHING:
return CUTTERM_NOTHING, None, CUTTERM_NOTHING, None
elif type == None:
if remainder.startswith(':'):
typeLeft = CUTTERM_NOTHING
valueLeft = None
remainder = remainder[1:]
else:
return None, None, None, None
else:
typeLeft = type
valueLeft = value
if typeLeft == CUTTERM_POSITION and valueLeft < 0:
return None, None, None, None
if typeLeft == CUTTERM_FIND and valueLeft[1] == 0:
return None, None, None, None
if remainder.startswith(':'):
remainder = remainder[1:]
else:
return None, None, None, None
type, value, remainder = ParseCutTerm(remainder)
if type == CUTTERM_POSITION and remainder == 'l':
return typeLeft, valueLeft, CUTTERM_LENGTH, value
elif type == None or remainder != '':
return None, None, None, None
elif type == CUTTERM_FIND and value[1] == 0:
return None, None, None, None
else:
return typeLeft, valueLeft, type, value
def Find(data, value, nth):
position = -1
while nth > 0:
position = data.find(value, position + 1)
if position == -1:
return -1
nth -= 1
return position
def CutData(stream, cutArgument):
if cutArgument == '':
return stream
typeLeft, valueLeft, typeRight, valueRight = ParseCutArgument(cutArgument)
if typeLeft == None:
return stream
if typeLeft == CUTTERM_NOTHING:
positionBegin = 0
elif typeLeft == CUTTERM_POSITION:
positionBegin = valueLeft
elif typeLeft == CUTTERM_FIND:
positionBegin = Find(stream, valueLeft[0], valueLeft[1])
if positionBegin == -1:
return ''
positionBegin += valueLeft[2]
else:
raise Exception("Unknown value typeLeft")
if typeRight == CUTTERM_NOTHING:
positionEnd = len(stream)
elif typeRight == CUTTERM_POSITION and valueRight < 0:
positionEnd = len(stream) + valueRight
elif typeRight == CUTTERM_POSITION:
positionEnd = valueRight + 1
elif typeRight == CUTTERM_LENGTH:
positionEnd = positionBegin + valueRight
elif typeRight == CUTTERM_FIND:
positionEnd = Find(stream, valueRight[0], valueRight[1])
if positionEnd == -1:
return ''
else:
positionEnd += len(valueRight[0])
positionEnd += valueRight[2]
else:
raise Exception("Unknown value typeRight")
return stream[positionBegin:positionEnd]
def ExtraInfoMD5(data):
if data == None:
return ''
return hashlib.md5(data).hexdigest()
def ExtraInfoSHA1(data):
if data == None:
return ''
return hashlib.sha1(data).hexdigest()
def ExtraInfoSHA256(data):
if data == None:
return ''
return hashlib.sha256(data).hexdigest()
def ExtraInfoENTROPY(data):
if data == None:
return ''
dPrevalence = {iter: 0 for iter in range(0x100)}
for char in data:
dPrevalence[P23Ord(char)] += 1
sumValues, entropy, countUniqueBytes, countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes = CalculateByteStatistics(dPrevalence)
return '%f' % entropy
def ExtraInfoHEADHEX(data):
if data == None:
return ''
return binascii.hexlify(data[:16]).decode()
def ExtraInfoHEADASCII(data):
if data == None:
return ''
return ''.join([IFF(P23Ord(b) >= 32 and P23Ord(b) < 127, P23Chr(b), '.') for b in data[:16]])
def ExtraInfoTAILHEX(data):
if data == None:
return ''
return binascii.hexlify(data[-16:]).decode()
def ExtraInfoTAILASCII(data):
if data == None:
return ''
return ''.join([IFF(P23Ord(b) >= 32 and P23Ord(b) < 127, P23Chr(b), '.') for b in data[-16:]])
def ExtraInfoHISTOGRAM(data):
if data == None:
return ''
dPrevalence = {iter: 0 for iter in range(0x100)}
for char in data:
dPrevalence[P23Ord(char)] += 1
result = []
count = 0
minimum = None
maximum = None
for iter in range(0x100):
if dPrevalence[iter] > 0:
result.append('0x%02x:%d' % (iter, dPrevalence[iter]))
count += 1
if minimum == None:
minimum = iter
else:
minimum = min(minimum, iter)
if maximum == None:
maximum = iter
else:
maximum = max(maximum, iter)
result.insert(0, '%d' % count)
result.insert(1, IFF(minimum == None, '', '0x%02x' % minimum))
result.insert(2, IFF(maximum == None, '', '0x%02x' % maximum))
return ','.join(result)
def ExtraInfoBYTESTATS(data):
if data == None:
return ''
dPrevalence = {iter: 0 for iter in range(0x100)}
for char in data:
dPrevalence[P23Ord(char)] += 1
sumValues, entropy, countUniqueBytes, countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes = CalculateByteStatistics(dPrevalence)
return '%d,%d,%d,%d,%d' % (countNullByte, countControlBytes, countWhitespaceBytes, countPrintableBytes, countHighBytes)
def GenerateExtraInfo(extra, index, zipfilename, filename, encrypted, timestamp, stream):
if extra == '':
return ''
if extra.startswith('!') or extra.startswith('#'):
extra = extra[1:]
dExtras = {'%INDEX%': lambda x: '%d' % index,
'%ZIPFILENAME%': lambda x: zipfilename,
'%FILENAME%': lambda x: filename,
'%ENCRYPTED%': lambda x: '%d' % encrypted,
'%TIMESTAMP%': lambda x: timestamp,
'%LENGTH%': lambda x: IFF(stream == None, '', lambda: '%d' % len(stream)),
'%MD5%': ExtraInfoMD5,
'%SHA1%': ExtraInfoSHA1,
'%SHA256%': ExtraInfoSHA256,
'%ENTROPY%': ExtraInfoENTROPY,
'%HEADHEX%': ExtraInfoHEADHEX,
'%HEADASCII%': ExtraInfoHEADASCII,
'%TAILHEX%': ExtraInfoTAILHEX,
'%TAILASCII%': ExtraInfoTAILASCII,
'%HISTOGRAM%': ExtraInfoHISTOGRAM,
'%BYTESTATS%': ExtraInfoBYTESTATS,
}
for variable in dExtras:
if variable in extra:
extra = extra.replace(variable, dExtras[variable](stream))
return extra.replace(r'\t', '\t').replace(r'\n', '\n')
def Format(string, length):
spaces = ' ' * (length - len(string))
if string.isdigit():
return spaces + string
else:
return string + spaces
def PrintOutput(output, outputExtraInfo, extra, separator, quote, fOut):
if extra.startswith('!'):
for line in outputExtraInfo[1:]:
Print(line, fOut)
elif extra.startswith('#'):
dOutput = {}
for line in outputExtraInfo[1:]:
if line in dOutput:
dOutput[line] += 1
else:
dOutput[line] = 1
for line, counter in sorted(dOutput.items(), key=operator.itemgetter(1)):
Print('%4d: %s' % (counter, line), fOut)
else:
if separator != '':
for i in range(len(output)):
Print(MakeCSVLine(output[i], separator, quote) + separator + outputExtraInfo[i], fOut)
else:
stringsOutput = [tuple(map(ToString, row)) for row in output]
lengthMaxRow = max([len(row) for row in output])
lengthsMax = [0 for i in range(lengthMaxRow)]
for i in range(lengthMaxRow):
for row in stringsOutput:
if i < len(row):
lengthsMax[i] = max(lengthsMax[i], len(row[i]))
for i in range(len(stringsOutput)):
Print(' '.join([Format(stringsOutput[i][j], lengthsMax[j]) for j in range(len(stringsOutput[i]))]) + ' ' + outputExtraInfo[i], fOut)
def IsNumeric(value):
if value == '':
return False
for c in value:
if c < '0' or c > '9':
return False
return True
def DecideToSelect(selectvalue, counter, zipfilename):
if selectvalue == '':
return True
if IsNumeric(selectvalue) and selectvalue == str(counter):
return True
return selectvalue == zipfilename
def GetDictionary(passwordfile):
if passwordfile != '.':
return File2Strings(passwordfile)
else:
# https://github.com/magnumripper/JohnTheRipper/blob/bleeding-jumbo/run/password.lst
return [
'infected',
'P@ssw0rd',
'123456',
'12345',
'password',
'password1',
'123456789',
'12345678',
'1234567890',
'abc123',
'computer',
'tigger',
'1234',
'qwerty',
'money',
'carmen',
'mickey',
'secret',
'summer',
'internet',
'a1b2c3',
'123',
'service',
'canada',
'hello',
'ranger',
'shadow',
'baseball',
'donald',
'harley',
'hockey',
'letmein',
'maggie',
'mike',
'mustang',
'snoopy',
'buster',
'dragon',
'jordan',
'michael',
'michelle',
'mindy',
'patrick',
'123abc',
'andrew',
'bear',
'calvin',
'changeme',
'diamond',
'fuckme',
'fuckyou',
'matthew',
'miller',
'tiger',
'trustno1',
'alex',
'apple',
'avalon',
'brandy',
'chelsea',
'coffee',
'falcon',
'freedom',
'gandalf',
'green',
'helpme',
'linda',
'magic',
'merlin',
'newyork',
'soccer',
'thomas',
'wizard',
'asdfgh',
'bandit',
'batman',
'boris',
'butthead',
'dorothy',
'eeyore',
'fishing',
'football',
'george',
'happy',
'iloveyou',
'jennifer',
'jonathan',
'love',
'marina',
'master',
'missy',
'monday',
'monkey',
'natasha',
'ncc1701',
'pamela',
'pepper',
'piglet',
'poohbear',
'pookie',
'rabbit',
'rachel',
'rocket',
'rose',
'smile',
'sparky',
'spring',
'steven',
'success',
'sunshine',
'victoria',
'whatever',
'zapata',
'8675309',
'amanda',
'andy',
'angel',
'august',
'barney',
'biteme',
'boomer',
'brian',
'casey',
'cowboy',
'delta',
'doctor',
'fisher',
'island',
'john',
'joshua',
'karen',
'marley',
'orange',
'please',
'rascal',
'richard',
'sarah',
'scooter',
'shalom',
'silver',
'skippy',
'stanley',
'taylor',
'welcome',
'zephyr',
'111111',
'aaaaaa',
'access',
'albert',
'alexander',
'andrea',
'anna',
'anthony',
'asdfjkl;',
'ashley',
'basketball',
'beavis',
'black',
'bob',
'booboo',
'bradley',
'brandon',
'buddy',
'caitlin',
'camaro',
'charlie',
'chicken',
'chris',
'cindy',
'cricket',
'dakota',
'dallas',
'daniel',
'david',
'debbie',
'dolphin',
'elephant',
'emily',
'friend',
'fucker',
'ginger',
'goodluck',
'hammer',
'heather',
'iceman',
'jason',
'jessica',
'jesus',
'joseph',
'jupiter',
'justin',
'kevin',
'knight',
'lacrosse',
'lakers',
'lizard',
'madison',
'mary',
'mother',
'muffin',
'murphy',
'nirvana',
'paris',
'pentium',
'phoenix',
'picture',
'rainbow',
'sandy',
'saturn',
'scott',
'shannon',
'shithead',
'skeeter',
'sophie',
'special',
'stephanie',
'stephen',
'steve',
'sweetie',
'teacher',
'tennis',
'test',
'test123',
'tommy',
'topgun',
'tristan',
'wally',
'william',
'wilson',
'1q2w3e',
'654321',
'666666',
'a12345',
'a1b2c3d4',
'alpha',
'amber',
'angela',
'angie',
'archie',
'asdf',
'blazer',
'bond007',
'booger',
'charles',
'christin',
'claire',
'control',
'danny',
'david1',
'dennis',
'digital',
'disney',
'edward',
'elvis',
'felix',
'flipper',
'franklin',
'frodo',
'honda',
'horses',
'hunter',
'indigo',
'james',
'jasper',
'jeremy',
'julian',
'kelsey',
'killer',
'lauren',
'marie',
'maryjane',
'matrix',
'maverick',
'mayday',
'mercury',
'mitchell',
'morgan',
'mountain',
'niners',
'nothing',
'oliver',
'peace',
'peanut',
'pearljam',
'phantom',
'popcorn',
'princess',
'psycho',
'pumpkin',
'purple',
'randy',
'rebecca',
'reddog',
'robert',
'rocky',
'roses',
'salmon',
'samson',
'sharon',
'sierra',
'smokey',
'startrek',
'steelers',
'stimpy',
'sunflower',
'superman',
'support',
'sydney',
'techno',
'walter',
'willie',
'willow',
'winner',
'ziggy',
'zxcvbnm',
'alaska',
'alexis',
'alice',
'animal',
'apples',
'barbara',
'benjamin',
'billy',
'blue',
'bluebird',
'bobby',
'bonnie',
'bubba',
'camera',
'chocolate',
'clark',
'claudia',
'cocacola',
'compton',
'connect',
'cookie',
'cruise',
'douglas',
'dreamer',
'dreams',
'duckie',
'eagles',
'eddie',
'einstein',
'enter',
'explorer',
'faith',
'family',
'ferrari',
'flamingo',
'flower',
'foxtrot',
'francis',
'freddy',
'friday',
'froggy',
'giants',
'gizmo',
'global',
'goofy',
'happy1',
'hendrix',
'henry',
'herman',
'homer',
'honey',
'house',
'houston',
'iguana',
'indiana',
'insane',
'inside',
'irish',
'ironman',
'jake',
'jasmin',
'jeanne',
'jerry',
'joey',
'justice',
'katherine',
'kermit',
'kitty',
'koala',
'larry',
'leslie',
'logan',
'lucky',
'mark',
'martin',
'matt',
'minnie',
'misty',
'mitch',
'mouse',
'nancy',
'nascar',
'nelson',
'pantera',
'parker',
'penguin',
'peter',
'piano',
'pizza',
'prince',
'punkin',
'pyramid',
'raymond',
'robin',
'roger',
'rosebud',
'route66',
'royal',
'running',
'sadie',
'sasha',
'security',
'sheena',
'sheila',
'skiing',
'snapple',
'snowball',
'sparrow',
'spencer',
'spike',
'star',
'stealth',
'student',
'sunny',
'sylvia',
'tamara',
'taurus',
'teresa',
'theresa',
'thunderbird',
'tigers',
'tony',
'toyota',
'travel',
'tuesday',
'victory',
'viper1',
'wesley',
'whisky',
'winnie',
'winter',
'wolves',
'xyz123',
'zorro',
'123123',
'1234567',
'696969',
'888888',
'Anthony',
'Joshua',
'Matthew',
'Tigger',
'aaron',
'abby',
'abcdef',
'adidas',
'adrian',
'alfred',
'arthur',
'athena',
'austin',
'awesome',
'badger',
'bamboo',
'beagle',
'bears',
'beatles',
'beautiful',
'beaver',
'benny',
'bigmac',
'bingo',
'bitch',
'blonde',
'boogie',
'boston',
'brenda',
'bright',
'bubba1',
'bubbles',
'buffy',
'button',
'buttons',
'cactus',
'candy',
'captain',
'carlos',
'caroline',
'carrie',
'casper',
'catch22',
'chance',
'charity',
'charlotte',
'cheese',
'cheryl',
'chloe',
'chris1',
'clancy',
'compaq',
'conrad',
'cooper',
'cooter',
'copper',
'cosmos',
'cougar',
'cracker',
'crawford',
'crystal',
'curtis',
'cyclone',
'dance',
'diablo',
'dollars',
'dookie',
'dumbass',
'dundee',
'elizabeth',
'eric',
'europe',
'farmer',
'firebird',
'fletcher',
'fluffy',
'france',
'freak1',
'friends',
'fuckoff',
'gabriel',
'galaxy',
'gambit',
'garden',
'garfield',
'garnet',
'genesis',
'genius',
'godzilla',
'golfer',
'goober',
'grace',
'greenday',
'groovy',
'grover',
'guitar',
'hacker',
'harry',
'hazel',
'hector',
'herbert',
'horizon',
'hornet',
'howard',
'icecream',
'imagine',
'impala',
'jack',
'janice',
'jasmine',
'jason1',
'jeanette',
'jeffrey',
'jenifer',
'jenni',
'jesus1',
'jewels',
'joker',
'julie',
'julie1',
'junior',
'justin1',
'kathleen',
'keith',
'kelly',
'kelly1',
'kennedy',
'kevin1',
'knicks',
'larry1',
'leonard',
'lestat',
'library',
'lincoln',
'lionking',
'london',
'louise',
'lucky1',
'lucy',
'maddog',
'margaret',
'mariposa',
'marlboro',
'martin1',
'marty',
'master1',
'mensuck',
'mercedes',
'metal',
'midori',
'mikey',
'millie',
'mirage',
'molly',
'monet',
'money1',
'monica',
'monopoly',
'mookie',
'moose',
'moroni',
'music',
'naomi',
'nathan',
'nguyen',
'nicholas',
'nicole',
'nimrod',
'october',
'olive',
'olivia',
'online',
'oscar',
'oxford',
'pacific',
'painter',
'peaches',
'penelope',
'pepsi',
'petunia',
'philip',
'phoenix1',
'photo',
'pickle',
'player',
'poiuyt',
'porsche',
'porter',
'puppy',
'python',
'quality',
'raquel',
'raven',
'remember',
'robbie',
'robert1',
'roman',
'rugby',
'runner',
'russell',
'ryan',
'sailing',
'sailor',
'samantha',
'savage',
'scarlett',
'school',
'sean',
'seven',
'shadow1',
'sheba',
'shelby',
'shit',
'shoes',
'simba',
'simple',
'skipper',
'smiley',
'snake',
'snickers',
'sniper',
'snoopdog',
'snowman',
'sonic',
'spitfire',
'sprite',
'spunky',
'starwars',
'station',
'stella',
'stingray',
'storm',
'stormy',
'stupid',
'sunny1',
'sunrise',
'surfer',
'susan',
'tammy',
'tango',
'tanya',
'teddy1',
'theboss',
'theking',
'thumper',
'tina',
'tintin',
'tomcat',
'trebor',
'trevor',
'tweety',
'unicorn',
'valentine',
'valerie',
'vanilla',
'veronica',
'victor',
'vincent',
'viper',
'warrior',
'warriors',
'weasel',
'wheels',
'wilbur',
'winston',
'wisdom',
'wombat',
'xavier',
'yellow',
'zeppelin',
'1111',
'1212',
'Andrew',
'Family',
'Friends',
'Michael',
'Michelle',
'Snoopy',
'abcd1234',
'abcdefg',
'abigail',
'account',
'adam',
'alex1',
'alice1',
'allison',
'alpine',
'andre1',
'andrea1',
'angel1',
'anita',
'annette',
'antares',
'apache',
'apollo',
'aragorn',
'arizona',
'arnold',
'arsenal',
'asdfasdf',
'asdfg',
'asdfghjk',
'avenger',
'baby',
'babydoll',
'bailey',
'banana',
'barry',
'basket',
'batman1',
'beaner',
'beast',
'beatrice',
'bella',
'bertha',
'bigben',
'bigdog',
'biggles',
'bigman',
'binky',
'biology',
'bishop',
'blondie',
'bluefish',
'bobcat',
'bosco',
'braves',
'brazil',
'bruce',
'bruno',
'brutus',
'buffalo',
'bulldog',
'bullet',
'bullshit',
'bunny',
'business',
'butch',
'butler',
'butter',
'california',
'carebear',
'carol',
'carol1',
'carole',
'cassie',
'castle',
'catalina',
'catherine',
'cccccc',
'celine',
'center',
'champion',
'chanel',
'chaos',
'chelsea1',
'chester1',
'chicago',
'chico',
'christian',
'christy',
'church',
'cinder',
'colleen',
'colorado',
'columbia',
'commander',
'connie',
'cookies',
'cooking',
'corona',
'cowboys',
'coyote',
'craig',
'creative',
'cuddles',
'cuervo',
'cutie',
'daddy',
'daisy',
'daniel1',
'danielle',
'davids',
'death',
'denis',
'derek',
'design',
'destiny',
'diana',
'diane',
'dickhead',
'digger',
'dodger',
'donna',
'dougie',
'dragonfly',
'dylan',
'eagle',
'eclipse',
'electric',
'emerald',
'etoile',
'excalibur',
'express',
'fender',
'fiona',
'fireman',
'flash',
'florida',
'flowers',
'foster',
'francesco',
'francine',
'francois',
'frank',
'french',
'fuckface',
'gemini',
'general',
'gerald',
'germany',
'gilbert',
'goaway',
'golden',
'goldfish',
'goose',
'gordon',
'graham',
'grant',
'gregory',
'gretchen',
'gunner',
'hannah',
'harold',
'harrison',
'harvey',
'hawkeye',
'heaven',
'heidi',
'helen',
'helena',
'hithere',
'hobbit',
'ibanez',
'idontknow',
'integra',
'ireland',
'irene',
'isaac',
'isabel',
'jackass',
'jackie',
'jackson',
'jaguar',
'jamaica',
'japan',
'jenny1',
'jessie',
'johan',
'johnny',
'joker1',
'jordan23',
'judith',
'julia',
'jumanji',
'kangaroo',
'karen1',
'kathy',
'keepout',
'keith1',
'kenneth',
'kimberly',
'kingdom',
'kitkat',
'kramer',
'kristen',
'laura',
'laurie',
'lawrence',
'lawyer',
'legend',
'liberty',
'light',
'lindsay',
'lindsey',
'lisa',
'liverpool',
'lola',
'lonely',
'louis',
'lovely',
'loveme',
'lucas',
'madonna',
'malcolm',
'malibu',
'marathon',
'marcel',
'maria1',
'mariah',
'mariah1',
'marilyn',
'mario',
'marvin',
'maurice',
'maxine',
'maxwell',
'me',
'meggie',
'melanie',
'melissa',
'melody',
'mexico',
'michael1',
'michele',
'midnight',
'mike1',
'miracle',
'misha',
'mishka',
'molly1',
'monique',
'montreal',
'moocow',
'moore',
'morris',
'mouse1',
'mulder',
'nautica',
'nellie',
'newton',
'nick',
'nirvana1',
'nissan',
'norman',
'notebook',
'ocean',
'olivier',
'ollie',
'oranges',
'oregon',
'orion',
'panda',
'pandora',
'panther',
'passion',
'patricia',
'pearl',
'peewee',
'pencil',
'penny',
'people',
'percy',
'person',
'peter1',
'petey',
'picasso',
'pierre',
'pinkfloyd',
'polaris',
'police',
'pookie1',
'poppy',
'power',
'predator',
'preston',
'q1w2e3',
'queen',
'queenie',
'quentin',
'ralph',
'random',
'rangers',
'raptor',
'reality',
'redrum',
'remote',
'reynolds',
'rhonda',
'ricardo',
'ricardo1',
'ricky',
'river',
'roadrunner',
'robinhood',
'rocknroll',
'rocky1',
'ronald',
'roxy',
'ruthie',
'sabrina',
'sakura',
'sally',
'sampson',
'samuel',
'sandra',
'santa',
'sapphire',
'scarlet',
'scorpio',
'scott1',
'scottie',
'scruffy',
'seattle',
'serena',
'shanti',
'shark',
'shogun',
'simon',
'singer',
'skull',
'skywalker',
'slacker',
'smashing',
'smiles',
'snowflake',
'snuffy',
'soccer1',
'soleil',
'sonny',
'spanky',
'speedy',
'spider',
'spooky',
'stacey',
'star69',
'start',
'steven1',
'stinky',
'strawberry',
'stuart',
'sugar',
'sundance',
'superfly',
'suzanne',
'suzuki',
'swimmer',
'swimming',
'system',
'taffy',
'tarzan',
'teddy',
'teddybear',
'terry',
'theatre',
'thunder',
'thursday',
'tinker',
'tootsie',
'tornado',
'tracy',
'tricia',
'trident',
'trojan',
'truman',
'trumpet',
'tucker',
'turtle',
'tyler',
'utopia',
'voyager',
'warcraft',
'warlock',
'warren',
'water',
'wayne',
'wendy',
'williams',
'willy',
'winona',
'woody',
'woofwoof',
'wrangler',
'wright',
'xfiles',
'xxxxxx',
'yankees',
'yvonne',
'zebra',
'zenith',
'zigzag',
'zombie',
'zxc123',
'zxcvb',
'000000',
'007007',
'11111',
'11111111',
'123321',
'171717',
'181818',
'1a2b3c',
'1chris',
'4runner',
'54321',
'55555',
'6969',
'7777777',
'789456',
'88888888',
'Alexis',
'Bailey',
'Charlie',
'Chris',
'Daniel',
'Dragon',
'Elizabeth',
'HARLEY',
'Heather',
'Jennifer',
'Jessica',
'Jordan',
'KILLER',
'Nicholas',
'Password',
'Princess',
'Purple',
'Rebecca',
'Robert',
'Shadow',
'Steven',
'Summer',
'Sunshine',
'Superman',
'Taylor',
'Thomas',
'Victoria',
'abcd123',
'abcde',
'accord',
'active',
'africa',
'airborne',
'alfaro',
'alicia',
'aliens',
'alina',
'aline',
'alison',
'allen',
'aloha',
'alpha1',
'althea',
'altima',
'amanda1',
'amazing',
'america',
'amour',
'anderson',
'andre',
'andrew1',
'andromeda',
'angels',
'angie1',
'annie',
'anything',
'apple1',
'apple2',
'applepie',
'april',
'aquarius',
'ariane',
'ariel',
'arlene',
'artemis',
'asdf1234',
'asdfjkl',
'ashley1',
'ashraf',
'ashton',
'asterix',
'attila',
'autumn',
'avatar',
'babes',
'bambi',
'barbie',
'barney1',
'barrett',
'bball',
'beaches',
'beanie',
'beans',
'beauty',
'becca',
'belize',
'belle',
'belmont',
'benji',
'benson',
'bernardo',
'berry',
'betsy',
'betty',
'bigboss',
'bigred',
'billy1',
'birdie',
'birthday',
'biscuit',
'bitter',
'blackjack',
'blah',
'blanche',
'blood',
'blowjob',
'blowme',
'blueeyes',
'blues',
'bogart',
'bombay',
'boobie',
'boots',
'bootsie',
'boxers',
'brandi',
'brent',
'brewster',
'bridge',
'bronco',
'bronte',
'brooke',
'brother',
'bryan',
'bubble',
'buddha',
'budgie',
'burton',
'butterfly',
'byron',
'calendar',
'calvin1',
'camel',
'camille',
'campbell',
'camping',
'cancer',
'canela',
'cannon',
'carbon',
'carnage',
'carolyn',
'carrot',
'cascade',
'catfish',
'cathy',
'catwoman',
'cecile',
'celica',
'change',
'chantal',
'charger',
'cherry',
'chiara',
'chiefs',
'china',
'chris123',
'christ1',
'christmas',
'christopher',
'chuck',
'cindy1',
'cinema',
'civic',
'claude',
'clueless',
'cobain',
'cobra',
'cody',
'colette',
'college',
'colors',
'colt45',
'confused',
'cool',
'corvette',
'cosmo',
'country',
'crusader',
'cunningham',
'cupcake',
'cynthia',
'dagger',
'dammit',
'dancer',
'daphne',
'darkstar',
'darren',
'darryl',
'darwin',
'deborah',
'december',
'deedee',
'deeznuts',
'delano',
'delete',
'demon',
'denise',
'denny',
'desert',
'deskjet',
'detroit',
'devil',
'devine',
'devon',
'dexter',
'dianne',
'diesel',
'director',
'dixie',
'dodgers',
'doggy',
'dollar',
'dolly',
'dominique',
'domino',
'dontknow',
'doogie',
'doudou',
'downtown',
'dragon1',
'driver',
'dude',
'dudley',
'dutchess',
'dwight',
'eagle1',
'easter',
'eastern',
'edith',
'edmund',
'eight',
'element',
'elissa',
'ellen',
'elliot',
'empire',
'enigma',
'enterprise',
'erin',
'escort',
'estelle',
'eugene',
'evelyn',
'explore',
'family1',
'fatboy',
'felipe',
'ferguson',
'ferret',
'ferris',
'fireball',
'fishes',
'fishie',
'flight',
'florida1',
'flowerpot',
'forward',
'freddie',
'freebird',
'freeman',
'frisco',
'fritz',
'froggie',
'froggies',
'frogs',
'fucku',
'future',
'gabby',
'games',
'garcia',
'gaston',
'gateway',
'george1',
'georgia',
'german',
'germany1',
'getout',
'ghost',
'gibson',
'giselle',
'gmoney',
'goblin',
'goblue',
'gollum',
'grandma',
'gremlin',
'grizzly',
'grumpy',
'guess',
'guitar1',
'gustavo',
'haggis',
'haha',
'hailey',
'halloween',
'hamilton',
'hamlet',
'hanna',
'hanson',
'happy123',
'happyday',
'hardcore',
'harley1',
'harriet',
'harris',
'harvard',
'health',
'heart',
'heather1',
'heather2',
'hedgehog',
'helene',
'hello1',
'hello123',
'hellohello',
'hermes',
'heythere',
'highland',
'hilda',
'hillary',
'history',
'hitler',
'hobbes',
'holiday',
'holly',
'honda1',
'hongkong',
'hootie',
'horse',
'hotrod',
'hudson',
'hummer',
'huskies',
'idiot',
'iforget',
'iloveu',
'impact',
'indonesia',
'irina',
'isabelle',
'israel',
'italia',
'italy',
'jackie1',
'jacob',
'jakey',
'james1',
'jamesbond',
'jamie',
'jamjam',
'jeffrey1',
'jennie',
'jenny',
'jensen',
'jesse',
'jesse1',
'jester',
'jethro',
'jimbob',
'jimmy',
'joanna',
'joelle',
'john316',
'jordie',
'jorge',
'josh',
'journey',
'joyce',
'jubilee',
'jules',
'julien',
'juliet',
'junebug',
'juniper',
'justdoit',
'karin',
'karine',
'karma',
'katerina',
'katie',
'katie1',
'kayla',
'keeper',
'keller',
'kendall',
'kenny',
'ketchup',
'kings',
'kissme',
'kitten',
'kittycat',
'kkkkkk',
'kristi',
'kristine',
'labtec',
'laddie',
'ladybug',
'lance',
'laurel',
'lawson',
'leader',
'leland',
'lemon',
'lester',
'letter',
'letters',
'lexus1',
'libra',
'lights',
'lionel',
'little',
'lizzy',
'lolita',
'lonestar',
'longhorn',
'looney',
'loren',
'lorna',
'loser',
'lovers',
'loveyou',
'lucia',
'lucifer',
'lucky14',
'maddie',
'madmax',
'magic1',
'magnum',
'maiden',
'maine',
'management',
'manson',
'manuel',
'marcus',
'maria',
'marielle',
'marine',
'marino',
'marshall',
'martha',
'maxmax',
'meatloaf',
'medical',
'megan',
'melina',
'memphis',
'mermaid',
'miami',
'michel',
'michigan',
'mickey1',
'microsoft',
'mikael',
'milano',
'miles',
'millenium',
'million',
'miranda',
'miriam',
'mission',
'mmmmmm',
'mobile',
'monkey1',
'monroe',
'montana',
'monty',
'moomoo',
'moonbeam',
'morpheus',
'motorola',
'movies',
'mozart',
'munchkin',
'murray',
'mustang1',
'nadia',
'nadine',
'napoleon',
'nation',
'national',
'nestle',
'newlife',
'newyork1',
'nichole',
'nikita',
'nikki',
'nintendo',
'nokia',
'nomore',
'normal',
'norton',
'noway',
'nugget',
'number9',
'numbers',
'nurse',
'nutmeg',
'ohshit',
'oicu812',
'omega',
'openup',
'orchid',
'oreo',
'orlando',
'packard',
'packers',
'paloma',
'pancake',
'panic',
'parola',
'parrot',
'partner',
'pascal',
'patches',