Rainbow Table

CR@K 이야기 2013. 4. 22. 22:24 Posted by TEAMCR@K

2012년 연말을 기점으로 저희 팀에 새 식구가 하나 늘었습니다.


동수?.....

는 아니고요...


Buffalo NAS 장비 입니다.

아래 보이는 바로 요 놈 입니다.


Buffalo NAS 장비


요 NAS 장비는 총 12TB 정도의 여유를 가지고 있습니다.

이 여유공간을 어떻게 활용할까 곰곰히 생각해 보다가 Rainbow Table로 일부 활용 해 보기로 했습니다.


DB Schema를 작성하고, DBMS를 구동하고

또 쉼 없이 데이터를 생성하는 프로그램도 작성해서 돌려봅니다.

데이터 작성만 해서는 의미가 없습니다.

작성된 데이터를 활용해 웹에서 해시를 검색하는 웹 UI도 만들어 봅니다.


아래는 만들어진 Rainbow 테이블을 서치 해 볼 수 있는 화면입니다.



일반 평문은 약 3억개 정도이며 각 해시 데이터들이 그 뒤를 잇고 있습니다.

평문에 먼저 데이터를 쌓도록 해 놓은 것이 주로 알파벳 26자와 숫자로 이루어진 단어들이며, 후일에 숫자만으로 된 데이터들도 추가했습니다.

현재 숫자 데이터는 8자리 숫자 데이터까지 검색 가능합니다.


이렇게 써 보다가 약간은 불편한게 생겼습니다.

해시 데이터가 다수 일 때...

물론 삽질을 좋아하는 누군가는 일일이 하나하나의 해시를 검색하고 그 결과를 보는것으로 만족 할 지 모릅니다.

하지만 역시 불편합니다.

그래서 해시 데이터를 파일로 업로드하여 검색하는 기능도 추가했습니다.


일단 해당 기능을 테스트 하기 위해 일반 단어사전을 생성합니다.

리눅스에 기본적으로 존재하는 단어사전에서 그 단어들을 100개 정도 추립니다.



이것을 기준으로 약 100개의 SHA-1 해시를 생성해 봅니다.



해당 데이터를 웹에 업로드 하여 테스트 해 봅니다.



DB에서 찾을 수 있는 해시보다 찾지 못하는 해시가 아직은 더 많습니다.


아래는 레인보우 테이블을 생성하는 코드 중 일부입니다.


>>> snip <<<


pthread_t threads[MAX_THREAD];

int is_interrupt = -1;

int is_pause = -1;

int is_failed = -1;


unsigned char lower_case[] = {

    'a','b','c','d','e','f','g','h','i','j',

    'k','l','m','n','o','p','q','r','s','t',

    'u','v','w','x','y','z', '\0'

};

unsigned char upper_case[] = {

    'A','B','C','D','E','F','G','H','I','J',

    'K','L','M','N','O','P','Q','R','S','T',

    'U','V','W','X','Y','Z', '\0'

};

unsigned char number_case[] = {

    '0','1','2','3','4','5','6','7','8','9', '\0' // 10

};

unsigned char special_case[] = {

    '`','~','!','@','#','$','%','^','&','*',

    '(',')','-','_','=','+','[','{',']','}',

    '\\','|',';',':','\'','"',',','<','.','>',

    '/','?', '\0'

};


unsigned char base[128];


>>> snip <<<


        memset(init_pass, 0x00, sizeof(init_pass));


        for(i = s; i < e; i++) {
            max += pow(count, i) + 0.0;
        }

        for(i = 0; i < max + s; i++) {
            j = 0;
            while(base[j] != '\0') {
                memset(pass, 0x00, sizeof(pass));
                init_pass[sizeof(init_pass) - 1] = init_pass[sizeof(init_pass) - 1] + 1;
                idx = 0;
                for(k = 0; k < sizeof(init_pass); k++) {
                    if(init_pass[k] != '\0') {
                        if(base[init_pass[k] - 1] == '\'') {
                            pass[idx] = '\\';
                            idx++;
                        }
                        if(base[init_pass[k] - 1] == '\\') {
                            pass[idx] = '\\';
                            idx++;
                        }
                        pass[idx] = base[init_pass[k] - 1];
                        idx++;
                    }
                }
                //fprintf(stdout, "[%.0f] Pass: %s\n", total, pass);
                snprintf(sql, sizeof(sql), "INSERT INTO %s(value) VALUES('%s')", info->tblname, pass);
                j++;
                total++;
                if(mysql_query(conn, sql)) {
                    //fprintf(stdout, "%s\n", mysql_error(conn));
                    continue;
                }
            }
>>> snip <<<


지속적으로 데이터를 축적해 나가다 보면 언젠가는 쓸만한 레인보우 테이블이 될 것 같습니다.