Examples
Complete, runnable Lua handlers for common protocols
Each example below is a complete handler. You can save it as a .lua file and run it with gonetsim run <file>.lua@<port>, or wire it into your config as a custom listener.
This is the best demonstration of what a script can cover in GoNetSim. It accepts mail and captures envelope addresses, the message body and decoded AUTH credentials.
The full handler can be found at examples/handlers/smtp.lua in the repository.
The complete version adds what makes it production-worthy as a sink:
- AUTH via
PLAIN&LOGINwith a ~20-line base64 decoder written in Lua, so captured credentials are decoded before being saved to the artifacts directory - Message lines that start with a dot arrive doubled; the handler strips them so captured messages read exactly as sent
conn:sleepbefore responses, for malware that treats instant answers as suspicious
Sends everything back to the client.
function handle(conn) while true do local data = conn:read(4096) if not data then break end conn:write(data) endendTry it with netcat localhost 7777. GoNetSim also ships this as a built-in (builtin:echo) so you don’t normally need to write it yourself.
UDP Responder
Section titled “UDP Responder”UDP scripts define handle_packet instead of handle. Each datagram is passed in as a string, and returning a string sends a reply back to the client.
function handle_packet(data) if data == "ping" then return "pong" end return nil -- no reply for anything elseendRun it on UDP with the /udp suffix, then test it:
gonetsim run pong.lua@:9999/udpecho "ping" | netcat -u localhost 9999 # replies with: pongThis handler tracks a nickname across commands and answers the few IRC messages malware usually needs to see:
function handle(conn) local nick = "guest"
conn:write(":gonetsim 001 " .. nick .. " :Welcome to GoNetSim IRC\r\n")
while true do local line = conn:read_line() if not line then break end line = line:gsub("%s+$", "")
if line ~= "" then capture:write("irc", line)
local cmd = line:match("^(%S+)") if cmd == "NICK" then nick = line:match("^NICK%s+(%S+)") or nick conn:write(":gonetsim 001 " .. nick .. " :Nickname set\r\n") elseif cmd == "PING" then conn:write(":gonetsim PONG gonetsim :" .. line:match("^PING%s+(.+)$") .. "\r\n") elseif cmd == "PRIVMSG" then conn:write(":gonetsim 001 " .. nick .. " :Message received\r\n") elseif cmd == "QUIT" then break end end endendPoint an IRC client at it, or a sample of malware that beacons over IRC, and every PRIVMSG it sends is captured under an === irc === section in the artifacts directory.
HTTP Headers
Section titled “HTTP Headers”read_until makes header-style protocols easy. This handler collects everything up to the blank line ending an HTTP header block, then replies with a fake page:
function handle(conn) local headers = conn:read_until("\r\n\r\n") if headers then capture:write("request", headers) local body = "<html><body>GoNetSim</body></html>" conn:write("HTTP/1.1 200 OK\r\n") conn:write("Content-Length: " .. #body .. "\r\n") conn:write("Connection: close\r\n\r\n") conn:write(body) endendFor real HTTP simulation you’ll want the built-in HTTP service instead, this pattern is for custom, HTTP-ish protocols.
Binary Messages
Section titled “Binary Messages”Binary C2 protocols usually frame messages with a length prefix. string.pack & string.unpack handle the byte-level work:
-- Echoes 2-byte big-endian length-prefixed messages back to the client.function handle(conn) while true do local head = conn:read(2) if not head then break end local len = string.unpack(">H", head)
local body = conn:read(len) if not body then break end capture:write("message", body)
conn:write(string.pack(">H", #body) .. body) endendRun it with gonetsim run messages.lua@:9000 and probe it:
printf '\x00\x05hello' | netcat localhost 9000 # replies with \x00\x05hellostring.pack/string.unpack support signed & unsigned integers from 1 to 8 bytes, floats, zero-terminated and length-prefixed strings. See the Lua API for the full format list.
More Examples
Section titled “More Examples”The GoNetSim repository ships a full set of example handlers, including a complete IRC server & a stateful FTP server with login tracking.
Browse the examples