Go黑帽子(第二章)

2.0 第二章 TCP、扫描器和代理

2.1 TCP握手机制

这部分内容就不详细说了,百度讲的会更详细,如果看不懂请移步到哔哩哔哩大学。

2.2 通过端口转发绕过防火墙

说白了就是防火墙不允许访问的网站,通过访问允许访问的网站将流量进行代理到目标网站上。

2.3 编写一个TCP扫描器
2.3.1 测试端口可用性

单个端口扫描器

package main

import (
	"fmt"
	"net"
)

func main() {
   
   
	_, err := net.Dial("tcp", "scanme.nmap.org:80")
	if err == nil {
   
   
		fmt.Println("Connection successful")
	}
}
2.3.2 执行非并发扫描

说白了就是循环检测,看看能不能脸上,我觉得这个效率极低。

package main

import (
	"fmt"
	"net"
)

func main() {
   
   
	for i := 1; i <= 1024; i++ {
   
   
		address := fmt.Sprintf("scanme.nmap.org:%d", i)
		conn, err := net.Dial("tcp", address)
		if err == nil {
   
   
			fmt.Println("Connection successful")
		} else {
   
   
			//端口已关闭或已过滤
			continue
		}
		conn.Close()
		fmt.Printf("%d opne\n", i)
	}
}
2.3.3 执行并发扫描

这个时候用到go语言的独有的goroutine

package main

import (
	"fmt"
	"net"
)

func main() {
   
   
	for i := 1; i <= 1024; i++ {
   
   
		go func(j int) {
   
   
			address := fmt.Sprintf("scanme.nmap.org:%d", j)
			conn, err := net.Dial("tcp", address)
			if err != nil {
   
   
				return
			}
			conn.Close()
			fmt.Printf("%d open\n", j)
		}(i)
	}
}
//这里给大家对这个程序进行解释
在这个代码片段中,i 被传递给了匿名函数作为参数 j。这是为了避免在并发的情况下出现竞态条件。
在Go语言中,使用 go 关键字启动一个 goroutine 时,它会在一个新的 goroutine 中执行指定的函数。由于 goroutines 是并发执行的,它们可能会在同一时间访问和修改相同的变量。在这个例子中,i 是在 for 循环中定义的,如果直接在匿名函数中使用 i,会导致竞态条件,因为 i 的值在 goroutines 中可能会被不同的 goroutines 修改。
通过将 i 作为参数传递给匿名函数,确保每个 goroutine 都使用了 for 循环中当前迭代的 i 值的副本,而不是共享相同的 i 变量。这有助于避免竞态条件和确保正确的结果。
所以,i 在后面是为了确保在 go 关键字创建的 goroutine 中使用当前迭代的 i 的正确副本。
             

竞态条件(Race Condition)是指在多线程或多进程的程序中,由于执行顺序不确定性导致的程序行为异常的情况。竞态条件发生在多个线程或进程同时访问共享资源,并且其中至少一个是写操作时。
竞态条件的发生通常需要满足以下几个条件:
并发访问: 两个或多个线程(或进程)同时访问相同的共享资源。
至少一个写操作: 其中至少有一个线程执行写操作,修改共享资源的状态。
无同步机制: 缺乏适当的同步机制,导致多个线程之间的执行顺序不确定。

以上代码在for循环结束后就会直接退出程序,说明这样做是有问题的,因为for循环完成的时间可能会小于完成连接所需要的时间 ,因此我们需要使用sync包中的waitgroup,这是一种控制并发的线程的安全的方法。

修改后的代码如下:

package main

import (
	"fmt"
	"net"
	"sync"
)

func main() {
   
   
	var wg sync.WaitGroup
	for i := 1; i <= 1024; i++ {
   
   
		wg.Add(1)//递增计数器
		go func(j int) {
   
   
			defer wg.Done()
			address := fmt.Sprintf("scanme.nmap.org:%d", j)
			conn, err := net.Dial("tcp", address)
			if err != nil {
   
   
				return
			}
			conn.Close()
			fmt.Printf("%d open\n", j)
		}(i)
	}
	wg.Wait()
}

defer 是 Go 语言中的一个关键字,用于延迟(defer)函数或方法的执行,通常用于确保在函数执行结束时(无论是正常返回还是发生异常)执行一些清理操作。(个人理解就是,只有当函数执行结束之前执行的语句,也就是最后一个执行的语句)

这里可以简单了解一下deferWaitGroup的用法,这里就不做详细解释。

以上代码还存在蛮多的问题比如:并发量太大,可能导致网络或系统限制、网络超时之后的操作等并没有给出。

因此代码可以进行进一步的优化:

使用goroutine池管理真正进行的并发工作

package main

import (
	"fmt"
	"sync"
)

func worker(ports chan int, wg *sync.WaitGroup) {
   
   
	for p := range ports {
   
   
		fmt.Println(p)
		wg.Done()
	}
}

func main() {
   
   
	ports := make(chan int, 100)
	var wg sync.WaitGroup
    //cap测量通道的容量大小
	for i := 0; i < cap(ports); i++ {
   
   
		go worker(ports, &wg)
	}
	for i := 1; i <= 1024; i++ {
   
   
		wg.Add(1)
		ports <- i
	}
	wg.</
### 关于《Python黑帽子第二版》中的Netcat实现 在网络安全工具中,`netcat`是一个非常重要的网络实用程序。通过使用Python来重新构建这个功能强大的工具,《Python黑帽子第二版》提供了详细的指导以及源码实例。 书中提到创建一个简单的TCP客户端和服务端的例子[^1]: #### 创建TCP服务器 ```python import socket def tcp_server(host='localhost', port=9999): """启动一个基本的TCP服务器""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, port)) s.listen(5) print(f'[*] Listening on {host}:{port}') while True: client_socket, addr = s.accept() print(f'[+] Accepted connection from {addr[0]}:{addr[1]}') request = client_socket.recv(1024) print(f"[++] Received: {request.decode('utf-8')}") client_socket.send(b"ACK!") client_socket.close() if __name__ == '__main__': tcp_server() ``` 此脚本会监听指定地址上的连接请求,并处理来自客户端的消息。当接收到数据包时,它将打印消息并回复确认信息给发送者。 #### 构建TCP客户端 为了与上述服务端通信,可以编写如下所示的一个简易客户端: ```python import socket def tcp_client(target_host="127.0.0.1", target_port=9999): """向目标主机发起TCP连接""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client: client.connect((target_host, target_port)) client.send(b"GET / HTTP/1.1\r\nHost: google.com\r\n\r\n") response = client.recv(4096) print(response.decode()) if __name__ == "__main__": tcp_client() ``` 这段代码尝试连接到特定的目标机器和端口上,模拟HTTP GET请求的行为并向对方发送一些数据;之后读取响应内容显示出来。 这两个例子展示了如何利用Python快速搭建起基础版本的Netcat工具。当然,在实际应用过程中还需要考虑更多因素如错误处理机制、多线程支持等特性以增强其健壮性和功能性。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

newbie_______

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值