FTZ를 리버싱의 주제로 선정한 이유는 FTZ에 각 LEVEL 에서 사용하는 소스의 목적을 분석하고
그에 맞는 의사 코드를 gdb를 이용해 디버깅하여 리버싱을 통해 복원해보는 과정을 주로 다루며
원본 코드 소스와 비교 해보는 과정을 학습하기 위함이다.
최종 목적은 level15이후의 버퍼 오버 플로우를 공부하고 그 단원의 코드를 분석해보는 것에 있다.
참고자료
Reverse Engineering on HackMe System
학습목표
■ 리버싱을 통한 의사 코드(가상 코드) 생성
■ exploit 코드 개발
상대편의 취약성을 공격하는 코드
HackMe(ftz.hackerschool.org)
참고 사이트 :
http//inhack.org/wordpress/?cat=68 문제 풀이에 대한 참고 사이트
http://www.codeengn.com/ (Google Search : site:codeengn.com intext:index.of.)
■ 학습 목적
- 메모리 구조에 대한 이해
- SetUID/SetGID/Sticky Bit 이해
- gdb 기본 사용법
(1) 운영체제 기본 정보 확인
[level1@ftz level1]$ cd tmp
[level1@ftz tmp]$ cat /etc/redhat-release
Red Hat Linux release 9 (Shrike) |
[level1@ftz tmp]$ uname -a
Linux ftz.hackerschool.org 2.4.20-8smp #1 SMP Thu Mar 13 16:43:01 EST 2003 i686 athlon i386 GNU/Linux |
[참고] Redhat 계열의 운영체제 버전 발전 과정
RedHat 6.X -> RedHat 7.X -> RedHat 8.X -> RedHat 9.X
-> RHEL 2.X -> RHEL 3.X -> RHEL 4.X -> RHEL 5.X -> RHEL 6.X -> RHEL 7.X
[참고] 리눅스 커널 버전에 대해서
Kernel 2.2.X -> Kernel 2.4.X -> Kernel 2.6.X
#include <stdio.h> #include <stdlib.h> int retVal = 0; int outVal; int main(void) { char string[] = "hello"; char *ptr; static int output = 1; ptr = (char *)malloc(sizeof(string));
printf("%s\n", string); return retVal; } |
의미없는 구문이다.
$ cd tmp
$ vi hello.c
$ gcc -o hello hello.c
$ ./hello
hello
$
■ Terms
CPU <------> MEM <------> DISK
■ 메모리 구조
-
Text
함수의 Code값이 위치하는 부분 -
Data
전역 변수가 위치한 Data 영역과 정적 변수가 위치한 BSS 영역으로 나뉜다. -
Heap
저장공간으로 사용, malloc이라는 함수로 메모리 공간을 확보 했을 때 할당된다.
동적할당을 할 때 사용, 메모리의 효율성이 가장 좋다. -
Stack
먼저 들어간게 나중에 나오는 거꾸로 된 구조
일반적으로 지역함수, 함수의 인자값, 복귀 조수 등이 위치, CPU에서 접근 속도가 가장 빠름.
■ 인자가 전달되는 방식의 예제
$ vi structure.c
#include<stdio.h> void function(int a, int b, int c) { char buffer1[5]; char buffer2[10]; } int main() { function(1,2,3); return 0; } |
$ gcc -o structure structure.c
$ ./structure
$ echo $?
■ gdb를 통해 structure 프로그램을 disassembly 해보기
(용어) 어셈블리어(Assembly)언어
■ 기계어 : CPU의 명령어(전기신호)를 숫자로 표현한 것
-> CPU의 명령어는 CPU제조회사에서 일정한 규칙을 두고 정한다.
■ 어셈블리 언어: CPU와 직접 대화 할 수 있는 언어(명령어의 집합)
disassembly ?
커널이 인식할수 있는 바이너리 형태로 만드는 과정 -> 컴파일
바이너리 형태를 C언어 형태로 만드는 과정 -> 디컴파일
어셈블리 언어란
1과 0으로 되어있는 코드는 분석,수정이 힘들다.
언어형태를 취할수 있게 변환하는 과정
바이너리 코드와 동일한 포맷
$0xfffffff0 ---->어셈블리 ---> 보기좋게 출력
보기좋은 출력값 ---->디스어셈블리 ---> $0xfffffff0
해석하기 어려운 코드를 어셈블리언어 형태에서 다시 c형태로 변환
$ gdb structure (gdb : GNU debugger)
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux-gnu"... (gdb) disassemble main Dump of assembler code for function main: 0x080482fc <main+0>: push %ebp 0x080482fd <main+1>: mov %esp,%ebp 0x080482ff <main+3>: sub $0x8,%esp 0x08048302 <main+6>: and $0xfffffff0,%esp 0x08048305 <main+9>: mov $0x0,%eax 0x0804830a <main+14>: sub %eax,%esp 0x0804830c <main+16>: sub $0x4,%esp 0x0804830f <main+19> : push $0x3 function(1,2,3); = $0x3,2,1 이다. 0x08048311 <main+21>: push $0x2 0x08048313 <main+23>: push $0x1 0x08048315 <main+25>: call 0x80482f4 <function> 순서대로 함수호출, 변수의 선언 및 초기화하는 작업 수행 0x0804831a <main+30>: add $0x10,%esp 함수호출시 순서대로 나오기 때문에 거꾸로 들어가야한다. 0x0804831d <main+33>: mov $0x0,%eax 0x08048322 <main+38>: leave 0x08048323 <main+39>: ret End of assembler dump. (gdb) |
-
인자값을 a=3 할당하고, b=2 할당하고, a=1 할당한다.
-
스택(Stack)은 지역변수가 쌓일수록 메모리의 낮은 주소 방향으로 데이터가 쌓이는 특이한 구조이다.
■ 위의 내용에 대한 해석
1 (gdb) disassemble main
main 함수를 disassemble(binary -> assembley) 한다.
2 Dump of assembler code for function main:
main 함수의 assembler가 덤프를 시작한다.
3 0x080482fc <main+0>: push %ebp
EBP 내용을 stack 주소를 넣는다.(최초의 프레임 포인터(ebp) 값을 스택에 저장한다.)
ebp 바로 전에 ret(return address)가 저장된다.
ebp(extended base pointer)는 함수 시작 전의 기준점이 된다.
스택에 저장된 ebp를 SFP(Saved Frame Pointer)라고 부른다.
ret(return address)에는 함수 종료시 점프할 주소값 저장
4 0x080482fd <main+1>: mov %esp,%ebp
현재 esp 값을 ebp 레지스터에 저장한다.
"push %ebp", "mov %esp %ebp"는 새로운 함수를 시작할 때 항상 똑같이 수행하는 명령으로 프롤로그(Prologue)라고 부른다.
5 0x080482ff <main+3>: sub $0x8,%esp
esp 레지스터 가리키는 주소에서 0x8만큼 주소를 뺀다.
일반적으로 변수를 설정할수 있는 공간을 확보 하는것이다.
변수의 종류(예: char or int)와 개수에 따라서 빼는 값이 틀려진다.
'Learning > └◆Reversing' 카테고리의 다른 글
[참고]어셈블리어의 기본 문법과 명령 (0) | 2017.01.19 |
---|---|
[참고]어셈블리 언어에 대해서_2 (0) | 2017.01.19 |
[참고]어셈블리 언어에 대해서 (0) | 2017.01.19 |
02_level1 -> level2[FTZ] 백도어에 대한 이해와 디버깅 동작 (2) | 2017.01.18 |