윈도우 NTFS 파일시스템의 타임스탬프 변화 표는 여러 블로그와 홈페이지에 연구되어 포스팅되어 있는 것들을 보았지만, 아직까지 리눅스 배포판에 대한 정리 표가 없는 것 같아 정리를 해 보았다.


리눅스 배포판 중 우선 Ubuntu 배포판을 선택하여 Ext3 파일시스템의 시간 변화에 대하여 조사하였고, 아래와 같이 엑셀 파일로 정리하였다.


혼자 정리했기 때문에 빠진 행위나 부족한 점이 있을지도 모르니 피드백을 보내면 피드백을 수렴하여 현재 배포판의 표 수정과 함께 다음 배포판 변화 표에 추가해 정리하도록 하겠다




리눅스 배포판 Time 변화 표 v0.1.xlsx




  1. Favicon of https://blueh4g.tistory.com BlogIcon bughela 2014.10.28 16:07 신고

    우와.. 정말 천재시네요 ㅜㅜ 이런건 어떻게 하나요? ㅠㅠㅠ

    • Favicon of https://maj3sty.tistory.com BlogIcon MaJ3stY 2014.10.30 16:31 신고

      앗, ㅋㅋㅋㅋ 깜짝이얔ㅋㅋㅋ

      포렌식 공부하시면 할 수 있습니당!

Network Forensics Puzzle Contest는 매년 열리는 데프콘에서 이벤트성으로 열리는 챌린지이다. 자세한 대회 소개는 다음 글을 읽어보기 바란다. 

주소  http://maj3sty.tistory.com/1083



[Round 1]

Password : izDEFCONf33ling22?#tSwift


 - 문제 지문

EFCON 2013 Network Forensics Puzzle Contest: From Pyongyang with Love


Thank you for accepting the case. Our Russian comrade has indicated that said documents released by Snowden may contain information about a bribery involving the 2015 Chess Boxing World Title. We've been monitoring Snowden's traffic, and need to know who all is involved. We suspect that there is a list of usernames, and we would like you to tell us who is the second name on the list. 

Use the Round 1 packet capture in this folder to learn more about the case and answer the following question: 


What is the second name on the list of usernames? 


문제 지문을 보면, 스노덴의 트래픽을 감시하여 유저명의 목록을 획득하려고 하는데, 가장 중요하게 얻으려 하는 유저명은 목록 중 두 번째의 유저명이다. 유저명은 텍스트 또는 파일로 스노덴이 다른 사람에게 전송할 가능성이 많으므로, 먼저 전송되는 파일들을 살펴본다.


[그림 1 - SMB 프로토콜로 전송되는 파일 목록]


SMB 프로토콜로 전송되는 파일 오브젝트들을 보면 Documents.zip 파일이 존재한다. 해당 파일을 해제하면 다음과 같이 여러 폴더와 파일들이 나오는데, 파일들의 내용은 모두 base64 인코딩 방식으로 인코딩되어 있어 인코딩을 해제해야만 문서의 내용을 획득할 수 있다.


[그림 2 - 인코딩되어 있는 docx 내용]


그 중 track6.docx 파일의 내용을 디코딩하면 다음과 같은 목록을 획득 할 수 있다.


The Mystery of Chess Boxing:

(usernames)


Mr. Method

Kim Ill-Song

Mr. Razor

Mr. Genius

Mr. G. Killah

Matt Cassel

Mr. I. Deck

Mr. M Killa

Mr. O.D.B.

Mr. Raekwon

Mr. U-God

Mr. Cappadonna (possibly)

John Woo?

Mr. Nas


두 번째 유저명이므로 답은 "Kim Ill-song" 이다.

Answer : Kim Ill-song


[Round 2]

Password : #pshth@twaSteh3@$y1#


 - 문제 지문

We see that North Korea is in the running for hosting next year's title fight. Kim Ill-song might be exactly who we are looking for. We've taken a capture of Mr. Kim Ill-song's network traffic, and we see that he's been communicating with many people from different countries. We suspect that he is among those making bribes, but we need proof. Cash is relatively easy to move, but we've got word that one of the bribes was something else. Voting for the hosting city begins soon. 

Use the Round 2 packet capture in this folder to learn more about the case and answer the following question: 


What city's official is accepting a non-cash bribe?


이번에는 김일성이 제공한 뇌물을 받은 도시의 관계를 찾는 것이다. 패킷의 대부분은 IRC 패킷으로 이루어져 있어 TCP 스트림을 살펴보면 IRC 메시지를 모두 살펴 볼 수 있다.

IRC 메시지 중 PRIVMSG로 'Killah'란 닉네임을 가진 사용자에게 인코딩된 메시지를 전송하는 것이 여럿 보인다. 해당 메시지는 처음에는 base64로 인코딩되어 있으며, 그 다음에는 base32로 인코딩되어 있다. 인코딩을 모두 풀고나면 다음과 같이 md5 hash 값이 보인다.


[그림 3 - base32 디코딩 모습]


획득한 md5 hash 값을 크랙하면 다음과 같은 값이 나온다.

[그림 4 - md5 cracker]


Answer : Caracas


[Round 3]

Password : Ib3tuth0ughtQat@r&&


 - 문제 지문

Thank you for getting that information to us. We can clearly see that the briber, Ill-song, is communicating with the official from Caracas to set up a non-cash bribe. We need more than that, however. We need an idea of what Ill-song is using to bribe the official. Look through this capture and see if you can find out what the non-cash bribe is. Please hurry, the voting is about to begin! 

Use the Round 3 packet capture in this folder to learn more about the case and answer the following question: 


What is the non-cash bribe? 


이번에는 김일성이 제공한 뇌물을 특정하는 문제이다. 패킷 파일을 열어보면 수많은 패킷들이 있어, 프로토콜로 일단 분석 포인트를 찾아보았다. 


[그림 5 - 프로토콜 정렬]


프로토콜을 기준으로 해당 패킷 파일에는 총 3개의 프로토콜이 존재한다. http, https, FTP가 그것인데, FTP의 내용을 보면 zip 파일을 전송하는 것을 볼 수 있다.


[그림 6 - FTP 내용]


zip 파일은 간단히 시그니처 카빙을 통해 추출하면 다음과 같은 파일들을 획득 할 수 있다.



[그림 7 - 카빙한 zip 파일 내용]


'sandofwhich.zip' 파일 말고도 여러 압축 파일들이 존재한다. 해당 파일들을 모두 카빙하면 동일하게 '.jpg' 확장자 파일들이 나오는데, 해당 파일들의 제목을 이어 붙이면 다음과 같은 문장이 만들어진다.


"I can’t in good conscience allow the U.S. government to destroy privacy, internet freedom and basic liberties for people around the world with this massive surveillance machine they’re secretly building."


그림 파일들을 보면 몇개의 파일들은 깨져보이며, 대부분의 파일들이 정상적으로 이미지를 보여주지 않는다. 위 문장의 처음인 "I"와 "building" 문자열의 파일을 보면 그림 파일의 헤더 시그니처와 푸터 시그니처를 가지고 있는 것을 볼 수 있다. 그러므로 각 단어들 제목의 파일 바이너리 데이터를 하나의 파일로 합쳐 보면 다음과 같은 이미지를 만들 수 있다.


[그림 8 - 조립된 이미지]


Answer : Chess Set


[Round 4]

Password : h0wd1dug3tth@t1?%


 - 문제 지문

Unfortunately, you were not quick enough and Pyongyang has been chosen for the Chess Boxing World Title. Furthermore, the chess set you uncovered was one of a very limited set and is incredibly expensive. To be frank, we're not sure how Kim Ill-song has the resources to obtain it. We've begun looking into Ill-song, but we can't seem to find anything on the guy. Rumor has it that he's trying to communicate with a particular individual, but we need to find out who and why. This capture shows him talking with someone else, but we're not sure how or what's being said. We need information on Ill-song before we can move on to his partner. Can you get us the device name of Ill-song's computer? 

Use the Round 4 packet capture in this folder to learn more about the case and answer the following question: 


What is the device name of Ill-song's computer?


김일성 컴퓨터의 이름을 파악하는 문제이다. 패킷 파일을 보면 기본적으로 http, https가 있는 반면에 STUN 프로토콜 패킷이 존재한다. STUN 프로토콜 패킷은 NAT 환경에서의 External IP/PORT를 P2P 단말이 알아볼 수 있도록 해주는 프로토콜이다. P2P 통신에 필요한 프로토콜이므로 컴퓨터에 대한 정보도 얻을 수 있지 않을까하여 해당 프로토콜에 분석 초점을 두고 분석을 시작 해 보았다. 또 문제 지문을 보면 개인적인 통신을 한다고 하니 STUN 프로토콜의 내용이 더욱더 의심이 간다.


문제 지문을 잘 읽어보면 해당 패킷 캡쳐를 통해 김일성이 누군가와 대화를 하고 있다고 한다. 그러므로 김일성의 통신 내용을 캡쳐했다고 볼 수 있다. STUN 프로토콜의 내용을 보면 다음과 같은 문자열이 전송되는 것을 볼 수 있다.


[그림 9 - 전송되는 컴퓨터 이름]


주소가 루프백이므로 주소 앞에 있는 값이 김일성 컴퓨터의 이름이다.


Answer : drpoppins-735


[Round 5]

Password : ur0nar0lln0w!@


 - 문제 지문

One of your colleagues was able to intercept messages between Ill-song and Ann Dercover, a professional chess boxer. The Chess Boxing World Title will be held in Pyongyang next year, and we know that this is only because of a bribe from a "Kim Ill-song". We now believe that this is an alias. Whoever it is has relations with Ann Dercover, and we believe that that Ill-song is using the Title to get her into North Korea. Since "Ill-song" is so determined to contact Ann, we've begun investigating her. So far we've just been tapping her phone and home network traffic. Based on their conversation, we believe that Mr. Ill-song (or whoever he is) will try to contact her in the near future and set up a time to meet. Look through this capture and let us know if you find out a meeting time. Remember, we need the date AND time. 

Use the Round 5 packet capture in this folder to learn more about the case and answer the following question: 


What is the month, date, and time of their meeting? 


어떤 여자와의 만나는 일자를 알아내는 것이 이번 문제의 목표이다. http 패킷의 대부분 내용이 SMS 메시지이다. 하지만, 메시지 대부분은 내용이 없는데, 몇 개의 메시지는 내용이 들어 있어 http 패킷 여러개를 보면 다음과 같은 패킷을 볼 수 있다.


[그림 10 - SMS 메시지]


"still we should be careful. Pay attention. I want to meet in September at 5PM" 이라는 메시지를 보면 September 5PM이란 대략적인 날짜와 시간을 알 수 있다. 하지만 정확한 기간은 다른 메시지들을 본 후 파악이 가능하다. 해당 메시지는 다음과 같다.


[그림 11 - 위치 표시 값]


[그림 11]을 보면 위도/경도 값이 보인다. 위 패킷 다음으로 계속해서 위도/경도 값이 나오는데, 해당 값들을 모두 조회하여 보면 다음과 같은 형태가 된다.


[그림 12 - 위도/경도 조회 결과]


Answer : September 17th at 5 PM


[Round 6]

Password : gud$luk^^0nth1s1


 - 문제 지문

Since the meeting time between Ann and Ill-song isn't for another month, we've continued monitoring their traffic and communications. This information led investigators to a hotel in Pyonyang. After a failed attempt to apprehend Ill-song in his hotel room, a detective found a thumb drive he left behind. One of your colleagues has discovered what appears to be encrypted data on the thumb drive. We don't know if there will be anything useful on it yet, but we think the data might be from an Apple device. If so, there may be network credentials from his personal network on the device. We'd like you to get the SSID from the network he was using. You can do that, right? 

Use the Round 6 zip file in this folder to learn more about the case and answer the following question:


What is the Wifi SSID from the device?


이번 문제는 Wifi SSID를 찾는 문제이다. 이번 문제는 처음에 패킷파일이 바로 주어지지 않는다. 조각난 것처럼 보이는 파일들이 압축되어 있는 압축파일 하나가 주어진다. 하지만 주어진 문제를 풀기전에 이전 문제 파일들로부터 얻어야 할 정보들이 있다.


먼저, Round 1에서 획득 했던 Documents.zip의 압축 파일들 중 "More Document" 디렉터리에 파일들에서 "NorthKorea.jpeg" 파일에 끝에 붙어 있는 "untitled.zip" 파일을 획득한다.


[그림 13 - 압축파일 획득]


압축 파일에는 "broken.py" 파일이 존재한다. 파이썬 스크립트 파일까지 획득 했다면, 이제는 Round 3 문제에서 획득 했던 이미지를 대상으로 스테가노그래피 기법을 이용 해 숨겨진 메시지를 획득해야 한다. 여러번 시도한 결과 "Slient eye" 도구를 이용 해 획득 할 수 있었다.


[그림  14 - 스테가노그래피 해제]


"i2454 2497d2496n2502 2470 2500 2507o2436s2452 2500s2503n2502l2487e2456 2497 2500h2485l2487 2470b2490e2491a2501m2466 2483a2501a2501e2505 2497 2500a2486"


"broken.py" 스크립트는 현재 스크립트로 정상 동작하기 위한 조건을 가지고 있지 않아 조금의 수정이 필요하다. 다음은 수정 전의 스크립트 코드이다.


--------------------------------------------------------------------------------------------------------------

def fileToString(pathToFile):

f = open(pathToFile, "r")

strs = ""

#adds each line of the file to the strs string

for line in f.readlines():

strs+=line

return strs

def ASCII():

#number of ASCII characters

NumOfASCII == 0

#returns list of all ASCII characters

return "".join([chr(i) for i in range(NumOfASCII)])

def sumName(name):

sums=0

#sums the indices in ASCII of all the characters in name

for x in name:

sums+=ord(x

return sums

def indexInFile(password):

indices = []

ASCIIArray = ASCII()

#populates an array of indices to be used by the encoder

for chrs in password:

indices.append(ASCIIArray.index(chrs)+sumName(name)*2

return indices

def indexInASCII(name):

indices = []

ASCIIArray = ASCII()

#split on all non-numeric characters

#remove first index because it is blank

indexList = re.split("[^\d]",encoded)[1:]

#converts encoded characters to ASCII

for index in indexList:

indices.append(ASCIIArray[int(index) - (sumName(name)*2)])

#returns decoded message

return "".join(indices)

def encode(name):

#returns a list of indices to be used for encoding

indices = indexInFile(password,name)

#convert file associated with name to a string

bill = fileToString("./%s.txt"%name)

encoded = ""

#add letter in file plus index of the letter in the file to the encoded string

for index in indices:

encoded+=bill[index]+str(index)


return encoded

--------------------------------------------------------------------------------------------------------------


다음은 수정 후의 스크립트 코드이다.


--------------------------------------------------------------------------------------------------------------

import re


def fileToString(pathToFile):

f = open(pathToFile, "r")

strs = ""

#adds each line of the file to the strs string

for line in f.readlines():

strs+=line

return strs


def ASCII():

#number of ASCII characters

NumOfASCII = 128

#returns list of all ASCII characters

return "".join([chr(i) for i in range(NumOfASCII)])


def sumName(name):

sums=0

#sums the indices in ASCII of all the characters in name

for x in name:

sums+=ord(x)

return sums


def indexInFile(password, name):

indices = []

ASCIIArray = ASCII()

#populates an array of indices to be used by the encoder

for chrs in password:

indices.append(ASCIIArray.index(chrs)+sumName(name)*2)

return indices

                       

def indexInASCII(password, name):

indices = []

ASCIIArray = ASCII()

#split on all non-numeric characters

#remove first index because it is blank

indexList = re.split("[^\d]",password)[1:]

#converts encoded characters to ASCII

for index in indexList:

indices.append(ASCIIArray[int(index) - (sumName(name)*2)])

#returns decoded message

return "".join(indices)


def encode(name):

#returns a list of indices to be used for encoding

indices = indexInFile(password,name)

#convert file associated with name to a string

bill = fileToString("./%s.txt"%name)

encoded = ""

#add letter in file plus index of the letter in the file to the encoded string

for index in indices:

encoded+=bill[index]+str(index)


return encoded


def decode(password, name):

    return indexInASCII(password, name)

--------------------------------------------------------------------------------------------------------------


획득한 문자열을 위 스크립트 코드에 넣고 디코딩하면 다음과 같이 패스워드가 출력된다. 인코딩 키는 "BillOfRights"이다.


[그림 15 - 패스워드 복호화]


복호화 문자열 : DontTry2BruteForceThisPassword


이제부터 이번 라운드 문제를 살펴보도록 하겠다. 이번 문제의 파일들은 모두 조각 형태로 이루어져 있다. 해당 파일들은 iPod touch의 iOS backup 파일들이 암호화되어 있는 파일들이다. 암호화를 풀기위한 도구들의 설치 과정 설명은 생략하도록 하겠다.


iphone-dataprotection 도구를 이용 해 복호화를 시도하면 다음과 같은 화면이 나오는데, 패스워드는 위에서 복호화한 문자열을 사용하면 된다. 


[그림 16 - 복호화]


복호화를 진행하면 다음과 같이 복호화된 파일들이 생성된다.


[그림 17 - 복호화되어 생성된 파일들]


이번에는 복호화된 백업 파일들을 대상으로 키체인을 찾아야 한다. 키체인 역시 iphone-dataprotection 도구의 키체인 스크립트를 사용하면 된다.


[그림 18 - 복호화 완료]


Answer : LeakingSecrets


[Round 7]

Password : !LA$$t0n3!!


 - 문제 지문

The International Chess Boxing Association is reviewing the decision to let Pyongyang host the Title, but we're still not sure of the true indentity of Mr. Ill-song. We did, however, manage to get ahold of a FireTV left behind back in the hotel in Pyongyang. We want you to look for any videos he might have been watching, and see if there isn't a more personal one with intimate information on it. Hopefully something with a meeting location in it. Our sources tell us that this location is probably in the US. We don't need to know the exact location, but we need the state that's mentioned in the video. This is the final task and it is very important, so please don't just try guessing the states starting with Alabama. 

Use the Round 7 file in this folder to learn more about the case and answer the following question: 


What is the name of the state mentioned in the video? 


이번 문제는 동영상 파일에서 언급하는 주 이름을 찾는 문제이다. 문제 파일은 압축파일로, 압축파일을 해제하면 iOS 계열 폴더들과 파일들이 나오는데 "/usr/share/networkFiles/" 디렉터리 아래에 "amazon.pcap" 파일과 "trekking.pcap" 파일이 존재한다. 일단 두 파일을 분석하는데에 초점으로 맞추고 분석을 진행한다.

"trekking.pcap" 파일을 보면 다음과 같이 "jumbled.mp3.zip" 파일을 하나 추출할 수 있다.


[그림 19 - 압축파일 전송 스트림]


압축 파일에는 mp3 파일이 압축되어 있고, 해당 mp3 파일을 들어보면 어떤 여성의 목소리가 들린다. 이외에는 해당 패킷 파일에서 획득할 정보가 없어 다음 패킷 파일 분석으로 넘어간다.


"amazon.pcap" 파일은 무선 네트워크 패킷을 캡쳐한 파일이다. 그러므로 우선적으로 802.11 프로토콜 패킷을 복호화 해야만 한다. 해당 프로토콜의 복호화는 와이어샤크에서 기본으로 제공해주는 기능을 이용해 복호화할 수 있다. 이전 문제에서 획득한 SSID의 비밀번호인 "UncrackableNetwork75"를 이용하여 복호화를 시도한다.


암호화는 WPA-PWD 방식으로 되어 있어, 다음과 같이 키를 추가한 후 복호화를 시도하면 복호화가 완료된다.


[그림 20 - 키 추가]


복호화를 하면 "synergy" 프로토콜이 많이 보인다. "synergy" 프로토콜은 키보드와 마우스를 공유해주는 소프트웨어에서 사용하는 프로토콜로, 패킷을 보면 키보드에서 전송된 문자가 무엇인지 파악 할 수 있다.


techno viking

nyam cat ncat nick cage

cats and bears and stuff

carve 0x250c6

carve 0xa250c5

defcon 22

stewie madT

stuart


대략 위와 같은 문자가 전송된 것을 파악할 수 있는데, 오프셋 카빙을 지시하는 말 같은것이 전송된 것을 볼 수 있다. mp3 파일을 대상으로 오프셋을 이용 해 카빙하면 바이트 분포도가 일정한 파일이 나오는데 이것으로 보아 해당 파일은 Truecrypt 컨테이너 파일로 의심할 수 있었고, 비밀번호는 앞서 획득한 mp3 파일의 음성을 들어보면 획득할 수 있다. 여성이 말하는 단어들은 모두 NATO의 Phonetic code로 해독하면 "True HOOHA."라는 문자열을 획득 할 수 있다. 이를 이용하여 컨테이너 파일을 복호화하면 다음과 같이 비디오를 획득 할 수 있다.


[그림 21 - 비디오 획득]


Answer : New Jersey


이번 챌린지의 주요 문제는 Round 7이 끝이다. 보너스 문제로 Round 8이 존재하며 문제 파일은 Round 4의 문제파일로 진행된다. 해당 문제는 아직까지 챌린지가 진행되고 있어 풀이를 공개하지 못하는 점 이해하기 바란다.



이번 챌린지 문제는 다양한 난이도와 다양한 컨텐츠로 인해 재미있었다는 것이 지금 느끼는 가장 큰 소감이다. 하지만, 힌트 없이는 조금 풀기 어려울 수도 있다는게 개인적인 생각이며, 오프라인으로 챌린지를 진행하게 되면 많이 당황했을 수도 있겠다는 생각이 든다.

이 글을 보는 사람들도 한번쯤은 문제 풀이를 실습할 겸 풀어보는 것도 좋을 것 같다.


  1. 2017.12.17 21:06

    비밀댓글입니다

일전에 올렸던 글에서 사용했던 도구를 공개합니다.


파이썬 2.7 버전으로 작성되었고, 필요한 라이브러리는 압축 파일 내부에 소개되어 있습니다.



lp 배포.zip


'[+] Forensic' 카테고리의 다른 글

[정리] Linux Timestamp Change Table  (2) 2014.09.11
[Tool] Windows JumpList Analysis Tool  (0) 2014.08.11
[Tool] Windows Link Analysis Tool  (0) 2014.08.11
[정리] Havex Artifacts  (0) 2014.06.30
[정리] TrueCrypt Forensics  (4) 2014.06.14

얼마 전 유럽의 스카다 시스템을 공격한 Havex 악성코드에 대한 기사가 해외에서 처음으로 보도가 되었는데, 이전에 해외에서 취약점 공격에 대한 아티팩트를 정리한 포스팅 글을 보고 특정 악성코드나 취약점 공격의 아티팩트 정리의 필요성을 느껴 샘플을 아는 지인분을 통해 구한 후 포렌식 아티팩트들을 다음과 같이 정리하여 보았다. 


다음 아티팩트들은 기존에 남겨지는 일반적인 아티팩트들이 아닌, 해당 악성코드가 특이하게 남기는 아티팩트들인 것을 알아두기 바란다.


[Live Data]

라이브 데이터에서는 프로세스의 목록과 악성코드의 동작을 파악할 수 있다. 실제 악성코드의 동작을 하는 'mdCHECK.dll'은 'rundll32.exe' 프로세스에 의해 동작하며, 정상 프로그램의 위장을 위해 'mbCHECK.exe' 파일이 드랍되어 실행 중인 것을 파악 할 수 있었으며, 악성 프로세스의 상세정보도 파악 할 수 있다.


[그림 1 - 프로세스 명령 라이브 데이터]


[그림 2 - mbCHECK.exe 프로세스의 상세정보]


[Prefetch]

프리패치 정보에서는 프로세스의 상하관계를 확인 할 수 있다.


[그림 3 - 프리패치 마지막 실행 시간]


프리패치의 마지막 실행 시간을 정렬하여 보면, 먼저 드롭퍼의 실행이 있었고, 'mbCHECK.dll'의 실행, 마지막으로 'mbCHECK.exe' 프로세스가 실행이 된다. 실행의 순서는 알 수 있지만 드랍의 순서까지는 파악할 수 없다는 것이 단점이다.


[Timeline]

타임라인에서는 앞에서 확인하였던 사항을 제외하고 기타 다른 생성 파일들의 생성을 확인할 수 있었다.


[그림 4 - 타임라인 흔적 1]


[그림 5 - 타임라인 흔적 2]


새로운 파일의 생성 흔적을 확인할 수 있었지만, 생성의 순서는 모두 동일한 초 시간대에 일어났기 때문에 정확한 순서는 파악 할 수 없다. 


[NTFS Log]

파일시스템 로그에서는 다음과 같이 다른 흔적들에게서 발견하지 못한 새로운 파일의 생성흔적을 발견할 수 있었다.


[그림 6 - 파일시스템 로그 흔적]


해당 파일은 생성과 동시에 바로 삭제되는 특이한 점을 상황을 연출한다. 또 테스트한 Case에서는 바로 삭제되어서인지 $MFT 레코드가 바로 덮어씌어지고 클러스터 또한 바로 할당에서 비할당으로 바뀌어 데이터가 남아 있지 않아 복구를 하지 못하였다. 하지만, 이는 Case by Case이기 때문에 운이 좋다면 복구를 할 수 있을 것이다. $MFT 레코드가 삭제되어 해당 파일이 어디에 생성되는지 확인 할 수 없었다는 것이 이번 흔적에서의 아쉬운 점이라고 말할 수 있다.


[Memory]

메모리는 라이브 데이터와 대부분 동일한 흔적을 보여주지만, 데이터를 직접 얻을 수 있는 장점이 있다. 메모리에서는 운이 좋다면 이미 삭제된 레코드가 있는 $MFT를 추출 할 수 있다. 이번 Case에서도 파일시스템 로그나 라이브 데이터를 수집하며 같이 수집했던 $MFT에서 찾아볼 수 없었던 'System.dll'의 레코드를 획득할 수 있었다.


[그림 7 - 메모리에서 복구한 $MFT의 'System.dll' 레코드]


추가적으로 메모리 덤프 당시의 윈도우 쉘 상태를 파악 할 수 있다.



[그림 8 - 윈도우 쉘 스크린 캡쳐]


[정리]

Havex 악성코드의 흔적을 정리하면 다음과 같다.


1. 'mbCHECK'.exe와 'mbCHECK.dll'을 Drop

2. 'rundll32.exe'를 이용하여 'mbCHECK.dll'을 실행

3. 'qln.dbx' 파일을 Drop

4. '%UserName%\AppData\Temp\' 폴더 아래에 난수로 된 '.tmp'와 '.YLS' 확장자 파일을 생성

5. '%UserName%\AppData\Temp\<랜덤문자열>\' 폴더 아래에 'System.dll' 파일 생성 및 삭제


이를 IOC 포맷으로 정리하여 보았다. Havex IOC는 다음과 같다.


[그림 9 - Havex IOC]


Havex.ioc


해당 IOC는 아직 완벽하지 못하다. 랜덤 문자열의 경로를 IOC로 표현할 수 있는지 불확실하기 때문에 IOC에 해당 항목을 추가하지 못하였다. 이는 추후 파악 후 추가할 예정이다.



'[+] Forensic' 카테고리의 다른 글

[Tool] Windows JumpList Analysis Tool  (0) 2014.08.11
[Tool] Windows Link Analysis Tool  (0) 2014.08.11
[정리] Havex Artifacts  (0) 2014.06.30
[정리] TrueCrypt Forensics  (4) 2014.06.14
Advanced Jump List Forensics  (0) 2014.05.10

Anti-Forensics에서 가장 난감한 것은 개인적으로 생각할 때 '암호화' 기술인 것 같다. 분석해야 할 매체가 앞에 있음에도 불구하고 암호화라는 갑옷으로 둘러싸여 있어 분석을 쉽사리 하지 못하기 때문이다. 암호기술은 수학적 지식을 기반으로 고안되어 있기 때문에 현재로서도 깨지 못하는 암호들이 많이 있다. 불가항력(?)을 이겨내보기 위해 디지털 포렌식 분야에서는 많은 연구가 이루어졌었다. 이때 대상으로 연구가 많이 된 것이 'TrueCrypt'라는 암호화 소프트웨어이다.


TrueCrypt는 단일 파일부터 부트 드라이브까지 암호화 대상을 가리지 않는다. 또한, 일반 사용자들이 쉽게 사용할 수 있도록 GUI 환경을 제공해 사용 범위에 있어 한계를 거의 느끼지 못한다. 이런 이유로 많은 컴퓨터 사용자들에게 자신의 데이터를 안전하게 보호할 수 있는 환경을 제공하였는데, 디지털 포렌식 전문가들은 이와 같은 환경으로 인해 어지간히 애를 먹는 것이 현실이다.


이번 글에서는 TrueCrypt의 암호화 과정을 간단히 살펴보고, 이에 대해 지금까지 어떤 연구가 이루어졌는지 알아보려 한다. 정리 차원에서 쓰는 글이므로 따로 연구를 하거나 하지는 않았다.


참고로 TrueCrypt는 개발자가 알려져 있지 않다. 더군다나 작년 쯤에 NSA 도청 사건으로 인해 민간단체에 의해 TrueCrypt 내부에 백도어가 숨겨져 있다는 의심까지 받아 민간단체에게 감사를 받은 적이 있다. 물론 결과는 '없다'로 결론지어 졌지만, TrueCrypt 개발자는 마음고생을 좀 했을 것으로 예상이 든다. 이와 맞물려 Windows XP의 지원 종료로 인해 TrueCrypt는 개발이 중단되었지만, 최근에 오픈소스 개발자들이 TrueCrypt의 개발을 재개하여 다행히도(?) 많은 사용자들이 TrueCrypt의 암호화 서비스를 계속해서 지원 받을 수 있게 되었다.


그럼 이제 TrueCrypt의 암호화 과정과 복호화를 위한 Anti Anti Forensic 기술을 간단히 살펴보자.


1. 정상 암/복호화 과정

TrueCrypt에서는 기본적으로 다음과 같은 알고리즘과 모드를 지원한다. 아마 '정보보안개론'을 공부해 본 사람이라면 한번 쯤 들어본 알고리즘일 것 이다.


[알고리즘]

 - AES

 - Twofish

 - Serpent

 - AES-Twofish

 - AES-Twofish-Serpent


[모드]

 - XTS

 - LWR

 - CBC, Outer CBC, Inner CBC


오픈소스이기 때문에 많은 연구원들에게 분석 되어 이미 분석되어 일부는 복호화를 지원하지만, 방법이 대부분 메모리 이미지에서 패스워드를 긁어와 복호화를 하는 방법이다. 대표적으로 'Passware Kit Forensic', 'Elcomsoft Forensic Disk Decryptor' 도구가 있다.


암호화 과정의 설명은 다음 그림을 참고하며 설명하도록 하겠다.


[그림 1 - 암호화]


[그림 1]은 암호화가 진행 되어 완료 된 호스트 상태이다. 주요 암호화 과정은 다음과 같다.


1) 사용자가 Passphrase를 입력한다.

2) TrueCrypt는 암호화 대상 파일을 임의로 생성한 Master Key로 암호화 한다. 여기서 기본 암호화는 AES이다.

3) 암호화 된 파일을 컨테이너(Container)라고 부르는데, 컨테이너 파일에 붙일 헤더를 생성한다. 이때 헤더는 512byte이며, 데이터를 암호화 할 때 사용한 Master Key를 헤더에 저장한다. 

4) Master Key가 저장 된 헤더는 사용자가 입력한 Passphrase와 64byte의 Salt 값을 이용해 생성한 Header Key를 이용하여 암호화한다. 이때 사용된 Salt 값은 헤더 앞부분 64byte에 평문으로 저장한다.


위와 같이 정상적인 암호화가 진행되었고, 사용자가 복호화를 원한다면 TrueCrypt는 다음과 같은 복호화 과정을 거친다.


1) 사용자가 Passphrase를 입력한다.

2) 사용자가 입력한 Passphrase와 헤더 부분에 있는 Salt 값을 이용해 Header Key를 생성하고 Header Key를 이용 해 컨테이너 헤더를 복호화 한다.

3) 복호화 된 컨테이너 헤더에서 Master Key를 꺼내 데이터를 복호화 한다.


암호 알고리즘이 복잡할 뿐 TrueCrypt의 암호화 과정은 의외로(?) 간단하다. 이러한 과정을 역이용하여 여러 복호화 방법이 고안되었는데, 이제부터 그 몇가지를 소개해보고자 한다.


2. 연구 된 복호화 과정

복호화 과정 중에 현재 사용 중이며, 현실성이 있는 방법들을 위주로 소개하니 이 점 참고하고 글을 읽어내려 가기 바란다.


2.1 Cached Passphrase in Memory

암/복호화 과정에서 가장 중요한 것은 사용자가 입력한 'Passphrase'이다. 또한 소프트웨어가 사용자 입력 값을 저장하고 사용하기 위해서는 메모리에 이 값을 저장해야 하는데, 이 값은 한군데만 남는 것이 아니라 여러군데에 남는다. 그러므로 소프트웨어가 이 값을 모두 지우기란 불가능하다.


연구원들은 이와 같은 사실을 이용 해 메모리를 이미징하고 이미징 된 메모리 이미지 파일에서 캐싱된 Passphrase를 추출 해 컨테이너를 복호화 하는 식의 방법을 고안하였다. Passphrase의 구조는 다음과 같다.


[Passphrase Structure]

#define MIN_PASSWORD 1 // Minimum possible password length

#define MAX_PASSWORD 64 // Maximum possible password length


typedef struct

{

unsigned __int32 Length;

unsigned char Text[MAX_PASSWORD + 1];

char Pad[3]; // keep 64-bit alignment

} Password;


예제)

17 00 00 00 74 72 75 65 63 72 79 70 74 70 61 73   ....truecryptpas

73 77 6f  72 64 73 65 63 75 72 65 00 00 00 00 00   swordsecure.....


Passphrase 구조는 보듯이 특별한 Signature가 존재하지 않는다. Passphrase 구조를 규칙으로 하여 Text의 내용이 문자인 부분을 모두 추출 해 사용자에게 보여주거나 길이 hex값의 특징을 Signature로 이용해 패스워드를 추출 할 수 있다. 다음은 외국 블로거가 작성한 Passphrase 추출 스크립트 코드이다.


import struct,string

def isasciistr(s):
    return all(c in string.printable for c in s)

def findPassphrases(memdump):
    img = open(memdump, 'rb', buffering=10240)

    while True:
        region = img.read(10240)
        if len(region) == 0:
            break
        startoffset = 0
        while startoffset < len(region):
            offset = region.find('\x00\x00\x00', startoffset)
            if offset > -1:
                startoffset = offset+3
                lengthField = region[offset-1]
                #we found a set of three null bytes
                length = struct.unpack('<B', region[offset-1])[0]
                if length > 0:
                    passphrase = region[offset+3:offset+3+length]
                    lengthReal = len(passphrase)
                    #make sure we aren't hurtling off the region boundary
                    if offset+3+length+1 < 10240:
                        #make sure byte right after string is a null byte (sure, more should be null, but whatever)
                        if ord(region[offset+3+length+1]) != 0:
                            break
                    #make sure that the string is as long as the field said it would be
                    if isasciistr(passphrase) and ord(lengthField) == lengthReal:
                        #print the possibility
                        print "POSITIVE: "+passphrase + " EXPECT("+hex(ord(lengthField))+")"+" GOT("+hex(lengthReal)+")"
            else:
                break

findPassphrases()

출처 : http://delogrand.blogspot.fi/2013/04/cyber-defense-exercise-2013-extracting.html


현재 Volatility에서 내놓을 TrueCrypt 플러그인도 위와 같은 방법으로 메모리 이미지에서 Passphrase를 추출한다.


2.2 Fake Header

Fake Header는 TrueCrypt를 패치하여 복호화 과정을 교묘하게 이용하는 방법이다. 캐싱된 Passphrase가 메모리 이미지에 없고, 캐싱된 Master Key만 있을 경우 사용하는 방법이다.


1) 처음에 임의의 컨테이너를 생성한다.

 $> truecrypt --text --create --encryp-on=AES --filesystem=FAT --hash=RIPEMD-160 --password=MaJ3stY --random-source=/dev/random --size=20971520 --volume-type=normal tempFile


2) 임의의 컨테이너의 헤더를 복호화 대상 컨테이너 헤더로 덮어 씌운다.

 $> dd if=tempFile of=originalFile bs=512 count=1 conv=notrunc


3) 메모리 이미지에서 Master Key 목록을 추출한다. 목록을 추출할 때에는 Cold Boot Attack 연구 때 같이 연구된 aeskeyfind 도구를 이용한다. 해당 도구는 Aes key의 구조와 Entropy를 이용해 메모리 이미지에서 Aes key와 비슷한 데이터들을 추출 해 준다.

 $> ./aeskeyfind <메모리 이미지>


4) TrueCrypt를 패치한다.


[그림 2 - 원본 코드 : Volume/VolumeHeader.cpp]


[그림 3 - 수정된 코드 : Volume/VolumeHeader.cpp]


수정된 코드가 실행 될 때는 이미 Header Key가 생성되고 컨테이너 헤더가 복호화 된 상태이다. 이때 메모리 이미지에서 추출한 Aes Key 목록을 읽어와 메모리 버퍼에 저장한 후 해당 키 값을 헤더에 있는 Master Key와 교체한다.


5) 임의의 컨테이너를 생성할 때 입력했던 Passphrase로 복호화를 수행한다.

 $> truecrypt --text --mount-options=readonly --password=ABC123 originalFile /mnt/truecrypt 


간단히 정리하면, 임의의 컨테이너 헤더로 덮어 씌어진 복호화 대상 컨테이너 파일은 사용자가 입력한 Passphrase로 컨테이너를 헤더를 복호화 할 수 있다. 하지만 헤더 내에 저장되어 있는 Master Key가 다르므로, 컨테이너의 내용은 복호화가 안된다. 이를 위해 TrueCrypt의 복호화 단계에서 헤더 내에 저장된 Master Key를 바꿔치기 하기 위해 코드를 수정하는 것이다. 바꿔치기된 Master Key 중에 유효한 키가 존재한다면 복호화는 정상적으로 수행될 것이다.


3. 정리

위에서 소개한 방법 외에도 연구된 방법은 많지만, 현재 사용되지 않고 있다. 대표적인 예로 BIOS Key Buffer에서 Passphrase를 추출하는 방법이 있는데, 이 방법은 상위버전에서 패치되어 현재는 소프트웨어가 자체적으로 쓸모 없는 값으로 Buffer를 Clear하여 Passphrase를 추출하지 못한다. 또 이외에 방법들은 위 방법들을 응용할 뿐이고 다른 부분이라고는 메모리를 어떻게 수집하는지에 대한 것이어서 다른 방법들에 대해서는 따로 언급하지 않겠다.


한번정도는 정리를 해야겠다고 마음을 먹고 있었는데 이제서야 정리를 하게되었다. 혹시 이 글이 도움이 되는 사람이 있길 바란다. :-)


아래는 각 버전별 Passphrase와 Master Key등이 메모리에 남는지에 대해 정리한 표이다.


[표 1 - 버전별 정리]


* 3.1a 버전의 경우 Passphrase가 char *buffer 공간에 있어 여러군데 캐시가 되지 않는다. 그 대신 'truecrypt.sys' 파일에 .data Section에 Passphrase를 대신하는 문자열이 하드코딩 되어 있어, 특별한 경우가 아니면 메모리에서 캐시된 Passphrase를 추출 할 필요가 없다.


** Master Key가 없는 버전들은 'truecrypt.sys' 파일의 심볼정보를 추적하면 Master Key를 추측할 수 있다.


summary는 컨테이너에 관한 정보이다.

  1. 2014.09.21 15:58

    비밀댓글입니다

  2. 아무개 2015.02.27 11:23

    레딧의 Truecrypt is dead? 스레드를 보니까, 최상위 도메인 관리기관을 통해 도메인 탈취로 가짜사이트 연결, 가짜 파일 제공으로도 모자라서
    소스 포지에 있던 구버젼 빌드들 까지 전부 바꿔치기 했다는거 같은데, TrueCrypt가 죽었다면 대체제는 무엇이 있나요?

    • Favicon of https://maj3sty.tistory.com BlogIcon MaJ3stY 2015.03.02 17:06 신고

      트루크립트 개발 중단이 되고나서 얼마 있지 않아 트루크립트 알고리즘을 기반으로 한 새로운 프로그램이 개발되어 나온적이 있습니다. 지금은 해당 도구 이름이 기억이 나질 않네요..
      일단 현재는 트루크립트의 계승 버전인 프로그램이 유일하다고 생각이 됩니다. 별다른 도구가 개발되었다는 이야기는 듣지 못했네요.

+ Recent posts