ひとまずやっつけ版 ◆RGSS..WS4M ■ まとめ * 送信先 - http://tkoolwatch.hp.infoseek.co.jp/cgi-bin/sn_inter/vote8.cgi * 送信されるタイミング - セーブを行った後,マップに戻ったタイミング (おそらく) * 送信されている情報 - 主人公 ( アクター番号 1 ) のステータス (Lv, HPなど) - ゲーム変数 44 の内容 - ゲーム変数 46 の内容 - 所持金 - パーティにいるキャラクタのIDとレベル - プレイ時間 (フレームカウント/フレームレート) - 送信時刻(この送信データを作った時刻) - 現在のマップ名 - セーブ回数 * 送信していないが収集されている可能性のある情報 - IPアドレス - リモートホスト ※ アクター番号とかゲーム変数の名前も判明したので追記 - ゲーム変数1 -> SB3:ストーリー進行 - ゲーム変数44 -> シリアルナンバー - ゲーム変数46 -> 戦闘した回数 - アクター1番 -> ぽにまろ シリアルナンバーっていうのは起動時(Scene_Title#main)の # シリアルナンバーを作成 now_time = Time.now ye = now_time.year * 100000000 mo = now_time.month * 1000000 dy = now_time.day * 10000 ho = now_time.hour * 100 mn = now_time.min * 1 $sil_num = ye + mo + dy + ho + mn だそうで。 ■ 解析メモ * スクリプト内部の送信処理 Scene_Save で $post_name, $post_comment を設定 トリガーはゲーム変数 1 が 5 より大きいとき $post_name は ゲーム変数 44 と セーブ回数を結合した文字列 $post_comment はこれやってないからわかんないけど主人公( アクター番号 1 )のレベルとかHPとか,あとは所持金などのステータスの模様。 スクリプトしかみてないからなんともいえないけど,普通にセーブする以外にもイベントでセーブしてたりするとここに飛ぶ可能性はある。 if $game_variables[1] > 5 save_count = $game_system.save_count.to_s $post_name = $game_variables[44].to_s + "_" + save_count line1 = "Lv " + $game_actors[1].level.to_s + " - HP " + $game_actors[1].maxhp.to_s line2 = " [" + $game_actors[1].level_grapple.to_s line2 += "," + $game_actors[1].level_sword.to_s line2 += "," + $game_actors[1].level_spear.to_s line2 += "," + $game_actors[1].level_axe.to_s line2 += "," + $game_actors[1].level_bow.to_s line2 += "," + $game_actors[1].level_cane.to_s + "] " line3 = $game_party.gold.to_s + "G / Bat-" + $game_variables[46].to_s + " : " line4 = "" for i in 0...$game_party.actors.size actor = $game_party.actors[i] if i < $game_party.actors.size - 1 line4 += "C" + actor.id.to_s + "-" + actor.level.to_s + " " else line4 += "C" + actor.id.to_s + "-" + actor.level.to_s + " / Tim-" end end total_sec = Graphics.frame_count / Graphics.frame_rate hour = total_sec / 60 / 60 min = total_sec / 60 % 60 sec = total_sec % 60 time_string = sprintf("%2d.%02d.%02d", hour, min, sec) line5 = time_string + " Now-" line6 = "" now_time = Time.now ye = now_time.year * 100000000 mo = now_time.month * 1000000 dy = now_time.day * 10000 ho = now_time.hour * 100 mn = now_time.min * 1 mp_tm_dt = load_data("Data/MapInfos.rxdata") line6 = (ye + mo + dy + ho + mn).to_s + " / " + mp_tm_dt[$game_map.map_id].name $post_comment = line1 + line2 + line3 + line4 + line5 + line6 end $post_name が空文字列じゃなくなったとき, Scene_Map で$post_name と $post_comment のデータ送信 送信先は http://tkoolwatch.hp.infoseek.co.jp/cgi-bin/sn_inter/vote8.cgi GET パラメータは mode=bbswrt&name=$post_name&com=$post_comment&vote=upload # MADE IN RGSS $post_name = "" if $post_name == nil $post_comment = "" if $post_comment == nil if $post_name != "" @postran_list1 = "" for i in 0...$post_name.split(//).size str = WinInet.pos_trc($post_name.split(//)[i]) @postran_list1 += str end @postran_list2 = "" for i in 0...$post_comment.split(//).size str = WinInet.pos_trc($post_comment.split(//)[i]) @postran_list2 += str end saba = "http://tkoolwatch.hp.infoseek.co.jp/" dirc = "cgi-bin/sn_inter/vote8.cgi" name = "?mode=bbswrt&name=" + @postran_list1 comt = "&com=" + @postran_list2 + "&vote=upload" WinInet.get(saba + dirc + name + comt) $post_name = "" end IPアドレスやリモートホストは CGI 側で取得することが可能なので送信する必要はない。 なんというスパイウェア。 それにしてもイテレータって概念しらんのか…。どこからつっこんでいいものやら。 忙しいのでかなり適当な解析。 WinInet使ってるので以前自分が作ったヤツが悪用されてる可能性もあるのであとでもうちょい詳しく調べます。 ■ おまけ WinInet使われてました。作り込まないでよかった。 パクられたあげく無様な改変されてる… # script by ◆RGSS..WS4M #$post_name = "" if $post_name == nil #$post_comment = "" if $post_comment == nil #if $post_name != "" # @postran_list1 = "" # for i in 0...$post_name.split(//).size # str = WinInet.pos_trc($post_name.split(//)[i]) # @postran_list1 += str # end # @postran_list2 = "" # for i in 0...$post_comment.split(//).size # str = WinInet.pos_trc($post_comment.split(//)[i]) # @postran_list2 += str # end # saba = "http://tkoolwatch.hp.infoseek.co.jp/" # dirc = "cgi-bin/sn_inter/vote8.cgi" # name = "?mode=bbswrt&name=" + @postran_list1 # comt = "&com=" + @postran_list2 + "&vote=upload" # WinInet.get(saba + dirc + name + comt) # $post_name = "" #end module WinInet INTERNET_OPEN_TYPE_DIRECT = 0x1 # direct connection INTERNET_OPEN_TYPE_PRECONFIG = 0x0 # using IE config INTERNET_OPEN_TYPE_PROXY = 0x3 # using proxy INTERNET_INVALID_PORT_NUMBER = 0x0 INTERNET_FLAG_ASYNC = 0x10000000 # async INTERNET_FLAG_FROM_CACHE = 0x01000000 # using cache (offline) INTERNET_FLAG_OFFLINE = 0x01000000 INTERNET_FLAG_RELOAD = 0x80000000 INTERNET_FLAG_NO_CACHE_WRITE = 0x04000000 INTERNET_FLAG_NO_AUTO_REDIRECT = 0x00200000 INTERNET_FLAG_PRAGMA_NOCACHE = 0x00000100 @@internet_open = Win32API.new("wininet", "InternetOpen", %w(P L! P P L!), "I") @@internet_open_url = Win32API.new("wininet", "InternetOpenUrl", %w(I P P L! L! L!), "I") @@internet_read_file = Win32API.new("wininet", "InternetReadFile", %w(I P L P), "I") @@internet_close_handle = Win32API.new("wininet", "InternetCloseHandle", %w(I), "I") @@multi_byte_to_wide_char = Win32API.new('kernel32', 'MultiByteToWideChar',%w(I L! P I P I), "I") @@wide_char_to_multi_byte = Win32API.new('kernel32', 'WideCharToMultiByte',%w(I L! P I P I P P),"I") def self.internet_open return @@internet_open end def self.internet_open_url return @@internet_open_url end def self.internet_read_file return @@internet_read_file end def self.internet_close_handle return @@internet_close_handle end POSTRANCE_TABLE = [ "a","i","u","e","o", "ka","ki","ku","ke","ko", "sa","si","su","se","so", "ta","ti","tu","te","to", "na","ni","nu","ne","no", "ha","hi","hu","he","ho", "ma","mi","mu","me","mo", "ya", "" ,"yu", "" ,"yo", "ra","ri","ru","re","ro", "wa", "" ,"wo", "" ,"wn", "ga","gi","gu","ge","go", "za","zi","zu","ze","zo", "da","di","du","de","do", "ba","bi","bu","be","bo", "pa","pi","pu","pe","po", "ya","yu","yo","_","wa", "a","i","u","e","o", "-","=", "_" , "." , "." , "A","I","U","E","O", "KA","KI","KU","KE","KO", "SA","SI","SU","SE","SO", "TA","TI","TU","TE","TO", "NA","NI","NU","NE","NO", "HA","HI","HU","HE","HO", "MA","MI","MU","ME","MO", "YA", "" ,"YU", "" ,"YO", "RA","RI","RU","RE","RO", "WA", "" ,"WO", "" ,"WN", "GA","GI","GU","GE","GO", "ZA","ZI","ZU","ZE","ZO", "DA","DI","DU","DE","DO", "BA","BI","BU","BE","BO", "PA","PI","PU","PE","PO", "YA","YU","YO","_","WA", "A","I","U","E","O", "-","=", "VU" , " " , "_" , "1","2","3","4","5", "6","7","8","9","0", "_","_","_","_","_", "Cast","Mura","Towr","Cave","Houz", "Port","Isln","Ke","Nai","Sou", "Drem","Ykt","Sono","Erth","Flr", "Undr","Kai","Wrld","Road","F", "あ","い","う","え","お", "か","き","く","け","こ", "さ","し","す","せ","そ", "た","ち","つ","て","と", "な","に","ぬ","ね","の", "は","ひ","ふ","へ","ほ", "ま","み","む","め","も", "や", "" ,"ゆ", "" ,"よ", "ら","り","る","れ","ろ", "わ", "" ,"を", "" ,"ん", "が","ぎ","ぐ","げ","ご", "ざ","じ","ず","ぜ","ぞ", "だ","ぢ","づ","で","ど", "ば","び","ぶ","べ","ぼ", "ぱ","ぴ","ぷ","ぺ","ぽ", "ゃ","ゅ","ょ","っ","ゎ", "ぁ","ぃ","ぅ","ぇ","ぉ", "ー","・", "・" , "!" , "?" , "ア","イ","ウ","エ","オ", "カ","キ","ク","ケ","コ", "サ","シ","ス","セ","ソ", "タ","チ","ツ","テ","ト", "ナ","ニ","ヌ","ネ","ノ", "ハ","ヒ","フ","ヘ","ホ", "マ","ミ","ム","メ","モ", "ヤ", "" ,"ユ", "" ,"ヨ", "ラ","リ","ル","レ","ロ", "ワ", "" ,"ヲ", "" ,"ン", "ガ","ギ","グ","ゲ","ゴ", "ザ","ジ","ズ","ゼ","ゾ", "ダ","ヂ","ヅ","デ","ド", "バ","ビ","ブ","ベ","ボ", "パ","ピ","プ","ペ","ポ", "ャ","ュ","ョ","ッ","ヮ", "ァ","ィ","ゥ","ェ","ォ", "ー","・","ヴ", " " , ":" , "1","2","3","4","5", "6","7","8","9","0", "(",")","(",")","#", "城","村","塔","窟","屋", "港","島","家","内","装", "夢","館","園","地","階", "下","会","界","道","F", ] # 辞書置換(総当りで該当を変換) def self.pos_trc(str) re = str for i in 215...POSTRANCE_TABLE.size if str == POSTRANCE_TABLE[i] re = POSTRANCE_TABLE[i - 215] end end return re end def self.get(url) result = "" h_internet = self.internet_open.call( "WinInet - test", INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0 ) h_file = self.internet_open_url.call( h_internet, url, nil, 0, INTERNET_FLAG_RELOAD, 0 ) loop do buf = "\0" * 9001 read_size = [0].pack("L") b_result = self.internet_read_file.call( h_file, buf, 9001, read_size ) read_size = read_size.unpack("L").first if read_size == 0 then break end result += buf; end self.internet_close_handle.call(h_file) self.internet_close_handle.call(h_internet) # sjis -> unicode length = @@multi_byte_to_wide_char.call( 932, 0, result, result.length, nil, 0) buffer = "\0" * length * 2 @@multi_byte_to_wide_char.call( 932, 0, result, result.length, buffer, length) # unicode -> utf-8 length = @@wide_char_to_multi_byte.call( 65001, 0, buffer, -1, nil, 0, nil, nil) result = "\0" * length @@wide_char_to_multi_byte.call(65001, 0, buffer, -1, result, result.length, nil, nil) return result end end