본문 바로가기

Hacked Brain/심심한 프로그래밍

유닉스 crack

 

유닉스 패스워드 크랙프로그램 과 패스워드 암호화의 원리


대부분의 크랙 프로그램은 crypt()함수를 많이 이용한다.

crypt()함수는 salt 키와 패스워드를 제공하면 암호화 시킨다.

역암호화 알고리즘이 존재하지도 않는데 어떻게 암호화 된 패스워드를

풀수 있을까?... 음...

크랙프로그램의 원리를

shadow 패스워드가 " 3tqNGDFbEOk1s " 가 있다고 하면,

크랙 프로그램은 단어 사전 파일을 준비한다.

들어가는 단어들로 이루어져 있는데, 예를 들면,

a
aa
aaa
aaaa
abc
across
auto
......
.......
z
zz
zzz
zoo
..

이런식으로 영단어 처음부터 나온다.(사전이 좋을수록 손쉽게 찾을수 있다.)

그러면 크랙 프로그램은 crypt() 함수에 위의 한줄에 한단어씩 넣어서 암호화된

패스워드를 만들어 " 3tqNGDFbEOk1s " 와 비교한다.

틀리면 다음 단어... 이런식으로 루프를 돌게 된다.

이게 바로 크랙 프로그램의 기본적인 동작이다.


간단한 크랙소스를 보자.

crypt 함수의 사용법.(man 페이지를 보면 알수 있다.)

char *crypt(const char *key, const char *salt);

salt 키는 암호화 할때 넣는 임시 변수로 값이 어떤것을 넣느냐에 따라

암호화된 패스워드가 달라진다.

일반적으로 암호화 된 패스워드의 맨 앞부분 두개 문자가 salt 키가 된다.

위에서 선보인 암호화된 패스워드를 살펴보면....(계속 나올꺼에요.)

" 3tqNGDFbEOk1s " 에서 salt 키는 "3t" 가 된다.

실제 프로그래밍 할때는 crypt("패스워드","3t");이런식이 된다.


[소스]


#include <unistd.h>
 
main(int argc, char **argv) // 입력을 받죠.
{

    char buf[1024]; // 버퍼
 
    if ( argc < 2 ) { // 인수가 잘못되면, 에러메세지
        printf("usage: %s password salt_key\n",argv[0]);
        exit(1);
    }
 
    strcpy(buf,crypt(argv[1],argv[2])); // crypt 함수 결과를 버퍼에 넣고

    printf("crypt [%s] => %s \n",argv[1],buf); // 출력합니다.
}

이코드는 패스워드를 처음인수로, 두번째 인수를 salt키를 받는다.


이번엔 간단한 크랙프로그램을 만들어보면,


먼저, salt 키와 암호화된 패스워드가 있어야된다.

암호화 된 패스워드 : 5tYu1ywBg8xf2
->  salt  키 : 5t

패스워드자리수 : 4
이정보를 이용해서 크랙프로그램을 만들어 보자.


/*
 * 4 자리 숫자 크랙 프로그램
*/
 
#include <unistd.h>
 
main(int argc, char **argv)
{
    int count;
    char buf[5];
 
    for ( count=1000 ; count < 10000 ; count++ ) { // 4자리수니까 1000~9999까지
        sprintf(buf,"%d",count);

        if( !strcmp("5tYu1ywBg8xf2", (char *)crypt(buf, "5t")) ) {//비교한다. 같으면
            printf("password crack success : %d \n",count );
            break;
        }
    }
}

너무간단하지않나 ^^

역시 숫자로만 이용한 패스워드 크랙은 정말 간단하게된다.

자리수가 늘어나고, 글자까지 포함하면, 점점 복잡해지게 되지만, 결국은 같은 원리.


사전을 이용한 크랙은 어떨까?


이번에는 새로운 암호화된 패스워드를 얻었습니다.

"99u5LyKkDNKgk"   <= 주의 대소문자를 잘 구분하세요. K 와 k 를.. ^^;


#include <stdio.h>
#include <unistd.h>
 
main(int argc, char **argv) // 이건 같다.
{
 
    char word[81],buf[20]; // 버퍼,
    FILE *fp; // 사전을 가져와야 하니까 파일 포인터
 
    if ( argc < 2 ) { // 에러 메세지
        printf("usage : %s 단어사전\n",argv[0]);
        exit(0);
    }
 
    fp = fopen(argv[1],"r");    // 파일을 열고
    if ( !fp ) { // 에러처리
        perror("open error");
        exit(0);
    }
 
    while ( 1 ) { // 루프,

        if ( fscanf(fp,"%s",word)  < 0)       // 사전에서 단어를 찾고,

  {       
            printf("실패..\n");
            break;
        }

        strcpy(buf,(char *)crypt(word,"99"));  /* 암호화    */
 
        if( !strcmp("99u5LyKkDNKgk",buf) )     /* 비교 */
      {         
            printf("패스워드 : %s \n",word );
            break;
        }
    }
 
    fclose(fp);
    exit(0);
}