
본 글은 연구목적으로 작성된 글이며 불법적 용도로 사용을 금합니다
[참고 논문] 윈도우 환경에서 카카오톡 데이터 복호화 및 아티팩트 분석 연구
카카오톡은 국내에서 가장 널리 사용되는 메신저로, PC 버전에서는 대화 기록을 EDB(Extensible Database) 파일 형태로 저장합니다.
하지만 이 파일은 SQLite 기반이지만 AES 암호화되어 있어 일반적인 방법으로는 접근이 어렵습니다.
1, 2편에서는 카카오톡 EDB 파일 복호화 파이썬 코드를 만들어보고 uuid, modelName, serialNumber 등을 확인하는 방법과 모든 것들을 다 조합하여 복호화에 성공한 EDB 파일을 sqLite browser 프로그램을 활용하여 내부 구조를 살펴보았습니다.
이번 편에서는 userid를 찾는 방법을 알아보도록하겠습니다.
2. 왜 userid를 알아야 하는가?
아래 코드를 보면 key와 iv 생성시에 pragma와 userid가 필요하게 되어있습니다. userid는 카카오톡 user마다 고유하게 부여되는 숫자로 최대 4억개정도(000000001~400000000)가 되는걸로 추정됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 |
def generate_key_and_iv(pragma, userId): # Pragma와 userId를 결합하여 512바이트까지 확장 key = (pragma + userId) * (512 // len(pragma + userId) + 1) key = key[:512] # MD5 해싱을 통해 Key 생성 key_hash = hashlib.md5(key.encode()).digest() # Base64 인코딩 후 다시 MD5 해싱을 통해 IV 생성 iv = hashlib.md5(base64.b64encode(key_hash)).digest() return key_hash, iv |
2. userid를 알아내는 방법
논문 “윈도우 환경에서 카카오톡 데이터 복호화 및 아티팩트 분석 연구” 에서 userid
를 찾는 방법을 정리하면 다음과 같습니다.
📌 카카오톡 EDB 파일에서 userid
찾는 방법
✅ 1. userid
의 역할
userid
는 카카오톡 데이터베이스 복호화에 필요한 입력값 중 하나로 사용됨- 하지만 기기 내에서 직접 획득할 수 없는 정보이므로 별도의 추론 과정이 필요함
✅ 2. userid
를 알아내는 방법
(1) 일반적인 전수조사 방법 (Brute Force)
userid
값을 1부터 순차적으로 증가시키면서 데이터베이스 복호화를 시도- 복호화 후 데이터 무결성 검사(
pragma integrity_check
) 가 정상적으로 실행되면 해당userid
가 올바른 값으로 판별됨
📌 알고리즘 요약
pragma
와userid
를 512바이트까지 반복하여 연결한 후 MD5 해시를 수행하여key
생성key
를 Base64 인코딩 후 MD5 해시를 수행하여iv
생성- 생성된
key, iv
를 사용해 AES 복호화 수행 - SQLite 데이터베이스 무결성 검사 실행
- 검사 통과 시 해당
userid
를 정답으로 판별
📌 단점
- 데이터베이스 파일 크기만큼 파일 I/O 및 SQL 실행이 반복되어 속도가 느림
(2) SQLite 헤더 기반 전수조사 방법
- SQLite 데이터베이스 파일의 상위 16바이트 헤더를 활용하여
userid
를 추론 - 복호화한 결과를 알려진 SQLite 파일 헤더 값과 비교하여 올바른
userid
를 판별
📌 장점
- 데이터베이스 전체를 복호화하지 않고 파일의 앞부분(16바이트)만 복호화하여 속도 향상
📌 단점
- 여전히
userid
변경 시마다 AES 키 스케줄을 반복 생성해야 하는 비효율적인 부분 존재
(3) 사용자 디렉토리명 기반 전수조사 방법 (가장 효율적)
- 카카오톡은 사용자별로 고유한 디렉토리를 생성하며, 이 디렉토리명은
userid
를 기반으로 암호화됨 - 따라서 디렉토리명을 복호화하여
userid
를 찾는 방식이 가능함
📌 알고리즘 요약
KAKAOTALK_PC_FOREVER
문자열을 MD5 해시하여key
생성Base64
인코딩 후 MD5 해시를 수행하여iv
생성- AES 암호화를 수행하여
userid
기반 사용자 디렉토리명 생성 - 기존 사용자 디렉토리명과 비교하여 일치하는
userid
를 찾음
📌 장점
- 파일 I/O와 SQL 실행 없이
userid
를 빠르게 찾을 수 있음 - AES 키 스케줄을 반복하지 않고 한 번 생성한 키를 재사용 가능
📌 실제 성능 비교 (전수조사 시간)
전수조사 방식 | 소요 시간 (4억 개 기준) |
---|---|
일반적인 전수조사 방법 | 35시간 33분 20초 |
헤더 기반 전수조사 | 17분 50초 |
사용자 디렉토리명 기반 전수조사 | 1분 30초 |
➡ 가장 빠르고 효율적인 방법은 “사용자 디렉토리명 기반 전수조사” 방식
🔍 결론
논문에서는 userid
를 찾기 위한 다양한 방법을 비교하고, 가장 효과적인 방법으로 “사용자 디렉토리명 기반 전수조사” 방식을 제시합니다.
이 방법을 사용하면 기존 방식보다 훨씬 빠르게 userid
를 찾아낼 수 있으며, 파일 접근을 최소화하여 전수조사 시간을 1분 30초까지 단축할 수 있습니다.
3. 코드로 만들어보기
여러가지 방법 중에 헤더 기반 전수조사 방법으로 userid를 찾는 코드를 아래 처럼 만들어 보았습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def read_encrypted_data_from_file(input_filename): with open(input_filename, 'rb') as f: encDB = f.read(16) return encDB input_filename = chatLogs_000000000.edb' encDB = read_encrypted_data_from_file(input_filename) userIdint = 000000001 userId = f"{userIdint:09d}" while userIdint < 400000000: key1, iv1 = generate_key_and_iv(pragma, userId) decDB = decrypt_database(key1, iv1, encDB) string_data = decDB.decode('utf-8', errors='ignore') string_data = string_data.rstrip('\x00') if string_data=="SQLite format 3": print(f"조건충족:userId는 {userId} 입니다.") break print(f"\ruserId찾는중: {userIdint}", end='') # 같은 줄에 현재 숫자를 출력 userIdint += 1 userId= f"{userIdint:09d}" |
시간은 조금 걸리기는 하지만 userid를 찾을 수 있었습니다.
댓글을 남겼는데 안올라가는거같네요ㅠ
앗 올라가네요
안녕하세요. 저는 자바 개발자로서 처음으로 파이썬을 배우고 있으며, 현재 VS Code에서 파이썬을 설치하고 과정을 따라가고 있습니다.
혹시 1편에서 제작하신 하드코딩된 바이트배열을 확인할 수 있는 방법이 궁금합니다. 이에 대한 도움을 주실 수 있을까요?
도움을 주신다면 정말 감사하겠습니다.
방장님 안녕하세요
덕분에 복호화 성공했습니다!
궁금한거 문의해서 메일로 답변주셨는데 늦게나마 인사드립니다 감사합니다
하드코딩된 바이트 배열을 확인하는 방법이 궁금합니다. 부탁드립니다. 감사합니다
기재된 이메일로 안내드렸습니다!!
댓글을 남겼는데 안 올라가는 것 같네요.. 한번 확인 가능하실까요
댓글은 제가 승인한 후에 공개가 됩니다.
글은 문제없이 올라가오니 이후에 글 남기시는 분들도 참고하시기 바랍니다~
좋은 글 작성해주셔서 감사합니다.
올려주신 내용 바탕으로 진행해보고 있는데, 하드코딩된 바이트 배열을 확인법 여쭤보고 싶습니다. 감사합니다
기재된 이메일로 안내드렸습니다!
안녕하세요 작성자님! 하드코딩된 바이트 배열을 확인법 여쭤보고 싶습니다. 감사합니다
기재된 이메일로 안내드렸습니다!
작성자님 죄송하지만 이메일로 아무것도 안와서..
다시 보내주실수 있나요..?
바쁘신데 죄송합니다 ㅠㅠ
기재된 이메일로 다시 안내드렸습니다!
안녕하세요!
하드코딩된 바이트 배열을 찾고싶은데 몇일째 방황하고 있네요 ㅠㅠ
혹시 확인법에 대해 여쭤보고 싶습니다.
기재된 이메일로 안내드렸습니다!
안녕하세요!
하드코딩된 바이트 배열을 며칠 째 찾아보고 있는데 생각보다 힘드네요, 그래서 바이트 배열을 알아내는 방법을 알아내고 싶은데 가능할까요?
기재된 이메일로 안내드렸습니다!