본문 바로가기

카테고리 없음

2024.8.12 리버싱 공부(나뭇잎 책)

UPack

-PE 패커

 

PEViewer로는 PE볼 수 없음 UPack으로 패킹하면 PE포멧을 신기하게 바꿔서.

 

Stud_PE로 볼 수 있는데

 

UPack이 주는 지식

 

1.PE 헤더 관련

 

1.1 헤더 겹쳐쓰기

Dos header(MZ헤더)와  NT header을 겹쳐씀. 헤더 공간 절약 및 복잡성 증가

MZ 헤더의 핵심 멤버는

magic number - MZ

e_lfanew - File address of new exe header(NT header 시작 위치)

보통의 경우 e_lfanew = mz크기(40)+Dos stub 크기

UPack에서는 10으로 MZ헤더와 NT 헤더가 겹쳐서 써짐


1.2 File header.SizeOfOptionalHeader 값 변경

File header.SizeOfOptionalHeader - OptionalHeader크기 , 섹션 헤더의 시작 offset

Optional header 시작하는 주소 + SizeOfOptionalHeader 위치에서 섹션 헤더가 시작함

 

UPack에서는 SizeOfOptionalHeader가 148로 정상적인 값 E0 or F0 보다 크게 설정됨.

헤더 안에 디코딩에 필요한 코드를 넣으려고


1.3 OptionalHeader.NumberOfRvaAndSize 값 변경

OptionalHeader의 Directory 구조체 배열의 원소 개수 정상적인 경우 10개 인데 UPack 에서는 A개로 변경.

Directory 구조체 뒤 6개 무시됨. 코드 덮어쓰려고

 

1.4 Section Header에서 사용되지 않는 항목에 데이터 기록.

Section header에서 중요한건

Name

virtual size

RVA

size of raw data

offset to raw data

UPack에서는 그 외의 부분은 덮어써버림

 

2. PE Section 관련

2.1 섹션 겹쳐쓰기

섹션을 겹쳐씀

섹션의 시작 offset과 크기등이 겹치게 씀

섹션의 RVA나 메모리 크기는 다름.

한 섹션에 원본파일을 압축시켜두고

다른 섹션에 코드 실행시 압축된걸 풀어서 실행

 

PE 유틸리티가 분석하기 어려워한 이유

 

1.RVA to RAW에 문제가 있었음.

RAW = RVA - virtualAddress  + PointerToRawData

PointerToRawData값이 FileAlignment의 배수여야하는데 그냥 더해줘서 오류가 생김.

 

2.Import Table이 특이함

Import Table을 보면 Import Descriptor 구조체(14바이트)가 나오는데 마지막은 이 구조체가 null로 차있어야 하는데 파일로 보면 null구조체가 아님.

메모리로 로딩될때 구조체 끝나는 부분까지만 로딩이돼서 남는 부분은 null로 차기때문에 문제가 발생하지 않음.

 

 

UPack 디버깅 방법

실행 흐름 : 

EP로 들어감 -> 디코딩 루프를 탐 -> IAT 세팅함 -> OEP로 감

 

인라인 패치

프로그램이 실행 압축 or 암호화 되어있을때 파일을 직접 수정하기 어렵기때문에 사용되는 기법

 

실행 압축 프로그램 실행 과정

 

원본 파일 Decoding -> jump to OEP -> 실행

 

인라인 패치 실행 과정

 

원본 파일 Decoding -> Jump to Code Cave -> Patch the Code -> jump to OEP -> 실행

 

코드를 수정시키는 역할을 하는 Code Cave라는 부분을 만들어서 실행시키고 OEP로 가는것이 인라인 패치

 

Code Cave 설치 위치

1.파일의 빈 영역 - 크기 작은 경우

2.마지막 섹션을 확장

3.새로운 섹션 추가

섹션의 characteristics에 write속성이 있어야함. 없으면 access violation 발생함.

 

패치하고 싶은 내용과 jump to OEP를 담은 Code Cave를 심고 

jump to OEP 영역을 찾아서 jump to Code Cave로 바꾼다.

바꿀 부분이 암호화되어있다면 복호화를 고려해서 복호화 된 것이 jump to Code Cave가 되도록 바꾼다.