Initial Commit - basic functionality incorperated
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 shell
This commit is contained in:
commit
329a709d49
2 changed files with 225 additions and 0 deletions
9
example-commands/stty-resize-copy
Normal file
9
example-commands/stty-resize-copy
Normal file
|
@ -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
|
216
main.go
Normal file
216
main.go
Normal file
|
@ -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…
Add table
Add a link
Reference in a new issue