A 51: Basic Port Scanning with Go (40 pts)

What You Need

A Debian 11 Linux machine.

Purpose

Learn very basic Go coding techniques.

Installing Go

On your local computer, in a Web browser, go to

https://golang.org/dl/

Find the latest Linux 64-bit version for the x86-64 architecture, as shown below. Note the file name and the SHA265 checksum, outlined in green in the image below.

On your Linux server, in a Terminal window, execute these commands, adjusting the filename to match the filename you found in the previous step:

wget https://go.dev/dl/go1.18.3.linux-amd64.tar.gz
sha256sum go1.*
Make sure the SHA256 value matches the value on the website, as shown below.

On your Linux server, in a Terminal window, execute these commands, adjusting the filename to match the filename you found in the previous step:

tar xvf go1.*
sudo chown -R root:root ./go
sudo mv go /usr/local
echo export GOPATH=$HOME/work >> ~/.profile
echo export PATH=\$PATH:/usr/local/go/bin:\$GOPATH/bin >> ~/.profile
source ~/.profile
go env -w GO111MODULE=auto
go
Go runs, showing a help message, as shown below.

First Program: Hello World

In a Terminal window, execute these commands to create the proper folder structure and the source code to print "Hello, World!".
mkdir work
mkdir -p work/src/my_project/hello
nano  work/src/my_project/hello/hello.go
In nano, enter this code, as shown below.
package main

import "fmt"

func main() {
    fmt.Printf("Hello, World!\n")
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/hello
hello
The program runs, as shown below.

Port Scanner

This program scans all 65,536 ports on your local server.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/portscan1
nano  work/src/my_project/portscan1/portscan1.go
In nano, enter this code, as shown below.
package main

import (
   "net"
   "fmt"
   "strconv"
)

func main() {

   for i := 1; i < 65535; i++ {
      port := strconv.FormatInt(int64(i), 10)
      conn, err := net.Dial("tcp", "127.0.0.1:" + port)
      if err == nil {
         fmt.Println("Port",i, "open")
         conn.Close()
      }
   }
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/portscan1
portscan1
The program runs, as shown below.

Banner Grabber

This program reads the banners from ports scanned, saves them in a local buffer, and prints them out.

On your Linux server, in a Terminal window, execute these commands:

mkdir -p work/src/my_project/portscan2
nano  work/src/my_project/portscan2/portscan2.go
In nano, enter this code, as shown below.
package main

import (
   "net"
   "fmt"
   "strconv"
)

func main() {

   for i := 20; i < 25; i++ {
      port := strconv.FormatInt(int64(i), 10)
      conn, err := net.Dial("tcp", "target1.bowneconsulting.com:" + port)
      fmt.Println("Scanning Port",i)
      if err == nil {
         fmt.Println("Port",i, "open")
       	 Buffer := make([]byte, 1024)
		 numBytesRead, err := conn.Read(Buffer)
		 if err == nil {
            fmt.Printf("Banner: %s\n", Buffer[0:numBytesRead])
		 }
         conn.Close()
      }
   }
}

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/portscan2
portscan2
The program runs, as shown below.

Scanning More Ports

On your Linux server, in a Terminal window, execute these commands:
mkdir -p work/src/my_project/portscan3
nano  work/src/my_project/portscan3/portscan3.go
In nano, enter this code, as shown below.
package main

import (
   "net"
   "fmt"
   "strconv"
)

func main() {

   for i := 20; i < 30; i++ {
      port := strconv.FormatInt(int64(i), 10)
      conn, err := net.Dial("tcp", "target1.bowneconsulting.com:" + port)
      fmt.Println("Scanning Port",i)
      if err == nil {
         fmt.Println("Port",i, "open")
       	 Buffer := make([]byte, 1024)
		 numBytesRead, err := conn.Read(Buffer)
		 if err == nil {
            fmt.Printf("Banner: %s\n", Buffer[0:numBytesRead])
		 }
         conn.Close()
      }
   }
}
This is the same as the banner grabber, but it goes from port 20 to 29.

Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/portscan3
portscan3
The program runs to port 24, but freezes there, as shown below.

Using Timeout

This problem is caused by a port that replies to a SYN but has no banner, such as SMTP on port 25. To make the scanner move along, we need to implment a timeout.

To do that, on your Linux server, in a Terminal window, execute this command:

mkdir -p work/src/my_project/portscan4
nano  work/src/my_project/portscan4/portscan4.go
In nano, enter this code, as shown below.
package main

import (
   "net"
   "fmt"
   "strconv"
   "time"
)

func main() {

   for i := 20; i < 30; i++ {
      port := strconv.FormatInt(int64(i), 10)
      conn, err := net.DialTimeout("tcp", "target1.bowneconsulting.com:" + port, 1*time.Second)
      fmt.Println("Scanning Port",i)
      if err == nil {
         fmt.Println("Port",i, "open")
       	 Buffer := make([]byte, 1024)
		 numBytesRead, err := conn.Read(Buffer)
		 if err == nil {
            fmt.Printf("Banner: %s\n", Buffer[0:numBytesRead])
		 }
         conn.Close()
      } else {
        fmt.Println("Error: ",err)
      }
    }
}
Save the file with Ctrl+X, Y, Enter.

Execute these commands to compile the program and run it:

go install my_project/portscan4
portscan4

Flag A 51.1: Error Message (10 pts)

Now the scanner goes through all the ports, showing banners and error messages. The flag is the error message for port 25, covered by a green rectangle in the image below.


A 51.2: Challenge: Find a Service (5 pts)

Find a service running on the target1.bowneconsulting.com server on a port between 21000 and 21030. Its banner reveals a flag, as shown below.


A 51.3: Challenge: Port Knocking 1 (10 pts)

Connect to the target1.bowneconsulting.com server on port 22010. Its banner reveals another port to connect to. The next service reveals a flag, as shown below.

Hint: Substring: How to Split a String

A 51.4: Challenge: Port Knocking 2 (15 pts)

Connect to the target1.bowneconsulting.com server on port 22020. Its banner reveals another port to connect to. The next service reveals a flag, as shown below.

Hint: 3 ways to split a string into a slice

Sources

How To Install Go on Debian 9
Port Scanner
Package net

Posted: 10-31-19

Updated for Go 16.6 7-16-2021
Updated 6-22-22