Microsoft 오피스 패스워드 검증과 문서 암호 해제

오피스 문서 포맷에 걸린 패스워드 검증과 문서 암호 해제에 대하여 알아봅니다.

테스트 환경 : Windows 7 & Office 2013 (엑셀 및 워드)

# 패스워드 검증 

먼저, 패스워드를 걸은 문서를 준비합니다.
오피스에서 패스워드를 설정할때 읽기 패스워드와 쓰기 패스워드를 설정해야 하는데 본 포스팅에서는 읽기 패스워드 검증만 다룹니다.

SSView.zip

오피스 문서의 구조를 볼 수 있는 Structured Storage Viewer로 문서 파일을 열어보면, EncryptionInfo에서 암호화 정보를 XML로 확인할 수 있습니다. 제 문서의 경우는 아래와 같았습니다.



아래 링크에 각 항목에 대한 설명이 있습니다.

읽기 패스워드를 검증하기 위해선 아래의 keyEncryptor 구조만 보면 됩니다. 
대략 살펴보면 반복 해시 10만번, salt 16바이트, AES256-CBC, SHA512 정도가 보입니다.
해당 정보들은 오피스 버전마다 다릅니다. 버전이 올라갈수록 암호화 강도도 세집니다.
(오피스 2007의 경우 반복 해시 0번에 SHA을 사용합니다.)

패스워드를 검증하는데 필요한 항목은 saltValue, encryptedVerifierHashInput, encryptedVerifierHashValue 이 세가지 입니다. 디코드하면 각각 16바이트, 16바이트, 64바이트입니다. 

salt는 사용자 입력 패스워드에 덧붙이는 랜덤 난수 생성 값으로 복호화 시 IV에 사용됩니다.
encryptedVerifierHashInput와 encryptedVerifierHashValue는 암호화 된 검증용 값들로 패스워드 해시로 유도한 대칭키로 복호화 한 후 패스워드가 올바른지 검증하는데 사용합니다.

패스워드를 검증하는 일련의 과정을 간략하게 도식화하면 아래와 같습니다.


[키 생성]


[키 검증]


첫번째 그림은 키 생성부입니다. 2개의 대칭키(복호화 키)를 뽑아내고 있습니다. 1 ~ 5)번까지의 과정입니다. 두번째 그림은 키 검증부입니다. 6 ~ 8)번까지의 과정입니다.

 

1) 16바이트 salt와 사용자 입력 패스워드를 sha512 해시(이하 해시)합니다.

2) 현재의 spin count를 입력하고 1)에서 생성한 해시를 붙입니다. (spin count (4바이트) + hash (64바이트))

3) 2)를 해시하고 spin count 뒤에 붙입니다. 이를 10만번 반복합니다. 최종적으로 패스워드 해시가 생성됩니다.


4) hash input 블록키를 패스워드 해시 뒤에 붙이고 해시합니다. 해당 해시는 encryptedVerifierHashInput의 대칭키가 됩니다.

5) hash value 블록키를 패스워드 해시 뒤에 붙이고 해시합니다. encryptedVerifierHashValue의 대칭키가 됩니다.

이제 얻어낸 키로 암호화 된 2개의 데이터를 복호화 해야 합니다.

AES 256비트와 CBC모드를 사용중이며 IV는 32바이트인데 salt (16바이트) + 패딩 0 (16바이트)로 되어 있습니다.

6) 4, 5)에서 얻어낸 각각의 대칭키를 넣고 복호화를 하여 16바이트 / 64바이트 데이터를 얻습니다.

7) 복호화 된 hash input 데이터를 해시한 후 복호화 된 hash value와 비교합니다.

8) 일치하면 올바른 패스워드입니다. 


# 문서 암호 해제 

복호화를 하기 전에 원본 문서 길이(복호화 길이)와 암호화된 문서 데이터를 알아야 합니다.


문서의 구조를 보면 EncryptedPackage 라는 항목이 있는데 원본 문서를 암호화 한 데이터가 들어가 있는 항목입니다.
첫번째 8바이트는 복호화 길이로 0x2071 = 8305바이트를 포함한다고 명시되어 있습니다.
암호화 된 데이터의 위치는 오프셋 0x8부터 끝까지입니다.

다시 xml구조를 봅니다. 문서를 복호화하는데 필요한 항목은 패스워드 검증할 때와 조금 다릅니다. 
keyEncryptor 구조의 encryptedKeyValue와 keyData 구조의 saltValue만 있으면 됩니다.

encryptedKeyValue는 암호화 된 대칭키입니다. 이 키로 문서를 복호화합니다. saltValue는 IV를 생성할 때 사용하는 salt입니다. 디코드를 하면 각각 32바이트, 16바이트입니다.

복호화 시 중요한 점은 문서 전체를 한번에 복호화 하는 것이 아닌 블록 단위 (4096바이트)로 합니다. 이 과정에서 IV는 매번 다른 값을 사용합니다.

1) key 블록키를 패스워드 해시 뒤에 붙이고 해시합니다. 해당 해시는 encryptedKeyValue의 대칭키가 됩니다. (블록키는 소스를 참조)

2) 1)에서 얻어낸 키로 복호화를 하여 32바이트 대칭키를 얻습니다.


3) IV연산은 16바이트 salt 에 4바이트 블록키를 더해서 생성합니다. 디폴트 블록키는 0이며 한 사이클당 1씩 증가합니다.

4) salt+블록키 = 20바이트를 해시합니다.

5) 해시된 데이터를 32바이트 컷합니다. (해시에 1 2 3  ... 64가 담겼다고 가정할 경우 32에서 컷) 해당 데이터를 IV로 사용합니다.

6) 대칭키와 IV, 그리고 암호화된 문서 블록(4096바이트)를 가지고 복호화합니다.

7) 3)부터 N번만큼 복호화를 반복합니다. 마지막 복호화의 길이는 원본문서길이 % 블록 사이즈입니다. 원본 길이가 8305이면 N은 3, 마지막 암/복호화 길이는 113입니다.

복호화된 데이터는 오피스에서 바로 오픈할 수 있습니다.


+ Recent posts