从协议提取到多功能RDP识别脚本

2018-06-07 14:50:36 浏览数 (1)

喜迎X大(涉及到这个数字后台就一直提醒可能违规,干脆)。然后,就是,我胡汉三又回来啦啦啦啦啦!!!身体养得差不多了,其实也没有什么大问题,谢谢大家关心~兄弟姐妹们,造起来啊~high起来啊~反正有大把时光~

谁再熬夜谁傻逼,以此为誓,违誓者发红包。

阅读此文大概需要8分钟,也可能80分钟

最近在公司和我们后端的兄弟聊了聊,他是FOFA 3.0的后端主要开发人员之一。把FOFA的协议识别与提取用Golang实现。 虽然没有他那么牛逼的编码技术,不过也对其架构稍稍了解。小小的学习了协议提取的知识。

下面介绍一些常用的提取方法,笔者所知主要有两种方法: 1、在使用一些客户端工具时候,Wireshark抓包提取发送和返回的数据包 2、直接发送一些指定的(特殊)字符串识别返回的banner头。

后一种方法发送什么字符串可以看看一些文档、手册或者用fuzz。

1F

RDP协议的提取

这里我以RDP协议的提取为例子。

第一步:打开wireshark,输入:ip.addr==ip_address 第二步:打开远程桌面连接

第三步:开始抓包,点击连接 我们看到抓到如下的数据包。

我们找到了发送data的这个数据包

右键追踪tcp流,可以看到如下为返回结果

我们把如下数据包的hex文本提取出来

我对windows 2k、2k3、2008、7、2012均进行测试

我们发送的数据包均为:

x03x00x00x13x0exe0x00x00x00x00x00x01x00x08x00x03x00x00x00

返回的数据包如下:

"2000": "0300000b06d00000123400" "2003": "030000130ed000001234000300080002000000" "2008": "030000130ed000001234000200080002000000" "win7OR2008R2": "030000130ed000001234000209080002000000" "2008R2DC": "030000130ed000001234000201080002000000" "2012R2OR8": "030000130ed00000123400020f080002000000"

我们看到了除了win2000外,其他的响应包的前10位均为030000130e,也就是前面的五个字节。 这边只提取这个五个作为判断。

2F

python脚本实现之最基础的socket连接判断

代码语言:javascript复制
import socket


target="101.200.146.54"
port =3389
scan = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
scan.settimeout(5)
address = (target, port)
scan.connect(address)
scan.send('x03x00x00x13x0exe0x00x00x00x00x00x01x00x08x00x03x00x00x00')
banner = scan.recv(5)
if banner == 'x03x00x00x13x0e':
    print "%s RDP Port is %s!" % (target, port)

3F

加上多线程和指定端口范围

下面的脚本算是五脏比较全了,加了如下功能: 1、端口范围的指定初步实现 2、端口打乱(如果我们指定范围按部就班的去) 2、多线程,用信号量控制线程数 3、加锁控制错误信息的整齐打印 需要注意一点的是ips.txt这个ip地址文本虽然用xreadlines。但是由于不知道用户的输入是否有多余的不可见字符。理应在socket连接之前用strip()过滤"r、n"之类的字符。不然会出现一些异常,

比如:errno 11001 getaddrinfo failed

代码语言:javascript复制
#!/usr/bin/python
# coding=utf-8

import random
import threading
from socket import *
import socket
print_lock = threading.Lock()
filename="ips.txt"
port_list = []
ports="3380-3390"
n,m =ports.split("-")
for line in range(int(n), int(m) 1):
    port_list.append(line)
port_lists = random.sample(port_list, int(m)-int(n))

semaphore = threading.BoundedSemaphore(value=10)
def run(target):
    global semaphore
    suc = False
    for port in port_list:
        if suc:
            break
        scan = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        scan.settimeout(5)

        if port:
            address=(target,int(port))
            try:
                scan.connect(address)
                scan.send('x03x00x00x13x0exe0x00x00x00x00x00x01x00x08x00x03x00x00x00')
                banner = scan.recv(5)
                if banner == 'x03x00x00x13x0e':
                    suc = True
                    with print_lock:
                        print "%s RDP Port is %s!"%(target,port)
                else:
                    with print_lock:
                        print "RDP close!"
            except Exception as e:
                with print_lock:
                    print  str(e)   target.strip()  " ,port:"   str(port)
            finally:
                pass
        scan.close()
    semaphore.release()
def main():
    with open(filename, "r") as fp:
        for ip in fp.xreadlines():
            semaphore.acquire()
            t = threading.Thread(target=run, args=(ip.strip(),))
            t.start()

if __name__ == "__main__":
    main()

4F

最终版本

1、在控制台的信息打印都加了锁,以保持整齐,这里提取出一个输出的函数打印错误信息。 如下:

代码语言:javascript复制
def print_status(ip, message, msg_type='*'):
    global print_lock
    with print_lock:
        print "[%s] %s - %s" % (msg_type, ip, message)

2、用argparse模块处理输入的参数 3、自己封装了一个类进行指定ip段的生成

代码语言:javascript复制
class gen_ip:
    def __init__(self,ip):
        self.ip = ip
    def gen_ip(self):
        start,end = [self.ip2num(x) for x in self.ip.split('-')]
        ip_list=  [self.num2ip(num) for num in  range(start,end 1) if num & 0xff]
        return ip_list
    def ip2num(self,ip):
        ip = [int(x) for x in ip.split('.')]
        return  ip[0]<<24 |ip[1]<<16 |ip[2]<<8 |ip[3]
    def num2ip(self,num):!
        return '%s.%s.%s.%s'%( (num & 0xff000000) >>24,
                                (num & 0x00ff0000) >>16,
                                (num & 0x0000ff00) >>8,
                                 num & 0x000000ff
                               )

这个生成一个1000w以内的B段差不多10秒内。

给出项目地址如下: https://github.com/lonelyvaf/rdp_find

后续可能会把这个封装为对象去写提取一些常用的协议吧,功能定位更多是内网的探测。

本来写了一个任务分发和结果集成管理,要用到kafka,先缓缓咯,有其他的事情。后续再一篇代码审计,送个0day给大家。

往期回顾

如何快速的搭建漏洞环境到复现到PoC

oreint db 远程代码执行漏洞

从iis认证方式的学习到一个路由器漏洞的调试

日志攻防初探之windows篇(iis日志介绍)

晨星先生

憋说话,要加速了

0 人点赞