freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

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

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

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

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

前言

事件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安全 # 漏洞分析 # 企业安全 # 网络安全技术
本文为 vinegar 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Freebuf
vinegar LV.1
这家伙太懒了,还未填写个人描述!
  • 1 文章数
  • 0 关注者
文章目录