diff --git a/data/jtr/dumb16.conf b/data/jtr/dumb16.conf index f331e10074e00..d45a8c1f3d088 100644 --- a/data/jtr/dumb16.conf +++ b/data/jtr/dumb16.conf @@ -36,9 +36,6 @@ void init() else maxlength = 2; - # UTF-8 representation is up to 3x the character length - if (maxlength * 3 > cipher_limit) - maxlength = (cipher_limit + 2) / 3; /* * This defines the character set. This is auto-generated from UnicodeData.txt * and we skip control characters. diff --git a/data/jtr/dumb32.conf b/data/jtr/dumb32.conf index 2bce77322126a..a28e3d46d69e3 100644 --- a/data/jtr/dumb32.conf +++ b/data/jtr/dumb32.conf @@ -41,9 +41,6 @@ void init() else maxlength = 2; - # UTF-8 representation is up to 4x the character length - if (maxlength * 4 > cipher_limit) - maxlength = (cipher_limit + 3) / 4; /* * This defines the character set. This is auto-generated from UnicodeData.txt * and we skip control characters. diff --git a/data/jtr/dynamic_flat_sse_formats.conf b/data/jtr/dynamic_flat_sse_formats.conf index a3136d2758acc..c238a0b91e3eb 100644 --- a/data/jtr/dynamic_flat_sse_formats.conf +++ b/data/jtr/dynamic_flat_sse_formats.conf @@ -92,7 +92,7 @@ Test=$dynamic_2005$e7222e806a8ce5efa6d48acb3aa56dc2$aaaaa:test3 TestD=$dynamic_2005$ba5528ac65c20213e105bb02e6aaf6a2$1234567890123456789012345678901234567890:12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 [List.Generic:dynamic_2006] -Expression=md5(md5($p).$s) (PW > 55 bytes) +Expression=md5(md5($p).$s) (vBulletin, PW > 55 bytes or/and salt > 23 bytes) Flag=MGF_SALTED Flag=MGF_KEYS_BASE16_IN1 Flag=MGF_FLAT_BUFFERS diff --git a/data/jtr/john.conf b/data/jtr/john.conf index 4ddbf8826909c..5dee1d9568f18 100755 --- a/data/jtr/john.conf +++ b/data/jtr/john.conf @@ -1,6 +1,6 @@ # # This file is part of John the Ripper password cracker, -# Copyright (c) 1996-2006,2008-2013 by Solar Designer +# Copyright (c) 1996-2006,2008-2013,2019 by Solar Designer # # Redistribution and use in source and binary forms, with or without # modification, are permitted. @@ -42,9 +42,11 @@ 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 wordlist mode rules when not in batch mode (if any). If this is +# changed from an 'empty list' to have default rules applied, and you later +# DO want to perform a run once without rules, use --rules:none on the +# command line. The default is 'empty' or NO rules run at all. +WordlistRules = # Default loopback mode rules (if any) # If this is set and you want to run once without rules, use --rules:none @@ -54,14 +56,11 @@ LoopbackRules = Loopback # 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 +# one option frequently changed (with above caveat) is setting DefaultIncrementalUTF8 = UTF8 DefaultIncremental = ASCII -#DefaultIncrementalUTF8 = UTF8 +DefaultIncrementalUTF8 = ASCII DefaultIncrementalLM = LM_ASCII # Time formatting string used in status ETA. @@ -85,19 +84,29 @@ TimeFormat24 = %H:%M:%S # strftime for more information: # http://en.cppreference.com/w/c/chrono/strftime # +# examples: # 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 +LogDateFormat = # if log date is being used, the time will default to local -# time. But if the next line is uncommented, it will output +# time. But if the next line is changed to 'Y', date output # in UTC. Note, if LogDateFormat is not set, this option -# does nothing. -#LogDateFormatUTC = Y +# is ignored. +LogDateFormatUTC = N # 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 +# +# example +# Feb 20 22:35:38 would be %b %d %H:%M:%S +LogDateStderrFormat = + +# If this is given, it will be printed in the end on any cracked password +# output. In case some 8-bit passwords upset your terminal, putting an +# ANSI "SGR Reset/Normal" here might be a cure. Any "^" characters will be +# parsed as ESC for use in ANSI codes (like in the default) +TerminalReset = ^[0m # This can be used to colorize (on screen) or otherwise emphasize (in log # files) output whenever a supposed administrator password gets cracked. @@ -108,9 +117,12 @@ 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 +# use in ANSI codes (like in the defaults). +# The "MarkOther" entries will make non-admin stuff brown. +MarkAdminStart = ^[0;31m MarkAdminEnd = ^[0m +MarkOtherStart = ^[0;33m +MarkOtherEnd = ^[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. @@ -118,16 +130,16 @@ MarkAdminString = (ADMIN ACCOUNT) # Permissions to set for session.log file # Default is 0600 -#LogFilePermissions = 0600 +LogFilePermissions = 0600 # Permissions to set for POT file # Default is 0600 -#PotFilePermissions = 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 +IgnoreChmodErrors = N # This figure is in MB. The default is to memory map wordlists not larger # than one terabyte. @@ -159,16 +171,25 @@ SingleSkipLogin = N # 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 +# Setting this to false stops Single mode from re-testing guessed plaintexts # with all other salts. -#SingleRetestGuessed = N +SingleRetestGuessed = Y + +# Max recursion depth for SingleRetestGuessed, so we don't blow the stack +SingleMaxRecursionDepth = 10000 # 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. +# 4 GB. Note that you may want to set SingleMaxBufferAvailMem (below) to +# true instead. +# +# If this figure is explicitly set to zero, and SingleMaxBufferAvailMem +# is false, there will be NO LIMIT! SingleMaxBufferSize = 4 +# If true, the actual amount of physical memory at runtime, if known, will +# override the figure from SingleMaxBufferSize (may increase or decrease!). +SingleMaxBufferAvailMem = N + # 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 @@ -183,7 +204,7 @@ SinglePrioResume = N # 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 +SessionFileProtect = Disabled # Protect the log files (*.log) from being reused by new sessons. # The default mode is "Disabled". That means, a nee session will just append @@ -196,7 +217,7 @@ SinglePrioResume = N # existing log file.) # Unless you use the --nolog option, setting LogFileProtect will also # prevent overwriting existing session files. -#LogFileProtect = Named +LogFileProtect = Disabled # 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 @@ -208,6 +229,12 @@ CrackStatus = N # will be exact while the screen output will be a multiple of batch size). StatusShowCandidates = N +# Show updated "Remaining" counts when we got rid of any salt(s). +ShowSaltProgress = N + +# Show updated "Remaining" counts on status output (if it changed). +ShowRemainOnStatus = N + # Write cracked passwords to the log file (default is just the user name) LogCrackedPasswords = N @@ -235,7 +262,7 @@ DefaultMSCodepage = CP850 # 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 +DefaultInternalCodepage = # Warn if seeing UTF-8 when expecting some other encoding, or vice versa. # This is disabled for ASCII or RAW encodings, for performance. @@ -304,6 +331,8 @@ PauseFile = /var/run/john/pause # With: password123 (Administrator:500) # Without password123 (Administrator) # This is disabled by --save-memory. +# NOTE: For WPAPSK, this will actually show gid instead, which is the MAC +# address of the access point. ShowUIDinCracks = N # This sets the "grace time" for --max-run-time=N. If john has not finished @@ -319,24 +348,6 @@ AbortGraceTime = 30 # 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) @@ -362,14 +373,6 @@ 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 @@ -380,78 +383,30 @@ TempStatus = Y UtilStatus = N FanStatus = N -# Abort session if GPU hits this temperature (in C) +# Abort the process or sleep for a while if a 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 +# Instead of aborting, sleep for this many seconds to cool the GPU down when +# the temperature hits the AbortTemperature value, then re-test the temperature +# and either wake up or go to sleep again. Set this to 0 to actually abort. +# Suppress repeated sleep/wakeup messages when SleepOnTemperature = 1, which we +# interpret as intent to keep the GPU temperature around the limit. +SleepOnTemperature = 1 [Options:OpenCL] -# Set default OpenCL device. Command line option will override this. +# Set default OpenCL device(s). 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 +# powerful device. Syntax is same as --device option. +Device = + +# *Always* show local/global work sizes (LWS/GWS). This is mostly for +# debugging, we try to show them when reasonable. +AlwaysShowWorksizes = N -# 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 +# If 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 = N # Global max. single kernel invocation duration, in ms. Setting this low # (eg. 10-100 ms) gives you a better responding desktop but lower performance. @@ -459,7 +414,7 @@ Frequency = 180 # 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 +Global_MaxDuration = # 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 @@ -467,7 +422,7 @@ Frequency = 180 # 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 +ForceScalar = N # Global build options. Format-specific build options below may be # concatenated to this. @@ -479,7 +434,6 @@ GlobalBuildOpts = -cl-mad-enable # Any other value (eg. 64) will be taken verbatim. AutotuneLWS = 1 - # Format-specific settings: # Uncomment the below for nvidia sm_30 and beyond. @@ -529,11 +483,115 @@ sha512crypt_Bonaire = -DUNROLL_LOOP=132104 # S -> supported # T -> not recommended: really bad software. I mean "trash". +# ZTEX specific settings +[List.ZTEX:Devices] +# If you list Serial Numbers (SN) of ZTEX boards here, it will display +# numbers (starting from 1) instead of factory programmed SN's. +# These numbers can be used in --dev command-line option. +#04A36E0000 +#04A36D0000 + +[ZTEX:descrypt] +# The design has programmable clock. Design tools reported possible +# frequency to be 221 MHz. Tested boards work reliably at 190. +Frequency = 190 + +[ZTEX:bcrypt] +# Define typical setting of hashes it's going to process. It allows +# to adjust for best performance. +TargetSetting = 5 +# Design tools reported possible frequency to be 141.5 MHz. +# Tested boards work reliably at 150, so that's what we use by default. +Frequency = 150 +# For any algorithm it's possible to set frequency on per-board and +# per-FPGA basis, but the lowest frequency will determine performance. +#Frequency_04A36E0FD6 = 142 +#Frequency_04A36E0FD6_1 = 143 +#Frequency_04A36E0FD6_4 = 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 241 MHz but tested boards +# miss guesses, often fail unless frequency is decreased. +# Tested boards work reliably at 175. +Frequency = 175 +#TargetRounds = 500000 + +# 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 + +# 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' + +[Formats:7z] +# With this enabled, the 7z formats check padding after AES decryption which +# more or less guarantees we don't get any false positives, and also makes +# the formats faster (in some cases a LOT faster). We've had one (1) report +# of getting a false negative having this enabled though, so if you fail to +# crack some archive you may want to disable this and re-try all attacks. +TrustPadding = Y + +# 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 + +[Debug] +# Changing this to Yes will enable legacy-style benchmarks, for comparisons +Benchmarks_1_8 = N +# Changing this to Yes will test salted formats as one/many salts, for debug +BenchmarkMany = N + [PRINCE] # Default wordlist file name. Will fall back to standard wordlist if not # defined. -#Wordlist = $JOHN/password.lst - +Wordlist = # Markov modes, see ../doc/MARKOV for more information [Markov:Default] @@ -606,7 +664,7 @@ 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 +DefaultCharset = # 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 @@ -676,69 +734,69 @@ MaxDiff = 7 -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 +-<6 >6 '6 +-<7 >7 '7 l +-<6 -c >6 '6 /?u l +-<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 +<* d +r c +-c <* (?a d c +-<5 -c >5 '5 /?u l +-c u Q +-c )?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 +-c <* c Q d +-<7 -c >7 '7 /?u +-<4 >4 '4 l +-c <+ (?l c r +-c <+ )?l l Tm +-<3 >3 '3 +-<4 -c >4 '4 /?u +-<3 -c >3 '3 /?u l +-c u Q r +<* d M 'l f Q +-c <* 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 \[ +>[2-8] x1\1 +>9 \[ # >3 x22 ... >9 x28 -->[4-9A] >\p[3-9] x2\p[2-8] +>[3-9] x2\p[2-8] # >4 x32 ... >9 x37 -->[5-9A] >\p[4-9] x3\p[2-7] +>[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 +-c >[2-8] x1\1 /?u l +-c >9 \[ /?u l # >3 x22 /?u l ... >9 x28 /?u l --c ->[4-9A] >\p[3-9] x2\p[2-8] /?u l +-c >[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 +-c >[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"!!!" +<* l $[1-9!0a-rt-z"-/:-@\[-`{-~] +-c <* (?a c $[1-9!0a-rt-z"-/:-@\[-`{-~] +-[:c] <* !?A (?\p1[za] \p1[lc] $s M 'l p Q X0z0 'l $s +-[:c] <* /?A (?\p1[za] \p1[lc] $s +<* l r $[1-9!] +-c <* /?a u $[1-9!] +-[:c] <- (?\p1[za] \p1[lc] Az"'s" +-[:c] <- (?\p1[za] \p1[lc] Az"!!" +-[:c] (?\p1[za] \p1[lc] $! <- Az"!!" # Removing vowels... --[:c] b1 /?v @?v >2 (?\p1[za] \p1[lc] -/?v @?v >2 al d +-[:c] /?v @?v >2 (?\p1[za] \p1[lc] +/?v @?v >2 <* d # crack -> cracked, crack -> cracking <* l [PI] -c <* l [PI] (?a c # mary -> marie --[:c] a1 (?\p1[za] \p1[lc] )y omi $e +-[:c] <* (?\p1[za] \p1[lc] )y omi $e # marie -> mary --[:c] b1 (?\p1[za] \p1[lc] )e \] )i val1 oay +-[:c] (?\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] @@ -838,9 +896,9 @@ l Q [RL] -[: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"20[012]" <+ >- l Az"19[7-9][0-9]" <+ -l Az"20[01][0-9]" <+ +l Az"20[012][0-9]" <+ l Az"19[6-0][9-0]" <+ [List.Rules:Extra] @@ -878,7 +936,7 @@ l Az"[1-90][0-9][0-9]" <+ # 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 +<7 >1 !?A l d # Lowercase and reverse pure alphabetic words >3 !?A l M r Q # Prefix pure alphabetic words with '1' @@ -894,13 +952,13 @@ l Az"[1-90][0-9][0-9]" <+ # 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 +-c <7 >1 !?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 +<7 >1 !?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' @@ -957,6 +1015,28 @@ W0Q ->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] +[List.Rules:Multiword] +-c / Dp l +-c / Dp c Tp +-c / Dp / Dp l +-c / Dp c Tp / Dp Tp +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %3[ ] vbpa Tb Q M %2[ ] vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %3[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %2[ ] vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %2[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c /[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q @?[Zw] +-c %2[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q @?[Zw] +-c %3[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q @?[Zw] +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q @?[Zw] +-c %2[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %3[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %2[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %3[ ] vbpa Tb Q @?[Zw] +-c %2[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %4[ ] vbpa Tb Q @?[Zw] +-c %3[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %4[ ] vbpa Tb Q @?[Zw] +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %3[ ] vbpa Tb Q M %2[ ] vbpa Tb Q @?[Zw] +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %2[ ] vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] +-c %4[ ] T[0z] \p0[Q:] \p0[M:] va01 vbpa Tb Q M %3[ ] vbpa Tb Q M /[ ] vbpa Tb Q @?[Zw] + # 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] @@ -1092,6 +1172,7 @@ b1 ] .include [List.Rules:Single-Extra] .include [List.Rules:Wordlist] .include [List.Rules:ShiftToggle] +.include [List.Rules:Multiword] .include [List.Rules:best64] # KoreLogic rules @@ -1674,613 +1755,547 @@ void init() type = ' '; } +# 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; -# 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() +void generate() { - int c; + int i; -/* 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; + i = 0; + while (i < length) + word[i++] = c; + word[i] = 0; -/* Password types to try (Numeric, Alpha-Num, Alpha-Num w/ Meta). */ - mintype = 0; // 0 - maxtype = 2; // 2 + if (c++ < maxc) + return; - crack_seed = 0x10000; - length = minlength - 1; - type = mintype; + c = minc; - count = 0; - c = '0'; while (c <= '9') charset[count++] = c++; + if (++length > maxlength) + c = 0; // Will NUL out the next "word" and thus terminate } -void generate() +# Try strings of repeated characters (range: space - 0xff). +[List.External:Repeats] +.include [List.External_base:Repeats] +void init() { - int seed, random; - int i, c; + 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; - if (crack_seed > 0xffff) { - crack_seed = 0; + length = minlength; c = minc; +} - if (++length > maxlength) { - length = minlength; +# 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'; - 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 + length = minlength; c = minc; +} +# Try strings of repeated lowercase letters (range: 'a' - 'z'). +[List.External:Repeats_lowercase] +.include [List.External_base:Repeats] 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]; - } + 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'; - word = 0; // We're done + length = minlength; c = minc; } -void restore() +# Try strings of repeated printable ASCII characters +# (range: ' ' - '~'). +[List.External:Repeats_printable_ASCII] +.include [List.External_base:Repeats] +void init() { - int i, c; + 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 = '~'; -/* 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]; + 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] /* - * 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 , - * 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. + * 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: */ -[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 */ +int minlength, from, to, maxlength, inc, direction; - /* 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++; -} +/* + * The value of these variables shouldn't be changed when copying + * an existing external mode: + */ +int length, first; void generate() { - int i, rand_seed, rand_result; + int i; - /* Terminate once we've generated for all * - * of the time range (Plus a bit more...) */ - if (endTime + 1000 < startTime) { - word = 0; - return; - } + i = 0; - /* Skip msecs that would generate dupes */ - while (endTime % msec != 0) { - if (++msec > 999) { - endTime--; - msec = 1; - } + while (i < length) { + word[i] = first + (i * inc * direction); + ++i; } + word[i] = 0; - 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; + // start the next sequence of the same length + // with the next character + first = first + direction; - rand_seed = rand_seed * 1103515245 + 12345; - rand_result <<= 10; - rand_result ^= (rand_seed >> 16) & 1023; + // 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; - rand_seed = rand_seed * 1103515245 + 12345; - rand_result <<= 10; - rand_result ^= (rand_seed >> 16) & 1023; + // 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; - word[i++] = charset[rand_result % charset_length]; - } - word[i] = 0; + 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; - if (++msec > 999) { - endTime--; - msec = 1; + 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; } } -void restore() +# 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() { - 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; - } - } + // Adjust the following 4 variables if you want to define + // a different external mode. - rand_seed = endTime / msec; + // 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'; - 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; + // 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; - rand_seed = rand_seed * 1103515245 + 12345; - rand_result <<= 10; - rand_result ^= (rand_seed >> 16) & 1023; + // 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; - rand_seed = rand_seed * 1103515245 + 12345; - rand_result <<= 10; - rand_result ^= (rand_seed >> 16) & 1023; + // For copied external modes, no further changes should be required + // in the statements following this comment - if (charset[rand_result % charset_length] != word[i++]) - break; - } + length = minlength; + first = from; - if (++msec > 999) { - endTime--; - msec = 1; - } + 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; } } -/* Awesome Password Generator RNG replay - * Written by Michael Samuel - * 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]; +# 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; -/* 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; + length = minlength; + first = from; -int password_length; + 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() { - 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++] = '?'; + from = 'z'; + to = 'a'; + minlength = 2; + inc = 1; - i = 0; - boundaries_charclass[i++] = 536870912; boundaries_charclass[i++] = 1073741824; - boundaries_charclass[i++] = 1610612736; boundaries_charclass[i++] = 2147483647; + length = minlength; + first = from; - 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; + if (from <= to) { + maxlength = to - from + 1; + direction = 1; + } else { + maxlength = from - to + 1; + direction = -1; + } +} - 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; +# 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; - 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; + length = minlength; + first = from; - seed = 0; + if (from <= to) { + maxlength = to - from + 1; + direction = 1; + } else { + maxlength = from - to + 1; + direction = -1; + } } -void generate() +# 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() { - int i, j, s, next, nextp, val, bucket, randnum, used_charsets; - int seedarray[56]; + from = '~'; + to = ' '; + minlength = 2; + inc = 1; - /* BEGIN System.Random(seed) */ - if(seed < 0) { - /* Only bother with non-negative integers */ - word = 0; - return; + length = minlength; + first = from; + + if (from <= to) { + maxlength = to - from + 1; + direction = 1; + } else { + maxlength = from - to + 1; + direction = -1; } +} - s = 161803398 - seed++; - seedarray[55] = s; - i = val = 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; - while(i < 55) { - bucket = 21 * i % 55; - seedarray[bucket] = val; - val = s - val; - if(val < 0) val += 2147483647; - s = seedarray[bucket]; - i++; - } + length = minlength; + first = from; - 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++; + if (from <= to) { + maxlength = to - from + 1; + direction = 1; + } else { + maxlength = from - to + 1; + direction = -1; } - 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++; +# 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 - word[i] = j; /* Temporarily store in word[] */ - used_charsets |= (1 << j); - i++; - } - } +void init() +{ + int i, c; - 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; + // Minimum password length to try, must be at least 1 + if (req_minlen) + minlength = req_minlen; + else + minlength = 1; - 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; -} + // 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; -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 */ + startdiff = 1; // Initial number of different characters to try + maxdiff = 3; // Maximum number of different characters to try - seed = 0; +/* This defines the character set */ + i = 0; + c = 0x20; + while (c <= 0x7e) + charset[i++] = c++; - while(seed > 0) { - /* BEGIN System.Random(seed) */ - s = 161803398 - seed++; - seedarray[55] = s; - i = val = 1; + if (maxdiff > (charcount = i)) + maxdiff = i; + if (maxdiff > maxlength) + maxdiff = maxlength; - while(i < 55) { - bucket = 21 * i % 55; - seedarray[bucket] = val; - val = s - val; - if(val < 0) val += 2147483647; - s = seedarray[bucket]; - i++; - } +/* + * 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; +} - 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) */ +void generate() +{ + int i; - 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() */ +/* Handle the typical case specially */ + if (word[last] = subset[++lastid]) return; - j = 0; - while(boundaries_charclass[j] < randnum) j++; + 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; + } - candidate[i] = j; - used_charsets |= (1 << j); - i++; + 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]; - 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 (subcount > maxdiff) { + word = 0; // Done + return; + } - 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; +/* + * 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; } # Try sequences of adjacent keys on a keyboard as candidate passwords @@ -2680,45 +2695,146 @@ void init() int length; int pos, ofs, i, c; - length = 8; // Must be one of: 4, 5, 7, 8 + 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]; +} + +# 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 < length - 6) { + while (pos < 6) { ofs = pos++ << 8; i = 0; - c = '0'; - while (c <= '9') - charset[ofs + i++] = c++; + c = 'a' - 1; + while (++c <= 'z') + if (C[c - 'a']) + 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) { + 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 = '0'; - while (c <= '9') - charset[ofs + i++] = c++; + c = 'a' - 1; + while (++c <= 'z') + if (A[c - 'a']) + charset[ofs + i++] = c; charset[ofs + i] = 0; } - ofs = pos++ << 8; - charset[ofs] = '/'; - charset[ofs + 1] = '.'; - charset[ofs + 2] = ':'; - charset[ofs + 3] = 0; + c = '1'; while (pos < length) { ofs = pos++ << 8; i = 0; - c = '0'; while (c <= '9') charset[ofs + i++] = c++; charset[ofs + i] = 0; + c = '0'; } last = length - 1; @@ -2760,547 +2876,560 @@ void restore() 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; +# 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 generate() +void init() { - int i; + int c; - i = 0; - while (i < length) - word[i++] = c; - word[i] = 0; +/* 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; - if (c++ < maxc) - return; +/* Password types to try (Numeric, Alpha-Num, Alpha-Num w/ Meta). */ + mintype = 0; // 0 + maxtype = 2; // 2 - c = minc; + crack_seed = 0x10000; + length = minlength - 1; + type = mintype; - if (++length > maxlength) - c = 0; // Will NUL out the next "word" and thus terminate + count = 0; + c = '0'; while (c <= '9') charset[count++] = c++; } -# Try strings of repeated characters (range: space - 0xff). -[List.External:Repeats] -.include [List.External_base:Repeats] -void init() +void generate() { - 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; + int seed, random; + int i, c; - length = minlength; c = minc; -} + if (crack_seed > 0xffff) { + crack_seed = 0; -# 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'; + if (++length > maxlength) { + length = minlength; - length = minlength; c = minc; -} + if (++type > maxtype) { + word[0] = 0; + return; + } + } -# 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'; + 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++; + } + } - length = minlength; c = minc; -} + seed = (crack_seed++ << 16 >> 16) * 22695477 + 1; -# 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 = '~'; + i = 0; + while (i < length) { + random = ((seed = seed * 22695477 + 1) >> 16) & 0x7fff; + word[i++] = charset[random % count]; + } - length = minlength; c = minc; + word[i] = 0; } -# 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: + * 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 , + * 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. */ -int minlength, from, to, maxlength, inc, direction; +[List.External:KDEPaste] +int charset[95]; +int charset_length, password_length, endTime, startTime, msec; -/* - * The value of these variables shouldn't be changed when copying - * an existing external mode: - */ -int length, first; +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; + int i, rand_seed, rand_result; - i = 0; + /* Terminate once we've generated for all * + * of the time range (Plus a bit more...) */ + if (endTime + 1000 < startTime) { + word = 0; + return; + } - while (i < length) { - word[i] = first + (i * inc * direction); - ++i; + /* Skip msecs that would generate dupes */ + while (endTime % msec != 0) { + if (++msec > 999) { + endTime--; + msec = 1; + } } - word[i] = 0; - // start the next sequence of the same length - // with the next character - first = first + direction; + rand_seed = endTime / msec; - // 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; + 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; - // 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; + rand_seed = rand_seed * 1103515245 + 12345; + rand_result <<= 10; + rand_result ^= (rand_seed >> 16) & 1023; - 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; + rand_seed = rand_seed * 1103515245 + 12345; + rand_result <<= 10; + rand_result ^= (rand_seed >> 16) & 1023; - 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; + word[i++] = charset[rand_result % charset_length]; + } + word[i] = 0; + + if (++msec > 999) { + endTime--; + msec = 1; } } -# 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() +void restore() { - // Adjust the following 4 variables if you want to define - // a different external mode. + int i, rand_seed, rand_result; - // 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'; + i = 0; - // 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; + /* Very crude restore, just dry-run until we hit last word */ + while (i != password_length) { - // 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; + while (endTime % msec != 0) { + if (++msec > 999) { + endTime--; + msec = 1; + } + } - // For copied external modes, no further changes should be required - // in the statements following this comment + rand_seed = endTime / msec; - length = minlength; - first = from; + 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; - 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; - } -} + rand_seed = rand_seed * 1103515245 + 12345; + rand_result <<= 10; + rand_result ^= (rand_seed >> 16) & 1023; -# 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; + rand_seed = rand_seed * 1103515245 + 12345; + rand_result <<= 10; + rand_result ^= (rand_seed >> 16) & 1023; - length = minlength; - first = from; + if (charset[rand_result % charset_length] != word[i++]) + break; + } - if (from <= to) { - maxlength = to - from + 1; - direction = 1; - } else { - maxlength = from - to + 1; - direction = -1; + if (++msec > 999) { + endTime--; + msec = 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] +/* Awesome Password Generator RNG replay + * Written by Michael Samuel + * 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() { - from = 'z'; - to = 'a'; - minlength = 2; - inc = 1; + password_length = 16; /* Change this to match config */ - length = minlength; - first = from; + int c, i; - if (from <= to) { - maxlength = to - from + 1; - direction = 1; - } else { - maxlength = from - to + 1; - direction = -1; - } -} + 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++; -# 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; + /* 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++] = '?'; - length = minlength; - first = from; + i = 0; + boundaries_charclass[i++] = 536870912; boundaries_charclass[i++] = 1073741824; + boundaries_charclass[i++] = 1610612736; boundaries_charclass[i++] = 2147483647; - if (from <= to) { - maxlength = to - from + 1; - direction = 1; - } else { - maxlength = from - to + 1; - direction = -1; - } -} + 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; -# 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; + 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; - length = minlength; - first = from; + 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; - if (from <= to) { - maxlength = to - from + 1; - direction = 1; - } else { - maxlength = from - to + 1; - direction = -1; - } + seed = 0; } -# 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() +void generate() { - from = ' '; - to = 0xff; - minlength = 2; - inc = 1; + int i, j, s, next, nextp, val, bucket, randnum, used_charsets; + int seedarray[56]; - length = minlength; - first = from; + /* BEGIN System.Random(seed) */ + if(seed < 0) { + /* Only bother with non-negative integers */ + word = 0; + return; + } - if (from <= to) { - maxlength = to - from + 1; - direction = 1; - } else { - maxlength = from - to + 1; - direction = -1; + 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) */ -# 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 + 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() */ -void init() -{ - int i, c; + j = 0; + while(boundaries_charclass[j] < randnum) j++; - // Minimum password length to try, must be at least 1 - if (req_minlen) - minlength = req_minlen; - else - minlength = 1; + word[i] = j; /* Temporarily store in word[] */ + used_charsets |= (1 << j); + i++; + } + } - // 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; + 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; +} - // "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 +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 */ -/* This defines the character set */ - i = 0; - c = 0x20; - while (c <= 0x7e) - charset[i++] = c++; + seed = 0; - if (maxdiff > (charcount = i)) - maxdiff = i; - if (maxdiff > maxlength) - maxdiff = maxlength; + while(seed > 0) { + /* BEGIN System.Random(seed) */ + s = 161803398 - seed++; + seedarray[55] = s; + i = val = 1; -/* - * 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; -} + while(i < 55) { + bucket = 21 * i % 55; + seedarray[bucket] = val; + val = s - val; + if(val < 0) val += 2147483647; + s = seedarray[bucket]; + i++; + } -void generate() -{ - int 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) */ -/* Handle the typical case specially */ - if (word[last] = subset[++lastid]) return; + 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() */ - 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; - } + j = 0; + while(boundaries_charclass[j] < randnum) j++; - if (++last < maxlength) { // Next length? - id[last] = lastid = 0; - word[last] = c0; - word[last + 1] = 0; - return; - } + candidate[i] = j; + used_charsets |= (1 << j); + i++; + } + } -/* Next subset */ - if (subcount) { - int j; - i = subcount - 1; - j = charcount; - while (++subid[i] >= j) { - if (i--) { - j--; - continue; + 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; } - subid[i = 0] = 0; - subset[++subcount] = 0; - break; } - } else { - subid[i = 0] = 0; - subset[++subcount] = 0; + if(i == password_length) return; } - subset[i] = charset[subid[i]]; - while (++i < subcount) - subset[i] = charset[subid[i] = subid[i - 1] + 1]; +} - if (subcount > maxdiff) { - word = 0; // Done - return; +# 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'; } +} -/* - * 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; +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; } - lastid = 0; - word[i] = 0; + if (o & 0x01000000) + return; // Not all-digit, leave unmodified + word[i--] = 0; + word[i] = map2[(o & 0xfff) + (e >> 12)]; } # Simple password policy matching: require at least one digit. @@ -3398,55 +3527,6 @@ void filter() 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 @@ -3892,7 +3972,8 @@ void next() .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' +# This is disabled by default since it's a security risk in case JtR is ever run with untrusted current directory +#.include './john-local.conf' # End of john.conf file. # Keep this comment, and blank line above it, to make sure a john-local.conf