파이썬에서는 multiprocessing 모듈을 이용해서 여러 코어에서 동시에 조합을 시도할 수 있습니다. 다만, 비밀번호 크래킹을 단순 brute-force(완전 탐색)로만 하면 경우의 수가 기하급수적으로 커져서 사실상 현실적으로 풀기 힘들어집니다. 그래서 실제 보안 연구나 해킹 실무에서는 여러 현대식 접근 방식이 사용되는데, 아래 코드 하단에 정리합니다.

 

2. 멀티코어 병렬처리, 비밀번호 찾기 (ZIP + MS Office)

 
import itertools
import zipfile
import msoffcrypto
import io
import os
import multiprocessing as mp

class PasswordCracker:
    """
    다양한 조합으로 비밀번호를 추측하여 ZIP, DOCX, XLSX, PPTX 파일의
    암호를 해독하는 클래스입니다.
    멀티프로세싱을 사용하여 속도를 높입니다.
    """
    def __init__(self, passwd_string, min_len, max_len, processes=None):
        """
        클래스를 초기화합니다.
       
        Args:
            passwd_string (str): 비밀번호에 사용될 문자열(예: '0123456789abc').
            min_len (int): 추측할 비밀번호의 최소 길이.
            max_len (int): 추측할 비밀번호의 최대 길이.
            processes (int, optional): 사용할 프로세스(코어)의 수. 지정하지 않으면 CPU 코어 수만큼 사용.
        """
        self.passwd_string = passwd_string
        self.min_len = min_len
        self.max_len = max_len
        self.processes = processes or mp.cpu_count()

    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"]:
            return self._crack_office(file_path)
        else:
            print(f"[!] {file_ext} 형식은 지원하지 않습니다. (zip, office만 지원)")
            return None

    # --- ZIP 파일 해독 관련 메서드 ---
    def _try_zip_password(self, args):
        """
        하나의 비밀번호로 ZIP 파일의 압축을 해제해 보는 함수입니다.
        성공하면 비밀번호를 반환하고, 실패하면 None을 반환합니다.

        Args:
            args (tuple): (파일 경로, 비밀번호) 튜플.

        Returns:
            str or None: 성공 시 비밀번호, 실패 시 None.
        """
        file_path, password = args
        try:
            zFile = zipfile.ZipFile(file_path)
            zFile.extractall(pwd=password.encode('utf-8'))
            return password
        except:
            return None

    def _crack_zip(self, file_path):
        """
        멀티프로세싱을 사용하여 ZIP 파일의 암호를 해독하는 함수입니다.
        각 비밀번호 추측 시도마다 터미널에 진행 상황을 표시합니다.

        Args:
            file_path (str): ZIP 파일의 경로.
           
        Returns:
            str or None: 비밀번호를 찾으면 비밀번호를, 찾지 못하면 None을 반환.
        """
        print(f"[*] ZIP 파일 '{file_path}' 암호 해독 시작...")
        with mp.Pool(self.processes) as pool:
            for length in range(self.min_len, self.max_len + 1):
                attempts = ("".join(p) for p in itertools.product(self.passwd_string, repeat=length))
                args_gen = ((file_path, pwd) for pwd in attempts)
               
                # imap_unordered를 사용하여 결과를 비동기적으로 처리
                for result in pool.imap_unordered(self._try_zip_password, args_gen, chunksize=1000):
                    # 현재 시도하고 있는 비밀번호를 터미널에 표시
                    print(f"[*] 시도 중: '{result if result else result, ' 실패한 추측'}'", end='\r')
                    if result:
                        print(f"\n[+] 비밀번호는 '{result}' 입니다.(zip)")
                        pool.terminate() # 비밀번호를 찾으면 모든 프로세스 종료
                        return result
       
        print("\n[-] 비밀번호를 찾지 못했습니다.(zip)")
        return None

    # --- MS Office 파일 해독 관련 메서드 ---
    def _try_office_password(self, args):
        """
        하나의 비밀번호로 MS Office 파일의 암호를 해제해 보는 함수입니다.
        성공하면 비밀번호를 반환하고, 실패하면 None을 반환합니다.

        Args:
            args (tuple): (파일 경로, 비밀번호) 튜플.

        Returns:
            str or None: 성공 시 비밀번호, 실패 시 None.
        """
        file_path, password = args
        try:
            with open(file_path, "rb") as f:
                office_file = msoffcrypto.OfficeFile(f)
                office_file.load_key(password=password)
                decrypted = io.BytesIO()
                office_file.decrypt(decrypted)
                return password
        except:
            return None

    def _crack_office(self, file_path):
        """
        멀티프로세싱을 사용하여 MS Office 파일의 암호를 해독하는 함수입니다.
        각 비밀번호 추측 시도마다 터미널에 진행 상황을 표시합니다.

        Args:
            file_path (str): MS Office 파일의 경로.

        Returns:
            str or None: 비밀번호를 찾으면 비밀번호를, 찾지 못하면 None을 반환.
        """
        print(f"[*] MS Office 파일 '{file_path}' 암호 해독 시작...")
        with mp.Pool(self.processes) as pool:
            for length in range(self.min_len, self.max_len + 1):
                attempts = ("".join(p) for p in itertools.product(self.passwd_string, repeat=length))
                args_gen = ((file_path, pwd) for pwd in attempts)
               
                # imap_unordered를 사용하여 결과를 비동기적으로 처리
                for result in pool.imap_unordered(self._try_office_password, args_gen, chunksize=500):
                    # 현재 시도하고 있는 비밀번호를 터미널에 표시
                    print(f"[*] 시도 중: '{result if result else result, ' 실패한 추측'}'", end='\r')
                    if result:
                        print(f"\n[+] 비밀번호는 '{result}' 입니다.(office)")
                        pool.terminate() # 비밀번호를 찾으면 모든 프로세스 종료
                        return result
       
        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)
 

 

  • 멀티프로세싱 사용 (multiprocessing.Pool)
    • 여러 CPU 코어에서 동시에 비밀번호 대입 시도
    • imap_unordered → 결과를 비동기적으로 받아서 성공 즉시 종료
  • 성능 최적화
    • chunksize 조절로 워커별 처리량 최적화
    • 작은 chunksize → 빠른 응답 (즉시 종료 가능)

 

[ Brute-force 이외의 현대적 비밀번호 찾는 방안 정리 ]

1. Dictionary Attack (사전 공격)

  • 미리 만들어둔 비밀번호 후보 사전을 활용해 시도.
  • 예: password123, qwerty, iloveyou, 12345678 등
  • 장점: 실제 사람들이 자주 쓰는 패턴을 빠르게 맞출 수 있음.
  • 단점: 사전에 없는 랜덤 비밀번호는 못 잡음.

2. Hybrid Attack (혼합 공격)

  • 사전 단어 + 규칙 변형
  • 예: password → Password1!, pa$$w0rd, password2025
  • 보통 John the Ripper 나 Hashcat 같은 툴이 이 방식을 자동 지원합니다.

3. Mask Attack (패턴 기반 공격)

  • 비밀번호가 규칙적이라는 전제에서 범위를 줄임.
  • 예: 은행·회사 시스템에서 많이 쓰는 패턴
    • 숫자 6자리 (예: 123456, 202308)
    • 첫 글자 대문자 + 영문 + 숫자 2자리 (예: Abcd12)
  • 범위를 줄여서 brute-force보다 훨씬 빠르게 시도 가능.

4. Rainbow Table Attack

  • 해시된 비밀번호(예: MD5, SHA1 등)에 대해 미리 계산된 해시-평문 매핑 테이블을 이용.
  • 비밀번호 해시만 있으면 빠르게 역추적 가능.
  • 단점: Salt(난수) 기법이 적용된 경우 무력화됨.

5. Rule-based Attack

  • 특정 규칙 기반 변형 (ex. 첫 글자 대문자, 뒤에 ! 붙임).
  • 사전 공격과 결합해 확장.

6. AI / ML 기반 공격 (최신 연구 분야)

  • 최근에는 머신러닝으로 사람들의 비밀번호 생성 습관을 학습한 뒤,
    • 실제로 자주 쓰이는 비밀번호를 확률적으로 예측
    • brute-force보다 훨씬 빠르게 "사람이 쓸 법한" 후보를 뽑아냄
  • 예: PassGAN, OMEN, DeepCrack 같은 연구 프로젝트

7. GPU 가속 (Hashcat, CUDA/OpenCL 활용)

  • CPU 대신 GPU를 이용해 수억~수십억 번/s 시도 가능.
  • 일반 PC에서 brute-force로 8자리 영문/숫자 탐색은 현실적으로 불가하지만,
    • GPU 1대로는 수일
    • GPU 클러스터로는 몇 시간 안에 가능

[ 정리 ]

  • Brute-force는 최후의 방법 (시간 너무 오래 걸림)
  • 현실적인 접근은:
    1. 사전 + 하이브리드 먼저
    2. 특정 패턴/마스크 기반
    3. 그래도 안 되면 GPU 병렬 brute-force

 

반응형

+ Recent posts