I'm overlooking something when implementing new algorithm: please help
#1
Hi,

I'd like to implement a DES-based algorithm. After figuring out how coding for oclHashcat works, everything went just fine. Implementation of step one, DES, works. What I did:


- Implement a new DES-based hash type.
- Use a fixed DES key: 0xAAAAAAAAAAAAAAAA;
- Encrypt an ASCII value (e.g. 12345678 = 3132333435363738) with this key and IV 0 = 0xF3C3F7A3B59D884B;
- Build oclHashcat, crack the hash: success:

Code:
john@dev:/opt/oclHashcat$ ./hashcat -m663 -a3 F3C3F7A3B59D884B ?d?d?d?d?d?d?d?d
hashcat (v3.00-beta-201-ge3c499c+) starting...
<SNAP>
F3C3F7A3B59D884B:12345678

Session.Name...: hashcat
Status.........: Cracked
Input.Mode.....: Mask (?d?d?d?d?d?d?d?d) [8]
Hash.Target....: F3C3F7A3B59D884B
Hash.Type......: TEST_DES
Time.Started...: Tue Jul 12 00:27:58 2016 (2 secs)
Speed.Dev.#1...: 10855.1 kH/s (11.56ms)
Recovered......: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.......: 14080000/100000000 (14.08%)
Rejected.......: 0/14080000 (0.00%)
Restore.Point..: 13952/100000 (13.95%)

Started: Tue Jul 12 00:27:58 2016
Stopped: Tue Jul 12 00:28:02 2016

So that all looks good. However, if I change my hard coded key to e.g. 0xAAAAAAAAAAAAAABC, calculate the corresponding target hash (0xC4935F6FA17C7C8D), rebuild and crack again, the hash is not found...

Can someone please point out what I'm missing? Code:

Code:
void m00663s (__local u32 (*s_SPtrans)[64], __local u32 (*s_skb)[64], u32 w[16], const u32 pw_len, __global pw_t *pws, __global kernel_rule_t *rules_buf, __global comb_t *combs_buf, __constant u32x * words_buf_r, __global void *tmps, __global void *hooks, __global u32 *bitmaps_buf_s1_a, __global u32 *bitmaps_buf_s1_b, __global u32 *bitmaps_buf_s1_c, __global u32 *bitmaps_buf_s1_d, __global u32 *bitmaps_buf_s2_a, __global u32 *bitmaps_buf_s2_b, __global u32 *bitmaps_buf_s2_c, __global u32 *bitmaps_buf_s2_d, __global plain_t *plains_buf, __global digest_t *digests_buf, __global u32 *hashes_shown, __global salt_t *salt_bufs, __global void *esalt_bufs, __global u32 *d_return_buf, __global u32 *d_scryptV_buf, const u32 bitmap_mask, const u32 bitmap_shift1, const u32 bitmap_shift2, const u32 salt_pos, const u32 loop_pos, const u32 loop_cnt, const u32 il_cnt, const u32 digests_cnt, const u32 digests_offset)
{
 const u32 gid = get_global_id (0);
 const u32 lid = get_local_id (0);
 const u32 search[4] =
 {
   digests_buf[digests_offset].digest_buf[DGST_R0],
   digests_buf[digests_offset].digest_buf[DGST_R1],
   0,
   0
 };
 // loop
 u32 w0l = w[0];
 for (u32 il_pos = 0; il_pos < il_cnt; il_pos += VECT_SIZE)
 {
   const u32x w0r = words_buf_r[il_pos / VECT_SIZE];
   const u32x w0 = w0l | w0r;

   u32x key[2];
   key[0] = 0xaaaaaaaa;
   key[1] = 0xaaaaaabc; // exactly the same code with key[1] = 0xaaaaaaaa works, key[1] = 0xaaaaaabc doesn't.
   u32x Kc[16];
   u32x Kd[16];
   _des_crypt_keysetup (key[0], key[1], Kc, Kd, s_skb);

   u32x in[2];
   in[0] = w0;
   in[1] = w[1];
   u32x out[2];
   _des_crypt_encrypt (out, in, Kc, Kd, s_SPtrans);

   // cmp
   u32x z = 0;
   COMPARE_S_SIMD (out[0], out[1], z, z);
 }
}

Thanks! 

John
Reply
#2
Did you remove the cached kernel after rebuilding?
Reply
#3
Just a guess:

With a key 0xAAAAAAAAAAAAAAAA you do not have to care about Little endian/Big endian, because the key has always the same byte value. Try again with 0xBBBBBBBBBBBBBBBB and update your Ciphertext and if we're on the right track it will still work. After that, try the key 0xAAAAAAAABCAAAAAA instead of 0xAAAAAAAAAAAAAABC with the original Ciphertext. If it still works it's for sure LE/BE handling.

Also note what epixoip said or, as an alternative for developer, use the

Quote:int force_jit_compilation = -1;

and set it to:

Quote:int force_jit_compilation = XXX;

Where XXX is your new hash mode. This will also enable you to use printf() on some OpenCL runtime from within the kernel.
Reply
#4
(07-12-2016, 05:27 AM)epixoip Wrote: Did you remove the cached kernel after rebuilding?

Yes, by a make clean && make.
Reply
#5
(07-12-2016, 09:26 AM)atom Wrote: Just a guess:

With a key 0xAAAAAAAAAAAAAAAA you do not have to care about Little endian/Big endian, because the key has always the same byte value. Try again with 0xBBBBBBBBBBBBBBBB and update your Ciphertext and if we're on the right track it will still work. 

0xBBBBBBBBBBBBBBBB  works.

Quote:After that, try the key 0xAAAAAAAABCAAAAAA instead of 0xAAAAAAAAAAAAAABC with the original Ciphertext. If it still works it's for sure LE/BE handling.

Works, bingo! Quick fix:
Code:
u32x convertEndian(u32x num)
{
   u32x b0,b1,b2,b3;
   b0= (num & 0x000000FF)>>0;
   b1= (num & 0x0000FF00)>>8;
   b2= (num & 0x00FF0000)>>16;
   b3= (num & 0xFF000000)>>24;
   num= (b0<<24) | (b1<<16) | (b2<<8) | (b3<<0) ;
   return num;
}

However I see some endian related functions in e.g. inc_common.cl. What would be the best / fastest / cleanest option for endian switching for a 64 bits value that's stored in two 32-bits values (u32x key[2])?

Quote:Also note what epixoip said or, as an alternative for developer, use the

int force_jit_compilation = -1;

and set it to:

int force_jit_compilation = XXX;

Where XXX is your new hash mode. This will also enable you to use printf() on some OpenCL runtime from within the kernel.

Very useful tip thanks!
Reply
#6
There's both swap32() and swap64() as well as swap32_S() and swap64_S() for scalar datatypes.
Reply