HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
0612
Aoriメインキーボードの履歴をテキストデータとして記録(続8解決


Aori

リンク

2011/6/12(Sun) 21:41:22|NO.39657

この前はお世話になりました。
今、思ったのですが、キーのデータはどうしてもonkeyを使わないと
記録できません。
そのonkeyですが、どうしてもウィンドウがアクティブでないと記録してくれません。
なので、アクティブでなくても記録できるようにすればいいでしょうか?
とりあえずスクリプトを載せておきます。

objsize 300,22 chkbox "キーボードを文字として「keydata.txt」として記録",c1 objsize 88,22 button "記録開始",*kiroku stop *kiroku ;"keydata.txt"が存在すればkeydataに読込 [ sdim keydata notesel keydata exist "keydatas.txt" if strsize != -1 : noteload "keydatas.txt" noteunsel ;] *main repeat //表示 mes "左クリック数"+b+"回" mes "右クリック数"+a+"回" mes "Enterキー押し下げ数"+ent+"回" mes "スペースキー押し下げ数"+spe+"回" //記録 stick key,0,0 if key&256:b+=1 if key&512:a+=1 if key&32 :ent+=1 if key&16 :spe+=1 ;キーボードとマウス両方のイベントとして設定 [ if (c1=1){ onkey gosub *mainkeychk } ;] a=ginfo(2) if a=-1:gsel 0,2 await 2 cls loop *mainkeychk notesel keydata ;keydataをノートとして選択 noteadd strf("[%c]", iparam)+gettime(0)+"/"+gettime(1)+"/"+gettime(2)+" "+gettime(4)+":"+gettime(5)+":"+gettime(6);ノートにiparamを文字列に変換して追加 notesave "keydatas.txt" ;ノートを"keydata.txt"として保存 noteunsel ;ノートの選択を解除 return
どうか皆様、回答をお願いします!



この記事に返信する


Cookies

リンク

2011/6/12(Sun) 21:50:42|NO.39658

ええ、そうなんですよ。
onkeyは便利ですが、アクティブでないと使えないのが欠点です。

簡単なやり方は、getkey or stickを使うことです。
ループ内に入れて、ずっと監視してるしかないです。

ループ内にウェイトを入れるわけですが、(入れないと…わかりますよね。。)
長すぎると短いキー入力が見つけられませんし、短すぎるとCPUを消費しすぎます。
それが気に入らなければ、WinAPIのGetAsyncKeyStateを使ってもいいかもしれません。

いや、全スレで木村さんが紹介している、e3dgetkeyboardstateを使ったほうがいいかも。



Cookies

リンク

2011/6/12(Sun) 21:51:50|NO.39659

すいません。前レスの、「全スレ」を「前スレ」に訂正お願いします。



木村

リンク

2011/6/13(Mon) 00:57:21|NO.39660

>>cookiesさん
 ごめんなさい。e3dgetkeyboardstate命令も、非アクティブ状態のキー入力は取得できません。

 キー情報はアクティブなウィンドウにしか送られないみたいなので、他のアクティブの受け取ったキー入力が欲しい場合はフックと呼ばれる処理でキー入力の情報を『横取り』しないといけないみたいです。
(恐ろしい事に『横取り』なので、キー情報をわざわざ返してあげないと、他のウィンドウ達はキー入力を一切受け取れなくなるという素晴らしい仕様らしい)

 仕方無いので、settimer命令を使ってWindowsから定期的にメッセージをもらうようにして、そのメッセージ(=WM_TIMER)を引き金にoncmd命令を発動させる事で解消させてみました。169行目辺りに変更部分があります。
 以下は一例ですが、何故WM_TIMERはデバッグ中にしか受け取れないのでしょうか?

#include "e3dhsp3.as" #include "hsp3util.as" #include "user32.as" #define WM_TIMER 0x0113 //使用する変数の領域を定義 dir = dir_cur //自身の存在するアドレス time = 0 //ログを取り始めてからの総フレーム数 note = "" //ログの保存先。行数が多いと鈍足になるので適時ハードに保存 page = 0 //ハードに保存したログの枚数 list = "" //dirlist命令への引数用途の変数。実際の意味は無い getdatestr t1 //t1 = 日時。ファイル名は[/]が使えないので[/]を変換 t1 = strmid(t1,0,4)+"年"+strmid(t1,5,2)+"月"+strmid(t1,8,2)+"日" gettimestr t2 //t2 = 時刻。ファイル名は[:]が使えないので[:]を変換 t2 = strmid(t2,0,2)+"時"+strmid(t2,3,2)+"分"+strmid(t2,6,2)+"秒" dim prekeybuf, 256 //1フレーム前の各キーの入力状態 dim keybuf, 256 //現フレームの各キーの入力状態 dim keycount, 256 //ログを取り始めてからの各キーの入力数 sdim keyname, 64, 256 //各キーの名前 repeat 256 //各キーに仮の名称を付ける keyname(cnt) = strf("unassigned($%02X)",cnt) loop //各キーに適当な名称を定義 keyname(VK_LBUTTON) = "左クリック"//$01 ;マウス 左クリック keyname(VK_RBUTTON) = "右クリック"//$02 ;マウス 右クリック keyname(VK_CANCEL) = "Ctrl+Break (CANCEL名義)"// $03 keyname(VK_MBUTTON) = "車輪クリック"//$04 ;/* NOT contiguous with L & RBUTTON */ keyname(VK_BACK) = "BackSpace (BACK名義)"// $08 keyname(VK_TAB) = "Tab"// $09 keyname(VK_CLEAR) = "非NumLock時のテンキー5 (CLEAR名義)"// $0C keyname(VK_RETURN) = "Enter (RETURN名義)"// $0D keyname(VK_SHIFT) = "Shift"// $10 keyname(VK_CONTROL) = "Ctrl"//$11 keyname(VK_MENU) = "Alt (MENU名義)"// $12 keyname(VK_PAUSE) = "Pause"// $13 keyname(VK_CAPITAL) = "Shift+CapsLock (CAPITAL名義)"//$14 keyname(VK_KANA) = "ひらがな/カタカナ (KANA名義)"// $15 keyname(VK_JUNJA) = "(JUNJA名義 $17)"// $17 keyname(VK_FINAL) = "(FINAL名義 $18)"// $18 keyname(VK_KANJI) = "Alt+半角/全角(HANJA名義)"// $19 keyname(VK_ESCAPE) = "Esc"// $1B ;エスケープキー keyname(VK_CONVERT) = "(CONVERT名義 $1C)"//$1C keyname(VK_NONCONVERT) = "(NONCONVERT名義 $1D)"// $1D keyname(VK_ACCEPT) = "(ACCEPT名義 $1E)"// $1E keyname(VK_MODECHANGE) = "(MODECHANGE名義 $1F)" // $1F keyname(VK_SPACE) = "Space"// $20 ;スペースキー keyname(VK_PRIOR) = "PageUp (PRIOR名義)"// $21 keyname(VK_NEXT) = "PageDown (NEXT名義)"// $22 keyname(VK_END) = "End"// $23 keyname(VK_HOME) = "Home"// $24 keyname(VK_LEFT) = "←"// $25 ;左矢印キー keyname(VK_UP) = "↑"// $26 ;上矢印キー keyname(VK_RIGHT) = "→"// $27 ;右矢印キー keyname(VK_DOWN) = "↓"// $28 ;下矢印キー keyname(VK_SELECT) = "(SELECT名義 $29)"// $29 keyname(VK_PRINT) = "(PRINT名義 $2A)"// $2A keyname(VK_EXECUTE) = "(EXECUTE名義 $2B)"//$2B keyname(VK_SNAPSHOT) = "(SNAPSHOT名義 $2C)"// $2C keyname(VK_INSERT) = "Insert"// $2D keyname(VK_DELETE) = "Delete"// $2E keyname(VK_HELP) = "(HELP名義 $2F)"// $2F word = "@" repeat 10 //数字 wpoke word, 0, 20354+cnt*256 keyname($30+cnt) = word loop repeat 26 //アルファベット wpoke word, 0, 24706+cnt*256 keyname($41+cnt) = word loop keyname(VK_LWIN) = "ウィンドウズキー左 (LWIN名義)"// $5B keyname(VK_RWIN) = "ウィンドウズキー右 (RWIN名義)"// $5C keyname(VK_APPS) = "Applicationキー[右クリックと等価] (APPS名義)"// $5D keyname(VK_SLEEP) = "(SLEEP名義 $5F)"// $5F word = "テンキーの@" repeat 10 //テンキーの数字 wpoke word, 10, 20354+cnt*256 keyname($60+cnt) = word loop keyname(VK_MULTIPLY) = "テンキーの*"// $6A keyname(VK_ADD) = "テンキーの+"// $6B keyname(VK_SEPARATOR) = "(SEPARATOR名義 $6C)"//$6C keyname(VK_SUBTRACT) = "テンキーの−"// $6D keyname(VK_DECIMAL) = "テンキーの."//$6E keyname(VK_DIVIDE) = "テンキーの/"// $6F word = "F@@" repeat 24 //ファンクションキー if cnt+1<10 { wpoke word, 4, 0 wpoke word, 2, 20354+(cnt+1)*256 } else { wpoke word, 2, 20354+((cnt+1)/10)*256 wpoke word, 4, 20354+((cnt+1)\10)*256 } keyname($70+cnt) = word loop keyname(VK_NUMLOCK) = "NumLock"//$90 keyname(VK_SCROLL) = "ScrollLock"// $91 keyname(VK_OEM_FJ_JISHO) = "(OEM_FJ_JISHO名義 $92)"// $92 ;// 'Dictionary' key keyname(VK_OEM_FJ_MASSHOU) = "(OEM_FJ_MASSHOU名義 $93)"//$93 ;// 'Unregister word' key keyname(VK_OEM_FJ_TOUROKU) = "(OEM_FJ_TOUROKU名義 $94)"//$94 ;// 'Register word' key keyname(VK_OEM_FJ_LOYA) = "(OEM_FJ_LOYA名義 $95)"// $95 ;// 'Left OYAYUBI' key keyname(VK_OEM_FJ_ROYA) = "(OEM_FJ_ROYA名義 $96)"// $96 ;// 'Right OYAYUBI' key keyname(VK_LSHIFT) = "左のShift"// $A0 keyname(VK_RSHIFT) = "右のShift"// $A1 keyname(VK_LCONTROL) = "左のCtrl"// $A2 keyname(VK_RCONTROL) = "右のCtrl"// $A3 keyname(VK_LMENU) = "左のAlt"// $A4 keyname(VK_RMENU) = "右のAlt"// $A5 keyname(VK_OEM_1) = "(OEM_1名義 $BA)"// $BA ;// ';:' for US keyname(VK_OEM_PLUS) = "(OEM_PLUS名義 $BB)"// $BB ;// '+' any country keyname(VK_OEM_COMMA) = "(OEM_COMMA名義 $BC)"//$BC ;// ',' any country keyname(VK_OEM_MINUS) = "(OEM_MINUS名義 $BD)"//$BD ;// '-' any country keyname(VK_OEM_PERIOD) = "(OEM_PERIOD名義 $BE)"// $BE ;// '.' any country keyname(VK_OEM_2) = "(OEM_2名義 $BF)"// $BF ;// '/?' for US keyname(VK_OEM_3) = "(OEM_3名義 $C0)"// $C0 ;// '`~' for US word = "(OEM_@名義 $@@)" repeat 5 //OEM_の4番目以降 keyname($DB+cnt) = strf("OEM_%01d名義 $%02X)",cnt+4,$DB+cnt) loop keyname(VK_OEM_102) = "(OEM_102名義 $E2)"//$E2 ;// "<>" or "\|" on RT 102-key kbd. //バッファ1の描画 buffer 1, 640, 500, 0 repeat 32 line -1, cnt*15, 640, cnt*15 line -1, cnt*15+14, 640, cnt*15+14 loop repeat 8 line cnt*80, -1, cnt*80, 480 line cnt*80+79, -1, cnt*80+79, 480 loop font msgothic, 12 for x, 0, 8, 1 for y, 0, 32, 1 pos x*80+2, y*15+2 mes strmid(keyname(x*32+y),0,13) next next list = "左クリック", "右クリック", "Enter", "Space" repeat 4 pos cnt*160, 484 mes list(cnt)+"  回" loop //マクロ定義(SAVE_NAMEはstrf関数の%が干渉したのでマクロにできず、残念) #define SAVE_DIR "入力ログのページ保管庫" ; #define ctype SAVE_NAME(%1) strf("ログの%04dページ目.txt",%1) //スクリーン0の描画 screen 0, 640, 500, 0 gsel 0, 2 pos 0, 0 color 255, 255, 255 gmode 4, 640, 480, 256 gcopy 1, 0, 0 //ログの保存先フォルダの作成と終了時の処理の定義 dirlist list, SAVE_DIR, 5 //listは飾り。dirlist命令の返り値が目当て if stat = 0 : mkdir SAVE_DIR onexit goto *ひゃっはー //実は結構危険な命令。使用時はヘルプ熟読の事 ;――――――――――――――――――――― //新規追加部分:手っ取り早く言うとループをウィンドウメッセージにした ;――――――――――――――――――――― settimer hwnd, 151, 50, 0 //ある種のループ命令 oncmd goto *タイマー発動ひゃっはー, WM_TIMER assert 1=0 //何故かデバッグ中じゃないとWM_TIMERを受け取ってくれない stop ;――――――――――――――――――――― //ループ部分 *タイマー発動ひゃっはー time += 1 e3dgetkeyboardstate keybuf redraw_flag = 0 repeat 256 change_flag = keybuf(cnt)-prekeybuf(cnt) //全域のredraw命令は処理が重いので、キー状態の変更時のみする方針で if change_flag ! 0 { if change_flag = 1 { //キーを押した場合 color 255, 255, 0 log = "入力" } else { //change_flag=-1、つまりキーから指を離した場合 color 255, 255, 255 log = "解放" keycount(cnt)+ //キーの入力とは指を離した瞬間だと考える } boxf (cnt/32)*80, (cnt\32)*15, (cnt/32)*80+79, (cnt\32)*15+14 pos (cnt/32)*80, (cnt\32)*15 color 255, 255, 255 gmode 4, 80, 15, 256 gcopy 1, (cnt/32)*80, (cnt\32)*15, 80, 15 notesel note noteadd strf("[%10d] "+keyname(cnt)+" を"+log,time) if notemax >= 100 { //ログが100行を超えたらハードに保存 chdir dir+"\\"+SAVE_DIR notesel note notesave strf("["+t1+" "+t2+"]ログの%04d枚目.txt",page) note = "" //ハードに保存したのでnoteを初期化 page+ //page数は1枚足す } redraw_flag = 1 //全域の再描画フラグ } loop if redraw_flag { //前述の全域再描画フラグが立っている場合は全域再描画 gmode 0, 640, 20 pos 0, 480 gcopy 1, 0, 480 font msmincho, 16 color list = VK_LBUTTON, VK_RBUTTON, VK_RETURN, VK_SPACE repeat 4 pos 60+cnt*160, 482 mes keycount(list(cnt)) loop redraw 1 redraw 0 } memcpy prekeybuf, keybuf, 256*4, 0, 0 //古いキー状態の更新 ; wait 3 stop //終了時の処理 *ひゃっはー chdir dir+"\\"+SAVE_DIR //メモリに駐在しているログをハードに保存 notesel note notesave strf("["+t1+" "+t2+"]ログの%04d枚目.txt",page) //ついでに総入力回数もハードに保存 note = "" notesel note repeat 256 if keycount(cnt) > 0 : noteadd keyname(cnt)+"   "+keycount(cnt)+"回" loop notesave "["+t1+" "+t2+"]キーの総入力回数.txt" end //強制終了。onexit命令使用時の最重要必須命令



Cookies

リンク

2011/6/13(Mon) 15:47:00|NO.39664

>ごめんなさい。e3dgetkeyboardstate命令も、非アクティブ状態のキー入力は取得できません。
 あれ?そうでしたっけ。すいません。。。
 GetAsyncKeyStateは、ちゃんと非アクティブの入力も取得できるようです。

>>aoriさん
 ちょっと悪い言葉かもしれませんが、「キーロガー」が作りたいわけですよね。
 それなら、「キーロガー スクリプト」でググると出たりするものです。
 http://ruffnex.oc.to/kenji/thekeylogger/KeyLogger.html
 プロセス隠蔽まで。。木村さんの言う「DLLインジェクション」についてもあります。
 これはDLLを作らねばなりませんので、HSPのみでは無理です。危険ですし。
 (自分もフックしてブルースクリーンへ行った経験あり。)

> 以下は一例ですが、何故WM_TIMERはデバッグ中にしか受け取れないのでしょうか?
 え、そんなことはないはず…これから調べますね。



Cookies

リンク

2011/6/13(Mon) 16:03:12|NO.39665

デバッグ解除してみましたが、ふつうに動きました。
174行目あたりのalertをコメントアウトして、
「HSP」→「Debugウィンドゥ表示」をオフにすればよいのですよね?

それから、
>//マクロ定義(SAVE_NAMEはstrf関数の%が干渉したのでマクロにできず、残念)
>#define ctype SAVE_NAME(%1) strf("ログの%04dページ目.txt",%1)
 前に発見したのですが、%を%%にするとうまくいくようです。


#define ctype SAVE_NAME(%1) strf("ログの%%04dページ目.txt",%1) 1=SAVE_NAME("6")//もちろんエラーが起きる。
と実行すると、


???(2) : error 2 : 文法が間違っています (2行目) --> 1=strf@hsp("ログの%04dページ目.txt",9999)
となるのがわかるでしょうか。ちゃんと置換されるようです。(偶然発見。)
正しいのかはわかりません。単なるバグかも。



木村

リンク

2011/6/16(Thu) 06:35:02|NO.39690

>>Cookies様
>前に発見したのですが、%を%%にするとうまくいくようです。
 おおっ、確かにこれで上手く動きます。仕様なのかバグなのか怪しい所が若干ありますけど、これでマクロの利便性が更に高まりました。ありがとうございます。

>デバッグ解除してみましたが、ふつうに動きました。
>174行目あたりのalertをコメントアウトして、
>「HSP」→「Debugウィンドゥ表示」をオフにすればよいのですよね?
 あら、普通に動作してしまいましたか。私の方の環境では、アクティブ時は普通に動くのですが、非アクティブ時のキー入力はデバッグ中でなければ受け取れませんでした。
 こちらの環境ではデバッグを利用するやり方はCPU使用率を2割近く食ってしまう為、やはりCookies様のおっしゃられたGetAsyncKeyState命令を利用する方法が、Aoriさんにとって最も最善の手段のように思えます。

>(自分もフックしてブルースクリーンへ行った経験あり。)
 やっぱりフックは危険な方法でしたか。推奨こそしませんでしたが、安易に提示するようなものではありませんでしたね。Aoriさんには危ない橋を渡らせる所でした。済みません。



info

リンク

2011/7/4(Mon) 05:22:56|NO.39925

windowhook 機能の内の一つである keyboardhook を使用すれば。
 確実に他のプロセスのキー入力を取得できますが。
 keyboardproc という名の コールバック関数を dll 内で 処理しなければ うまくいきません。

 幸なことに 月影とも さんがモジュールを作ってくださったようなので。
 下のページを参照してみればいいと思います。
 http://tu3.jp/0524



Aori

リンク

2011/9/11(Sun) 18:07:15|NO.41307

すみません。
かなりこのスレを放置していました......
ごめんなさい。
とりあえず皆様の発言を参考に「キーロガー」を作ろうと思います。。。
すみませんでした



ONION software Copyright 1997-2023(c) All rights reserved.