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

喜迎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连接判断

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

#!/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、在控制台的信息打印都加了锁,以保持整齐,这里提取出一个输出的函数打印错误信息。 如下:

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段的生成

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日志介绍)

晨星先生

憋说话,要加速了

原文发布于微信公众号 - 晨星先生(MoXuanIT)

原文发表时间:2017-10-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ShaoYL

iOS逆向实战与工具使用(微信添加好友自动确认)

5406
来自专栏向治洪

ECMAScript 6 入门简介

ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。它的目标,是使得JavaScript语言...

1947
来自专栏老马寒门IT

开发者的如何优雅的使用OSX

Mac对于IT开发者来说是最好的开发工具,没有之一。

23410
来自专栏腾讯Bugly的专栏

移动App入侵与逆向破解技术-iOS篇

如果您有耐心看完这篇文章,您将懂得如何着手进行app的分析、追踪、注入等实用的破解技术,另外,通过“入侵”,将帮助您理解如何规避常见的安全漏洞,文章大纲: 简单...

2.3K6
来自专栏macOS 开发学习

macOS 应用注入开发简介与实践

本文主要介绍的是动态链接库注入的相关实践,这不仅仅局限于macOS,同时对iOS应用也具有相同的效果,希望大家可以借鉴使用.

1463
来自专栏互联网杂技

如何学习用Typescript写Reactjs?

首先扫盲一下,先从搭建环境开始: 1.安装node,因为ts的编译器是js/ts写的; 安装node后同时获得npm命令,这是nodejs世界里的包管理器...

56912
来自专栏即时通讯技术

金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(实战篇)

本文接上篇《金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)》,以iOS端的Objective-C代码为例,向您演示如何使用P...

832
来自专栏Java3y

AJAX入门这一篇就够了

什么是Ajax Ajax(Asynchronous JavaScript and XML) 异步JavaScript和XML Ajax实际上是下面这几种技术的融...

1.1K8
来自专栏ytkah

微信公众平台开放JS-SDK(微信内网页开发工具包)

微信公众平台开放JS-SDK(微信内网页开发工具包),这次开放接口是质的飞跃,是对开发者和广大用户一个利好的消息。未来的公众号图文消息会更丰富多彩,准备脑洞大开...

2.7K6
来自专栏极客猴

多线程爬取 unsplash 图库

我公众号文章的封面配图都在 Unsplash 上找的。因为 Unsplash 是一个完全免费的、无版权的高清图片资源网站。

1873

扫码关注云+社区