Ann이 클릭한 첫 영화의 제목을 구해야 한다. pcap 파일로 주어진 문제 파일을 확인하기 위해 Wireshark를 실행시켰다.
우선 주어진 패킷 파일 중 Ann이 사용한 IP주소에 해당하는 패킷만 보기 위해 필터 조건을 설정했다. 글자가 작아서 잘 안보이겠지만 ip.addr==192.168.1.10 이라고 입력한 상태이다.
필터링을 했지만 여전히 패킷이 많아서 쉽게 찾기에는 어려움이 있어 보인다.
힌트를 얻기 위해 문제를 다시 읽어보면, 구해야 하는 것은 Ann이 클릭한첫영화의 제목이다.
Ann이 클릭 이벤트를 발생시킨 것에 의해 서버에 request 패킷이 보내졌을 것임을 짐작하고, [Statistics] - [HTTP] - [Requests] 메뉴에 들어가서 관련 패킷이 있는지 확인한다. 물론 여기서 관련 패킷이라는 것은 영화와 관련된 패킷을 말한다.
해당 메뉴에 들어가면 아래와 같이 현재 패킷 목록에서 사용된 request 주소들을 확인할 수 있는데, 영화를 클릭했다는 것은 클릭을 통해서 그 영화를 볼려고 했을 것이라고 자연스레..? 생각할 수 있다. 사실 너무 자연스럽게 viewMovie 라는 키워드가 눈에 띄어서 여기에서 사용된 id값을 wireshark packet 목록에서 검색했다. 이 id값이 사용된 위치와 인접한 곳에 해당 id값을 가지는 영화의 정보도 함께 있으리라 생각했기 때문이다.
이 Requests 목록에서는 viewMoview 키워드를 가지는 url이 두 개다. 어느 것이 먼저인지 알아보기 위해서 두 개의 id값을 모두 검색해서 packet list 상에서 먼저 나온 패킷이 어느 것인지 확인했다.
확인한 결과 id 283963264 가 있는 packet number는 883이고,
id 333441649 가 있는 packet number는 56이다.
더 빨리 발생한 request가 56번 패킷이므로 이 패킷의 데이터를 확인했다.
그리고 예상대로 이 id값이 위치한 곳에서 인접한 위치에 title이라고 적힌 key값과 함께 Hackers라는 영화 제목을 확인할 수 있었다.
주어진 pcap 파일을 Wireshark를 이용해서 열어보면 가장 먼저 보이는 packet list에서 눈에 띄는 프로토콜을 발견할 수 있다.
RTP 프로토콜... Real-time Transfer Protocol의 앞글자를 딴 이름을 가지는 프로토콜로, 말 그대로 실시간 전송(스트리밍 미디어, 시스템 등)에 쓰이는 프로토콜이다.
UDP 프로토콜을 기반으로 동작하는 프로토콜이며, 그렇기 때문에 오류 검사와 수정보다는 실시간으로 데이터를 전송하는 데에 초점이 맞춰져 있다. (포트도 UDP 포트를 사용한다.)
RTP 프로토콜은 RTCP 프로토콜과 함께 쓰인다. RTCP 프로토콜이라는 이름은 Real-time Transfer Control Protocol 의 앞글자를 딴 것이며, 여기서도 짐작할 수 있듯이 RTP 프로토콜의 control을 위해 쓰이는 프로토콜이다. 이 문제에서 주어진 pcap 파일에서도 볼 수 있다시피, RTP 프로토콜을 이용하여 실시간으로 데이터를 전송할 때 중간중간 RTCP 프로토콜이 보내지고 있는 것을 볼 수 있다.
RTCP 프로토콜을 사용하는 이유로는 RTP 프로토콜의 전송 통계나 QoS(Quality of Service) 모니터링, 다중 스트림 동기화 등이 있다. 쉽게 생각하면 RTP 프로토콜의 제어 정보 및 QoS 정보, 통계 등을 전송하기 위함이라고 볼 수 있다.
hex dump를 보는게 습관이 되어서 그런지 이 문제를 본 뒤에도 RTP Header format부터 찾은 뒤에 packet hex를 들여다보았던것 같다. RTP 패킷 파일을 선택한 후 해당 패킷의 detail 페이지를 확인해보면 Payload type으로부터 전송된 데이터가 G.711 PCMA으로 된 것임을 알 수 있었다. 여기서 G.711는 주로 전화에서 사용되는 Audio 코덱인데, 이러한 정보를 참고한다면 음성 전화 내용에서 Gregory를 죽인 사람에 대한 힌트를 얻을 수 있지 않을까..
그럼 이 Audio 데이터를 어떻게 해야 들어볼 수 있을까,,
Wireshark에 내장된 기능인 RTP Player를 이용하면 된다. 이 기능을 이용하면 RTP 프로토콜의 stream만 똑 떼어내서 그 스트림으로 전송된 음성본을 들을 수 있다.
물론.. 지원되는 음성 코덱만 가능하다. 현재 내 wireshark 버전에서 지원하는 코덱이 어떤게 있는지 확인하기 위해 [About Wireshark] - [Plugins] 메뉴에 들어간다. 그리고 우측 상단부에 위치한 Filter by type에서 codec을 선택하면 아래 리스트에서 지원되는 코덱의 이름을 확인할 수 있다.
리스트를 확인해보면 제일 위에 G.711 코덱이 지원된다고 있음을 알 수 있다. 이렇게 RTP Player가 지원되는 코덱의 데이터가 전송된 것을 확인했으므로 RTP Player를 사용하여 데이터의 내용을 확인하면 될 것 같다. 이를 위해 RTP 패킷 하나를 선택한 후 [Telephony] - [RTP] - [Stream Analysis] 메뉴를 선택하여 해당 스트림을 타고 간다.
RTP Streams를 선택하면 정말 여기에 있는 RTP stream만을 리스트 형태로 보여주는데, Stream Analysis를 선택하면 stream내의 패킷들을 analysis까지 해주기 때문에 이 스트림에서 전송된 데이터를 음성 재생하여 들을 수 있게 해 준다.
[Stream Analysis] 메뉴를 선택하면 나오는 화면이다. 그리고 여기에서 아래 Play Stream 버튼을 누르면 RTP Player가 나오고, 이를 이용하여 RTP 프로토콜로 전송된 음성 데이터를 들어볼 수 있다.
Player 창을 열고 재생시키면 Jack와 Victoria가 전화를 하는 내용을 들을 수 있다. 음성이 깨끗하지는 않지만.. Jack이 Victoria에게 너가 죽였냐고 하는 것만은 분명히 들을 수 있어서 Victoria가 범인임을 유추할 수 있다.
key값을 찾기 위해 문제에서 제공한 정보는 오로지 pcapng 형식의 파일 하나뿐이었다.
Wireshark를 이용하여 열어보니 USB protocol로 통신한 흔적뿐이었다.
USB protocol에서 사용되는 통신의 유형은 총 4가지가 있는데 각 통신이 주로 사용되는 상황은 다음과 같다. 1. Control Transfer : 호스트가 장치에 명령을 전송하거나, 장치 설정 정보 등을 요청할 때 사용된다. ex) 장치 초기 설정, 관리 2. Interrupt Transfer : 소량의 데이터를 자주 보내야 할 때 사용된다. ex) 마우스, 키보드 3. Bulk Transfer : 대용량 데이터 전송에 사용된다. ex) 프린트, 대용량 데이터 4. Isochronous Transfer : 데이터의 실시간 전송에 사용된다. ex) 음악, 동영상 스트리밍
위 Wireshark 패킷 목록을 보면 알 수 있겠지만 장치가 호스트에게 interrupt 통신으로 데이터들을 계속 보내고 있다. 그리고 여기서 장치가 호스트에게 보내는 패킷들을 확인해보면, 아래와 같이 Leftover Capture Data라는 이름으로 어떤 데이터가 함께 전송되고 있는 것을 확인할 수 있다.
같은 USB protocol을 사용한다고 해도 데이터를 전송하는 형식이 다르기 때문에 어떤 장치가 보낸 데이터인지 확인할 필요가 있다.
USB 장치가 연결되면 호스트는 가장 먼저 연결된 장치에게 설정 정보를 보내라는 요청을 보낸다. (Control transfer - 1번 패킷) 이 요청을 받은 장치는 자신의 descriptor를 호스트에게 보낸다. (Control transfer - 2번 패킷) 이 과정을 통해 장치와 호스트가 데이터를 송수신할 준비를 하게 되고 그 후 통신이 시작된다. 그러므로 장치에 대한 정보는 2번 패킷인, 장치가 보낸 패킷 안에 있을 것임을 유추해볼 수 있다.
2번 패킷을 들여다보면 정말 DEVICE DESCRIPTOR가 있는 것을 볼 수 있는데, 여기서 idVendor와 idProduct를 통해 장치의 제조사와 제품명을 알 수 있다. Wacom의 Bamboo Pen인 것을 알았다. 아마 좀 전에 interrupt transfer로 전송된 많은 데이터들은 이 펜마우스로부터 전송된 데이터들인 건가 보다. (3, 4번 패킷도 마찬가지로 descriptor를 확인해보면 허브인 것을 알 수 있는데, 이후 패킷들로는 Pen과 호스트 간에 송수신한 패킷만 존재하므로 패스했다.)
그럼 이제 이 제품의 데이터 전송 형식을 찾은 뒤 capture data만 추출하여 그 데이터들이 그리고 있는 그림이 어떤 것인지 알아내면 key에 대한 정보를 볼 수 있을 것 같다.
사실 이 문제 풀면서 bamboo pen 전송 데이터 형식 찾는 게 제일 어려웠다... 일단 처음에는 bamboo pen protocol과 같은 키워드로 검색을 했는데, 여기서 발견한 것이 다음과 같은 사이트였다. bamboo pen을 판매하는 것과 같은 느낌의 사이트였는데, tech specs에서 이 펜이 microsoft pen protocol을 사용한다는 정보를 얻게 되었다. 곧바로 키워드를 바꿨다.
Microsoft Pen Protocol을 검색해보면 아래와 같은 내용이 담긴 문서를 찾을 수 있다.
문제에서 사용된 장치는 Pen.. 따라서 마우스 부분에 해당되는 부분을 보면 X좌표와 Y좌표 순서로 데이터를 전송한다는 것을 알 수 있다. 그런데 위 내용의 마지막을 보면 알 수 있지만.. Note... "however this interface would not be acceptable for a Boot Device (use separate interfaces for keyboards and mouse devices)" 대략 위의 폼으로 전송되지만 이게 확실한지를 결정하려면 추가적인 정보가 필요하다.
내가 능력이 안 되는 건지.. 정확히 저 모델의 포맷을 찾는데 실패했다,, 그래서 도움을 좀 받은 결과 다음과 같은 포멧을 가진다고 한다. 길이가 9인 Capture Data가 02 F0 4C 1C D8 12 00 00 04의 값을 가진다고 할 때,
02 F0 : 헤더 4C 1C : X 좌표 D8 12 : Y 좌표 00 00 : Z 좌표 (펜을 누른 정도, 압력) 04 : 접미사
따라서 위 패킷 목록에서 Capture Data가 있는 패킷들만 뽑은 후 그 안에서 다시 Capture Data 값만 추출해 낸다. 그 후 다시 여기에서 뽑아낼 수 있는 X 좌표와 Y 좌표를 화면 상에 나타내면 저 펜을 이용하여 어떤 그림을 그렸는지 알아낼 수 있을 것이다.
이 작업을 위해 우선 Wireshark에서 Capture Data가 있는 패킷만 골라 별도의 pcapng 파일로 저장한다. 필터링을 할 수 있는 입력란에 usb protocol packet 중 capdata가 있는 파일만 골라낼 수 있는 검색어인 usb.capdata를 입력하면 된다. 그 후 [File] - [Export Specified Packets]를 이용하여 필터링된 패킷들을 별도의 pcapng 파일로 저장한다.
그 후 패킷 내의 특정 데이터들만 추출하기 위해 Wireshark의 자매품인 tshark를 사용한다. command line 버전 Wireshark라고 생각하면 되는데 이것의 사용을 위해 리눅스를 켠다. 그 후 아래와 같은 명령어로 좀 전에 capdata만 있는 패킷 내에서 capdata 필드만 뽑아서 capdata.txt 파일에 저장한다. (tshark를 설치한 적이 없으면 설치해야 한다.. 당연히..)
$ tshark -r (대상 pcapng 파일) -T fields -e (필드명)
** 뽑아낼 필드가 여러 개일 경우 -e (필드명 1) -e (필드명 2) -e (필드명 3)...처럼 이어서 적어주면 된다.
그러면 다음과 같이 capdata 필드 값만 파일에 저장된 것을 볼 수 있다.
여기에서 필요한 값은 X, Y, Z 값이므로 이들만 추출해주기 위해 다음의 명령어를 사용할 수 있다.
뭐지.. 하는 생각을 한동안 가지고 있다가 알게 된 것이 gnuplot에 넣을 데이터 체계가 gnuplot이 실행되고 있는 시스템의 체계와 일치하도록 해야 된다는 것이었다. 즉, 내 gnuplot이 실행되고 있는 리눅스 환경은 little endian 바이트 체계를 사용하기 때문에 내가 입력해주는 데이터도 little endian 형식으로 만들어서 넣어줘야 한다는 것이다.
http://www.gnuplot.info/docs_5.5/Gnuplot_5_5.pdf
내 데이터는 big endian 체계로 가져온 값이 었는데 이 부분 때문에 문제가 생겼나 보다... 하고 리틀 엔디안 방식으로 x, y값의 체계를 바꿔서 저장할 수 있도록 코드를 수정했다.
from pwn import *
f = open("data.txt", "r")
for s in f.readlines():
ss = s.split(" ")
x = int(ss[0], 16)
y = int(ss[1], 16)
z = int(ss[2], 16)
if z > 0:
print(u16(struct.pack(">H", x)), u16(struct.pack(">H", y)))
** u16 함수와 struct.pack 함수는 pwntools 라이브러리에서 지원하는 함수이다.
u16는 16바이트의 패킹된 바이트 문자열을 인자로 받아 unpacking 된 바이트 문자열로 바꿔주기 위해 사용된다. endian에 대한 별다른 옵션을 붙여주지 않을 경우 기본적으로 들어온 바이트 문자열을 little endian 타입으로 변환한다.
문제파일을 다운로드 받으면 tar 확장자를 가진 압축 파일이 나오는데, 이를 풀면 passwd와 shadow 두 개의 파일을 얻을 수 있다.
그리고 역시나 두 파일 내에 suninatas 라는 이름의 user가 있었다. 이를 이용하여 비밀번호를 구하면 된다.
구글링을 통해 passwd 파일과 shadow 파일을 이용하여 비밀번호 cracking을 할 때 john(john the ripper) 을 주로 쓴다는 것을 알았다. 곧바로 설치해준다.
++ shadow 파일을 보면 각 사용자별로 username:$number$hash 형태로 내용이 적혀있는데, 여기서 number값이 그 number에 해당하는 암호화 알고리즘으로 hash를 만들었다는 것을 의미한다고 한다. number는 1~6 범위에 있는 숫자인데 여기서는 6번에 해당하는 암호화 방법과 salt로 hash를 만든 것이고 이 정보를 이용하여 john이 복호화를 해주는 것. 리눅스에서 사용자의 비밀번호 암호화 시 6가지 암호화알고리즘 중 하나와 특정 salt값을 이용한다는 것을 알 수 있는 대목이다. ++
# install | configuration
~/src$ git clone git://github.com/magnumripper/JohnTheRipper -b bleeding-jumbo john
~/src/john/src$ ./configure && make -s clean && make -sj4
# testing
~/src/john/run$ ./john --test
(애초에 apt로 john을 설치하면 john 파일이 아닌 다른 위치에서도 실행가능.! 그런데 이렇게만 해도 john이 활성화까지 되는지는 모르겠다..) 설치를 마쳤으면 문제에서 주어진 두 파일을 이용하여 unshadow 한 결과를 password.txt에 저장한다.
$ unshadow passwd shadow > password.txt
그리고 그 파일을 john 명령어를 통해서 실행시켜준다. 그리고 성공한다면 john이 --show 옵션으로 확인해보라고 알려준다.
$ john ~/Downloads/password.txt
$ john --show ~/Downloads/password.txt
일단 무작정 파일을 열어보니 그 안에서 HTTP 패킷같이 생긴 텍스트들이 여럿 발견되었고 문제 제목으로부터 network 관련된 것이라는 것을 참고하여 이를 Wireshark로 열어봤다.
그랬더니 기다렸다는 듯이 패킷들이 정렬되어 보여졌다! (나중에 알고보니 이 파일의 signature가 0A 0D 0D 0A로 pcapng 파일의 것임을 알았다.)
.pcap 파일의 signature
나같은 경우는 패킷분석을 위해 Wireshark를 살펴볼 때 주로 제일 먼저 찾아보는 것이 Protocol Hierarchy Statistics 이다.
현재 이 파일 내에 잡힌 패킷들에 어떤 프로토콜이 얼마나 많이 쓰였는지를 한눈에 파악하기 좋기 때문이다.
여기서 이 창을 통해 발견한 것은 HTTP 프로토콜 밑에 Malformed Packet이 있다는 것이었는데, Malformed Packet이란 패킷 파일이 손상되는 등의 문제로 제대로 보여지지 못하고 있는 경우를 말한다. 사실 패킷 분석하면서 이런 패킷이 있는 경우를 처음 봐서...무슨 일이 있었길래 이런 패킷이 있게 된건지 궁금해졌다.
그래서 해당 패킷의 Stream을 살펴보니.. 응답 패킷에 PNG 파일이 있다? 물론 PNG가 담길 수는 있는건데 왜 Malformed Packet이 표시가 뜬걸까
이 패킷은 HTTP 프로토콜을 사용하여 통신하다가 이런 오류가 생긴 것으므로 HTTP Stream에 어떤 문제가 생긴건지 좀 봐야겠어서 나머지 패킷들도 살펴봤다.
아까 그렇게 Malformed Packet 표시가 있던 패킷은 443번 패킷인데, 확실히 png 파일이 담긴 것은 맞는 것 같다. 파일 이름은 treasure1 이라고 한다. 그리고 그 밑에 이와 관련되어 있어 보이는 이름인 treasure2와 treasure3가 차례차례 보인다. 그런데 이 패킷들은 단순히 text/plain 형태이다.
우선 각 패킷 내에서 해당 파일들만 가져와 저장하여 빠르게 살펴봐야겠다. (HTTP object list 하단의 preview를 이용하면 빠르게 파일들만 저장할 수 있다! 처음에 그것도 모르고 TCP stream 다 뒤져가면서 내려받았었던 기억이...)
내려받은 각 파일들을 HxD Editor로 열어봤다.
treasure1.png
그리고 treasure1.png 파일의 Signature가 잘 있는지 봤는데, Header Signature인 89 50 4E 47 0D 0A 1A 0A 는 찾을 수 있었지만 Footer Signature인 49 45 4E 44 AE 42 60 82 는 찾을 수 없었다. (File Signature 참고: http://forensic-proof.com/archives/323 )
이게 Malformed Packet의 원인이었던 것 같다. 이 파일만 실행시켰을 때에도 뭔가 매우 불편해보이는 이미지를 볼 수 있었다.
나머지 두 파일도 정체가 뭐길래 2, 3번의 이름이 붙은 것인지 봐야겠다.
treasure2treasure3
treasure2에서 발견한 것은 수 많은 00 과 그 사이에 드물게 있던 몇몇 hex들이었고, treasure3에서 발견한 것은 수 많은 00 과 그 끝에 있던 IEND, Footer Signature였다!
treasure2가 모두 0으로만 가득차있었더라면 버리고 3만 쓰고자 했을 수도 있었을텐데..ㅎ 중간에 있던 데이터들이 소중하게 보여서 모두 연결해보기로 했다.
Header Signature가 있던 treasure1을 제일 처음에 붙이고 Footer Signature가 있던 treasure3을 당연히 제일 마지막에 붙여야 할 것 이다. 남은 treasure2는 두 파일 사이에 위치시켰다. HxD 에서 [도구] - [파일 도구] - [연결] 을 이용하면 파일을 손쉽게 연결시킬 수 있다.
이렇게 해서 연결한 파일에 .png 확장자를 붙여서 열면 key값이 담긴 이미지를 볼 수 있고, 이를 이용하여 해쉬값을 만들면 성공이다.
treasure1, 2, 3의 존재를 발견한 후에 이 파일을 내려받는 방식으로 TCP Stream의 패킷 내용을 RAW로 저장한 다음, 그 안에서 초반 ~ 0A 0D 0A 0D 까지를 싹 다 지운 데이터를 사용하여 이어붙이기를 반복했었다. (이유는 이전에 어떤 다른 문제에서 그런식으로 패킷내용으로부터 데이터를 카빙하는 것을 보았기 때문)
근데 뭐가 문제인건지 그렇게 해서 이어붙이면 제대로된 파일이 만들어지지 않았다. 앞으로 자유롭게 손카빙 할 수 있을 정도의 실력이 되기 전까지는 가능한 preview...로 정신적 고통을 덜어야겠다ㅠ