Python脚本学习(一)

前言

最近在学习python网络脚本编写,利用tcp客户端/服务器学习编写了一个代替netcat(简陋)的工具,记录一下。

TCP 客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# coding:utf-8
import socket

# 设置连接ip和端口
target_host = "0.0.0.0"
target_port = 22

# 创建socket对象
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接
client.connect((target_host, target_port))

# 发送消息
client.send("Hey, I'm TCP client service!")

# 获取响应并打印
response = client.recv(4096)
print response

这是一个简单的TCP客户端,向指定的ip和端口发送数据,然后将返回输出,由这个我们可以拓展出一个简易的端口扫描器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# coding:utf-8
import socket
# 设置扫描的主机
hosts = ['127.0.0.1', '192.168.0.1', '10.0.0.1']

# 设置常用端口
ports = [22, 445, 80, 443, 3389]

s = socket.socket()
# 遍历列表,获取到有相应的端口时打印
for host in hosts:
for port in ports:
try:
print "Attempting to connect to " + host + ':' + str(port)
s.connect((host, port))
s.send('sketch_pl4ne \n')
banner = s.recv(1024)
if banner:
print "Host:" + host + "Port:" + str(port) +" open:" + banner
except: pass

效果图如下:

感觉有那么点意思了= =

TCP 服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# coding:utf-8
import socket
import threading # 用于多线程处理

# 设置要监听的ip和端口
bind_ip = "0.0.0.0"
bind_port = 9999

# 创建socket对象
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定ip和端口
server.bind((bind_ip, bind_port))

# 开始监听并设置最大连接数
server.listen(5)

print "[*] Listening on %s:%d" % (bind_ip, bind_port)

# 客户连接处理线程
def handle_client(client_socket):

request = client_socket.recv(1024)

print "[*] Received: %s" % request

client_socket.send("ACK!")

client_socket.close()

# 循环监听,当有客户端连接就调用 handler_client()函数
while True:

# 接受客户端连接,返回(新套接字, 连接客户端地址)的一个元组
client, addr = server.accept()

print "[*] Accepted connection from: %s:%d" % (addr[0], addr[1]) # addr[0]是ip, addr[1]是端口

# 挂起客户端线程,处理传入的数据
client_handler = threading.Thread(target=handle_client, args=(client, )) # target为需要调用的函数,args为函数对应的参数(元组)
client_handler.start()

这个脚本主要用来监听端口并且接收连接,比如我们可以用刚刚的客户端给它发消息:

netdog

这个脚本使用python编写来代替netcat(大多数情况下没有nc但是有python的环境中)实现上传文件,获取shell,发送信息等等功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# coding:utf-8

import sys # 调用系统函数
import socket # 建立TCP连接
import getopt # 获取命令行参数
import threading # 多线程
import subprocess # 处理命令,返回命令执行结果

# 定义全局变量
target = ""
port = 0
listen = False
execute = ""
command = False
upload = False
upload_destination = ""


# 帮助信息
def usage():
print "NetDog Tool"
print
print "Usage: netdog.py -t target_host -p port"
print "-l --listen - listen on [host]:[port] for incoming connections"
print "-e --execute=file_to_run - execute the given file upon receiving a connection"
print "-c --command - initialize a command shell"
print "-u --upload=destination - upon receiving connection upload a file and write to [destination]"
print
print
print "Examples: "
print "netdog.py -t 192.168.0.1 -p 5555 -l -c"
print "netdog.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"
print "netdog.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
print "echo 'ABCDEFGHI' | ./netdog.py -t 192.168.11.12 -p 135"
sys.exit(0)


# 主函数
def main():
global target
global port
global listen
global execute
global command
global upload_destination

if not len(sys.argv[1:]):
usage()

try:
opts, args = getopt.getopt(sys.argv[1:], "t:p:u:e:hlc", ["target", "port", "upload", "execute", "help", "listen, command"])
except getopt.GetoptError as err:
print str(err)
usage()

# 读取命令行选项,根据选项给相应的全局变量变量初始化
for option_name, option_value in opts:
if option_name in ("-h", "--help"):
usage()
elif option_name in ("-l", "--listen"):
listen = True
elif option_name in ("-e", "--execute"):
execute = option_value
elif option_name in ("-c", "--commandshell"):
command = True
elif option_name in ("-u", "--upload"):
upload_destination = option_value
elif option_name in ("-t", "--target"):
target = option_value
elif option_name in ("-p", "--port"):
port = int(option_value)
else:
assert False, "Unkonw Option"

# 不处于监听模式时
if not listen and len(target) and port > 0:
buffer_str = sys.stdin.read()
client_sender(buffer_str)
# 处于监听模式时
if listen:
server_loop()


# 发送消息,并将返回结果打印
def client_sender(buffer_str):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
client.connect((target, port))
if len(buffer_str):
client.send(buffer_str)

while True:
recv_len = 1
response = ""

while recv_len:
data = client.recv(4096)
recv_len = len(data)
response += data

if recv_len < 4096:
break

print response,

# 继续获取输入,为了与命令行匹配加上换行符
buffer_str = raw_input("")
buffer_str += "\n"

client.send(buffer_str)
except:
print "[*] Exception! Exiting."
client.close()


# 设置监听循环
def server_loop():
global target

# 如果没有指定ip,默认为监听本机ip
if not len(target):
target = "0.0.0.0"

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))

server.listen(5)

while True:
# 当有客户端连接时,挂起一个线程,执行client_handler((client_socket))函数
client_socket, addr = server.accept()
client_thread = threading.Thread(target=client_handler, args=(client_socket,))
client_thread.start()


# 执行从客户端获取的命令,返回执行结果
def run_command(command):
command = command.rstrip()

try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
output = "Failed to execute command.\r\n"

return output


# 当有客户端连接之后,根据命令行选项执行不同的功能
def client_handler(client_socket):
global upload
global execute
global command

# 上传文件至指定路径
if len(upload_destination):
file_buffer = ""

while True:
data = client_socket.recv(1024)

if not data:
break
else:
file_buffer += data

try:
file_descriptor = open(upload_destination, "wb")
file_descriptor.write(file_buffer)
file_descriptor.close()

client_socket.send("Successfully saved file to %s\r\n" % upload_destination)
except:
client_socket.send("Failed to save file to %s\r\n" % upload_destination)

# 执行命令,返回结果
if len(execute):
output = run_command(execute)
client_socket.send(output)

# 返回一个shell
if command:
while True:
client_socket.send("<netdog:#> ")

cmd_buffer = ""
while "\n" not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
response = run_command(cmd_buffer)
client_socket.send(response)


if __name__ == "__main__":
main()

执行演示:

开始界面

获取shell

注意:未指定-t target默认是监听本机,另外连接时,输入完命令需要手动CTRL+D输入语句结束符,才能连接到shell

发送HTTP请求

下面我们试试用netdog发送HTTP请求,获取www.baidu.com的响应:

成功~

参考文献

Black hat Python: Python Programming for Hackers and PentestersP1~P21

PS:netdog是随便取的,仅用于学习时方便记忆,侵删!

小结

刚开始学习,只学了点皮毛,继续加油吧 = =

0%