Скачать презентацию 리버스 엔지니어링 IT Cook Book 정보 보안 개론과 Скачать презентацию 리버스 엔지니어링 IT Cook Book 정보 보안 개론과

e9ec06f366e8f7deca1f8e5c222da288.ppt

  • Количество слайдов: 82

리버스 엔지니어링 IT Cook. Book, 정보 보안 개론과 실습 : 시스템 해킹과 보안(개정판) 리버스 엔지니어링 IT Cook. Book, 정보 보안 개론과 실습 : 시스템 해킹과 보안(개정판)

Contents v 학습목표 § 리버스 엔지니어링의 개념을 이해한다 § PE 파일 구조를 이해한다 § Contents v 학습목표 § 리버스 엔지니어링의 개념을 이해한다 § PE 파일 구조를 이해한다 § 리버스 엔지니어링 툴을 사용할 수 있다 § 리버스 엔지니어링 공격을 수행할 수 있다 § 리버스 엔지니어링 공격에 대한 대응책을 이해한다 v 내용 § 리버스 엔지니어링에 대한 이해 § PE 파일에 대한 이해 § 리버스 엔지니어링 툴 § 리버스 엔지니어링 공격 § 리버스 엔지니어링에 대한 대응책 2/82

리버스 엔지니어링에 대한 이해 v 리버스 엔지니어링(Reverse Engineering) : 역공학(逆 學), 장치나 시스템의 구조를 리버스 엔지니어링에 대한 이해 v 리버스 엔지니어링(Reverse Engineering) : 역공학(逆 學), 장치나 시스템의 구조를 분석하여 원리를 발견하는 과정 [그림 5 -1] 리버스 엔지니어링의 개념 ➊ 이미 만들어진 프로그램 동작 원리 이해, 유사 프로그램 제작 ➋ 프로그램의 보안 문제, 동작 문제, 오류 등을 이용, 제품 출시 전 문제점과 오류 제거·검토 ➌ 바이러스(또는 웜), 백신 제작 3/82

실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 1 v 새 프로젝트 생성 § 실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 1 v 새 프로젝트 생성 § [File]-[New] 메뉴 선택 → Win 32 Console Application’ 선택 →프로젝트 이름 (Project Name), 위치(Location) 지정 [그림 5 -2] 새 프로젝트 생성과 종류 선택 4/82

실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 1 v 새 프로젝트 생성 § 실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 1 v 새 프로젝트 생성 § ‘Win 32 Console Application’의 하위 옵션 나타나면‘Hello World’가 출력되는 기본 프로그램 선택 [그림 5 -3] ‘Hello World’프로그램 선택 5/82

실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 2 v 프로그램 생성 § [Build]-[Build 실습 5 -1 비주얼 C++ 컴파일러 사용법 익히기 2 v 프로그램 생성 § [Build]-[Build REVERSE_1. exe]메뉴(또는 F 7) 실행 § ‘프로젝트명Debug’디렉터리에서 생성된 실행 파일 (REVERSE_1. exe) 확인 [그림 5 -4] ‘Hello World’프로그램 컴파일과 실행 파일 확인 [그림 5 -5] REVERSE_1. exe 프로그램 실행 6/82

PE 파일에 대한 이해 v PE 파일 § 표준안 작성(1993년 MS) § 메모리에서도 디스크에 PE 파일에 대한 이해 v PE 파일 § 표준안 작성(1993년 MS) § 메모리에서도 디스크에 저장된 파일 형태로 바로 실행될 수 있도록 설계 § Win 32의 기본 파일 형식 § EXE 파일, 동적 링크 라이브러리(DLL, Dynamic Linking) 파일도 PE 파일 형식 § 파일 구조를 확인을 위해 STUD_PE 툴과 XVI 32 HEX 에디터를 사용 7/82

PE 파일에 대한 이해 § 파일 구조를 확인을 위해 STUD_PE 툴과 XVI 32 HEX PE 파일에 대한 이해 § 파일 구조를 확인을 위해 STUD_PE 툴과 XVI 32 HEX 에디터를 사용 [그림 5 -7] Stud_PE 실행 8/82

PE 파일에 대한 이해 v 헤더 § 도스 헤더 : DOS와 호환하기 위해 사용, PE 파일에 대한 이해 v 헤더 § 도스 헤더 : DOS와 호환하기 위해 사용, 64바이트 § 버튼 클릭면 [그림 5 -8]의 창 2개가 뜬다. (a) 창에서 선택한 항목이 (b) 창에서 붉은 색 박스 안에 표시 a) PE 파일 구조 (b) HEX 에디터에서 연 REVERSE_1. EXE 파일 [그림 5 -8] DOS 헤더 영역 확인 9/82

PE 파일에 대한 이해 § DOS 헤더 항목을 확장한‘Magic Number’부분은 HEX 에디터의 오른쪽 블록에서‘MZ’ PE 파일에 대한 이해 § DOS 헤더 항목을 확장한‘Magic Number’부분은 HEX 에디터의 오른쪽 블록에서‘MZ’ 문자열 확인 § MZ는 DOS 헤더의 시그니처로 사용 운영체제가MZ 문자 § DOS 헤더에서 중요한 부분은 마지막‘File address of new exe header’ e_lfanew 값이라고도 하는데, 여기에는PE 헤더의 주소 값이 적혀 있다. § REVERSE_1. EXE의‘File address of new exe header’값은 000000 D 8 10/82

PE 파일에 대한 이해 a) PE 파일 구조 [그림 5 -9] DOS 헤더의 주요 PE 파일에 대한 이해 a) PE 파일 구조 [그림 5 -9] DOS 헤더의 주요 부분 확인 (b) HEX 에디터에서 연 REVERSE_1. EXE 파일 11/82

PE 파일에 대한 이해 § DOS Stub 코드 : ‘File address of new exe PE 파일에 대한 이해 § DOS Stub 코드 : ‘File address of new exe header’값이 기록된 부분(00000040)과 000000 D 8 주소 값 사이에 표시한 부분 § ‘This program cannot be run in DOS mode’와 같이 적절하지 못한 상황에서 PE 파일이 실행될 때 경고문 등에 대한 데이터 포함. 12/82

PE 파일에 대한 이해 v PE 헤더 [그림 5 -11] PE 파일 헤더 영역 PE 파일에 대한 이해 v PE 헤더 [그림 5 -11] PE 파일 헤더 영역 확인 13/82

PE 파일에 대한 이해 v PE 헤더 § PE 파일의 구성 정보 보유, 데이터 PE 파일에 대한 이해 v PE 헤더 § PE 파일의 구성 정보 보유, 데이터 특성별로 섹션으로 구분하여 저장 • Machine(0 x 014 C, 2바이트) : CPU ID. IA 32(Intel Architecture 32)의 경우 0 x 014 C IA 64일 경우 0 x 0200 • Number. Of. Sections(0 x 0005, 2바이트) : 파일에 존재하는 섹션의 개수. • Time. Date. Stamp(0 x 4 CAD 899 A, 4바이트) : 파일이 생성된 시간과 날짜 • Size. Of. Optional. Header(0 x 000 E, 2바이트) : PE 파일 헤더 뒤에 오는 옵션 헤더(optionalheader) 크기를 16으로 나눈 값 • Characteristics(0 x 010 E, 2바이트) : 파일의 속성. 일반 실행 파일의 경우 값 0 x 010 F 이 속성을 통해 파일이 exe인지 dll인지 구분 § 섹션헤더 • Optional 헤더라고도 불리며, PE 파일에서 프로그램과 관련한 필수 정보를 담고 있는 부분 • Magic(0 x 010 B, 2바이트) : 시작 위치의 필드, Optional 헤더 구분 시그니처(값 0 x 010 B) • Address. Of. Entry. Point(0 x 00001120, 4바이트) : PE 파일이 메모리에 로드된 후 처음 실행 되는 코드의 주소, 가상 주소의 절대 값이 아닌 이미지 베이스부터의 오프셋 값인 상대 가상 주소(RVA, Relative Virtual Address)다. 엔트리 포인트는. text 섹션 (실행 코드를 담고 있는 메모리 영역)의 시작점인 경우가 대부분 이 값은. text 섹션 헤더의 가상 주소 값과 일치하는 경우가 많다. 14/82

PE 파일에 대한 이해 § 섹션헤더(Data Directory) [그림 5 -12] 섹션 헤더 15/82 PE 파일에 대한 이해 § 섹션헤더(Data Directory) [그림 5 -12] 섹션 헤더 15/82

PE 파일에 대한 이해 § 섹션헤더(Data Directory) • 다른 DLL에서 함수를 가져오거나 본 파일의 PE 파일에 대한 이해 § 섹션헤더(Data Directory) • 다른 DLL에서 함수를 가져오거나 본 파일의 함수를내보낼 때 해당 정보를 기록 - Export Table(16바이트) : Export 함수들에 대한 Export Table의 시작 위치와 크기 - Import Table(16바이트) : Import 함수들에 대한 Import Table의 시작 위치와 크기 • PE 파일이 실행될 때 외부에서 가져와 사용하는 함수(DLL) 목록이 들어있다. • DLL은 함수 Export , EXE는 해당 DLL로부터 함수 Impor. • Export된 함수를 가져온다는 것 : 해당 DLL과 사용하는 함수에 대한 정보를 저장하는 것을 의미 • 이 정보를 저장하고 있는 곳이 Import Table. • PE 파일의 섹션 테이블에는. idata라는 이름으로 지정 [그림 5 -13] Data Directories 16/82

PE 파일에 대한 이해 v 섹션 테이블 § 메모리 보호를 위한 최소 단위가 페이지이므로, PE 파일에 대한 이해 v 섹션 테이블 § 메모리 보호를 위한 최소 단위가 페이지이므로, 페이지 단위로 속성 설정 § 속성에 위배되는 행동 시 접근 오류 발생하여 메모리 보호 § 페이지 단위 메모리 속성 설정 • 성질이 다른 데이터들은 하나의 페이지에 설정 불가 • 실행 코드, 읽고 쓰기가 가능한 데이터, 읽기만 가능한 데이터는 별도 페이지에 설정 § PE 파일에 존재하는 섹션 • • • . text : 실행되는 코드를 담고 있는 섹션. data : 초기화된 전역 변수를 담고 있으며, 읽고 쓰기가 가능한 섹션. rdata : 읽기 전용의 데이터 섹션, 문자열 표현이나C++/com 가상 함수 테이블을 담고 있음. bss : 초기화되지 않은 전역 변수를 위한 섹션. idata : 다른 DLL에서 가져다 쓰는 함수들의 정보를 담고 있는 섹션. IMAGE_ IMPORT_DESCRIPTOR 의 배열, 하나당 DLL 하나의 정보를 담고 있음 • . edata : 다른 모듈이 이 PE 파일에 정의된 함수를 사용할 수 있도록 함수 목록 담고 있는 섹션 17/82

PE 파일에 대한 이해 [그림 5 -14] 섹션 테이블 18/82 PE 파일에 대한 이해 [그림 5 -14] 섹션 테이블 18/82

PE 파일에 대한 이해 §. text 섹션 • Name(. text, 8바이트) : 섹션 이름 PE 파일에 대한 이해 §. text 섹션 • Name(. text, 8바이트) : 섹션 이름 • Virtual Size(0 x 0001 E 100, 8바이트) : 섹션 크기 • Virtual Offset(0 x 00001000, 8바이트) : 섹션이 로드 될 가상 주소 PE 형식 내에서 이 필드도 상대 가상 주소(RVA)임 • Size of Raw Data(0 x 000100 F 0, 8바이트) : File Alignment의 다음 배수 값까지 반올림 한 섹션 데이터의 크기 • Pointer To Raw Data(0 x 00001000, 8바이트) : 섹션의 시작을 담고 있는 파일 오프셋 PE로더는 파일 안의 섹션에서 데이터 위치를 알기 위해 이 영역의 값 이용 • Characteristics(0 x 60000020, 8바이트) : 섹션의 실행 코드, 초기화된 데이터, 비초기화된 데이터와 같은 Flag(플래그)를 가지고 있음 메모리에 대한 실행(e. Xecute), 읽기(Read), 쓰기(Write) 속성 지 정 § 로더 : Pointer. To. Raw. Data가 지정한 곳부터 데이터를 Size. Of. Raw. Data만큼 읽음 Virtual Offset에 맵핑한 후 Characteristics에 설정된 속성 정보를 이용 페이지별 메모리 보호 적용 § 이 섹션 테이블의 내용을 Stud_PE의 [Section] 탭에서 각 섹션별로 확인 19/82

PE 파일에 대한 이해 § 이 섹션 테이블의 내용을 Stud_PE의 [Section] 탭에서 각 섹션별로 PE 파일에 대한 이해 § 이 섹션 테이블의 내용을 Stud_PE의 [Section] 탭에서 각 섹션별로 확인 [그림 5 -15] 섹션 테이블 내용 20/82

PE 파일에 대한 이해 v 섹션 § 동일한 성질의 데이터가 저장되는 영역 § 각 PE 파일에 대한 이해 v 섹션 § 동일한 성질의 데이터가 저장되는 영역 § 각 섹션은 해당 섹션을 선택→ 마우스 오른쪽 버튼의 팝업 메뉴 [Go. To. Section Start]로 해당 값 조회 [그림 5 -16]. text 섹션의 내용 확인 21/82

리버스 엔지니어링 툴 v 올리 디버거의 기본 구조와 사용법 [그림 5 -17] www. ollydbg. 리버스 엔지니어링 툴 v 올리 디버거의 기본 구조와 사용법 [그림 5 -17] www. ollydbg. de 22/82

리버스 엔지니어링 툴 § [Options]-[Debugging options] 메뉴 선택 § [Event] 탭에서 ‘Entry point of 리버스 엔지니어링 툴 § [Options]-[Debugging options] 메뉴 선택 § [Event] 탭에서 ‘Entry point of main module’로 선택 [그림 5 -18] ollydbg. ini 설정 [그림 5 -19] 파일 분석 시 올리 디버거 시작 지점 설정 23/82

리버스 엔지니어링 툴 ➊ ➋ ➌ ➍ ➎ ➏ ➐ [그림 5 -20] 올리 리버스 엔지니어링 툴 ➊ ➋ ➌ ➍ ➎ ➏ ➐ [그림 5 -20] 올리 디버거 인터페이스 24/82

리버스 엔지니어링 툴 ➊ 메모리 주소 : 프로그램을 메모리에 로드 시 메모리상에 로드된 프로그램의 리버스 엔지니어링 툴 ➊ 메모리 주소 : 프로그램을 메모리에 로드 시 메모리상에 로드된 프로그램의 명령어 코드 및 데이터의 가상 주소와 라벨 표시 ➋ 기계어 코드와 어셈블리어 코드 : 프로그램의 기계어 코드와 어셈블리어 코드 출력 ➌ 주석 창 : 올리 디버거가 분석한 API 함수, 문자열, 함수 인자 확인 사용자가 주석 입력 ➍ 레지스터와 플래그 창 : 주요 레지스터와 플래그의 상태 값 확인 ➎ 변수 값 출력 창 : 디버깅 중에 주요 변수 값 확인 ➏ HEX 덤프 창 : 프로그램을 HEX 값으로 덤프하여 보여주며, 바이너리 파일을 직접 수정 ➐ 스택 : 스택의 현재 상태 등 확인 25/82

리버스 엔지니어링 툴 키 기능 설명 F 2 Toggle F 9 Run 브레이크 포인트까지 리버스 엔지니어링 툴 키 기능 설명 F 2 Toggle F 9 Run 브레이크 포인트까지 실행 Restart 코드 처음 부분으로 회귀 Ctrl+F 2 F 7 Step into F 8 Step over 브레이크 포인트를 지정 Call함수나 반복적으로 수행하는 Rep 명령을 만났을 때 함수 내부로 추적 또는 Rep 조건을 만족할 때까지 계속 수행 함수 내부로 추적하지 않고 함수 실행 후 그 다음 코드로 넘어감 Rep 같은 반복 명령도 한번에 처리하고 다음 코드로 실행 Ctrl+F 9 Execute till return API 함수나 추적해 들어갈 필요 없는 함수 내부로 추적해 들어갔을 때 Alt+K Call Stack 현재 호출된 함수 목록을 보여줌 해당 함수의 ret 명령 지점까지 한번에 실행하고 함수를 나온다. [표 5 -1] 올리 디버거 키와 기능 26/82

리버스 엔지니어링 툴 27/82 리버스 엔지니어링 툴 27/82

리버스 엔지니어링 툴 v 함수찾기 § 문자열 찾기 : 함수 찾기의 가장 일반적 방법 리버스 엔지니어링 툴 v 함수찾기 § 문자열 찾기 : 함수 찾기의 가장 일반적 방법 § REVERSE_1. EXE를 올리 디버거로 연다 § 어셈블리어 창에서 마우스 오른쪽 버튼 [Search for]-[All referenced text strings] [그림 5 -22] 프로그램에 존재하는 모든 문자열을 찾는 메뉴 실행 28/82

리버스 엔지니어링 툴 v 함수찾기 § 문자열이 위치한 주소(Address)와 어셈블리 명령어, 찾은 문자열의 내용 리버스 엔지니어링 툴 v 함수찾기 § 문자열이 위치한 주소(Address)와 어셈블리 명령어, 찾은 문자열의 내용 확인 § [Follow in Disassembler] 메뉴를 실행 § 커서가 어셈블리어 창에서 해당 문자열이 존재하는 위치에 놓인다. [그림 5 -23] ‘Hello World!’문자열을 통한 main 함수 추적 과정 29/82

리버스 엔지니어링 툴 v 로직 확인하기 § REVERSE_1. EXE의 00401010 주소 라인에서 F 2(Toggle)를 리버스 엔지니어링 툴 v 로직 확인하기 § REVERSE_1. EXE의 00401010 주소 라인에서 F 2(Toggle)를 눌러 브레이크 포인트 설정 [그림 5 -24] 브레이크 포인트 설정 30/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 9(Run)를 누르면 브레이크 포인트를 설정한 라인 리버스 엔지니어링 툴 v 로직 확인하기 § F 9(Run)를 누르면 브레이크 포인트를 설정한 라인 바로 위 라인까지 실행 § F 7(Step into) 클릭: EIP 현재 값 00401011, EBP 값 0012 FFC 0 이 값은 라인 0012 FF 80에 포함 ` ` [그림 5 -25] ‘PUSH EBP’를 실행한 화면 31/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 7클릭 : 00401011 라인에서‘MOV EBP, ESP’가 리버스 엔지니어링 툴 v 로직 확인하기 § F 7클릭 : 00401011 라인에서‘MOV EBP, ESP’가 실행되고 ESP(0012 FF 80)로 바뀜 [그림 5 -26] ‘MOV EBP, ESP’를 실행한 화면 : [그림 5 -25] + F 7 1번 32/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 7 4번 더 클릭 : 커서가‘LEA 리버스 엔지니어링 툴 v 로직 확인하기 § F 7 4번 더 클릭 : 커서가‘LEA EDI, DWORD PTR SS: [EBP-40]’라인에 위치 SS(Stack Segment)는 0023, ‘ EBP-40’은0012 FF 40(=0012 FF 80 -40) ` ` [그림 5 -27]‘ PUSH EBX’, ‘ PUSH ESI’, ‘ PUSH EDI’를 실행한 화면 : [그림 5 -26]+ F 7 4번 33/82

리버스 엔지니어링 툴 v 로직 확인하기 § 다시 F 7 클릭 : ‘ LEA 리버스 엔지니어링 툴 v 로직 확인하기 § 다시 F 7 클릭 : ‘ LEA EDI, DWORD PTR SS: [EBP-40]’ 실행 [그림 5 -28] ‘LEA EDI, DWORD PTR SS: [EBP-40]’을 실행한 화면 : [그림 5 -27]+ F 7 1번 34/82

리버스 엔지니어링 툴 v 로직 확인하기 § 다시 F 7 2번 클릭 : ‘ 리버스 엔지니어링 툴 v 로직 확인하기 § 다시 F 7 2번 클릭 : ‘ MOV ECX, 10’라인과‘MOV EAX, CCCC’라인 실행 ECX 값 00000010, EAX 값 CCCC 00401026 주소 라인에서‘REP STOS DWORD PTR ES: [EDI]’ 실행되도록 설정 ` [그림 5 -29]‘ MOV ECX, 10’, ‘ MOV EAX, CCCC’를 실행한 화면 : [그림 5 -28]+ F 7 2번 35/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 7 2번 더 클릭 : 레지스터 리버스 엔지니어링 툴 v 로직 확인하기 § F 7 2번 더 클릭 : 레지스터 창에서 ECX 값 0000000 E(2감소) ` [그림 5 -30] ‘REP STOS DWORD PTR ES: [EDI]’의 반복 실행 결과 : [그림 5 -29] +F 7 2번 36/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 7 클릭시 : ECX 1씩 감소, 리버스 엔지니어링 툴 v 로직 확인하기 § F 7 클릭시 : ECX 1씩 감소, EDI 4씩 증가, EDI가 가리키는 스택 CCCC로 채워짐 § F 7 을 계속 눌러‘REP STOS DWORD PTR ES: [EDI]’ 모두 실행, 커서가 ‘CALL REVERSE_. printf’라인에 위치토록 함. 이 라인이‘Hello World!’ 실행 위한 명령 [그림 5 -31] ‘CALL REVERSE_. printf’함수 라인 확인 : [그림 5 -30] + F 7 14번 37/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 7 누르면 printf가 구현된 어셈블리어 코드로 리버스 엔지니어링 툴 v 로직 확인하기 § F 7 누르면 printf가 구현된 어셈블리어 코드로 화면이 넘어감 [그림 5 -32] ‘CALL REVERSE_. printf’함수 라인에서 을 실행한 결과 : [그림 5 -31]+ F 7 1번 38/82

리버스 엔지니어링 툴 v 로직 확인하기 § F 8 누르면 원래 화면에서‘CALL REVERSE_. printf’가 리버스 엔지니어링 툴 v 로직 확인하기 § F 8 누르면 원래 화면에서‘CALL REVERSE_. printf’가 실행된 바로 다음 라인으로 넘어감 [그림 5 -33] ‘CALL REVERSE_. printf’함수 라인에서 을 실행한 결과 : [그림 5 -31]+ F 7 1번 39/82

리버스 엔지니어링 툴 v 프로그램의 변수 값 변경 후 디버깅하기 § 레지스터 값 고치기(레지스터를 리버스 엔지니어링 툴 v 프로그램의 변수 값 변경 후 디버깅하기 § 레지스터 값 고치기(레지스터를 변경하여 디버깅) • • ECX가 0000000 E일때, ECX에서 마우스 오른쪽 버튼 눌러 ➊[Modify] 메뉴 선택 팝업창이 뜨면 HEX나 10진수값 등을 넣을 수 있음 0000000 E를 ➋0000000 A로 변경 ECX 레지스터 값이 0000000 A로 변경되며, ‘ REP STOS DWORD PTR ES: [EDI]’문도 ➌0000000 A번만수행된다 40/82

리버스 엔지니어링 툴 ➊ ` ➋ ➌ ` ` [그림 5 -34] ECX 레지스터 리버스 엔지니어링 툴 ➊ ` ➋ ➌ ` ` [그림 5 -34] ECX 레지스터 값을 직접 변경 41/82

리버스 엔지니어링 툴 v 프로그램의 변수 값 변경 후 디버깅하기 § 어셈블리어 코드 고치기(디버거에서 리버스 엔지니어링 툴 v 프로그램의 변수 값 변경 후 디버깅하기 § 어셈블리어 코드 고치기(디버거에서 어셈블리어를 고쳐 프로그램 실행) • ‘ MOVECX, 10’실행되는 0040101 C 주소 라인에서 마우스 오른쪽 버튼 눌러 ➊[Assemble] 메뉴 선택, 팝업창이 뜨면‘MOV ECX, 10’를 ➋‘MOV ECX, 7’로 수정 • 버튼을 누르면 해당 라인의 변경이 적용되고, 붉은색으로 표시, 실행하면 ➌‘MOV ECX, 7’로 적용되어 프로그램 실행 42/82

리버스 엔지니어링 툴 ➊ ` ➋ ➌ ` ` [그림 5 -35] 어셈블리어 코드 리버스 엔지니어링 툴 ➊ ` ➋ ➌ ` ` [그림 5 -35] 어셈블리어 코드 수정을 통한 ECX 레지스터의 값 변경 43/82

리버스 엔지니어링 툴 v 값 찾기 § 문자열 찾기 • • • 분석할 포인트를 리버스 엔지니어링 툴 v 값 찾기 § 문자열 찾기 • • • 분석할 포인트를 찾기 위해 가장 많이 사용하는 기능 찾는 문자열은 화면에 출력되는 문자열일 수도 있고, 함수의 이름일 수도 있다. 어셈블리어 창에서 마우스 오른쪽 버튼 클릭 [Search for]-[All referenced text strings] 이용 [Searchfor]-[Binary String] : 특정 값을 찾기 위해 많이 사용 ASCII 문자열 찾기 UNICODE나 찾고자 하는 HEX 값을 직접 입력해 찾기 44/82

리버스 엔지니어링 툴 [그림 5 -36] 분석 포인트를 찾기 위한 문자열 찾기 메뉴 실행 리버스 엔지니어링 툴 [그림 5 -36] 분석 포인트를 찾기 위한 문자열 찾기 메뉴 실행 [그림 5 -37] 문자열 검색 창 45/82

리버스 엔지니어링 툴 v 값 찾기 § 스택과 파일 덤프 위치 찾기 • ‘REP 리버스 엔지니어링 툴 v 값 찾기 § 스택과 파일 덤프 위치 찾기 • ‘REP STOS DWORD PTR ES: [EDI]’라인에서 F 7을 눌러 두세 번 실행 • EDI 값에서 마우스 오른쪽 버튼 클릭 : [Follow in Dump]과 [Follow in Stack] 메뉴 확인 • 파일 덤프 창과 스택에서 해당 주소 값으로 위치 찾아갈 때 사용 [그림 5 -38] 레지스터에 기록된 주소 값의 덤프와 스택 값 확인을 위한 메뉴 확인 46/82

리버스 엔지니어링 툴 v 값 찾기 § 스택과 파일 덤프 위치 찾기 • ‘Follow 리버스 엔지니어링 툴 v 값 찾기 § 스택과 파일 덤프 위치 찾기 • ‘Follow in Dump’와‘Follow in Stack’명령을 통해 파일 덤프 창과 오른쪽의 스택 창에서 0013 FF 50 주소의 위치로 갈 수 있다 ` ` [그림 5 -39] 파일 덤프 창과 스택 창에서 0 x 0013 FF 50 주소의 값 확인 47/82

리버스 엔지니어링 툴 v 스택 창 기능 § EBP, ESP 주소 값으로 스택 창 리버스 엔지니어링 툴 v 스택 창 기능 § EBP, ESP 주소 값으로 스택 창 이동하기 • EBP : 함수가 호출되어 시작되는 위치의 주소 값 • 스택에서 마우스 오른쪽 버튼 클릭 : [Go to EBP] 메뉴 실행 • 현재 EBP 레지스터가 가리키는 주소 값에 해당하는 위치로 스택 이동 [그림 5 -40] EBP에 해당하는 주소로 스택 창 이동 48/82

리버스 엔지니어링 툴 v 스택 창 기능 § 스택 고정하기 • [Lock stack] : 리버스 엔지니어링 툴 v 스택 창 기능 § 스택 고정하기 • [Lock stack] : 스택이 표시되는 윈도우가 ESP의 값에 따라서 변하는 것을 막을 때 사용 § 스택 값 확인하기 • [Show ASCII dump]나 [Show UNICODE dump] 메뉴 실행 • 스택에 들어 있는 데이터를 아스키 값이나 유니코드 값으로 확인 [그림 5 -41] 스택 내용을 아스키 문자로 확인 49/82

리버스 엔지니어링 툴 § 스택 상대 주소 확인하기 • [Address]-[Relative to. EBP] 메뉴 : 리버스 엔지니어링 툴 § 스택 상대 주소 확인하기 • [Address]-[Relative to. EBP] 메뉴 : EBP를 기준으로 스택의 상대 주소 확인 [그림 5 -43] EBP 기준 스택의 상대 주소 출력된 결과 50/82

리버스 엔지니어링 툴 v 기타 툴 § IDA • 디스어셈블러로 올리 디버거와 마찬가지로 리버스 리버스 엔지니어링 툴 v 기타 툴 § IDA • 디스어셈블러로 올리 디버거와 마찬가지로 리버스 엔지니어링에 매우 많이 사용 • 보통 리버서(리버스 엔지니어링을 수행하는 사람)는 올리 디버거와 IDA를 병용 • IDA의 강력한 기능 : 함수의 실행 관계를 그래프 형태로 보여주는 것 [그림 5 -45] IDA 실행 화면 51/82

리버스 엔지니어링 툴 [그림 5 -46] 그래프 형태로 분석된 함수 실행 구조 52/82 리버스 엔지니어링 툴 [그림 5 -46] 그래프 형태로 분석된 함수 실행 구조 52/82

리버스 엔지니어링 툴 v 기타 툴 § Process Monitor • 레지스터 모니터, 파일 모니터, 리버스 엔지니어링 툴 v 기타 툴 § Process Monitor • 레지스터 모니터, 파일 모니터, 네트워크 모니터, 프로세스 및 스레드 모니터가 있다. ` [그림 5 -48] Process Monitor 실행 결과 53/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § 리버스 엔지니어링으로 얻을 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § 리버스 엔지니어링으로 얻을 수 있는 것은 프로그램 실행 구조와 로직이다. § 프로그램 코드 #include "stdafx. h" #include "stdio. h“ #include "string. h“ int main(int argc, char* argv[]) { char password[12] ; char Correct_password[12] = "abcd"; printf("Input the password!!n"); scanf("%s", &password); } if (strcmp(password, Correct_password)==0) printf("%s !! is the Correct Password!n", password); else printf("%s !! is a Wrong Password!n", password); return 0; 54/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 1 v 실습용 테스트 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 1 v 실습용 테스트 파일 생성 § 실행시 다음과 같이 패스워드를 입력 § abcd 입력시 틀리면 ‘∼ !! is a Wrong Password!’, 맞으면 ‘abcd !! is the Correct Password!’출력 [그림 5 -49] Reverse_2. exe 실행 결과 v 파일 열기 2 § [File]-[Open]에서 Reverse_2. exe 파일 열기 55/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 포인트 찾기 § 잘못된 패스워드 입력시, ‘∼ !! is a Wrong Password!’메시지 출력 § 이 메시지 출력 지점을 시작점으로 검증 로직 찾아보자. § 올리 디버거 어셈블리어 영역에서 마우스 오른쪽 버튼 클릭 § [Search for]-[All referenced text strings] 메뉴 실행 [그림 5 -50] [Search for]-[All referenced text strings] 메뉴의 실행 56/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 포인트 찾기 § [Search for text] 메뉴 : 파일이 큰 경우 사용 [그림 5 -51] [Search for]-[All referenced text strings] 메뉴 실행 57/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 3 v 리버스 엔지니어링 포인트 찾기 § 해당 문자열에서 마우스 오른쪽 버튼 클릭 [Follow in Disassembler] 메뉴 선택 § 어셈블리어 코드 확인 [그림 5 -52] [Follow in Disassembler] 메뉴의 실행 58/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 4 v 프로그램 변경 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 4 v 프로그램 변경 포인트 찾기 순번 주소 어셈블리어 코드와 주석 1 0040106 B CALL REVERSE_. strcmp 2 00401070 ADD ESP, 8 3 00401073 TEST EAX, EAX 4 00401075 JNZ SHORT REVERSE_. 0040108 A 5 00401077 LEA EAX, DWORD PTR SS: [EBP-C] 6 0040107 A PUSH EAX ; 7 0040107 B PUSH OFFSET REVERSE_. ? ? [email protected]_0 [email protected]@? $CF>; |format = “%s !! is the ; strcmp /<%s> Correct Password!” 8 00401080 CALL REVERSE_. printf ; printf 9 00401085 ADD ESP, 8 10 00401088 JMP SHORT REVERSE_. 0040109 B 11 0040108 A LEA ECX, DWORD PTR SS: [EBP-C] 12 0040108 D PUSH ECX ; 13 0040108 E PUSH OFFSET REVERSE_. ? ? [email protected]_0 [email protected]@? $CF>; |format = “%s !! is a /<%s> Wrong Password!” 14 00401093 CALL REVERSE_. printf ; 15 00401098 16 0040109 B XOR EAX, EAX 17 0040109 D POP EDI 18 0040109 E printf POP ESI ADD ESP, 8 59/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § (1)번의‘CALL REVERSE_. strcmp’부터 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § (1)번의‘CALL REVERSE_. strcmp’부터 (3)번까지 : 어떤 값을 비교 § (4)번, (10)번 : 점프문 § (4)번 점프 주소 : 0040108 A, 이 값은 (11)번 주소 값 § (10)번 점프 주소 : 0040109 B, 이 값은 (16)번 주소 값 § 문자열을 비교(어셈블리어코드(1)∼(3)) § ZF값 0이 아니면 0040108 A 주소로 점프 § 0040108 A 주소에‘%s !! is a Wrong Password!’ 출력 구문(어셈블리어 코드 (11)∼(14)) § ZF 값이 0 이면 맞는 패스워드 출력 (어셈블리어 코드 (5)∼(8)) 0040109 B로 점프 함수종료 60/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § JNZ 다음의 주소를 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 § JNZ 다음의 주소를 00401077로 바꾸면 ZF 값에 관계없이 문자열 비교 결과와 상관없이 항상 맞는 패스워드 출력, 함수 종료 61/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 5 v 프로그램 변경하기 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 5 v 프로그램 변경하기 § 변경할 라인에서 마우스 오른쪽 버튼 클릭 [Assemble] 메뉴 선택 § JNZ 목적 주소지 00401077로 바꾼 뒤 버튼 클릭 팝업창 닫기 [그림 5 -55] 어셈블리어 구문 변경 62/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 프로그램 변경하기 5 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 프로그램 변경하기 5 § 해당 라인에서 마우스 오른쪽 버튼 클릭 [Copy to executable]-[Selection] 메뉴 선택 § 마우스 오른쪽 버튼 클릭 [Save File] 메뉴로 파일을 다른 이름으로 저장 (a) 변경된 프로그램 저장하기 1 [그림 5 -56] 변경된 프로그램 저장하기 63/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 프로그램 변경하기 5 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 프로그램 변경하기 5 (b) 변경된 프로그램 저장하기 2 [그림 5 -56] 변경된 프로그램 저장하기 64/82

실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 결과 확인하기 : 실습 5 -2 바이너리 파일 수정을 통해 리버스 엔지니어링 공격하기 v 결과 확인하기 : 저장한 파일 실행 6 [그림 5 -57] 변경된 프로그램 확인 65/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 § 프로그램의 검증 로직을 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 § 프로그램의 검증 로직을 우회하는 공격 수행 1 v 파일 열기 2 v 리버스 엔지니어링 포인트 찾기 [그림 5 -58] REVERSE_2. EXE의 검증 로직 부분 66/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 3 v 로직 분석 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 3 v 로직 분석 § ‘PUSH OFFSET REVERSE_. ? ? [email protected]_0 [email protected]@Inpu>; /format =“ Input the password!!’구문, ‘JNZ SHORT REVERSE_. 0040108 A’구문 순번 주소 어셈블리어 코드와 주석 1 00401045 PUSH OFFSET REVERSE_. ? ? [email protected]_0 [email protected]@Inpu>; /format =“ Input the password!!” 2 0040104 A CALL REVERSE_. printf 3 0040104 F ADD ESP, 4 4 00401052 LEA EAX, DWORD PTR SS: [EBP-C] 5 00401055 PUSH EAX 6 00401056 PUSH OFFSET REVERSE_. ? ? [email protected]_02 [email protected]? $CFs? >; /format = “%s” 7 0040105 B CALL REVERSE_. scanf 8 00401060 ADD ESP, 8 9 00401063 LEA ECX, DWORD PTR SS: [EBP-18] 10 00401066 PUSH ECX 11 00401067 LEA EDX, DWORD PTR SS: [EBP-C] ; | 12 0040106 A PUSH EDX ; |s 1 13 0040106 B CALL REVERSE_. strcmp ; strcmp 14 00401070 ADD ESP, 8 15 00401073 TEST EAX, EAX 16 00401075 JNZ SHORT REVERSE_. 0040108 A ; printf ; scanf ; /s 2 67/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 § (1), (2)번 프로그램 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 § (1), (2)번 프로그램 실행 시 출력되는 ‘Input the password!!’ 출력 § (3) ∼ (8) 입력된 패스워드 스택 저장 § (9)∼(10)번 SS : [EBP-18] 주소 값 ECX에 저장 § (11)∼(12)번 SS : [EBP-C] 주소 값 EDX에 저장, (13)번에서 strcmp 함수 호출 § ECX에 저장된 SS : [EBP-18] 값과 EDX에 저장된 SS : [EBP-C] 값을 비교하는 것임 68/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 § 00401060 주소에 브레이크 포인트 설정→ F 9 눌러 REVERSE_2. EXE 파일 올리 디버거에서 실행 § DOS 창에서 ‘Inputthe password!!’ 메시지 확인 [그림 5 -59] Reverse_2. exe 프로그램 실행 69/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 § aaaa를 입력하고 Enter : 올리디버거에서 브레이크 포인트에서 정지 확인 [그림 5 -60] Reverse_2. exe 프로그램 실행 후 브레이크 포인트 확인 70/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 § 현재 EBP는 0 x 0012 FF 00, F 7 눌러 한 단계 진행, 레지스터 창에서 EBP 선택 → 마우스 오른쪽 버튼 클릭→ [Follow in Stack] 메뉴 선택 스택 내용 확인 [그림 5 -61] EBP 값 기준 스택 조회 71/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 § 스택의 각 라인에서 마우스 오른쪽 버튼 눌러 [Show ASCII dump] 메뉴 선택 § [Address]-[Relative to EBP]’를 선택 § EBP 기준으로 아스키로 스택의 내용 바꿔 내용 확인 [그림 5 -62] EBP 값 기준 스택 조회 결과 72/82

실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 실습 5 -3 프로그램 로직 분석을 통해 리버스 엔지니어링 공격하기 4 v 로직 확인 § ‘EBP-C’ 문자열과 ‘EBP-18’ 문자열 비교, 패스워드 적절성 여부 검사 § ‘ aaaa’는 테스트용으로 넣은 문자열, ‘ abcd’가 맞는 문자열 ` ` [그림 5 -63] 0 x 00401070까지 실행한 결과 § 다시 실행하여‘abcd’ 입력 73/82

리버스 엔지니어링에 대한 대응책 § 안티 리버싱(Anti-Reversing) : 리버스 엔지니어링을 어렵게 만드는 기술 v 리버스 엔지니어링에 대한 대응책 § 안티 리버싱(Anti-Reversing) : 리버스 엔지니어링을 어렵게 만드는 기술 v 패킹 § 원본 프로그램을 새로운 PE 파일에 패킹된 형태로 압축, 암호화하여 저장하는 기술 § 패킹된 프로그램은 프로그램이 정상적으로 실행될 수 있도록 복호화하고 압축을 풀어내는 로직 포함 74/82

리버스 엔지니어링에 대한 대응책 v 안티 디버깅 : 수행되는 디버거의 활동을 탐지하여 프로그램 강제 리버스 엔지니어링에 대한 대응책 v 안티 디버깅 : 수행되는 디버거의 활동을 탐지하여 프로그램 강제 종료 v 타이밍 체크 § 프로세스가 디버깅 중 CPU 연산 시간이 정상적으로 실행되었을 때보다 많이 걸린다는 점에서 착안 § RDTSC(Read Time-Stamp Counter) 명령 : 두 구간 사이의 Time Stemp 값 비교 § 시간이 많이 걸리는 특정구간을 디버깅 중으로 판단, 프로그램이나 디버거 종료 v 쓰레기 코드 넣기와 치환 § 코드 사이에 의미가 없는 쓰레기(Garbage Code) 코드를 넣고 다단계의 점프 문을 섞어 코드를 치환(Permutation) 배치 75/82

실습 5 -4 UPX 패킹하기 § 가장 일반적으로 쓰이는 패킹기술, 주목적은 코드의 암호화가 아닌 실습 5 -4 UPX 패킹하기 § 가장 일반적으로 쓰이는 패킹기술, 주목적은 코드의 암호화가 아닌 압축로직 확인 1 v UPX 다운로드 [그림 5 -65] UPX 다운로드 76/82

실습 5 -4 UPX 패킹하기 2 v UPX를 통한 패킹 수행 : 옵션 확인 실습 5 -4 UPX 패킹하기 2 v UPX를 통한 패킹 수행 : 옵션 확인 [그림 5 -66] UPX 옵션 확인 77/82

실습 5 -4 UPX 패킹하기 § 압축을 위한 패커 upx -v c: REVERSE_2DebugREVERSE_2. exe 실습 5 -4 UPX 패킹하기 § 압축을 위한 패커 upx -v c: REVERSE_2DebugREVERSE_2. exe [그림 5 -67] UPX를 이용한 REVERSE_2. exe 패킹 78/82

실습 5 -4 UPX 패킹하기 3 v UPX를 통한 패킹 결과 확인 § UPX를 실습 5 -4 UPX 패킹하기 3 v UPX를 통한 패킹 결과 확인 § UPX를 이용 패킹한REVERSE_2. exe 파일 올리 디버거로 다시 열어보자 § 원래는 확인 가능하던 어셈블리어 코드 내용을 전혀 확인 할 수 없다 [그림 5 -68] UPX로 패킹한 REVERSE_2 파일 79/82

실습 5 -4 UPX 패킹하기 4 v UPX 파일 언패킹 § UPX 등으로 패킹된 실습 5 -4 UPX 패킹하기 4 v UPX 파일 언패킹 § UPX 등으로 패킹된 파일 분석 위해서는 다시 언패킹 § 언패킹하기 전에 어떤 패커로 패킹되었는지 확인(PEi. D, Exeinfo PE와 같은 툴 사용) § 래는 확인 가능하던 어셈블리어 코드 내용을 전혀 확인 할 수 없다 ` [그림 5 -69] Exeinfo PE를 이용해 UPX로 패킹된 파일 확인 80/82

실습 5 -4 UPX 패킹하기 § UPX로 패킹된 파일은 -d 옵션 이용 다시 풀 실습 5 -4 UPX 패킹하기 § UPX로 패킹된 파일은 -d 옵션 이용 다시 풀 수 있다. upx -d c: REVERSE_2DebugREVERSE_2. exe [그림 5 -70] UPX를 이용한 REVERSE_2. exe 언패킹 81/82

IT Cook. Book, 정보 보안 개론과 실습 : 시스템 해킹과 보안(개정판) IT Cook. Book, 정보 보안 개론과 실습 : 시스템 해킹과 보안(개정판)