1. Header = 시작위치부터 1 sector (512 byte)
▶ Signature(MagincID): D0 CF 11 E0 A1 B1 1A E1 = HWP문서의 고유 시그니처
▶ CLSID: 0x08 ~ 0x17 (16byte)
▶ Version(Minor Version, Major Version): 3E 00 03 00
▶ Byte Order BOM: FE FF
* UTF-16 : FF FE=little endian, FE FF=Big endian
여기선 little endian방식으로 쓰여 있으므로 FE FF 읽으면 FF FE 즉 little endian방식
* 엔디안(Endian)은 바이트 배열 방법(Byte Order) ex) 12 34 56 78
리틀 엔디안은 최하위 바이트부터 차례대로 저장하는 방식 > 78 56 34 12
빅 엔디안은 최상위 바이트부터 차례대로 저장하는 방식 > 12 34 56 78
▶ BBAT Size : 09 00 => BBAT 1 Sector Size = 512Byte 00 09 = 2^(16^0*9)
▶ SBAT Size : 06 00 => SBAT 1 Sector Size = 64Byte 00 06 = 2^(16^0*6)
▶ 00 00 00 00 00 00 00 00 00 00 (reserved 1~3) =사용X
▶ BBAT Depot Count : 0B 00 00 00 (109개 이상일 경우 ExtraBBAT참조)
▶ Root Storage ID (섹터 시작 번호, 0x30-0x33위치): 02 00 00 00
헤더(512 byte)이후부터 0번으로 시작하기 때문에 헤더의 크기를 더해줘야 함.
섹터 시작 위치 계산: 0x02(=2, root storage ID) * 0x200(=512, sector size) + 0x200(=512, header size)
* root storage 읽기: ID(=2)를 읽고 BBAT를 참조해 모든 sector를 연결 > 읽어온 root storage와 연결된 모든 디렉토리 분석
▶ 00 00 00 00 (reserved 4)
▶ SBAT Reference Size (Max small stream size) : 00 10 00 00 => 4096Byte
▶ SBAT Depot ID (Small Block Allocation Table Depot 시작 섹터 번호): 07 00 00 00
이 위치를 찾아가면 (7+1)*0x200 = 0x1000 = SBAT Depot의 위치임
* 위치로 갈 때 1을 더하는 이유는 sectorID로 접근시 header를 제외해야하기 때문
▶ SBAT Sector Size (Small Block Allocation Table 크기 값, 몇 개의 섹터를 차지하는지) : 01 00 00 00 => 00 00 00 01 -> 1*512(sector size)= 512Byte
▶ start block Extended BBAT(확장된 BBAT시작 섹터 번호): FE FF FF FF (BBAT개수 109 이하)
▶ Extended BBAT Count : 00 00 00 00 (BBAT개수 109 이하, 이상인 경우 확장된 수 만큼 추가됨)
▶ BBAT Depot (0x4C~0x01FF, 헤더 끝): 109개의 BBAT엔트리저장. 4바이트씩 sector ID를 가지고 있음.
순서대로 읽고 연결해 하나의 BBAT 만듦. 최대(109개)를 초과할 경우 start block extended BBAT를 참조해서 확장된 BBAT읽음.
03 =800 / 0C =1A00 / 0D =1C00 / 75 01 =2EC00 / 76 01 =2EE00 / 77 01 =2F000 / 78 01 =2F200 / 79 01 =30000 / A4 03 =74A00 / A5 03 =74C00 / FE 04 =9FE00
▶ Root Entry의 Chain :BBAT를 참고하여 chain 연결. start entry는 Root entry의 Start Sector ID(0x674-0x677)를 이용.
* RootEntry 프로퍼티는 프로퍼티의 크기와 상관 없이 무조건 BBAT를 참조한다.
entry8(09 00 00 00) -> entry9(0A 00 00 00) -> entry10(0B 00 00 00) -> entry11(6E 01 00 00) -> entry366(6F 01 00 00) -> entry367(70 01 00 00) -> entry368 -> entry369 -> entry370 -> entry371 -> entry372(FE FF FF FF)
* 엔트리 빨리 찾아가기: entry366 => 366*4=1464=0x5B8 offset으로 가면 됨
▶ Property List :start entry는 Root Storage ID (0x30-0x33)
entry2 (=(2+1)*512=1536=0x600)-> entry4 -> entry5 -> entry6
▶ FileHeader 스트림
- Name(0x680-6BF) : 46 00 69 00
- Name Length(0x6C0-0x6C1) : 16 00
- Type(0x6C2) : 02 – Stream
* 0–Empty, 1–Storage, 2–Stream, 3–Lock Bytes, 4–Property, 5–Root
- Node Color(0x6C3) : 01
- Left Node : 06 00 00 00 > 좌측 노드는 6개
* 현재 노드(디렉토리)의 좌측 자식 노드의 인덱스 번호. 존재하지 않으면 0xFFFFFFFF
- Right Node : 03 00 00 00 > 우측 노드는 3개
- Child Node : FF FF FF FF > 자식노드는 존재하지 않음
- CLSID(0x6D0-0x6DF)
- Start sector ID(현재 오브젝트의 시작 섹터 ID, 0x6F4-0x6F7)): 43 00 00 00 =67
- Object size: 00 01 00 00(low) / 00 00 00 00(high) =256byte > size가 4096(0x1000)보다 작기 때문에 SBAT참조
67/8=8 block
67%8=3
Root Entry Chain 에서 8번째 엔트리 (0번부터 시작)
(Entry + 1) *512 + 64*나머지값
= (370+1) *512 + 64*3 = 189952+192 = 190144 = 0x2E6C0
'Project > 문서형 악성코드' 카테고리의 다른 글
한글 악성파일 분석 (0) | 2020.12.01 |
---|---|
HWP 파일 구조 분석 (2) | 2020.09.27 |
댓글