MySQL PASSWORD() function decryptor

MySQL에서 PASSWORD()를 이용하여 hash 된 값을 찾아낼 수 있다.
7자리까진 빠르게 진행되지만, 8자리부터는.. 속도가 orz..

그래도 background로 돌려놓으면 나름 잘찾는것같다. 후후훗

/* This program is public domain. Share and enjoy.
*
* Example:
* $ gcc -O2 -fomit-frame-pointer mysqlfast.c -o mysqlfast
* $ mysqlfast 6294b50f67eda209
* Hash: 6294b50f67eda209
* Trying length 3
* Trying length 4
* Found pass: barf
*
* The MySQL password hash function could be strengthened considerably
* by:
* - making two passes over the password
* - using a bitwise rotate instead of a left shift
* - causing more arithmetic overflows
*/
#include <stdio.h>

typedef unsigned long ULONG;

// 비밀번호에 있는 문자들을 정의. 33부터 126사이의 문자가 ascii code
#define MIN_CHAR 33
#define MAX_CHAR 126

// 비밀번호의 길이 범위
#define MIN_LEN 1
#define MAX_LEN 12

#define MASK 0x7fffffffL

int crack0(int stop, ULONG targ1, ULONG targ2, int *pass_ary)
{
	int i, c;
	ULONG d, e, sum, step, diff, div, xor1, xor2, state1, state2;
	ULONG newstate1, newstate2, newstate3;
	ULONG state1_ary[MAX_LEN-2], state2_ary[MAX_LEN-2];
	ULONG xor_ary[MAX_LEN-3], step_ary[MAX_LEN-3];

	i = -1;
	sum = 7;
	state1_ary[0] = 1345345333L;
	state2_ary[0] = 0x12345671L;

	while(1)
	{
		while(i < stop)
		{
			i++;
			pass_ary[i] = MIN_CHAR;
			step_ary[i] =(state1_ary[i] & 0x3f) + sum;
			xor_ary[i] = step_ary[i] * MIN_CHAR +(state1_ary[i] << 8);
			sum += MIN_CHAR;
			state1_ary[i + 1] = state1_ary[i] ^ xor_ary[i];
			state2_ary[i + 1] = state2_ary[i] + ((state2_ary[i] << 8) ^ state1_ary[i + 1]);
		}

		state1 = state1_ary[i + 1];
		state2 = state2_ary[i + 1];
		step =(state1 & 0x3f) + sum;
		xor1 = step * MIN_CHAR + (state1 << 8);
		xor2 =(state2 << 8) ^ state1;

		for(c = MIN_CHAR; c <= MAX_CHAR; c++, xor1 += step)
		{
			newstate2 = state2 + (xor1 ^ xor2);
			newstate1 = state1 ^ xor1;

			newstate3 = (targ2 - newstate2) ^ (newstate2 << 8);
			div = (newstate1 & 0x3f) + sum + c;
			diff = ((newstate3 ^ newstate1) - (newstate1 << 8)) & MASK;

			if(diff % div != 0) continue;

			d = diff / div;

			if(d < MIN_CHAR || d > MAX_CHAR) continue;

			div = (newstate3 & 0x3f) + sum + c + d;
			diff = ((targ1 ^ newstate3) - (newstate3 << 8)) & MASK;

			if(diff % div != 0) continue;

			e = diff / div;

			if(e < MIN_CHAR || e > MAX_CHAR) continue;

			pass_ary[i + 1] = c;
			pass_ary[i + 2] = d;
			pass_ary[i + 3] = e;

			return 1;
		}

		while(i >= 0 && pass_ary[i] >= MAX_CHAR)
		{
			sum -= MAX_CHAR;
			i--;
		}

		if(i < 0) break;

		pass_ary[i]++;
		xor_ary[i] += step_ary[i];

		sum++;

		state1_ary[i + 1] = state1_ary[i] ^ xor_ary[i];
		state2_ary[i + 1] = state2_ary[i] + ((state2_ary[i] << 8) ^ state1_ary[i + 1]);
	}

	return 0;
}

void crack(char *hash)
{
	int i, len;
	ULONG targ1, targ2, targ3;
	int pass[MAX_LEN];

	if(sscanf(hash, "%8lx%lx", &targ1, &targ2) != 2)
	{
		printf("Invalid password hash: %s\n", hash);
		return;
	}

	printf("Hash: %08lx%08lx\n", targ1, targ2);

	targ3 = targ2 - targ1;
	targ3 = targ2 -((targ3 << 8) ^ targ1);
	targ3 = targ2 -((targ3 << 8) ^ targ1);
	targ3 = targ2 -((targ3 << 8) ^ targ1);

	for(len = MIN_LEN; len <= MAX_LEN; len++)
	{
		printf("Trying length %d\n", len);

		if(crack0(len-4, targ1, targ3, pass))
		{
			printf("Found pass: ");

			for(i = 0; i < len; i++)
			{
				putchar(pass[i]);
			}

			putchar('\n');

			break;
		}
	}

	if(len > MAX_LEN)
	{
		printf("Pass not found\n");
	}
}

int main(int argc, char *argv[])
{
	int i;

	if(argc <= 1)
	{
		printf("usage: %s hash\n", argv[0]);
	}

	for(i = 1; i < argc; i++)
	{
		crack(argv[i]);
	}

	return 0;
}
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2007/02/07 01:03 2007/02/07 01:03
, ,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/69


블로그 이미지

빗소리를 먹는 사람.

- 장현준

Notices

Archives

Authors

  1. 장현준

Recent Trackbacks

  1. 듀얼클러치의 생각 rsvin28's me2DAY 2009

Calendar

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      

Site Stats

Total hits:
158014
Today:
84
Yesterday:
228