농소
바이너리 분석 연습 본문
리버싱을 통해 해당 실행파일의 패스워드를 찾기위한 연습을 진행한다.
실행을 해 보았더니 패스워드를 입력하라는 input이 호출되고
아무번호나 입력했더니 wrong password라는 false를 반환한다.
true값을 반환받기 위해 이 파일을 분석해 보겠다.
우선 gdb로 바이너리를 asm로 변환시킨 모습이다.
자 이제부터 처음부터 차근차근 분석 해 보겠다.
1
우선 프롤로그를 설정해 주었고, printf를 calll하고 있는걸 봐선 앞에 push값은
주소값을 보아 segment영역 일 것이고 전역변수인 것을 알 수 있다.
확인해 보았더니 Input password: 라는 문자열이 나왔다.
이 과정을 c로 변환해 보면
int main()
{
printf("Input password: ");
return 0;
}
자료형은 아직 알순없다. 더 추가적인 정보가 있어야 확인가능하다 또 변수이름은 확인 불가능하다.
2
[ebp-1024]주소를 eax레지스터 에 선언하고 그 값을 push, gets함수를 call하고
입력받은 문자열을 ebp-1024에 초기화 하였다.
그리고 입력받은 값을 strlen함수를 돌려 길이를 반환하여 그것을 ebp-1036에 초기화 하였다.
c언어
int main()
{
char buffer[1024]; or 256 or 128 // [ebp-1024]
? unknown // [ebp-1028 ~ 1032]
int len; // [ebp-1036]
fgets(buffer);
len = strlen(buffer);
return 0;
}
아직 지역변수들의 자료형은 알 수 없고, strlen을 1036에 받는걸로 보아 자료형이 int임을 알 수 있다.
3
cmp 가 들어가는것을 봐선 분기나 조건중 하나 일 것이다.
허나 jmp로 되돌아가는게 없는걸로 봐선 이 cmp는 조건문에 쓰이는 것을 알 수있다.
그리고 조건문이 2개나 되는데 조건실행후 동작하는 내용과 jmp가
동일한 위치에서 떨어지는걸 봐선 다중조건임을 알 수 있다.
조건문이 끝나고 해당 문자열 주소를 ebp-1028에 넣고 어떠한 값을 ebp-1032에 넣고 있다.
이 값이 무엇인지 확인해 보면
실제 패스워드를 ebp-1032에 넣고있다. 아마 이것을 입력해야 true를 뱉고 아니라면 false를 반환할 것이다.
c언어
char buffer[1024] // [ebp-1024]
???* a; // [ebp-1028]
???* b; // [ebp-1032]
int len; // [ebp-1036]
if(len > 0 && buffer[len-1] == '\n') {
buffer[len-1] = 0;
}
a = buffer;
b = pwd;
1바이트씩 읽어 나감을 확인 했으므로 buffer의 자료형은 char일 것이고,
주소값을 변수에 넣는걸로봐선 포인터변수임을 알 수 있다.
4
cmp명령어가 여러개가 있고 끝에 다시 되돌아오는 jmp문이 존재하기 때문에 반복문임을 알 수있다.
또 jmp문이 모두 하나로 이어지므로 다중조건임을 알 수 있다.
[ebp-1028] 과 [ebp-1032] 를 서로 비교할때 al로 변환 한것을 보면 자료형이 char인것을 알 수 있다.
c언어
while( *a != 0 && *b != 0 && *a == *b)
{
a++;
b++;
}
입력한 buffer와 pwd를 1 바이트씩 비교해나가고 있다.
buffer와 pwd가 일치하면 결과적으로 a와b 에 0이 담겨있을 것이고
다르면 해당 주소에 서로 다른 문자가 들어있을 것이다.
5
두번의 cmp가 있는데 각각 cmp 마다 전역변수를 push하는데 그 값을 알아보면
*a와 *b를 각각 0과 비교하여 같지않으면 false레이블로 jmp하고 같다면 true레이블로 jmp 한다.
이번에도 cmp가 같은위치로 jmp하고 있으므로 다중구문 이고
중간에 false를 피하기위해 jmp 하므로 if~else구문일 것임을 알 수 있다.
c언어
if( *a == 0 && *b == 0 )
{
printf("Congratulations! You got it!\n"
} else if
{
printf("Oops! wrong password! : -P\n"
}
결과
#include <stdio.h>
char pwd[] = "th3p4ssw0rd";
int main()
{
char buffer[1024]; // ebp-1024
char* a; // ebp-1028
char* b; // ebp-1032
int len; // ebp-1036
printf("Input password: ");
fgets(buffer);
len = strlen(buffer);
if(len > 0 && buffer[len-1] == '\n') {
buffer[len-1] = 0;
}
a = buffer;
b = pwd;
while( *a != 0 && *b != 0 && *a == *b ) {
a++;
b++;
}
if (*a == 0 && *b == 0){
printf("Congratulations! You got it!\n");
}else {
printf("Oops! wrong password! :-P\n");
}
return 0;
}
<해당 실행파일을 c로 변환해본 모습>
올바른 패스워드를 입력했더니 true값을 반환받았다.
'Security > System Hacking' 카테고리의 다른 글
쉘코드 기계어 제작, 메모리 강제 삽입 (0) | 2018.02.02 |
---|---|
버퍼 오버플로우(Buffer Overflow), 취약점 (0) | 2018.01.31 |
디버거 GDB 사용법 (0) | 2018.01.26 |
시스템 프로그래밍, 시스템 콜 (0) | 2018.01.25 |
asm 지역변수 배열, main 함수의 인자 int argc, char *argv[ ] (0) | 2018.01.24 |