Python 为什么输出保持空白?
我在阅读《黑帽Python》一书,作者创建了一个TCP代理,但我似乎无法让它工作 以下是我正在使用的代码:Python 为什么输出保持空白?,python,python-3.x,proxy,Python,Python 3.x,Proxy,我在阅读《黑帽Python》一书,作者创建了一个TCP代理,但我似乎无法让它工作 以下是我正在使用的代码: import sys import socket import threading # this is a pretty hex dumping function directly taken from # http://code.activestate.com/recipes/142812-hex-dumper/ def hexdump(src, length=16): r
import sys
import socket
import threading
# this is a pretty hex dumping function directly taken from
# http://code.activestate.com/recipes/142812-hex-dumper/
def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src, str) else 2
for i in range(0, len(src), length):
s = src[i:i + length]
hexa = b' '.join([b"%0*X" % (digits, ord(x)) for x in s])
text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
result.append(
b"%04X %-*s %s" % (i, length * (digits + 1), hexa, text))
print(b'\n'.join(result))
def receive_from(connection):
buffer = b''
# We set a 2 second time-out. Depending on your target this may need
# to be adjusted
connection.settimeout(2)
try:
# keep reading into the buffer until there's no more data or we
# time-out
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except TimeoutError:
pass
return buffer
# modify any requests destined for the remote host
def request_handler(buffer):
# perform packet modifications
return buffer
# modify any responses destined for the local host
def response_handler(buffer):
# perform packet modifications
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
# connect to the remote host
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
# receive data from the remote end if necessary
if receive_first:
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
# send it to our response handler
remote_buffer = response_handler(remote_buffer)
# if we have data to send to our local client send it
if len(remote_buffer):
print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
# now let's loop and read from local, send to remote, send to local
# rinse wash repeat
while True:
# read from local host
local_buffer = receive_from(client_socket)
if len(local_buffer):
print("[==>] Received %d bytes from localhost." % len(local_buffer))
hexdump(local_buffer)
# send it to our request handler
local_buffer = request_handler(local_buffer)
# send off the data to the remote host
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
# receive back the response
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[<==] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
# send to our response handler
remote_buffer = response_handler(remote_buffer)
# send the response to the local socket
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
# if no more data on either side close the connections
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print("[*] No more data. Closing connections.")
break
def server_loop(local_host, local_port, remote_host, remote_port,
receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
server.bind((local_host, local_port))
except socket.error as exc:
print("[!!] Failed to listen on %s:%d" % (local_host,
local_port))
print("[!!] Check for other listening sockets or correct "
"permissions.")
print(f"[!!] Caught exception error: {exc}")
sys.exit(0)
print("[*] Listening on %s:%d" % (local_host, local_port))
server.listen(5)
while True:
client_socket, addr = server.accept()
# print out the local connection information
print("[==>] Received incoming connection from %s:%d" % (
addr[0], addr[1]))
# start a thread to talk to the remote host
proxy_thread = threading.Thread(target=proxy_handler, args=(
client_socket, remote_host, remote_port, receive_first))
proxy_thread.start()
def main():
# no fancy command line parsing here
if len(sys.argv[1:]) != 5:
print("Usage: ./proxy.py [localhost] [localport] [remotehost] "
"[remoteport] [receive_first]")
print("Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True")
sys.exit(0)
# setup local listening parameters
local_host = sys.argv[1]
local_port = int(sys.argv[2])
# setup remote target
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
# this tells our proxy to connect and receive data
# before sending to the remote host
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else:
receive_first = False
# now spin up our listening socket
server_loop(local_host, local_port, remote_host, remote_port, receive_first)
main()
程序应给出如下输出:
[*] Listening on 127.0.0.1:21
[==>] Received incoming connection from 127.0.0.1:59218
0000 32 32 30 20 50 72 6F 46 54 50 44 20 31 2E 33 2E 220 ProFTPD 1.3.
0010 33 61 20 53 65 72 76 65 72 20 28 44 65 62 69 61 3a Server (Debia
0020 6E 29 20 5B 3A 3A 66 66 66 66 3A 35 30 2E 35 37 n) [::ffff:22.22
0030 2E 31 36 38 2E 39 33 5D 0D 0A .22.22]..
[<==] Sending 58 bytes to localhost.
[==>] Received 12 bytes from localhost.
0000 55 53 45 52 20 74 65 73 74 79 0D 0A USER testy..
[==>] Sent to remote.
[<==] Received 33 bytes from remote.
0000 33 33 31 20 50 61 73 73 77 6F 72 64 20 72 65 71 331 Password req
0010 75 69 72 65 64 20 66 6F 72 20 74 65 73 74 79 0D uired for testy.
0020 0A .
[<==] Sent to localhost.
[==>] Received 13 bytes from localhost.
0000 50 41 53 53 20 74 65 73 74 65 72 0D 0A PASS tester..
[==>] Sent to remote.
[*] No more data. Closing connections.
)
我错过了什么
如果您使用
127.0.0.1 21
sudo ./proxy.py 127.0.0.1 21 ftp.dlptest.com 21 True
然后,您必须使用
ftp 127.0.0.1 21
然后它开始工作
但是有不同的问题:它似乎是为Python2创建的
hextump
,它将bytes
和str
视为相同类型的数据,并使用ord()
将字符转换为其代码/数字。在Python3中不需要它
您还可以直接将其代码转换为字符串chr(x)
,并连接到要显示的字符串
def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src, str) else 2
#print('[DEBUG] src:', type(src))
for i in range(0, len(src), length):
s = src[i:i+length]
data = ['%0*X' % (digits, x) for x in s]
#print('[DEBUG] data:', data)
hexa = ' '.join(data)
#print('[DEBUG] hexa:', hexa)
data = [chr(x) if 0x20 <= x < 0x7F else '.' for x in s]
#print('[DEBUG] data:', data)
text = ''.join(data)
#print('[DEBUG] text:', text)
result.append(
"%04X %-*s %s" % (i, length * (digits+1), hexa, text))
print('\n'.join(result))
但对于本地数据,它需要10秒
local_buffer = receive_from(client_socket, 10)
顺便说一句: 我还捕获了
KeyboardInterrupt
,以便在使用Ctrl+C
停止服务器时关闭连接
我还要补充一点
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
要解决服务器再次启动时错误[Errno 98]地址已在使用的问题
代码: 第二
ftp 127.0.0.1 5005
然后我得到
$ sudo python3.7 proxy.py 127.0.0.1 5005 ftp.dlptest.com 21 True
[*] Listening on 127.0.0.1:5005
[==>] Received incoming connection from 127.0.0.1:50124
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 5005), raddr=('127.0.0.1', 50124)>
ftp.dlptest.com 21
True
receive first
[DEBUG] buffer:
220-#########################################################
220-Please upload your web files to the public_html directory.
220-Note that letters are case sensitive.
220-#########################################################
220 This is a private system - No anonymous login
0000 32 32 30 2D 23 23 23 23 23 23 23 23 23 23 23 23 220-############
0010 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
0020 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
0030 23 23 23 23 23 23 23 23 23 23 23 23 23 0D 0A 32 #############..2
0040 32 30 2D 50 6C 65 61 73 65 20 75 70 6C 6F 61 64 20-Please upload
0050 20 79 6F 75 72 20 77 65 62 20 66 69 6C 65 73 20 your web files
0060 74 6F 20 74 68 65 20 70 75 62 6C 69 63 5F 68 74 to the public_ht
0070 6D 6C 20 64 69 72 65 63 74 6F 72 79 2E 0D 0A 32 ml directory...2
0080 32 30 2D 4E 6F 74 65 20 74 68 61 74 20 6C 65 74 20-Note that let
0090 74 65 72 73 20 61 72 65 20 63 61 73 65 20 73 65 ters are case se
00A0 6E 73 69 74 69 76 65 2E 0D 0A 32 32 30 2D 23 23 nsitive...220-##
00B0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00C0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00D0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00E0 23 23 23 23 23 23 23 0D 0A 32 32 30 20 54 68 69 #######..220 Thi
00F0 73 20 69 73 20 61 20 70 72 69 76 61 74 65 20 73 s is a private s
0100 79 73 74 65 6D 20 2D 20 4E 6F 20 61 6E 6F 6E 79 ystem - No anony
0110 6D 6F 75 73 20 6C 6F 67 69 6E 0D 0A mous login..
[<==] Sending 284 bytes to localhost.
[DEBUG] buffer:
USER furas
[==>] Received 12 bytes from localhost.
0000 55 53 45 52 20 66 75 72 61 73 0D 0A USER furas..
[==>] Sent to remote.
[DEBUG] buffer:
331 User furas OK. Password required
[<==] Received 38 bytes from remote.
0000 33 33 31 20 55 73 65 72 20 66 75 72 61 73 20 4F 331 User furas O
0010 4B 2E 20 50 61 73 73 77 6F 72 64 20 72 65 71 75 K. Password requ
0020 69 72 65 64 0D 0A ired..
[<==] Sent to localhost.
[DEBUG] buffer:
PASS adasdasda
[==>] Received 16 bytes from localhost.
0000 50 41 53 53 20 61 64 61 73 64 61 73 64 61 0D 0A PASS adasdasda..
[==>] Sent to remote.
[DEBUG] buffer:
[*] No more data. Closing connections.
^CKeyboardInterrupt
顺便说一句:如果您使用的端口大于
1024
(如我的回答中的5005
),那么它应该在没有sudo的情况下运行,只是为了清楚起见,“输出保持空白”意味着您运行此脚本,但它根本不打印任何内容,而是立即退出?我的意思是它被卡在“侦听…”上,它不接收(?)传入连接您应该运行ftp 127.0.0.1 21
与服务器连接。这给我提供了从127.0.0.1:52776接收到的[=>]传入连接。但它仍然需要一些更改下一个问题-您必须使用socket.timeout
而不是timeout
来捕获超时下一个问题-代码不需要ord()
,因为它从服务器获取字节。这段代码似乎是为python2
而创建的,它需要ord()
,因为它像str
一样处理字节,用你的代码我得到了预期的结果,我需要彻底研究它谢谢你,我真的学到了很多
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
import sys
import socket
import threading
# this is a pretty hex dumping function directly taken from
# http://code.activestate.com/recipes/142812-hex-dumper/
def hexdump(src, length=16):
result = []
digits = 4 if isinstance(src, str) else 2
#print('[DEBUG] src:', type(src))
for i in range(0, len(src), length):
s = src[i:i+length]
data = ['%0*X' % (digits, x) for x in s]
#print('[DEBUG] data:', data)
hexa = ' '.join(data)
#print('[DEBUG] hexa:', hexa)
data = [chr(x) if 0x20 <= x < 0x7F else '.' for x in s]
#print('[DEBUG] data:', data)
text = ''.join(data)
#print('[DEBUG] text:', text)
result.append(
"%04X %-*s %s" % (i, length * (digits+1), hexa, text))
print('\n'.join(result))
def receive_from(connection, timeout=2):
buffer = b''
# We set a 2 second time-out. Depending on your target this may need
# to be adjusted
connection.settimeout(timeout)
try:
# keep reading into the buffer until there's no more data or we
# time-out
while True:
data = connection.recv(4096)
if not data:
break
buffer += data
except socket.timeout as ex:
#print('TimeoutError:', ex)
pass
print('[DEBUG] buffer:')
print(buffer.decode())
return buffer
# modify any requests destined for the remote host
def request_handler(buffer):
# perform packet modifications
return buffer
# modify any responses destined for the local host
def response_handler(buffer):
# perform packet modifications
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
print(client_socket)
print(remote_host, remote_port)
print(receive_first)
# connect to the remote host
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
# receive data from the remote end if necessary
if receive_first:
print('receive first')
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
# send it to our response handler
remote_buffer = response_handler(remote_buffer)
# if we have data to send to our local client send it
if len(remote_buffer):
print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
# now let's loop and read from local, send to remote, send to local
# rinse wash repeat
while True:
# read from local host
local_buffer = receive_from(client_socket, 10) # longer time for user response
if len(local_buffer):
print("[==>] Received %d bytes from localhost." % len(local_buffer))
hexdump(local_buffer)
# send it to our request handler
local_buffer = request_handler(local_buffer)
# send off the data to the remote host
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
# receive back the response
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[<==] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
# send to our response handler
remote_buffer = response_handler(remote_buffer)
# send the response to the local socket
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
# if no more data on either side close the connections
if not len(local_buffer) or not len(remote_buffer):
client_socket.close()
remote_socket.close()
print("[*] No more data. Closing connections.")
break
def server_loop(local_host, local_port, remote_host, remote_port,
receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
server.bind((local_host, local_port))
except socket.error as exc:
print("[!!] Failed to listen on %s:%d" % (local_host,
local_port))
print("[!!] Check for other listening sockets or correct "
"permissions.")
print(f"[!!] Caught exception error: {exc}")
sys.exit(0)
print("[*] Listening on %s:%d" % (local_host, local_port))
server.listen(5)
try:
while True:
client_socket, addr = server.accept()
# print out the local connection information
print("[==>] Received incoming connection from %s:%d" % (
addr[0], addr[1]))
# start a thread to talk to the remote host
proxy_thread = threading.Thread(target=proxy_handler, args=(
client_socket, remote_host, remote_port, receive_first))
proxy_thread.start()
except KeyboardInterrupt:
print('KeyboardInterrupt')
server.close()
def main():
# no fancy command line parsing here
if len(sys.argv[1:]) != 5:
print("Usage: ./proxy.py [localhost] [localport] [remotehost] "
"[remoteport] [receive_first]")
print("Example: ./proxy.py 127.0.0.1 9000 10.12.132.1 9000 True")
sys.exit(0)
# setup local listening parameters
local_host = sys.argv[1]
local_port = int(sys.argv[2])
# setup remote target
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
# this tells our proxy to connect and receive data
# before sending to the remote host
receive_first = sys.argv[5]
receive_first = ("True" in receive_first)
# now spin up our listening socket
server_loop(local_host, local_port, remote_host, remote_port, receive_first)
main()
sudo python3.7 proxy.py 127.0.0.1 5005 ftp.dlptest.com 21 True
ftp 127.0.0.1 5005
$ sudo python3.7 proxy.py 127.0.0.1 5005 ftp.dlptest.com 21 True
[*] Listening on 127.0.0.1:5005
[==>] Received incoming connection from 127.0.0.1:50124
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 5005), raddr=('127.0.0.1', 50124)>
ftp.dlptest.com 21
True
receive first
[DEBUG] buffer:
220-#########################################################
220-Please upload your web files to the public_html directory.
220-Note that letters are case sensitive.
220-#########################################################
220 This is a private system - No anonymous login
0000 32 32 30 2D 23 23 23 23 23 23 23 23 23 23 23 23 220-############
0010 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
0020 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
0030 23 23 23 23 23 23 23 23 23 23 23 23 23 0D 0A 32 #############..2
0040 32 30 2D 50 6C 65 61 73 65 20 75 70 6C 6F 61 64 20-Please upload
0050 20 79 6F 75 72 20 77 65 62 20 66 69 6C 65 73 20 your web files
0060 74 6F 20 74 68 65 20 70 75 62 6C 69 63 5F 68 74 to the public_ht
0070 6D 6C 20 64 69 72 65 63 74 6F 72 79 2E 0D 0A 32 ml directory...2
0080 32 30 2D 4E 6F 74 65 20 74 68 61 74 20 6C 65 74 20-Note that let
0090 74 65 72 73 20 61 72 65 20 63 61 73 65 20 73 65 ters are case se
00A0 6E 73 69 74 69 76 65 2E 0D 0A 32 32 30 2D 23 23 nsitive...220-##
00B0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00C0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00D0 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 ################
00E0 23 23 23 23 23 23 23 0D 0A 32 32 30 20 54 68 69 #######..220 Thi
00F0 73 20 69 73 20 61 20 70 72 69 76 61 74 65 20 73 s is a private s
0100 79 73 74 65 6D 20 2D 20 4E 6F 20 61 6E 6F 6E 79 ystem - No anony
0110 6D 6F 75 73 20 6C 6F 67 69 6E 0D 0A mous login..
[<==] Sending 284 bytes to localhost.
[DEBUG] buffer:
USER furas
[==>] Received 12 bytes from localhost.
0000 55 53 45 52 20 66 75 72 61 73 0D 0A USER furas..
[==>] Sent to remote.
[DEBUG] buffer:
331 User furas OK. Password required
[<==] Received 38 bytes from remote.
0000 33 33 31 20 55 73 65 72 20 66 75 72 61 73 20 4F 331 User furas O
0010 4B 2E 20 50 61 73 73 77 6F 72 64 20 72 65 71 75 K. Password requ
0020 69 72 65 64 0D 0A ired..
[<==] Sent to localhost.
[DEBUG] buffer:
PASS adasdasda
[==>] Received 16 bytes from localhost.
0000 50 41 53 53 20 61 64 61 73 64 61 73 64 61 0D 0A PASS adasdasda..
[==>] Sent to remote.
[DEBUG] buffer:
[*] No more data. Closing connections.
^CKeyboardInterrupt
$ ftp 127.0.0.1 5005
Connected to 127.0.0.1.
220-#########################################################
220-Please upload your web files to the public_html directory.
220-Note that letters are case sensitive.
220-#########################################################
220 This is a private system - No anonymous login
Name (127.0.0.1:furas):
331 User furas OK. Password required
Password:
421 Service not available, remote server has closed connection
Login failed.
No control connection for command: Success
ftp> quit