freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Adobe Flash过期封禁策略技术分析及应对方法
2021-01-18 22:01:18

前言

事件1

再见,Flash!

2017年7月25日,Adobe 终于官宣了 Flash 的产品寿命结束计划:

2020年12月31日,终止 Flash Player 的开发支持工作;

2021年1月12日,Flash Player 将不再支持播放 Flash 内容;

同时,该公司“强烈建议”所有用户立即在系统中卸载 Flash Player。
image

事件2

Flash 停服引起故障,大连车务段昼夜攻关

事件3

家里的网站也被这个flash屏蔽给搞坏了。
image.png

Flash服务了这么多年,可以说覆盖率相当大,此次停用,等同于埋了一个后门,定时触发“后门攻击”,不同于安全漏洞,它是有意为之。造成的影响不亚于一次供应链攻击。

很好奇,它是如何实现的呢?

分析

分析目的

Adobe在pepflashplayer.dll里如何实现对过期使用的封禁?从安全对抗的角度,这个限制策略是否可以绕过?

分析对象

名称版本md5
pepflashplayer.dll32.0.0.465AF6D91D849B5AD7BF71CE730EF1AC0E0

分析环境

Win10
Chrome 87.0.4280.141

分析工具

BurpSuit Pro
QQAnalyzer
WinDbg Preview
IDA
010 Editor

分析过程

1、寻找突破口

Adobe在其之前发布的几版Flash软件中埋下了逻辑后门,会在2021年1月12日触发,导致代码在此日期之后拒绝渲染任何更多内容。

这颗逻辑后门是否就在flash.dll里呢?

我们当前的dll位置:C:\Users\vinegar\AppData\Local\Google\Chrome\User Data\PepperFlash\32.0.0.465\pepflashplayer.dll

下载一个老版本v26.0.0.131,替换该pepflashplayer.dll,重启chrome,flash渲染正常,可以断定逻辑后门确实在该dll中。

过期使用封禁的策略是怎样的呢?

猜测两个可能,一个是联网状态,获取服务端限制策略,使本地逻辑开关关闭,另一个是获取本地日期,与限制日期比较。

情况一 联网抓包

针对http/https请求,burpsuit未发现可疑请求

针对TCP/UDP请求,QQAnalyzer也未发现可疑请求

也可能看漏了。。。

情况二 日期比较

这种情况,又分4种

(1) 当前日期来自本地,限制日期来自服务端

(2) 当前日期来自服务端,限制日期来自本地

(3) 当前日期来自本地,限制日期来自本地

(4) 当前日期来自服务端,限制日期来自服务端[这种类似情况一,但是直接下发一个开关就好了,没必要从server拿两个日期到client比较]

抓包没有发现,直接修改本地时间到2021.1.12之前,重启浏览器,加载成功。

可以确定,flash获取了本地时间,进行比较。

2、定位系统时间获取函数

Win中可以获取系统时间的方式很多,如何确定目标DLL是如何获取的呢?

可以参考导入函数表

IDA加载pepflashplayer.dll,查看导入函数,time关键字过滤
image

这里关注Get相关函数,有了时间获取函数,可以批量下断,动态调试跟踪逻辑了。

3、定位时间校验逻辑

我们知道chrome是多进程运行,包括浏览器,渲染器和插件程序
image
哪一个才是我们要调试的进程呢?

知识补充:

Adobe Flash Player 

ActiveX:适用于7、Vista、XP系统IE内核浏览器zhi、本地视频、游戏客户端

NPAPI:适用于FireFox(火狐)、Safari(苹果)、Opera (欧dao朋,12.17版以下)

PPAPI:适用于Chromium浏览器、Opera (欧朋,15.00版以上)

我们用的是chrome浏览器,所以目标锁定在上图第三个进程16736,--type=ppapi

WinDbg Preview 附加,lm查看加载模块,果然,我们的分析对象就在这里
image

从实际效果看,Attach方式调试已经晚了,校验逻辑已经执行完毕

如何在时间校验逻辑触发前,就断下来呢?

需要 Launch方式加载chrome.exe,并且调试子进程
image

进入我们需要调试的目标子进程

8:071> |
   0	id: 448c	create	name: chrome.exe
   1	id: 3e30	child	name: chrome.exe
   2	id: 326c	child	name: chrome.exe
   3	id: 1f84	child	name: chrome.exe
   4	id: a60	child	name: chrome.exe
   5	id: 46d8	child	name: chrome.exe
   6	id: 45d0	child	name: chrome.exe
   7	id: 3580	child	name: chrome.exe
.  8	id: 3a24	child	name: chrome.exe
8:071> | 8 s
ntdll!LdrpDoDebuggerBreak+0x30:
00007fff`6b610fcc cc              int     3
8:071> |.
.  8	id: 3a24	child	name: chrome.exe

设置模块加载断点

8:071> sxe ld:pepflashplayer
8:071> g
ModLoad: 00007fff`689c0000 00007fff`68b58000   C:\Windows\System32\gdi32full.dll
ModLoad: 0000016e`9a1d0000 0000016e`9a364000   C:\Windows\System32\USER32.dll
ModLoad: 00007fff`6b400000 00007fff`6b42e000   C:\Windows\System32\IMM32.DLL
ModLoad: 00007fff`67e00000 00007fff`67e0c000   C:\Windows\SYSTEM32\CRYPTBASE.DLL
ModLoad: 00007fff`13b50000 00007fff`15ad4000   C:\Users\vinegar\AppData\Local\Google\Chrome\User Data\PepperFlash\32.0.0.465\pepflashplayer.dll
0000016e`99051734 c3              ret

批量设置获取时间函数断点

8:071> bm KERNEL32!GetSystemTime*
  1: 00007fff`69f5ec90 @!"KERNEL32!GetSystemTimeAdjustmentStub"
  2: 00007fff`69f5a840 @!"KERNEL32!GetSystemTimeStub"
  3: 00007fff`69f56a70 @!"KERNEL32!GetSystemTimeAsFileTimeStub"
  4: 00007fff`69f5e470 @!"KERNEL32!GetSystemTimesStub"
  5: 00007fff`69f625c0 @!"KERNEL32!GetSystemTimePreciseAsFileTime"
8:071> bl
     1 e Disable Clear  00007fff`69f5ec90     0001 (0001)  8:**** KERNEL32!GetSystemTimeAdjustmentStub
     2 e Disable Clear  00007fff`69f5a840     0001 (0001)  8:**** KERNEL32!GetSystemTimeStub
     3 e Disable Clear  00007fff`69f56a70     0001 (0001)  8:**** KERNEL32!GetSystemTimeAsFileTimeStub
     4 e Disable Clear  00007fff`69f5e470     0001 (0001)  8:**** KERNEL32!GetSystemTimesStub
     5 e Disable Clear  00007fff`69f625c0     0001 (0001)  8:**** KERNEL32!GetSystemTimePreciseAsFileTime

截获的时间函数调用很多,如何确定哪一个才是我们要找的呢?

这里有个笨办法,还好被调用的也就8,9次。

每次时间函数断下,修改系统时间,gu放行,再改回系统时间,g放行,查看页面效果,确认哪次修改,会使flash正常工作。

操作发现,GetSystemTimeAsFileTimeStub函数断下后,修改系统时间,可使flash正常工作。但该函数的上层调用位于chrome.dll中,并未在pepflashplayer.dll中。

难道check逻辑是在chrome.dll中?这与我们上面的验证逻辑不符,替换pepflashplayer.dll为老版本,可以正常渲染,难道chrome.dll能判断版本?

继续追溯上层调用发现,

Breakpoint 3 hit
KERNEL32!GetSystemTimeAsFileTimeStub:
00007fff`69f56a70 48ff2571210600  jmp     qword ptr [KERNEL32!_imp_GetSystemTimeAsFileTime (00007fff`69fb8be8)] ds:00007fff`69fb8be8={KERNELBASE!GetSystemTimeAsFileTime (00007fff`685bd100)}
8:071> gu
chrome!ChromeMain+0x867:
00007ffe`f05e5817 4c89f0          mov     rax,r14
8:071> gu
chrome!ChromeMain+0x6b3:
00007ffe`f05e5663 4889f0          mov     rax,rsi
8:071> gu
chrome!RelaunchChromeBrowserWithNewCommandLineIfNeeded+0xae2056:
00007ffe`f492cea6 488b0e          mov     rcx,qword ptr [rsi] ds:00000038`4bffdcf0=002f176961bc531f
8:071> gu
pepflashplayer!IAEModule_IAEKernel_UnloadModule+0x8863a3:
00007fff`14f86f03 f20f5905a5ea1800 mulsd   xmm0,mmword ptr [pepflashplayer!curl_share_strerror+0x134ee0 (00007fff`151159b0)] ds:00007fff`151159b0=408f400000000000
8:071> gu
pepflashplayer!PPP_ShutdownBroker+0x19ef45:
00007fff`13db35d5 0f28f0          movaps  xmm6,xmm0

原来chrome.dll中的上层调用,来自pepflashplayer.dll。

所以是flash.dll从chrome.dll中获取时间,到自己内部做判断。奇怪,它自己读时间不简单嘛?

4、时间校验逻辑分析

基址信息

00007ff6`14d70000 00007ff6`14fa0000   chrome_exe
00007ffe`f05e0000 00007ffe`f9a5c000   chrome
00007fff`13b50000 00007fff`15ad4000   pepflashplayer

GetSystemTimeAsFileTimeStub函数的上层调用函数偏移计算:

内存中chrome.dll的获取时间函数地址:00007ffef05e5817
内存中chrome.dll的基址:00007ffef05e0000
IDA中chrome.dll的基址:180000000
IDA中chrome.dll的获取时间函数地址:00007ffef05e5817-00007ffef05e0000+180000000=180005817

所以GetSystemTimeAsFileTimeStub函数的上层调用位于chrome.dll的sub_180005680函数
image

继续追溯,上层调用位于pepflashplayer.dll的sub_181436EF0函数
image

上层调用位于pepflashplayer.dll的sub_180262FD0函数
image

比对参数就是qword_1815F8468,数值写死
image

分析总结

程序流程

image

时间校验流程

image

思考

时间校验逻辑中的对比数据,硬编码在dll中,直接修改该数据足够大,是否能绕过该check呢?

POC测试

1、定位pepflashplayer.dll中的时间戳硬编码位置: 40 46 3E 6F 77 42
image

2、修改该时间戳硬编码,足够大:FF FF FF FF FF 42
image

3、重启chrome,poc生效,成功

结论

Adobe Flash Player的过期封禁策略,是通过pepflashplayer.dll调用chrome.dll获取系统时间戳,与本地硬编码的时间戳做对比,实现过期无法渲染的逻辑。

有三种方式可以绕过上述校验逻辑:

1、hook上述check函数,修改读取到的系统时间戳;

2、时间戳对比结果值存储于寄存器al,修改该寄存器的值;

3、修改pepflashplayer.dll中的时间戳硬编码,flash未对dll做防篡改校验;

# 黑客 # web安全 # 漏洞分析 # 企业安全 # 网络安全技术
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录