AI, 클라우드, 문서, 자동화/파이썬 요리조리
당황하지 말자, 기억나지 않는 문서 암호/비밀번호 찾기(1)
아톨
2025. 8. 22. 01:00
반응형
본인이 작성한 오피스(워드, 엑셀, 파워포인트)나 집파일에 암호를 걸어두고, 시간이 지나 비밀번호가 생각나지 않을때가 종종 있어 난처한 경우가 발생합니다. 이때, 시간 여유가 많이 있고 또한 아주 간단한 암호를 설정했다면 '단순 brute-force(무차별 대입) 방식'을 시도해 볼 수 있습니다. (*암호화된 파일을 분실한 경우, 개발사에서도 암호를 복구해 주지 않는 것으로 알고 있습니다. 사본/이전본을 찾는 게 현실적인 해법입니다. 추가로, 본문 하단에 암호분실을 대비한 예방팁을 정리하였습니다.)
- ZIP 파일
- zipfile 모듈로 열 수 있고, extractall(pwd=...) 같은 방식으로 비밀번호 검증 가능.
- MS Office (ppt, pptx, doc, docx, xls, xlsx 등)
- pptx/docx/xlsx는 사실상 ZIP 압축 기반 구조지만, 내부에 MS가 정한 암호화 헤더가 포함돼 있음.
- 단, 전용 라이브러리 필요.
- 아래한글(HWP)
- HWP 5.0 이후는 OLE Compound File 포맷 (마이크로소프트 OLE 구조).
- 암호화는 자체 알고리즘으로 되어 있어 파이썬에서 직접 풀 수 있는 공개 라이브러리는 사실상 없음.
- → olefile + 한글 암호화 해석 구현이 필요 (공식 라이브러리 없음).
- 암호화된 HWP는 한글에서 AES, SHA1 기반 암호화를 쓰는데, 비밀번호 없이는 복호화 불가.
- 가능하다면 “암호 해제 프로그램” (상용 소프트웨어) 사용이 현실적이나, 현재까지 그러한 프로그램은 없다고 알고 있음.
1. 통합 코드 (ZIP + MS Office 파일 비밀번호 찾기)
# pip install msoffcrypto-tool
import itertools
import zipfile
import msoffcrypto
import io
import os
class PasswordCracker:
"""
다양한 조합으로 비밀번호를 추측하여 ZIP, DOCX, XLSX, PPTX 파일의
암호를 해독하는 클래스입니다.
"""
def __init__(self, passwd_string, min_len, max_len):
"""
클래스를 초기화합니다.
Args:
passwd_string (str): 비밀번호에 사용될 문자열(예: '0123456789').
min_len (int): 추측할 비밀번호의 최소 길이.
max_len (int): 추측할 비밀번호의 최대 길이.
"""
self.passwd_string = passwd_string
self.min_len = min_len
self.max_len = max_len
def crack(self, file_path):
"""
주어진 파일의 암호를 해독하는 메인 함수입니다.
파일 확장자에 따라 적절한 해독 메서드를 호출합니다.
Args:
file_path (str): 암호를 해독할 파일의 경로.
Returns:
str or None: 비밀번호를 찾으면 비밀번호를, 찾지 못하면 None을 반환.
"""
file_ext = os.path.splitext(file_path)[1].lower()
if file_ext == ".zip":
return self._crack_zip(file_path)
elif file_ext in [".pptx", ".docx", ".xlsx"]: # 'xlsx'는 문자열로 변경
return self._crack_office(file_path)
else:
print(f"[!] {file_ext} 형식은 지원하지 않습니다.(zip, office만 지원)")
return None
def _crack_zip(self, file_path):
"""
ZIP 파일의 암호를 해독하는 함수입니다.
비밀번호를 찾으면 즉시 해당 비밀번호를 반환하고, 함수를 종료합니다.
"""
try:
zFile = zipfile.ZipFile(file_path)
except zipfile.BadZipFile:
print("[-] 유효하지 않은 ZIP 파일입니다.")
return None
for length in range(self.min_len, self.max_len + 1):
for attempt in itertools.product(self.passwd_string, repeat = length):
passwd = "".join(attempt)
# 시도 중인 비밀번호를 터미널에 표시 (동일 라인에 덮어쓰기)
print(f"[*] 시도 중: '{passwd}'", end='\r')
try:
zFile.extractall(pwd=passwd.encode('utf-8'))
print(f"\n[+] 비밀번호는 '{passwd}'입니다.(zip)")
return passwd # 비밀번호를 찾으면 즉시 반환
except (RuntimeError, zipfile.BadZipFile):
# 비밀번호가 틀렸을 때 발생하는 예외는 무시하고 다음 시도를 계속
continue
print("\n[-] 비밀번호를 찾지 못했습니다.(zip)")
return None
def _crack_office(self, file_path):
"""
MS Office 파일의 암호를 해독하는 함수입니다.
비밀번호를 찾으면 즉시 해당 비밀번호를 반환하고, 함수를 종료합니다.
"""
for length in range(self.min_len, self.max_len + 1):
for attempt in itertools.product(self.passwd_string, repeat=length):
passwd = "".join(attempt)
# 시도 중인 비밀번호를 터미널에 표시 (동일 라인에 덮어쓰기)
print(f"[*] 시도 중: '{passwd}'", end='\r')
try:
with open(file_path, "rb") as f:
office_file = msoffcrypto.OfficeFile(f)
office_file.load_key(password=passwd)
decrypted = io.BytesIO()
office_file.decrypt(decrypted)
print(f"\n[+] 비밀번호는 '{passwd}'입니다.(office)")
return passwd # 비밀번호를 찾으면 즉시 반환
except Exception as e:
# 비밀번호가 틀렸을 때 발생하는 예외는 무시하고 다음 시도를 계속
continue
print("\n[-] 비밀번호를 찾지 못했습니다.(office)")
return None
if __name__ == "__main__":
# 비밀번호에 사용될 문자와 최소/최대 길이 설정
passwd_string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
cracker = PasswordCracker(passwd_string, min_len=3, max_len=4)
# 파일 경로 지정
file_path = "워드암호파일_123.docx"
cracker.crack(file_path)
- 파일 확장자 자동 구분
- .zip → zipfile 모듈로 brute-force
- .pptx/.docx/.xlsx → msoffcrypto-tool로 brute-force
- 무차별 대입(brute-force)
- min_len ~ max_len 길이의 모든 조합을 생성 (itertools.product)
- 하나씩 대입 → 맞으면 성공, 프로그램 종료

[ 예방 팁 ]
- 비밀번호 관리자 사용: 조직/개인별로 안전하게 공유·보관.
- 버전 기록이 있는 저장소 사용: OneDrive/SharePoint/Google Drive 등.
- 중요 문서는 이중 보호: 암호+접근권한(ACL)로 관리하고, 비상 복구 담당자/절차를 미리 지정.
- 규칙적 백업: 로컬+클라우드 3-2-1 규칙(사본 3개, 매체 2종, 오프사이트 1개).
반응형