1. 환경 설정
1) Red Hat Linux 6.2
- 부팅시 LILO BOOT에서 linux-up 입력
2) telenet 이용 방법
>> /etc/securetty
pts/0 ~ pts/8 추가
>> /etc/pam.d/login
둘째줄 주석처리
#auth required /lib/security/pam_securetty.so
3) NASM 설치 및 다운로드
#wget http://www.nasm.us/pub/nasm/releasebuilds/0.99.05/nasm-0.99.05.tar.gz
#tar xvfz nasm-0.99.05.tar.gz
#cd nasm-0.99.05.tar.gz
#./configure
#make
#make install
#cp nasm /usr/bin
2. 사용되는 도구들
- C컴파일러: GCC(GNU C Compiler)
- 어셈블러 : GAS(GNU Assembler) - AT&T 문법
NASM(Netwired Assembler) - AT&T, INTER 문법을 지원한다.
- 디버거 : GDB(GNU DeBugger) - 바이너리 분석 디버거
3. C 프로그램(컴파일)
- windows 환경 : visual studio. eclips, ... etc
- IDE : 통합 개발 환경, 주로 컴파일러 + 편집기 + 디버거가 결합된 형태
(visual studio는 compiler가 아니라 compiler가 포함된 IDE)
- linux 환경: compiler(GCC), editor(VI,VIM), debugger(GDB)
- C 파일이 실행파일이 되는 과정은 아래와 같다.
hello.c -> hello.i -> hello.s(asm) -> hello.o -> hello
간단히 hello.c를 작성해보자.
1 2 3 4 5 6 7 8 | #include <stdio.h> int main() { printf("Hello, World!!!\n"); return 0; } |
# gcc hello.c
- 이름 옵션(-o)를 사용하지 않으면 기본 파일면은 a.out으로 나온다.
# ./a.out
Hello, World!!!
4. 컴파일 과정
# gcc -v 소스파일.c : 소스파일 컴파일 과정을 보여준다.
1) 전처리 단계 - cpp(C PreProcess /tmp/ccg9MiUY.i) -save-temps
- hello.c -> hello.i
- 매크로, 해더파일이 처리된다.
2) 컴파일 단계 - cc1
- hello.i -> hello.s
- 어셈블리 언어로 변환
어셈블리 언어로 변환하는 이유는 C언어가 바로 기계어로 변환되지 못하기 때문이다.
바이너리(실행파일)은 0,1로 이루어진 파일이다. 사람이 바이너리 파일을 직접 만드는것은 어렵기 때문에
소스를 작성해 어셈블리 언어로 변환한 후 컴파일러에 의해 자동 기계어로 변환된다.
또한, 어셈블리언어는 기계어에 일대일 대응하기 때문에 사용된다.
GAS는 .s, NASM은 .asm 확장자를 사용한다.
3) 어셈블러 단계 - as(GAS)
- hello.s -> hello.o
- 어셈블리 -> 기계어
- object 파일로만은 라이브러리 파일에 있는 함수를 사용할 수 없다.
- 어셈블리 언어를 바이너리(0,1)형태로 바꿔주는 과정
4) 링크 단계 - collect2, ls, gcc (일반적으로 dynamic-linker 사용)
- hello.o -> hello
- object 파일을 가지고 여러가지 라이브러리를 합쳐서 하나의 바이너리를 만든다.
* 만일 우리가 파일을 C 언어로 작성하지 않고 어셈블리로 작성하면, 1), 2)단계가 생략되고, 3),4)단계만 진행된다.
hello.c 는 단지 C언어로 작성된 파일이기 때문에 text파일이지 실행할수있는 바이너리 파일은 아니다.
hello는 컴파일 후 생긴 바이너리 파일이다. window 환경에서 exe파일을 linux환경에서 ELF 파일이라고 한다.
따라서 hello는 실행할 수 있는 elf 파일이다.
컴파일 과정을 좀 더 자세히 알아보기 위해 hello1.c를 만들어보자.
#define NUMBER 1000이 어떻게 처리되는지 알아보자.
# gcc -E -o hello.i hello.c(전처리 단계)
# gcc -S -o hello.s hello.c(컴파일 단계)
위 명령어를 통해 .i .s .o파일을 만들 수 있다.
전처리 과정을 통해 hello1.i 파일에서 매크로 함수가 처리된것을 확인할 수 있다.
5. 바이너리를 이용해 의사 코드 작성하기
1 2 3 4 5 6 7 8 | #include <stdio.h> int main() { pirntf("Hello, World!!!\n"); return 0; } | cs |
1) C 라이브러리를 이용한 어셈블리 프로그램 작성
vi hello.c
======== 분석 ==========
실제 실행되는 코드는 main: 의 두 줄이다.
a) data segment
- 읽기/쓰기 가능한 메모리 영역
- 프로그램 실행에 필요한 데이터
b) text segment
- 실행 가능한 메모리 영역(쓰기 불가)
- 주로 실행할 명령어들이 들어있다.
2) C 라이브러리를 사용하지 않고 프로그램 작성 (original)
위와 같이 C로 작성하지 않고 어셈블리어로 작성하면, 파일 내용을 최소화 할 수 있고,
불필요한것들을 제거할 수 있다. 또한 파일의 실행속도가 빨라진다.
중요한 점은 어셈블리 프로그래밍을 할 때 각각의 세그먼트를 직접 지정해주어야 한다.
5. 기본 지식
- 프로그램이 실행되려면 디스크에 있던 파일을 메모리에 옮겨야한다.
- 모든 실행 중인 파일은 메모리에 상주해 있어야 한다.
- 실행 중인 프로그램을 프로세스라고 한다.
- 메모리에서 해제되면 프로세스가 종료된다 라고 한다.
- 32bit 환경에서 한 프로세스가 사용하는 전체 크기는 4GB이다.
리눅스의 경우 1G(커널) + 3G(프로세스)로 나눈다.
3G 프로세스를 크게 text ,data, stack 영역으로 나눈다.
윈도으ㅜ의 경우 2G(커널) + 2G(프로세스)fh sksnsek.
- segement or pase or section 이라고 부른다.
- 운영체제는 무엇을 보고 segment를 분리할까??
실행파일 시스템의 구조를 보고 분류한다.
주로 PE 구조를 보고 확인할 수 있다.
elf: 리눅스, pe: 윈도우
'Pwnable' 카테고리의 다른 글
어셈블리 프로그래밍 심화3 (0) | 2018.07.19 |
---|---|
어셈블리 프로그래밍 심화2 (0) | 2018.07.12 |
어셈블리 프로그래밍 심화 및 CPU 구조 (0) | 2018.07.04 |
어셈블리 와 C언어, 리눅스의 이해 (0) | 2018.07.04 |
C언어로 만들어진 프로그램의 실행과정의 이해 (0) | 2018.01.18 |