본문 바로가기

Learning/└보고서

암호학 분석 및 추측 의사코드 작성 [FTZ LEVEL7]

 

[과제] /bin/level7 파일을 디버깅하여 의사코드를 만들어 보자.




 

 

level6 사용자 로그인

-> ID/PASS : level7/come together

 

$ cat hint

/bin/level7 명령을 실행하면, 패스워드 입력을 요청한다.

 

1. 패스워드는 가까운곳에..

2. 상상력을 총동원하라.

3. 2진수를 10진수를 바꿀 수 있는가?

4. 계산기 설정을 프로그래머용으로 바꾸어라.

 

$ ls -l /bin/level7

-rws--x----          1   level8     level7        12312     8월     19    12:58   /bin/level7

 

 

$ /bin/level7

Insert The Password : 0000
올바르지 않은 패스워드 입니다.
    패스워드는 가까운곳에...
--_--_- --____- ---_-__ --__-_- 

 

$ /bin/level7

Insert The Password : mate

Congratulation! next password is "break the world".

 

■ 공격용 코드 개발

 

$ vi conversion.c

#include <stdio.h>

#include <string.h>


#define MAXARRAY 4


int binToInt(char *bin);


int main()

{

        int i, decimal[MAXARRAY];

        char *bin="--_--_- --____- ---_-__ --__-_-";

        char *ptr=bin;

        char dec[MAXARRAY*8];

        char ascii[MAXARRAY];

        char cmd[5]={"\n"};


        printf("Resvered signals : --_--_- --____- ---_-__ --__-_-\n");

        for(i=0; i<strlen(bin); i++)

        {

                if(*ptr == '-')       dec[i] = '1';

                else if(*ptr == '_')  dec[i] = '0';

                else if(*ptr == ' ')  dec[i] = '\0';    

                ptr++;

        }


        dec[i] = '\0';   

        printf("Changed binary : %s %s %s %s\n", &dec[0], &dec[8], &dec[16], &dec[24]);

                                                    

        printf("Changed decimal : ");

        for(i=0; i<MAXARRAY; i++)

        {

                decimal[i] = binToInt(&dec[i*8]);

                printf(" %d ", decimal[i]);

        }

        printf("\n");


        printf("Chaged ascii :");

        for(i=0; i<MAXARRAY; i++)

                printf(" %c ", decimal[i]);

        printf("\n");

 

      sprintf(cmd, "(printf \"%c%c%c%c\" ; cat) | /bin/level7", decimal[0], decimal[1], decimal[2], decimal[3]);       

                     

        system(cmd);

}


int binToInt(char *bin)

{

        int i=0;

        int count=0;


        while (bin[count])

                i=(i << 1) | (bin[count++] - '0');


        return i;

}

 

$ gcc -o conversion conversion.c

$ ./conversion

Resvered signals : --_--_- --____- ---_-__ --__-_-

Changed binary : 1101101 1100001 1110100 1100101

Changed decimal : 109 97 116 101

Chaged ascii : m a t e

<ENTER>

Insert The Password :

Congratulation! next password is "break the world".

<ENTER>

 

 

■ 복원 의사코드

$ gdb /bin/level7

(gdb) disas main
Dump of assembler code for function main:
0x08048454 <main+0>:    push   %ebp
0x08048455 <main+1>:    mov    %esp,%ebp
0x08048457 <main+3>:    sub    $0x8,%esp
0x0804845a <main+6>:    and    $0xfffffff0,%esp
0x0804845d <main+9>:    mov    $0x0,%eax
0x08048462 <main+14>:   sub    %eax,%esp
0x08048464 <main+16>:   sub    $0xc,%esp
0x08048467 <main+19>:   push   $0x64
0x08048469 <main+21>:   call   0x8048344 <malloc>
0x0804846e <main+26>:   add    $0x10,%esp


malloc(0x64)라는 코드가 실행되 힙 공간에 100바이트 만큼의 공간을 확보한다.


0x08048471 <main+29>:   mov    %eax,0xfffffffc(%ebp)
0x08048474 <main+32>:   sub    $0xc,%esp
0x08048477 <main+35>:   push   $0x80485c0                               “Insert The Password :"
0x0804847c <main+40>:   call   0x8048384 <printf>       문자열을 스택에 올리고 printf를 호출.

 

0x08048481 <main+45>:   add    $0x10,%esp

 

 

 

0x08048484 <main+48>:   sub    $0x4,%esp

0x08048487 <main+51>:   pushl  0x8049744             0과 100을 스택에 올리고 fgets 함수 호출.
0x0804848d <main+57>:   push   $0x64                  여기서 0은 STDIN을 의미한다.(Standard Input)
0x0804848f <main+59>:   pushl  0xfffffffc(%ebp)       즉, fgets(input, 0x64, STDIN) 코드가 실행되어
0x08048492 <main+62>:   call   0x8048354 <fgets>    패스워드를 100바이트까지 받는다는 것이다.
0x08048497 <main+67>:   add    $0x10,%esp
0x0804849a <main+70>:   sub    $0x4,%esp

 

0x0804849d <main+73>:   push   $0x4                    0x4를 스택에 올리고 mate라는 문자열을 스택에 올리고
0x0804849f <main+75>:   push   $0x80485d7              또 변수공간을 메모리에 올린다. 그 후,
0x080484a4 <main+80>:   pushl  0xfffffffc(%ebp)         strncmp(input, "mate", 0x4) 코드가 실행되어
0x080484a7 <main+83>:   call   0x8048364 <strncmp>  입력받은 값의 4자리가 “mate"인지 비교한다.
0x080484ac <main+88>:   add    $0x10,%esp             그런데 바로 앞에서 패스워드를 100바이트 까지
                                                     받을 수 있었으므로 가장 앞에서부터 4자리가 mate 이기만 하면
                                                     뒤에오는 문자들은 상관없이 무조건 패스워드를 얻는다.


0x080484af <main+91>:   test   %eax,%eax                  앞에서 입력한 문자열이 mate인지 아닌지 비교
0x080484b1 <main+93>:   jne    0x80484cd <main+121>  mate가 아닐 경우, main+121로 점프
0x080484b3 <main+95>:   sub    $0xc,%esp                 아닐 경우엔 그대로 이어서 진행.
0x080484b6 <main+98>:   push   $0x80485e0
0x080484bb <main+103>:  call   0x8048384 <printf>   main+75 "mate"를 입력했을 경우
0x080484c0 <main+108>:  add    $0x10,%esp           패스워드 출력
0x080484c3 <main+111>:  sub    $0xc,%esp            mate를 입력했을 경우
0x080484c6 <main+114>:  push   $0x0                     스워드를 출력하고 프로그램 종료
0x080484c8 <main+116>:  call   0x8048394 <exit>
0x080484cd <main+121>:  sub    $0xc,%esp            mate가 아닐 경우 121로 점프
0x080484d0 <main+124>:  push   $0x8048617            /bin/wrong.txt 파일 출력
0x080484d5 <main+129>:  call   0x8048334 <system>
0x080484da <main+134>:  add    $0x10,%esp
0x080484dd <main+137>:  leave
0x080484de <main+138>:  ret
0x080484df <main+139>:  nop
End of assembler dump.

 

■ 의사 소스코드

 

초기 단계 기본소스

            printf("Insert The Password : ");

        
            printf("Congratulation! next password is \"break the world\".");
            else
            cat /bin/wrong.txt

 

$ wrong.txt

올바르지 않은 패스워드 입니다.
    패스워드는 가까운곳에...
--_--_- --____- ---_-__ --__-_

 

의사코드

#include <stdio.h>
#include <malloc.h>

int main()
{
        char *input;
        char *pass = "mate";

        if((input = (char *)malloc(0x64)) == NULL)
        {
                printf("malloc() error\n");
                exit(1);
        }
        printf("Insert The Password : ");

        fgets(input, 0x64, stdin);
        if(strncmp(input, pass, 0x4) == 0)
        {
                printf("\nCongratulation! next password is \"break the world\".\n");
                exit(0);
        }
        system("cat /bin/wrong.txt");
        free(input);

        return 0;

 

 

■ 원본 소스코드

 

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main()
{
    char *str;
    str = (char *)malloc(100);
    printf( "Insert The Password : " );
    fgets( str, 100, stdin );

    if(strncmp( str, "mate", 4) == 0 ){
 printf( "\nCongratulation! next password is \"break the world\".\n\n" );
     exit(0);
    }
    system("cat /bin/wrong.txt");

 

원본 소스의 경로는 iso 이미지 파일을 마운트해서 확인할 수 있다.