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;
}