Search results

'분석'에 해당하는 글들

  1. 2011/07/13  [KakaoTalk] JSON Objects (5) (6)
  2. 2011/06/19  [KakaoTalk] Preliminary Research / Analysis (1) (3)

에.. 이번 글에서는 카카오톡 클라이언트와 서버 사이에서 어떤 데이터가 오고가는지 짧게 적어보려 합니다.
다른 플랫폼으로 (windows phone, pc, 등등) 포팅하실분들에게 약간이나마 도움이 될지도 모르겠네요.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

일단 제 프로그램에서는 세션키 인증이 끝나면 바로 친구 리스트를 불러옵니다.
친구리스트는 다음 URL에 리퀘스트를 보내면 받을 수 있습니다:
https://ch-talk.kakao.com/iphone/chats/list.json

그러면, 다음과 같은 object에 파싱해서 넣을 수 있습니다.

view [FriendsListJSON.cs]



앞으로의 모든 JSON 객체에서 status 필드를 보실 수 있는데, 0일 경우엔 성공 음수일 경우엔 각 에러코드를 나타냅니다. 예를들어, -500 은 세션키가 http 헤더에 제공되지 않았을때 리턴되고 -998은 잘못된 (서버에 등록되어있지 않은) 세션키가 제공되었을때 리턴됩니다.


각각의 Friend 객체는 다음과 같은 구조를 가지고 있습니다.
필드설명:
- type: 현재 친구와의 관계 (1 == 이미 친구, -4 == 친구 아님)
- directChatId: 직접 채팅(방) 아이디
- userId: 유져 고유번호
- nickName: 친구 이름 (상대방이 자신의 닉네임으로 설정한 것)
- phoneNumber: 폰 번호 (폰 번호가 저장되어있다면.. 아이디로만 저장되있으면 폰 번호 없음)
- profileImageUrl: 작은 프로필 사진 주소
- statusMessage: 이름 옆에 뜨는 '오늘의 메세지'
- friendNickName: 자신이 설정한 친구의 닉네임
- UUID: 아이디 (친구 검색할때 쓰는 아이디)
- fullProfileImageUrl: 원본 프로필 사진 주소

view [Friend.cs]




이제 친구 찾기에 대해서 알아봅시다~
친구찾기는 다음 url로 리퀘스트를 보내면 됩니다:
https://fr-talk.kakao.com/iphone/friends/find_by_uuid.json?uuid=UUID
찾고 싶은 친구의 아이디 (uuid)를 파라미터로 넘기면 다음과 같은 JSON이 리턴됩니다.

필드설명:
- status: 찾기 성공 여부 (0 == 찾음, -1002 == 존재하지 않는 아이디거나 공개찾기 거부)
- member: 상대방 정보 (사실 지금보니까 그냥 Friend 클래스를 썼어도 될것 같네요, 한가지 차이점은 friendNickName 필드가 없다는것 정도..)

view [FindFriendByUUIDJSON.cs]



친구 추가를 할 때는, 다음 url에 리퀘스트를 하면 됩니다:
https://fr-talk.kakao.com/iphone/friends/add.json?id=userId
여기서 주의해야 할 점은, 위에서 말씀드린 유져 고유번호인 userId를 넣어줘야한다는점입니다. UUID (사용자 아이디)가 아닙니다.

성공적으로 리스폰스가 돌아온다면 다음과 같은 JSON이 리턴됩니다.
필드설명 (FriendJSON class):
- status: 친구 추가 성공여부 (0 or 1 == 성공 | 처음으로 추가하는거면 0, 한번 해본적 있으면 1 인듯?)
- friend: 친구 정보

친구 삭제 시에는, 다음 url에 리퀘스트를 하면 됩니다:
https://fr-talk.kakao.com/iphone/friends/remove.json
하지만, 이번 리퀘스트는 그냥 GET으로는 파라미터를 넘길 수 없고, POST를 써야합니다 (한번에 여러 아이디 삭제가 가능하므로). POST 데이터는 다음과 같습니다:
ids=[userId1,userId2,...,userIdn]
이번 역시 userId를 넣어주어야합니다.

성공적으로 리스폰스가 돌아온다면 다음과 같은 JSON이 리턴됩니다.
필드설명 (FriendIdsJSON class):
- status: 친구 삭제 성공여부 (0 == 성공)
- friendIds: 삭제된 친구 userId 리스트 (클라이언트 리스트에서 삭제할 수 있도록)

view [FriendJSON.cs]



대충 이 정도하면 친구 불러오기, 찾기, 추가, 그리고 삭제와 같은 친구관련 작업들은 다 할 수 있습니다.

이제 마지막으로 채팅에 관련된 극히 일부분을 보도록 하죠 ㅎㅎ
최근에 시간이 없어서 (제일 중요한 ^^;) 채팅쪽을 많이 못봤습니다.. 베타버전에서 이미지 전송까지 해놓으려고했는데 다음..(기약없음..ㅋㅋ)으로 미뤄야하겠네요.

일단 다음은 채팅방 리스트를 불러오는 url 입니다:
https://ch-talk.kakao.com/iphone/chats/list.json

저는 개인적으로 세션키 validation을 할때밖에 쓰지 않습니다만.. 유용한 날이 오겠죠 ㅎㅎ

view [ChatListJSON.cs]




실질적으로 채팅이 이루어지는 부분을 보도록 하죠.
사실 카카오톡에서는 '채팅'의 개념보다는 '비동기식 메세지 교환' 이라고 보는게 나을지도 모르겠네요.
한쪽에서 메세지를 보내면, 이 메세지는 카카오톡 서버에 저장되어있다가 다른쪽 유져가 '나 메세지 받은거 있니?' 라고 물어보면 서버가 받아두었던 메세지를 전달해주는 방식입니다. 물론, 그 시점에서 서버단에서 그 메세지가 삭제가 되는지 저장이 되는지는 (^^;) 저로써는 알 방법이 없지만, 카카오톡 구조상 무조건 서버에 한번은 저장되어야 합니다.

그리고 또 한가지 재밌는것은, 카카오톡은 이미 처음부터 그룹채팅을 디자인으로 개발되었던것 같습니다.
그래서, 모든것이 다수가 참여할 수 있는 '채팅방'의 구조로 되어있고 1:1대화는 그저 유져가 두 명인 채팅방에 불과합니다.

다음 url로 채팅방을 생성 또는 메세지를 적을 수 있습니다:
https://ch-talk.kakao.com/iphone/chats/create_and_write.json

사실, 보통은 create_and_write은 대화를 맨 처음 할때 한번만 전송되고 그 이후부터는 그 채팅방에 부여된 채팅방 아이디를 사용해서 메세지를 보내고 받고 하지만, 저는 따로 내부 DB를 관리하고 있지 않기때문에 그냥 그때그때 create_and_write에 리퀘스트를 합니다. 그렇다고 그때마다 채팅방이 새롭게 생기는것은 아닙니다 ㅎㅎ 고맙게도(?) 이미 존재하는 채팅이면 서버단에서 처리를 해주는것 같더군요.

위의 리퀘스트는 당연히 POST이여야하고, POST 데이터는 다음과 같습니다:
receiver_ids[]=id1,id2,...,idn   (사실 저는 지금 1:1 만 지원중이라 여러아이디에 보내는데에 쓰이는 구분자가 잘 기억이 안나네요 -_-; 콤마였던거 같은데 아닐수도있으니 그룹대화 지원하실분은 체크 먼저 하시길..)
message=msg (한글은 UTF-8 인코딩해야함)
push_alert= true (또는 false)

필드설명 (ChatRoomJSON):
- status: 성공 여부 (0 == 성공적으로 전송, -401 == 실패했음)
- chatRoom: 채팅방 정보
- chatLogs: 채팅방 로그 (아직 확인 하지 않은 메세지들)

필드설명 (ChatRoom):
- type: 그룹인지 1:1인지 판별?
- activeMemberIds: 대화 참여중인 멤버 아이디들
- lastMessage: 마지막 메세지
- pushAlert: push notification 설정 되있는지 여부
- activeMembersCount: 참여중인 멤버 수
- members: 참여중인 멤버들 정보
- watermarks: ???
- lastUpdatedAt: 마지막으로 업데이트 된 시간 (내부 카운터)
- lastLogId: 마지막으로 확인한 로그 고유번호
- newMessageCount: 새 메세지 갯수
- chatId: 현재 채팅방의 고유번호

필드설명 (ChatLog):
- type: 까먹음 (그룹 또는 1:1?)
- logId: 로그 고유번호
- message: 메세지
- sendAt: 보내진 시간 (내부 카운터)
- chatId: 로그가 속한 채팅방 고유번호

view [ChatRoomJSON.cs]



해보지는 않았지만, 요즘 화두가 되고있는 '카카오톡 서버가 메세지를 저장을 하고 있느냐 아니냐'의 질문은 아무래도 이미 (채팅방 안의 모든 멤버가) 확인한 메세지의 ChatLog를 다시 불러올 수 있느냐 없느냐로 판별 할 수도있겠네요. 정상적이라면 채팅방에 있는 멤버가 특정 메세지를 모두 확인하는 순간 (즉, 메세지 옆에 뜨는 노란 숫자가 0이 되는 순간) 서버단에서 해당 로그를 지워야하겠죠. 그런데도 그 로그 아이디로 메세지를 불러올 수 있다면, 서버에 메세지들을 계속 저장하고 있다는 뜻이겠죠.

이제 마지막으로, https://ch-talk.kakao.com/iphone/chats/chatId.json?since=lastLogId 로 리퀘스트를 보내게 되면, 역시 ChatRoomJSON이 넘어오게 됩니다. 보시다시피 chatId와 lastLogId로 새로운 메세지가 도착했는지 안했는지 fetch할 수 있습니다. 방금전에 위에서 말한 테스팅을 손쉽게 할 수 있는 리퀘스트죠 :)

제가 해보진 않았습니다만.. (별로 그쪽엔 관심이 없는지라..) 다른분들이 해보시고 알게되면 댓글 달아주세요 ^^


대충 이정도가 제가 알고있는 자료구조입니다. 사실 자료구조라고 하기에도 좀 난감한 'JSON parsing' 입니다.
리퀘스트해서 돌아오는 리스폰스를 파싱해서 그 데이터를 알맞게 잘 쓰면 카카오톡 포팅이 가능한거죠.

나중에 시간과 기회가 된다면, 그룹대화 (뭐 이번 포스팅에서도 대충 설명하긴했습니다만..)와 이미지/동영상 등 전송에 대해서 설명하도록 하겠습니다.

질문이 있으시면 댓글로 남겨주시거나 이메일 주시면 됩니다~~




2011/07/13 23:34 2011/07/13 23:34
─ tag  , , ,

Starting with this blog post, and over the next few posts, I'm going to explain in detail what I have found out about internals for KakaoTalk -- the most popular mobile messaging service in Korea.

In this article, I'm going to briefly go over from what KakaoTalk is, and why it's interesting target to look at. (To be honest, I started this just for fun then turned into something that I wanted to blog about :p)

So, let the fun begin!

=-=-=-=-=-=-=-=-=-=-=

Preliminary research on KakaoTalk:
  • It is well-designed (in terms of the structure), well-organized (highly modular), and carefully planned application for the users. And as a plus, it is security-aware application :)
  • There are 15 million users, and the number is growing really fast.
  • Multi-lingual support. They really try hard to push this application globally. They utilize localization, so it's really easy for them to adopt any new language if they wanted to.
  • Kakao, for some reason, doesn't make a PC version of KakaoTalk.
    • Some people have tried to make PC version in the past, but many stopped once every packet is encrypted with SSL and thus packet capturing is meaningless.
    • My guess is that they are working on making KakaoTalk PC, but it may not be true after all :p (Maybe they don't want to be just like Skype, etc. and decided to stay only on mobile side.)
  • KakaoTalk supports both Android OS and iPhone OS.
    • Obviously, Android KakaoTalk is in Java and iOS KakaoTalk is in Object-C.
    • Uses the (very) similar protocol / data structure.
  • Some traces of development environments: (Minor Security Alert!)
    • They seem to use SVN to do version controlling, but failed to manage permissions properly. I didn't look closely anymore, but there might be some juicy/useful information that can be gathered with this vulnerability.
    • Webservers: http://www.kakao.com/.svn/entries , http://www.kakao.com/talk/.svn/entries, etc.

Well, that took me a good 20 minutes or so of googling and poking at their servers.
Not many interesting things.. So I decided to dig up some interesting facts about KakaoTalk!

To do preliminary analysis on applications, I needed to grab the binaries from my iPhone and my friend's Android. This was easily done by scp (secure copy) from my iPhone to my computer, since my device was already jailbroken. Now that I received two applications for KakaoTalk, one for iOS and the other for Android, I immediately started analyzing them.



Preliminary Analysis on KakaoTalk:

Well, before I actually open up the binaries and start disassembling, I started by running through a packet capture tool -- wireshark. As I mentioned above, the traffic was encrypted with SSL. Of course, there is known way of efficiently breaking SSL, so I didn't even try to decrypt the packets :)

사용자 삽입 이미지

SSL encrypted packets


I guess we only have one option now! Open up the binary and reverse engineer!

So we load up in IDA, and find these...awesome... wait.. what?
All the symbols are stripped?!

사용자 삽입 이미지

No Symbols :'(


I don't usually do Obj-C binary reversing, but when I do, I almost always found nicely annotated symbols! I'm not an expert at Mac Hacking, but because of the way Obj-C code does function calls, it's usually not trivial to strip symbols. (Or, I guess there's a tool that does it for you... haven't check it yet.)

BUT! Whatever! Reverse engineering is more fun without symbols. Right?

Again, the way Obj-C code runs is by event-driven function calls. Thus, there's no such thing as control flow as in usual C or C++ programs. Another annoying thing about analyzing mobile phone is that we have to deal with either ARM or MIPS architecture.

Note: For iPhone, the architecture is ARM. So, unless you have hexray-arm, you will have to go through awesome ARM opcodes. For Android, all the apps are java program that runs on Dalvik VM.. so it's usually possible to use decompilers to recover the source code (or at least some kind of IL).


Since two are almost exactly the same client, the program logic should also be very similar -- which means that if we understand one thing thoroughly, we will quickly understand the other one as well, even with the protections/obfuscation.

Ok, the binary for iPhone is stripped. How about Android one?

사용자 삽입 이미지

Obfuscated java!



Aww. Crap. We can successfully decompile the classes, but class names, method names, and variable names are all obfuscated. This makes reversing little bit harder since it's not trivial to follow the method or class names such as 'a' or 'b'. Also, Android KakaoTalk seems to use AESObfuscator. Of course, this can be decrypted since we know the IV (Initialization Vector) and other necessary parameters that were used to encrypt, but it's just a tad annoying. (AESObfuscator is basically just Base64 + AES)

At this point, I realized that KakaoTalk actually care about securing their application and the network traffic to some degree. This doesn't mean that it is perfectly secure, but they tried the security through obscurity -- usually this is a wrong way of doing security...


Anyhow, are we stumped then? The answer is 'not really'.

There are some tricks that we can do:
  1. Get (part of) code flow in iOS applications using debugger.
  2. Re-label the obfuscated java files to understand the program logic.
  3. Hack KakaoTalk server and get the source code...
And... using the information from above techniques + static analysis in IDA, we can actually disable SSL encryption -- such that we can view non-encrypted packet data.

In the next blog post, I will discuss and explain what exactly they do inside of the binary and show how I could bypass SSL and get a clean capture of the packets.

Also in the following series, I will talk about their protocols, data structures and design. And of course, the security measures on each of them.


Thanks for reading!




2011/06/19 23:04 2011/06/19 23:04
openclose