Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Mon, 2 Jul 2012 19:14:15 +0200
From: Frank Dittrich <frank_dittrich@...mail.com>
To: john-dev@...ts.openwall.com
Subject: I think I got it (was: For some dynamic formats on linux-x86-mmx
 build cracking depends on password candidate sequence)

On 06/30/2012 09:03 AM, Frank Dittrich wrote:
> On 06/29/2012 11:52 PM, jfoug wrote:
>> But this does appear to be something along the lines of improper key cleaning. 
> 
> Please note that with --mkpc=127 the bug disappears as well.

$ ./john --list=build-info
Version: 1.7.9-jumbo-6+unstable
Build: linux-x86-clang
Arch: 32-bit LE
$JOHN is ./
Rec file version: REC3
CHARSET_MIN: 32 (0x20)
CHARSET_MAX: 126 (0x7e)
CHARSET_LENGTH: 8
Compiler version: 4.2.1 Compatible Clang Compiler
gcc version: 4.2.1
clang version: 2.9 (tags/RELEASE_29/final)


I think I know what happens, and IMO the sse2i format just passes the
test suite by accident.

In the pw.dic, we have passwords that are 110 characters long in certain
positions.

$ ./john --list=format-all-details |grep -B 15 -A 5 dynamic_2:

Format label                    	dynamic
Max. password length in bytes   	82
Min. keys per crypt             	1
Max. keys per crypt             	128
Flags
 Case sensitive                 	yes
 Supports 8-bit characters      	yes
 Converts 8859-1 to UTF-16/UCS-2	no
 Honours --encoding=NAME        	no
 False positives possible       	no
 Uses a bitslice implementation 	no
 The split() method unifies case	no
Number of test cases for --test 	24
Algorithm name                  	128/128 SSE2 intrinsics 8x4x4
Format name                     	dynamic_2: md5(md5($p)) (e107)
Benchmark comment               	
Benchmark length                	-1
Binary size                     	16
Salt size                       	0


This format defines a max. password length of 82, while it should limit
it to 59.

input_buf and input_buf2 are defined like this:

dynamic_fmt.c:432:__declspec(align(16)) unsigned char
input_buf[BLOCK_LOOPS][64*MMX_COEF];
dynamic_fmt.c:433:__declspec(align(16)) unsigned char
input_buf2[BLOCK_LOOPS][64*MMX_COEF];

input_buf will store the password, but it must store 0x80 immediately
after the password, and the password length in the last 4 bytes.

What happens in static void set_key(char *key, int index) is that john
cuts the 110 character password to length 82, but then in the while loop

	while((temp = *key32++) & 0xff) {

more than 64 bytes get written to the input_buf.

For passwords close to the end of a MAX_KEYS_PER_CRYPT buffer, this will
destroy input_buf2.

May be when the password length is reduced to the length that really
works, we can also get rid of this (line 1170):

                if(index==0) {
                        // we 'have' to use full clean here. NOTE 100%
sure why, but 10 formats fail if we do not.
                        DynamicFunc__clean_input_full();



I think we really need to construct the input dictionary more carefully,
and we need to make sure the test cases contain passwords that are close
to the max. password length that the format claims to support.

Frank

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.