zoukankan      html  css  js  c++  java
  • 应急中机器名的查询

    背景


    在应急过程中经常处理到Windows域控的登录日志审计。在这个过程中,会发现一个比较重要的麻烦,那就是域控记录的是MachineName(机器名)而不是记录IP地址,这在很多场景下造成了较大的麻烦。那么机器名要如何查找对应的主机或者IP地址呢。

    查找机器名的常用方法


    广播域内

    # 例如该机器名为WIN-ABC0D1E2FGH
    # 如果在一个广播域内可以通过种方式来获取机器名的IP地址
    # 方法一
    > ping WIN-ABC0D1E2FGH
    # 方法二(反向确认IP的机器名是不是自己查到的那个)
    > nbtstat -A 1.2.3.4 -n
    # 备注nbtstat -s 可以查找与本机通信的机器名
    

    跨广播域

    AD域内

    # 在AD域内其实也是很好办的,直接使用nslookup即可,记住nslookup要指定域DNS服务器
    > nslookup WIN-ABC0D1E2FGH
    

    AD域外

    # 这里就不是很方便了,需要对方开启了3389端口(不需要知道用户名和密码)
    > sudo nmap -sS -A 1.2.3.4 #(通过IP地址反向确认机器名)
    

    当然 -A选项会全扫描,较慢,因此我们来分析下Nmap扫描机器名的原理,首先这个扫描是通过3389端口确认的

    然后Nmap向对方发起了一个数据包,对方回一个数据包,收到对方回复的数据包可以看到如下图:

    在这个0x13后面一个16进制数是机器名的长度0x00-0xff,然后机器名结尾补个0,然后是0x1e 0x17,中间的部分就是机器名。

    工具化

    由于使用Nmap -A 全扫描比较慢,我把这部分逻辑写了个脚本,方便自己调用:
    MachineNameScan

    # -*- coding:utf-8 -*-
    """
    作者:挖洞的土拨鼠
    背景:应急的时候被不能跨广播域找到netbios的机器名,急死了,分析了一波Nmap -A的扫描机器名的原理,发现是靠3389
    端口通信里面的返回值判断的(有主机名),这样可以在一定程度上解决这个问题,如果单纯只需要检查机器名的时候可以使用。
    """
    # 需要用到的依赖库
    import sys
    import socket
    
    
    #全局配置,配置套接字超时时间
    socket.setdefaulttimeout(3)
    
    
    #全局变量、函数
    def StringToBinary(content):
        """将文本16进制字符串转成二进制流字符串"""
        try:
            content = content.replace(" ", '').replace('
    ', '')
        except Exception, reason:
            raise
        try:
            content = content.decode('hex')
        except Exception, reason:
            raise
        return content
    
    #3389发送数据包数据
    CorePayload = """
    1603010200010001fc0303428aed87844464ed9311e408e
    97a4a98e475b5ccf350cc328e029c3358ecdef90000da00
    05000400020001001600330039003a00180035000a001b0
    02f0034c010c006c015c00bc001003bc030c02cc028c024
    c014c00a00a500a300a1009f006b006a006900680038003
    700360088008700860085c01900a7006d0089c032c02ec0
    2ac026c00fc005009d003d0084c02fc02bc027c023c013c
    00900a400a200a0009e00670040003f003e003200310030
    009a0099009800970045004400430042c01800a6006c009
    b0046c031c02dc029c025c00ec004009c003c0096004100
    07c011c007c016c00cc002c012c00800130010000dc017c
    00dc00300ff010000f9000b000403000102000a001c001a
    00170019001c001b0018001a0016000e000d000b000c000
    9000a00230000000d0020001e0601060206030501050205
    03040104020403030103020303020102020203000f00010
    1001500a000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000
    00000000000000000000000000000000000000000000000"""
    
    
    #机器名扫描类
    class NmScanner:
        """机器名扫描类"""
        def __init__(self,ipaddress,port=None):
            """初始化参数数据"""
            self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.address = (ipaddress, int(port)) if port != None else (ipaddress, 3389)
            self.data = CorePayload
        def Scan(self):
            """扫描函数,根据回显提取机器名数据"""
            try:
                self.client.connect(self.address)
            except Exception, reason:
                return "无法扫描出机器名"
            try:
                self.client.send(StringToBinary(self.data))
            except Exception, reason:
                return "无法扫描出机器名"
            data = self.client.recv(4096)
            self.client.close()
            """
                取回来的回显字段是数据包中的一段数据,\x1e\x17是回包紧跟在机器名后面的标志字段值;
                前面的标志位是\x13后面接一个机器名长度的16进制\x00-\xff中的一个值,然后就是机器名;
                机器名结尾有个0;
            """
            return repr(data)[0:repr(data).find('\x1e\x17')].split('\x13')[-1][4:-1]
    
    if __name__ == "__main__":
        try:
            ip = sys.argv[1]
        except Exception, reason:
            print "请输入对方IP地址"
            exit(0) 
        try:
            port = int(sys.argv[2])
            scanner = NmScanner(ip,port)
        except Exception, reason:
            scanner = NmScanner(ip)
        print scanner.Scan()
    
    
  • 相关阅读:
    电脑处理器i5和i7的区别,如何选择?
    趣漫揭秘!中国程序员生存现状?
    趣漫揭秘!中国程序员生存现状?
    程序员职业规划
    程序员职业规划
    盘点程序员开发遇到的30个问题
    盘点程序员开发遇到的30个问题
    推荐VSCode12个比较实用的插件
    Flask之模板之宏、继承、包含
    Flask之模板之控制语句
  • 原文地址:https://www.cnblogs.com/KevinGeorge/p/9220357.html
Copyright © 2011-2022 走看看