일시: 2022.09.17
스터디원: 정현수, 엄설인, 유예지, 이유빈
활동내용: 도서 [리버싱 입문] 1장, 부록 페이지 개별학습 후 발표 및 피드백
http://www.yes24.com/Product/Goods/27628413
활동내용 정리
1장 - 엄설인
PE파일(exe 파일…): 윈도우 운영체제에서 사용하는 실행 파일 형식
ᄋ 프로그램을 실행하는 데 필요한 기본 정보와 파일을 메모리 어디에 저장해야할지 알려주는 배치 정보가 들어있음
ᄋ 구성: 헤더(PE.섹션헤더, 중요한 정보/어떻게 동작해야하는지에 대한 규칙)+보디(코드, 데이터) - PE 헤더에 있는 정보를 분석해서 PE 보디에 있는 코드와 데이터를 메모리에 배치
IAT(Import Address Table): 실행(PE)파일 안에 어떤 라이브러리의 어떤 함수를 가져다 사용하는지 기록해놓은 정보
ᄋ 코드에서 라이브러리를 참조하는 부분은 IAT 내부에 있는 함수 주소를 사용하고 있음
레지스터: CPU에서 사용하는 고속의 기억장치
ᄋ CPU는 연산을 수행하기 위해 메모리에 있는 데이터를 CPU 내부에 있는 레지스터로 가지고 옴→ 연산 중간에도 레지스터에 데이터를 저장함
1. EAX(Extended Accumulator Register): 곱셈과 나눗셈 명령에서 사용. 함수의 반환값 저장
2. EDX(Extended Datat Register): EAX와 같이 사용. 부호 확장 명령 등에 활용
3. ESI(Extended Source Index): 데이터 복사하거나 조작할 때 소스 데이터 주소 저장
4. EDI(Extended Destination Index): 복사 작업을 할 때 목적지 주소 저장
5. EBX(Extended Base Register): ESI나 EDI와 결합해 인덱스에 사용(ESI+EDI)
6. ECX(Extended Counter Register): 반복 명령어를 사용할 때 반복 카운터 저장
7. EGP(Extended Base Pointer): 하나의 스택 프레임의 시작 주소 저장
현재 사용한 스택 프레임이 사라지면 이전에 사용되던 스택 프레임 가리킴
8. ESP(Extended Stack Pointer): 하나의 스택 프레임의 끝 지점 주소가 저장
PUSH, POP에 따라 4bite씩 값 변함
9. EIP(Extended Instruction Pointer): 다음에 실행할 명령어가 저장된 메모리 주소 저장
현재 명령어 모두 실행한 다음 EIP에 저장된 주소에 명령어 실행
-PUSH: 데이터를 스택에 집어넣는 명령어
-POP: 데이터를 스택에서 꺼내는 동작
—> 프로그램은 이 2개 명령어를 가지고 스택 제어함
스택: 메모리의 한 부분. LIFO(후입선출)방식으로 동작하는 자료구조
ᄋ 한 방향으로만 데이터 쌓임(시작주소에서 주소가 작아지는 방향으로)
ᄋ 위치: 스택 포인터라고 불리는 ESP(하나의 스택 프레임의 끝지점 주소 저장됨) 레지스터에 저장
ᄋ PUSH→ 스택의 주소는 4bite만큼 감소하면서 데이터가 스택으로 들어감→POP→ 스택으로부터 데이터가 꺼내지고 스택의 주소는 다시 4bite만큼 증가
ᄋ 서브루틴(함수)로 인자 전달→서브루틴 내부에서 사용하는 지역 변수가 저장되는 공간 제공하며, 서브루틴이 종료될 때 되돌아갈 주소를 저장하는 역할 함
디버거 어셈블러) 함수 호출할 때 정확하게 인자를 스택으로 PUSH→ 서브루틴(함수)이 종료될 때 복귀 주소를 스택에서 POP
스택 동작 방식을 이해 못하면 리버싱 이해할 수 없음!
스택 프레임: 서브루틴(함수)이 가지는 자신만의 스택 영역
ᄋ 서브루틴 내부에서 사용하는 데이터 저장
OllyDbg: 윈도우용 어셈블러를 분석할 수 있는 디버거
ᄋ 직관적인 사용자 화면 제공. 다양한 플로그인 통해 기능 확장할 수 있음
어셈블러: 컴퓨터가 이해할 수 있는 연속적인 비트로 구성된 기계어를 사람이 알아볼 수 있도록 만든 일종의 매크로 모음
부록: 올리디버거 설치-유예지
OllyDbg 개요
- 윈도우용 어셈블러를 분석할 수 있는 디버거
- 32비트 지원
기본 설정
[Options]-> udd 저장 폴더 설정
뷰
CPU
- 운영체제가 프로그램을 실행한다는 것:
- 저장된 PE(실행 파일)을 메모리에 로딩하고 프로세스로 만들어 CPU가 동작을 수행하도록 명령하는 것
- 메모리에 있는 정보를 레지스터로 가지고 와서 제어 장치과 연산 장치에서 이를 처리
- 어떤 정보를 사용하고 어디에 정보를 저장하는지 살펴 볼 수 있음.
코드 영역
- 주소(메모리에 저장된 절대 주소), 기계어(운영체제가 인식할 수 있는 연속적인 바이너리 조합), 어셈블러(사람이 알아볼 수 잇는 매크로로 변환), 주석(올리디버거가 어셈블러를 분석해서 해석을 달아둔 것. 직접 달기 가능)
- 실행 파이의 어셈블러 코드를 보여줌.
- 왼쪽 기계어, 오른쪽 어셈블러.
- 리버싱시에는 어셈블러 코드 중심으로.
- 디버거로 프로그램을 열면 PE 헤더에 저장된 엔트리 포인트에서 실행이 멈춤
힌트 영역
- 어셈블러 코드에 있는 상대 주소와 아스키 코드, 16진수 등을 우리가 알기 쉬운 언어로 표현해 주는 영역.
- 어셈블러를 따라가는 과정을 자동화하여 힌트 영역에서 보여줌
- 스택, 함수가 반환하는 EAX 레지스터에 대한 정보 등을 보여줌.
메모리 영역
- 어셈블러가 사용하는 메모리를 보여줌. PE 헤더에서 데이터 영역으로 지정된 부분을 보여줌.
- 다른 섹션으로 넘어가려면: [Go to]=>[Expression]
- Address, Hexdump, ASCII 영역으로 구분
- Address: 메모리에 실제로 저장된 주소
- Hex dump; 바이너리 스트링을 16진수로 변경
- ASCII: 16진수에 해당하는 아스키 코드 값을 보여줌.
- 문자열은 연석된 값으로 저장, 맨 마지막에 문자열의 끝을 의미하는 널 문자(00)가 저장됨.
레지스터 영역
- CPU가 연산을 수행하면서 사용하는 데이터 영역
- CPU는 연산을 위해 메모리로부터 레지스터로 데이터를 가지고 오며, 프로그램 흐름을 제어하기 위한 정보를 레지스터에 저장.
- EAX~EIP 레지스터, ZERO FLAG 레지스터 사용
- EAX: 연산의 결과 저장
- EBP: 프레임 포인터 저장
- ESP: 스택의 맨 위를 가리킴.
- EIP: 다음에 실행할 명령어 주소 저장
- ZERO FLAG: 비교 연산의 결과 저장, JMP 명령어의 기준값으로 사용.
스택 영역
- 메모리에 위치한 스택을 보여줌.
- 메인 함수에서 서브루틴으로 들어갈 때 넘겨주는 인자와 복귀할 주소, 그리고 서브루틴 내부에서 사용하는 변수가 스택에 저장됨.
메모리 맵
- 스택 구조, 히프 메모리 . 현재 PE 파일이 메모리에 로딩된 주소 영역 알 수 있음
실행 모듈
- 프로그램에서 사용하는 실행 모듈의 세부 정보 열람 가능.
- 현재 메모리에 로딩된 실행 모듈의 이름과 버전, PE 파일 경로까지 구체적인 정보 보여줌.
- 분석 대상 프로그램도 하나의 실행파일로 간주.
콜 스택
- 서브루틴 호출 구조
코드 영역 메뉴
- [Copy as table]: 주소, 바이너리, 어셈블러 전체를 복사할 수 있는 기능. 코드 영역에서 볼 수 있는 데이터 전체 복사
- [BIinary copy] : 바이너리만 복사 가능. 실행 파일 수정할 때 사용
- [Binary edit]: 코드를 직접 수정할 때 많이 사용.
- [Copy to executable]: 수정된 코드를 실행 파일로 저장하는 역할.
- [Add comments]: 주석입력
- [Assemble]: 디버거 화면에서 직접 어셈블러 코드를 입력할 수 있게 해줌.
- [New origin here]: 다음에 실행할 명령어 주소를 현재 선택된 명령어 주소로 강제적으로 변경하는 기능 제공.
- [Follow in dump]:
- Immediate constant: 명령어에 인수로 오는 메모리 주소로 이동
- Selection: 선책된 명령어가 저장된 주소로 바로 이동.
- Go to
- Origin: 레지스터에 들어 있는 주소로 바로 이동
- Expression: 주소를 검색해서 해당 위치로 바로 이동하는 기능 제공
- Previous location: 이전에 분석한 코드를 다시 보고 싶을 때 사용
- Executable file: PE 파일 전체를 하나의 화면에 보여줌
- [Search for]: 다양한 검색 기능 제공.
- [Find reference to]: 현재 선택한 명령어를 호출하는 부분을 찾음.
부록: PE 파일 구조 - 이유빈
- PE 파일(Portable Executable File)
- 우리가 만든 File이 실행할 수 있는, 이식가능한 다른 곳에 옮겨져도(Portable) 실행가능하도록(Executable) 만들어 놓은 파일
- 윈도우 실행파일이라고도 부르며, 윈도우 운영체제에서 사용되는 실행파일 형식을 말함
- 예를 들어, 우리가 간단히 만든 hello,world를 출력하는 프로그램도 PE 구조를 가지고 있으며, 윈도우에 기본적으로 내장되어 있는 notepad.exe, calc.exe 프로그램도 PE 구조를 가지고 있다.
PE 파일의 구조
- 헤더: PE 파일이 어떻게 동작해야 하는 지의 규칙, 파일 구성 관련 정보
PE Header(모든 PE 파일이 동일하게 소유)
Section Header(파일마다 내용이 다름)
- 보디: 헤더에 적힌 규칙따라 실행되는 기계어
Section Data(파일마다 내용이 다름)
- 구조체 형식이 아님.
💠 PE Header
- IMAGE_DOS_HEADER
윈도우 운영체제의 하위 호환성 지원
DOS 운영체제가 윈도우용 PE 파일을 실행했을 때 적절한 오류 메시지를 보여주고 실제 윈도우용 PE 헤더(IMAGE_NT_HEADERS) 위치를 가리킴
- MS-DOS Stub Program
DOS 운영체제에서 윈도우용 PE 파일 실행 시 보여줄 오류 메시지를 저장함
- IMAGE_NT_HEADERS
4바이트 Signature 2개, IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER로 구성
- IMAGE_DATA_DIRECTORY
RVA와 Size로 구성된 8바이트 구조체 16개로 구성
16번째 구조체는 마지막을 의미하는 null
리버싱에서 자주 사용되는 구조체:
- Export Table: 외부에 공개하고자 하는 함수 정보를 저장하는 곳
- Import Table: PE 파일이 다른 라이브러리로부터 가져와 사용하는 함수 정보 저장->리버싱에서 굉장히 중요한 내용
- Resource Table: PE 파일에서 사용하는 리소스가 저장된 영역
- Base Relocation Table: PE 헤더에 있는 Image Base 값 사용을 못할 때, PE 파일 내부 절대 주소를 변경할 시 사용되는 구조체
- TLS Table: 엔트리 포인트 이전에 실행되는 함수 지정 시 사용
- Import Address Table: 리버싱에서 핵심적 역할을 하는 구조체
💠Section Header
- 로더(Loader:OS 일부분)가 섹션 데이터를 메모리로 로딩하고 속성을 설정하는데 필요한 정보가 저장돼 있다.
- 즉, 섹션 데이터 사용을 위한 기본 정보가 들어 있다.
- PE 파일에는 다양한 섹션 데이터를 포함할 수 있는데, 각각 섹션 데이터에 해당하는 섹션 헤더가 존재
💠Section Data
- 제 프로그램을 실행하기 위한 데이터가 들어가 있음(PE 헤더는 데이터에 접근하기 위한 설정 정보만 있다.)
- 일정 구조체 형식이 아님 -> 데이터가 자유롭게 분포
- PE 헤더에서 섹션데이터의 각 영역에 어떤 형식의 데이터가 저장될 것인지 지정하느냐에 따라 저장 데이터 종류가 달라짐
- IAT(Import Address Table)
- PE 파일 안에 어떤 라이브러리에서 어떤 함수를 가져다 쓰는지 기록해놓은 정보
- PE File 내의 특정 구조체인 'IMAGE_IMPORT_DESCRIPTOR'에 Import에 관한 정보를 저장
- PEView에서 실행 파일 내용
- Raw Data: 실제 파일에 들어 있는 바이너리 데이터
- pFile: 파일 내부에서 오프셋(파일 처음 위치부터 해당 바이트가 얼마나 떨어져 있는지)
- Value: 바이너리 데이터를 ASCII 코드로 변환한 값
- 주소 지정 방식
- PE 파일 분석 시 내가 찾는 데이터 위치가 어디에 있는지는 헤더에 있는 정보로 찾음, 이때 사용하는 값이 주소
- 종류 : pFile, RVA, VA
- RVA(Relative Virtual Address)
- 메모리가 로드 됐을 때, 기준값에서 얼마나 떨어져 있는지 나타내는 상대 위치(상대 주소)
- 기준값: PE Header 속 IMAGE_NT_HEADERS->IMAGE_OPTIONAL_HEADER에 Image Base가 있는데, 이는 PE 파일이 메모리에 로드될 때 데이터가 저장되는 기준 주소를 의미함. 즉, 기준값 = Image Base
- VA(Virtual Address)
- PE 파일이 메모리에 로드 됐을 때, 가상 메모리상 저장되는 실제 주소
- 디스크에 저장된 PE 파일이 기준값(Image Base)에서 PE 헤더 파일에 지정된 RVA값만큼 떨어진 위치 = VA
'2. Reversing (리버싱) > 1) Write UP' 카테고리의 다른 글
[2022.10.08] R4 - crackme#3, crackme#4, crackme#5 문제 풀이 (0) | 2022.10.08 |
---|---|
[2022.10.01] R4 - crackme#1, crackme#2 문제 풀이 (1) | 2022.10.03 |
[2022.05.07] 5장 리버싱의 어려운 문제들 ① (0) | 2022.05.17 |
[2022 . 3. 26] 리버고고싱 활동일지 (0) | 2022.03.30 |
[2022.03.12] 활동일지 (리버고고싱) (0) | 2022.03.12 |