Follow @Openwall on Twitter for new release announcements and other news

Defining an external mode.

To define an external cracking mode you need to create a configuration file section called [List.External:MODE], where MODE is any name that you assign to the mode. The section should contain some functions programmed in a C-like language. John will compile and use the functions if you enable this cracking mode via the command line.

External functions.

The following functions are currently used by John:

init()		called at startup, should initialize global variables
filter()	called for each word to be tried, can filter some words out
generate()	called to generate words, when no other cracking modes used
restore()	called when restoring an interrupted session

All of them are of type "void", with no arguments, and should use the global variable "word" (pre-defined as "int word[]"), except for init() which is called before "word" is initialized. The variable "word" contains the current candidate password to be tried, one character in each array element, terminated with a zero.

The functions, if defined, should do the following with "word":

* filter() can modify the word, or zero out "word[0]" to skip it;

* generate() should set "word" to the next word to be tried, or zero out "word[0]" when cracking is complete (this will cause John to terminate);

* restore() should set global variables to continue from the "word".

You can use an external mode on its own or with some other cracking mode, in which case only init() and filter() will be used (and only filter() will be required). Using an external filter is compatible with all the other cracking modes and with the "--make-charset" command line option.

It is recommended that you don't use filter() or at least don't filter too many words out when using an external mode with your own generate(). It is better to modify generate() not to generate words that would get filtered out.

Pre-defined variables.

Besides the "word" variable documented above, John the Ripper 1.7.9 and newer pre-defines two additional variables: "abort" and "status", both of type "int". When set to 1 by an external mode, these cause the current cracking session to be aborted or the status line to be displayed (just like on a keypress), respectively. These actions are taken after having tested at least all of the candidate passwords that were in external mode's "word" so far. In other words, the actions may be delayed in order to process any buffered candidate passwords.

The language.

The compiler supports a C-like language, which includes only a basic subset of C and differs from C in multiple ways. The supported keywords are: break, continue, else, if, int, return, void, while.

You can define functions to be called by John (the ones described above), define global and local variables (including one-dimensional arrays), use all the integer operations supported in C, and use C and C++ comments.

The following C features or traits are missing from John's compiler:

* short-circuit evaluation (instead, full expressions are currently evaluated, with any side effects they might have);

* function calls (any functions defined as part of an external mode can only be called by John core, but not by other external mode functions);

* "do" and "for" loops (there's only "while");

* data type declarations other than "int", one-dimensional arrays of "int", and "void";

* "static" local variables (as it happens, all local variables are currently static by default);

* pointers (array name alone refers to the first element);

* type casting (there's no use for it when we only have "int" anyway);

* comma operator;

* probably a lot more...

You can find some external mode examples in the default configuration file supplied with John.

Limited portability, and undefined behavior.

The "int" data type is currently implemented in John using the system's native C "int" data type. Thus, its size can vary, but on systems supported by John it can be assumed to be at least 32 bits (and usually is exactly 32 bits). Also, being a signed integer type, its behavior on overflow is undefined (but in practice will usually be two's complement wraparound).

Starting with version 1.8.0, literal character constants (given in single quotes, such as 'a') are treated as "unsigned char" cast to "int", thus producing values in the range 0 to 255. We intend to preserve this behavior in future versions. However, in pre-1.8.0 versions, literal character constants with the 8th bit set could appear as negative "int" values.

While the current implementation and all older versions of John so far consistently lack short-circuit evaluation, treat local variables as "static", and treat array name alone as referring to the first element, these properties might change in the future.

Limited robustness, and insecurity.

While the current implementation is meant to be reasonably robust for use, it lacks array bounds checking. It is external mode authors' and users' responsibility to ensure array sizes and indices are correct.

There's currently no compile-time checking that expressions being assigned to or modified are valid lvalues. Attempting to assign to or modify an expression that isn't a valid lvalue results in John crashing.

In general, external mode programs (and John configuration files in general) are treated as trusted input, much like you would treat a C file in John source tree. A malicious external mode can use out of bounds array accesses to trigger arbitrary machine code execution.

$Owl: Owl/packages/john/john/doc/EXTERNAL,v 1.5 2016/05/31 09:12:22 solar Exp $