在幾位評論員的幫助下,我現在已經明白了。
Linux版本如下:
package main
import (
「bytes」
「encoding/binary」
「fmt」
「os」
「os/exec」
「syscall」
)
// parses through the /proc/bus/input/devices file for keyboard devices.
// Copied from `github.com/gearmover/keylogger` with trivial modification.
func dumpDevices() ([]string, error) {
cmd := exec.Command(「/bin/sh」, 「-c」, 「/bin/grep -E ‘Handlers|EV=’ /proc/bus/input/devices | /bin/grep -B1 ‘EV=120013’ | /bin/grep -Eo ‘event[0-9]+’」)
output, err := cmd.Output()
if err != nil {
return nil, err
}
buf := bytes.NewBuffer(output)
var devices []string
for line, err := buf.ReadString(‘\n’); err == nil; {
devices = append(devices, 「/dev/input/」+line[:len(line)-1])
line, err = buf.ReadString(‘\n’)
}
return devices, nil
}
// Using MS names, just because I don’t feel like looking up the Linux versions.
var keys = map[uint16]string{
0xa3: 「VK_MEDIA_NEXT_TRACK」,
0xa5: 「VK_MEDIA_PREV_TRACK」,
0xa6: 「VK_MEDIA_STOP」,
0xa4: 「VK_MEDIA_PLAY_PAUSE」,
}
// Most of the code here comes from `github.com/gearmover/keylogger`.
func main() {
// drop privileges when executing other programs
syscall.Setgid(65534)
syscall.Setuid(65534)
// dump our keyboard devices from /proc/bus/input/devices
devices, err := dumpDevices()
if err != nil {
fmt.Println(err)
}
if len(devices) == 0 {
fmt.Println(「No input devices found」)
return
}
// bring back our root privs
syscall.Setgid(0)
syscall.Setuid(0)
// Open the first keyboard device.
input, err := os.OpenFile(devices[0], os.O_RDONLY, 0600)
if err != nil {
fmt.Println(err)
return
}
defer input.Close()
// Log media keys
var buffer = make([]byte, 24)
for {
// read the input events as they come in
n, err := input.Read(buffer)
if err != nil {
return
}
if n != 24 {
fmt.Println(「Weird Input Event Size: 「, n)
continue
}
// parse the input event according to the <linux/input.h> header struct
binary.LittleEndian.Uint64(buffer[0:8]) // Time stamp stuff I could care less about
binary.LittleEndian.Uint64(buffer[8:16])
etype := binary.LittleEndian.Uint16(buffer[16:18]) // Event Type. Always 1 for keyboard events
code := binary.LittleEndian.Uint16(buffer[18:20]) // Key scan code
value := int32(binary.LittleEndian.Uint32(buffer[20:24])) // press(1), release(0), or repeat(2)
if etype == 1 && value == 1 && keys[code] != 「」 {
// In a real application I would send a message here.
fmt.Println(keys[code])
}
}
}
和Windows版本:
package main
import (
「fmt」
「syscall」
「time」
)
var user32 = syscall.NewLazyDLL(「user32.dll」)
var procGAKS = user32.NewProc(「GetAsyncKeyState」)
// Key codes from MSDN
var keys = [4]uint{
0xb0, // VK_MEDIA_NEXT_TRACK
0xb1, // VK_MEDIA_PREV_TRACK
0xb2, // VK_MEDIA_STOP
0xb3, // VK_MEDIA_PLAY_PAUSE
}
var names = [4]string{
「VK_MEDIA_NEXT_TRACK」,
「VK_MEDIA_PREV_TRACK」,
「VK_MEDIA_STOP」,
「VK_MEDIA_PLAY_PAUSE」,
}
func main() {
fmt.Println(「Running…」)
// Since I don’t want to trigger dozens of times for each key I need to track state.
// I could check the bits of GAKS’ return value, but that is not reliable.
down := [4]bool{false, false, false, false}
for {
time.Sleep(1 * time.Millisecond)
for i, key := range keys {
// val is not a simple boolean!
// 0 means 「not pressed」 (also certain errors)
// If LSB is set the key was just pressed (this may not be reliable)
// If MSB is set the key is currently down.
val, _, _ := procGAKS.Call(uintptr(key))
// Turn a press into a transition and track key state.
goingdown := false
if int(val) != 0 && !down[i] {
goingdown = true
down[i] = true
}
if int(val) == 0 && down[i] {
down[i] = false
}
if goingdown {
// In a real application I would send a message here.
fmt.Println(names[i])
}
}
}
}
唯一的 「問題」 是Linux版本必須以root身份運行。對我來說這不是問題。如果以root身份運行是一個問題,我認爲有一種方法涉及到X11 ...
你可能想用鍵盤記錄程序開始你的搜索。這是一個可以和linux一起使用的軟件包。類似的邏輯可以用於mac https://github.com/gearmover/keylogger。 Windows不在我的領域是知識,但我相信一些谷歌搜索和堆棧搜索將產生結果。 https://play.golang.org/p/wHJ-8D2nKT – reticentroot
謝謝你,我從來沒有想過檢查鍵盤記錄器......你鏈接的人有足夠的信息,我可以得到Linux的工作,現在我只需要一些Windows的東西.. (有趣的是,鏈接密鑰記錄器爲媒體密鑰產生未知的掃描碼錯誤,但這是因爲它的映射不完整)。 –
是的,可能是映射問題。你可能碰到過這個窗口,但如果不是這裏的窗口。 https://github.com/SaturnsVoid/Windows-KeyLogger – reticentroot