Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance dynamic so it can 'compile' a self-contained thin format from an expression #1463

Closed
7 tasks done
jfoug opened this issue Jun 22, 2015 · 141 comments
Closed
7 tasks done

Comments

@jfoug
Copy link
Collaborator

jfoug commented Jun 22, 2015

RFC:

This one is somewhat of a pie in the sky wish. A command like this

../run/john -format="dynamic=md5($s.sha1($p.$s).$s)" input.txt

Now, input.txt could either by 'raw' hashes (32 byte hex, appended with $salt), OR it could be in the format that would be written to the .pot file. This format will NOT contain a $dynamic_##$ signature. The signature must be something that triggers the code compiler. I think the format label can be any length (it is a char*), so I think we could use this as the .pot line:

@dynamic=md5($s.sha1($p.$s).$s)@hash$salt:password   (there may be a better hash layout).

If this is done, then I expect to use an expression language very similar to what is being used within pass_gen.pl

ISSUES:

  • Building the test[] vectors
  • The actual compile code
  • how to handle valid()
  • how to handle split()
  • make sure that a large raw file, will remove found candidates even if found by a different expression. If they are found, they are found!
  • Handling more than 1 script type (-show stuff). For run-time, we will search for only 1 script type
  • make work with regen-salts logic
@magnumripper
Copy link
Member

That would be really awesome, but it might be a QC nightmare. We could add all sorts of stuff to TS but the user may find untested variants that ends up with latent bugs.

Having said that, we should support username salts ($u, shouldn't pose a problem) and perhaps constant strings (that may or may not need hex notation) for salt/pepper/whatnot.

If nothing else, it will be a cool experiment.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 22, 2015

Doing some stuff by hand (using the lexer/parser output from pass_gen.pl). Here is a by hand run-thru (just thinking outloud, and writing it down so I do not forget).

$ ../run/pass_gen.pl 'dynamic=num=6001,debug=1,format=md5($p.$p.md5($p.$p.$p.$p.md5($p.$p.md5($p).md5($p).md5($p.$p))))'

dynamic_push
dynamic_app_p
dynamic_app_p
dynamic_push
dynamic_app_p
dynamic_app_p
dynamic_app_p
dynamic_app_p
dynamic_push
dynamic_app_p
dynamic_app_p
dynamic_push
dynamic_app_p
dynamic_f5h
dynamic_push
dynamic_app_p
dynamic_f5h
dynamic_push
dynamic_app_p
dynamic_app_p
dynamic_f5h
dynamic_f5h
dynamic_f5h
dynamic_f5h

var1 = f1($p.$p.$var2)
var2 = f2($p.$p.$p.$p.$var3)
var3 = f3($p.$p.$var4)
var4 = md5($p).$var5
var5 = md5($p).$var6
var6 = md5($p.$p)
f3 = md5
f2 = md5
f1 = md5

compute backwards
var1 = md5($p.$p.$var2)
var2 = md5($p.$p.$p.$p.$var3)
var3 = md5($p.$p.$var4)
var4 = md5($p).$var5
var5 = md5($p).$var6
var6 = md5($p.$p)

find common sub_expressions  (optimization)
var1 = md5($p.$p.$var2)
var2 = md5($p.$p.$p.$p.$var3)
var3 = md5($p.$p.$var4)
var4 = $tmp1.$var5
var5 = $tmp1.$var6
tmp1 = md5($p)
var6 = md5($p.$p)

Build script (reverse order)

#var6
clean_1
append_keys
append_keys
md5_crypt
#tmp1
clean_2
append_keys2
md5_crypt2
#var3
clean1
append_keys
append_keys
   #var4
append_output2
   #var5
append_output2
   #var6
append_output1
md5_crypt
#var2
clean2
append_keys2
append_keys2
append_keys2
append_keys2
append_output1
md5_crypt2
#var1  (result)
clean1
append_keys2
append_keys2
append_output2
md5_crypt

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 22, 2015

I would think the ONLY things supported will end up being the flat_buffer functions. The flat buffer methods ARE more limiting, since there is only the ability to crypt from an input outputting to an input (appending or overwriting). So things like that common sub-expression may not be able to be done. The reason I did it the way I did, was I have 2 input and 2 output buffers. I built the flat buffer code the way I did, because it greatly reduces the complexity of the code. I 'could' change that, to work more like the interleaved code, but I would really have to think that one through.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 22, 2015

I only plan on support of these things:

all usable hash types
uc, lc, unicode
$p
$s
$c1..$c9
$u

I do not plan on support of $f1..$f9 $s2

Flags would not be 'settable', but I think I can find several optimizations (such as all salts being hash($s), then I can use the MGF_SALT_AS_HEX, and there are other optimizations that can be auto-found, such as the common expressions here.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 24, 2015

Ok, I have this done:

  1. created a new format for these 'compiled' data. There has to be 'some' default stuff in it (a default script, a default Test= item, etc).
  2. got most/all of the 'linkage' stuff working.

I did get things running (not compiling a script 'yet'

../run/john -test=0 -format=dynamic
...
Testing: dynamic_2011 [md5($s.md5($p.$s)) (PW > 32 or salt > 23 bytes, sse2) 32/32 (MD5_body)]... PASS
Testing: dynamic_2014 [md5($s.md5($p).$s) (PW > 55 or salt > 11 bytes, sse2) 32/32 (MD5_body)]... PASS
Testing: @dynamic= [md5($p) 32/32 (MD5_body)]... PASS
Testing: PHPS2 [md5(md5($p).$s) 32/32 (MD5_body)]... PASS
Testing: FormSpring [sha256($s.$p) 32/32sha2-OpenSSL]... PASS
Testing: md5ns, Netscreen [md5($s.$p) (OSC) (PW > 31 bytes, sse2) 32/32 (MD5_body)]... PASS
Testing: osc, osCommerce [md5($s.$p) (OSC) 32/32 (MD5_body)]... PASS

The 'new' format is the @dynamic= line. At least it works. I also have most of the 'linkage' functions done that manage everything EXCEPT the compile of the script. The compile should be easy. I will simply add constant code that can handle a couple of 'static' hashes. I think I will allow md5($s.$p), sha1($p), sha512($p) at first (and then simply strcmp to return the proper script). Yes, it is not a compiler, 'but' it will allow me to make sure that everything else is working. Once I get to that point, I simply have to get the parser/emitter done (big task). But this may be more than just a pipe dream now.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 24, 2015

Getting close. Current the compile only 'handles' these 4 exact signatures. Now, I just have to get the real parser working (for real)

$ ../run/john -test=5 -form='@dynamic=sha1($p)@'
Benchmarking: @dynamic= [sha1($p) 128/128 AVX 4x1]... DONE
Raw:    12890K c/s real, 12878K c/s virtual

$ ../run/john -test=5 -form='@dynamic=sha1($p.$p)@'
Benchmarking: @dynamic= [sha1($p.$p) 128/128 AVX 4x1]... DONE
Raw:    9992K c/s real, 9996K c/s virtual

$ ../run/john -test=5 -form='@dynamic=md5($p)@'
Benchmarking: @dynamic= [md5($p) 128/128 AVX 4x3]... DONE
Raw:    18270K c/s real, 18237K c/s virtual

$ ../run/john -test=5 -form='@dynamic=sha1(md5($p))@'
Benchmarking: @dynamic= [sha1(md5($p)) 128/128 AVX 4x1]... DONE
Raw:    8059K c/s real, 8056K c/s virtual

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 24, 2015

Here is a fun one :)

The 'script' which the expression compiler will have to produced (I did it by hand now)

Expression=gost($p.$s.$c1.gost($p.$c2))
Flag=MGF_FLAT_BUFFERS
Flag=MGF_INPUT_32_BYTE
Flag=MGF_SALTED
Const1=boobies
Const2=bootie
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__clean_input2_kwik
Func=DynamicFunc__append_keys2
Func=DynamicFunc__append_input2_from_CONST2
Func=DynamicFunc__append_keys
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_input1_from_CONST1
Func=DynamicFunc__GOST_crypt_input2_append_input1
Func=DynamicFunc__GOST_crypt_input1_to_output1_FINAL
Test=@dynamic=gost($p.$s.$c1.gost($p.$c2)),c1=boobies,c2=bootie@f79261b1dbf7181e6076a0a70344ec29df28dd4d6dc2d4311446bce6a2bae332$OtJbYYOO:abc

Generation of some data (using pass_gen.pl)

$ ../run/pass_gen.pl 'dynamic=num=6000,format=gost($p.$s.$c1.gost($p.$c2)),const1=boobies,const2=bootie' < ../run/password.lst | sed 's/\$dynamic_6000\$//' > inp
Got 1500, not processing more. Use -count to bump limit.

And running

$ ../run/john -form='@dynamic=gost($p.$s.$c1.gost($p.$c2)),c1=boobies,c2=bootie@' inp
Using default input encoding: UTF-8
Loaded 1500 password hashes with 1500 different salts (@dynamic= [gost($p.$s.$c1.gost($p.$c2)) 64/64])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Press 'q' or Ctrl-C to abort, almost any other key for status
basketball       (u154)
christ1          (u1309)
power            (u1015)
tamara           (u429)
shalom           (u137)
1212             (u723)
christmas        (u1310)
poppy            (u1014)
taurus           (u430)
silver           (u138)
1111             (u722)
Family           (u725)
q1w2e3           (u1018)
china            (u1307)
teresa           (u431)
...
colette          (u1321)
wolves           (u445)
ashley           (u153)
ricardo          (u1031)
andre1           (u739)
college          (u1322)
rhonda           (u1030)
alpine           (u738)
xyz123           (u446)
scooter          (u136)
asdfjkl;         (u152)
                 (u21)
1500g 0:00:00:00 DONE 2/3 (2015-06-24 16:35) 12096g/s 95475p/s 144346c/s 144346C/s 123456..phillips
Use the "--show" option to display all of the cracked passwords reliably
Session completed

$ ../run/john -form='@dynamic=gost($p.$s.$c1.gost($p.$c2)),c1=boobies,c2=bootie@' inp
Using default input encoding: UTF-8
Loaded 1500 password hashes with 1500 different salts (@dynamic= [gost($p.$s.$c1.gost($p.$c2)) 64/64])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
No password hashes left to crack (see FAQ)

And the .pot file

$ tail ../run/john.pot
139a557b4a6a680bebe65fdbf84f75c65b6c2e9293166c9d195cd202ab6a5533$woPhuO2i:ashley
cd29fdb309b2d46dab5325512c56deb23968c6295310e99a6c7e88a1c05413be$8vmSg3bl:ricardo
0153b3ee3b3ca53f2fc14e83e6344a826c727a58a781db96d47779ac700e465f$AcaJNNJF:andre1
1ac65e3a33578492e8d85110c84b679f5848d0245187b2f77f01263c4f19a0f5$1KVDMeul:college
1431773f2b001845f0bbcb20702b71c7b8710c51594648d15d8fe8ad1e822f6d$e9SifzPr:rhonda
590675e2f672a259ddc85189b87a3cd30b4f429535fa485f0d4cabf77dc35142$LTNFYXDF:alpine
5e0bc2f2d0e038a79cdb554af2653c9d8400204f5501e4ed7e6bd7cb6dc9fa0c$3YBHtP8Z:xyz123
ce572416e0e2812a377ed5febedb8dd4fe7fdab01727fc722fc22b7068f9e022$DeMxLEDn:scooter
93aa2dee7b083b40b551e7359555bcc8d250041f1e1e2fe176f0297be9ac5719$FDSFlyVc:asdfjkl;
41e960d66834153dd2e5a6d0ba94e4140c331af9a837f5997ef8a4f3ac27d369$Lv7NJPH3:

And a -show command

$ ../run/john -form='@dynamic=gost($p.$s.$c1.gost($p.$c2)),c1=boobies,c2=bootie@' -show inp
u0:123456:0:0:123456:
u1:12345:1:0:12345:
u2:password:2:0:password:
u3:password1:3:0:password1:
u4:123456789:4:0:123456789:
u5:12345678:5:0:12345678:
...
u1493:israel:1493:0:israel:
u1494:italia:1494:0:italia:
u1495:italy:1495:0:italy:
u1496:jackie1:1496:0:jackie1:
u1497:jacob:1497:0:jacob:
u1498:jakey:1498:0:jakey:
u1499:james1:1499:0:james1:

1500 password hashes cracked, 0 left

@frank-dittrich
Copy link
Collaborator

Does it matter what exactly you specify as --format on the command line?
Without storing the @dynamic=gost($p.$s.$c1.gost($p.$c2)),c1=boobies,c2=bootie@ part in the pot file, you'll hardly be able to reproduce the cracking of these hashes, because after the ./john session completed, you'll most likely not remember what --format you used.
So may be your newest enhancement still has some usability issues.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 24, 2015

There are 2 lines in the split function which are commented out. Remove those comments and the format will behave like you request.

Yes this is still very early. I am not ready to announce it's behavior to the user base.

@jfoug jfoug added this to the 1.8.0-jumbo2 milestone Jun 25, 2015
@jfoug
Copy link
Collaborator Author

jfoug commented Jun 25, 2015

Ok, one benefit of current logic, is that if the prefixes do not get added, then hashes are removed as found upon a re-run, no matter what expression was used.

So a list of raw hashes is obtained, and someone runs a md5(md5(md5($p))) and finds a bunch, if later a run of md5(sha1($p)) is run, all of the items found on the first run will not be looked at again. Now on a raw run, it does not matter all that much. But if these were salted, it really matters (or if doing re-gen-salts )

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 25, 2015

Ok, here is an example. I created a file called inp with 20 hashes each, made with sha1($p), sha1($p.$p) and sha1(md5($p)) (each of those are currently 'accepted' by our fake compiler).

I changed the format to output the expressions to the front part of the hash. Here is the results:

$ ../run/john -form='@dynamic=sha1($p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p) 128/128 AVX 4x1])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
123123           (u19)
a1b2c3a1b2c3     (u18)
internetinternet (u17)
summersummer     (u16)
secretsecret     (u15)
mickeymickey     (u14)
carmencarmen     (u13)
moneymoney       (u12)
qwertyqwerty     (u11)
12341234         (u10)
tiggertigger     (u9)
computercomputer (u8)
abc123abc123     (u7)
12345678901234567890 (u6)
1234567812345678 (u5)
123456789123456789 (u4)
password1password1 (u3)
passwordpassword (u2)
1234512345       (u1)
123456123456     (u0)
40g 0:00:00:08  3/3 4.910g/s 116821p/s 116821c/s 2337KC/s betewel..123qty
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

$ ../run/john -form='@dynamic=sha1($p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p) 128/128 AVX 4x1])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Remaining 20 password hashes with no different salts
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:04  3/3 0g/s 74567p/s 74567c/s 1491KC/s jh1188..setal
Session aborted

$ ../run/john -form='@dynamic=sha1($p.$p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p.$p) 128/128 AVX 4x1])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
20g 0:00:00:09  3/3 2.038g/s 185861p/s 185861c/s 7434KC/s lhiplp..lmjm
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

$ ../run/john -form='@dynamic=sha1($p.$p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p.$p) 128/128 AVX 4x1])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Remaining 40 password hashes with no different salts
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:02  3/3 0g/s 163959p/s 163959c/s 6558KC/s 123456
Session aborted

$ ../run/john -form='@dynamic=sha1(md5($p))@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1(md5($p)) 128/128 AVX 4x1])
Warning: invalid UTF-8 seen reading $JOHN/john.pot
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
20g 0:00:00:03  3/3 5.580g/s 98554p/s 98554c/s 3942KC/s anigme..benno
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

So as is shown, the already found hashes are not removed, and are re-tested. Note, the first run that found 40 instead of 20, was due to rules (double a password rule).

I changed the format back to not appending the @dynamic=... wort onto the hashes, reran the input file, and here is what was seen.

$ ../run/john -form='@dynamic=sha1(md5($p))@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1(md5($p)) 128/128 AVX 4x1])
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
20g 0:00:00:02  3/3 9.438g/s 154798p/s 154798c/s 6192KC/s 123456
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

$ ../run/john -form='@dynamic=sha1($p.$p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p.$p) 128/128 AVX 4x1])
Remaining 40 password hashes with no different salts
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
20g 0:00:00:01  3/3 10.77g/s 130626p/s 130626c/s 2613KC/s 123456
Use the "--show" option to display all of the cracked passwords reliably
Session aborted

$ ../run/john -form='@dynamic=sha1($p)@' inp
Using default input encoding: UTF-8
Loaded 60 password hashes with no different salts (@dynamic= [sha1($p) 128/128 AVX 4x1])
Remaining 20 password hashes with no different salts
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (u19)
a1b2c3           (u18)
internet         (u17)
summer           (u16)
secret           (u15)
mickey           (u14)
carmen           (u13)
money            (u12)
qwerty           (u11)
1234             (u10)
tigger           (u9)
computer         (u8)
abc123           (u7)
1234567890       (u6)
12345678         (u5)
123456789        (u4)
password1        (u3)
password         (u2)
12345            (u1)
123456           (u0)
20g 0:00:00:00 DONE 1/3 (2015-06-25 11:43) 5000g/s 26000p/s 26000c/s 276000C/s u0..u0u0
Use the "--show" option to display all of the cracked passwords reliably
Session completed

It can be seen here that the hashes are being properly removed from subsequent runs, without regard to what type expression found it before.

Now, I ALSO like adding the expression to the found hash, SO THAT you really know just wtf type algorithm created and can crack this hash. BUT if we do that, then I will have to find some way to make sure that proper reducing behavior is seen.

@magnumripper
Copy link
Member

It can be seen here that the hashes are being properly removed from subsequent runs, without regard to what type expression found it before.

This is definitely a problem, because it means --show will use them too. Let's say you cracked the password "magnum" with sha1($p.$p). It will be stored in john.pot like

b5280eb7275bc490104202d9e33e1c3d29e6e90b:magnum

Then you use sha1($p) and --show. It will say the password is "magnum" although it's really "magnummagnum" [for that algo].

Similar problems may exist for H(s.p) versus H(p.s) formats.

For any raw hash (of non-UTF16 data), we can live without tags in john.pot but anything else needs tags!

@magnumripper
Copy link
Member

But another aspect of what you said is true: If we have a million unknown 128-bit hashes (of mixed origin), we store them untagged and try eg. some MD4 algos on them. Many are cracked. Then we try some MD5 algos. Now we'd not want the already cracked MD4 ones to be included. Fixing the problem I describe means it will be hard to accomplish this.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 25, 2015

Yes, this is NOT an easy fix, I think. It all depends on where the hash is coming from, and how it is expected to be used. You are 100% right on the -show. They need the tags. But if tags are there, then we need to know if we are 'running', and if so when re-reading the .pot file, we need to strip tags to 'check', and also strip them from input (just for the check), BUT likely we only have this type behavior IF we are cracking. hmmmm.

@magnumripper
Copy link
Member

This is not new with @dynamic@ though. Here's another way to look at it.

$ cat john.pot
$dynamic_0$488911ea30ce711dca20bf7413fc49cc:johnripper
$dynamic_1$488911ea30ce711dca20bf7413fc49cc$ripper:john
$dynamic_1$488911ea30ce711dca20bf7413fc49cc$ipper:johnr
$dynamic_4$488911ea30ce711dca20bf7413fc49cc$john:ripper
$dynamic_4$488911ea30ce711dca20bf7413fc49cc$jo:hnripper

With clever handling (and perhaps a revision of john.pot format) any of the formats would be able to use any one of the lines to produce a correct --show figure from an input hash.

For example, you load the hash $dynamic_1$488911ea30ce711dca20bf7413fc49cc$ripper. The format finds the line $dynamic_4$488911ea30ce711dca20bf7413fc49cc$john:ripper in john.pot and draws the conclusion the proper plaintext for dynamic_1 is "john".

@magnumripper
Copy link
Member

Yet another way to look at it, is that all prepend/append-salt raw formats like h($s.$p) and h($p.$s) should ideally store results in john.pot in raw, unsalted format, and reverse that when loading pot entries.

Maybe this should be an "issue" on its own, for possible enhancements.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 25, 2015

I am 'working' on a kludge. If I get that working, then we can use the logic to figure out what to do the right way.

You are right, this might be something that we can do in a generic way, and get this behavior for other formats (specifically other dynas). This would be 'almost' as good as alias.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 25, 2015

Ok, here it the kludge (for cracking).

First, comment out the #if HAVE_CRYPT stuff around the ldr_in_pot in loader.c. My build does not have CRYPT (VC), BUT I need that flag set. I know no reason to ONLY set that flag if the build has crypt lib??

Then, I changed the split in the thin format to this:

static char *our_split(char *ciphertext, int index, struct fmt_main *self)
{
    extern int ldr_in_pot;
    if (strncmp(ciphertext, "@dynamic=", 9) && strncmp(ciphertext, dyna_signature, dyna_sig_len)) {
        // convert back into @dynamic@ format
        static char Buf[512];
        sprintf(Buf, "%s%s", dyna_signature, ciphertext);
        ciphertext = Buf;
    }
    if (ldr_in_pot == 1 && !strncmp(ciphertext, "@dynamic=", 9)) {
        static char Buf[512], Buf2[512];
        char *cp = strchr(&ciphertext[1], '@');
        if (cp) {
            strcpy(Buf, &cp[1]);
            sprintf(Buf2, "%s%s", dyna_signature, Buf);
            ciphertext = Buf2;
        }
    }
    return ciphertext;
}

What this does is if loading from .pot file, if it sees any @dynamic= hashes, it strips those off, and in their place, it inserts the proper signature.

NOTE, for show, this would NOT be the right way. This would be as bad as having the raw hashes in the DB. Again, that gets back to my point of we not only need to know where the data is coming from, BUT how it is being used.

@magnumripper
Copy link
Member

I'll open a new issue for the generic brain-storming

#1469

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 28, 2015

I have the get_token, lexer (with FULL expression validation, and points out exact spot of any errors), and pcode compiler parts done. Now all I need to do is to get this optimized, and the pcode converted into dynamic script (an emitter module).

I think I am also going to extend the dynamic language. I think I am going to add a few temp variables. One thing I can see, is to pre-process into temp vars. So if I have a hash like md5(md5($p).$s.$p.md5($p)) that I can put md5($p) into a temp var. This would end up being a flag to dyna, so that when new keys were added, the temp var would get filled in. I can see other usages for these vars.

@jfoug
Copy link
Collaborator Author

jfoug commented Jun 28, 2015

I now have a partly working script generator. But I now have to be able to properly build Test= string(s). I will probably have to use dynamic crypt_all in some way to do this. But I am sort of in that proverbial chicken and egg conundrum.

However, things are getting closer. I would LOVE to be able to drop the arbitrary numbering system of dynamic, which results in needing 'alias' logic to tell that dyna_0 and dyna_2000 are the same. It would be so much better to simply use dynamic=md5($p) and lose the implementation detail driven ambiguity

@magnumripper
Copy link
Member

I guess you should always use OpenSSL for building test vectors.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 22, 2015

I forced NoFlat and ran the dyna-compiler-test.sh and here is what I got for first group

FAILURE!!! 1 -> md5($p.$s)   (works with ,saltlen=32)
FAILURE!!! 4 -> md5($s.$p)  (works with ,saltlen=-24)
FAILURE!!! 5 -> md5($s.$p.$s)   (works with ,saltlen=-12)
FAILURE!!! 8 -> md5(md5($s).$p)  (need to use 32 bytes for the salt, since it is a hash).
FAILURE!!! 10 -> md5($s.md5($s.$p))
FAILURE!!! 11 -> md5($s.md5($p.$s))
FAILURE!!! 16 -> md5(md5(md5($p).$s).$s2)
FAILURE!!! 22 -> md5(sha1($p))
FAILURE!!! 23 -> sha1(md5($p))
FAILURE!!! 29 -> md5(utf16($p))
FAILURE!!! 39 -> md5($s.pad16($p)),saltlen=-231

I would be most of the failures are due to improper MaxLength setting.

Dyna1 works, except that I reduced salt from -32 to -16, and all salt in the test data were 32, so the new format loaded no test hashes. So if i set ,saltlen=32 then that format works fine.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 22, 2015

After a little more work, I am here:

FAILURE!!! 10 -> md5($s.md5($s.$p))
FAILURE!!! 11 -> md5($s.md5($p.$s))
FAILURE!!! 16 -> md5(md5(md5($p).$s).$s2)
FAILURE!!! 22 -> md5(sha1($p))
FAILURE!!! 23 -> sha1(md5($p))
FAILURE!!! 39 -> md5($s.pad16($p)),saltlen=-231

Getting closer, but I think I am going to turn in for the nite, and work on this later.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 22, 2015

Ok, I think I am getting closer. I am able to handle this type format now:

../run/john -test=0 -form=dynamic='sha1($s.sha1($s.sha1($s.$p)).$s)'

Before I was failing with this one

../run/john -test=0 -form=dynamic='sha1($s.sha1($s.sha1($p)))' which is dynamic_38.

Now, I can not do this one (not 'sure' that I can do it with flat dynamic at all).

./run/john -test=0 -form=dynamic='sha1($s.sha1($s.sha1($s.$p)).$s,sha1($p.$s))' I believe that this hash would require 3 input buffers for the flat dyna to do. It could have been done by having 4 'data' fields (prior to going to the flat interface). We had 2 input and 2 output buffers, and we 'could' have done this one by using an output buffer as a temp variable. Here is the 'script' that is being generated, and I will highlight where the problem is:

Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_keys
Func=DynamicFunc__SHA1_crypt_input1_overwrite_input2
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_input_from_input2
Func=DynamicFunc__SHA1_crypt_input1_overwrite_input2
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_keys
Func=DynamicFunc__append_salt
# first bug.  We have just lost what was in input2, the hash of sha1($s.sha1($s.$p))
Func=DynamicFunc__SHA1_crypt_input1_overwrite_input2
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_salt
# second bug.  the code generator thinks that input 2 stores sha1($s.sha1($s.$p)) and sha1($p.$s), so it tries to append both.  In actuality, input2 contains sha1($p.$s), and this gets appended twice.
Func=DynamicFunc__append_input_from_input2
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_input_from_input2
Func=DynamicFunc__SHA1_crypt_input1_to_output1_FINAL

However, with a bit of creativity (much more than I think I would EVER be able to put into the compiling engine), I 'think' I can do this format by hand. I will try and see.

Ok, I was able to actually do this format in flat dyna.

Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_keys
Func=DynamicFunc__clean_input2_kwik
Func=DynamicFunc__append_salt2
Func=DynamicFunc__SHA1_crypt_input1_append_input2
Func=DynamicFunc__SHA1_crypt_input2_overwrite_input2
Func=DynamicFunc__append_salt2
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_keys
Func=DynamicFunc__append_salt
Func=DynamicFunc__SHA1_crypt_input1_append_input2
Func=DynamicFunc__clean_input_kwik
Func=DynamicFunc__append_salt
Func=DynamicFunc__append_input_from_input2
Func=DynamicFunc__SHA1_crypt_input1_to_output1_FINAL

$ ../run/john -test -form=dynamic_2222
Benchmarking: dynamic_2222 [dynamic=sha1($s.sha1($s.sha1($s.$p)).$s.sha1($p.$s)) 128/128 AVX 4x1]... DONE
Many salts:     2483K c/s real, 2475K c/s virtual
Only one salt:  2365K c/s real, 2371K c/s virtual

But again, I just do not see the code generator being made smart enough to 'find' these type methods.

@magnumripper
Copy link
Member

I may not fully grasp this, but how about doing the very first step in mixed mode, and the rest in flat? Is it already possible? Doable? No-go zone?

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

That usually does not help much. The conversion loses gain, and then you are in flat mode. Now, by hand, I have gone the other way (for expressions with several to many crypts). Then if the password is only in one small part of the expression, I have done that flat, so that I am not limited by 1 limb, and then switched over to mixed. This is pretty much what we have done with the PBKDF2 code. 1 oSSL hashes and from then on, single limb hashes (the 2nd limb of a 2 limb crypt), can easily be done in mixed format.

I will move to get mixed SIMD working as well as possible for md[45], but there will likely be some area where it will simply return a self-test failure for some expressions, and then you will simply have to live with flat expressions. Even flat expressions will have a point where they do not generate working code. If I add the 'variable' fields, that point could be greatly extended, but there will STILL be a limit.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

I am going to first expand the large-hash interface. Currently it only allows this:

  1. setting output type (hex, HEX, raw, base64 of 2 types).
  2. calling crypt on an input, and that either appends or overwrites (in the output format) to another input.
    2a. there are only 2 append functions. input 1 appends to input2, and input 2 appends to input1.
    2b. there are 4 overwrite functions 1 to 1, 1 to 2, 2 to 2 and 2 to 1
  3. there are 2 functions that are 'finals'. These only crypt to output1 (which is crypt_out), and only copy over the first 16 bytes, truncating larger hashes. This IS the final crypt.

This was done because it WAS all hand coded and maintained crap before. But now, with the code being auto-generated, I think I will add more functions. Maintenance is nothing. I simply have to get the function 'macro's done properly once, and then they are ALL done. Once I do this, it will double the available variables. This is as good as it gets on the mixed simd code.

To do this, I only need to add 4 functions.
crypt_input1_to_output1
crypt_input1_to_output2
crypt_input2_to_output1
crypt_input2_to_output2

Now, I do have those already (for md[45] and some for sha1) in the mixed mode. The code would be pretty much the same, but it would not have mixed mode stuff. Only flat (multi-buffer), and oSSL.

I think I can get this EASILY done, and see how far it takes me. And this should add almost no complexity to the 'code' of dynamic. It will add a LOT of boiler plate functions, but they will all 'work' right out of the box.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

Hmm, I thought I was going to be able to use all the existing manipulation functions of the mixed SIMD code. I do not think so. The only code there, that uses the 'output' data works only for md[45], 16 byte. That is why the sha1 is only very limited hooked into the mixed SIMD code. I still think I can do this easily, but it will not be as simple as I had hoped for (leveraging existing code). Well it may actually be better in the end, writing all new code for this, scrapping the legacy stuff, which is a hodge podge of half finished ideas. At least so far, the FLAT interface has maintained some reasonable design thought.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

@magnumripper, @frank-dittrich, How big is 'too' big of a .c source file? dynamic_big_crypt.c could get pretty large. I 'could' split the file, but that would mean either the functions in dynamic_big_crypt_header.cin would have to become extern global, or be static and replicated. Now, since it is auto-generated code, replicated would never have problems with code maintenance. But it is extra 'bloat'. But in the same sense, it also does localize the code and put functions closer to each other (if that matters at all anymore).

I think all the manipulation functions will be singletons (I do not need them for each hash type), but the in1->out1, etc functions will all have to be specialized for each hash type. The output buffers will be shared between all types (thus, they will be 128 bits blocks in arrays. There will also be some other data for each output buffer (I may go with 4 instead of 2), and that data will be width of hash currently in the buffer, if it needs swapped for output, etc. Then these output buffers could be used as data to input conversion functions (which would know amount of data, and how to treat it), or they could be used as intermediate results (as is #saltfail, PBKDF2, etc!!!) or as 'raw' input. Not quite the 'generic' buffer I wanted, but half way there.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

Here is my big hash output variable. What do you think, before I get too far into this?

typedef struct {
    union {
        uint32_t w32[128/4];
        uint64_t w64[128/8];
        uint8_t b[128];
        char c[128];
    } *dat;
    int width;
    int BE;
} BIG_HASH_OUT;

// Then I will have these in dynamic_fmt.c, allocated in init()

BIG_HASH_OUT dynamic_BHO[4];

init() {
  // ....
 for (i = 0; i < 4; ++i) {
   dynamic_BHO.dat = mem_calloc_tiny(max_keys * sizeof(*(dynamic_BHO.dat)), SIMD_COEF);

I think it looks workable, it should be writable by oSSL, by SIMD. Now, it does not do MD5_body (x2), but I am not sure I am supporting that at this time. Yes, it did help some non-intel systems, but it was a LOT more ugly code to maintain. I may put it in at some later time, but not right now. Flat has always been pure CTX or SIMD logic only.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

I love the new way I did dynamic! I just added 280 extern global and 70 'static' dynamic functions functions in an hour. Now, right now, they only 'work' for CTX, but all I have to do is one function (which would be 35 more static functions), and it works for CTX and SIMD.

The 8 new 'extern' functions are very thin. They simply handle the DYNA_OMP_PARAMS, and then simply call the single function, passing in a 1 or 2 for input, and a 1, 2, 3, 4 for the output.

Once I get them working (for both SIMD and CTX), I will then make the data manipulators. The nice thing about those functions, is they can be in the dynamic_big_crypt_header.cin file. They only have to be a single function, not something tied to the crypt type.

@frank-dittrich
Copy link
Collaborator

@jfoug for generated code I wouldn't care if the file size increases. IMHO there's no reason to add extra bloat just to split that file into smaller ones.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

the .o file is 1.4mb now (but that is lots of dbg stuff also. It builds fine right now. The 8 new external globals for each type (that will increase) was pretty thin. Those functions do very little. They just set things up for a static inline 'common' function, that is told which of the inputs and which of the outputs to use, and then calls either the CTX or the SIMD function (again, 2 new inlines for each hash).

Later, I will likely have to add functions that can crypt from one of these outputs, into an input or possibly also into another output (including crypt_out_4_to_out_4 for an inplace crypt).

Adding these functions, and getting them right, is trivial. One thing I have thought of, is that the output is not 'packed'. I should probably re-think how I have my structure, and try to pack them. I have added new code to the SIMD, and I bet it would be better if I did not, and instead tried to use packed data, and possibly even SIMD mixed data for these buffers. The mixed might be something optional (would need another flag in the structure). If I know that I will do a lot of crypt into one of these buffers, then muliple crypts (or even just one more), directly from these buffers, then storing mixed, to reload mixed 'might' be fastest.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

@magnumripper

If I use SSEi_FLAT_OUT can I resume, i.e. multi buffers ?

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

Nope! SSEi_FLAT_OUT can not be resumed (here is a test)

#include "arch.h"
#include "simd-intrinsics.h"
#include <stdio.h>
#include <openssl/md5.h>

ARCH_WORD_32 __attribute__((__alligned__(16))) Buffer[5000];
ARCH_WORD_32 __attribute__((__alligned__(16))) input[5000];
void dump(ARCH_WORD_32 *, int);
int main() {
    MD5_CTX ctx;
    strcpy((char*)input, "1234567890123456789012345678901234567890123456789012345678901234567890\x80");
    input[30] = 70*8;
    dump(input,128);
    SIMDmd5body(input, Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT_FIRST_BLK);
    SIMDmd5body(&input[16], Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT|SSEi_RELOAD);
    dump(Buffer,16);
    SIMDmd5body(input, Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT_FIRST_BLK|SSEi_FLAT_OUT);
    SIMDmd5body(&input[16], Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT|SSEi_RELOAD|SSEi_FLAT_OUT);
    dump(Buffer,16);
    SIMDmd5body(input, Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT_FIRST_BLK);
    SIMDmd5body(&input[16], Buffer, Buffer, SSEi_FLAT_IN|SSEi_2BUF_INPUT|SSEi_RELOAD);
    dump(Buffer,16);
    MD5_Init(&ctx);
    MD5_Update(&ctx, "1234567890123456789012345678901234567890123456789012345678901234567890", 70);
    MD5_Final((unsigned char *)Buffer, &ctx);
    dump(Buffer,16);
    system("echo -n 1234567890123456789012345678901234567890123456789012345678901234567890 | md5sum");
    return 0;
}
void dump(ARCH_WORD_32 *_p, int len) {
    int i;
    unsigned char *p = (unsigned char*)_p;
    for (i = 0; i < len; ++i) {
        printf ("%02x", p[i]);
        if (i & 4 == 3)
            printf (" ");
    }
    printf ("\n");
}

Output is:

3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003002000000000000
689de1e3145b0dcd145b0dcd145b0dcd
0297aa44c31ac1b3a34ef80801d2d6c3
689de1e3145b0dcd145b0dcd145b0dcd
689de1e396ad9c089ae2b9aaffd6faf7
689de1e396ad9c089ae2b9aaffd6faf7 *-

the 0297.... is from the SSEi_FLAT_OUT run.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 23, 2015

@magnumripper

We already have a SSEi_FLAT_RELOAD_SWAPLAST flag.. But we have to flat_reload.

Is there any way I can talk you into building code for a new flag:

SSEi_RELOAD_FLAT = 0x2000 | SSEi_RELOAD

Now I do find this in sybase-ase:

SIMDSHA256body(prep_key[index/MAX_KEYS_PER_CRYPT], crypt32, NULL, SSEi_FLAT_IN|SSEi_FLAT_RELOAD_SWAPLAST);
SIMDSHA256body(&(prep_key[index/MAX_KEYS_PER_CRYPT][1]), crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD|SSEi_FLAT_RELOAD_SWAPLAST);
SIMDSHA256body(NULL_LIMB, crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD);
SIMDSHA256body(NULL_LIMB, crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD);
SIMDSHA256body(NULL_LIMB, crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD);
SIMDSHA256body(NULL_LIMB, crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD);
SIMDSHA256body(NULL_LIMB, crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD);
SIMDSHA256body(&(prep_key[index/MAX_KEYS_PER_CRYPT][2]), crypt32, crypt32, SSEi_FLAT_IN|SSEi_RELOAD|SSEi_FLAT_RELOAD_SWAPLAST);
// Last one with FLAT_OUT
SIMDSHA256body(&(prep_key[index/MAX_KEYS_PER_CRYPT][3]), crypt_out[index], crypt32, SSEi_FLAT_IN|SSEi_RELOAD|SSEi_FLAT_OUT);

But I may need (almost certainly will) any intermediate values to be flat format, yet still need to be able to re-run the hash. I guess I could byte swap if I need to run the next limb, but doing so on the CPU side is not simple, and then I have to address the hash type, the PARA, etc.

@magnumripper
Copy link
Member

How big is 'too' big of a .c source file?

To me it can be a gigabyte as long as it's within a certain topic.

Is there any way I can talk you into building code for a new flag:
SSEi_RELOAD_FLAT = 0x2000 | SSEi_RELOAD

I'm not sure I understand your need yet but if there's a combination we don't support that would gain speed or functionality, we should just add it.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 24, 2015

I hope I can get by without it. However, I did have to add this, and it was easy to add:

SSEi_OUTPUT_AS_2BUF_INP_FMT  = 0x2000 | SSEi_OUTPUT_AS_INP_FMT

This was added because the buffers I have added (output 1 to output4), are arrays of 128 byte buffers. They can hold 'any' hash type, and are 'self-describing' at least on what data is in there. So, for the 32 bit formats, I had to add a 2-buffer-input format since these buffers are input style, but offset 128 bytes. I also added that flag to the SIMD64 sha512 formats, but it is not used (yet). But with this change to the 64 bit ones, it would allow them to crypt directly into the 'real' input buffer array, which is 256 bytes (or 2 input buffers). So doing something like sha512raw(sha512raw(sha512raw(sha512raw($p)))) would be considerably faster, since there would be no data marshaling or data manipulation. Just do the first crypt, set the buffer up properly, and then call the crypt as many times as needed, then byteswap the final result (only 16 bytes), and put the results into the 'crypt' buffer.

But let me work on, and see what I can do, without the reload of a flat crypt.

@jfoug
Copy link
Collaborator Author

jfoug commented Jul 31, 2015

This Fedora cross compiled exe not running in 'real' windos is really disheartening. What sux, is that john can run a single hash just fine:

for f in `(./john -list=formats -format=dynamic-all && ./john -list=formats) | sed s/,//g` ; do ./john -test=0 -form=$f 2>/dev/null ; done

This simply runs john testing all formats but doing so 1 at a time. This works like a champ, as does a real test (not just -test=0). But simply running -test or -test=0 with this build, and not specifying a format, will crash on most formats. Ugg...

@jfoug
Copy link
Collaborator Author

jfoug commented Dec 4, 2015

Getting 'close' on regen salts.

^jG#ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppf$hv (u642)
>o9gppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp&L+Y (u742)
-#gpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp/}T~ (u1136)
vel&pppppppppppA~Iy (u1345)
CJekppppppppT>a< (u1447)
1321g 0:00:00:00 DONE (2015-12-04 16:06) 7725g/s 21093p/s 5399Kc/s 8085MC/s 3qW|p▒ppppp▒pp%'y▒..ko}GpppVeLj
Use the "--show" option to display all of the cracked passwords reliably
Session completed

 $ ../run/john -form='dynamic=md5($s.$p)' '-regen=@dynamic=md5($s.$p)@:32:?h?h' -w=pw-new.dic xxxxxx -pot=reg.pot
Loaded 1500 password hashes with no different salts (dynamic=md5($s.$p) [128/128 XOP 4x2])
Remaining 179 password hashes with no different salts
Warning: no OpenMP support for this hash type, consider --fork=4
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:00:00 DONE (2015-12-04 16:06) 0g/s 26137p/s 6691Kc/s 1197MC/s 3qW|p▒ppppp▒pp%'y▒..ko}GpppVeLj
Session completed

 $ head reg.pot
@dynamic=md5($s.$p)@4a0cb74b168f86912e464e3d6d3f24e6$00:OkVLpppppppppppppppppppppg}G;
@dynamic=md5($s.$p)@10358b14d99a0056036a73e5ac93476c$00: ,SRpppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppKR?S
@dynamic=md5($s.$p)@b02c6061d5a8b3443fd908fd88dcdbbd$00:3b5Oppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp%pyz
@dynamic=md5($s.$p)@87d854c1fe6aa8b9ebd7de47a31d1e9b$00:(G1spppppppppppppppppppppp rN0
@dynamic=md5($s.$p)@8fe39e58e1dd8f7dadeb1eabaa4b1ad4$00:T#oJpppppppppppppppppppppppppppppppppppppppppppppppppp*IH
@dynamic=md5($s.$p)@4f5f48bad2a482a64a7a70189a638afb$00:g8wZpppppppppppYB.>
@dynamic=md5($s.$p)@ad34ace4b7ee19fb62a3984aec06dd0f$10:R9t9ppppppppppo#w-
@dynamic=md5($s.$p)@ec3af543fa6d4ada5939f61c0ebf82cc$10:HS#xppppppppp,MY?
@dynamic=md5($s.$p)@1c869c5de698597d46c206206e2ba855$10:[LEYpppppppJH'(
@dynamic=md5($s.$p)@820c3c943cf92fb996240798ddec6eec$10:^'7,pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp)+48

It does not find them all. It is possible, that the file is invalid. I will have to check to make sure.

@jfoug
Copy link
Collaborator Author

jfoug commented Dec 4, 2015

Ok, re-running the original file (with the $dynamic_6000$ signature cut off, netted my 1322 cracks. The regen netted me 1321. I am going to call it good (after a bit more testing). This may be due to 110 byte password limit of dyna. But things are currently looking good.

This will be the signature needed: '-regen=@dynamic=md5($s.$p)@:32:?h?h' It 'may' also work with '-regen=dynamic_6000:32:?h?h' But that may or may not make it into a final version.

I have to make sure things ARE working properly, get some code cleaned up, and adjust the documentation. Also, I will be away from computer for a few days, so it will have to wait a bit, lol.

@kernelr00ter
Copy link

example:
hash md5 salt passwd
4297f44b13955235245b2497399d7a93 123 123

my_wordlist.txt
123

test:
./john --regen-lost-salts='@dynamic=md5($s.md5($p))@:32:?d?d?d-' --wordlist=my_wordlist.txt --format='dynamic=md5($s.md5($p))' test_salt_md5.txt

And nothing !

Why doesn't find anything ?

@solardiz
Copy link
Member

solardiz commented Dec 8, 2020

@kernelr00ter You probably won't achieve anything useful, at least beyond what I wrote below, by posting what looks like an advanced user support request as a mostly-offtopic comment to a closed issue on GitHub.

That said, FWIW, your hash is a md5($s.$p), not md5($s.md5($p)), and I have no idea what you mean to achieve by using --regen-lost-salts here. You might want to join the john-users mailing list and start by describing what you're actually trying to achieve, then ask for advice on how to achieve it best.

@solardiz
Copy link
Member

solardiz commented Dec 8, 2020

@kernelr00ter OK, you did achieve a bit more. This works:

$ ./john pw --regen-lost-salts='@dynamic=md5($s.$p)@:32:?d?d?d' --mask='?d?d?d' --format='dynamic=md5($s.$p)'
Using default input encoding: UTF-8
Loaded 1 password hash (dynamic=md5($s.$p) [128/128 AVX 4x3])
Warning: no OpenMP support for this hash type, consider --fork=32
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (?)     
1g 0:00:00:00  3.225g/s 3225p/s 3225Kc/s 3225KC/s 111..777
Use the "--show --format=dynamic=md5($s.$p)" options to display all of the cracked passwords reliably
Session completed. 

Whether it's a good solution to your actual (unspecified) problem or not is a separate question, not for here.

@kernelr00ter
Copy link

@kernelr00ter OK, you did achieve a bit more. This works:

$ ./john pw --regen-lost-salts='@dynamic=md5($s.$p)@:32:?d?d?d' --mask='?d?d?d' --format='dynamic=md5($s.$p)'
Using default input encoding: UTF-8
Loaded 1 password hash (dynamic=md5($s.$p) [128/128 AVX 4x3])
Warning: no OpenMP support for this hash type, consider --fork=32
Press 'q' or Ctrl-C to abort, almost any other key for status
123              (?)     
1g 0:00:00:00  3.225g/s 3225p/s 3225Kc/s 3225KC/s 111..777
Use the "--show --format=dynamic=md5($s.$p)" options to display all of the cracked passwords reliably
Session completed. 

Whether it's a good solution to your actual (unspecified) problem or not is a separate question, not for here.

I entered the hash incorrectly.
Your example worked great.
There was an error that I wanted to talk about.

We don't know in advance which hash is salted.
And if we accidentally put salted and regular hashes in one file.
Then, depending on the order of the hashes in the file, we get an error.
Example:
md5-raw pass
c4ca4238a0b923820dcc509a6f75849b 1

md5($s.$p) salt pass
d3d9446802a44259755d38e6d163e820 1 0

in file hash_dump.txt
c4ca4238a0b923820dcc509a6f75849b
d3d9446802a44259755d38e6d163e820

run john --regen-lost-salts
Result:
0                (?)

*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: Address not mapped (1)
Failing at address: (nil)
[ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f4d13061390]
[ 1] /john[0x47b785]
[ 2] /john[0x6bee8b]
[ 3] /john[0x6bfe30]
[ 4] /john[0x6c0605]
[ 5] /john[0x6dd359]
[ 6] /john[0x6cdd51]
[ 7] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f4d12ca6840]
[ 8] /john[0x407099]
*** End of error message ***
Segmentation fault (core dumped)

In this case, the utility correctly detects the hash result, but does not show the salt. And the report file remains empty.

But if you swap hashes
d3d9446802a44259755d38e6d163e820
c4ca4238a0b923820dcc509a6f75849b

Everything works perfectly.

If you try to run the same file with examples in the format raw-md5
For a salted hash, we get the following answer:
$dynamic_0$d3d9446802a44259755d38e6d163e820:10

Or does she just write the salt and password this way.
Instead:
@dynamic=md5($s.$p)@d3d9446802a44259755d38e6d163e820$1:0

I don't know if this is a mistake or not.
Anyway, thanks a lot for the answers.

Создателю JTR, Александру, большое спасибо за труд.

@magnumripper
Copy link
Member

Wow, looks like it actually finds "the salt", but with it being NULL it then dies, LOL. I'll open an issue for that (we abuse the issue tracker by writing here). Thank you for reporting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants