Dork's port

Wavve(웨이브) HLS 프로토콜 분석 및 None DRM 콘텐츠 핑거프린트(워터마킹) 분석 -1 본문

DRM

Wavve(웨이브) HLS 프로토콜 분석 및 None DRM 콘텐츠 핑거프린트(워터마킹) 분석 -1

Dork94 2022. 1. 30. 16:05

저번에 DRM 콘텐츠 분석을 끝내고 일반 콘텐츠는 어떻게 동작을 하는지, 다운로드가 가능하다면 다운로드 한 파일에 대해 사용자에 대한 핑거프린트가 적용이 되어있는지 의문이 생겨 글 작성을 하려합니다.

이번 포스팅의 목적은 3가지이며, 웨이브 동영상을 다운받고자 설명하려는 목적이 아님을 밝힙니다.

1. HLS 프로토콜 분석

2. 다운로드가 불가능 한 콘텐츠의 다운로드 가능성 분석

3. 다운로드 한 영상에 사용자의 정보(fingerprint)가 포함되어 콘텐츠가 유출되었을 경우 유출한 사람을 특정할 수 있는 가능성이 있는지

내용이 많아 2개의 포스팅으로 나누었으며, 첫 번째 포스팅에는 웨이브 소개와 프로토콜 분석, 두 번째 포스팅에는 동영상 다운로드와 핑거프린팅 분석으로 나눠서 포스팅 하도록 하겠습니다.

아래부터 편한 말로 작성을 하도록 하겠습니다.

우선 웨이브에는 이용권에는 다운로드 할 수 있는 기능이 존재한다.

웨이브의 다운로드

다운로드를 누르게 되면 해당 영상을 다운로드할 수 있는 링크가 주어지고, 이 링크를 통해 영상을 mp4 형식으로 다운로드할 수 있다.

이용권에 고지한 다운로드에 관련된 내용을 찾아보니 다음과 같다.

방송VOD 다운로드는 콘텐츠에 따라 다운로드가 제한될 수 있으며, 서비스 사정에 따라 다운로드 횟수가 제한될 수 있습니다.
방송VOD 다운로드는 TV에서는 제공하지 않습니다.

즉, 다운로드 할 수 있는 콘텐츠가 제한되어 있고 횟수 또한 제한되어 있다는 뜻인데, 실제로 다운로드가 가능한 콘텐츠와 그렇지 않은 콘텐츠가 나뉘어 져 있는 것을 쉽게 찾을 수 있었다.

다운로드 가능 콘텐츠

 

다운로드 불가능 콘텐츠

우선 웨이브에서 지원하는 다운로드에 대해 알았으니, 본격적으로 HLS 프로토콜에 대한 분석을 해보도록 하자.

프로토콜 분석은 MacOS의 크롬 브라우저에서 진행되었다.

웨이브에서 재생을 시작했을때 네트워크 프로토콜을 살펴보자. 

웨이브 일반 콘텐츠 네트워크 프로토콜

재생과 무관한 js, data 파일들을 제외 하면, 가장 먼저 발생하는 프로토콜은 GET 방식으로 https://apis.wavve.com/fz/streaming 주소에 파라미터와 함께 request가 발생한다. 

<!-- https://apis.wavve.com/fz/streaming parameters -->
device: pc
partner: pooq
apikey: E5F3E0D30947AA5440556471321BB6D9
credential: Private information
pooqzone: none
region: kor
drm: none
targetage: all
contentid: C3601_C36000000023_01_0002.1
contenttype: vod
hdr: sdr
videocodec: avc
audiocodec: aac
issurround: n
format: normal
withinsubtitle: n
action: hls
protocol: hls
quality: auto
deviceModelId: Mac OS X
guid: ebda780c-17f4-11eb-a60c-12f21e1997c6
lastplayid: none
authtype: cookie
isabr: y
ishevc: n

 

파라미터를 살펴보면, 사용자가 재생을 할 수 있는지 검증하기 위한 credential 값과 재생하는 재생하는 장치에 대한 정보를 비롯해서 프로토콜의 정보, 코덱정보, 콘텐츠 정보(id)가 파라미터로 사용되는 것을 볼 수 있다.

특이한 점이라면, DRM이 적용된 콘텐츠에는 MPEG-DASH프로토콜이 사용되었는데, DRM이 적용되지 않은 콘텐츠는 HLS방식으로 스트리밍을 하는 것을 알 수 있다.

https://apis.wavve.com/fz/streaming의 응답 값

응답 값을 보면 해당 콘텐츠를 재생하기 위해 필요한 정보와 콘텐츠에 대한 정보가 json 형태로 오는것을 볼 수 있는데, DRM에서 분석한 것과 마찬가지로 aws cookie가 제공되며 이를 헤더 쿠키 값에 추가하여 이후에 발생할 프로토콜에 대해 콘텐츠 접근을 제어한 다는 것을 유추할 수 있다. 

<!-- Response of https://apis.wavve.com/fz/streaming -->
{
   "play":"y",
   "prerollad":{
      
   },
   "authtype":"cookie",
   "playurl":"https://vod.sdn.wavve.com/hls/C3601/C3601_C36000000023_01_0002.1/2/chunklist5000.m3u8",
   "liveurl":"",
   "etcurl":"https://vod.sdn.wavve.com/etc/C3601/C3601_C36000000023_01_0002.1/2/",
   "awscookie":"Policy=",
   "subtitles":[
      
   ],
   "issue":"2022-01-30 16:53:01+0900",
   "playid":"00b2fed59e664d54af581830e250bf86",
   "qualities":{
      "ishevc":"n",
      "pagecount":"5",
      "count":"5",
      "mediatypes":[
         "SDR"
      ],
      "list":[
         {
            "id":"1080p",
            "name":"FHD",
            "marks":"",
            "filesize":"1 GB"
         },
         {
            "id":"720p",
            "name":"HD",
            "marks":"",
            "filesize":"642 MB"
         },
         {
            "id":"480p",
            "name":"SD",
            "marks":"",
            "filesize":"357 MB"
         },
         {
            "id":"360p",
            "name":"모바일화질",
            "marks":"",
            "filesize":"191 MB"
         },
         {
            "id":"100p",
            "name":"오디오모드",
            "marks":"",
            "filesize":"0 MB"
         }
      ]
   },
   "quality":"1080p",
   "preview":{
      
   },
   "chargedtype":"y",
   "pricetype":"p",
   "concurrencygroup":"1",
   "playtime":"3600",
   "onairvod":{
      
   },
   "drmtype":"",
   "drm":{
      
   },
   "previewtime":"60",
   "nexttriggerseconds":"30",
   "marketing":{
      
   },
   "postscreen":"recommend",
   "country":"KR",
   "extraitem":"",
   "version":"3.47 preview message2",
   "from":"azure",
   "debug":{
      "version":"2.32a",
      "process.env.deploystate":"production"
   },
   "errormessage":"서비스 연결이 지연되고 있습니다.\n잠시 후 이용해 주세요.",
   "mediatype":"SDR",
   "bookmarkextra":{
      "product":"pk_1489=pass,",
      "pca":"y,cloudfront",
      "origin":"inside"
   }
}

위의 응답 값에서 주목할 만한 부분은 playurl 인데, 이 주소를 통해 콘텐츠를 스트리밍 할때 사용되는 m3u8 포맷을 얻을 수 있다.

다음으로 발생하는 네트워크 활동으로 https://vod.sdn.wavve.com/hls/C3601/C3601_C36000000023_01_0002.1/2/chunklist5000.m3u8의 주소로 request가 발생하는 것을 볼 수 있었는데, 이 주소는 이전에 응답 값의 playurl 주소와 일치한다. 

 

<!-- chunklist5000.m3u8 -->
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=249000,AVERAGE-BANDWIDTH=204507,CODECS="avc1.4D4015,mp4a.40.2",RESOLUTION=480x270,FRAME-RATE=30.00
150/chunklist.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=410592,AVERAGE-BANDWIDTH=300239,CODECS="avc1.4D4015,mp4a.40.2",RESOLUTION=480x270,FRAME-RATE=30.00
250/chunklist.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=867808,AVERAGE-BANDWIDTH=605301,CODECS="avc1.4D401E,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=30.00
500/chunklist.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1637856,AVERAGE-BANDWIDTH=1121595,CODECS="avc1.4D401F,mp4a.40.2",RESOLUTION=854x480,FRAME-RATE=30.00
1000/chunklist.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2865120,AVERAGE-BANDWIDTH=2090548,CODECS="avc1.4D401F,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=30.00
2000/chunklist.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7521504,AVERAGE-BANDWIDTH=5174707,CODECS="avc1.4D4028,mp4a.40.2",RESOLUTION=1920x1080,FRAME-RATE=30.00
5000/chunklist.m3u8

 

m3u8의 파일에는 재생을 위한 url이 있는 것이 아닌, 또다른 m3u8 파일을 참조하도록 구성되어있는데, 동영상 화질에 따라 각각 다른 m3u8 파일을 참조하도록 url이 구성되어 있는 것을 알 수 있다.

우선 여기까지 하고, 다음 네트워크 활동을 보도록 하자.

chunklist5000이후 네트워크 활동

다음 네트워크 활동으로는 또다른 m3u8 파일을 얻도록 요청을 보내는 것을 확인할 수 있는데, 이 주소는 이전의 m3u8파일 (chunklist5000)에서 얻어 왔다는 사실을 알 수 있다. 

그럼 위의 네트워크에 대한 응답을 보자.

<!-- chunklist.m3u8-->

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:2.067,
0/media_1.ts
#EXTINF:2.000,
0/media_2.ts
...
0/media_367.ts
#EXT-X-ENDLIST

 

마침내 실제로 스트리밍할때 필요한 주소가 들어있는 m3u8파일을 얻을 수 있었다.

hls도 dash와 마찬가지로 미디어 파일을 여러개의 segment로 나누어서 스트리밍을 하는 것을 알 수 있으며, 각 segment의 uri 주소를 m3u8파일에 명시해줌으로서 스트리밍이 동작하게 하는 방식이다.

실제로 이 네트워크 활동 이후에는 m3u8 파일에 명시되어있는 주소로 요청을 하나씩 보내는 것을 확인할 수 있었으며 응답으로는 실제 데이터(동영상)이 응답으로 오는 것을 알 수 있다. 

 

실제 동영상 데이터를 요청하는 uri와 응답

 

그럼 지금까지의 과정을 정리해보자.

1. 사용자 정보와 content id로 m3u8 주소 요청 -> 화질별 m3u8의 주소가 담겨있는 m3u8 

2. 원하는 화질의 m3u8 주소로 요청 -> 실제 동영상의 데이터를 받을 수 있는 m3u8 

3 m3u8에 있는 uri로 요청 -> 실제 동영상 데이터  

즉, m3u8 파일을 2번 요청하게 되며 첫 번째 m3u8 파일은 화질별 m3u8의 uri 주소가 담겨있고, 두 번째 m3u8에 실제로 동영상 데이터를 얻을 수 있는 uri이 포함되어 있다. DASH 프로토콜과 다른점은 video와 audio가 나뉘어져있지 않고, uri가 파일안에 제공되는 것 같다. 파일의 크기나 네트워크 패킷의 수를 줄일때는 dash 방식이, 내가 알아볼땐 hls가 편한 느낌..

그럼 프로토콜 분석은 끝났으니, 이를 이용해서 실제로 동영상을 다운받을 수 있는지, 그리고 프로토콜 분석을 통해 다운받은 동영상과  실제로 웨이브에서 지원하는 다운로드 영상과 차이는 있는지, 동영상을 다운받을 수 있다면, 다운받은 사람을 추적할 수 있는 핑거프린팅이 적용되어있는지 다음 포스팅에서 알아보도록 하자. 

 

 

Comments