반응형

네이버 나우 방송을 녹화하는 툴을 만들어서 사용하고 있었는데 최근에 또 작동이 안 됐다. 시행착오 끝에 방법을 찾아내긴 했는데 또 미래에 하게 될 삽질을 위해 기록을 남겨둔다.

최초에는 주소 추출이 쉬웠다. 그냥 개발자 도구로 네트워크 탭을 열고 찾아보면 json 형식으로 데이터를 받고 있었고 이 안에 주소가 있었다.

https://now.naver.com/api/nnow/v1/stream/911/livestatus/

이런 주소에서 videoStreamUrl 키에 m3u8 주소가 들어있었다. 그러다가 api 버전이 v2도 바뀌면서 주소가 암호화되기 시작했다.

다른 능력자분 덕분에 AES 방식 암호화란 걸 알았고 암호키도 알았다. 알고 보니 암호키가 소스 코드에 그냥 하드코딩 되어 있었다. 키는 !@7now$%1api)6*

이후로 한차례 api 주소도 바뀌고 했지만 큰 변화는 없었다.

여기까지가 역사(...)고 이제부터 삽질기이다.

최근에 다운로드를 시도하니 오류가 나서 로그를 확인해보니까 암호화된 값이 빈칸으로 왔다. 또 api 주소가 변경됐나 싶어서 네트워크 탭을 열고 살펴보았으나 바뀐 게 없었다. 그래서 해당 api를 직접 호출해보니 네트워크 탭의 결과와는 다르게 값들이 빈칸으로 온다.

https://apis.naver.com/now_web/nowapi-xhmac/nnow/v2/stream/911/livestatus/

뭐, 이런 경우는 뻔하게 리퍼러 문제겠지 싶어서 헤더에 "Referer: https://now.naver.com/"을 추가했더니 값이 정상적으로 온다ㅎㅎ

그런데 기존 키로 복호화가 안된다! 암호화 키가 바뀌었단 사실에 절망했지만 어차피 브라우저에서 재생하려면 어딘가에서 복호화를 해야 하는 법! 키를 찾기 위한 삽질을 시작했다.

먼저 소스 보기부터 시작한다. 뭐 중요한 정보는 아니지만 vue.js를 사용하는 걸로 확인된다... 아무튼 지난번 경험으로 crypto-js 라이브러리를 쓴다는 걸 알았으니 자바스크립트 파일을 뒤져서 decrypt 메소드를 사용하는 곳을 찾았다.

https://now.naver.com/js/app.3fb03ede.js

찾아보니 저 파일에서 AES.decrypt 메소드를 사용하고 있었다. 번들링 된 파일이 압축되어 있어 보기가 힘드니 보기 좋게 정렬해주자. 지난번에 소개한 사이트를 이용했다.

예전엔 저기 근처에 암호화 키도 떡하니 적혀있었는데 이젠 없다....ㅠㅜ

도저히 암호화 키를 찾을 수가 없어서 AES.decrypt 메소드 위에 console.log(e, d)를 적고 무식하게 개발자 도구 콘솔에 전체 자바스크립트를 붙여넣었다.ㄷㄷ

의외로 멀쩡히 동작한다?! 추가한 console.log도!!

덕분에 암호화 키를 얻었다. 얘로 복호화가 가능한지 간단하게 테스트해봤다.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
    <script>
        function encrypt(message = '', key = ''){
            var message = CryptoJS.AES.encrypt(message, key);
            return message.toString();
        }
        function decrypt(message = '', key = ''){
            var code = CryptoJS.AES.decrypt(message, key);
            var decryptedMessage = code.toString(CryptoJS.enc.Utf8);
            return decryptedMessage;
        }

        console.log(decrypt('U2FsdGVkX18+1jiygGMdPysPnQ6i/SQQGRi+UrVOmluOWL1lzzTSfZb2UXyRVcHt3WXDBDRhCabc5fkaGBHOnyq9dOCi5QXEjn390O/PPedrTgpdsj7OZtY+UZ+Eor1STGU+KuSkenFnZvHFmNnnE/sP75ClGCzJOBQf2rFXkKwJeC0tILemUSWgG2oQCnPdpRXgGPe9Y+Ok4fAHwzjlsn5xzR7GxsUX3PDpkAL01z6mxgJu5bF3qLD6An86J60hl1NRU54OtTkuWTGX5QJxFNjakj0FELO0tPRklhJpFeberBOGLrB++9gqXoti5J9/0sbhVQPFIEmL1FcWd9IXaLrc4/zcqF21P8jDOV9Xlr1JVzIgY0yFkk/ZPFAHkyuq3pEtapUT0oZtJlUnqNRunmjjnJsp2aANfhuZ5qDChHC9RWdK/+S4P+X2AsSJj/M+eBWTgjsF343e19M34vLGLHQv8Y0SMfEI3jW7sHfNq2lP7+3dmxokxEsDsYCq5aII7oHOaVTxmbdRpHoVGIM+1ofGL4NMn/a3HzYOE6MJdzli4tmwoeoVVYxqYnR+vNnJC+rOU/M1Kx26/mQV9s0+HJh4exTsauPLZCkvS1wA9ytHWJQld6NJgoLjE+30TF9ukYmdG/1kk9zm26zTRnzHhUCTGHmU//MXfkOnVu1XJItT+aD8amNmWdxrQDVxx3u/iG0tFaGW2dZol4v+xVa75uOA5HnaWAL9BnkzF47Damo=', '9c896d751e3db00321cb4b2e4139e6b5'))
    </script> 
  </head>
  <body></body>
</html>

 

짜잔~ 매우 잘된다. 혹시나 해서 다른 방송으로 테스트해보니 그건 안됐다. 방송마다 암호화 키가 달랐던 것... 그렇다면 서버에서 받아오는 값 중에 키가 들어있겠지 싶어서 네트워크 탭에서 검색을 해봤다. 생각보다 허무하게도 암호화된 videoStreamUrl 키를 받아오던 api에 암호화 키도 들어있었다.

근데 키 이름은 왜 color지...

아무튼 이렇게 다시 방송 주소를 추출할 수 있었다. 글에는 성공 과정만 정리해놔서 쉽게 해결한 거 같지만 사실 중간에 삽질도 많이 했다...

반응형

+ Recent posts