format ELF executable
entry start
segment readable writeable
usage_part1 db 'Usage:',10
.len	    = $-usage_part1
usage_part3 db ' [anything at all] md5hash',10
.len	    = $-usage_part3

digits	    db 'Processing: '
.len	    = $-digits

wronglen    db 'Incorrect length for MD5 string',10
.len	    = $-wronglen

lf	    db 10


  md5hash  db 33 dup 0
  password db 13 dup 0

  length dd 0

  digit1  db  '1',0
  digit2  db  '2',0
  digit3  db  '3',0
  digit4  db  '4',0
  digit5  db  '5',0
  digit6  db  '6',0
  digit7  db  '7',0
  digit8  db  '8',0
  digit9  db  '9',0
  digit10 db '10',0
  digit11 db '11',0
  digit12 db '12',0

  savebp dd ?
  savesp dd ?

  a dd 067452301h
  b dd 0efcdab89h
  c dd 098badcfeh
  d dd 010325476h

  temp dd ?

  temp0 dd 0D98C1DD4h
  temp1 dd 004B2008Fh
  temp2 dd 0980980E9h
  temp3 dd 07E42F8ECh

  test4_0 dd ?
  test4_1 dd ?
  test4_2 dd ?
  test4_3 dd ?

  test8_0 dd ?
  test8_1 dd ?
  test8_2 dd ?
  test8_3 dd ?

  test12_0 dd ?
  test12_1 dd ?
  test12_2 dd ?
  test12_3 dd ?

  strr dd ?

segment executable
;functions
strlen: ;stolen from azillionmonkeys.com (Paul Hsieh)
lea	ecx,[ebx-1]
.l1:

inc	ecx
test	ecx,3
jnz	.l3
.l2:

mov	edx,[ecx]	 ; U
mov	eax,07F7F7F7Fh	 ;   V
and	eax,edx 	 ; U
add	ecx,4		 ;   V
add	eax,07F7F7F7Fh	 ; U
or	eax,edx 	 ; U
and	eax,080808080h	 ; U
cmp	eax,080808080h	 ; U
je	.l2		 ;   V +1brt
sub	ecx,4
.l3:

cmp	byte [ecx],0
jne	.l1
sub	ecx,ebx
ret

start:
pop	ecx
pop	ebx
dec	ecx
jz	error_no_args
.pop:
pop	edx
dec	ecx
jnz	.pop

mov	[strr],edx

mov	ebx,edx
call	strlen
cmp	ecx,32
jne	error_wrong_length

mov	eax,4
mov	ebx,1
mov	ecx,digits
mov	edx,digits.len
int	80h

mov	eax,4
mov	ebx,1
mov	ecx,[strr]
mov	edx,32
int	80h

mov	eax,4
mov	ebx,1
mov	ecx,lf
mov	edx,1
int	80h

find:

  S11 =  7
  S12 = 12
  S13 = 17
  S14 = 22
  S21 =  5
  S22 =  9
  S23 = 14
  S24 = 20
  S31 =  4
  S32 = 11
  S33 = 16
  S34 = 23
  S41 =  6
  S42 = 10
  S43 = 15
  S44 = 21

macro	optadd	a,l,k
{
if k eq 0
else if k eq 1
	add	a,edi
else if k eq 2
  if l<20h
  else if l eq 20h
	add	a,80h
       else
	add	a,ebp
  end if
else if k eq 3
  if l<40h
  else if l eq 40h
	add	a,80h
       else
	add	a,esp
  end if
else if k eq 4
  if l eq 60h
	add	a,80h
  end if
else if k eq 5
	add	a,l
end if
}

macro	FF	a,b,c,d,s,i,l,k
{
	mov	esi,c
	xor	esi,d
	and	esi,b
	xor	esi,d
	lea	a,dword[a+esi+i]
	optadd	a,l,k
	rol	a,s
	add	a,b
}

macro	GG	a,b,c,d,s,i,l,k
{
	mov	esi,b
	xor	esi,c
	and	esi,d
	xor	esi,c
	lea	a,dword[a+esi+i]
	optadd	a,l,k
	rol	a,s
	add	a,b
}

macro	HH	a,b,c,d,s,i,l,k
{
	mov	esi,b
	xor	esi,c
	xor	esi,d
	lea	a,dword[a+esi+i]
	optadd	a,l,k
	rol	a,s
	add	a,b
}

macro	II	a,b,c,d,s,i,l,k
{
	mov	esi,d
	not	esi
	or	esi,b
	xor	esi,c
	lea	a,dword[a+esi+i]
	optadd	a,l,k
	rol	a,s
	add	a,b
}

macro	invII	a,b,c,d,s,i,k
{
	sub	a,b
	ror	a,s
if k eq 0
else
	sub	a,k
end if
	mov	esi,d
	not	esi
	or	esi,b
	xor	esi,c
	sub	a,esi
	sub	a,i
}

macro	hash	l
{
	mov	eax,[a]
	mov	ebx,[b]
	mov	ecx,[c]
	mov	edx,[d]

	FF	eax,ebx,ecx,edx,S11,0d76aa478h,l,1
	FF	edx,eax,ebx,ecx,S12,0e8c7b756h,l,2
	FF	ecx,edx,eax,ebx,S13,0242070dbh,l,3
	FF	ebx,ecx,edx,eax,S14,0c1bdceeeh,l,4
	FF	eax,ebx,ecx,edx,S11,0f57c0fafh,l,0
	FF	edx,eax,ebx,ecx,S12,04787c62ah,l,0
	FF	ecx,edx,eax,ebx,S13,0a8304613h,l,0
	FF	ebx,ecx,edx,eax,S14,0fd469501h,l,0
	FF	eax,ebx,ecx,edx,S11,0698098d8h,l,0
	FF	edx,eax,ebx,ecx,S12,08b44f7afh,l,0
	FF	ecx,edx,eax,ebx,S13,0ffff5bb1h,l,0
	FF	ebx,ecx,edx,eax,S14,0895cd7beh,l,0
	FF	eax,ebx,ecx,edx,S11,06b901122h,l,0
	FF	edx,eax,ebx,ecx,S12,0fd987193h,l,0
	FF	ecx,edx,eax,ebx,S13,0a679438eh,l,5
	FF	ebx,ecx,edx,eax,S14,049b40821h,l,0

	GG	eax,ebx,ecx,edx,S21,0f61e2562h,l,2
	GG	edx,eax,ebx,ecx,S22,0c040b340h,l,0
	GG	ecx,edx,eax,ebx,S23,0265e5a51h,l,0
	GG	ebx,ecx,edx,eax,S24,0e9b6c7aah,l,1
	GG	eax,ebx,ecx,edx,S21,0d62f105dh,l,0
	GG	edx,eax,ebx,ecx,S22,002441453h,l,0
	GG	ecx,edx,eax,ebx,S23,0d8a1e681h,l,0
	GG	ebx,ecx,edx,eax,S24,0e7d3fbc8h,l,0
	GG	eax,ebx,ecx,edx,S21,021e1cde6h,l,0
	GG	edx,eax,ebx,ecx,S22,0c33707d6h,l,5
	GG	ecx,edx,eax,ebx,S23,0f4d50d87h,l,4
	GG	ebx,ecx,edx,eax,S24,0455a14edh,l,0
	GG	eax,ebx,ecx,edx,S21,0a9e3e905h,l,0
	GG	edx,eax,ebx,ecx,S22,0fcefa3f8h,l,3
	GG	ecx,edx,eax,ebx,S23,0676f02d9h,l,0
	GG	ebx,ecx,edx,eax,S24,08d2a4c8ah,l,0

	HH	eax,ebx,ecx,edx,S31,0fffa3942h,l,0
	HH	edx,eax,ebx,ecx,S32,08771f681h,l,0
	HH	ecx,edx,eax,ebx,S33,06d9d6122h,l,0
	HH	ebx,ecx,edx,eax,S34,0fde5380ch,l,5
	HH	eax,ebx,ecx,edx,S31,0a4beea44h,l,2
	HH	edx,eax,ebx,ecx,S32,04bdecfa9h,l,0
	HH	ecx,edx,eax,ebx,S33,0f6bb4b60h,l,0
	HH	ebx,ecx,edx,eax,S34,0bebfbc70h,l,0
	HH	eax,ebx,ecx,edx,S31,0289b7ec6h,l,0
	HH	edx,eax,ebx,ecx,S32,0eaa127fah,l,1
	HH	ecx,edx,eax,ebx,S33,0d4ef3085h,l,4
	HH	ebx,ecx,edx,eax,S34,004881d05h,l,0
	HH	eax,ebx,ecx,edx,S31,0d9d4d039h,l,0
	HH	edx,eax,ebx,ecx,S32,0e6db99e5h,l,0
	HH	ecx,edx,eax,ebx,S33,01fa27cf8h,l,0
	HH	ebx,ecx,edx,eax,S34,0c4ac5665h,l,3

	II	eax,ebx,ecx,edx,S41,0f4292244h,l,1
if l>20h
	II	edx,eax,ebx,ecx,S42,0432aff97h,l,0
	II	ecx,edx,eax,ebx,S43,0ab9423a7h,l,5
	II	ebx,ecx,edx,eax,S44,0fc93a039h,l,0
	II	eax,ebx,ecx,edx,S41,0655b59c3h,l,0
	II	edx,eax,ebx,ecx,S42,08f0ccc92h,l,4
	II	ecx,edx,eax,ebx,S43,0ffeff47dh,l,0
	II	ebx,ecx,edx,eax,S44,085845dd1h,l,2
end if
if l>40h
	II	eax,ebx,ecx,edx,S41,06fa87e4fh,l,0
	II	edx,eax,ebx,ecx,S42,0fe2ce6e0h,l,0
	II	ecx,edx,eax,ebx,S43,0a3014314h,l,0
	II	ebx,ecx,edx,eax,S44,04e0811a1h,l,0
	II	eax,ebx,ecx,edx,S41,0f7537e82h,l,0
	II	edx,eax,ebx,ecx,S42,0bd3af235h,l,0
	II	ecx,edx,eax,ebx,S43,02ad7d2bbh,l,3
end if
}

macro	compare a,b,c,d,i
{
	cmp	eax,a
	jne	notfound#i
	cmp	ebx,b
	jne	notfound#i
	cmp	ecx,c
	jne	notfound#i
	cmp	edx,d
	jne	notfound#i
	mov	[length],i
	jmp	found
	notfound#i:
}

macro	new	r,l
{
if l eq 1
	inc	edi
	cmp	edi,803ah
	jne	next1e#l
	add	edi,27h
	next1e#l:
	cmp	edi,807bh
	jne new1
else
	inc	edi
	mov	r,edi
	and	r,0ffh
	cmp	r,3ah
	jne	next1#l
	add	edi,27h
	next1#l:
	cmp	r,7bh
	jne	new#l

	add	edi,0b5h
	mov	r,edi
	and	r,0ff00h
	cmp	r,3a00h
	jne	next2#l
	add	edi,2700h
	next2#l:
	cmp	r,7b00h
	jne	new#l
if l>2
	add	edi,0b500h
	mov	r,edi
	and	r,0ff0000h
	cmp	r,3a0000h
	jne	next3#l
	add	edi,270000h
	next3#l:
	cmp	r,7b0000h
	jne	new#l
if l>3
	add	edi,0b50000h
	mov	r,edi
	and	r,0ff000000h
	cmp	r,3a000000h
	jne	next4#l
	add	edi,27000000h
	next4#l:
	cmp	r,7b000000h
	jne	new#l
if l>4
if l eq 5
	mov	edi,30303030h

	inc	ebp
	cmp	ebp,803ah
	jne	next5e#l
	add	ebp,27h
	next5e#l:
	cmp	ebp,807bh
	jne	new#l
else
	mov	edi,30303030h

	inc	ebp
	mov	r,ebp
	and	r,0ffh
	cmp	r,3ah
	jne	next5#l
	add	ebp,27h
	next5#l:
	cmp	r,7bh
	jne	new#l

	add	ebp,0b5h
	mov	r,ebp
	and	r,0ff00h
	cmp	r,3a00h
	jne	next6#l
	add	ebp,2700h
	next6#l:
	cmp	r,7b00h
	jne	new#l
if l>6
	add	ebp,0b500h
	mov	r,ebp
	and	r,0ff0000h
	cmp	r,3a0000h
	jne	next7#l
	add	ebp,270000h
	next7#l:
	cmp	r,7b0000h
	jne	new#l
if l>7
	add	ebp,0b50000h
	mov	r,ebp
	and	r,0ff000000h
	cmp	r,3a000000h
	jne	next8#l
	add	ebp,27000000h
	next8#l:
	cmp	r,7b000000h
	jne	new#l
if l>8
if l eq 9
	mov	edi,30303030h
	mov	ebp,edi

	inc	esp
	cmp	esp,803ah
	jne	next9e#l
	add	esp,27h
	next9e#l:
	cmp	esp,807bh
	jne	new#l
else
	mov	edi,30303030h
	mov	ebp,edi

	inc	esp
	mov	r,esp
	and	r,0ffh
	cmp	r,3ah
	jne	next9#l
	add	esp,27h
	next9#l:
	cmp	r,7bh
	jne	new#l

	add	esp,0b5h
	mov	r,esp
	and	r,0ff00h
	cmp	r,3a00h
	jne	next10#l
	add	esp,2700h
	next10#l:
	cmp	r,7b00h
	jne	new#l
if l>10
	add	esp,0b500h
	mov	r,esp
	and	r,0ff0000h
	cmp	r,3a0000h
	jne	next11#l
	add	esp,270000h
	next11#l:
	cmp	r,7b0000h
	jne	new#l
if l>11
	add	esp,0b50000h
	mov	r,esp
	and	r,0ff000000h
	cmp	r,3a000000h
	jne	next12#l
	add	esp,27000000h
	next12#l:
	cmp	r,7b000000h
	jne	new#l
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
end if
}

macro	str2hex r,i
{
	mov	edi,[esi]
	mov	ebp,edi
	and	edi,0ffh
	and	ebp,0ff00h
	cmp	edi,61h
	jb	num0#r#i
	sub	edi,27h

	num0#r#i:
	sub	edi,30h
	cmp	edi,10h
	jb	ncaps0#r#i
	sub	edi,7h

	ncaps0#r#i:
	cmp	ebp,6100h
	jb	num1#r#i
	sub	ebp,2700h

	num1#r#i:
	sub	ebp,3000h
	cmp	ebp,1000h
	jb	ncaps1#r#i
	sub	ebp,700h

	ncaps1#r#i:
	shl	edi,4h
	shr	ebp,8h
	add	edi,ebp
	shl	r,8h
	add	r,edi
	sub	esi,2h
}

macro	s2h	r
{
	str2hex r,0
	str2hex r,1
	str2hex r,2
	str2hex r,3
}

macro	digit	d
{
	mov	ebp,[savebp]
	mov	esp,[savesp]
;        invoke  SetDlgItemText,[hwnddlg],ID_DIGIT,d

}

	mov	[savebp],ebp
	mov	[savesp],esp
;        invoke  GetDlgItemText,[hwnddlg],ID_MD5HASH,md5hash,33
	mov	eax,[strr]
	mov	edx,[eax]
	mov	dword [md5hash],edx
	mov	edx,[eax+4]
	mov	dword [md5hash+4],edx
	mov	edx,[eax+8]
	mov	dword [md5hash+8],edx
	mov	edx,[eax+12]
	mov	dword [md5hash+12],edx
	mov	edx,[eax+16]
	mov	dword [md5hash+16],edx
	mov	edx,[eax+20]
	mov	dword [md5hash+20],edx
	mov	edx,[eax+24]
	mov	dword [md5hash+24],edx
	mov	edx,[eax+28]
	mov	dword [md5hash+28],edx

	lea	esi,[md5hash+1eh]

	s2h	edx
	s2h	ecx
	s2h	ebx
	s2h	eax

	compare [temp0],[temp1],[temp2],[temp3],0

	sub	eax,[a]
	sub	ebx,[b]
	sub	ecx,[c]
	sub	edx,[d]

	invII	ebx,ecx,edx,eax,S44,0eb86d391h,0h

	mov	[test12_0],eax
	mov	[test12_1],ebx
	mov	[test12_2],ecx
	mov	[test12_3],edx

	invII	ecx,edx,eax,ebx,S43,02ad7d2bbh,0h
	invII	edx,eax,ebx,ecx,S42,0bd3af235h,0h
	invII	eax,ebx,ecx,edx,S41,0f7537e82h,0h
	invII	ebx,ecx,edx,eax,S44,04e0811a1h,0h
	invII	ecx,edx,eax,ebx,S43,0a3014314h,0h
	invII	edx,eax,ebx,ecx,S42,0fe2ce6e0h,0h
	invII	eax,ebx,ecx,edx,S41,06fa87e4fh,0h

	mov	[test8_0],eax
	mov	[test8_1],ebx
	mov	[test8_2],ecx
	mov	[test8_3],edx

	invII	ebx,ecx,edx,eax,S44,085845dd1h,0h
	invII	ecx,edx,eax,ebx,S43,0ffeff47dh,0h
	invII	edx,eax,ebx,ecx,S42,08f0ccc92h,0h
	invII	eax,ebx,ecx,edx,S41,0655b59c3h,0h
	invII	ebx,ecx,edx,eax,S44,0fc93a039h,0h

	mov	[test4_0],eax
	mov	[test4_1],ebx
	mov	[test4_2],ecx
	mov	[test4_3],edx

	mov	ebp,[savebp]
;        invoke  SetDlgItemText,[hwnddlg],ID_DIGIT,digit1

	invII	ecx,edx,eax,ebx,S43,0ab9423a7h,8h
	invII	edx,eax,ebx,ecx,S42,0432aff97h,0h

	mov	[temp2],ecx
	mov	[temp3],edx

	mov	edi,8030h
	mov	ebp,eax
	mov	esp,ebx

	new1:
	hash	8h
	compare ebp,esp,[temp2],[temp3],1
	new	esp,1

	digit	digit2

	mov	eax,[test4_0]
	mov	ebx,[test4_1]
	mov	ecx,[test4_2]
	mov	edx,[test4_3]

	invII	ecx,edx,eax,ebx,S43,0ab9423a7h,10h
	invII	edx,eax,ebx,ecx,S42,0432aff97h,0h

	mov	[temp1],ebx
	mov	[temp2],ecx
	mov	[temp3],edx

	mov	edi,803030h
	mov	ebp,eax

	new2:
	hash	10h
	compare ebp,[temp1],[temp2],[temp3],2
	new	esp,2

	digit	digit3

	mov	eax,[test4_0]
	mov	ebx,[test4_1]
	mov	ecx,[test4_2]
	mov	edx,[test4_3]

	invII	ecx,edx,eax,ebx,S43,0ab9423a7h,18h
	invII	edx,eax,ebx,ecx,S42,0432aff97h,0h

	mov	[temp1],ebx
	mov	[temp2],ecx
	mov	[temp3],edx

	mov	edi,80303030h
	mov	ebp,eax

	new3:
	hash	18h
	compare ebp,[temp1],[temp2],[temp3],3
	new	esp,3

	digit	digit4

	mov	eax,[test8_0]
	mov	ebx,[test8_1]
	mov	ecx,[test8_2]
	mov	edx,[test8_3]

	invII	ebx,ecx,edx,eax,S44,085845dd1h,80h
	invII	ecx,edx,eax,ebx,S43,0ffeff47dh,0h
	invII	edx,eax,ebx,ecx,S42,08f0ccc92h,0h
	invII	eax,ebx,ecx,edx,S41,0655b59c3h,0h
	invII	ebx,ecx,edx,eax,S44,0fc93a039h,0h
	invII	ecx,edx,eax,ebx,S43,0ab9423a7h,20h
	invII	edx,eax,ebx,ecx,S42,0432aff97h,0h

	mov	[temp1],ebx
	mov	[temp2],ecx
	mov	[temp3],edx

	mov	edi,30303030h
	mov	ebp,eax

	new4:
	hash	20h
	compare ebp,[temp1],[temp2],[temp3],4
	new	esp,4

	digit	digit5

	mov	edi,30303030h
	mov	ebp,8030h

	new5:
	hash	28h
	compare [test8_0],[test8_1],[test8_2],[test8_3],5
	new	esp,5

	digit	digit6

	mov	edi,30303030h
	mov	ebp,803030h

	new6:
	hash	30h
	compare [test8_0],[test8_1],[test8_2],[test8_3],6
	new	esp,6

	digit	digit7

	mov	edi,30303030h
	mov	ebp,80303030h

	new7:
	hash	38h
	compare [test8_0],[test8_1],[test8_2],[test8_3],7
	new	esp,7

	digit	digit8

	mov	eax,[test12_0]
	mov	ebx,[test12_1]
	mov	ecx,[test12_2]
	mov	edx,[test12_3]

	invII	ecx,edx,eax,ebx,S43,02ad7d2bbh,80h
	invII	edx,eax,ebx,ecx,S42,0bd3af235h,0h
	invII	eax,ebx,ecx,edx,S41,0f7537e82h,0h
	invII	ebx,ecx,edx,eax,S44,04e0811a1h,0h
	invII	ecx,edx,eax,ebx,S43,0a3014314h,0h
	invII	edx,eax,ebx,ecx,S42,0fe2ce6e0h,0h
	invII	eax,ebx,ecx,edx,S41,06fa87e4fh,0h

	mov	[temp0],eax
	mov	[temp1],ebx
	mov	[temp2],ecx
	mov	[temp3],edx

	mov	edi,30303030h
	mov	ebp,edi

	new8:
	hash	40h
	compare [temp0],[temp1],[temp2],[temp3],8
	new	esp,8

	digit	digit9

	mov	edi,30303030h
	mov	ebp,edi
	mov	esp,8030h

	new9:
	hash	48h
	compare [test12_0],[test12_1],[test12_2],[test12_3],9
	new	[temp],9

	digit	digit10

	mov	edi,30303030h
	mov	ebp,edi
	mov	esp,803030h

	new10:
	hash	50h
	compare [test12_0],[test12_1],[test12_2],[test12_3],10
	new	[temp],10

	digit	digit11

	mov	edi,30303030h
	mov	ebp,edi
	mov	esp,80303030h

	new11:
	hash	58h
	compare [test12_0],[test12_1],[test12_2],[test12_3],11
	new	[temp],11

	digit	digit12

	mov	edi,30303030h
	mov	ebp,edi
	mov	esp,edi

	new12:
	hash	60h
	compare [test12_0],[test12_1],[test12_2],[test12_3],12
	new	[temp],12

      found:
	mov	dword[password],edi
	mov	dword[password+4h],ebp
	mov	dword[password+8h],esp
	mov	esi,dword[length]
	mov	[password+esi],0h
	mov	ebp,[savebp]
	mov	esp,[savesp]
;        invoke  SetDlgItemText,[hwnddlg],ID_PASSWORD,password
	mov	ebx,password
	call	strlen
	mov	edx,ecx
	mov	ecx,ebx
	mov	ebx,1
	mov	eax,4
	int	80h

finish:        ;ended successfully.
mov	eax,1
xor	ebx,ebx
int	80h

error_no_args: ;error, no arguments. spit out Usage
push	ebx ;save program name
mov	eax,4
mov	ebx,1
mov	ecx,usage_part1
mov	edx,usage_part1.len
int	80h
pop	ebx
call	strlen ;program name is already in ebx
mov	edx,ecx
mov	ecx,ebx
mov	ebx,1
mov	eax,4
int	80h
mov	eax,4
mov	ebx,1
mov	ecx,usage_part3
mov	edx,usage_part3.len
int	80h
mov	eax,1
mov	ebx,eax
int	80h	;exit with error

error_wrong_length:
mov	eax,4
mov	ebx,1
mov	ecx,wronglen
mov	edx,wronglen.len
int	80h
mov	eax,1
mov	ebx,eax
int	80h	;exit with error