This is a basic listener that works similarly to nc -l It's selling point is that you can run a command when the window is resized. An example is given for putting an appropraet stty command on the clipboard for a reverse shellmaster
commit
329a709d49
2 changed files with 225 additions and 0 deletions
@ -0,0 +1,9 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
# |
||||||
|
# This gets the dimentions of the terminal and puts the approprate stty command on the clipboard for reverse shells |
||||||
|
|
||||||
|
|
||||||
|
columns=$(stty -a < /dev/stdin | grep -oE 'columns [0-9]+' | cut -d' ' -f2) |
||||||
|
rows=$(stty -a < /dev/stdin | grep -oE 'rows [0-9]+' | cut -d' ' -f2) |
||||||
|
notify-send "Terminal dimensions" "Rows: $rows\nColumns: $columns\nstty command on clipboard" |
||||||
|
echo "stty rows $rows cols $columns" | xclip -i -selection clipboard |
@ -0,0 +1,216 @@ |
|||||||
|
// go-nc project main.go
|
||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"flag" |
||||||
|
"fmt" |
||||||
|
"io" |
||||||
|
"log" |
||||||
|
"net" |
||||||
|
"os" |
||||||
|
"os/exec" |
||||||
|
"os/signal" |
||||||
|
"strconv" |
||||||
|
"syscall" |
||||||
|
) |
||||||
|
|
||||||
|
// Handles TC connection and perform synchorinization:
|
||||||
|
// TCP -> Stdout and Stdin -> TCP
|
||||||
|
func tcp_con_handle(con net.Conn) { |
||||||
|
chan_to_stdout := stream_copy(con, os.Stdout) |
||||||
|
chan_to_remote := stream_copy(os.Stdin, con) |
||||||
|
select { |
||||||
|
case <-chan_to_stdout: |
||||||
|
log.Println("Remote connection is closed") |
||||||
|
case <-chan_to_remote: |
||||||
|
log.Println("Local program is terminated") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Performs copy operation between streams: os and tcp streams
|
||||||
|
func stream_copy(src io.Reader, dst io.Writer) <-chan int { |
||||||
|
buf := make([]byte, 1024) |
||||||
|
sync_channel := make(chan int) |
||||||
|
go func() { |
||||||
|
defer func() { |
||||||
|
if con, ok := dst.(net.Conn); ok { |
||||||
|
con.Close() |
||||||
|
log.Printf("Connection from %v is closed\n", con.RemoteAddr()) |
||||||
|
} |
||||||
|
sync_channel <- 0 // Notify that processing is finished
|
||||||
|
}() |
||||||
|
for { |
||||||
|
var nBytes int |
||||||
|
var err error |
||||||
|
nBytes, err = src.Read(buf) |
||||||
|
if err != nil { |
||||||
|
if err != io.EOF { |
||||||
|
log.Printf("Read error: %s\n", err) |
||||||
|
} |
||||||
|
break |
||||||
|
} |
||||||
|
_, err = dst.Write(buf[0:nBytes]) |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("Write error: %s\n", err) |
||||||
|
} |
||||||
|
} |
||||||
|
}() |
||||||
|
return sync_channel |
||||||
|
} |
||||||
|
|
||||||
|
//Accept data from UPD connection and copy it to the stream
|
||||||
|
func accept_from_udp_to_stream(src net.Conn, dst io.Writer) <-chan net.Addr { |
||||||
|
buf := make([]byte, 1024) |
||||||
|
sync_channel := make(chan net.Addr) |
||||||
|
con, ok := src.(*net.UDPConn) |
||||||
|
if !ok { |
||||||
|
log.Printf("Input must be UDP connection") |
||||||
|
return sync_channel |
||||||
|
} |
||||||
|
go func() { |
||||||
|
var remoteAddr net.Addr |
||||||
|
for { |
||||||
|
var nBytes int |
||||||
|
var err error |
||||||
|
var addr net.Addr |
||||||
|
nBytes, addr, err = con.ReadFromUDP(buf) |
||||||
|
if err != nil { |
||||||
|
if err != io.EOF { |
||||||
|
log.Printf("Read error: %s\n", err) |
||||||
|
} |
||||||
|
break |
||||||
|
} |
||||||
|
if remoteAddr == nil && remoteAddr != addr { |
||||||
|
remoteAddr = addr |
||||||
|
sync_channel <- remoteAddr |
||||||
|
} |
||||||
|
_, err = dst.Write(buf[0:nBytes]) |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("Write error: %s\n", err) |
||||||
|
} |
||||||
|
} |
||||||
|
}() |
||||||
|
log.Println("Exit write_from_udp_to_stream") |
||||||
|
return sync_channel |
||||||
|
} |
||||||
|
|
||||||
|
// Put input date from the stream to UDP connection
|
||||||
|
func put_from_stream_to_udp(src io.Reader, dst net.Conn, remoteAddr net.Addr) <-chan net.Addr { |
||||||
|
buf := make([]byte, 1024) |
||||||
|
sync_channel := make(chan net.Addr) |
||||||
|
go func() { |
||||||
|
for { |
||||||
|
var nBytes int |
||||||
|
var err error |
||||||
|
nBytes, err = src.Read(buf) |
||||||
|
if err != nil { |
||||||
|
if err != io.EOF { |
||||||
|
log.Printf("Read error: %s\n", err) |
||||||
|
} |
||||||
|
break |
||||||
|
} |
||||||
|
log.Println("Write to the remote address:", remoteAddr) |
||||||
|
if con, ok := dst.(*net.UDPConn); ok && remoteAddr != nil { |
||||||
|
_, err = con.WriteTo(buf[0:nBytes], remoteAddr) |
||||||
|
} |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("Write error: %s\n", err) |
||||||
|
} |
||||||
|
} |
||||||
|
}() |
||||||
|
return sync_channel |
||||||
|
} |
||||||
|
|
||||||
|
// Handle UDP connection
|
||||||
|
func udp_con_handle(con net.Conn) { |
||||||
|
in_channel := accept_from_udp_to_stream(con, os.Stdout) |
||||||
|
log.Println("Waiting for remote connection") |
||||||
|
remoteAddr := <-in_channel |
||||||
|
log.Println("Connected from", remoteAddr) |
||||||
|
out_channel := put_from_stream_to_udp(os.Stdin, con, remoteAddr) |
||||||
|
select { |
||||||
|
case <-in_channel: |
||||||
|
log.Println("Remote connection is closed") |
||||||
|
case <-out_channel: |
||||||
|
log.Println("Local program is terminated") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func main() { |
||||||
|
var destinationPort string |
||||||
|
var resizeCommand string |
||||||
|
var isUdp bool |
||||||
|
|
||||||
|
sigs := make(chan os.Signal, 1) |
||||||
|
|
||||||
|
flag.BoolVar(&isUdp, "u", false, "Use UDP instead of the default option of TCP.") |
||||||
|
flag.StringVar(&resizeCommand, "r", "", "Use UDP instead of the default option of TCP.") |
||||||
|
flag.Parse() |
||||||
|
if flag.NFlag() == 0 && flag.NArg() == 0 { |
||||||
|
fmt.Println("go-nc [-u] [-r command] [port]") |
||||||
|
flag.Usage() |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
|
||||||
|
if isUdp { |
||||||
|
log.Println("Protocol:", "udp") |
||||||
|
} else { |
||||||
|
log.Println("Protocol:", "tcp") |
||||||
|
} |
||||||
|
|
||||||
|
if flag.NArg() < 1 { |
||||||
|
fmt.Println("when you use -l option [port] is mandatory argument") |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
if _, err := strconv.Atoi(flag.Arg(0)); err != nil { |
||||||
|
log.Println("Destination port shall be not empty and have integer value") |
||||||
|
os.Exit(1) |
||||||
|
} |
||||||
|
destinationPort = fmt.Sprintf(":%v", flag.Arg(0)) |
||||||
|
|
||||||
|
log.Println("Port:", destinationPort) |
||||||
|
|
||||||
|
if len(resizeCommand) != 0 { |
||||||
|
log.Println("Resize command:", resizeCommand) |
||||||
|
signal.Notify(sigs, syscall.SIGWINCH) |
||||||
|
go func() { |
||||||
|
for true{ |
||||||
|
<-sigs |
||||||
|
log.Println("Window Resized") |
||||||
|
cmd := exec.Command(resizeCommand) |
||||||
|
cmd.Stdin = os.Stdin |
||||||
|
_, err := cmd.Output() |
||||||
|
|
||||||
|
log.Printf("err: %#v\n", err) |
||||||
|
} |
||||||
|
}() |
||||||
|
} |
||||||
|
|
||||||
|
if !isUdp { |
||||||
|
|
||||||
|
listener, err := net.Listen("tcp", destinationPort) |
||||||
|
if err != nil { |
||||||
|
log.Fatalln(err) |
||||||
|
} |
||||||
|
log.Println("Listening on", destinationPort) |
||||||
|
con, err := listener.Accept() |
||||||
|
if err != nil { |
||||||
|
log.Fatalln(err) |
||||||
|
} |
||||||
|
log.Println("Connect from", con.RemoteAddr()) |
||||||
|
tcp_con_handle(con) |
||||||
|
|
||||||
|
} else { |
||||||
|
addr, err := net.ResolveUDPAddr("udp", destinationPort) |
||||||
|
if err != nil { |
||||||
|
log.Fatalln(err) |
||||||
|
} |
||||||
|
con, err := net.ListenUDP("udp", addr) |
||||||
|
if err != nil { |
||||||
|
log.Fatalln(err) |
||||||
|
} |
||||||
|
log.Println("Has been resolved UDP address:", addr) |
||||||
|
log.Println("Listening on", destinationPort) |
||||||
|
udp_con_handle(con) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue