希望你能看到我做错了什么。
BHP 的第四章让我们尝试重新创建一个基本版本的 netcat。尝试将程序作为侦听器运行时出现类型错误,但我无法弄清楚原因。据我所知,一切都已检查完毕,但它说我正在尝试在我的“监听方法”中将“str”作为“int”运行
回溯(最后一次通话): 文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 172 行,位于 数控运行() 运行中的文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 39 行 自.listen() 文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 85 行,在 listen 中 self.socket.bind((self.args.target, self.args.port)) # 1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ 类型错误:“str”对象不能解释为整数
有人能看到我看不到的东西吗?
import argparse
import socket
import shlex
import subprocess
import sys
import textwrap
import threading
def execute(cmd):
cmd = cmd.strip()
if not cmd:
return
output = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT)
return output.decode()
'''
subprocess.check_output() runs a command on the local operating system,
and then returns the output from that command.
'''
class NetCat:
def __init__(self, args, buffer=None): # 1
self.args = args
self.buffer = buffer
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #2
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
'''
1. We initialize the NetCat object with the arguments from the command line and the buffer
2. We create the socket object
the SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state,
without waiting for its natural timeout to expire.
'''
def run(self):
if self.args.listen:
self.listen()
else:
self.send()
'''
RUN METHOD
If we are setting up a listener, then the program will call the listen method,
Otherwise it will call the send method.
'''
def send(self):
self.socket.connect((self.args.target, self.args.port)) # 1
if self.buffer:
self.socket.send(self.buffer)
try: # 2
while True: # 3
recv_len = 1
response = ''
while recv_len:
data = self.socket.recv(4096)
recv_len = len(data)
response += data.decode()
if recv_len < 4096:
break # 4
if response:
print(response)
buffer = input('> ')
buffer += '\n'
self.socket.send(buffer.encode()) # 5
except KeyboardInterrupt: # 6
print('User Terminated.')
self.socket.close()
sys.exit()
'''
SEND METHOD
1. We connect the target and port. If we havea buffer we connect that to the target first.
The we set up a try/catch block so we can manually close the connection with ctrl-c
2. We start a loop
3. Loop receives data from target. If there is no more data
4. We break out of the loop.
5. Otherwise, we print the response data and pause to get interactive input,
send the input and continue the loop.
6. Loop will continue until KeyboardInterrupt occurs, ctrl-c, which will close the socket.
'''
def listen(self):
self.socket.bind((self.args.target, self.args.port)) # 1
self.socket.listen(5)
while True: # 2
client_socket, _ = self.socket.accept()
client_thread = threading.Thread(target=self.handle, args=(client_socket,)) # 3
client_thread.start()
'''
1. The listen method binds to the target and the port
2. Starts listening in a loop.
3. Passes the connected socket to the handle method
'''
def handle(self, client_socket):
if self.args.execute: # 1
output = execute(self.args.execute)
client_socket.send(output.encode())
elif self.args.upload: # 2
file_buffer = b''
while True:
data = client_socket.recv(4096)
if data:
file_buffer += data
else:
break
elif self.args.command: # 3
cmd_buffer = b''
while True:
try:
client_socket.send(b'BHP: $> ')
while '\n' not in cmd_buffer.decode():
cmd_buffer += client_socket.recv(64)
response = execute(cmd_buffer.decode())
if response:
client_socket.send(response.encode())
cmd_buffer = b''
except Exception as e:
print(f'server killed {e}')
self.socket.close()
sys.exit()
'''
HANDLE METHOD
The handle method executes the task corresponding to the command line argument it receives.
1. The handle method passed the given command to the execute function
and sends the output back on the socket.
2. If a file should be uploaded, we set up a loop to listen for content on the listening socket
and receive data until there's no more data coming in.
Then the accumulated content is written to the specified file.
3. Finally, if a shell is to be created, we set up a loop, send a prompt to the sender, and wait for a
command string to come back. We then execute the command by using the execute function and return the output
of the command to the sender.
The shell scan for a newline character to determine when to process a command,
which makes it netcat friendly. Meaning, we can use this program on the listener side
and use netcat itself on the sender side.
However, if we are coming up with a Python program to speak to it, we need to remember to
add the newline character.
In the send method you can see the character was added after receiving input from the console.
'''
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='BHP Net Tool',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent('''Example:
netcat.py -t 192.168.1.108 -p 5555 -l -c # command shell
netcat.py -t 192.168.1.108 -p 5555 -l -u=mytest.txt # upload to file
netcat.py -t 192.168.1.108 -p 5555 -l -e=\"cat /etc/passwd\" # execute command
echo 'ABC' | ./netcat.py -t 192.168.1.108 -p 135 # echo text to server port 135
netcat.py -t 192.168.1.108 -p 5555 # connect to server
'''))
parser.add_argument('-c', '--command', action='store_true', help='command_shell')
parser.add_argument('-e', '--execute', help='execute specified command')
parser.add_argument('-l', '--listen', action='store_true', help='listen')
parser.add_argument('-p', '--port', default=5555, help='specified port')
parser.add_argument('-t', '--target', default='192.168.1.203', help='specified IP')
parser.add_argument('-u', '--upload', help='upload file')
args = parser.parse_args()
if args.listen:
buffer = ''
else:
buffer = sys.stdin.read()
nc = NetCat(args, buffer.encode())
nc.run()
'''
1. We use the argparse module from the standard library tpp create command line interface.
2. We provide example usage that the program will display when the user invokes it with '--help',
and add six arguments that specify how we want the program to behave.
3. the -c argument sets up an interactive shell,
the -e argument executes one specific command,
the -l argument indicates a listener should be set up,
the -p argument specifies the port on which to communicate,
the -t argument specifies the target IP
the -u argument specifies the name of a file to upload.
Both the sender and receiver can use this program, so arguments determine whether its invoked to send or listen.
The -c, -e, and -u arguments imply the -l argument, because those arguments apply to only the listener side of
of the communication.
Senders only connect to the listener so they only need -t and -p arguments to define their target.
4. When setting up a listener, we invoke the NetCat object with and empty buffer string.
Otherwise, we send the buffer content from stdin.
Finally, we call the run method to start it up.
'''
我跑的时候 'python3 netcat_custom.py -t 192.168.116.128 -p 5555 -l -c'
我应该能够进入命令 shell,或者如果我去掉 -c 参数,它应该以侦听器模式运行,但我得到了类型错误:
回溯(最后一次通话): 文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 172 行,位于 数控运行() 运行中的文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 39 行 自.listen() 文件“/home/steelcoyote/PycharmProjects/toolkit/netcat_custom.py”,第 85 行,在 listen 中 self.socket.bind((self.args.target, self.args.port)) # 1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^ 类型错误:“str”对象不能解释为整数