diff --git a/README.md b/README.md
index 88f52ab..4dbd9aa 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,10 @@ This is a **'free time'** project, for study propose only.
[![https://travis-ci.com/github/pyperanger/gorootcheck](https://api.travis-ci.com/pyperanger/gorootcheck.svg?branch=master&status=passed)](https://travis-ci.com/github/pyperanger/gorootcheck)
Standalone rootcheck by **OSSEC** wrtitten in Go
-2020-04-05 | v0.5.0 - Some false positives(**rootkit_files.txt**) and bugs
+#### 2020-04-05 | v0.6.0
+- Some false positives(**rootkit_files.txt**) and bugs persist
+- Improve performance in general
+
### Install
```
diff --git a/internal/gorootcheck/args.go b/internal/gorootcheck/args.go
index b53bcbb..89b110f 100644
--- a/internal/gorootcheck/args.go
+++ b/internal/gorootcheck/args.go
@@ -2,6 +2,7 @@ package gorootcheck
import (
"flag"
+ "os"
"fmt"
)
@@ -10,7 +11,7 @@ var (
version = flag.Bool("version", false, "Show version")
debug = flag.Bool("v", false, "Debug mode")
help = flag.Bool("h", false, "This massage")
- VERSION = "0.5.0"
+ VERSION = "0.6.0"
)
func argsUsage() {
@@ -21,6 +22,10 @@ v` + VERSION + ` - github.com/pyperanger/gorootcheck
func Args() bool {
argsUsage()
+ if os.Getuid() != 0 {
+ fmt.Println("- Run gorootcheck as root")
+ bye()
+ }
flag.Parse()
if *help {
flag.Usage()
diff --git a/internal/gorootcheck/hiddenport.go b/internal/gorootcheck/hiddenport.go
index a023355..2b88859 100644
--- a/internal/gorootcheck/hiddenport.go
+++ b/internal/gorootcheck/hiddenport.go
@@ -5,7 +5,7 @@ to check every tcp and udp port on the system. If we
can’t bind to the port (it’s being used), but netstat
does not show it, we probably have a rootkit installed
-Check TCP/UDP ports
+Check TCP/UDP ports
[X] TCP
[ ] UDP
@@ -14,20 +14,20 @@ Check TCP/UDP ports
package gorootcheck
import (
- "syscall"
- "os/exec"
- "strings"
"fmt"
+ "net"
+ "os/exec"
"regexp"
"strconv"
- "net"
+ "strings"
+ "syscall"
)
-// check port in ss output
+// Return TRUE is NOT FOUND port in output
func inssstd(std string, port int) bool {
ss := strings.Split(std, "\n")
- spgex, _ := regexp.Compile(`(?m)(\S+$)`)
- for _, p := range ss {
+ spgex, _ := regexp.Compile(`(?m)(\d+$)`)
+ for _, p := range ss[1:len(ss)-1] {
ssport, err := strconv.Atoi(spgex.FindString(p))
if err != nil {
return false
@@ -39,10 +39,16 @@ func inssstd(std string, port int) bool {
return true
}
+func closefd(fd int) {
+ if err := syscall.Close(fd); err != nil {
+ return
+ }
+}
+
// Execute `ss` command
-// protocol -> t[cp] or u[dp]
+// protocol -> t[cp] or u[dp]
func inss(protocol string, port int) bool {
- ss := exec.Command("ss", "-l", protocol, "n")
+ ss := exec.Command("ss", "-l", protocol, "-n")
awk := exec.Command("awk", "{print $4}")
pipe, err := ss.StdoutPipe()
if err != nil {
@@ -57,39 +63,57 @@ func inss(protocol string, port int) bool {
if err != nil {
return false
}
+
if inssstd(string(std), port) {
return true
}
return false
}
-// Check if port is already in use
-func ssport(port int) bool {
+// Check if TCP port is already in use
+func tcpssport(port int) bool {
fd, err := syscall.Socket(syscall.AF_INET, syscall.O_NONBLOCK|syscall.SOCK_STREAM, 0)
if err != nil {
- return false
+ return false
}
defer syscall.Close(fd)
if err = syscall.SetNonblock(fd, true); err != nil {
- return false
+ return false
}
addr := syscall.SockaddrInet4{Port: port}
copy(addr.Addr[:], net.ParseIP("0.0.0.0").To4())
if err = syscall.Bind(fd, &addr); err != nil {
- // TCP
if inss("-t", port) {
+ closefd(fd)
return true
}
}
+ closefd(fd)
+ return false
+}
+
+// Check if UDP port is already in use
+func udpssport(port int) bool {
+ pc, err := net.ListenPacket("udp", ":" + strconv.Itoa(port))
+ if err != nil {
+ if inss("-u", port) {
+ return true
+ }
+ return false // invalid memory address or nil pointer dereference
+ }
+ defer pc.Close()
return false
}
func hidden_port() {
fmt.Println("#6 - Searching for hidden ports [ TCP/UDP - IPV4/IPV6 ]")
- for i := 0; i <= 65535 ; i++ {
- if ssport(i) {
- fmt.Println("\t- Hidden Port: ", i)
+ for i := 0; i <= 65535; i++ {
+ if tcpssport(i) {
+ fmt.Println("\t- Hidden TCP Port: ", i)
+ }
+ if udpssport(i) {
+ fmt.Println("\t- Hidden UDP Port: ", i)
}
}
}
\ No newline at end of file
diff --git a/internal/gorootcheck/promisc.go b/internal/gorootcheck/promisc.go
index 21e9d77..e25e7b5 100644
--- a/internal/gorootcheck/promisc.go
+++ b/internal/gorootcheck/promisc.go
@@ -9,7 +9,7 @@ we probably have a rootkit installed.
file:
/sys/class/net//flags
-ref:
+ref:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
https://github.com/torvalds/linux/blob/master/include/uapi/linux/if.h
*/
@@ -17,10 +17,10 @@ package gorootcheck
import (
"fmt"
- "regexp"
- "strconv"
"io/ioutil"
"os/exec"
+ "regexp"
+ "strconv"
)
// return all interfaces name
@@ -33,18 +33,18 @@ func listinterfaces() ([]string, error) {
for _, i := range ifacedirs {
iface = append(iface, i.Name())
}
- return iface, nil
+ return iface, nil
}
// return TRUE if given interface is in promisc mode
// promisc mode bitmask 100
func scaninterface(iface string) bool {
- flags, err := ioutil.ReadFile("/sys/class/net/"+iface+"/flags")
+ flags, err := ioutil.ReadFile("/sys/class/net/" + iface + "/flags")
if err != nil {
fmt.Println(" - Error reading flags from interface: ", iface)
return false
}
- bytemark := flags[2:len(flags)-1]
+ bytemark := flags[2 : len(flags)-1]
if len(bytemark) < 3 {
return false
}
@@ -52,13 +52,13 @@ func scaninterface(iface string) bool {
if err != nil {
return false
}
- if bitmark / 100 == 11 || bitmark / 100 == 1 {
+ if bitmark/100 == 11 || bitmark/100 == 1 {
return true
}
return false
}
-// return TRUE if interface is promisc mode
+// return TRUE if interface is promisc mode
// in ifconfig command
func ifconfigface(iface string) bool {
cmd := exec.Command("ifconfig", iface)
@@ -84,4 +84,4 @@ func promisc() {
fmt.Println("\t- Interface in hidden promisc mode: ", i)
}
}
-}
\ No newline at end of file
+}