1. 스터디 과제
C/C++ 언어의 다양한 개념들이 어떤 x86 어셈블리 언어로 변환되는지 알아보기
여기서 말하는 다양한 개념들이란 ? (변환 작업은 스터디 1주차 1-2에서 작성)
- main 함수
- 변수의 선언/할당/사용 (문자열, 포인터, 배열 등)
- 상수의 선언/초기화/사용
- 공용체, 구조체, 클래스의 선언/정의/사용
- 클래스의 접근제한자(private/protected/public)
- 객체의 생성자/소멸자 호출
- 멤버 변수의 선언/할당/사용
멤버 함수의 선언/정의/사용
- 함수의 선언/정의/호출/반환
- loop문 (for, while, do while 등)
- continue/break/goto 문
- 다양한 함수 (malloc/free/strcpy/strcmp 등)
- 다양한 연산자 (new/delete 등)
목적 1) 프로그래밍 언어 등 고수준의 추상 개념들이 명령어 등의 더 낮은 수준에서 어떻게 구현되는지 이해합니다.
여기서 말하는 낮은 수준의 언어는 기계어(Machine Language), 어셈블리어(Assembly Language) 중 어셈블리어를
말하는 것 같다.
▶ 기계어(Machine Language) : CPU가 직접 해독하고 실행할 수 있는 Bit 단위로 쓰인 컴퓨터 언어를 통틀어 일컫는 말.
누구나 기계어로 명령어를 구성할 수 있으나 숫자로만 이루어진 기계어를 외워서 쓰기에는 많은 제약이 있다.
예를 들어 간단한 프로그래밍은 할 수 있으나 몇 백 줄 되는 코드를 만들기에는 어려움을 겪을 수 있다.
따라서 기계어와 대응되면서 사람이 쉽게 사용할 수 있는 언어를 개발한 것이 어셈블리어인 것 같다.
▶ 어셈블리어(Assembly Language) : 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어.
위의 기계어보다 어셈블리어가 이해하기 쉽다.(인간기준)
이 어셈블리언어가 기계어와 일대일 대응이 되어 컴퓨터가 코드를 처리한다.
즉 위에 어셈블리 언어의 2번째 줄 push ebp(인간이 쉽게 알아보기 위해 쓰인 언어)가 기계어로 변환된 뒤 CPU가 해석 후 해당 코드를 처리하는 것이 일반적인 과정.
∴ "목적1" 은 프로그래밍 언어를 어셈블리언어로, 어셈블리 언어를 프로그래밍 언어로 바꾸는 과정을 해보라는 뜻.
(아래 과정을 해보라는 뜻)
목적 2) 64-bit Windows에서 32-bit 프로그램은 "Program Files (x86)" 폴더에, 64-bit 프로그램은 "Program Files" 폴더에 설치됩니다. Windows 사용자의 경우 당장 두 폴더를 열어 최상위 폴더의 개수(설치된 프로그램의 수)를 확인해보면 보통은 32-bit 프로그램의 수가 더 많을 것입니다. Windows x64가 대중화된 아직도 x86-64(또는 x64, AMD64)보다 하위 호환 목적으로 지원하는 기존 아키텍처(명령어 세트)인 x86-32(또는 x86, IA-32)가 더 많이 사용되고 있다보니 적어도 Windows 실행 파일을 분석하려는 리버스 엔지니어라면 반드시 x86-32 명령어 세트는 알고 있어야 합니다.
여기서 말하는 명령어 세트는 32bit에서 사용되는 명령어를 이야기한다.
32bit와 64bit에서 사용되는 명령어 규칙 및 저장규격 등은 아래에서 보듯 다르다.
PUSH, ADD, SUB 등 다양한 명령어를 처음부터 알기는 힘드므로 수시로 찾아보고 기억하는 것이 편할듯 하다.
// Visual Studio를 사용한 C/C++ 프로젝트 빌드
1. Release 구성을 선택합니다. (Release 구성은 프로그램을 배포할 때 일반적으로 지정하는 속성들을 기본값으로 가지며, Debug 구성은 Visual Studio의 내장 디버거를 사용하기위해 필요한 속성들을 기본값으로 가집니다)
2. Win32 플랫폼을 설정합니다. (x86-32 명령어 세트를 사용하는 32-bit 프로그램을 빌드합니다)
3. 현재 구성 및 플랫폼에 대해 최적화 옵션을 끕니다. (명령어가 최적화 되면 읽기 어렵게 바뀌거나 의미 없는 명령어가 제거되는 등 분석 난이도가 올라갑니다)
1) C++ 프로젝트의 속성 페이지 대화 상자를 엽니다.
2) 속성을 변경할 구성 및 플랫폼을 선택합니다 (Release / Win32)
3) 프로젝트 > 속성 > 구성 속성 > C/C++ 메뉴의 최적화 속성 페이지에서 다음과 같이 속성을 변경합니다.
- 최적화: 사용 안 함(/Od)
- 인라인 함수 확장: 사용 안 함(/Ob0)
인라인함수란? : 함수의 내용을 호출을 통해서 실행 시키는 것이 아니라 호출되는 함수가 코드자체가 되어버림.
- 내장 함수 사용: 아니요
내장함수란? : 사용언어가 제공하는 자체 함수 ex) C언어에서는 printf, fopen 같은 것들.
- 프레임 포인터 생략: 아니요(/Oy-)
프레임포인터 레지스터란 ? : 함수 호출 이전의 Stack Pointer위치를 저장하고 있는 레지스터
- 전체 프로그램 최적화: 아니요
▶ 3) 설정 방법
// 추가 과제가 필요한 사람만
+과제: Release/Debug 구성 속성에 따른 차이를 분석하고 원인 추측해보기
구성차이 분석:
1. Release파일에는 iobj, ipdb 파일이 있으나 Debug파일에는 ilk파일이 있다.
ILK - Incremental Linking File로 IDE인 Microsoft Visual Studio에서 사용되는 파일. 컴파일 된 실행파일에 대한 링커 데이터를 포함하고 있다.
IOBJ - Microsoft Visual Studio Intermediate Object에서 제공하는 파일. (잘 모르겠다...)
IPDB - IP Address Tracker IP Database로 데이터베이스 파일이며, IP 주소 추적기와 연결되어 IP 주소 데이터베이스가 포함된 파일에 사용된다라고 하는데 이해 못 했음.
2. Release/Debug 둘 다에 .pdb 파일이 있으며 용량이 같다.
PDB - Pegasus, MS Visual Studio 등 다양한 응용 프로그램에서 사용하는 데이터 베이스 파일.
일반적으로 독점 형식으로 저장된 파일이다. 그러니까 Pegasus PDB 파일이 Visual Studio에서는 인식되지 않는다.
Visual Studio에서 PDB 파일은 프로그램에 대한 디버깅 정보를 저장한다. 출처 : whatext.com/ko/pdb
그런데 왜 Release 파일에 PDB 파일이 있을까?
아마 Release 파일도 나중에 수정해야할 경우가 생김. PDB파일에 Debug정보가 생성 따라서 추후에 유용할 수 있다.
3. Release/Debug 파일 둘 다 exe파일이 있으나 용량이 다르다.
용량이 다른 이유?
3-1. 사전적 의미를 생각하여 추론
Release : 풀어주다, 놓아주다, 발표하다, 발매하다 등의 뜻을 가짐
Debug : (컴퓨터 프로그램에서) 오류를 검출하여 제거하다.
따라서 Release 모드는 최종 결과물, 발매품이 되므로 용량, 성능, 속도 등이 최적화 되어 빠르면서 용량도 작아야 하지 않을까 생각해봄.
Debug는 오류를 검출하기 위한 작업. 모든 과정을 하나하나 세세하게 뜯어봐야 하므로 용량이 Release와 다르게 큼.
3-2. 실제 Release와 Debug 용량 차이는 어디서 비롯된 것일까?
위의 자료에 따르면 성능 최적화는 Release를, Debug를 찾는데는 Debug Bulid를 사용하라고 한다.
'리버싱 > 리버싱 걸음마' 카테고리의 다른 글
정보보안 SUA - [정보보안공부] 5주차 과제 - Hooking의 기초 (0) | 2021.03.03 |
---|---|
정보보안 SUA - [정보보안공부] 4주차 과제 - Windows 데스크톱 앱 개발 (0) | 2021.02.26 |
정보보안 SUA - [정보보안공부] 3주차 과제 - 리버싱 로드 맵 및 PE로더 (0) | 2021.02.24 |
정보보안 SUA - [정보보안공부] 2주차 과제 - Windows 데스크톱 앱 개C/C++ 언어의 다양한 개념들이 x86 어셈블리 언어로 변환 결과물 (0) | 2021.02.05 |
1. abe crackme (0) | 2020.10.29 |