Forensics

[포렌식] 윈도우 카카오톡 데이터베이스 복호화 분석 및 구현 #2

pental 2024. 3. 24. 03:21

#1 에서는 윈도우 카카오톡 데이터 베이스 복호화 분석을 진행했다. 

#2 에서는 자동화 하는 기능을 소개하려고 한다. 일단 Pragma를 생성하기 위해서 레지스트리에 접근해야하지 않는가?

def get_pragma() :
    DeviceInfo_Path = "Software\Kakao\KakaoTalk\DeviceInfo"
    keypath = winreg.OpenKey(winreg.HKEY_CURRENT_USER, DeviceInfo_Path, 0, winreg.KEY_READ)
    reg_path = winreg.QueryValueEx(keypath, "Last")[0]
    DeviceInfo_Key_Path = DeviceInfo_Path +"\\" + reg_path
    keypath = winreg.OpenKey(winreg.HKEY_CURRENT_USER, DeviceInfo_Key_Path, 0, winreg.KEY_READ)
    hdd_model = winreg.QueryValueEx(keypath, "hdd_model")[0]
    hdd_serial = winreg.QueryValueEx(keypath, "hdd_serial")[0]
    sys_uuid = winreg.QueryValueEx(keypath, "sys_uuid")[0]
    pragma = f"{sys_uuid}|{hdd_model}|{hdd_serial}"
    f = open("pragma.txt", "w")
    f.write(pragma)
    f.close()
    return pragma
HKCU\Software\Kakao\KakaoTalk\DeviceInfo

위 레지스트리에 존재하는 hdd_model, hdd_serial, sys_uuid 를 가져와서 pragma를 저장한다. 

이제 pragma를 생성했으니 EDB파일들도 복사해와햐하지 않는가?

def copy_kakaotalk_database() :
    local_appdata_path = (os.getenv('LOCALAPPDATA'))
    kakaotalk_path = os.path.join(local_appdata_path, 'Kakao\\KakaoTalk\\users')
    folder_data = (os.listdir(kakaotalk_path))
    user_uuid = []
    for i in folder_data :
        if len(i) == 40 :
            user_uuid.append(i)
    if len(user_uuid) == 1 :
        user_uuid = user_uuid[0]
    else :
        select_index = 0
        for idx, value in enumerate(user_uuid) :
            print("{} : {}".format(idx + 1, value))
        select_index = int(input(">> "))
        user_uuid = user_uuid[select_index - 1]

    if os.path.isdir(os.path.join(os.getcwd(), "EDB")) == False :
        os.mkdir(os.path.join(os.getcwd(), "EDB"))


    kakaotalk_TalkUserDB_path = os.path.join(kakaotalk_path, user_uuid)
    file_lists = os.listdir(kakaotalk_TalkUserDB_path)

    for i in file_lists :
        if i == "TalkUserDB.edb" :
            shutil.copy(os.path.join(kakaotalk_TalkUserDB_path, i), os.path.join(os.getcwd(), "EDB"))

    kakaotalk_user_chat_path = os.path.join(kakaotalk_path, user_uuid, "chat_data")
    edb_lists = os.listdir(kakaotalk_user_chat_path)
                     
    for i in edb_lists :
        if ("chatLogs" in i and ".edb" in i) or i == "TalkUserDB.edb" :
            shutil.copy(os.path.join(kakaotalk_user_chat_path, i), os.path.join(os.getcwd(), "EDB"))

카카오톡 Chat Log EDB파일들을 복사하기 위해서 shutil 모듈을 사용하였으며 TalkUserDB의 경우 누구랑 대화를 나눴는지 확인하기 위해서 필요로 하다. TalkUserDB에는 카카오톡 친구들의 목록을 가지고 있다. (물론 오픈채팅방의 유저들의 데이터도 존재한다.)

파이썬 코드를 돌려보면 EDB 폴더가 생성되며 chatLogs_*.EDB 파일들이 복사되고, #1에서 제작한 알고리즘을 바탕으로 복호화를 진행한다.

 

[포렌식] 윈도우 카카오톡 데이터베이스 복호화 분석 및 구현

본 글은 언제든지 비공개 되거나, 삭제될수 있음을 미리 알려드립니다. (뭐,, 카카오톡 본사에서 글 내려라 하지 않는 이상 없어지진 않지 않을까...?) 이 글은 여러 논문을 참조하여 분석 및 구현

blog.system32.kr

데이터베이스를 추출했으니 CSV 파일로 변경하기 위해 함수를 작성한다.

def humantime(temp) :
    unix = datetime(1970, 1, 1)
    cocoa = datetime(2001, 1, 1)
    delta = cocoa - unix
    timestamp = datetime.fromtimestamp(int(temp)) + delta
    time = (timestamp.strftime('%Y-%m-%d %H:%M:%S'))
    return time 


def parse_db_to_csv(message_file, contact_file) :
    contact_con = sqlite3.connect(contact_file)
    contact_cursor_message = contact_con.cursor()
    contact_cursor_message.execute("SELECT userid, nickName, friendNickName FROM talkUser")
    contact = {}
    for i in contact_cursor_message :
        contact[i[0]] = str(i[1]) + "_" +str(i[2])
    
    message_con = sqlite3.connect(message_file)
    message_cursor_message = message_con.cursor()
    message_cursor_message.execute("SELECT authorId, type, sendAt, message FROM chatLogs")
    message_dataframe = list(message_cursor_message)
    for i in range(len(message_dataframe)) :
        message_dataframe[i] = list(message_dataframe[i])
        try:
            message_dataframe[i][0] = contact[message_dataframe[i][0]]
        except :
            pass
        message_dataframe[i][2] = humantime(message_dataframe[i][2])
    message_dataframe = pandas.DataFrame(message_dataframe)
    message_dataframe.to_csv("{}.csv".format(message_file))

위 로직에 따르면, 먼저 TalkUserDB에서 key값으로 UserID를 넣어주고, nickName(원본 이름), friendNickName(사용자가 지정한 이름)을 "_" 로 묶어서 딕셔너리 형태로 만든다.

그후 ChatLog_*.EDB 파일을 돌면서 authorID, 즉 UserID의 값이다. 이 값을 딕셔너리 키값과 동일하면 이름을 변경하고 CSV 파일로 저장한다.

그나저나 HumanTime 코드를 잘못작성했나보다,,, 뭐 날짜는 맞으니까 연도만 수정하면 될것 같다.

근데 이걸 악용하게 된다면 문제가 생길것 같다는 생각이 든다, 만약 내가 공격범인 상황을 가정한다.

간단하게 소스 짜서 Pyinstaller로 배포해서 USB에 담아서 다른 PC에 꽂았다고 가정한다.

간단하게 실행만하면 pragma와 EDB파일들을 모두 빼오게 된다,,,

허걱,,, 잘못했다간 내 개인정보가 다 털릴수도 있다는 끔찍한 상상을 하게 되고,, 앞으로는 모르는 사람에게 컴퓨터를 빌려주면 안될것 같다,,, 잠깐 조작 1~2초 만에 정보가 다 털릴수도 있으니 조심하자.