Mechanizeでソシャゲーにログインしよう
ソシャゲーやってると、機能不足を感じるんですよ。
例えば、持ってるアイテムの一覧とか、レベルアップ可能な一覧とか。
そういう、支援が欲しいんですよ。
今回は、某ソシャゲーに、Mechanizeでログインするところまでやろうと思います。
cookieの復号
色々検索してたら、Win32APIのCryptUnprotectData()を使うことで、復号できるそうです。
ってことで、書いてみました。
require 'fiddle/import' require 'fiddle/types' module WinAPI module Win32 extend Fiddle::Importer dlload 'kernel32.dll', 'crypt32.dll' include Fiddle::BasicTypes include Fiddle::Win32Types extern 'long LocalFree(void*)' extern 'BOOL CryptUnprotectData(DATA_BLOB*, LPWSTR*, DATA_BLOB*, PVOID, CRYPTPROTECT_PROMPTSTRUCT*, DWORD, DATA_BLOB*)' DATA_BLOB = struct(['DWORD size', 'void* data']) end NULL = 0x00 CRYPTPROTECT_UI_FORBIDDEN = 0x01 def crypt_unprotect_data (val) data_in = Win32::DATA_BLOB.malloc data_in.size = val.bytesize data_in.data = val data_out = Win32::DATA_BLOB.malloc success = Win32::CryptUnprotectData(data_in, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, data_out) unless success raise Exception('Failed to decrypt data'); end unprotect_data = data_out.data.to_str(data_out.size) Win32::LocalFree(data_out.data) unprotect_data end module_function :crypt_unprotect_data end
それと、拡張
module MechanizeExtension refine Mechanize do def load_chrome_cookie (cookie_domain, cookie_path='/') path_to_chrome_cookies = Object::File.expand_path('AppData/Local/Google/Chrome/User Data/Default/Cookies', ENV['USERPROFILE']) unless File.exists? path_to_chrome_cookies raise "Not found Chrome cookie database file." end load_cookies = {} db = nil begin require 'sqlite3' db = SQLite3::Database.new(path_to_chrome_cookies) db.results_as_hash = true sql = "select * from cookies" + " where host_key like \"#{cookie_domain}\"" + " and path = \"#{cookie_path}\"" time_from_utc = ->(utc){ Time.at(Time.utc(1601,1,1,0,0,0,0).to_i, utc) } db.execute(sql) do |r| r['creation_utc'] = time_from_utc.call(r['creation_utc']) r['expires_utc'] = time_from_utc.call(r['expires_utc']) if r['value'].nil? or r['value'].empty? r['value'] = WinAPI::crypt_unprotect_data(r['encrypted_value']) end load_cookies[r['name']] = r end rescue => err p err ensure db.close unless db.nil? end load_cookies.each do |name, param| cookie_params = { name: name , value: param['value'] , domain: cookie_domain , expires: param['expires_utc'] , created_at: param['creation_utc'] , path: cookie_path , } cookie = Mechanize::Cookie.new(cookie_params) self.cookie_jar.add(cookie) end self.cookies.map{|e| e.cookie_value + ';'}.join(' ') end end end
使い方
こんな風に使えます。
# extensions using MechanizeExtension # configuration m = Mechanize.new.tap{|x| x.user_agent = $config['UserAgent'] x.load_chrome_cookie($config['CookieDomain']) } # get html html = m.get($config['BaseURL'])
良いソシャゲーライフを! (サーバーに負荷をかけちゃ駄目ですよ)