password 파일을 gdb를 활요하여 어셈블리 언어로 변경했다. 아래 코드는 전체 파일에 대한 코드이다 


Dump of assembler code for function main:

0x8048430 <main>: push   %ebp

0x8048431 <main+1>: mov    %ebp,%esp

0x8048433 <main+3>: sub    %esp,0x40c

0x8048439 <main+9>: push   0x8048580

0x804843e <main+14>: call   0x8048370 <printf>

0x8048443 <main+19>: add    %esp,4

0x8048446 <main+22>: lea    %eax,[%ebp-1024]

0x804844c <main+28>: push   %eax

0x804844d <main+29>: call   0x8048330 <gets>

0x8048452 <main+34>: add    %esp,4

0x8048455 <main+37>: lea    %eax,[%ebp-1024]

0x804845b <main+43>: push   %eax

0x804845c <main+44>: call   0x8048350 <strlen>

0x8048461 <main+49>: add    %esp,4

0x8048464 <main+52>: mov    DWORD PTR [%ebp-1036],%eax


0x804846a <main+58>: cmp    DWORD PTR [%ebp-1036],0

0x8048471 <main+65>: jle    0x8048497 <main+103>

0x8048473 <main+67>: mov    %eax,DWORD PTR [%ebp-1036]

0x8048479 <main+73>: dec    %eax

0x804847a <main+74>: lea    %edx,[%ebp-1024]

0x8048480 <main+80>: cmp    BYTE PTR [%eax+%edx],0xa

0x8048484 <main+84>: jne    0x8048497 <main+103>

0x8048486 <main+86>: mov    %eax,DWORD PTR [%ebp-1036]

0x804848c <main+92>: dec    %eax

0x804848d <main+93>: lea    %edx,[%ebp-1024]

0x8048493 <main+99>: mov    BYTE PTR [%eax+%edx],0x0

0x8048497 <main+103>: lea    %ecx,[%ebp-1024]

0x804849d <main+109>: mov    DWORD PTR [%ebp-1028],%ecx

0x80484a3 <main+115>: mov    DWORD PTR [%ebp-1032],0x80495d8


0x80484ad <main+125>: lea    %esi,[%esi]

0x80484b0 <main+128>: mov    %eax,DWORD PTR [%ebp-1028]

0x80484b6 <main+134>: cmp    BYTE PTR [%eax],0x0

0x80484b9 <main+137>: je     0x80484e0 <main+176>

0x80484bb <main+139>: mov    %eax,DWORD PTR [%ebp-1032]

0x80484c1 <main+145>: cmp    BYTE PTR [%eax],0x0

0x80484c4 <main+148>: je     0x80484e0 <main+176>

0x80484c6 <main+150>: mov    %eax,DWORD PTR [%ebp-1028]

0x80484cc <main+156>: mov    %edx,DWORD PTR [%ebp-1032]

0x80484d2 <main+162>: mov    %al,BYTE PTR [%eax]

0x80484d4 <main+164>: cmp    %al,BYTE PTR [%edx]

0x80484d6 <main+166>: je     0x80484e2 <main+178>

0x80484d8 <main+168>: jmp    0x80484e0 <main+176>

0x80484da <main+170>: lea    %esi,[%esi]

0x80484e0 <main+176>: jmp    0x80484f0 <main+192>

0x80484e2 <main+178>: inc    DWORD PTR [%ebp-1028]

0x80484e8 <main+184>: inc    DWORD PTR [%ebp-1032]

0x80484ee <main+190>: jmp    0x80484b0 <main+128>

0x80484f0 <main+192>: mov    %eax,DWORD PTR [%ebp-1028]

0x80484f6 <main+198>: cmp    BYTE PTR [%eax],0x0

0x80484f9 <main+201>: jne    0x8048515 <main+229>

0x80484fb <main+203>: mov    %eax,DWORD PTR [%ebp-1032]

0x8048501 <main+209>: cmp    BYTE PTR [%eax],0x0

0x8048504 <main+212>: jne    0x8048515 <main+229>

0x8048506 <main+214>: push   0x8048591

0x804850b <main+219>: call   0x8048370 <printf>

0x8048510 <main+224>: add    %esp,4

0x8048513 <main+227>: jmp    0x8048522 <main+242>

0x8048515 <main+229>: push   0x80485af

0x804851a <main+234>: call   0x8048370 <printf>

0x804851f <main+239>: add    %esp,4

0x8048522 <main+242>: xor    %eax,%eax

0x8048524 <main+244>: jmp    0x8048526 <main+246>

0x8048526 <main+246>: leave  

0x8048527 <main+247>: ret    

0x8048528 <main+248>: nop    

0x8048529 <main+249>: nop    

0x804852a <main+250>: nop    

0x804852b <main+251>: nop    

0x804852c <main+252>: nop    

0x804852d <main+253>: nop    

0x804852e <main+254>: nop    

0x804852f <main+255>: nop    



입력받은 코드를 분석해보면 


0x8048430 <main>: push   %ebp

0x8048431 <main+1>: mov    %ebp,%esp   

프롤로그를 표현한다.



0x8048433 <main+3>:         sub    %esp,0x40c

0x8048439 <main+9>:         push   0x8048580

0x804843e <main+14>: call   0x8048370 <printf>

0x8048443 <main+19>: add    %esp,4


sub로 저장할 위치를 확보하고 push후 printf 하는걸 보니 전역 변수 1036 바이트를 확보한후 printf 하는걸 확인할 수 있다.

0x8048580 값을 확인해 보면




 "input password: " 패스워드를 입력받는 문자열이 출력된다


지금까지 확인된 정보는 전역 변수 .지역 변수가 몇개 인지는 모르지만 총 1036 바이트의 저장공간을 확보했고 


int main(){

printf("Input password");

}

프린트 문장이 하나 출력되는걸 알 수 있다. 

0x8048446 <main+22>: lea    %eax,[%ebp-1024]

0x804844c <main+28>: push   %eax

0x804844d <main+29>: call   0x8048330 <gets>

0x8048452 <main+34>: add    %esp,4


lea로 주소를 불러오고 push 후 call로 gets 함수를 부르는걸 확인해보니 아마 1024 바이트를 사용하는 지역변수를 입력받는 부분같다

입력받은 값들이 1024 부터 저장되는걸 보니까 배열로 입력받는거 같다 


0x8048455 <main+37>: lea    %eax,[%ebp-1024]

0x804845b <main+43>: push   %eax

0x804845c <main+44>: call   0x8048350 <strlen>

0x8048461 <main+49>: add    %esp,4

0x8048464 <main+52>: mov    DWORD PTR [%ebp-1036],%eax

ebp-1024의 위치 주소를 가지고오고 strlen 을 하는거 보니 입력받은 배열의 길이를 ebp-1036에 저장한다

지금까지 C언어로 확인하면 크기가 1024인 배열이 하나 있는거 같고 그 배열의 길이를 저장하는 int형 변수가 있다. 


int main(){

?[bufffer] =1024;  //[ebp-1024]

?...                   //[ebp 1024~1036]

int length= //[ebp-1036]

int length=strlen(buffer);

printf("Input password");

}



0x804846a <main+58>: cmp    DWORD PTR [%ebp-1036],0

0x8048471 <main+65>: jle    0x8048497 <main+103>


0x8048473 <main+67>: mov    %eax,DWORD PTR [%ebp-1036]

0x8048479 <main+73>: dec    %eax

0x804847a <main+74>: lea    %edx,[%ebp-1024]

0x8048480 <main+80>: cmp    BYTE PTR [%eax+%edx],0xa

0x8048484 <main+84>: jne    0x8048497 <main+103>


0x8048486 <main+86>: mov    %eax,DWORD PTR [%ebp-1036]

0x804848c <main+92>: dec    %eax

0x804848d <main+93>: lea    %edx,[%ebp-1024]


0x8048493 <main+99>: mov    BYTE PTR [%eax+%edx],0x0


0x8048497 <main+103>: lea    %ecx,[%ebp-1024]

0x804849d <main+109>: mov    DWORD PTR [%ebp-1028],%ecx

0x80484a3 <main+115>: mov    DWORD PTR [%ebp-1032],0x80495d8


두개의 조건일때 같은 곳으로 지목하는걸 보니까 다중 조건문일 가능성이 크다/


조건 && 조건  인걸 확인 할 수 있다.

0x804846a <main+58>: cmp    DWORD PTR [%ebp-1036],0

0x8048480 <main+80>: cmp    BYTE PTR [%eax+%edx],0xa


if (length > 0 && buffer[length] == '\n'){

length--;

buffer[length]=0;

}

뉴라인을 제거하는 코드 같다.


0x8048497 <main+103> 라인을 보면 

[ebp-1024] 의 값을 ebp-1028에 저장하고 0x80495d8 에 있는 값을 [%ebp-1032] 여기에 저장한다.

배열로 입력받은 값을 ebp-1028에 저장하고 

0x80495d8의 값을   ebp-1032에 저장한다.

여기서 얻은 내용으로 C언어를 작성하면 


pwd="th3p4ssw0rd"

int main(){

char [bufffer] =1024;  //[ebp-1024]

char *p                   //[ebp-1028]

char *q                  //[ebp -1032]

int length= //[ebp-1036]

printf("Input password");

gets(buffer);

int length=strlen(buffer);

if (length > 0 && buffer[length] == '\n'){

length--;

buffer[length]=0;

}

p=buffer;

q=pwd ;


}

0x80484ad <main+125>: lea    %esi,[%esi]

0x80484b0 <main+128>: mov    %eax,DWORD PTR [%ebp-1028]  // p의 값을 eax에 저장

0x80484b6 <main+134>: cmp    BYTE PTR [%eax],0x0   //  eax에 저장된 값이 0이면 0x80484e0 이동

0x80484b9 <main+137>: je     0x80484e0 <main+176>

0x80484bb <main+139>: mov    %eax,DWORD PTR [%ebp-1032] //q의 값을 eax 에 저장 

0x80484c1 <main+145>: cmp    BYTE PTR [%eax],0x0 // 0이면  0x80484e0 이동

0x80484c4 <main+148>: je     0x80484e0 <main+176>


0x80484c6 <main+150>: mov    %eax,DWORD PTR [%ebp-1028]     //eax에 p의 값을 저장

0x80484cc <main+156>: mov    %edx,DWORD PTR [%ebp-1032]    //edx에 q의 값을 저장 

0x80484d2 <main+162>: mov    %al,BYTE PTR [%eax]                   //eax값을 al로 저장 

0x80484d4 <main+164>: cmp    %al,BYTE PTR [%edx]                   //즉 p의 값과 q의 값을 비교하고  

0x80484d6 <main+166>: je     0x80484e2 <main+178>                //같으면 0x80484e2 이동 

0x80484d8 <main+168>: jmp    0x80484e0 <main+176>              // 다르면 0x80484e0이동 



0x80484da <main+170>: lea    %esi,[%esi]

0x80484e0 <main+176>: jmp    0x80484f0 <main+192>    //jmp 192로 이동한다

0x80484e2 <main+178>: inc    DWORD PTR [%ebp-1028]  //p값을 1증가

0x80484e8 <main+184>: inc    DWORD PTR [%ebp-1032]  //q값을 1증가 

0x80484ee <main+190>: jmp    0x80484b0 <main+128>   // 반복문 실행


while(*p != 0 && *q ! = 0 && *p=*q ){

p++;

q++;

}


0x80484f0 <main+192>: mov    %eax,DWORD PTR [%ebp-1028]   // p값을 eax에 대입

0x80484f6 <main+198>: cmp    BYTE PTR [%eax],0x0                  //값이 0이 아니면 

0x80484f9 <main+201>: jne    0x8048515 <main+229>              //229로 이동 

0x80484fb <main+203>: mov    %eax,DWORD PTR [%ebp-1032]  //q값을 eax에 대입하고 

0x8048501 <main+209>: cmp    BYTE PTR [%eax],0x0                //값이 0이 아니면

0x8048504 <main+212>: jne    0x8048515 <main+229>            //역시 229로 이동한다

p,q의 값이 0을 가리키고 있으면 성공하는 문장이 출력되고 

0x8048506 <main+214>: push   0x8048591  

           

0x804850b <main+219>: call   0x8048370 <printf>

0x8048510 <main+224>: add    %esp,4

0x8048513 <main+227>: jmp    0x8048522 <main+242>

0x8048515 <main+229>: push   0x80485af            

아니면 실패하는 문장을 출력하고 프로그램이 종료된다

0x804851a <main+234>: call   0x8048370 <printf>

0x804851f <main+239>: add    %esp,4

0x8048522 <main+242>: xor    %eax,%eax  //eax를 초기화 하고 

0x8048524 <main+244>: jmp    0x8048526 <main+246>

0x8048526 <main+246>: leave  

0x8048527 <main+247>: ret    


if( *p == 0 && *q == 0 )

{

  printf("Congratulations! You got it!\n"

} else if

  {

    printf("Oops! wrong password! : -P\n"

  }


이제 내용을 종합해 보면

#include <stdio.h>

char pwd[]="th3p4ssw0rd";

//char *pwd ="th3p4ssw0rd";

int main()

{

char buffer[1024];  //[ebp-1024]

char *p;                   //[ebp-1028]

char *q;                  //[ebp -1032]

int length; //[ebp-1036]

printf("Input password:");

gets(buffer);

length=strlen(buffer);

if (length > 0 && buffer[length] == '\n'){

length--;

buffer[length]=0;

}

p=buffer;

q=pwd ;

while(*p != 0 && *q != 0 && *p==*q ){

p++;

q++;

}

if (*p==0 && *q==0){

        printf("Congratulations! You got it\n");

}

else{

        printf("Oops! wrong password! :-p\n");

}

return 0;

}



+ Recent posts