After I analyzed LOCO protocol of KakaoTalk, I’ve been curious about the operation of other messaging applications. Like KakaoTalk, LINE is the instant messaging application on smartphones and PCs. LINE is not popular in Korea, but media currently said that LINE is one of the most popular messaging app in Japan. So, I decided to analyze the protocol of LINE and I’ll record the steps that I followed in this post. My final goal is to implement the LINE protocol in python, especially sending and receiving messages.
1. Download xap file
First of all, I needed a xap file of LINE windows mobile application, so I searched it on Google.
Finally, I found the old version of LINE xap file (version : 1.7.0.71). The latest version of windows LINE application is 2.7.0.155.
2. Unzip xap file
The first thing that attracted me was ‘Line.dll’ file and I guessed it may have core functions for the chat protocol. And also, I could see ‘Thrift.dll’ which is the library for Thrift framework. After I searched Google for a moment, I found that Thrift is an open source project for cross-language service built by Apache.
Now, I knew LINE uses Thrift library for network communication, which is not their own protocol, so I thought it might be easy to implement LINE chat system (compare to LOCO protocol).
3. Packet Analysis
Before I did the static analysis, I used Windows mobile phone emulator for the packet analysis. Of course, the network between application and server was encrypted using https. There were some packets which seem to be TCP protocol but I focused on the HTTP communication. After looked over the packet, I used .Net reflector to see the real decompiled source code of applications.
I searched https as a string, changed them to http, and re-zipped the xap file. At this point, I found out that the DNS of main server for chat communication was gm.line.naver.jp. Especially, gm.line.naver.jp/S3 is used for authorization and chat service for LINE.
http://gm.line.naver.jp/api/v3/TalkService.do for talkSession
Then, I could see the plain chat communication between server and client in the packets.
I’m not sure that HTTP is LINE’s main protocol, because LOCO protocol of KakaoTalk used their own packet structure which was encrypted with AES. As you can see, LINE doesn’t encrypt any messages, so I can see the plain message from packet. Also, X-Line-Access, which was included in the header, seems like a session key, so I was wonder whether the previous session can be used for communication or not. So I quickly wrote a dirty python code which send the exactly same packet to the server…
print"[*] Result " data = response.read() print data #data = json.loads(data ,encoding='utf-8')
if __name__ == '__main__': send()
It worked pretty well!
HTTP(S) data
Now, I decide to analyze the LINE protocol in more detail.
4. HTTP(S) Analysis
There are two particular headers, one is X-Line-Application and the other is X-Line-Access. The first header, X-Line-Application, specify the kind of mobile phone, which is not that interesting one ;(
However, the second header X-Line-Access seems like a session key and part of the key is encrypted by Base64. I’ll talk about this later. Anyway, after I decode the encrypted data, I can get iat: 1378973334524 (string data) and ��" [���<Z� � 5wxwO� (byte[] data)
The format of POST data seems like ‘bson’ string which is used in LOCO protocol but it isn’t. To find out how the application deals with the session key and what kind of data type is used for POST data, I used .NET Reflector again and find out some interesting functions like send_sendMessage(int seq, Message message).
As you can see in this picture, there is a string sendMessage which also can be found in the POST data. Therefore, I guess that this sendMessage function makes the POST data. I also figure out that WriteMessageBegin() and WriteMessageEnd() are the functions for Thrift platform. I keep read some posts and decompiled codes to find out how Thrift works, but I can’t figure out the exact structure of Thrift HTTP protocol.
## VERSION of Thrift protocol ## # TBinaryProtocol.VERSION_1 | type data = '\x80\x01\x00\x01'
## Function ## # \x00\x00\x00\x0b : sendMessage # \x00\x00\x00\x0f : fetchOperations, for read message data += '\x00\x00\x00\x0b'# length of function data += 'sendMessage'
## Message information for static message ## ## (not include sticker information) ## data += '\x00\x00\x00\x00' data += '\x08\x00\x01\x00' data += '\x00\x00\x00\x0c' data += '\x00\x02\x0b\x00'
# \x01\x00\x00\x00 : from # \x02\x00\x00\x00 : to data += '\x02\x00\x00\x00'# to data += '????'# chat id to send message data += '\x0b\x00\x0a'# ChatId footer
## User input : not included in Thift protocol ## message = raw_input(">> ")
## Length of message ## #data += '\x00\x00\x00\x10' # \x06 : length data += struct.pack('>I',len(message))
## Message ## #for i in range(16): # data += chr(49 + i) # 65 : A, 49 : 1 data += message
## Message footer ## #data += '\x0a\x02\x00\x0e\x00\x00\x00' data += '\x02\x00\x0e\x00\x00\x00'
The bellow picture is the structure of Thrift packet based on the packet analysis that I took. (which may include some errors)
And the bellow code is a short python code which can be used to send message to someone (not me).
defsend(): data = '\x80\x01\x00\x01\x00\x00\x00\x0b' data += 'sendMessage' data += '\x00\x00\x00\x00\x08\x00\x01\x00\x00\x00\x00\x0c\x00\x02\x0b\x00\x02\x00\x00\x00' data += '????'# chat id to send message data += '\x0b\x00\x0a' message = raw_input(">> ") data += struct.pack('>I',len(message)) data += message data += '\x02\x00\x0e\x00\x00\x00'
data = response.read() for d in data: print"%#x" % ord(d), print print data
while1: send()
I can also figure out how to send an emoticon message through LINE. I wish I can send some emoticons, which I have to buy to use them, but it doesn’t worked with an error message “current user does not have this sticker” :(
ps. you can send some charged emoticons in LOCO protocol for nothing :)
Session key
Finally, I want to talk about session key and auth key.
5. Session key
At first, I tried to follow UpdateAuthToken() function because this function adds the X-Line-Access header to the HTTP protocol. As I followed this function, I finally arrived to create() function which updates the old session key. It wasn’t hard to understand how this function updates authKey, but I couldn’t figure out when LINE change an auth key.
It seems like LINE’s session key is changed when a user change his/her mobile phone or re-install the application. In other words, the session key won’t be changed if you don’t erase or change your mobile phone. This can cause security problems if someone change the code of LINE application and distribute it to the internet…but I don’t think it will happen :)
Bellow is the list of functions that I followed to find out how LINE update their authorization key.
publicstaticstringGetAccessToken(string authKey) { long timestamp = (DateTime.get_UtcNow() - new DateTime(0x7b2, 1, 1, 0, 0, 0, 1)).get_TotalMilliseconds(); // use time stamp for making access token return GetAccessToken(timestamp, authKey); }