LINEアプリのスタンプダウンロードについて解析してみる

私のウェブサイトにたどり着く検索ワードに、「LINE 解析」など、LINE関係の解析について知りたい方が多いようです。

ですので今回はLINEのスタンプについて書いていこうと思います。
iPhone版のアプリが、どうやってスタンプをダウンロードしているかです。
今回はアプリがサーバからスタンプをダウンロードし、フォルダに保存をするところまでをパソコン上でやります。
なお、アプリの逆コンパイルは禁止されている上に技術的にもそんなことできないので、
恐らくアプリはこうやってダウンロードしているんだろうなあ、という推定になります。

前提知識:スタンプフォルダの構成

自分の持っているスタンプのIDを特定

[LINEのフォルダ]/Library/Application Support/Sticker Packagesを開いてください。
f:id:shutingrz:20140813024246p:plain
"*1.*2.linestk"の、*1の部分がスタンプIDになります。

スタンプフォルダの構成

f:id:shutingrz:20140813032942p:plain
この画像を見てください。
ID:2431のフォルダの中に、
"*_key@2x.png"
"*@2x.png"
"productInfo.plist"
"tab_off@2x.png"
"tab_on@2x.png"
があります。

このファイル達は様々なタイプの画像になっています。

"*_key@2x.png"はトーク画面内のスタンプを選択した時の確認画面の画像
"*@2x.png"はスタンプの画像
"productInfo.plist"はスタンプの名前、値段などの情報
"tab_off@2x.png"は、トーク画面のスタンプ一覧で選択していない時の白黒画像
"tab_on@2x.png"は選択している時のカラー画像

また、LINE公式サイトからもスタンプのIDを特定できます。
LINE STOREに飛びます。
調べたいスタンプのURLにIDがあります。


アナと雪の女王のスタンプをダウンロードする

実はスタンプ達は購入しなくても誰でもダウンロードができるのです。
今回はスタンプID:2046の「アナと雪の女王」をダウンロードしていこうと思います。
burpsuiteでHTTPの盗聴をしながらスタンプショップの「アナと雪の女王」のスタンプ情報を見ると、
ttp://dl.stickershop.line.naver.jp/products/0/0/1/2046/iphone/productInfo.meta
にアクセスしていることが確認できます。
productInfo.metaの中身は以下のようになっています。

{"packageId":2046,"onSale":true,"validDays":0,"title":{"en":"Frozen","es":"Frozen","in":"Frozen","ja":"アナと雪の女王","ko":"겨울왕국","th":"Frozen","zh-Hans":"冰雪奇缘","zh-Hant":"冰雪奇緣"},"author":{"en":"The Walt Disney Company (Japan) Ltd.","ja":"ウォルト・ディズニー・ジャパン(株)","ko":"The Walt Disney Company (Japan) Ltd.","zh-Hans":"The Walt Disney Company (Japan) Ltd.","zh-Hant":"The Walt Disney Company (Japan) Ltd."},"price":[{"price":100.00,"symbol":"NLC","currency":"NLC","country":"@@"},{"price":15.00,"symbol":"HK$","currency":"HKD","country":"HK"},{"price":200.00,"symbol":"¥","currency":"JPY","country":"JP"},{"price":2000.00,"symbol":"₩","currency":"KRW","country":"KR"},{"price":2.58,"symbol":"S$","currency":"SGD","country":"SG"},{"price":60.00,"symbol":"NT$","currency":"TWD","country":"TW"},{"price":1.99,"symbol":"$","currency":"USD","country":"US"}],"stickers":[{"id":42836,"height":161,"width":170},{"id":42837,"height":151,"width":150},{"id":42838,"height":151,"width":159},{"id":42839,"height":151,"width":170},{"id":42840,"height":151,"width":160},{"id":42841,"height":150,"width":167},{"id":42842,"height":152,"width":165},{"id":42843,"height":161,"width":162},{"id":42844,"height":151,"width":174},{"id":42845,"height":151,"width":166},{"id":42846,"height":151,"width":182},{"id":42847,"height":161,"width":142},{"id":42848,"height":155,"width":166},{"id":42849,"height":161,"width":170},{"id":42850,"height":161,"width":170},{"id":42851,"height":151,"width":160},{"id":42852,"height":161,"width":130},{"id":42853,"height":151,"width":159},{"id":42854,"height":140,"width":185},{"id":42855,"height":142,"width":183},{"id":42856,"height":161,"width":167},{"id":42857,"height":152,"width":160},{"id":42858,"height":125,"width":179},{"id":42859,"height":151,"width":159},{"id":42860,"height":161,"width":183},{"id":42861,"height":156,"width":171},{"id":42862,"height":161,"width":130},{"id":42863,"height":151,"width":160},{"id":42864,"height":161,"width":160},{"id":42865,"height":161,"width":134},{"id":42866,"height":160,"width":159},{"id":42867,"height":151,"width":150},{"id":42868,"height":150,"width":149},{"id":42869,"height":152,"width":114},{"id":42870,"height":151,"width":160},{"id":42871,"height":161,"width":169},{"id":42872,"height":161,"width":162},{"id":42873,"height":133,"width":186},{"id":42874,"height":161,"width":157},{"id":42875,"height":159,"width":184}]}

順に見ていきましょう。

packageId:このスタンプのID
onSale:購入可能状態か
valieDays:有効期限
title:各言語(英語、日本語、韓国語、繁体字簡体字
price:各国の料金
stickers:スタンプ画像IDがスタンプの数だけあります。

このstickersのスタンプ画像IDは、例えば一番初めの画像ID、42836だと、
ttp://dl.stickershop.line.naver.jp/products/0/0/1/2046/PC/stickers/42836.png
ttp://dl.stickershop.line.naver.jp/products/0/0/1/2046/PC/stickers/42836_key.png
以上のように表示できます。

tab_off@2x.png、tab_on@2x.pngもダウンロードできます。
ttp://dl.stickershop.line.naver.jp/products/0/0/1/2046/android/tab_on.png

iPhoneのLINEアプリのスタンプフォルダの形式そのままにする

今までのURLを駆使して、2046.1.linestkフォルダを作成し、その中に
全ての*_key@2x.png、*@2x.png、tab_off@2x.png、tab_on@2x.pngをダウンロードし
そして最後に、productInfo.metaをproductInfo.plistに変換すれば、iPhoneのLINEアプリのスタンプフォルダそのままになります。
肝心のproductInfo.plistはどうすればいいでしょうか。これはMaxOSX版の独自の形式で、productInfo.metaそのままではありません。
というわけで作りました。
productInfo.metaからproductInfo.plistに変換するrubyスクリプトです。
gemでcfpropertylistを入れてください。

#!/usr/local/bin/ruby
# -*- coding: utf-8 -*-

require 'json'
require 'net/http'
require 'uri'
require 'cfpropertylist'

id = ARGV[0]
stdir = "#{id}.1.linestk"
plist = CFPropertyList::List.new

plistName = "productInfo.plist"
url = URI.parse("http://dl.stickershop.line.naver.jp/")
res = Net::HTTP.start(url.host, url.port) {|http|
  http.get("/products/0/0/1/#{id}/iphone/productInfo.meta")
}
js = JSON.parse(res.body)

data = Array.new
sp = Hash.new
js.each do |param|
	data << param
end

data.each do |line|
	if (line[1].class == Array || line[1].class == Hash) then
		hashs = Hash.new
		line[1].each do |value|
			hashs.store(value[0],value[1])
		end
	end
	sp.store(line[0],line[1])
end


plist.value = CFPropertyList.guess(sp)
plist.save("#{plistName}", CFPropertyList::List::FORMAT_BINARY)

引数にスタンプIDを入れれば、カレントディレクトリにproductInfo.plistが作成されます。



そしてそれを2046.1.linestkの中に入れれば、このスタンプを買った時と同じ構成のフォルダができあがります。
f:id:shutingrz:20140813040946p:plain

以上でLINEアプリがスタンプをダウンロードしている仕組みとなっています。
インターネット上の不特定多数が見られる場所にこうやって著作物を置いていて、ちょっと怖いですよね〜

                • -

追記
これを全て自動でダウンロードするスクリプトを作成しました。
ruby1.9で動きます。また、gemでcfpropertylistを入れてください。
使用する際は引数にスタンプIDを入れてください。


getStickers.rb