Skip to content

Commit

Permalink
Adding Linux namespace support to ifconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
precurse committed Jan 5, 2024
1 parent b20c537 commit 2c5d8ef
Show file tree
Hide file tree
Showing 12 changed files with 833 additions and 11 deletions.
5 changes: 3 additions & 2 deletions implant/go-mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ require (
github.com/stretchr/testify v1.7.0
github.com/tetratelabs/wazero v1.2.0
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43
github.com/vishvananda/netns v0.0.4
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e
golang.org/x/crypto v0.13.0
golang.org/x/net v0.15.0
golang.org/x/sys v0.14.0
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb
google.golang.org/protobuf v1.31.0
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259
)

require (
Expand All @@ -37,7 +40,6 @@ require (
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.13.0 // indirect
Expand All @@ -48,5 +50,4 @@ require (
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 // indirect
gopkg.in/jcmturner/rpc.v1 v1.1.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 // indirect
)
2 changes: 2 additions & 0 deletions implant/go-sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ github.com/tetratelabs/wazero v1.2.0 h1:I/8LMf4YkCZ3r2XaL9whhA0VMyAvF6QE+O7rco0D
github.com/tetratelabs/wazero v1.2.0/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ=
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43 h1:+sN63SJGqchSsVyNoeW4GyA0Y+g0LvKOHcaeqs1Rf6M=
github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e h1:6SWomM8ezwUwnN3lqKxE4r7bYVwpY9514DQkwBV9IPI=
github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e/go.mod h1:r1bHcNa22x8rrg/Kj/cDF5bX6UtZrHiQgRFvj3Mnpl8=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
Expand Down
118 changes: 110 additions & 8 deletions implant/sliver/handlers/rpc-handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ package handlers
*/

import (
"io/ioutil"
"net"
"os"
"path/filepath"
"runtime"
"syscall"

// {{if .Config.Debug}}
"log"
Expand All @@ -35,6 +40,8 @@ import (
"github.com/bishopfox/sliver/protobuf/sliverpb"

"google.golang.org/protobuf/proto"

"github.com/vishvananda/netns"
)

// ------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -103,19 +110,17 @@ func ifconfigHandler(_ []byte, resp RPCResponse) {
resp(data, err)
}

func ifconfig() *sliverpb.Ifconfig {
netInterfaces, err := net.Interfaces()
if err != nil {
return nil
func ifconfigParseInterfaces(netInterfaces []net.Interface, interfaces *sliverpb.Ifconfig, namespaceId ...string) {
// Append namespace ID if passed in
var appendNsId = ""
if len(namespaceId) > 0 {
appendNsId = namespaceId[0]
}

interfaces := &sliverpb.Ifconfig{
NetInterfaces: []*sliverpb.NetInterface{},
}
for _, iface := range netInterfaces {
netIface := &sliverpb.NetInterface{
Index: int32(iface.Index),
Name: iface.Name,
Name: iface.Name + appendNsId,
}
if iface.HardwareAddr != nil {
netIface.MAC = iface.HardwareAddr.String()
Expand All @@ -128,9 +133,106 @@ func ifconfig() *sliverpb.Ifconfig {
}
interfaces.NetInterfaces = append(interfaces.NetInterfaces, netIface)
}
}

func ifconfig() *sliverpb.Ifconfig {
netInterfaces, err := net.Interfaces()
if err != nil {
return nil
}

interfaces := &sliverpb.Ifconfig{
NetInterfaces: []*sliverpb.NetInterface{},
}

ifconfigParseInterfaces(netInterfaces, interfaces)

// Linux namespace handling
if runtime.GOOS == "linux" {
nsLinuxIfconfig(interfaces)
}

return interfaces
}

func nsLinuxIfconfig(interfaces *sliverpb.Ifconfig) {
namespacesFound := make(map[uint64]string)

procDir := "/proc"
procContents, err := ioutil.ReadDir(procDir)

if err != nil {
//{{if .Config.Debug}}
log.Printf("error reading /proc: %v", err)
//{{end}}
return
}

for _, entry := range procContents {
if !entry.IsDir() {
continue
}
match, _ := filepath.Match("[1-9]*", entry.Name())
if match {
// Check if /proc/PID/net/ns exists
checkPath := filepath.Join(procDir, entry.Name(), "/ns/net")

if _, err := os.Stat(checkPath); !os.IsNotExist(err) {
// path for /proc/PID/ns/net exists

Check failure on line 181 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / Linux & Windows Test

undefined: syscall.Stat_t

Check failure on line 181 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / Linux & Windows Test

undefined: syscall.Stat_t

Check failure on line 181 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / MacOS Test

undefined: syscall.Stat_t

Check failure on line 181 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / MacOS Test

undefined: syscall.Stat_t
// inode used to track unique namespaces
var inode uint64

fileinfo, err := os.Stat(checkPath)

if err != nil {
//{{if .Config.Debug}}
log.Printf("error : %v", err)
//{{end}}
continue
}
inode = fileinfo.Sys().(*syscall.Stat_t).Ino

Check failure on line 193 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / Linux & Windows Test

undefined: syscall.Stat_t

Check failure on line 193 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / Linux & Windows Test

undefined: syscall.Stat_t

Check failure on line 193 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / MacOS Test

undefined: syscall.Stat_t

Check failure on line 193 in implant/sliver/handlers/rpc-handlers.go

View workflow job for this annotation

GitHub Actions / MacOS Test

undefined: syscall.Stat_t
// Track unique namespaces
namespacesFound[inode] = checkPath
}

}
}

// Lock the OS Thread so we don't accidentally switch namespaces
runtime.LockOSThread()
defer runtime.UnlockOSThread()

// Save the current network namespace
origns, _ := netns.Get()
defer origns.Close()

// We only need to use the path value
for _, v := range namespacesFound {
nsPath, err := netns.GetFromPath(v)
if err != nil {
continue
}
// Ignore origin namespace
if nsPath.UniqueId() == origns.UniqueId() {
continue
}
err = netns.Set(nsPath)

if err != nil {
// Failed to enter namespace
continue
}

ifaces, _ := net.Interfaces()
// {{if .Config.Debug}}
log.Printf("Interfaces: %v\n", ifaces)
// {{end}}
ifconfigParseInterfaces(ifaces, interfaces, nsPath.UniqueId())
}
// Switch back to the original namespace
netns.Set(origns)
}

func netstatHandler(data []byte, resp RPCResponse) {
netstatReq := &sliverpb.NetstatReq{}
err := proto.Unmarshal(data, netstatReq)
Expand Down
2 changes: 2 additions & 0 deletions implant/vendor/github.com/vishvananda/netns/.golangci.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

192 changes: 192 additions & 0 deletions implant/vendor/github.com/vishvananda/netns/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2c5d8ef

Please sign in to comment.