3900 lines
106 KiB
Plaintext
Executable File
3900 lines
106 KiB
Plaintext
Executable File
#
|
||
# This file is part of John the Ripper password cracker,
|
||
# Copyright (c) 1996-2006,2008-2013 by Solar Designer
|
||
#
|
||
# Redistribution and use in source and binary forms, with or without
|
||
# modification, are permitted.
|
||
#
|
||
# There's ABSOLUTELY NO WARRANTY, express or implied.
|
||
#
|
||
# Please note that although this configuration file is under the cut-down BSD
|
||
# license above, many source files in John the Ripper are under GPLv2.
|
||
# For licensing terms for John the Ripper as a whole, see doc/LICENSE.
|
||
#
|
||
# ...with changes in the jumbo patch, by various authors
|
||
#
|
||
|
||
# The [Options] section is for general options only.
|
||
# Note that MPI specific options have been moved
|
||
# to [Options.MPI]
|
||
# There is also a new section [Options.OpenCL]
|
||
# for OpenCL specific options
|
||
# Default settings for Markov mode have been moved
|
||
# to [Markov.Default], but you can define other
|
||
# Markov modes as well, see ../doc/MARKOV
|
||
[Options]
|
||
# Default wordlist file name (including in batch mode)
|
||
Wordlist = $JOHN/password.lst
|
||
# Use idle cycles only
|
||
Idle = Y
|
||
# Crash recovery file saving delay in seconds
|
||
Save = 60
|
||
# Beep when a password is found (who needs this anyway?)
|
||
Beep = N
|
||
# if set to Y then dynamic format will always work with bare hashes. Normally
|
||
# dynamic only uses bare hashes if a single dynamic type is selected with
|
||
# the -format= (so -format=dynamic_0 would use valid bare hashes).
|
||
DynamicAlwaysUseBareHashes = N
|
||
|
||
# Default Single mode rules
|
||
SingleRules = Single
|
||
|
||
# Default batch mode Wordlist rules
|
||
BatchModeWordlistRules = Wordlist
|
||
|
||
# Default wordlist mode rules when not in batch mode (if any)
|
||
# If this is set and you want to run once without rules, use --rules:none
|
||
#WordlistRules = Wordlist
|
||
|
||
# Default loopback mode rules (if any)
|
||
# If this is set and you want to run once without rules, use --rules:none
|
||
LoopbackRules = Loopback
|
||
|
||
# Max. number of times to warn about crypting suboptimally small batches,
|
||
# before suppressing the warnings.
|
||
MaxKPCWarnings = 10
|
||
|
||
# If set to true, relax the KPC warning checks and only warn for really
|
||
# bad situations (the fewer salts, the more slack).
|
||
RelaxKPCWarningCheck = N
|
||
|
||
# Default/batch mode Incremental mode
|
||
# Warning: changing these might currently break resume on existing sessions
|
||
DefaultIncremental = ASCII
|
||
#DefaultIncrementalUTF8 = UTF8
|
||
DefaultIncrementalLM = LM_ASCII
|
||
|
||
# Time formatting string used in status ETA.
|
||
#
|
||
# TimeFormat24 is used when ETA is within 24h, so it is possible to omit
|
||
# the date then if you like, and show seconds instead.
|
||
#
|
||
# %c means 'local' specific canonical form, such as:
|
||
# 05/06/11 18:10:34
|
||
#
|
||
# Other examples
|
||
# %d/%m/%y %H:%M (day/mon/year hour:min)
|
||
# %m/%d/%y %H:%M (mon/day/year hour:min)
|
||
# %Y-%m-%d %H:%M (ISO 8601 style, 2011-05-06 18:10)
|
||
TimeFormat = %Y-%m-%d %H:%M
|
||
TimeFormat24 = %H:%M:%S
|
||
|
||
#
|
||
# optional add a date timestamp in front of every logged line.
|
||
# the default is no timestamp logging. See the docs for
|
||
# strftime for more information:
|
||
# http://en.cppreference.com/w/c/chrono/strftime
|
||
#
|
||
# 2016-02-20T22:35:38+01:00 would be %Y-%m-%dT%H:%M:%S%z
|
||
# Feb 20 22:35:38 would be %b %d %H:%M:%S
|
||
#LogDateFormat = %Y-%m-%dT%H:%M:%S%z
|
||
|
||
# if log date is being used, the time will default to local
|
||
# time. But if the next line is uncommented, it will output
|
||
# in UTC. Note, if LogDateFormat is not set, this option
|
||
# does nothing.
|
||
#LogDateFormatUTC = Y
|
||
|
||
# if logging to stderr (--log-stderr command line switch used),
|
||
# then use date format when outputting to the stderr.
|
||
#LogDateStderrFormat = %b %d %H:%M:%S
|
||
|
||
# This can be used to colorize (on screen) or otherwise emphasize (in log
|
||
# files) output whenever a supposed administrator password gets cracked.
|
||
#
|
||
# Set this to N or comment it out to disable all "MarkAdmin" stuff.
|
||
MarkAdminCracks = Y
|
||
|
||
# If MarkAdminCracks = Y above, the below will be used (if defined) for
|
||
# terminal output. The default is to change color to red before the username
|
||
# and reset to normal after it. Any "^" characters will be parsed as ESC for
|
||
# use in ANSI codes (like in the defaults)
|
||
MarkAdminStart = ^[31m
|
||
MarkAdminEnd = ^[0m
|
||
|
||
# If MarkAdminCracks = Y above, the below will be used (if defined) for logs.
|
||
# This literal string will be printed after the " + Cracked: root" line.
|
||
MarkAdminString = (ADMIN ACCOUNT)
|
||
|
||
# Permissions to set for session.log file
|
||
# Default is 0600
|
||
#LogFilePermissions = 0600
|
||
|
||
# Permissions to set for POT file
|
||
# Default is 0600
|
||
#PotFilePermissions = 0600
|
||
|
||
# John exits if another user owns log or pot file because CHMOD fails,
|
||
# If this is set John prints a warning and continues
|
||
# Default is N
|
||
#IgnoreChmodErrors = N
|
||
|
||
# This figure is in MB. The default is to memory map wordlists not larger
|
||
# than one terabyte.
|
||
# Set this to 0 to disable any use of memory-mapping in wordlist mode.
|
||
WordlistMemoryMapMaxSize = 1048576
|
||
|
||
# For single mode, load the full GECOS field (before splitting) as one
|
||
# additional candidate. Normal behavior is to only load individual words
|
||
# from that field. Enabling this can help when this field contains email
|
||
# addresses or other strings that are better used unsplit, but it increases
|
||
# the number of words tried so it may also slow things down.
|
||
PristineGecos = N
|
||
|
||
# Add an extra pass when loading Single words, that tries to parse things
|
||
# like JEdgarHoover to J Edgar Hoover and so on.
|
||
JumboSingleWords = N
|
||
|
||
# For single mode, ignore the login field.
|
||
# Normal behavior is to use the login field for single mode.
|
||
# Skipping the login field should only be enabled if previous single mode
|
||
# sessions did already make use of the login field, but no other information,
|
||
# and now you want to use other information, skip the login field, but still
|
||
# want the login field to be reported on successful cracks or with --show.
|
||
SingleSkipLogin = N
|
||
|
||
# Over-ride SINGLE_WORDS_PAIR_MAX in params.h. This may slow down Single mode
|
||
# but it may also help cracking a few more candidates. Default in core John
|
||
# is 4 while the Jumbo default is 6. This limit is automagically increased
|
||
# by word seed options --single-seed and/or --single-wordlist if needed.
|
||
SingleWordsPairMax = 6
|
||
|
||
# Un-commenting this stops Single mode from re-testing guessed plaintexts
|
||
# with all other salts.
|
||
#SingleRetestGuessed = N
|
||
|
||
# Set the maximum word buffer size used by Single mode. The default is
|
||
# 4 GB. If running fork this is the *total* used by a session (size is
|
||
# divided by number of forks). If running MPI, we try to determine the
|
||
# number of local processes on each node and divide it accordingly.
|
||
SingleMaxBufferSize = 4
|
||
|
||
# When running single mode with a GPU or accelerator, we prioritize speed
|
||
# (saturating buffers) over resume ability: When resuming such a session
|
||
# it may take longer to catch up. Set this option to Y to prioritize
|
||
# resuming instead, at the cost of max. speed.
|
||
SinglePrioResume = N
|
||
|
||
# Protect the restore files (*.rec) from being overwritten. The default
|
||
# mode is "Disabled". This mode will provide no protection, but has been
|
||
# the default mode in JtR forever, so to not change behavior, that mode
|
||
# has been kept as default. You can change this to "Named" or "Always"
|
||
# If this option is changed to "Named", then any restore file created
|
||
# with a --session=xxxx will be protected from being overwritten. If
|
||
# the option is set to "Always", then all .rec files will be kept from
|
||
# being overwritten, even ${JOHN}/john.rec file
|
||
#SessionFileProtect = Named
|
||
|
||
# Protect the log files (*.log) from being reused by new sessons.
|
||
# The default mode is "Disabled". That means, a nee session will just append
|
||
# to an existing log file.
|
||
# With "Named", a new session will not be allowed to append to an existing
|
||
# log file, except if the --session=NAME option hasn't been used.
|
||
# With "Always", not even the default log file ${JOHN}/john.log can be
|
||
# reused by a new session.
|
||
# (Of course, a restored session will always be allowed to append to an
|
||
# existing log file.)
|
||
# Unless you use the --nolog option, setting LogFileProtect will also
|
||
# prevent overwriting existing session files.
|
||
#LogFileProtect = Named
|
||
|
||
# Emit a status line whenever a password is cracked (this is the same as
|
||
# passing the --crack-status option flag to john). NOTE: if this is set
|
||
# to true here, --crack-status will toggle it back to false.
|
||
CrackStatus = N
|
||
|
||
# When printing status, show number of candidates tried (eg. 123456p).
|
||
# This is added to the "+ Cracked" line in the log as well (and that figure
|
||
# will be exact while the screen output will be a multiple of batch size).
|
||
StatusShowCandidates = N
|
||
|
||
# Write cracked passwords to the log file (default is just the user name)
|
||
LogCrackedPasswords = N
|
||
|
||
# Disable the dupe checking when loading hashes. For testing purposes only!
|
||
NoLoaderDupeCheck = N
|
||
|
||
# Default encoding for input files (ie. login/GECOS fields) and wordlists
|
||
# etc. If this is not set here and --encoding is not used either, the default
|
||
# is ISO-8859-1 for Unicode conversions and 7-bit ASCII encoding is assumed
|
||
# for rules, e.g., uppercasing of letters other than a-z will not work at all!
|
||
DefaultEncoding = UTF-8
|
||
|
||
# Default --target-encoding for Microsoft hashes (LM, NETLM et al) when input
|
||
# encoding is UTF-8. CP850 would be a universal choice for covering most
|
||
# "Latin-1" countries.
|
||
DefaultMSCodepage = CP850
|
||
|
||
# Default internal legacy codepage to be used by mask mode and within the
|
||
# rules engine, when both input and target encodings are Unicode (eg. UTF-8
|
||
# wordlist and NT hashes). In some cases this hits performance but lets us
|
||
# do things like Unicode case conversions. You can pick any supported
|
||
# legacy codepage that has as much support for the input data as possible,
|
||
# e.g., for "Latin-1" language passwords you can use ISO-8859-1, CP850 or
|
||
# CP1252 and it will hardly make any difference but in some cases, ISO-8859-1
|
||
# is fastest. Using "UTF-8" (which is not a legacy codepage!) will disable.
|
||
#
|
||
# The default is to NOT use any internal codepage.
|
||
#DefaultInternalCodepage = ISO-8859-1
|
||
|
||
# Warn if seeing UTF-8 when expecting some other encoding, or vice versa.
|
||
# This is disabled for ASCII or RAW encodings, for performance.
|
||
WarnEncoding = Y
|
||
|
||
# Always report (to screen and log) cracked passwords as UTF-8, regardless of
|
||
# input encoding. This is recommended if you have your terminal set for UTF-8.
|
||
AlwaysReportUTF8 = Y
|
||
|
||
# Always store Unicode (UTF-16) passwords as UTF-8 in john.pot, regardless
|
||
# of input encoding. This prevents john.pot from being filled with mixed
|
||
# and eventually unknown encodings. This is recommended if you have your
|
||
# terminal set for UTF-8 and/or you want to run --loopback for LM->NT
|
||
# including non-ASCII.
|
||
UnicodeStoreUTF8 = Y
|
||
|
||
# Always report/store non-Unicode formats as UTF-8, regardless of input
|
||
# encoding. Note: The actual codepage that was used is not stored anywhere
|
||
# except in the log file.
|
||
# This is needed e.g. for --loopback to crack LM->NT including non-ASCII.
|
||
CPstoreUTF8 = Y
|
||
|
||
# Normally, we try to handle Unicode characters not in our selected codepage
|
||
# with best effort. Enabling this option will instead translate any such
|
||
# character to "?" (default), to meet certain formats' behavior.
|
||
EmulateBrokenEncoding = N
|
||
ReplacementCharacter = ?
|
||
|
||
# Default verbosity is 3, valid figures are 1-5 right now.
|
||
# 4-5 enables some extra output and diagnostics.
|
||
# 4 is same verbosity as "john proper" aka. non-jumbo.
|
||
# 3 mutes rules & incremental output in logs (LOTS of lines).
|
||
# 2 mutes some other diagnostics.
|
||
# 1 even mutes printing (to screen) of cracked passwords.
|
||
Verbosity = 3
|
||
|
||
# If set to Y, do not output, log or store cracked passwords verbatim.
|
||
# This implies a different default .pot database file "secure.pot" instead
|
||
# of "john.pot" but it can still be overridden using --pot=FILE.
|
||
# This also overrides other options, e.g. LogCrackedPasswords.
|
||
SecureMode = N
|
||
|
||
# If set to Y, a session using --fork or MPI will signal to other nodes when
|
||
# it has written cracks to the pot file, so they will re-sync. Note that this
|
||
# may be delayed by buffers and the "Save" timer setting near top of this file.
|
||
ReloadAtCrack = N
|
||
|
||
# If set to Y, a session using --fork or MPI will signal to other nodes when
|
||
# it has cracked all hashes (there's nothing more to do!). This is ignored
|
||
# when ReloadAtCrack = Y because it's redundant.
|
||
ReloadAtDone = Y
|
||
|
||
# If set to Y, resync pot file when saving session. This does not involve any
|
||
# signalling, we just detect that someone else wrote to the pot file.
|
||
# This will sync with concurrent sessions even when not using --fork or MPI
|
||
# but it may be delayed by the "Save" timer setting near top of this file.
|
||
ReloadAtSave = Y
|
||
|
||
# If this file exists, john will abort cleanly
|
||
AbortFile = /var/run/john/abort
|
||
|
||
# While this file exists, john will pause
|
||
PauseFile = /var/run/john/pause
|
||
|
||
# If set to true, the uid will be appended to user name on cracks
|
||
# With: password123 (Administrator:500)
|
||
# Without password123 (Administrator)
|
||
# This is disabled by --save-memory.
|
||
ShowUIDinCracks = N
|
||
|
||
# This sets the "grace time" for --max-run-time=N. If john has not finished
|
||
# this long after the initial abort signal, it will send another one (similar
|
||
# to pressing ctrl-c a second time) which will stop john immediately and not
|
||
# wait further for an optimal resume point.
|
||
# Setting this to 0 means NO grace time - immediately abort. Setting it to
|
||
# a negative number means UNLIMITED grace time - never hard abort.
|
||
AbortGraceTime = 30
|
||
|
||
# Setting this to true allows SAP-B and SAP-G "half hashes" to be cracked.
|
||
# These are taken from RFC_READ_TABLE and padded with nulls to correct length.
|
||
# This may produce some false positives if enabled, at least for SAP-B.
|
||
SAPhalfHashes = N
|
||
|
||
# This allows you to list a few words/names that will be used by single mode
|
||
# as if they were included in every GECOS field. Use sparingly! Please note
|
||
# that the example words are commented out, so the list is empty!
|
||
[List.Single:SeedWords]
|
||
#Pass
|
||
#Secret
|
||
#Test
|
||
|
||
# This allows you to read extra pot files when loading hashes. Nothing will
|
||
# ever be written to these files, they are just read. Any directory in this
|
||
# list will be traversed and files in it with an extension of .pot will be
|
||
# read. However there will NOT be any recursion down further directory levels.
|
||
# Any entries that don't exist will be silently ignored.
|
||
[List.Extra:Potfiles]
|
||
#somefile.pot
|
||
#somedirectory
|
||
#$JOHN/my.pot
|
||
|
||
[Options:CPUtune]
|
||
# If preset is given, use it and skip autotune (NOTE: non-intel archs will
|
||
# currently ignore this option and always autotune)
|
||
UsePreset = Y
|
||
# Performance sample time, default 10 ms
|
||
AutoTuneSampleTime = 10
|
||
# Required gain to consider this scale better. Default is 1 %
|
||
AutoTuneReqGain = 1
|
||
# Max crypt_all() duration for trying a higher scale, default 100 ms
|
||
AutoTuneMaxDuration = 100
|
||
# If we tried this many increases of scale w/o gain, give up. Default 3.
|
||
AutoTuneMaxNoProgress = 3
|
||
|
||
[Options:MPI]
|
||
# Automagically disable OMP if MPI is used (set to N if
|
||
# you want to run one MPI process per multi-core host)
|
||
MPIOMPmutex = Y
|
||
|
||
# Print a notice if disabling OMP (when MPIOMPmutex = Y)
|
||
# or when running OMP and MPI at the same time
|
||
MPIOMPverbose = Y
|
||
|
||
# Assume all MPI nodes are homogenous; Enforce same OpenCL workgroup sizes.
|
||
MPIAllGPUsSame = N
|
||
|
||
# These formats are disabled from all-formats --test runs, or auto-selection
|
||
# of format from an input file. Even when disabled, you can use them as long
|
||
# as you spell them out with the --format option. Or you can delete a line,
|
||
# comment it out, or change to 'N'
|
||
[Disabled:Formats]
|
||
#formatname = Y
|
||
.include '$JOHN/dynamic_disabled.conf'
|
||
|
||
# Options that may affect both GPUs and other accelerators (eg. FPGA)
|
||
[Options:GPU]
|
||
# Show GPU temperature, fan and utilization along with normal status output
|
||
SensorsStatus = Y
|
||
|
||
# If SensorsStatus is true, individual ones can be turned off
|
||
TempStatus = Y
|
||
UtilStatus = N
|
||
FanStatus = N
|
||
|
||
# Abort session if GPU hits this temperature (in C)
|
||
AbortTemperature = 95
|
||
|
||
|
||
# ZTEX specific settings
|
||
[ZTEX:descrypt]
|
||
# The design has two programmable clocks. The 1st one is supplied to
|
||
# pipelines of DES rounds, the 2nd clock is supplied to comparators.
|
||
# Startup frequencies are 220,160.
|
||
#Frequency = 220,160
|
||
|
||
[ZTEX:bcrypt]
|
||
# Define typical setting of hashes it's going to process. It allows
|
||
# to adjust for best performance.
|
||
TargetSetting = 6
|
||
# Startup frequency for bcrypt-ztex is 140. Design tools guaranteed
|
||
# 141.5 in worst-case temperature and voltage.
|
||
Frequency = 141
|
||
# It's possible to set frequency on per-board and per-fpga basis.
|
||
#Frequency_04A36E0FD6 = 142
|
||
#Frequency_04A36E0FD6_0 = 143
|
||
#Frequency_04A36E0FD6_3 = 144
|
||
|
||
[ZTEX:sha512crypt]
|
||
#TargetRounds = 5000
|
||
# Design tools reported possible frequency to be 215 MHz.
|
||
# We never encountered a board where this worked anywhere close
|
||
# to such high frequency. Default frequency is set to 160 MHz.
|
||
# Some lucky boards might run at some higher frequency.
|
||
Frequency = 160
|
||
#Config1 = \x00\x00
|
||
|
||
[ZTEX:Drupal7]
|
||
#TargetRounds = 16384
|
||
# Drupal7 uses same bitstream as sha512crypt, see comment regarding
|
||
# default frequency in sha512crypt section.
|
||
#Frequency = 160
|
||
# Some bitstreams accept runtime configuration.
|
||
# In sha512crypt/Drupal7, configuration is 2 bytes. That's interpreted
|
||
# as a bitmask. By setting any of the lowest 10 bits to 1 it turns off
|
||
# corresponding unit (there are 10 units in the bitstream).
|
||
# This turns off units 0 and 1.
|
||
#Config1 = \x03\x00
|
||
# This turns off all 10 units (resulting in a timeout).
|
||
#Config1_04A36E0FD6_0 = \xff\x03
|
||
|
||
[ZTEX:sha256crypt]
|
||
# Design tools reported possible frequency is 166.3 but tested boards
|
||
# miss guesses, often fail unless frequency is decreased.
|
||
#Frequency = 165
|
||
Frequency = 135
|
||
#TargetRounds = 1000000
|
||
|
||
# md5crypt and phpass use same bitstream. Design tools reported
|
||
# possible frequency is 202 MHz. Tested boards run OK at 180 MHz.
|
||
[ZTEX:md5crypt]
|
||
Frequency = 180
|
||
|
||
[ZTEX:phpass]
|
||
Frequency = 180
|
||
#TargetRounds = 2048
|
||
|
||
[Options:OpenCL]
|
||
# Set default OpenCL device. Command line option will override this.
|
||
# If not set, we will search for a GPU or fall-back to the most
|
||
# powerful device.
|
||
#Device = 0
|
||
|
||
# If commented out and set to true, store LWS and GWS in session file for
|
||
# later resume. Note that when resuming, this option is ignored: If the
|
||
# session file was written with this option set, it will still be used.
|
||
#ResumeWS = Y
|
||
|
||
# Global max. single kernel invocation duration, in ms. Setting this low
|
||
# (eg. 10-100 ms) gives you a better responding desktop but lower performance.
|
||
# Setting it high (eg. 200-500 ms) will maximize performance but your desktop
|
||
# may lag. Really high values may trip watchdogs (eg. 5 seconds). Some versions
|
||
# of AMD Catalyst may hang if you go above 200 ms, and in general any good
|
||
# kernel will perform optimally at 100-200 ms anyway.
|
||
#Global_MaxDuration = 200
|
||
|
||
# Some formats vectorize their kernels in case the device says it's a good
|
||
# idea. Some devices give "improper" hints which means we vectorize but get
|
||
# a performance drop. If you have such a device, uncommenting the below
|
||
# will disable vectorizing globally.
|
||
# With this set to N (or commented out) you can force it per session with
|
||
# the --force-scalar command-line option instead.
|
||
#ForceScalar = Y
|
||
|
||
# Global build options. Format-specific build options below may be
|
||
# concatenated to this.
|
||
GlobalBuildOpts = -cl-mad-enable
|
||
|
||
# Initial local work-size for auto-tune (CPU devices excepted).
|
||
# 0 means let the OpenCL implementation pick a suitable value.
|
||
# 1 means query for "best multiple" (usually corresponds to "warp size").
|
||
# Any other value (eg. 64) will be taken verbatim.
|
||
AutotuneLWS = 1
|
||
|
||
|
||
# Format-specific settings:
|
||
|
||
# Uncomment the below for nvidia sm_30 and beyond.
|
||
# Please, check if it is really better.
|
||
#sha512crypt_BuildOpts = -cl-nv-maxrregcount=80
|
||
|
||
# Best configuration value to be used at runtime.
|
||
sha512crypt_Bonaire = -DUNROLL_LOOP=132104
|
||
|
||
# Example: Override auto-tune for RAR format.
|
||
#rar_LWS = 128
|
||
#rar_GWS = 8192
|
||
|
||
[List.OpenCL:Drivers]
|
||
#Driver ; Description ; Recommendation
|
||
#AMD driver versions
|
||
938 , 2 ; 12.8 ;
|
||
1084, 4 ; 13.1 ;
|
||
1124, 2 ; 13.4 ;
|
||
1214, 3 ; 13.6 beta ;
|
||
1311, 2 ; 13.11 beta-1 ;
|
||
1348, 5 ; 13.12 ;
|
||
1445, 5 ; 14.4 (Mantle) ;
|
||
1526, 3 ; 14.6 beta (Mantle) ;
|
||
1573, 4 ; 14.9 (Mantle) ; VGL S
|
||
1642, 5 ; 14.12 (Omega) ; VGL S
|
||
1702, 3 ; 15.5 beta ; T
|
||
1729, 3 ; 15.5 ;
|
||
1800, 5 ; 15.7 ; VG* R
|
||
1800, 8 ; 15.7.1 ; VGW R
|
||
1800, 11; 15.9 ; VGL S
|
||
1912, 5 ; 15.12 ;
|
||
#NVIDIA driver versions
|
||
346, 0 ; ; N* R
|
||
319, 0 ; ; N* S
|
||
#End
|
||
0, 0 ; ;
|
||
|
||
#Labels
|
||
# * -> all OS
|
||
# N -> NVIDIA
|
||
# G -> GCN
|
||
# V -> VLIW4 and VLIW5
|
||
# W -> Windows
|
||
# L -> Linux
|
||
# R -> recommended
|
||
# S -> supported
|
||
# T -> not recommended: really bad software. I mean "trash".
|
||
|
||
[PRINCE]
|
||
# Default wordlist file name. Will fall back to standard wordlist if not
|
||
# defined.
|
||
#Wordlist = $JOHN/password.lst
|
||
|
||
|
||
# Markov modes, see ../doc/MARKOV for more information
|
||
[Markov:Default]
|
||
# Default Markov mode settings
|
||
#
|
||
# Statsfile cannot be specified on the command line, so
|
||
# specifying it here is mandatory
|
||
Statsfile = $JOHN/stats
|
||
# MkvLvl and MkvMaxLen should also be specified here, as a fallback for
|
||
# --markov usage without specifying LEVEL and/or --max-length on the
|
||
# command line.
|
||
MkvLvl = 200
|
||
MkvMaxLen = 12
|
||
# MkvMinLvl and MkvMinLen should not be specified at all in [Markov:Default],
|
||
# or they should be equal to 0 (which is the default if not specified.
|
||
# MkvMinLvl and MkvMinLen can be used in other Markov mode sections
|
||
# except [Markov:Default]
|
||
; MkvMinLvl = 0
|
||
; MkvMinLen = 0
|
||
|
||
# A user defined character class is named with a single digit, ie. 0..9. After
|
||
# the equal-sign, just list all characters that this class should match. You
|
||
# can specify ranges within brackets, much like pre-processor ranges in rules.
|
||
# BEWARE of encoding if using non-ASCII characters. If you put UTF-8 characters
|
||
# here, it will *not* work! You must use a singlebyte encoding and it should
|
||
# be the same here as you intend to use for your dictionary.
|
||
# You can however put characters here in \xA3 format (for codepoint 0xA3 - in
|
||
# many iso-8859 codepages that would mean a pound sign). This works in ranges
|
||
# too. Using \x00 is not supported though - it will not be parsed as null.
|
||
#
|
||
# This is a couple of example classes:
|
||
# ?0 matches (one version of) base64 characters
|
||
# ?1 matches hex digits
|
||
# ?2 matches the TAB character (never try to use \x00!)
|
||
[UserClasses]
|
||
0 = [a-zA-Z0-9/.]
|
||
1 = [0-9a-fA-F]
|
||
2 = \x09
|
||
|
||
[Mask]
|
||
# When iterating over length, emit a status line after each length is done
|
||
MaskLengthIterStatus = Y
|
||
|
||
# Default mask for -mask if none is given. This is same as hashcat's default.
|
||
DefaultMask = ?1?2?2?2?2?2?2?3?3?3?3?d?d?d?d
|
||
|
||
# Default mask for Hybrid mask mode if none is given.
|
||
DefaultHybridMask = ?w?d?d?d?d
|
||
|
||
# Mask mode have custom placeholders ?1..?9 that look similar to user classes
|
||
# but are a different thing. They are merely defaults for the -1..-9 command
|
||
# line options. As delivered, they resemble hashcat's defaults.
|
||
1 = ?l?d?u
|
||
2 = ?l?d
|
||
3 = ?l?d*!$@_
|
||
4 =
|
||
5 =
|
||
6 =
|
||
7 =
|
||
8 =
|
||
9 =
|
||
|
||
[Subsets]
|
||
# When iterating over length, emit a status line after each length is done
|
||
LengthIterStatus = Y
|
||
|
||
# Min/Max number of unique characters. MaxDiff can't be set larger than 16.
|
||
MinDiff = 1
|
||
MaxDiff = 7
|
||
|
||
# Default charset, either a literal string or a single-digit number pointing
|
||
# to one of the sets below. If not defined, all printable ASCII is used.
|
||
#DefaultCharset = 0
|
||
|
||
# Subsets mode charsets 0-9. These are literal strings. TAB and space
|
||
# characters can be used as long as they do not come first or last. The only
|
||
# "magic" used here is \U+HHHH or \U+HHHHH for any Unicode character (except
|
||
# the very highest private area that has six hex digits). For example, you
|
||
# could say \U+1F600 for a "Grinning Face".
|
||
0 = 0123456789abcdef
|
||
1 = ABCDEF0123456789
|
||
2 = 0123456789abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿
|
||
3 = 0123456789άέήίαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώΆΈΉΊΌΎΏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩΪΫ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
|
||
4 = 0123456789абвгдежзийклмнопрстуфхцчшщъыьэюяёЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ№ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
|
||
5 =
|
||
6 =
|
||
7 =
|
||
8 =
|
||
9 =
|
||
|
||
[Regen_Salts_UserClasses]
|
||
# These are user defined character sets. Their purpose is to allow custom salt
|
||
# values to be used within the salt_regen logic. These will be the characters
|
||
# to use for this character within the salt. So if we had a salt that was 4
|
||
# characters, and 0-9a-m, we can easily do this by 0 = [0-9a-m]. If this is
|
||
# used, the regen salt value would be ?0?0?0?0 and salts such as a47m 2kd5
|
||
# would be valid.
|
||
1 = [1-9]
|
||
|
||
# A "no rules" rule for eg. super-fast Single mode (use with --single=none)
|
||
[List.Rules:None]
|
||
:
|
||
|
||
# A "drop all" rule for even faster Single mode (debugging :)
|
||
[List.Rules:Drop]
|
||
<1'0
|
||
|
||
# These are good rules on larger sites where a user ID may already be used,
|
||
# so a user simply appends numbers to create his loginID, but then uses the
|
||
# login name he wanted as basis for password. Just strip off digits and treat
|
||
# the base-word to some manipulation. These rules found from the 2015 A-M
|
||
# leak. Only adds 30-50 permutations and only applied to user names that have
|
||
# digits contained within them, and cracks quite a few.
|
||
# These are currently Jumbo-specific.
|
||
[List.Rules:JumboSingle]
|
||
/?d @?d >4
|
||
/?d @?d M @?A >4 Q
|
||
-c /?d @?d >4 M [lc] Q
|
||
-c /?d @?d M @?A >4 Q M [lc] Q
|
||
@?D Q >4
|
||
/?d @?d >3 <* $[0-9] Q
|
||
-c /?d @?d >3 <* M [lc] Q $[0-9]
|
||
/?d @?d >3 <- Az"12" <+ Q
|
||
-c /?d @?d >3 <- M [lc] Q Az"12" <+
|
||
/?d @?d >3 Az"123" <+ Q
|
||
-c /?d @?d >3 M [lc] Q Az"123" <+
|
||
/?d @?d >2 al d
|
||
-c /?d @?d >2 al M [lc] Q d
|
||
(?a )?d /?d a0 'p Xpz0
|
||
)?a (?d /?a a0 'p Xpz0
|
||
|
||
|
||
# "Single crack" mode rules
|
||
[List.Rules:Single]
|
||
# Simple rules come first...
|
||
:
|
||
-s x**
|
||
-c (?a c Q
|
||
-c l Q
|
||
-s-c x** /?u l
|
||
# These were not included in crackers I've seen, but are pretty efficient,
|
||
# so I include them near the beginning
|
||
-<6 ->6 >6 '6
|
||
-<7 ->7 >7 '7 l
|
||
-<6 ->6 -c >6 '6 /?u l
|
||
-<5 ->5 >5 '5
|
||
|
||
# Wedge the Jumbo-specific addons in here!
|
||
.include [List.Rules:JumboSingle]
|
||
|
||
# Weird order, eh? Can't do anything about it, the order is based on the
|
||
# number of successful cracks...
|
||
al d
|
||
a0 r c
|
||
-c al (?a d c
|
||
-<5 ->5 -c >5 '5 /?u l
|
||
-c a0 u Q
|
||
-c a0 )?a r l
|
||
-[:c] <* !?A \p1[lc] p
|
||
-c al c Q d
|
||
-<7 ->7 -c >7 '7 /?u
|
||
-<4 ->4 >4 '4 l
|
||
-c a0 (?l c r
|
||
-c a0 )?l l Tm
|
||
-<3 ->3 >3 '3
|
||
-<4 ->4 -c >4 '4 /?u
|
||
-<3 ->3 -c >3 '3 /?u l
|
||
-c a0 u Q r
|
||
al d M 'l f Q
|
||
-c al l Q d M 'l f Q
|
||
# About 50% of single-mode-crackable passwords get cracked by now...
|
||
# >2 x12 ... >8 x18
|
||
->[3-9] >\p[2-8] x1\0
|
||
->9 >9 \[
|
||
# >3 x22 ... >9 x28
|
||
->[4-9A] >\p[3-9] x2\p[2-8]
|
||
# >4 x32 ... >9 x37
|
||
->[5-9A] >\p[4-9] x3\p[2-7]
|
||
# >2 x12 /?u l ... >8 x18 /?u l
|
||
-c ->[3-9] >\p[2-8] x1\0 /?u l
|
||
-c ->9 >9 \[ /?u l
|
||
# >3 x22 /?u l ... >9 x28 /?u l
|
||
-c ->[4-9A] >\p[3-9] x2\p[2-8] /?u l
|
||
# >4 x32 /?u l ... >9 x37 /?u l
|
||
-c ->[5-9A] >\p[4-9] x3\p[2-7] /?u l
|
||
# Now to the suffix stuff...
|
||
a1 l $[1-9!0a-rt-z"-/:-@\[-`{-~]
|
||
-c a1 (?a c $[1-9!0a-rt-z"-/:-@\[-`{-~]
|
||
-[:c] a1 !?A (?\p1[za] \p1[lc] $s M 'l p Q X0z0 'l $s
|
||
-[:c] a1 /?A (?\p1[za] \p1[lc] $s
|
||
a1 l r $[1-9!]
|
||
-c a1 /?a u $[1-9!]
|
||
-[:c] a2 (?\p1[za] \p1[lc] Az"'s"
|
||
-[:c] a2 (?\p1[za] \p1[lc] Az"!!"
|
||
-[:c] a3 (?\p1[za] \p1[lc] Az"!!!"
|
||
# Removing vowels...
|
||
-[:c] b1 /?v @?v >2 (?\p1[za] \p1[lc]
|
||
/?v @?v >2 al d
|
||
# crack -> cracked, crack -> cracking
|
||
<* l [PI]
|
||
-c <* l [PI] (?a c
|
||
# mary -> marie
|
||
-[:c] a1 (?\p1[za] \p1[lc] )y omi $e
|
||
# marie -> mary
|
||
-[:c] b1 (?\p1[za] \p1[lc] )e \] )i val1 oay
|
||
# The following are some 3l33t rules
|
||
-[:c] l /[aelos] s\0\p[4310$] (?\p1[za] \p1[:c]
|
||
-[:c] l /a /[elos] sa4 s\0\p[310$] (?\p1[za] \p1[:c]
|
||
-[:c] l /e /[los] se3 s\0\p[10$] (?\p1[za] \p1[:c]
|
||
-[:c] l /l /[os] sl1 s\0\p[0$] (?\p1[za] \p1[:c]
|
||
-[:c] l /o /s so0 ss$ (?\p1[za] \p1[:c]
|
||
-[:c] l /a /e /[los] sa4 se3 s\0\p[10$] (?\p1[za] \p1[:c]
|
||
-[:c] l /a /l /[os] sa4 sl1 s\0\p[0$] (?\p1[za] \p1[:c]
|
||
-[:c] l /a /o /s sa4 so0 ss$ (?\p1[za] \p1[:c]
|
||
-[:c] l /e /l /[os] se3 sl1 s\0\p[0$] (?\p1[za] \p1[:c]
|
||
-[:c] l /[el] /o /s s\0\p[31] so0 ss$ (?\p1[za] \p1[:c]
|
||
-[:c] l /a /e /l /[os] sa4 se3 sl1 s\0\p[0$] (?\p1[za] \p1[:c]
|
||
-[:c] l /a /[el] /o /s sa4 s\0\p[31] so0 ss$ (?\p1[za] \p1[:c]
|
||
-[:c] l /e /l /o /s se3 sl1 so0 ss$ (?\p1[za] \p1[:c]
|
||
-[:c] l /a /e /l /o /s sa4 se3 sl1 so0 ss$ (?\p1[za] \p1[:c]
|
||
# Now to the prefix stuff...
|
||
l ^[1a-z2-90]
|
||
-c l Q ^[A-Z]
|
||
^[A-Z]
|
||
l ^["-/:-@\[-`{-~]
|
||
-[:c] <9 (?a \p1[lc] A0"[tT]he"
|
||
-[:c] <9 (?a \p1[lc] A0"[aA]my"
|
||
-[:c] <9 (?a \p1[lc] A0"[mdMD]r"
|
||
-[:c] <9 (?a \p1[lc] A0"[mdMD]r."
|
||
-[:c] <9 (?a \p1[lc] A0"__"
|
||
<- !?A l p ^[240-9]
|
||
# Some word pair rules...
|
||
# johnsmith -> JohnSmith, johnSmith
|
||
-p-c (?a 2 (?a c 1 [cl]
|
||
# JohnSmith -> john smith, john_smith, john-smith
|
||
-p 1 <- $[ _\-] + l
|
||
# JohnSmith -> John smith, John_smith, John-smith
|
||
-p-c 1 <- (?a c $[ _\-] 2 l
|
||
# JohnSmith -> john Smith, john_Smith, john-Smith
|
||
-p-c 1 <- l $[ _\-] 2 (?a c
|
||
# johnsmith -> John Smith, John_Smith, John-Smith
|
||
-p-c 1 <- (?a c $[ _\-] 2 (?a c
|
||
# Applying different simple rules to each of the two words
|
||
-p-[c:] 1 \p1[ur] 2 l
|
||
-p-c 2 (?a c 1 [ur]
|
||
-p-[c:] 1 l 2 \p1[ur]
|
||
-p-c 1 (?a c 2 [ur]
|
||
# jsmith -> smithj, etc...
|
||
-[:c] (?a \p1[lc] [{}]
|
||
-[:c] (?a \p1[lc] [{}] \0
|
||
# Toggle case...
|
||
-c <+ )?u l Tm
|
||
-c T0 Q M c Q l Q u Q C Q X0z0 'l
|
||
-c T[1-9A-E] Q M l Tm Q C Q u Q l Q c Q X0z0 'l
|
||
-c l Q T[1-9A-E] Q M T\0 Q l Tm Q C Q u Q X0z0 'l
|
||
-c >2 <G %2?a [lu] T0 M T2 T4 T6 T8 TA TC TE Q M l Tm Q X0z0 'l
|
||
-c >2 /?l /?u t Q M c Q C Q l Tm Q X0z0 'l
|
||
# Deleting chars...
|
||
>[2-8] D\p[1-7]
|
||
>[8-9A-E] D\1
|
||
-c /?u >[2-8] D\p[1-7] l
|
||
-c /?u >[8-9A-E] D\1 l
|
||
=1?a \[ M c Q
|
||
-c (?a >[1-9A-E] D\1 c
|
||
# Inserting a dot...
|
||
-[:c] >3 (?a \p1[lc] i[12].
|
||
# More suffix stuff...
|
||
<- l Az"[190][0-9]"
|
||
-c <- (?a c Az"[190][0-9]"
|
||
<- l Az"[782][0-9]"
|
||
-c <- (?a c Az"[782][0-9]"
|
||
<* l $[A-Z]
|
||
-c <* (?a c $[A-Z]
|
||
# cracking -> CRACKiNG
|
||
-c u /I sIi
|
||
# Crack96 -> cRACK96
|
||
%2?a C Q
|
||
# Crack96 -> cRACK(^
|
||
/?A S Q
|
||
# Crack96 -> CRaCK96
|
||
-c /?v V Q
|
||
# Really weird charset conversions, like "england" -> "rmh;smf"
|
||
:[RL] Q
|
||
l Q [RL]
|
||
-c (?a c Q [RL]
|
||
:[RL] \0 Q
|
||
# Both prefixing and suffixing...
|
||
<- l ^[1!@#$%^&*\-=_+.?|:'"] $\1
|
||
<- l ^[({[<] $\p[)}\]>]
|
||
# The rest of two-digit suffix stuff, less common numbers...
|
||
<- l Az"[63-5][0-9]"
|
||
-c <- (?a c Az"[63-5][0-9]"
|
||
# Some multi-digit numbers...
|
||
-[:c] (?a \p1[lc] Az"007" <+
|
||
-[:c] (?a \p1[lc] Az"123" <+
|
||
-[:c] (?a \p1[lc] Az"[0-9]\0\0" <+
|
||
-[:c] (?a \p1[lc] Az"1234" <+
|
||
-[:c] (?a \p1[lc] Az"[0-9]\0\0\0" <+
|
||
-[:c] (?a \p1[lc] Az"12345" <+
|
||
-[:c] (?a \p1[lc] Az"[0-9]\0\0\0\0" <+
|
||
-[:c] (?a \p1[lc] Az"123456" <+
|
||
-[:c] (?a \p1[lc] Az"[0-9]\0\0\0\0\0" <+
|
||
# Some [birth] years...
|
||
l Az"19[7-96-0]" <+ >-
|
||
l Az"20[01]" <+ >-
|
||
l Az"19[7-9][0-9]" <+
|
||
l Az"20[01][0-9]" <+
|
||
l Az"19[6-0][9-0]" <+
|
||
|
||
[List.Rules:Extra]
|
||
# Insert/overstrike some characters...
|
||
!?A >[1-6] l i\0[a-z]
|
||
!?A l o0[a-z]
|
||
!?A >[1-7] l o\0[a-z]
|
||
# Toggle case everywhere (up to length 8), assuming that certain case
|
||
# combinations were already tried.
|
||
-c T1 Q M T0 Q
|
||
-c T2 Q M T[z0] T[z1] Q
|
||
-c T3 Q M T[z0] T[z1] T[z2] Q
|
||
-c T4 Q M T[z0] T[z1] T[z2] T[z3] Q
|
||
-c T5 Q M T[z0] T[z1] T[z2] T[z3] T[z4] Q
|
||
-c T6 Q M T[z0] T[z1] T[z2] T[z3] T[z4] T[z5] Q
|
||
-c T7 Q M T[z0] T[z1] T[z2] T[z3] T[z4] T[z5] T[z6] Q
|
||
# Very slow stuff...
|
||
l Az"[1-90][0-9][0-9]" <+
|
||
-c (?a c Az"[1-90][0-9][0-9]" <+
|
||
<[\-9] l A\p[z0]"[a-z][a-z]"
|
||
<- l ^[a-z] $[a-z]
|
||
|
||
# Wordlist mode rules
|
||
[List.Rules:Wordlist]
|
||
# Try words as they are
|
||
:
|
||
# Lowercase every pure alphanumeric word
|
||
-c >3 !?X l Q
|
||
# Capitalize every pure alphanumeric word
|
||
-c (?a >2 !?X c Q
|
||
# Lowercase and pluralize pure alphabetic words
|
||
<* >2 !?A l p
|
||
# Lowercase pure alphabetic words and append '1'
|
||
<* >2 !?A l $1
|
||
# Capitalize pure alphabetic words and append '1'
|
||
-c <* >2 !?A c $1
|
||
# Duplicate reasonably short pure alphabetic words (fred -> fredfred)
|
||
<7 >1 al !?A l d
|
||
# Lowercase and reverse pure alphabetic words
|
||
>3 !?A l M r Q
|
||
# Prefix pure alphabetic words with '1'
|
||
>2 !?A l ^1
|
||
# Uppercase pure alphanumeric words
|
||
-c >2 !?X u Q M c Q u
|
||
# Lowercase pure alphabetic words and append a digit or simple punctuation
|
||
<* >2 !?A l $[2!37954860.?]
|
||
# Words containing punctuation, which is then squeezed out, lowercase
|
||
/?p @?p >3 l
|
||
# Words with vowels removed, lowercase
|
||
/?v @?v >3 l
|
||
# Words containing whitespace, which is then squeezed out, lowercase
|
||
/?w @?w >3 l
|
||
# Capitalize and duplicate short pure alphabetic words (fred -> FredFred)
|
||
-c <7 >1 al !?A c d
|
||
# Capitalize and reverse pure alphabetic words (fred -> derF)
|
||
-c <+ >2 !?A c r
|
||
# Reverse and capitalize pure alphabetic words (fred -> Derf)
|
||
-c >2 !?A l M r Q c
|
||
# Lowercase and reflect pure alphabetic words (fred -> fredderf)
|
||
<7 >1 al !?A l d M 'l f Q
|
||
# Uppercase the last letter of pure alphabetic words (fred -> freD)
|
||
-c <+ >2 !?A l M r Q c r
|
||
# Prefix pure alphabetic words with '2' or '4'
|
||
>2 !?A l ^[24]
|
||
# Capitalize pure alphabetic words and append a digit or simple punctuation
|
||
-c <* >2 !?A c $[2!3957468.?0]
|
||
# Prefix pure alphabetic words with digits
|
||
>2 !?A l ^[379568]
|
||
# Capitalize and pluralize pure alphabetic words of reasonable length
|
||
-c <* >2 !?A c p
|
||
# Lowercase/capitalize pure alphabetic words of reasonable length and convert:
|
||
# crack -> cracked, crack -> cracking
|
||
-[:c] <* >2 !?A \p1[lc] M [PI] Q
|
||
# Try the second half of split passwords
|
||
-s x**
|
||
-s-c x** M l Q
|
||
|
||
# Case toggler for cracking MD4-based NTLM hashes (with the contributed patch)
|
||
# given already cracked DES-based LM hashes. Use --rules=NT to use this.
|
||
[List.Rules:NT]
|
||
:
|
||
-c T0Q
|
||
-c ->2 a0 T1QT[z0]
|
||
-c ->3 a0 T2QT[z0]T[z1]
|
||
-c ->4 a0 T3QT[z0]T[z1]T[z2]
|
||
-c ->5 a0 T4QT[z0]T[z1]T[z2]T[z3]
|
||
-c ->6 a0 T5QT[z0]T[z1]T[z2]T[z3]T[z4]
|
||
-c ->7 a0 T6QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]
|
||
-c ->8 a0 T7QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]
|
||
-c ->9 a0 T8QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]
|
||
-c ->A a0 T9QT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]
|
||
-c ->B a0 TAQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]
|
||
-c ->C a0 TBQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]
|
||
-c ->D a0 TCQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB]
|
||
-c ->E a0 TDQT[z0]T[z1]T[z2]T[z3]T[z4]T[z5]T[z6]T[z7]T[z8]T[z9]T[zA]T[zB]T[zC]
|
||
|
||
# Shift toggler, up to length 16
|
||
[List.Rules:ShiftToggle]
|
||
:
|
||
W0Q
|
||
->2 a0 W1QW[z0]
|
||
->3 a0 W2QW[z0]W[z1]
|
||
->4 a0 W3QW[z0]W[z1]W[z2]
|
||
->5 a0 W4QW[z0]W[z1]W[z2]W[z3]
|
||
->6 a0 W5QW[z0]W[z1]W[z2]W[z3]W[z4]
|
||
->7 a0 W6QW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]
|
||
->8 a0 W7QW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]
|
||
->9 a0 W8QW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]
|
||
->A a0 W9QW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]
|
||
->B a0 WAQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]
|
||
->C a0 WBQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]W[zA]
|
||
->D a0 WCQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]W[zA]W[zB]
|
||
->E a0 WDQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]W[zA]W[zB]W[zC]
|
||
->F a0 WEQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]W[zA]W[zB]W[zC]W[zD]
|
||
->G a0 WFQW[z0]W[z1]W[z2]W[z3]W[z4]W[z5]W[z6]W[z7]W[z8]W[z9]W[zA]W[zB]W[zC]W[zD]W[zE]
|
||
|
||
# Used for loopback. This rule will produce candidates "PASSWOR" and "D" for
|
||
# an input of "PASSWORD" (assuming LM, which has halves of length 7).
|
||
[List.Rules:Split]
|
||
:
|
||
-s x**
|
||
|
||
# Some Office <=2003 files have passwords truncated at 15
|
||
[List.Rules:OldOffice]
|
||
:
|
||
->F -<F >F 'F
|
||
|
||
# Rules from Hash Runner 2014
|
||
[List.Rules:o1]
|
||
# o[0-9A-Z][ -~]
|
||
->\r[1-9A-ZZ] >\p[0-9A-Z] o\0[ -~] Q
|
||
|
||
[List.Rules:o2]
|
||
# o[0-9A-E][ -~] Q M o[0-9A-E][ -~] Q
|
||
->[1-9A-F] ->[1-9A-F] >\p1[0-9A-E] >\p2[0-9A-E] o\3[ -~] Q M o\4[ -~] Q
|
||
|
||
[List.Rules:o3]
|
||
# o[0-9][ -~] Q M o[0-9][ -~] Q M o[0-9][ -~] Q
|
||
->[1-9A] ->[1-9A] ->[1-9A] >\p1[0-9] >\p2[0-9] >\p3[0-9] o\4[ -~] Q M o\5[ -~] Q M o\6[ -~] Q
|
||
|
||
[List.Rules:o]
|
||
.include [List.Rules:o1]
|
||
.include [List.Rules:o2]
|
||
|
||
[List.Rules:i1]
|
||
# i[0-9A-Z][ -~]
|
||
->\r[2-9A-ZZZ] >\p1[0-9A-Z] i\0[ -~]
|
||
|
||
[List.Rules:i2]
|
||
# i[0-9A-E][ -~] i[0-9A-E][ -~]
|
||
->[2-9A-G] ->[2-9A-G] >\p1[0-9A-E] >\p2[0-9A-E] i\3[ -~] i\4[ -~]
|
||
|
||
[List.Rules:i3]
|
||
# i[0-9][ -~] i[0-9][ -~] i[0-9][ -~]
|
||
->[4-9A-D] ->[4-9A-D] ->[4-9A-D] >\p1[0-9] >\p2[0-9] >\p3[0-9] i\4[ -~] i\5[ -~] i\6[ -~]
|
||
|
||
[List.Rules:i]
|
||
.include [List.Rules:i1]
|
||
.include [List.Rules:i2]
|
||
|
||
[List.Rules:oi]
|
||
.include [List.Rules:o1]
|
||
.include [List.Rules:i1]
|
||
.include [List.Rules:o2]
|
||
.include [List.Rules:i2]
|
||
|
||
[List.Rules:T9]
|
||
a0 /?D l sa2 sb2 sc2 sd3 se3 sf3 sg4 sh4 si4 sj5 sk5 sl5 sm6 sn6 so6 sp7 sq7 sr7 ss7 st8 su8 sv8 sw9 sx9 sy9 sz9 s?D*
|
||
a0 /?D l sa2 sb2 sc2 sd3 se3 sf3 sg4 sh4 si4 sj5 sk5 sl5 sm6 sn6 so6 sp7 sq7 sr7 ss7 st8 su8 sv8 sw9 sx9 sy9 sz9 /?D s?D#
|
||
|
||
# A few rule sets from hashcat (taken as-is from https://github.com/hashcat/)
|
||
#
|
||
# Note that these are very poorly optimized with our measure, as they lack
|
||
# rule-rejection flags. Also, they don't use the preprocessor so are a lot
|
||
# harder to digest (for a human looking at them that is, for JtR there's
|
||
# virtually no difference).
|
||
#
|
||
[List.Rules:best64]
|
||
!! hashcat logic ON
|
||
.include <rules/best64.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:d3ad0ne]
|
||
!! hashcat logic ON
|
||
.include <rules/d3ad0ne.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:dive]
|
||
!! hashcat logic ON
|
||
.include <rules/dive.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:InsidePro]
|
||
!! hashcat logic ON
|
||
.include <rules/InsidePro-PasswordsPro.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:T0XlC]
|
||
!! hashcat logic ON
|
||
.include <rules/T0XlC.rule>
|
||
.include <rules/T0XlCv1.rule>
|
||
.include <rules/T0XlC-insert_top_100_passwords_1_G.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:rockyou-30000]
|
||
!! hashcat logic ON
|
||
.include <rules/rockyou-30000.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:specific]
|
||
!! hashcat logic ON
|
||
.include <rules/specific.rule>
|
||
!! hashcat logic OFF
|
||
|
||
[List.Rules:hashcat]
|
||
.include [List.Rules:best64]
|
||
.include [List.Rules:d3ad0ne]
|
||
.include [List.Rules:dive]
|
||
.include [List.Rules:InsidePro]
|
||
.include [List.Rules:T0XlC]
|
||
.include [List.Rules:rockyou-30000]
|
||
.include [List.Rules:specific]
|
||
|
||
# These are for phrase wordlists w/ spaces
|
||
[List.Rules:passphrase-rule1]
|
||
.include <rules/passphrase-rule1.rule>
|
||
|
||
[List.Rules:passphrase-rule2]
|
||
.include <rules/passphrase-rule2.rule>
|
||
|
||
# Default Loopback mode rules.
|
||
[List.Rules:Loopback]
|
||
.include [List.Rules:ShiftToggle]
|
||
.include [List.Rules:Split]
|
||
!! hashcat logic ON
|
||
+m
|
||
-m
|
||
!! hashcat logic OFF
|
||
b1 ]
|
||
|
||
# For Single Mode against fast hashes
|
||
[List.Rules:Single-Extra]
|
||
.include [List.Rules:Single]
|
||
.include [List.Rules:Extra]
|
||
.include [List.Rules:OldOffice]
|
||
|
||
# For Wordlist mode and very fast hashes
|
||
[List.Rules:Jumbo]
|
||
.include [List.Rules:Single-Extra]
|
||
.include [List.Rules:Wordlist]
|
||
.include [List.Rules:ShiftToggle]
|
||
.include [List.Rules:best64]
|
||
|
||
# KoreLogic rules
|
||
.include <korelogic.conf>
|
||
|
||
# Everything, including all KoreLogic and the rest of included hashcat rules.
|
||
# Only for very fast hashes and/or Single mode. Some of these rules are of
|
||
# ridiculous quality and lack optimizations - you have been warned.
|
||
[List.Rules:All]
|
||
.include [List.Rules:Jumbo]
|
||
.include [List.Rules:KoreLogic]
|
||
.include [List.Rules:T9]
|
||
.include [List.Rules:hashcat]
|
||
|
||
# Incremental modes
|
||
|
||
# This is for one-off uses (make your own custom.chr)
|
||
[Incremental:Custom]
|
||
File = $JOHN/custom.chr
|
||
MinLen = 0
|
||
|
||
# The theoretical CharCount is 211, we've got 196.
|
||
[Incremental:UTF8]
|
||
File = $JOHN/utf8.chr
|
||
MinLen = 0
|
||
CharCount = 196
|
||
|
||
# This is CP1252, a super-set of ISO-8859-1.
|
||
# The theoretical CharCount is 219, we've got 203.
|
||
[Incremental:Latin1]
|
||
File = $JOHN/latin1.chr
|
||
MinLen = 0
|
||
CharCount = 203
|
||
|
||
[Incremental:ASCII]
|
||
File = $JOHN/ascii.chr
|
||
MinLen = 0
|
||
MaxLen = 13
|
||
CharCount = 95
|
||
|
||
[Incremental:LM_ASCII]
|
||
File = $JOHN/lm_ascii.chr
|
||
MinLen = 0
|
||
MaxLen = 7
|
||
CharCount = 69
|
||
|
||
# This is CP858 (CP850 + Euro sign, superset of CP437).
|
||
# The theoretical CharCount is 209 minus lowercase, we've got 132.
|
||
[Incremental:LanMan]
|
||
File = $JOHN/lanman.chr
|
||
MinLen = 0
|
||
MaxLen = 7
|
||
CharCount = 132
|
||
|
||
# This is alnum (upper & lower case) as well as space.
|
||
[Incremental:Alnumspace]
|
||
File = $JOHN/alnumspace.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 63
|
||
|
||
[Incremental:Alnum]
|
||
File = $JOHN/alnum.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 62
|
||
|
||
[Incremental:Alpha]
|
||
File = $JOHN/alpha.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 52
|
||
|
||
[Incremental:LowerNum]
|
||
File = $JOHN/lowernum.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 36
|
||
|
||
[Incremental:UpperNum]
|
||
File = $JOHN/uppernum.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 36
|
||
|
||
[Incremental:LowerSpace]
|
||
File = $JOHN/lowerspace.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 27
|
||
|
||
[Incremental:Lower]
|
||
File = $JOHN/lower.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 26
|
||
|
||
[Incremental:Upper]
|
||
File = $JOHN/upper.chr
|
||
MinLen = 1
|
||
MaxLen = 13
|
||
CharCount = 26
|
||
|
||
[Incremental:Digits]
|
||
File = $JOHN/digits.chr
|
||
MinLen = 1
|
||
MaxLen = 20
|
||
CharCount = 10
|
||
|
||
# Some pre-defined word filters as used to generate the supplied .chr files
|
||
[List.External:Filter_ASCII]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c < 0x20 || c > 0x7e || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_LanMan]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i]) {
|
||
if (i >= 14) { // of up to 14 characters long
|
||
word = 0; return;
|
||
}
|
||
if (c >= 'a' && c <= 'z') // Convert to uppercase
|
||
word[i] &= 0xDF;
|
||
i++;
|
||
}
|
||
|
||
word[7] = 0; // Truncate at 7 characters
|
||
}
|
||
|
||
[List.External:Filter_LM_ASCII]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i]) {
|
||
if (c < 0x20 || c > 0x7e || // Require ASCII-only
|
||
i >= 14) { // of up to 14 characters long
|
||
word = 0; return;
|
||
}
|
||
if (c >= 'a' && c <= 'z') // Convert to uppercase
|
||
word[i] &= 0xDF;
|
||
i++;
|
||
}
|
||
|
||
word[7] = 0; // Truncate at 7 characters
|
||
}
|
||
|
||
[List.External:Filter_Alnumspace]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c != ' ' && (((c < '0' || c > '9') &&
|
||
((c &= 0xDF) < 'A' || c > 'Z'))) || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_Alnum]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (((c < '0' || c > '9') && ((c &= 0xDF) < 'A' || c > 'Z')) ||
|
||
i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_Alpha]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if ((c &= 0xDF) < 'A' || c > 'Z' || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_LowerNum]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (((c < 'a' || c > 'z') && (c < '0' || c > '9')) || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_UpperNum]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (((c < 'A' || c > 'Z') && (c < '0' || c > '9')) || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_LowerSpace]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (((c < 'a' || c > 'z') && c != ' ') || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_Lower]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c < 'a' || c > 'z' || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_Upper]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c < 'A' || c > 'Z' || i > 13) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_Digits]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c < '0' || c > '9' || i > 20) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
|
||
[List.External:Filter_No_Cap_or_Symbols]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) {
|
||
return;
|
||
}
|
||
word = 0; return;
|
||
}
|
||
|
||
|
||
# Reject words that are illegal UTF-8
|
||
# We obviously let pure ASCII through too
|
||
[List.External:Filter_UTF8]
|
||
void filter()
|
||
{
|
||
int s, a, p;
|
||
|
||
p = 0;
|
||
while (s = word[p++] & 0xff) {
|
||
if (s > 0x7f) {
|
||
if (s < 0xc2 || s > 0xf7) { // illegal single-byte
|
||
word = 0; return;
|
||
}
|
||
// two-byte c2..df
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
word = 0; return;
|
||
}
|
||
if (s > 0xdf) { // three-byte e0..ef
|
||
if (s == 0xe0 && a < 0xa0) {
|
||
word = 0; return;
|
||
}
|
||
if (s == 0xed && a > 0x9f) {
|
||
word = 0; return;
|
||
}
|
||
if (s == 0xf0 && a < 0x90) {
|
||
word = 0; return;
|
||
}
|
||
if (s == 0xf4 && a > 0x8f) {
|
||
word = 0; return;
|
||
}
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
word = 0; return;
|
||
}
|
||
if (s > 0xef) { // four-byte f0..f7
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
word = 0; return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
# Reject words that are LEGAL UTF-8 (also rejects pure ASCII)
|
||
[List.External:Filter_non-UTF8]
|
||
void filter()
|
||
{
|
||
int s, a, p;
|
||
|
||
p = 0;
|
||
while (s = word[p++] & 0xff) {
|
||
if (s > 0x7f) {
|
||
if (s < 0xc2 || s > 0xf7) { // illegal single-byte
|
||
return;
|
||
}
|
||
// two-byte c2..df
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
return;
|
||
}
|
||
if (s > 0xdf) { // three-byte e0..ef
|
||
if (s == 0xe0 && a < 0xa0) {
|
||
return;
|
||
}
|
||
if (s == 0xed && a > 0x9f) {
|
||
return;
|
||
}
|
||
if (s == 0xf0 && a < 0x90) {
|
||
return;
|
||
}
|
||
if (s == 0xf4 && a > 0x8f) {
|
||
return;
|
||
}
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
return;
|
||
}
|
||
if (s > 0xef) { // four-byte f0..f7
|
||
a = word[p++] & 0xff;
|
||
if (a < 0x80 || a > 0xbf) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
word = 0;
|
||
}
|
||
|
||
# A simple cracker for LM hashes
|
||
[List.External:LanMan]
|
||
int length; // Current length
|
||
int maxlength;
|
||
|
||
void init()
|
||
{
|
||
if (req_minlen)
|
||
length = req_minlen;
|
||
else
|
||
length = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else // the format's limit
|
||
maxlength = cipher_limit;
|
||
word[0] = 'A' - 1; // Start with "A"
|
||
word[length] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
i = length - 1; // Start from the last character
|
||
while (++word[i] > 'Z') // Try to increase it
|
||
if (i) // Overflow here, any more positions?
|
||
word[i--] = 'A'; // Yes, move to the left, and repeat
|
||
else // No
|
||
|
||
if (length < maxlength) {
|
||
word[i = ++length] = 0; // Switch to the next length
|
||
while (i--)
|
||
word[i] = 'A';
|
||
return;
|
||
} else {
|
||
word = 0; return; // We're done
|
||
}
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
length = 0; // Calculate the length
|
||
while (word[length]) length++;
|
||
}
|
||
|
||
# Simple and well-commented, yet useful external mode example
|
||
# NOTE, this has now been 'split' up into a base extern, 'base', and then
|
||
# multiple External:double functions. It still has same code as original
|
||
# double, but now can be easily expanded.
|
||
[List.External_base:Double]
|
||
/*
|
||
* This cracking mode tries all the possible duplicated lowercase alphabetic
|
||
* "words" of up to 8 characters long. Since word halves are the same, it
|
||
* only has to try about 500,000 words.
|
||
*/
|
||
|
||
/* Global variables: current length and word */
|
||
/* make this 'long' enough for other externs that include this one */
|
||
/* (up to 125 bytes long) */
|
||
|
||
int length, current[126], max;
|
||
|
||
/* this new 'type' variable, is used to tell double what character set to
|
||
* use. It can use the original (alpha). If type is 0 (i.e. unset), then
|
||
* a-z (alpha) character set is used. If type is '0' (a zero ascii byte)
|
||
* then alnum charset is used, a-z0-9. If type is a space char, then all
|
||
* charset is used [space - tilde] or [ -~]. This required setting the
|
||
* type var in the init() of alnum or all doubles (it can be left unset
|
||
* in the alpha versions). It also requires some if logic in generate.
|
||
* other than that, it works the same, with almost no performance hit */
|
||
int type;
|
||
|
||
/* Generates a new word */
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
/* Export last generated word, duplicating it at the same time; here "word"
|
||
* is a pre-defined external variable. */
|
||
word[(i = length) << 1] = 0;
|
||
while (i--) word[length + i] = word[i] = current[i];
|
||
|
||
/* Generate a new word */
|
||
i = length - 1; // Start from the last character
|
||
if (type == 0) {
|
||
/* alpha */
|
||
while (++current[i] > 'z') // Try to increase it
|
||
if (i) // Overflow here, any more positions?
|
||
current[i--] = 'a'; // Yes, move to the left, and repeat
|
||
else { // No
|
||
current = 0; // Request a length switch
|
||
break; // Break out of the loop
|
||
}
|
||
} else if (type == '0') {
|
||
/* alnum */
|
||
if (current[i] == 'z') current[i] = '0'-1;
|
||
while (++current[i] == '9') { // Try to increase it
|
||
if (i) // Overflow here, any more positions?
|
||
current[i--] = 'a'; // Yes, move to the left, and repeat
|
||
else { // No
|
||
current = 0; // Request a length switch
|
||
break; // Break out of the loop
|
||
}
|
||
if (current[i] == 'z') current[i] = '0'-1;
|
||
}
|
||
} else if (type == ' ') {
|
||
/* all */
|
||
while (++current[i] > '~') { // Try to increase it
|
||
if (i) // Overflow here, any more positions?
|
||
current[i--] = ' '; // Yes, move to the left, and repeat
|
||
else { // No
|
||
current = 0; // Request a length switch
|
||
break; // Break out of the loop
|
||
}
|
||
}
|
||
}
|
||
/* else ????? wtf?? */
|
||
|
||
/* Switch to the next length, unless we were generating 8 character long
|
||
* words already. */
|
||
if (!current && length < max) {
|
||
i = ++length;
|
||
if (type == 0 || type == '0')
|
||
while (i--) current[i] = 'a';
|
||
else if (type == ' ')
|
||
while (i--) current[i] = ' ';
|
||
}
|
||
}
|
||
|
||
/* Called when restoring an interrupted session */
|
||
void restore()
|
||
{
|
||
int i;
|
||
|
||
/* Import the word back */
|
||
i = 0;
|
||
while (current[i] = word[i]) i++;
|
||
|
||
/* ...and calculate the half-word length */
|
||
length = i >> 1;
|
||
}
|
||
|
||
[List.External:Double]
|
||
.include [List.External_base:Double]
|
||
|
||
/* Called at startup to initialize the global variables */
|
||
void init()
|
||
{
|
||
int i;
|
||
|
||
if (req_minlen)
|
||
i = length = (req_minlen + 1) / 2;
|
||
else
|
||
i = length = 2; // Start with 4 character long words
|
||
while (i--) current[i] = 'a'; // Set our half-word to "aa"
|
||
if (req_maxlen)
|
||
max = (req_maxlen + 1) / 2;
|
||
else if (length > 4)
|
||
max = length;
|
||
else
|
||
max = 4;
|
||
}
|
||
|
||
[List.External:Double_alnum]
|
||
.include [List.External_base:Double]
|
||
|
||
/* Called at startup to initialize the global variables */
|
||
void init()
|
||
{
|
||
int i;
|
||
|
||
if (req_minlen)
|
||
i = length = (req_minlen + 1) / 2;
|
||
else
|
||
i = length = 2; // Start with 4 character long words
|
||
while (i--) current[i] = 'a'; // Set our half-word to "aa"
|
||
if (req_maxlen)
|
||
max = (req_maxlen + 1) / 2;
|
||
else if (length > 4)
|
||
max = length;
|
||
else
|
||
max = 4;
|
||
|
||
type = '0';
|
||
}
|
||
|
||
[List.External:Double_all]
|
||
.include [List.External_base:Double]
|
||
void init()
|
||
{
|
||
int i;
|
||
|
||
if (req_minlen)
|
||
i = length = (req_minlen + 1) / 2;
|
||
else
|
||
i = length = 2; // Start with 4 character long words
|
||
while (i--) current[i] = ' '; // Set our half-word to " "
|
||
if (req_maxlen)
|
||
max = (req_maxlen + 1) / 2;
|
||
else if (length > 4)
|
||
max = length;
|
||
else
|
||
max = 4;
|
||
|
||
type = ' ';
|
||
}
|
||
|
||
|
||
# Strip 0.5 ("Secure Tool for Recalling Important Passwords") cracker,
|
||
# based on analysis done by Thomas Roessler and Ian Goldberg. This will
|
||
# crack passwords you may have generated with Strip; other uses of Strip
|
||
# are unaffected.
|
||
[List.External:Strip]
|
||
int minlength, maxlength, mintype, maxtype;
|
||
int crack_seed, length, type;
|
||
int count, charset[128];
|
||
|
||
void init()
|
||
{
|
||
int c;
|
||
|
||
/* Password lengths to try; Strip can generate passwords of 4 to 16
|
||
* characters, but traditional crypt(3) hashes are limited to 8. */
|
||
minlength = req_minlen;
|
||
if (minlength < 4)
|
||
minlength = 4;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else // the format's limit
|
||
maxlength = cipher_limit;
|
||
if (maxlength >16) maxlength = 16;
|
||
|
||
/* Password types to try (Numeric, Alpha-Num, Alpha-Num w/ Meta). */
|
||
mintype = 0; // 0
|
||
maxtype = 2; // 2
|
||
|
||
crack_seed = 0x10000;
|
||
length = minlength - 1;
|
||
type = mintype;
|
||
|
||
count = 0;
|
||
c = '0'; while (c <= '9') charset[count++] = c++;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int seed, random;
|
||
int i, c;
|
||
|
||
if (crack_seed > 0xffff) {
|
||
crack_seed = 0;
|
||
|
||
if (++length > maxlength) {
|
||
length = minlength;
|
||
|
||
if (++type > maxtype) {
|
||
word[0] = 0;
|
||
return;
|
||
}
|
||
}
|
||
|
||
count = 10;
|
||
if (type >= 1) {
|
||
c = 'a'; while (c <= 'f') charset[count++] = c++;
|
||
c = 'h'; while (c <= 'z') charset[count++] = c++;
|
||
c = 'A'; while (c <= 'Z') charset[count++] = c++;
|
||
}
|
||
if (type == 2) {
|
||
charset[count++] = '!';
|
||
c = '#'; while (c <= '&') charset[count++] = c++;
|
||
c = '('; while (c <= '/') charset[count++] = c++;
|
||
c = '<'; while (c <= '>') charset[count++] = c++;
|
||
charset[count++] = '?'; charset[count++] = '@';
|
||
charset[count++] = '['; charset[count++] = ']';
|
||
charset[count++] = '^'; charset[count++] = '_';
|
||
c = '{'; while (c <= '~') charset[count++] = c++;
|
||
}
|
||
}
|
||
|
||
seed = (crack_seed++ << 16 >> 16) * 22695477 + 1;
|
||
|
||
i = 0;
|
||
while (i < length) {
|
||
random = ((seed = seed * 22695477 + 1) >> 16) & 0x7fff;
|
||
word[i++] = charset[random % count];
|
||
}
|
||
|
||
word[i] = 0;
|
||
}
|
||
|
||
# A variation of KnownForce configured to try all the 385641000 possible
|
||
# auto-generated passwords of DokuWiki versions up to at least 2013-05-10.
|
||
[List.External:DokuWiki]
|
||
int last; // Last character position, zero-based
|
||
int lastofs; // Last character position offset into charset[]
|
||
int lastid; // Current character index in the last position
|
||
int id[0x7f]; // Current character indices for other positions
|
||
int charset[0x7f00]; // Character sets, 0x100 elements for each position
|
||
|
||
void init()
|
||
{
|
||
int A[26], C[26], V[26];
|
||
int length;
|
||
int pos, ofs, i, c;
|
||
|
||
i = 0; while (i < 26) { A[i] = C[i] = 1; V[i++] = 0; }
|
||
i = 'a' - 'a'; C[i] = 0; V[i] = 1;
|
||
i = 'e' - 'a'; C[i] = 0; V[i] = 1;
|
||
i = 'i' - 'a'; C[i] = 0; V[i] = 1;
|
||
i = 'o' - 'a'; C[i] = 0; V[i] = 1;
|
||
i = 'u' - 'a'; C[i] = 0; V[i] = 1;
|
||
i = 'q' - 'a'; A[i] = C[i] = 0;
|
||
i = 'x' - 'a'; A[i] = C[i] = 0;
|
||
i = 'y' - 'a'; A[i] = C[i] = 0;
|
||
|
||
length = 8;
|
||
|
||
/* This defines the character sets for different character positions */
|
||
pos = 0;
|
||
while (pos < 6) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = 'a' - 1;
|
||
while (++c <= 'z')
|
||
if (C[c - 'a'])
|
||
charset[ofs + i++] = c;
|
||
charset[ofs + i] = 0;
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = 'a' - 1;
|
||
while (++c <= 'z')
|
||
if (V[c - 'a'])
|
||
charset[ofs + i++] = c;
|
||
charset[ofs + i] = 0;
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = 'a' - 1;
|
||
while (++c <= 'z')
|
||
if (A[c - 'a'])
|
||
charset[ofs + i++] = c;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
c = '1';
|
||
while (pos < length) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
while (c <= '9')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
c = '0';
|
||
}
|
||
|
||
last = length - 1;
|
||
pos = -1;
|
||
while (++pos <= last)
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
lastid = (lastofs = last << 8) - 1;
|
||
word[pos] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int pos;
|
||
|
||
/* Handle the typical case specially */
|
||
if (word[last] = charset[++lastid]) return;
|
||
|
||
word[pos = last] = charset[lastid = lastofs];
|
||
while (pos--) { // Have a preceding position?
|
||
if (word[pos] = charset[++id[pos]]) return;
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
}
|
||
|
||
word = 0; // We're done
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i, c;
|
||
|
||
/* Calculate the current length and infer the character indices */
|
||
last = 0;
|
||
while (c = word[last]) {
|
||
i = lastofs = last << 8;
|
||
while (charset[i] != c && charset[i]) i++;
|
||
if (!charset[i]) i = lastofs; // Not found
|
||
id[last++] = i;
|
||
}
|
||
lastid = id[--last];
|
||
}
|
||
|
||
/*
|
||
* This takes advantage of CVE-2013-2120 to find seeds that KDE Paste applet
|
||
* uses to generate passwords.
|
||
*
|
||
* This software is Copyright (c) Michael Samuel <mik@miknet.net>,
|
||
* and it is hereby released to the general public under the following terms:
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted.
|
||
*/
|
||
[List.External:KDEPaste]
|
||
int charset[95];
|
||
int charset_length, password_length, endTime, startTime, msec;
|
||
|
||
void init()
|
||
{
|
||
password_length = 8; /* Change this to match config */
|
||
endTime = session_start_time;
|
||
startTime = 1343743200; /* Aug 1 2012 - Change this as necessary */
|
||
|
||
msec = 1; /* msec is never 0 - it would crash the applet */
|
||
|
||
charset_length = 0;
|
||
int c;
|
||
|
||
/* Comment out classes that you don't need, but keep the order the same */
|
||
/* Lowers */
|
||
c = 'a'; while (c <= 'z') charset[charset_length++] = c++;
|
||
|
||
/* Uppers */
|
||
c = 'A'; while (c <= 'Z') charset[charset_length++] = c++;
|
||
|
||
/* Numbers */
|
||
c = '0'; while (c <= '9') charset[charset_length++] = c++;
|
||
charset[charset_length++] = '0'; /* Yep, it's there twice */
|
||
|
||
/* Symbols */
|
||
c = '!'; while (c <= '/') charset[charset_length++] = c++;
|
||
c = ':'; while (c <= '@') charset[charset_length++] = c++;
|
||
c = '['; while (c <= '`') charset[charset_length++] = c++;
|
||
c = '{'; while (c <= '~') charset[charset_length++] = c++;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i, rand_seed, rand_result;
|
||
|
||
/* Terminate once we've generated for all *
|
||
* of the time range (Plus a bit more...) */
|
||
if (endTime + 1000 < startTime) {
|
||
word = 0;
|
||
return;
|
||
}
|
||
|
||
/* Skip msecs that would generate dupes */
|
||
while (endTime % msec != 0) {
|
||
if (++msec > 999) {
|
||
endTime--;
|
||
msec = 1;
|
||
}
|
||
}
|
||
|
||
rand_seed = endTime / msec;
|
||
|
||
i = 0;
|
||
while (i < password_length) {
|
||
/* this works like rand_r() from eglibc */
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result = (rand_seed >> 16) & 2047;
|
||
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result <<= 10;
|
||
rand_result ^= (rand_seed >> 16) & 1023;
|
||
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result <<= 10;
|
||
rand_result ^= (rand_seed >> 16) & 1023;
|
||
|
||
word[i++] = charset[rand_result % charset_length];
|
||
}
|
||
word[i] = 0;
|
||
|
||
if (++msec > 999) {
|
||
endTime--;
|
||
msec = 1;
|
||
}
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i, rand_seed, rand_result;
|
||
|
||
i = 0;
|
||
|
||
/* Very crude restore, just dry-run until we hit last word */
|
||
while (i != password_length) {
|
||
|
||
while (endTime % msec != 0) {
|
||
if (++msec > 999) {
|
||
endTime--;
|
||
msec = 1;
|
||
}
|
||
}
|
||
|
||
rand_seed = endTime / msec;
|
||
|
||
i = 0;
|
||
while (i < password_length) {
|
||
/* this works like rand_r() from eglibc */
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result = (rand_seed >> 16) & 2047;
|
||
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result <<= 10;
|
||
rand_result ^= (rand_seed >> 16) & 1023;
|
||
|
||
rand_seed = rand_seed * 1103515245 + 12345;
|
||
rand_result <<= 10;
|
||
rand_result ^= (rand_seed >> 16) & 1023;
|
||
|
||
if (charset[rand_result % charset_length] != word[i++])
|
||
break;
|
||
}
|
||
|
||
if (++msec > 999) {
|
||
endTime--;
|
||
msec = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Awesome Password Generator RNG replay
|
||
* Written by Michael Samuel <mik@miknet.net>
|
||
* Public Domain.
|
||
*
|
||
* This takes advantage of a subtle bug, where a crypto RNG is used to
|
||
* seed the C# System.Random() class, which takes a 32-bit input, but
|
||
* converts negative numbers into non-negative numbers, resulting in
|
||
* only 31 bits of security.
|
||
*
|
||
* This only implements "easy to type" being *unticked*, and numbers,
|
||
* lowers, uppers and symbols being ticked, in random password mode.
|
||
* Changing the password length is easy, anything else is left as an
|
||
* exercise to the reader.
|
||
*
|
||
* Running Awesome Password Generator (1.3.2 or lower) in Mono is still
|
||
* vulnerable, but uses a different RNG, so this mode isn't compatible.
|
||
*/
|
||
|
||
/* Awesome Password Generator 1.3.2 does a two-pass run, selecting which
|
||
* charset each position will have, then picking the character. This
|
||
* leads to heavy bias, and is fixed in 1.4.0 (along with many other
|
||
* fixes). If you have been using Awesome Password Generator, you should
|
||
* upgrade immediately and change your passwords.
|
||
*/
|
||
[List.External:AwesomePasswordGenerator]
|
||
int numbers[10];
|
||
int lowers[26];
|
||
int uppers[26];
|
||
int symbols[32];
|
||
|
||
/* Since we don't have a double datatype, I simply pre-calculated the
|
||
* transition numbers calculating the scale formula:
|
||
* (double)randNum * 4.656612873077393e-10 * {4/10/26/32}
|
||
*/
|
||
int boundaries_charclass[4];
|
||
int boundaries_numbers[10];
|
||
int boundaries_letters[26];
|
||
int boundaries_symbols[32];
|
||
|
||
/* This is the bug we're exploiting - the seed for the RNG is 32 bits
|
||
* from the crypto rng. The non-crypto RNG converts negative numbers
|
||
* into non-negative numbers, so there's only 2^31 possible seeds.
|
||
*/
|
||
int seed;
|
||
|
||
int password_length;
|
||
|
||
void init()
|
||
{
|
||
password_length = 16; /* Change this to match config */
|
||
|
||
int c, i;
|
||
|
||
c = '0'; i = 0; while (c <= '9') numbers[i++] = c++;
|
||
c = 'a'; i = 0; while (c <= 'z') lowers[i++] = c++;
|
||
c = 'A'; i = 0; while (c <= 'Z') uppers[i++] = c++;
|
||
|
||
/* Symbols */
|
||
i = 0;
|
||
symbols[i++] = '!'; symbols[i++] = '@'; symbols[i++] = '#'; symbols[i++] = '$';
|
||
symbols[i++] = '%'; symbols[i++] = '^'; symbols[i++] = '&'; symbols[i++] = '*';
|
||
symbols[i++] = '('; symbols[i++] = ')'; symbols[i++] = '~'; symbols[i++] = '-';
|
||
symbols[i++] = '_'; symbols[i++] = '='; symbols[i++] = '+'; symbols[i++] = '\\';
|
||
symbols[i++] = '|'; symbols[i++] = '/'; symbols[i++] = '['; symbols[i++] = ']';
|
||
symbols[i++] = '{'; symbols[i++] = '}'; symbols[i++] = ';'; symbols[i++] = ':';
|
||
symbols[i++] = '`'; symbols[i++] = '\''; symbols[i++] = '"'; symbols[i++] = ',';
|
||
symbols[i++] = '.'; symbols[i++] = '<'; symbols[i++] = '>'; symbols[i++] = '?';
|
||
|
||
i = 0;
|
||
boundaries_charclass[i++] = 536870912; boundaries_charclass[i++] = 1073741824;
|
||
boundaries_charclass[i++] = 1610612736; boundaries_charclass[i++] = 2147483647;
|
||
|
||
i = 0;
|
||
boundaries_numbers[i++] = 214748365; boundaries_numbers[i++] = 429496730;
|
||
boundaries_numbers[i++] = 644245095; boundaries_numbers[i++] = 858993460;
|
||
boundaries_numbers[i++] = 1073741824; boundaries_numbers[i++] = 1288490189;
|
||
boundaries_numbers[i++] = 1503238554; boundaries_numbers[i++] = 1717986919;
|
||
boundaries_numbers[i++] = 1932735284; boundaries_numbers[i++] = 2147483647;
|
||
|
||
i = 0;
|
||
boundaries_letters[i++] = 82595525; boundaries_letters[i++] = 165191050;
|
||
boundaries_letters[i++] = 247786575; boundaries_letters[i++] = 330382100;
|
||
boundaries_letters[i++] = 412977625; boundaries_letters[i++] = 495573150;
|
||
boundaries_letters[i++] = 578168675; boundaries_letters[i++] = 660764200;
|
||
boundaries_letters[i++] = 743359725; boundaries_letters[i++] = 825955250;
|
||
boundaries_letters[i++] = 908550775; boundaries_letters[i++] = 991146300;
|
||
boundaries_letters[i++] = 1073741824; boundaries_letters[i++] = 1156337349;
|
||
boundaries_letters[i++] = 1238932874; boundaries_letters[i++] = 1321528399;
|
||
boundaries_letters[i++] = 1404123924; boundaries_letters[i++] = 1486719449;
|
||
boundaries_letters[i++] = 1569314974; boundaries_letters[i++] = 1651910499;
|
||
boundaries_letters[i++] = 1734506024; boundaries_letters[i++] = 1817101549;
|
||
boundaries_letters[i++] = 1899697074; boundaries_letters[i++] = 1982292599;
|
||
boundaries_letters[i++] = 2064888124; boundaries_letters[i++] = 2147483647;
|
||
|
||
i = 0;
|
||
boundaries_symbols[i++] = 67108864; boundaries_symbols[i++] = 134217728;
|
||
boundaries_symbols[i++] = 201326592; boundaries_symbols[i++] = 268435456;
|
||
boundaries_symbols[i++] = 335544320; boundaries_symbols[i++] = 402653184;
|
||
boundaries_symbols[i++] = 469762048; boundaries_symbols[i++] = 536870912;
|
||
boundaries_symbols[i++] = 603979776; boundaries_symbols[i++] = 671088640;
|
||
boundaries_symbols[i++] = 738197504; boundaries_symbols[i++] = 805306368;
|
||
boundaries_symbols[i++] = 872415232; boundaries_symbols[i++] = 939524096;
|
||
boundaries_symbols[i++] = 1006632960; boundaries_symbols[i++] = 1073741824;
|
||
boundaries_symbols[i++] = 1140850688; boundaries_symbols[i++] = 1207959552;
|
||
boundaries_symbols[i++] = 1275068416; boundaries_symbols[i++] = 1342177280;
|
||
boundaries_symbols[i++] = 1409286144; boundaries_symbols[i++] = 1476395008;
|
||
boundaries_symbols[i++] = 1543503872; boundaries_symbols[i++] = 1610612736;
|
||
boundaries_symbols[i++] = 1677721600; boundaries_symbols[i++] = 1744830464;
|
||
boundaries_symbols[i++] = 1811939328; boundaries_symbols[i++] = 1879048192;
|
||
boundaries_symbols[i++] = 1946157056; boundaries_symbols[i++] = 2013265920;
|
||
boundaries_symbols[i++] = 2080374784; boundaries_symbols[i++] = 2147483647;
|
||
|
||
seed = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i, j, s, next, nextp, val, bucket, randnum, used_charsets;
|
||
int seedarray[56];
|
||
|
||
/* BEGIN System.Random(seed) */
|
||
if(seed < 0) {
|
||
/* Only bother with non-negative integers */
|
||
word = 0;
|
||
return;
|
||
}
|
||
|
||
s = 161803398 - seed++;
|
||
seedarray[55] = s;
|
||
i = val = 1;
|
||
|
||
while(i < 55) {
|
||
bucket = 21 * i % 55;
|
||
seedarray[bucket] = val;
|
||
val = s - val;
|
||
if(val < 0) val += 2147483647;
|
||
s = seedarray[bucket];
|
||
i++;
|
||
}
|
||
|
||
i = 1;
|
||
while(i < 5) {
|
||
j = 1;
|
||
while(j < 56) {
|
||
seedarray[j] -= seedarray[1 + (j + 30) % 55];
|
||
if(seedarray[j] < 0) seedarray[j] += 2147483647;
|
||
j++;
|
||
}
|
||
i++;
|
||
}
|
||
next = 0;
|
||
nextp = 21;
|
||
/* END System.Random(seed) */
|
||
|
||
used_charsets = 0;
|
||
while(used_charsets != 15) {
|
||
i = 0;
|
||
while(i < password_length) {
|
||
/* BEGIN Random.Sample() */
|
||
if (++next >= 56) next = 1;
|
||
if (++nextp >= 56) nextp = 1;
|
||
randnum = seedarray[next] - seedarray[nextp];
|
||
if (randnum == 2147483647) randnum--;
|
||
if (randnum < 0) randnum += 2147483647;
|
||
seedarray[next] = randnum;
|
||
/* END Random.Sample() */
|
||
|
||
j = 0;
|
||
while(boundaries_charclass[j] < randnum) j++;
|
||
|
||
word[i] = j; /* Temporarily store in word[] */
|
||
used_charsets |= (1 << j);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
i = 0;
|
||
while(i < password_length) {
|
||
/* BEGIN Random.Sample() */
|
||
if (++next >= 56) next = 1;
|
||
if (++nextp >= 56) nextp = 1;
|
||
randnum = seedarray[next] - seedarray[nextp];
|
||
if (randnum == 2147483647) randnum--;
|
||
if (randnum < 0) randnum += 2147483647;
|
||
seedarray[next] = randnum;
|
||
/* END Random.Sample() */
|
||
j = 0;
|
||
|
||
if(word[i] == 0) {
|
||
while(boundaries_letters[j] < randnum) j++;
|
||
word[i++] = lowers[j];
|
||
} else if (word[i] == 1) {
|
||
while(boundaries_letters[j] < randnum) j++;
|
||
word[i++] = uppers[j];
|
||
} else if (word[i] == 2) {
|
||
while(boundaries_numbers[j] < randnum) j++;
|
||
word[i++] = numbers[j];
|
||
} else { /* if (word[i] == 3) */
|
||
while(boundaries_symbols[j] < randnum) j++;
|
||
word[i++] = symbols[j];
|
||
}
|
||
}
|
||
word[i] = 0;
|
||
}
|
||
|
||
|
||
void restore()
|
||
{
|
||
int i, j, s, next, nextp, val, bucket, randnum, used_charsets;
|
||
int seedarray[56];
|
||
int candidate[32]; /* This needs to be at-least as big as password-length */
|
||
|
||
seed = 0;
|
||
|
||
while(seed > 0) {
|
||
/* BEGIN System.Random(seed) */
|
||
s = 161803398 - seed++;
|
||
seedarray[55] = s;
|
||
i = val = 1;
|
||
|
||
while(i < 55) {
|
||
bucket = 21 * i % 55;
|
||
seedarray[bucket] = val;
|
||
val = s - val;
|
||
if(val < 0) val += 2147483647;
|
||
s = seedarray[bucket];
|
||
i++;
|
||
}
|
||
|
||
i = 1;
|
||
while(i < 5) {
|
||
j = 1;
|
||
while(j < 56) {
|
||
seedarray[j] -= seedarray[1 + (j + 30) % 55];
|
||
if(seedarray[j] < 0) seedarray[j] += 2147483647;
|
||
j++;
|
||
}
|
||
i++;
|
||
}
|
||
next = 0;
|
||
nextp = 21;
|
||
/* END System.Random(seed) */
|
||
|
||
used_charsets = 0;
|
||
while(used_charsets != 15) {
|
||
i = 0;
|
||
while(i < password_length) {
|
||
/* BEGIN Random.Sample() */
|
||
if (++next >= 56) next = 1;
|
||
if (++nextp >= 56) nextp = 1;
|
||
randnum = seedarray[next] - seedarray[nextp];
|
||
if (randnum == 2147483647) randnum--;
|
||
if (randnum < 0) randnum += 2147483647;
|
||
seedarray[next] = randnum;
|
||
/* END Random.Sample() */
|
||
|
||
j = 0;
|
||
while(boundaries_charclass[j] < randnum) j++;
|
||
|
||
candidate[i] = j;
|
||
used_charsets |= (1 << j);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
i = 0;
|
||
while(i < password_length) {
|
||
/* BEGIN Random.Sample() */
|
||
if (++next >= 56) next = 1;
|
||
if (++nextp >= 56) nextp = 1;
|
||
randnum = seedarray[next] - seedarray[nextp];
|
||
if (randnum == 2147483647) randnum--;
|
||
if (randnum < 0) randnum += 2147483647;
|
||
seedarray[next] = randnum;
|
||
/* END Random.Sample() */
|
||
j = 0;
|
||
|
||
if(candidate[i] == 0) {
|
||
while(boundaries_letters[j] < randnum) j++;
|
||
if(lowers[j] != word[i++]) break;
|
||
} else if (candidate[i] == 1) {
|
||
while(boundaries_letters[j] < randnum) j++;
|
||
if(uppers[j] != word[i++]) break;
|
||
} else if (candidate[i] == 2) {
|
||
while(boundaries_numbers[j] < randnum) j++;
|
||
if(numbers[j] != word[i++]) break;
|
||
} else { /* if (word[i] == 3) */
|
||
while(boundaries_symbols[j] < randnum) j++;
|
||
if(symbols[j] != word[i++]) break;
|
||
}
|
||
}
|
||
if(i == password_length) return;
|
||
}
|
||
}
|
||
|
||
# Try sequences of adjacent keys on a keyboard as candidate passwords
|
||
[List.External:Keyboard]
|
||
int maxlength, length; // Maximum password length to try, current length
|
||
int fuzz; // The desired "fuzz factor", either 0 or 1
|
||
int id[15]; // Current character indices for each position
|
||
int m[0x800]; // The keys matrix
|
||
int mc[0x100]; // Counts of adjacent keys
|
||
int f[0x40], fc; // Characters for the first position, their count
|
||
|
||
void init()
|
||
{
|
||
int minlength;
|
||
int i, j, c, p;
|
||
int k[0x40];
|
||
|
||
// Initial password length to try
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
fuzz = 1; // "Fuzz factor", set to 0 for much quicker runs
|
||
|
||
/*
|
||
* This defines the keyboard layout, by default for a QWERTY keyboard.
|
||
*/
|
||
i = 0; while (i < 0x40) k[i++] = 0;
|
||
k[0] = '`';
|
||
i = 0; while (++i <= 9) k[i] = '0' + i;
|
||
k[10] = '0'; k[11] = '-'; k[12] = '=';
|
||
k[0x11] = 'q'; k[0x12] = 'w'; k[0x13] = 'e'; k[0x14] = 'r';
|
||
k[0x15] = 't'; k[0x16] = 'y'; k[0x17] = 'u'; k[0x18] = 'i';
|
||
k[0x19] = 'o'; k[0x1a] = 'p'; k[0x1b] = '['; k[0x1c] = ']';
|
||
k[0x1d] = '\\';
|
||
k[0x21] = 'a'; k[0x22] = 's'; k[0x23] = 'd'; k[0x24] = 'f';
|
||
k[0x25] = 'g'; k[0x26] = 'h'; k[0x27] = 'j'; k[0x28] = 'k';
|
||
k[0x29] = 'l'; k[0x2a] = ';'; k[0x2b] = '\'';
|
||
k[0x31] = 'z'; k[0x32] = 'x'; k[0x33] = 'c'; k[0x34] = 'v';
|
||
k[0x35] = 'b'; k[0x36] = 'n'; k[0x37] = 'm'; k[0x38] = ',';
|
||
k[0x39] = '.'; k[0x3a] = '/';
|
||
|
||
i = 0; while (i < 0x100) mc[i++] = 0;
|
||
fc = 0;
|
||
|
||
/* rows */
|
||
c = 0;
|
||
i = 0;
|
||
while (i < 0x40) {
|
||
p = c;
|
||
c = k[i++] & 0xff;
|
||
if (!c) continue;
|
||
f[fc++] = c;
|
||
if (!p) continue;
|
||
m[(c << 3) + mc[c]++] = p;
|
||
m[(p << 3) + mc[p]++] = c;
|
||
}
|
||
f[fc] = 0;
|
||
|
||
/* columns */
|
||
i = 0;
|
||
while (i < 0x30) {
|
||
p = k[i++] & 0xff;
|
||
if (!p) continue;
|
||
j = 1 - fuzz;
|
||
while (j <= 1 + fuzz) {
|
||
c = k[i + 0x10 - j++] & 0xff;
|
||
if (!c) continue;
|
||
m[(c << 3) + mc[c]++] = p;
|
||
m[(p << 3) + mc[p]++] = c;
|
||
}
|
||
}
|
||
|
||
length = 0;
|
||
while (length < minlength)
|
||
id[length++] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i, p, maxcount;
|
||
|
||
word[i = 0] = p = f[id[0]];
|
||
while (++i < length)
|
||
word[i] = p = m[(p << 3) + id[i]];
|
||
word[i--] = 0;
|
||
|
||
if (i) maxcount = mc[word[i - 1]]; else maxcount = fc;
|
||
while (++id[i] >= maxcount) {
|
||
if (!i) {
|
||
if (length < maxlength) {
|
||
id[0] = 0;
|
||
id[length++] = 0;
|
||
}
|
||
return;
|
||
}
|
||
id[i--] = 0;
|
||
if (i) maxcount = mc[word[i - 1]]; else maxcount = fc;
|
||
}
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i;
|
||
|
||
/* Calculate the length */
|
||
length = 0;
|
||
while (word[length])
|
||
id[length++] = 0;
|
||
|
||
/* Infer the first character index */
|
||
i = -1;
|
||
while (++i < fc) {
|
||
if (f[i] == word[0]) {
|
||
id[0] = i;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* This sample can be enhanced to infer the rest of the indices here */
|
||
}
|
||
|
||
# Simplest (fastest?) possible dumb exhaustive search, demonstrating a
|
||
# mode that does not need any special restore() handling.
|
||
# Defaults to printable ASCII.
|
||
[List.External:DumbDumb]
|
||
int maxlength; // Maximum password length to try
|
||
int startchar, endchar; // Range of characters (inclusive)
|
||
|
||
void init()
|
||
{
|
||
int i;
|
||
|
||
startchar = ' '; // Start with space
|
||
endchar = '~'; // End with tilde
|
||
|
||
// Create first word, honoring --min-len
|
||
if (!(i = req_minlen))
|
||
i++;
|
||
word[i] = 0;
|
||
while (i--)
|
||
word[i] = startchar;
|
||
word[0] = startchar - 1;
|
||
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen; // --max-len
|
||
else
|
||
maxlength = cipher_limit; // format's limit
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
if (++word <= endchar)
|
||
return;
|
||
|
||
i = 0;
|
||
|
||
while (word[i] > endchar) {
|
||
word[i++] = startchar;
|
||
if (!word[i]) {
|
||
word[i] = startchar;
|
||
word[i + 1] = 0;
|
||
} else
|
||
word[i]++;
|
||
}
|
||
|
||
if (i >= maxlength)
|
||
word = 0;
|
||
}
|
||
|
||
/*
|
||
* This mode will resume correctly without any restore handing.
|
||
* The empty function just confirms to John that everything is in order.
|
||
*/
|
||
void restore()
|
||
{
|
||
}
|
||
|
||
# Generic implementation of "dumb" exhaustive search, given a range of lengths
|
||
# and an arbitrary charset. This is pre-configured to try 8-bit characters
|
||
# against LM hashes, which is only reasonable to do for very short password
|
||
# half lengths.
|
||
[List.External:DumbForce]
|
||
int maxlength; // Maximum password length to try
|
||
int last; // Last character position, zero-based
|
||
int lastid; // Character index in the last position
|
||
int id[0x7f]; // Current character indices for other positions
|
||
int charset[0x100], c0; // Character set
|
||
|
||
void init()
|
||
{
|
||
int minlength;
|
||
int i, c;
|
||
|
||
// Initial password length to try, must be at least 1
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
|
||
/*
|
||
* This defines the character set.
|
||
*
|
||
* Let's say, we want to try TAB, all non-control ASCII characters, and all
|
||
* 8-bit characters, including the 8-bit terminal controls range (as these are
|
||
* used as regular national characters with some 8-bit encodings), but except
|
||
* for known terminal controls (risky for the terminal we may be running on).
|
||
*
|
||
* Also, let's say our hashes are case-insensitive, so skip lowercase letters
|
||
* (this is right for LM hashes).
|
||
*/
|
||
i = 0;
|
||
charset[i++] = 9; // Add horizontal TAB (ASCII 9), then
|
||
c = ' '; // start with space (ASCII 32) and
|
||
while (c < 'a') // proceed till lowercase 'a'
|
||
charset[i++] = c++;
|
||
c = 'z' + 1; // Skip lowercase letters and
|
||
while (c <= 0x7e) // proceed for all printable ASCII
|
||
charset[i++] = c++;
|
||
c++; // Skip DEL (ASCII 127) and
|
||
while (c < 0x84) // proceed over 8-bit codes till IND
|
||
charset[i++] = c++;
|
||
charset[i++] = 0x86; // Skip IND (84 hex) and NEL (85 hex)
|
||
charset[i++] = 0x87;
|
||
c = 0x89; // Skip HTS (88 hex)
|
||
while (c < 0x8d) // Proceed till RI (8D hex)
|
||
charset[i++] = c++;
|
||
c = 0x91; // Skip RI, SS2, SS3, DCS
|
||
while (c < 0x96) // Proceed till SPA (96 hex)
|
||
charset[i++] = c++;
|
||
charset[i++] = 0x99; // Skip SPA, EPA, SOS
|
||
c = 0xa0; // Skip DECID, CSI, ST, OSC, PM, APC
|
||
while (c <= 0xff) // Proceed with the rest of 8-bit codes
|
||
charset[i++] = c++;
|
||
|
||
/* Zero-terminate it, and cache the first character */
|
||
charset[i] = 0;
|
||
c0 = charset[0];
|
||
|
||
last = minlength - 1;
|
||
i = 0;
|
||
while (i <= last) {
|
||
id[i] = 0;
|
||
word[i++] = c0;
|
||
}
|
||
lastid = -1;
|
||
word[i] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
/* Handle the typical case specially */
|
||
if (word[last] = charset[++lastid]) return;
|
||
|
||
lastid = 0;
|
||
word[i = last] = c0;
|
||
while (i--) { // Have a preceding position?
|
||
if (word[i] = charset[++id[i]]) return;
|
||
id[i] = 0;
|
||
word[i] = c0;
|
||
}
|
||
|
||
if (++last < maxlength) { // Next length?
|
||
id[last] = lastid = 0;
|
||
word[last] = c0;
|
||
word[last + 1] = 0;
|
||
} else // We're done
|
||
word = 0;
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i, c;
|
||
|
||
/* Calculate the current length and infer the character indices */
|
||
last = 0;
|
||
while (c = word[last]) {
|
||
i = 0; while (charset[i] != c && charset[i]) i++;
|
||
if (!charset[i]) i = 0; // Not found
|
||
id[last++] = i;
|
||
}
|
||
lastid = id[--last];
|
||
}
|
||
|
||
# Generic implementation of exhaustive search for a partially-known password.
|
||
# This is pre-configured for length 8, lowercase and uppercase letters in the
|
||
# first 4 positions (52 different characters), and digits in the remaining 4
|
||
# positions - however, the corresponding part of init() may be modified to use
|
||
# arbitrary character sets or even fixed characters for each position.
|
||
[List.External:KnownForce]
|
||
int last; // Last character position, zero-based
|
||
int lastofs; // Last character position offset into charset[]
|
||
int lastid; // Current character index in the last position
|
||
int id[0x7f]; // Current character indices for other positions
|
||
int charset[0x7f00]; // Character sets, 0x100 elements for each position
|
||
|
||
void init()
|
||
{
|
||
int length, maxlength;
|
||
int pos, ofs, i, c;
|
||
|
||
if (req_minlen)
|
||
length = req_minlen;
|
||
else
|
||
length = 8; // Password length to try (NOTE: other [eg. shorter]
|
||
// lengths will not be tried!)
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
|
||
/* This defines the character sets for different character positions */
|
||
if (length > maxlength)
|
||
length = maxlength;
|
||
pos = 0;
|
||
while (pos < 4) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = 'a';
|
||
while (c <= 'z')
|
||
charset[ofs + i++] = c++;
|
||
c = 'A';
|
||
while (c <= 'Z')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
while (pos < length) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = '0';
|
||
while (c <= '9')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
|
||
last = length - 1;
|
||
pos = -1;
|
||
while (++pos <= last)
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
lastid = (lastofs = last << 8) - 1;
|
||
word[pos] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int pos;
|
||
|
||
/* Handle the typical case specially */
|
||
if (word[last] = charset[++lastid]) return;
|
||
|
||
word[pos = last] = charset[lastid = lastofs];
|
||
while (pos--) { // Have a preceding position?
|
||
if (word[pos] = charset[++id[pos]]) return;
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
}
|
||
|
||
word = 0; // We're done
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i, c;
|
||
|
||
/* Calculate the current length and infer the character indices */
|
||
last = 0;
|
||
while (c = word[last]) {
|
||
i = lastofs = last << 8;
|
||
while (charset[i] != c && charset[i]) i++;
|
||
if (!charset[i]) i = lastofs; // Not found
|
||
id[last++] = i;
|
||
}
|
||
lastid = id[--last];
|
||
}
|
||
|
||
# A variation of KnownForce configured to try likely date and time strings.
|
||
[List.External:DateTime]
|
||
int last; // Last character position, zero-based
|
||
int lastofs; // Last character position offset into charset[]
|
||
int lastid; // Current character index in the last position
|
||
int id[0x7f]; // Current character indices for other positions
|
||
int charset[0x7f00]; // Character sets, 0x100 elements for each position
|
||
|
||
void init()
|
||
{
|
||
int length;
|
||
int pos, ofs, i, c;
|
||
|
||
length = 8; // Must be one of: 4, 5, 7, 8
|
||
|
||
/* This defines the character sets for different character positions */
|
||
pos = 0;
|
||
while (pos < length - 6) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = '0';
|
||
while (c <= '9')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
if (pos) {
|
||
ofs = pos++ << 8;
|
||
charset[ofs] = '/';
|
||
charset[ofs + 1] = '.';
|
||
charset[ofs + 2] = ':';
|
||
charset[ofs + 3] = 0;
|
||
}
|
||
while (pos < length - 3) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = '0';
|
||
while (c <= '9')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
ofs = pos++ << 8;
|
||
charset[ofs] = '/';
|
||
charset[ofs + 1] = '.';
|
||
charset[ofs + 2] = ':';
|
||
charset[ofs + 3] = 0;
|
||
while (pos < length) {
|
||
ofs = pos++ << 8;
|
||
i = 0;
|
||
c = '0';
|
||
while (c <= '9')
|
||
charset[ofs + i++] = c++;
|
||
charset[ofs + i] = 0;
|
||
}
|
||
|
||
last = length - 1;
|
||
pos = -1;
|
||
while (++pos <= last)
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
lastid = (lastofs = last << 8) - 1;
|
||
word[pos] = 0;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int pos;
|
||
|
||
/* Handle the typical case specially */
|
||
if (word[last] = charset[++lastid]) return;
|
||
|
||
word[pos = last] = charset[lastid = lastofs];
|
||
while (pos--) { // Have a preceding position?
|
||
if (word[pos] = charset[++id[pos]]) return;
|
||
word[pos] = charset[id[pos] = pos << 8];
|
||
}
|
||
|
||
word = 0; // We're done
|
||
}
|
||
|
||
void restore()
|
||
{
|
||
int i, c;
|
||
|
||
/* Calculate the current length and infer the character indices */
|
||
last = 0;
|
||
while (c = word[last]) {
|
||
i = lastofs = last << 8;
|
||
while (charset[i] != c && charset[i]) i++;
|
||
if (!charset[i]) i = lastofs; // Not found
|
||
id[last++] = i;
|
||
}
|
||
lastid = id[--last];
|
||
}
|
||
|
||
# Try strings of repeated characters.
|
||
#
|
||
# This is the code which is common for all [List.External:Repeats*]
|
||
# sections which include this External_base section.
|
||
# The generate() function will limit the maximum length of generated
|
||
# candidates to either the format's limit (maximum password length)
|
||
# or to the limit specified with --stdout=LENGTH (Default: 125),
|
||
# thus avoiding duplicate candidates for formats with limited maximum
|
||
# passwortd length.
|
||
# The comparison of the current length and the limit is only done
|
||
# after switching to a new length.
|
||
# So, if the minimum length specified already exceeds this limit,
|
||
# then all the candidates for the minimum length will be generated
|
||
# nevertheless.
|
||
[List.External_base:Repeats]
|
||
int minlength, maxlength, minc, maxc, length, c;
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
i = 0;
|
||
while (i < length)
|
||
word[i++] = c;
|
||
word[i] = 0;
|
||
|
||
if (c++ < maxc)
|
||
return;
|
||
|
||
c = minc;
|
||
|
||
if (++length > maxlength)
|
||
c = 0; // Will NUL out the next "word" and thus terminate
|
||
}
|
||
|
||
# Try strings of repeated characters (range: space - 0xff).
|
||
[List.External:Repeats]
|
||
.include [List.External_base:Repeats]
|
||
void init()
|
||
{
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
minc = 0x20;
|
||
maxc = 0xff;
|
||
|
||
length = minlength; c = minc;
|
||
}
|
||
|
||
# Try strings of repeated digits (range: '0' - '9').
|
||
[List.External:Repeats_digits]
|
||
.include [List.External_base:Repeats]
|
||
void init()
|
||
{
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
minc = '0';
|
||
maxc = '9';
|
||
|
||
length = minlength; c = minc;
|
||
}
|
||
|
||
# Try strings of repeated lowercase letters (range: 'a' - 'z').
|
||
[List.External:Repeats_lowercase]
|
||
.include [List.External_base:Repeats]
|
||
void init()
|
||
{
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
minc = 'a';
|
||
maxc = 'z';
|
||
|
||
length = minlength; c = minc;
|
||
}
|
||
|
||
# Try strings of repeated printable ASCII characters
|
||
# (range: ' ' - '~').
|
||
[List.External:Repeats_printable_ASCII]
|
||
.include [List.External_base:Repeats]
|
||
void init()
|
||
{
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = cipher_limit; // the format's limit
|
||
minc = ' ';
|
||
maxc = '~';
|
||
|
||
length = minlength; c = minc;
|
||
}
|
||
|
||
# Try character sequences ("0123456", "acegikmoqs", "ZYXWVU", etc.).
|
||
#
|
||
# The generate() function will limit the maximum length of generated
|
||
# candidates to either the format's limit (maximum password length)
|
||
# or to the limit specified with --stdout=LENGTH (Default: 125),
|
||
# thus avoiding duplicate candidates for formats with limited maximum
|
||
# passwortd length.
|
||
# The comparison of the current length and the limit is only done
|
||
# after switching to a new length.
|
||
# So, if the minimum length specified already exceeds this limit,
|
||
# then all the candidates for the minimum length will be generated
|
||
# nevertheless.
|
||
# External modes reusing this External_base mode should only need to
|
||
# adjust the init() function.
|
||
# In the init() function, a minimum length which is > 1 should be
|
||
# specified.
|
||
# Otherwise, the generated candidates will not depend on the increment
|
||
# specified.
|
||
# For length = 1, the candidates will be the same as for external mode
|
||
# Repeats with length 1.
|
||
# Actually, Repeats is a special case of Sequence, using increment = 0.
|
||
# External modes reusing this External_base mode should also make sure
|
||
# that the number of different characters (specified as a range from "from"
|
||
# to "to") is not smaller than the minimum length ("minlength"),
|
||
# if the start increment "inc" is 1.
|
||
# For a start increment > 1, the number of different characters in the
|
||
# range "from" - "to" must be greater than or equal to
|
||
# (1 + ("minlength" - 1) * "inc").
|
||
# Otherwise you might get unexpected results.
|
||
# The range of characters to be used for the sequences needs to be
|
||
# specified by adjusting the "from" and "to" variables.
|
||
# To generate sequences which decrement characters ("987654"),
|
||
# "from" must be > "to".
|
||
# Otherwise, the generated sequences will increment characters ("abcdef").
|
||
#
|
||
# Variables to be used and the generate() function are common
|
||
# for all sections which include this External_base section.
|
||
[List.External_base:Sequence]
|
||
/*
|
||
* See the [List.External:Sequence_0-9] section to learn more about
|
||
* the meaning of these variables which can be adjusted to define
|
||
* new external modes based on an existing one:
|
||
*/
|
||
int minlength, from, to, maxlength, inc, direction;
|
||
|
||
/*
|
||
* The value of these variables shouldn't be changed when copying
|
||
* an existing external mode:
|
||
*/
|
||
int length, first;
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
i = 0;
|
||
|
||
while (i < length) {
|
||
word[i] = first + (i * inc * direction);
|
||
++i;
|
||
}
|
||
word[i] = 0;
|
||
|
||
// start the next sequence of the same length
|
||
// with the next character
|
||
first = first + direction;
|
||
|
||
// But check that a sequence of the current length
|
||
// is still possible (without leaving the range of
|
||
// characters allowed
|
||
if ((direction > 0 && first + (length - 1) * inc > to) ||
|
||
(direction < 0 && first - (length - 1) * inc < to)) {
|
||
// No more sequence is possible. Reset start character
|
||
first = from;
|
||
// Now try the next length.
|
||
// But just in case an individual External mode reusing
|
||
// this External_base mode did specify a maxlength
|
||
// which is larger than the one supported by the format
|
||
// or by --stdout=LENGTH, make sure no more candidates
|
||
// are generated.
|
||
// Checking this just once per length per increment
|
||
// doen't really hurt performance.
|
||
if (maxlength > cipher_limit)
|
||
maxlength = cipher_limit;
|
||
|
||
// For a similar reason, the maximum length of a
|
||
// sequence is limited by the number of different
|
||
// characters and by the increment.
|
||
// The larger the increment, the smaller
|
||
// the maximum possible length for a given
|
||
// character range.
|
||
while (inc * (maxlength - 1) > direction * (to - from))
|
||
--maxlength;
|
||
|
||
if (++length > maxlength) {
|
||
// The maximum length for this increment has been reached.
|
||
// Restart at minimum length with the next possible
|
||
// increment
|
||
++inc;
|
||
// Unfortunately, we have to check again
|
||
// if the maximum length needs to be reduced
|
||
// for the new increment
|
||
while (inc * (maxlength - 1) > direction * (to - from))
|
||
--maxlength;
|
||
|
||
length = minlength;
|
||
}
|
||
if (maxlength < minlength)
|
||
// With the current increment, we can't even generate
|
||
// sequences of the minimum required length.
|
||
// So we need to stop here.
|
||
// This will make sure that no more candidiates
|
||
// will be generated:
|
||
first = 0;
|
||
}
|
||
}
|
||
|
||
# Try sequences of digits (range: '0' - '9').
|
||
#
|
||
# Aditional comments can be found in the
|
||
# section [List.External_base:Sequence]
|
||
#
|
||
# This external mode is thoroughly commented,
|
||
# to make it easier to copy and adjust it as needed.
|
||
[List.External:Sequence_0-9]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
// Adjust the following 4 variables if you want to define
|
||
// a different external mode.
|
||
|
||
// This is the start character for the generated sequence
|
||
// if "from" is smaller than "to", the increment from
|
||
// first to second character ... will be positive ("0123456789").
|
||
// Otherwise, it will be negative ("987654321").
|
||
from = '0';
|
||
to = '9';
|
||
|
||
// minimum length of the sequence
|
||
// make sure it is not larger than the number of different characters
|
||
// in the range between "from" and "to" specified above
|
||
minlength = 2;
|
||
|
||
// start increment for generating the sequence, usually 1
|
||
// if it is larger than 1, you need even more characters
|
||
// in the range between "from" and "to"
|
||
// Don't specify a negative value here.
|
||
// If you want to generate sequences like "zyxwvu" or "86420",
|
||
// adjust "from" and "to" so that "from" is larger than "to".
|
||
// (A start increment of 0 is also possible, in that case the first
|
||
// sequences will be candidates which just repeat the same character.)
|
||
inc = 1;
|
||
|
||
// For copied external modes, no further changes should be required
|
||
// in the statements following this comment
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
// We have to create sequences which decrement the previous character
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
# Try sequence of lower case letters (range: 'a' - 'z').
|
||
# This external mode is not very well documented.
|
||
# Refer to [List.External:Sequence_0-9] for more detailed information.
|
||
[List.External:Sequence_a-z]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
from = 'a';
|
||
to = 'z';
|
||
minlength = 2;
|
||
inc = 1;
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
# Try sequence of lower case letters (range: 'a' - 'z'), but reversed
|
||
# ("zxywvu").
|
||
# This external mode is not very well documented.
|
||
# Refer to [List.External:Sequence_0-9] for more detailed information.
|
||
[List.External:Sequence_z-a]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
from = 'z';
|
||
to = 'a';
|
||
minlength = 2;
|
||
inc = 1;
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
# Try sequence of printable ASCII characters (range: ' ' - '~').
|
||
# This external mode is not very well documented.
|
||
# Refer to [List.External:Sequence_0-9] for more detailed information.
|
||
[List.External:Sequence_printable_ascii]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
from = ' ';
|
||
to = '~';
|
||
minlength = 2;
|
||
inc = 1;
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
# Try sequence of printable ASCII characters (range: ' ' - '~'),
|
||
# but decrementing characters ("fedcba") instead of incrementing.
|
||
# This external mode is not very well documented.
|
||
# Refer to [List.External:Sequence_0-9] for more detailed information.
|
||
[List.External:Sequence_reversed_ascii]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
from = '~';
|
||
to = ' ';
|
||
minlength = 2;
|
||
inc = 1;
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
# Try sequence of characters (range: space - 0xff).
|
||
# This external mode is not very well documented.
|
||
# Refer to [List.External:Sequence_0-9] for more detailed information.
|
||
[List.External:Sequence]
|
||
.include [List.External_base:Sequence]
|
||
void init()
|
||
{
|
||
from = ' ';
|
||
to = 0xff;
|
||
minlength = 2;
|
||
inc = 1;
|
||
|
||
length = minlength;
|
||
first = from;
|
||
|
||
if (from <= to) {
|
||
maxlength = to - from + 1;
|
||
direction = 1;
|
||
} else {
|
||
maxlength = from - to + 1;
|
||
direction = -1;
|
||
}
|
||
}
|
||
|
||
|
||
# Generate candidate passwords from many small subsets of characters from a
|
||
# much larger full character set. This will test for passwords containing too
|
||
# few different characters. As currently implemented, this code will produce
|
||
# some duplicates, although their number is relatively small when the maximum
|
||
# number of different characters (the maxdiff setting) is significantly lower
|
||
# than the maximum length (the maxlength setting). Nevertheless, you may want
|
||
# to pass the resulting candidate passwords through "unique" if you intend to
|
||
# test them against hashes that are salted and/or of a slow to compute type.
|
||
[List.External:Subsets]
|
||
int minlength; // Minimum password length to try
|
||
int maxlength; // Maximum password length to try
|
||
int startdiff; // Initial number of characters in a subset to try
|
||
int maxdiff; // Maximum number of characters in a subset to try
|
||
int last; // Last character position, zero-based
|
||
int lastid; // Character index in the last position
|
||
int id[0x7f]; // Current character indices for other positions
|
||
int subset[0x100], c0; // Current subset
|
||
int subcount; // Number of characters in the current subset
|
||
int subid[0x100]; // Indices into charset[] of characters in subset[]
|
||
int charset[0x100]; // Full character set
|
||
int charcount; // Number of characters in the full charset
|
||
|
||
void init()
|
||
{
|
||
int i, c;
|
||
|
||
// Minimum password length to try, must be at least 1
|
||
if (req_minlen)
|
||
minlength = req_minlen;
|
||
else
|
||
minlength = 1;
|
||
|
||
// Maximum password length to try, must be at least same as minlength
|
||
// This external mode's default maximum length can be adjusted
|
||
// using --max-length= on the command line
|
||
if (req_maxlen)
|
||
maxlength = req_maxlen;
|
||
else
|
||
maxlength = 8;
|
||
|
||
// "cipher_limit" is the variable which contains the format's
|
||
// maximum password length
|
||
if (maxlength > cipher_limit)
|
||
maxlength = cipher_limit;
|
||
|
||
startdiff = 1; // Initial number of different characters to try
|
||
maxdiff = 3; // Maximum number of different characters to try
|
||
|
||
/* This defines the character set */
|
||
i = 0;
|
||
c = 0x20;
|
||
while (c <= 0x7e)
|
||
charset[i++] = c++;
|
||
|
||
if (maxdiff > (charcount = i))
|
||
maxdiff = i;
|
||
if (maxdiff > maxlength)
|
||
maxdiff = maxlength;
|
||
|
||
/*
|
||
* Initialize the variables such that generate() gets to its "next subset"
|
||
* code, which will initialize everything for real.
|
||
*/
|
||
subcount = (i = startdiff) - 1;
|
||
while (i--)
|
||
subid[i] = charcount;
|
||
subset[0] = c0 = 0;
|
||
last = maxlength - 1;
|
||
lastid = -1;
|
||
}
|
||
|
||
void generate()
|
||
{
|
||
int i;
|
||
|
||
/* Handle the typical case specially */
|
||
if (word[last] = subset[++lastid]) return;
|
||
|
||
lastid = 0;
|
||
word[i = last] = c0;
|
||
while (i--) { // Have a preceding position?
|
||
if (word[i] = subset[++id[i]]) return;
|
||
id[i] = 0;
|
||
word[i] = c0;
|
||
}
|
||
|
||
if (++last < maxlength) { // Next length?
|
||
id[last] = lastid = 0;
|
||
word[last] = c0;
|
||
word[last + 1] = 0;
|
||
return;
|
||
}
|
||
|
||
/* Next subset */
|
||
if (subcount) {
|
||
int j;
|
||
i = subcount - 1;
|
||
j = charcount;
|
||
while (++subid[i] >= j) {
|
||
if (i--) {
|
||
j--;
|
||
continue;
|
||
}
|
||
subid[i = 0] = 0;
|
||
subset[++subcount] = 0;
|
||
break;
|
||
}
|
||
} else {
|
||
subid[i = 0] = 0;
|
||
subset[++subcount] = 0;
|
||
}
|
||
subset[i] = charset[subid[i]];
|
||
while (++i < subcount)
|
||
subset[i] = charset[subid[i] = subid[i - 1] + 1];
|
||
|
||
if (subcount > maxdiff) {
|
||
word = 0; // Done
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* We won't be able to fully use the subset if the length is smaller than the
|
||
* character count. We assume that we've tried all smaller subsets before, so
|
||
* we don't bother with such short lengths.
|
||
*/
|
||
if (minlength < subcount)
|
||
last = subcount - 1;
|
||
else
|
||
last = minlength - 1;
|
||
c0 = subset[0];
|
||
i = 0;
|
||
while (i <= last) {
|
||
id[i] = 0;
|
||
word[i++] = c0;
|
||
}
|
||
lastid = 0;
|
||
word[i] = 0;
|
||
}
|
||
|
||
# Simple password policy matching: require at least one digit.
|
||
[List.External:AtLeast1-Simple]
|
||
void filter()
|
||
{
|
||
int i, c;
|
||
|
||
i = 0;
|
||
while (c = word[i++])
|
||
if (c >= '0' && c <= '9')
|
||
return; // Found at least one suitable character, good
|
||
|
||
word = 0; // No suitable characters found, skip this "word"
|
||
}
|
||
|
||
# The same password policy implemented in a more efficient and more generic
|
||
# fashion (easy to expand to include other "sufficient" characters as well).
|
||
[List.External:AtLeast1-Generic]
|
||
int mask[0x100];
|
||
|
||
void init()
|
||
{
|
||
int c;
|
||
|
||
mask[0] = 0; // Terminate the loop in filter() on NUL
|
||
c = 1;
|
||
while (c < 0x100)
|
||
mask[c++] = 1; // Continue looping in filter() on most chars
|
||
|
||
c = '0';
|
||
while (c <= '9')
|
||
mask[c++] = 0; // Terminate the loop in filter() on digits
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
int i;
|
||
|
||
i = -1;
|
||
while (mask[word[++i]])
|
||
continue;
|
||
if (word[i])
|
||
return; // Found at least one suitable character, good
|
||
|
||
word = 0; // No suitable characters found, skip this "word"
|
||
}
|
||
|
||
# An efficient and fairly generic password policy matcher. The policy to match
|
||
# is specified in the check at the end of filter() and in mask[]. For example,
|
||
# lowercase and uppercase letters may be treated the same by initializing the
|
||
# corresponding mask[] elements to the same value, then adjusting the value to
|
||
# check "seen" for accordingly.
|
||
[List.External:Policy]
|
||
int mask[0x100];
|
||
|
||
void init()
|
||
{
|
||
int c;
|
||
|
||
mask[0] = 0x100;
|
||
c = 1;
|
||
while (c < 0x100)
|
||
mask[c++] = 0x200;
|
||
|
||
c = 'a';
|
||
while (c <= 'z')
|
||
mask[c++] = 1;
|
||
c = 'A';
|
||
while (c <= 'Z')
|
||
mask[c++] = 2;
|
||
c = '0';
|
||
while (c <= '9')
|
||
mask[c++] = 4;
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
int i, seen;
|
||
|
||
/*
|
||
* This loop ends when we see NUL (sets 0x100) or a disallowed character
|
||
* (sets 0x200).
|
||
*/
|
||
i = -1; seen = 0;
|
||
while ((seen |= mask[word[++i]]) < 0x100)
|
||
continue;
|
||
|
||
/*
|
||
* We should have seen at least one character of each type (which "add up"
|
||
* to 7) and then a NUL (adds 0x100), but not any other characters (would
|
||
* add 0x200). The length must be 8.
|
||
*/
|
||
if (seen != 0x107 || i != 8)
|
||
word = 0; // Does not conform to policy
|
||
}
|
||
|
||
# Append the Luhn algorithm digit to arbitrary all-digit strings. Optimized
|
||
# for speed, not for size nor simplicity. The primary optimization trick is to
|
||
# compute the length and four sums in parallel (in two SIMD'ish variables).
|
||
# Then whether the length is even or odd determines which two of the four sums
|
||
# are actually used. Checks for non-digits and for NUL are packed into the
|
||
# SIMD'ish bitmasks as well.
|
||
[List.External:AppendLuhn]
|
||
int map1[0x100], map2[0x1fff];
|
||
|
||
void init()
|
||
{
|
||
int i;
|
||
|
||
map1[0] = ~0x7fffffff;
|
||
i = 1;
|
||
while (i < 0x100)
|
||
map1[i++] = ~0x7effffff;
|
||
i = -1;
|
||
while (++i < 10)
|
||
map1['0' + i] = i + ((i * 2 % 10 + i / 5) << 12);
|
||
i = -1;
|
||
while (++i < 0x1fff) {
|
||
if (i % 10)
|
||
map2[i] = '9' + 1 - i % 10;
|
||
else
|
||
map2[i] = '0';
|
||
}
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
int i, o, e;
|
||
|
||
i = o = e = 0;
|
||
while ((o += map1[word[i++]]) >= 0) {
|
||
if ((e += map1[word[i++]]) >= 0)
|
||
continue;
|
||
if (e & 0x01000000)
|
||
return; // Not all-digit, leave unmodified
|
||
word[i--] = 0;
|
||
word[i] = map2[(e & 0xfff) + (o >> 12)];
|
||
return;
|
||
}
|
||
if (o & 0x01000000)
|
||
return; // Not all-digit, leave unmodified
|
||
word[i--] = 0;
|
||
word[i] = map2[(o & 0xfff) + (e >> 12)];
|
||
}
|
||
|
||
# Trivial Rotate function, which rotates letters in a word
|
||
# by a given number of places (like 13 in case of ROT13).
|
||
# Words which don't contain any letters (and thus wouldn't be changed
|
||
# by this filter) are skipped, because these unchanged words probably
|
||
# should have been tried before trying a mangled version.
|
||
[List.External_base:Filter_Rotate]
|
||
|
||
int rot; // The number of places to rotate each letter in a word
|
||
|
||
void filter()
|
||
{
|
||
int i, j, c;
|
||
|
||
i = 0;
|
||
j = 0; // j counts the number of changed characters
|
||
|
||
while (c = word[i]) {
|
||
if (c >= 'a' && c <= 'z') {
|
||
c = c - 26 + rot;
|
||
if (c < 'a') c += 26;
|
||
word[i] = c;
|
||
j++;
|
||
} else if (c >= 'A' && c <= 'Z' ) {
|
||
c = c - 26 + rot;
|
||
if (c < 'A') c += 26;
|
||
word[i] = c;
|
||
j++;
|
||
}
|
||
i++;
|
||
}
|
||
if (j == 0)
|
||
// Nothing changed. Reject this word.
|
||
word = 0;
|
||
}
|
||
|
||
# ROT13 Example
|
||
[List.External:Filter_ROT13]
|
||
.include [List.External_base:Filter_Rotate]
|
||
void init()
|
||
{
|
||
// Just in case someone wants to "rotate" by other values,
|
||
// adjust the value of the rot variable
|
||
// (may be in a copied external mode):
|
||
// 13: "abcABCxyzXYZ" -> "nopNOPklmKLM"
|
||
// 1: "abcABCxyzXYZ" -> "bcdBCDyzaYZA"
|
||
// 25: "abcABCxyzXYZ" -> "zabZABwxyWXY"
|
||
// -1: "abcABCxyzXYZ" -> "zabZABwxyWXY"
|
||
// and so on
|
||
// Allowed range: -25 <= rot <= -1, or 1 <= rot <= 25
|
||
rot = 13;
|
||
|
||
// Don't change the following statement.
|
||
// It is supposed to "sanitize" the value to be in the
|
||
// range
|
||
rot = (rot + 26) % 26;
|
||
}
|
||
|
||
# Trivial parallel processing example (obsoleted by the "--node" option)
|
||
[List.External:Parallel]
|
||
/*
|
||
* This word filter makes John process some of the words only, for running
|
||
* multiple instances on different CPUs. It can be used with any cracking
|
||
* mode except for "single crack". Note: this is not a good solution, but
|
||
* is just an example of what can be done with word filters.
|
||
*/
|
||
|
||
int node, total; // This node's number, and node count
|
||
int number; // Current word number
|
||
|
||
void init()
|
||
{
|
||
node = 1; total = 2; // Node 1 of 2, change as appropriate
|
||
number = node - 1; // Speedup the filter a bit
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
if (number++ % total) // Word for a different node?
|
||
word = 0; // Yes, skip it
|
||
}
|
||
|
||
# Interrupt the cracking session after "max" words tried
|
||
[List.External:AutoAbort]
|
||
int max; // Maximum number of words to try
|
||
int number; // Current word number
|
||
|
||
void init()
|
||
{
|
||
max = 1000;
|
||
number = 0;
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
if (++number > max)
|
||
abort = 1; // Interrupt the cracking session
|
||
}
|
||
|
||
# Print the status line after every "interval" words tried
|
||
[List.External:AutoStatus]
|
||
int interval; // How often to print the status
|
||
int number; // Current word number
|
||
|
||
void init()
|
||
{
|
||
interval = 1000;
|
||
number = 0;
|
||
}
|
||
|
||
void filter()
|
||
{
|
||
if (number++ % interval)
|
||
return;
|
||
status = 1; // Print the status line
|
||
}
|
||
|
||
#
|
||
# Reference example hybrid-mode external. same as jtr-rule: $[0-9]$[0-9]
|
||
# this format is to be used similar to a filter, in that it requires some
|
||
# other word generator (markov, wordlist, etc). However, this type external
|
||
# will get new() called with each word, and then have next() called, until
|
||
# the word[0]=0 is seen (meaning all candidates for the base word have been
|
||
# generated. Prior to new() or restore(), word[] is the 'base' word.
|
||
# if the script is able to properly resume, then it should set the global
|
||
# variable hybrid_total to the count of candidates that will be generated
|
||
# for this word (in new() / restore(), then in the body of restore() there
|
||
# is a global variable set 'hybrid_resume' that was the prior number of
|
||
# canidates generated for this base-word. Resume should start at the NEXT
|
||
# If the script is not able to easily resume, then simply do NOT set the
|
||
# global hybrid_total to anything either function. JtR will 'still' resume
|
||
# propery, but it will do so by calling new()/next()/next().../next() until
|
||
# back to the proper resume location.
|
||
#
|
||
# script changed to append a _ character before the number, each time within
|
||
# the next() function. Done this way to better validate that -restore within
|
||
# jtr is working properly.
|
||
#
|
||
[List.External:Hybrid_example]
|
||
/* static vars for the script */
|
||
int cnt, length, total;
|
||
|
||
void init()
|
||
{
|
||
/* in this simple example, we always generate 100 candidates per word */
|
||
total = 100;/* this is a VERY simple example */
|
||
}
|
||
|
||
/* new word */
|
||
void new()
|
||
{
|
||
/* get the word length) */
|
||
length = 0; while (word[length++]) ; --length;
|
||
|
||
/*
|
||
* If this was a more complex script, we would compute total candidates
|
||
* at this location, if we can. If we can not compute total candidates
|
||
* then it is likely we can not resume 'easily', so if that is the
|
||
* case, we would simply set hybrid_total to -1, or do nothing, since
|
||
* do_external_hybrid_crack() sets it to -1 before calling this function.
|
||
*/
|
||
hybrid_total = total;
|
||
|
||
/* Reset or counter for THIS word. */
|
||
cnt = 0;
|
||
|
||
/*
|
||
* word will be too long to be used, or too short to be used. If so
|
||
* then set hybrid_total to 0 and this entire word will be skipped.
|
||
*/
|
||
if (req_minlen > length - 2 || (req_maxlen && req_maxlen < length + 2))
|
||
hybrid_total = 0;
|
||
}
|
||
|
||
void next()
|
||
{
|
||
/* in this simple script, if cnt is 100, this word is DONE */
|
||
if (cnt == 100) {
|
||
word[0] = 0;
|
||
return;
|
||
}
|
||
|
||
/* set word[] to the next candidate */
|
||
word[length++] = '_';
|
||
word[length ] = '0' + cnt / 10;
|
||
word[length+1] = '0' + cnt % 10;
|
||
word[length+2] = 0;
|
||
++cnt;
|
||
}
|
||
|
||
/* Called when restoring an interrupted session */
|
||
void restore()
|
||
{
|
||
int i;
|
||
|
||
length = 0; while (word[length++]) ; --length;
|
||
|
||
/* for this simple script, simply setting cnt resumes */
|
||
cnt = hybrid_resume + 1; if (cnt > 100) cnt=100;
|
||
i = 0;
|
||
while (i++ < cnt) word[length++] = '_';
|
||
word[length] = 0;
|
||
|
||
/* tell john that we have properly 'resumed', by setting a 'proper' total */
|
||
hybrid_total = total;
|
||
}
|
||
|
||
# External hybrid 'leet code
|
||
[List.External:Leet]
|
||
/*
|
||
* 1337 language in this script:
|
||
* a -> a4@
|
||
* b -> b8
|
||
* e -> e3
|
||
* g -> g9
|
||
* i -> i1!
|
||
* l -> l1
|
||
* o -> o0
|
||
* s -> s$5
|
||
* t -> t7
|
||
*/
|
||
|
||
int rotor[626]; /* max length input is 125 bytes [125*5+1]; */
|
||
int rotors[125];
|
||
int rotor_ptr[125];
|
||
int rotor_idx[125];
|
||
int rotor_cnt[125];
|
||
int current_word_count;
|
||
int max_mangle; /* controls how many bytes we run through our 'leet' code */
|
||
int max_mangle_letters;
|
||
int original_word; /* if set to 1 then we start with original word. If 0, then start with first mangled word */
|
||
|
||
void init()
|
||
{
|
||
/* note, 3^10 is 59k so aaaaaaaaaa will produce that many words! */
|
||
max_mangle_letters = 10; /* only mangle 10 characters max */
|
||
max_mangle = 4000; /* Stop building new letters if our count goes over this value */
|
||
original_word = 0;
|
||
}
|
||
|
||
/* new word */
|
||
void new()
|
||
{
|
||
int rotor_off, idx, wlen;
|
||
idx = rotor_off = wlen = 0;
|
||
hybrid_total = 1;
|
||
while (word[wlen++]) ; --wlen;
|
||
if (req_minlen > wlen || (req_maxlen && req_maxlen < wlen )) {
|
||
hybrid_total = 0;
|
||
return;
|
||
}
|
||
wlen = 0;
|
||
while (word[wlen] && idx < max_mangle_letters && hybrid_total < max_mangle) {
|
||
rotor_cnt[wlen] = rotor_idx[wlen] = 0;
|
||
rotor_ptr[wlen] = rotor_off;
|
||
if (word[wlen] == 'a') {
|
||
rotor[rotor_off++] = 'a';
|
||
rotor[rotor_off++] = '4';
|
||
rotor[rotor_off++] = '@';
|
||
}
|
||
else if (word[wlen] == 'b') {
|
||
rotor[rotor_off++] = 'b';
|
||
rotor[rotor_off++] = '8';
|
||
}
|
||
else if (word[wlen] == 'e') {
|
||
rotor[rotor_off++] = 'e';
|
||
rotor[rotor_off++] = '3';
|
||
}
|
||
else if (word[wlen] == 'g') {
|
||
rotor[rotor_off++] = 'g';
|
||
rotor[rotor_off++] = '9';
|
||
}
|
||
else if (word[wlen] == 'i') {
|
||
rotor[rotor_off++] = 'i';
|
||
rotor[rotor_off++] = '1';
|
||
rotor[rotor_off++] = '!';
|
||
}
|
||
else if (word[wlen] == 'l') {
|
||
rotor[rotor_off++] = 'l';
|
||
rotor[rotor_off++] = '1';
|
||
}
|
||
else if (word[wlen] == 'o') {
|
||
rotor[rotor_off++] = 'o';
|
||
rotor[rotor_off++] = '0';
|
||
}
|
||
else if (word[wlen] == 's') {
|
||
rotor[rotor_off++] = 's';
|
||
rotor[rotor_off++] = '$';
|
||
rotor[rotor_off++] = '5';
|
||
}
|
||
else if (word[wlen] == 't') {
|
||
rotor[rotor_off++] = 't';
|
||
rotor[rotor_off++] = '7';
|
||
}
|
||
if (rotor_off > rotor_ptr[wlen]) {
|
||
rotor_cnt[wlen] = rotor_off-rotor_ptr[wlen];
|
||
hybrid_total *= rotor_cnt[wlen];
|
||
rotors[idx++] = wlen;
|
||
}
|
||
++wlen;
|
||
}
|
||
/* hybrid_total+666 is our indicator that this is the original word */
|
||
if (original_word)
|
||
current_word_count = hybrid_total+666;
|
||
else {
|
||
current_word_count = 1; /* skip the 'original' word */
|
||
}
|
||
}
|
||
|
||
/* next iteration of this word word */
|
||
void next()
|
||
{
|
||
int idx, idx2;
|
||
if (current_word_count >= hybrid_total) {
|
||
if (current_word_count == hybrid_total+666) {
|
||
/* first word (starting word) we leave alone */
|
||
/* by making it > hybrid_total, we avoid a 2nd if statement */
|
||
current_word_count = 1;
|
||
return;
|
||
}
|
||
word[0] = 0;
|
||
return;
|
||
}
|
||
idx = rotors[idx2=0];
|
||
while (++rotor_idx[idx] >= rotor_cnt[idx]) {
|
||
rotor_idx[idx] = 0;
|
||
word[idx] = rotor[ rotor_ptr[idx] ];
|
||
idx = rotors[++idx2];
|
||
}
|
||
word[idx] = rotor[ rotor_ptr[idx]+rotor_idx[idx] ];
|
||
++current_word_count;
|
||
}
|
||
/* restore() not needed. john properly restores fast enough without it */
|
||
|
||
# External hybrid CaSE mutation code
|
||
[List.External:Case]
|
||
|
||
int rotor[251]; /* max length input is 125 bytes [125*5+1]; */
|
||
int rotors[125];
|
||
int rotor_ptr[125];
|
||
int rotor_idx[125];
|
||
int rotor_cnt[125];
|
||
int current_word_count;
|
||
int max_mangle; /* controls how many bytes we run through our 'leet' code */
|
||
int original_word; /* if set to 1 then we start with original word. If 0, then start with first mangled word */
|
||
|
||
void init()
|
||
{
|
||
max_mangle = 20; /* only mangle 20 characters max (2^20 is 1 million) */
|
||
original_word = 1; /* for case mangle, unless the data is 100% lower case, we really can not skip the original word */
|
||
}
|
||
|
||
/* new word */
|
||
void new()
|
||
{
|
||
int rotor_off, idx, wlen, ch;
|
||
idx = rotor_off = wlen = 0;
|
||
hybrid_total = 1;
|
||
while (word[wlen++]) ; --wlen;
|
||
if (req_minlen > wlen || (req_maxlen && req_maxlen < wlen )) {
|
||
hybrid_total = 0;
|
||
return;
|
||
}
|
||
wlen = 0;
|
||
while (word[wlen] && idx < max_mangle) {
|
||
rotor_cnt[wlen] = rotor_idx[wlen] = 0;
|
||
rotor_ptr[wlen] = rotor_off;
|
||
ch = word[wlen];
|
||
if (ch >= 'A' && ch <= 'Z') {
|
||
ch += 0x20;
|
||
word[wlen] = ch;
|
||
rotor[rotor_off++] = ch;
|
||
rotor[rotor_off++] = ch-0x20;
|
||
}
|
||
if (ch >= 'a' && ch <= 'z') {
|
||
rotor[rotor_off++] = ch;
|
||
rotor[rotor_off++] = ch-0x20;
|
||
rotor_cnt[wlen] = 2;
|
||
hybrid_total *= 2;
|
||
rotors[idx++] = wlen;
|
||
}
|
||
++wlen;
|
||
}
|
||
/* hybrid_total+666 is our indicator that this is the original word */
|
||
if (original_word)
|
||
current_word_count = hybrid_total+666;
|
||
else {
|
||
current_word_count = 1; /* skip the 'original' word */
|
||
}
|
||
}
|
||
|
||
/* next iteration of this word word */
|
||
void next()
|
||
{
|
||
int idx, idx2;
|
||
if (current_word_count >= hybrid_total) {
|
||
if (current_word_count == hybrid_total+666) {
|
||
/* first word (starting word) we leave alone */
|
||
/* by making it > hybrid_total, we avoid a 2nd if statement */
|
||
current_word_count = 1;
|
||
return;
|
||
}
|
||
word[0] = 0;
|
||
return;
|
||
}
|
||
idx = rotors[idx2=0];
|
||
while (++rotor_idx[idx] >= rotor_cnt[idx]) {
|
||
rotor_idx[idx] = 0;
|
||
word[idx] = rotor[ rotor_ptr[idx] ];
|
||
idx = rotors[++idx2];
|
||
}
|
||
word[idx] = rotor[ rotor_ptr[idx]+rotor_idx[idx] ];
|
||
++current_word_count;
|
||
}
|
||
/* restore() not needed. john properly restores fast enough without it */
|
||
|
||
# Alternate hybrid external 'leet' mode (HybridLeet)
|
||
.include <hybrid.conf>
|
||
|
||
# dumb-force UTF-16, in an external file
|
||
.include <dumb16.conf>
|
||
|
||
# dumb-force UTF-32, in an external file
|
||
.include <dumb32.conf>
|
||
|
||
# repeats UTF-16, in an external file
|
||
.include <repeats16.conf>
|
||
|
||
# repeats UTF-32, in an external file
|
||
.include <repeats32.conf>
|
||
|
||
# Dynamic ($dynamic_n$) scripting code, in an external file
|
||
.include <dynamic.conf>
|
||
|
||
# Regex alphabets
|
||
.include <regex_alphabets.conf>
|
||
|
||
# NOTE, this file (john.local.conf) is deprecated. If you had any modified logic in this
|
||
# file, please create and move it to john-local.conf. The file simply can be renamed to
|
||
# the new john-local.conf if you so choose.
|
||
.include '$JOHN/john.local.conf'
|
||
|
||
# include john-local.conf (This file can be created by user, to override defaults in this john.conf file)
|
||
.include '$JOHN/john-local.conf'
|
||
|
||
# include john-local.conf in local dir, it can override john.conf, john-local.conf (or any other conf file loaded)
|
||
.include './john-local.conf'
|
||
|
||
# End of john.conf file.
|
||
# Keep this comment, and blank line above it, to make sure a john-local.conf
|
||
# that does not end with \n is properly loaded.
|