一、故事背景

现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时。就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的。相比较短视频有一个比较有逼格的编辑工具「Vue」个人已经用了很长时间了,拍出来的视频借助强大滤镜真的很好看,显得逼格也高,更重要的是他有我最喜欢的功能就是可以添加视频背景音乐,选择自己喜欢的音乐,然后还可以编辑这段背景音乐,反正我个人觉的这个是我最喜欢用的产品了。但是好用的东西必定有它不好的地方,因为他真的很强大所以应用就把视频加上了水印,为了更好的宣传作用。

其实有很多视频都是有水印的,比如抖音视频,不过这里顺便说一下抖音视频其实传到服务器上是没有水印的,而在我们保存到本地的时候有水印的。因为开发过视频的人都知道,一般就是借助ffmpeg库添加水印,水印一般都是一张图片。如果抖音后台把视频加上水印一方面是设计版权问题,因为现在很多原创作者一个作品视频会在很多平台发放,那么同样的视频有抖音水印,西瓜水印,快手水印等。再者就是添加水印是有点消耗性能的,抖音现在每天上传视频数量巨大,每个都添加水印服务器压力会很大的。介于这两点抖音没有选择给服务器后台的视频添加水印,只有用户保存到本地的时候把水印在本地添加,所以网上很多人都想去除抖音水印,其实很简单直接抓包然后获取视频原始地址就可以了。不了解抖音的数据协议,可以看这篇文章:Android中分析某音视频协议数据。

二、逆向分析应用

说的有点远了,接着回来看看我们这款应用给的水印问题,其实这个应用没有视频上传功能,就是把本地视频编辑加上滤镜和背景音乐然后在保存到本地,而保存的过程中就把水印给添加上了,所以我们的目的去除水印,那么就在这个过程做手脚就可以了。关于视频添加水印的功能其实网上很多资料,大部分都是借助ffmpeg的库进行操作。先来看看这个应用添加的水印效果吧:

然后我们看看应用的使用过程:

他是通过分段拍摄处理然后合并的操作,直接跳到后面看看保存的地方:

看到这里就在保存视频了,那么添加水印的地方就很有可能在这个地方了,我们借助UI工具直接提取这个进度条的id作为突破口信息:

看到了控件的resid值,然后去jadx中直接搜索R.id.video_view,以后大家都这么搜,如果搜不到在去public.xml中转化成十进制搜索,这里的应用就两个dex不是很大,但是资源很多,大家可以用压缩工具打开apk把res文件夹删了,因为Jadx卡需要解析res下的资源。这里我们不查看res下的东东就直接删除,然后直接打开apk即可,这样也不用多开jadx打开多个dex了:

找到之后点击进入查看详情:

果然看到用到了最常用的TextureVideoView这个是用来处理视频滤镜效果结合ffmpeg的常用手法,不过我们关心的是进度,因为保存肯定有进度的。网上看到自定义了一个矩形动画进度控件,点进去看看:

的确查看到了他有一个更新进度的方法,然后右键查看这个方法的调用地方:

点进去查看详情即可:

看到这里是a.n.a方法通过回调更新进度的,不过这里有个问题就是这个a方法点击跳转失败的,这个之前说过了,因为Jadx可能解析类失败,所以我们需要手动去找这个方法,查看n类型:

有了包名类名就好办了,直接去查看这个类信息:

找到了a方法,看到这里感觉游戏了,保存本地视频的文件有了,继续往下跟进:

这里有断片了,方法点击失败,而且发现多层调用按照包名变量查找太费劲了,直接查看smali代码比较直接,这里记住这个小技巧,当在Jadx中查看一个方法失败可以去查看smali代码:

最后调用的是h类的a方法,再去Jadx中找这个h类:

到这里,就开始豁然开朗了因为我们已经找到最关键的地方了,就是这个执行ffmpeg命令的方法,因为我之前做过视频应用,用ffmpeg做过滤镜效果。所以看到这种代码瞬间就眼前一亮。不过你没做过也没关系,这里可以直接hook操作了:

直接拦截方法,打印参数看结果即可,这里顺便就把我去除水印的几个方法介绍一下吧:

首先我想到的第一个方案是:过滤添加水印的命令参数,因为添加水印的命令网上很多:

那么我就把相关的四个命令给删除了。所以看到我上面的处理命令代码比较简单自己看就好了。不过可惜的是这个方案我执行失败了,我猜想可能是哪个-filter_complex还有其他用途不能直接删除,但是这个命令的参数值太复杂了看得我头疼,所以放弃用了第二个方案:就是在-filter_complex命令参数中修改水印图片的位置,让其超过手机屏幕,这样就看不到水印了,这个方案肯定靠谱的,我们运行这个Xposed模块,然后看看日志:

看到命令被打印出来了,而且看到了默认的水印图片,这个图片地址一定要记住,后面会给出一个更加巧妙的破解方案就是要用到这个地址。看到水印的xy坐标值,我们直接修改:

然后在操作Vue录制视频,发现视频的确没有水印效果了,这里不方便上次视频,大家可以自己操作看效果就好了。

三、解决方案

那么到这里我们大致就搞清楚了这个应用添加水印的流程和技术,主要就是借助ffmpeg库利用命令进行添加水印,我们去除水印的方式比较粗暴就是直接修改水印图片位置。但是到这里就结束了吗?肯定不是因为我们想让每个人都能用到无水印效果的Vue,所以得弄出一个成品apk文件。那么这里有很多思路:

第一个思路:修改smali代码,修改xy值,然后回编译。这个的确是个思路但是我觉得修改smali代码有点费劲。

第二个思路:弄一个空白的水印图片,放在手机的sd卡,然后修改smali代码,替换默认的水印图片地址,这个思路靠谱但是还是需要修改smali代码不方便。

第三个思路:从上面的命令看到那个默认的水印图片存在sd卡的目录,可以直接用空白图片替换这个有水印的图片,这个思路可以,不过可惜的是不可信,因为我们去查看这个目录:

我操作了三次,就产生三张图片,也就说这里每次编辑视频都会从一个地方弄个水印图片后面的数字是变化的,所以这种方案我们没法提前预知图片名字无法完成提前替换。

第四个思路:这个是在第三个思路基础上想到的,也是最终方案。我们从第三个思路中可以看到这个水印图片肯定不是本地用代码生成的,从网上下载下来的可能性也很低,因为是同样的图片,而且没必要从网上获取,所以想了一下发现这图片肯定在本地apk中,那么不多猜想直接解压apk去res下查找:

皇天不负有心人总算被我找到了,也验证了我的猜想,我们对比这个和sd卡中的默认水印图片:

完全一样,肉眼没法辨别了。好了到这里我们就开始大胆尝试吧,弄个空白图片,直接替换res下的水印图片,这样应用内部在使用多个地方使用水印图片都是我们替换之后的空白图片,这个思路还是很巧妙的。

四、二次打包

下面就怎么生成一个空白图片呢?这个不难,谁叫我们会PS呢?打开PS软件,通过上面查看那个res图片的大小尺寸是132*40的:

记得一定要选择透明的,尺寸也是注意是像素单位,然后确定就好了:

然后保存为png格式即可。直接替换原来的水印图片:

这里就替换成功了,开始回编译吧,可惜的是回编译失败。一般现在很多都会回编译失败问题,这类问题我一般都是避免,因为解决的话没个头了。那么我们怎么不反编译就能替换这个文件呢?有的同学会想到直接用解压工具解压apk,然后替换会压缩修改后缀名apk即可。这个你们可以去尝试一下会发现压缩成apk是有问题的,因为路径问题没法这么做的,那么我们该怎么办呢?这个就要借助我的逆向大黄书「Android应用安全防护和逆向分析」的第三章中介绍的aapt命令用法了,还没有购买的同学赶紧入手吧。aapt命令可以用来操作apk文件的,比如查看apk的xml文件,添加删除一个文件到apk中。用aapt命令添加无需解压apk文件的,比如这里我们替换这个文件,可以先删除这个文件,命令如下:aapt remove -v vue.apk res\drawable- www.120xh.cn   xxhdpi-v4\ www.taohuayuan178.com stamp_logo.png;这样就把原始的水印图片删除了,然后在用命令添加我们的空白水印图片:aapt add -v vue.apk res/drawable-xxhdpi-v4/stamp_logo. www.jypt178.cn png 这里有个小小的坑,就是这个命令执行的路径一定要包含res/drawable-xxhdpi-v4/stamp_logo.png文件,而命令中的这个路径是不能变化的,不然添加是失败的。

就这样我们用aapt命令巧妙的替换了水印图片,当然要二次签名了,因为我们替换文件了。二次签名简单不多解释了,这样我们就安装弄好之后的应用,运行都是成功的,这个有点出乎我的意料,应用没做签名校验防止二次打包吗?正当我怀疑的时候,发现问题了,视频滤镜失效了,所以这个应用还是做了检测了。不过没关系,这时候第一眼就要想到我写的爆破工具kstools,不了解这个工具的同学可以查看这里:Android中爆破签名校验问题工具kstools原理解析,这里要注意得先用工具获取正确的原始签名,不然还是失败的,好了这里在继续操作安装吧,这下就可以愉快的操作无水印的高逼格视频编辑工作了。到这里我们就把所有的流程都说完了,内容还是很多的,下面来总结一下本文获取的知识点:

  • 第一、了解了视频添加水印一般都采用ffmpeg库的命令方式添加一张水印图片
  • 第二、使用ps造一个空白png图片
  • 第三、使用aapt命令实现apk包文件的原始操作

Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题的更多相关文章

  1. Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)

    Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码) 来源 https://blog.csdn.net/jiangwei0910410003/article/details/51 ...

  2. Android逆向之旅---静态分析技术来破解Apk

    一.前言 从这篇文章开始我们开始我们的破解之路,之前的几篇文章中我们是如何讲解怎么加固我们的Apk,防止被别人破解,那么现在我们要开始破解我们的Apk,针对于之前的加密方式采用相对应的破解技术,And ...

  3. Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正

    Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正 http://blog.csdn.net/jiangwei0910410003/article/details/51 ...

  4. Android逆向之旅---SO(ELF)文件格式详解(转)

    第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...

  5. Android 逆向实战篇(加密数据包破解)

    1. 实战背景由于工作需要,要爬取某款App的数据,App的具体名称此处不便透露,避免他们发现并修改加密逻辑我就得重新破解了. 爬取这款App时发现,抓包抓到的数据是加密过的,如图1所示(原数据较长, ...

  6. Android逆向之旅---带你爆破一款应用的签名验证问题

    一.前言 在之前的文章中说过Android中的安全和破解是相辅相成的,为了防止被破解.非常多应用做了一些防护策略.可是防护策略也是分等级.一般简单的策略就是混淆代码和签名校验.而对于签名校验非常多应用 ...

  7. Android逆向之旅---基于对so中的section加密技术实现so加固

    一.前言 好长时间没有更新文章了,主要还是工作上的事,连续加班一个月,没有时间研究了,只有周末有时间,来看一下,不过我还是延续之前的文章,继续我们的逆向之旅,今天我们要来看一下如何通过对so加密,在介 ...

  8. Android逆向之旅---SO(ELF)文件格式详解

    第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...

  9. 【我的Android进阶之旅】推荐一款视频转换GIF图片格式的转换工具(Video to GIF)

    一.背景 最近想把一些Android Demo的运行效果图获取下来,但是一直使用真机进行调试,在电脑上不好截取一段gif动画.而之前使用模拟器的时候可以使用 GifCam 工具进行屏幕动画截取.Gif ...

随机推荐

  1. Python数值

    一.python数值类型 python数值类型有以下四种: int(整数) float(浮点数) complex(复数) bool(布尔型) 注意:python3取消了long型.  二.python ...

  2. 吐血分享:QQ群霸屏技术教程2017(维护篇)

    排名上去,并不是终极稳定,日常维护相当重要. 群排名做上去了,如果不去维护,排名很可能会下去,尤其是咱们做了很多群的时候,完全不会留意到. 为什么不稳定? 1.活跃度下去了,排名当然不稳定,这个需要日 ...

  3. Promise 的基础用法

    Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promi ...

  4. python3 练习题100例 (二十八)打印一定范围内的素数

    题目内容: 给定一个大于2的正整数n,打印出小于n(不包括n且n不大于100)的所有素数. 要求将符合条件的输出填入一个列表中,打印的结果为该列表. 输入格式: 共一行,为一个大于2的正整数 输出格式 ...

  5. Codeforces Round #500 (Div. 2) BC

    CodeForces 1013B And CodeForces 1013C  Photo of The Sky B 可以发现只有一次与操作是有意义的,所以答案只有-1,0,1,2四种情况 #inclu ...

  6. hadoop jar x.jar 执行过程

    hadoop jar  x.jar  执行过程 Yarn框架执行内容 1,job.waitforcompletion() 启动 Runjar 进程  -> Resourcemanage申请一个j ...

  7. JAVA学习一 对象数组

    对象数组 今天在写一个代码,才发现自己对于对象数组的理解是不够的,那么就讲讲自己现在的理解. 对于数组中的每一个元素都是一个针对对象的引用 他会指向你的具体的一个堆上的对象,它本身知识一个地址值,与其 ...

  8. Grok Debugger本地安装(转载)

    原文链接:http://fengwan.blog.51cto.com/508652/1758845 最近在使用ELK对日志进行集中管理,因为涉及到日志的规则经常要用到http://grokdebug. ...

  9. WPF 构建无外观(Lookless)控件

    原文:WPF 构建无外观(Lookless)控件 构建一个用户可以使用Template属性设置外观的WPF控件需要以下几步 1.继承自System.Windows.Controls.Control 2 ...

  10. C# String函数

    public static bool IsNullOrEmpty(string value) 如果 true 参数为 value 或空字符串 (""),则为 null:否则为 fa ...