[과제] /bin/level7 파일을 디버깅하여 의사코드를 만들어 보자.
level6 사용자 로그인
-> ID/PASS : level7/come together
$ cat hint
/bin/level7 명령을 실행하면, 패스워드 입력을 요청한다.
1. 패스워드는 가까운곳에..
2. 상상력을 총동원하라.
3. 2진수를 10진수를 바꿀 수 있는가?
4. 계산기 설정을 프로그래머용으로 바꾸어라.
$ ls -l /bin/level7
$ /bin/level7
올바르지 않은 패스워드 입니다.
패스워드는 가까운곳에...
--_--_- --____- ---_-__ --__-_-
$ /bin/level7
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
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("Congratulation! next password is \"break the world\".");
else
cat /bin/wrong.txt
$ wrong.txt
패스워드는 가까운곳에...
--_--_- --____- ---_-__ --__-_
의사코드
#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 이미지 파일을 마운트해서 확인할 수 있다.
'Learning > └보고서' 카테고리의 다른 글
Buffer overflow Attack Report (0) | 2017.01.30 |
---|---|
Egg Shell & Format String Bug & Buffer Overflow [FTZ LEVEL11] (0) | 2017.01.30 |
Forensics Tools Foremost Report (ppt첨부) (0) | 2017.01.23 |
Extundelete Tool report (0) | 2017.01.20 |