黑帽Python TCP客户端

2024-04-23 18:59:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在阅读Black Hat Python书籍,虽然它是在2015年编写的,但其中一些代码似乎有点过时。例如,print语句不使用括号。但是,我似乎无法让下面的脚本运行,并且不断出现错误

    # TCP Client Tool

import socket

target_host = "www.google.com"
target_port = 80

# creates a socket object. AF_INET parameter specifies IPv4 addr/host. SOCK_STREAM is TCP specific, not UDP.
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# connect the client
client.connect((target_host, target_port))

# sending some data
client.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n\")

# receive some data
response = client.recv(4096)

print(response)

我得到的错误只是读取,文件“”,第15行 client.send(“GET/HTTP/1.1\r\nHost:google.com\r\n\r\n\”) ^


Tags: comclienthosttargetstreamportconnect错误
2条回答

通过在前面放置\来转义",这意味着python不知道字符串在这里结束。您可以注意到,在您的帖子中,该行后面的所有代码都被着色,就像它是一个字符串一样

client.send还需要一个byte-like object,而不是一个字符串。您可以通过在字符串前放置b来指定:

client.send(b"GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")

在那之后,脚本工作得很好

我认为@Anonyme2000完全回答了这个问题,解决这个问题所需的所有细节都在那里。然而,由于这是一个从书中学习的练习,其他人可能会来这里,并且@Anonyme2000的答案中的细节有点简短,我将进一步展开

Python,像许多其他语言一样,有所谓的Escape Sequences,简而言之,将\放在某个东西前面意味着——后面的任何东西都有特殊的含义。两个例子:

示例1:换行符(新行)

print("Something \nThis is a new line")

这将导致python将n解释为字母“n”,而不是一个表示“这里应该有一个新行”的特殊字符,这一切都要归功于\n位于字母n前面\r也是一条“新线”,但在过去,它相当于移动carriage printer head to the start of the line,而不仅仅是移动一条线

示例2:引号在字符串中转义

print("I want to print this quote: \" in my string")

在这个例子中,因为我们使用引号字符”来启动和结束我们的字符串,在中间添加它会破坏字符串(希望这对你来说是清楚的)为了继续在文本的中间添加引号,我们需要再次在引用之前添加一个转义序列字符\kbd>,这就告诉Python不要把引用作为一个引号解析,而是简单地把它添加到字符串中。这样做的另一种选择,即:

print('I want to print this quote: " in my string')

这是因为整个字符串是由开始和结束的,这使Python能够准确地猜测(解析)实际整个字符串的开始和结束-这使它100%确信本例中的引号只是字符串的另一部分。这些转义序列有更多示例


字节与字符串

为了更好地理解这一区别,我们首先来看看Python和您使用的终端是如何交互的。我假设您是从cmd.exepowershell.exe或在Linux中运行Python脚本,比如xterm或其他什么。基本终端就是这样

终端将尝试解析发送到其输出缓冲区的任何内容,并将其表示给您。您可以通过执行以下操作进行测试:

print('\xc3\xa5\xc3\xa4\xc3\xb6') # Most Linux systems
print('\xe5\xe4\xf6') # Most Windows systems

理论上,上面的一个打印应该让你只打印一堆字节,终端知道如何将这些字节呈现为åäö。甚至你的浏览器也为你这样做(有趣的是,这也是他们解决表情符号问题的方法,每个人都同意某些字节组合应该成为🙀。我说的是大多数windows和Linux,因为这完全取决于您安装操作系统时选择的区域/语言。我在EU North(瑞典),所以我在windows中的默认编解码器是^{,在我所有的Linux机器中我都有^{这些编解码器很重要,因为这是表示文本的人机界面

知道这一点后,通过执行print("...")sys.stdout.write("...")-发送到终端输出缓冲区的任何内容都将由终端解释并在您的区域设置中呈现。如果不可能,则会发生错误

这就是Python2和Python3开始变成两种不同的野兽的地方。这就是为什么你今天在这里。简单地说,{}做了很多自动化和神奇的猜测工作“,这样您就可以将字符串发送到套接字——Python将为您处理编码。Python2解析它们并以各种方式转换它们。在Python3中,许多自动猜测工作被删除,因为它常常让人困惑。通过函数和套接字发送的数据本质上是薛定谔数据,有时是字符串,有时是字节。因此,现在由开发人员来转换数据并对其进行编码始终

那么字节和字符串是什么呢

bytes正在进行中man术语,一个没有以任何方式编码的字符串,因此可以包含任何与“数据”相关的内容。它不必只是一个字符串(a-Z,0-9,!“#·%等等),它还可以包含特殊的字节,如\x00,它是一个Null byte/character。Python永远不会尝试在Python3中自动解析此数据。执行此操作时:

print(b'\xe5\xe4\xf6')

与上面一样,除了在Python3中将字符串定义为bytes string之外,Python会将字节的表示形式而不是实际字节的表示形式发送到终端缓冲区,因此,终端永远不会将它们解释为实际字节

示例1:对数据进行编码

这就引出了第一个示例。那么如何将包含bytesprint(b'\xe5\xe4\xf6')转换为终端中表示的字符,通过将其转换为具有特定编码的strings。在上面的示例中,三个字符\xe5\xe4\xf6恰好是ISO-8859-1编码器正在制作中。我知道这一点,因为我目前在windows上,如果您在终端中运行命令chcp,您将得到正在使用的which code page/encoder

在这方面,我可以做到:

print(b'\xe5\xe4\xf6'.decode('ISO-8859-1')

这将把bytes对象转换成string对象(带有编码)
这里的问题是,如果您将此string发送到我的Linux机器,它将不知道发生了什么。因为,如果您尝试:

print(b'\x86\x84\x94'.decode('UTF-8'))

您将得到如下错误消息:

>>> print(b'\x86\x84\x94'.decode('UTF-8'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 0: invalid start byte

这是因为,在UTF-8地区,字节\x86不存在。因此它无法知道如何处理它。而且因为我的Linux机器的默认编码器是UTF-8,所以您的windows数据对我的机器来说是垃圾

这让我们想到

插座

在Python3和计算机的大多数物理领域中,编码和字符串不受欢迎,因为它们不是真正的东西。相反,机器在bits中进行通信,简而言之,1和0。其中8个变成了byte,这就是Python的bytes发挥作用的地方。当从机器向机器发送内容时(或应用程序到应用程序),我们必须将任何文本表示转换为bytes序列,这样机器就可以相互通信。无需编码,无需解析。只需获取数据即可

我们通过三种方式实现这一点,它们是:

print('åäö'.encode('UTF-8'))
print(bytes('åäö', 'UTF-8'))
print(b'åäö')

最后一个选项将失败-但我故意将其保留下来,以显示告诉Python的区别,“嘿,这个奇怪的东西,将其转换为字节对象”

所有这些选项都将使用编码器*返回bytesåäö表示(除最后一个选项外,它将仅使用ASCII解析器进行编码,这最多是有限的)

UTF-8情况下,将返回如下内容:

b'\xc3\xa5\xc3\xa4\xc3\xb6'

这是你可以在插座上发送的东西。因为它只是一系列字节,终端、机器和应用程序除了一系列的1和0之外不会接触或处理它们*('11000011 10100101 11000011 10100100 11000011 10110110'具体来说)

再加上一些网络逻辑,这就是将要在你的套接字上发送的内容。这就是机器通信的方式

enter image description here

这是对正在发生的事情的概述。“人”是终端,也就是机器-人界面,您可以在其中输入您的åäö,终端将其编码/解析为特定的编码。您的应用程序必须发挥魔力才能将其转换为套接字/物理世界可以使用的东西

相关问题 更多 >