前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从协议提取到多功能RDP识别脚本

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

作者头像
lonelyvaf
发布2018-06-07 14:50:36
1.5K0
发布2018-06-07 14:50:36
举报

喜迎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均进行测试

我们发送的数据包均为:

\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00

返回的数据包如下:

"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('\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00')
banner = scan.recv(5)
if banner == '\x03\x00\x00\x13\x0e':
    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('\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00')
                banner = scan.recv(5)
                if banner == '\x03\x00\x00\x13\x0e':
                    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日志介绍)

晨星先生

憋说话,要加速了

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 晨星先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
代码审计
代码审计(Code Audit,CA)提供通过自动化分析工具和人工审查的组合审计方式,对程序源代码逐条进行检查、分析,发现其中的错误信息、安全隐患和规范性缺陷问题,以及由这些问题引发的安全漏洞,提供代码修订措施和建议。支持脚本类语言源码以及有内存控制类源码。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档