관련지식
Cookie, Decompile, Instagram API

인스타그램의 WEB API 는 호출 횟수에 제한이 있습니다. 정상적인 호출이라고 하더라도 빈번하게 호출하게 되면 429 오류가 발생합니다. 3rd party app이 서버에 과도한 부하를 줄수 있으니 인스타그램으로서는 당연한 제약이겠지만, API를 사용하는 입장에서는 제약으로 인해 개발/서비스 하기가 어려울수도 있을것입니다.

그런데 아래와 같은 댓글을 하나 보게 되었습니다.

인스타그램 앱의 쿠키를 사용하면 제한없이 사용할수 있다는 뜻으로 해석되네요. 생각해보면 인스타그램 앱이 API를 사용하지 않을 이유가 없습니다. WEB API는 증권사 MTS처럼 0.1초 이내의 실시간 처리가 필요한 경우엔 적합하지 않지만 단순 조회 용으로는 매우 편리하기 때문입니다. 그래서 인스타그램도 API를 사용하고 있을것이라 가정하고, 어플의 쿠키값을 어떻게 하면 알아낼수 있을지 시도해 보았습니다.

MITM, SSL Strip

먼저 인스타그램 앱이 WEB API 형태를 사용하는지 확인해보았습니다.

Packet Capture 프로그램을 이용하여 확인했을때 WEB API인지는 알수 없지만 SSL을 호출한다는 것은 확인할수 있었습니다. 도메인 fbcdn.net 은 아마 이미지 서버인것으로 추측되지만 facebook.com 은 용도를 모르겠습니다. API 일수도 있고, 아닐수도 있습니다. 적어도 어디에선가 API를 사용할 가능성은 높아졌습니다.

그런데 HTTPS 즉 SSL로 호출하고 있기 때문에 트래픽 캡쳐 프로그램으로 간단하게 볼수는 없었습니다. SSL 통신을 가로채기 위해서 유명한 방식은 MITM / SSL Strip 방식이 있습니다.

MITM : http://www.itworld.co.kr/news/117021
SSL Strip : http://noplanlife.com/?p=1418

그러나 브라우저가 아닌 앱 기반에서 호출되는 것이라면 둘다 탐지가 가능할것으로 생각되어 시도를 안했습니다. 브라우저에서도 정상적인 SSL 연결이 되었는지 확인이 가능하니, 당연히 인스타그램 앱에서도 체크를 하고 있겠죠?

쿠키 파일

윈도우7 이후는 모르겠지만, 윈도우XP 시절을 생각해보겠습니다. 인터넷 익스플로러에서 어떤 도메인을 접속하게 되면, 해당 도메인에 대한 쿠키 파일을 Temporary Internet Files 에 생성을 했었습니다. 쿠키는 브라우저를 닫으면 삭제 되는것이 아니라 설정에 따라 오랜 기간 재사용이 되므로 쿠키 내용을 저장할 필요가 있는것이죠. 그것은 윈도우10, 크롬 브라우저, 모바일 환경 어디에서든 마찬가지 입니다. 저장하는 방식이 다를뿐이죠. 따라서 인스타그램 앱에서 저장한 쿠키 파일을 찾는게 더 쉽겠다는 생각을 했습니다. 물론 일반적으로는 앱 설치 디렉토리에 접근할수 없으므로 안드로이드 루팅을 해야만 합니다.

데이터 추출

사용중인 핸드폰에선 금융관련 앱을 사용해야 하고, 언루팅이 될지 확신할수 없으므로 Oracle VM VirtualBox 에 안드로이드를 설치하고 그것을 루팅하였습니다. 버추얼박스에 안드로이드를 설치하는 방법은 따로 설명하지 않겠습니다. VMM 이 사용가능한 시놀로지 사용자라면 VMM 에 안드로이드를 설치할 수도 있습니다.
안드로이드 루팅에는 Kingo Root 를 사용했습니다. 안드로이드 초기에 하던 루팅과 달리 루팅 앱 설치후에 실행을 하면 간단하게 루팅이 완료됩니다. 시스템이 재부팅되면 자동으로 언루팅이 되네요.

Kingo Root : https://www.kingoapp.com
VirtualBox : https://www.virtualbox.org

아래 이미지는 루팅 후에 Root Explorer를 이용하여 Root 디렉토리를 탐색하는 모습입니다. ‘ROOT > DATA > DATA’ 로 이동하니 인스타그램이 설치된 디렉토리 com.instagram.android 가 보이네요. 저 디렉토리를 내부 디렉토리로 복사하겠습니다.

많은 파일중에 어떤 파일이 쿠키와 관련된 파일인지 모르겠습니다. 인스타그램의 API 에서는 csrftoken 이라는 키를 사용하고 있는데, 그 이름으로 검색을 해보면 굉장히 수상해보이는 파일 한개가 찾아집니다.

저 파일의 내용을 한번 열어보겠습니다.

파일 이름도 그렇지만 xml 안에 있는 속성 이름들에 cookie_ 가 붙어 있는것이 제대로 찾은것 같습니다! 그런데 값들이 ‘ACDE0005~’ 형태로 있습니다. 암호화 또는 인코딩이 된것 같은데 저것을 풀지 못하면 의미가 없습니다.

소스 추출

안드로이드는 Play스토어를 통해 설치하지만, 설치된 프로그램을 APK로 추출하는 것은 ES파일탐색기 등 여러 프로그램을 통해서 쉽게 가능합니다. 추출한 APK는 디컴파일러를 이용하여 리소스와 자바 소스로 분리할수 있습니다. JDK 1.4 이후부터는 디컴파일된 소스의 완성도가 매우 떨어지지만 어쩔수 없습니다. 아쉬운대로 봐야죠. 디컴파일은 간편하게 온라인으로 하겠습니다.

APK Decompiler : http://www.javadecompilers.com/apk

기존 클래스가 난독화(obfuscation) 되어있었기 때문에 추출된 소스 대부분의 클래스 이름과 함수 이름이 의미 없는 이름으로 되어있지만, UserCookiePrefsFile_~.xml 파일을 읽는 소스 부분을 찾아보면 난독화되지 않은 이름중에 무척 의심스러운 이름이 보입니다.(어떤 부분인지는 생략합니다.)

해당 이름의 소스를 확인해보면 아래와 같습니다.

저 함수가 제대로 동작할지 모르지만 시도해 보는것이 좋겠네요. 소스의 내용을 참고하여 필요한 클래스 등을 추려냅니다. 물론 디컴파일된 소스가 있더라도 어느 정도의 코딩은 필요합니다. 저는 쿠키 정보가 저장된 xml 파일을 읽고 decodeCookie() 함수를 호출하는 부분을 코딩 했습니다. 그리고 실행해보면 제대로된 형태의 값이 보이게 됩니다.

테스트

뽑혀진 쿠키가 실제로 쓸수 있는 쿠키인지는 WEB API를 호출해보면 됩니다. Follow 정보를 알아낼수 있는 API는 ‘https://www.instagram.com/graphql/query?query_hash=58712303d941c6855d4e888c5f0cd22f&variables=%7B%22id%22:%22사용자아이디%22,%22first%22:%2210%22,%22after%22:%22%22%7D‘ 입니다. 이 API에 로그인정보가 연동되지 않으면 Follow count 만 조회되지만, 연동이 잘 될경우 Follow 사용자 목록까지 볼수 있을것입니다.(인스타그램이 로그인된 브라우저와 로그인되지 않은 브라우저에서 호출해보면 쉽게 차이를 확인할수 있습니다.) 참고로 사용자아이디는 로그인할때 사용되는 아이디가 아니라 내부적으로 사용되는 userid 입니다.(브라우저로 인스타그램 로그인후 개발자도구로 알아낼수 있습니다.)

쿠키를 연동하는 호출 테스트는 PostMan, RestClient, CURL 또는 직접 코딩을 하는등 여러 방법으로 할수 있습니다. CURL로 테스트 할 경우 아래와 같은 형태가 되겠네요.

  1. curl --cookie 'mid=XakGwAAEAAGFmz4DQz-ucU5m; csrftoken=gvaLDnJd2IE3v3SjjeHctbPDezI0; ds_user_id=사용자아이디; sessionid=223248085CEydJmo5TcQqt%3A3; shbid=10835; shbts=15735295.988997; rur=PRN; ' 'https://www.instagram.com/graphql/query?query_hash=58712303d941c6855d4e888c5f0cd22f&variables=%7B%22id%22:%22사용자아이디%22,%22first%22:%2210%22,%22after%22:%22%22%7D'

테스트를 해보면 정상적인 호출이 가능합니다. 저 쿠키로 WEB API를 무한 사용이 가능한지 아직 모르겠지만, 적어도 모바일 APP에서 사용하는 쿠키를 추출한건 맞는것 같습니다.

정리

이번에 작성한 내용은 실제 서비스되는 앱의 비정상적인 사용을 유도하는 내용이기 때문에, 제가 만든 코드나 디컴파일된 소스등 많은 내용은 공개하지 않고 과정 위주로 작성하였습니다. 하지만 저처럼 Java 코딩만 조금 할수 있으면 누구나 할수 있는 내용인것 같습니다. 혹시 인스타그램의 모바일 쿠키를 추출하고 싶은 분은 참고하시면 좋겠네요.

처음에 답변을 했던 외국 친구는 결국 어떻게 추출할수 있는지 답변을 안했는데, 궁금해하는 외쿡 친구들을 위해 제목에 영어도 넣었봤습니다. 과연 번역기로 이 글을 읽을수 있을지 모르겠네요 ㅎㅎ