首页
社区
课程
招聘
[原创]分享一个对抗JUMPOUT的小技巧
2020-4-22 14:52 21463

[原创]分享一个对抗JUMPOUT的小技巧

2020-4-22 14:52
21463
    本人小菜一枚,虽然技术不咋地,但是对一些事物比较有耐心并且善于观察,偶尔会因为自己的细心获得一些额外的小收获;今天我就来分享一个小技巧,不是什么高大上的技巧,但相信很多人在逆向过程中都遇见过;该技巧用来对抗JUMPOUT,它对于我这样的小白来说还是挺有用的,如果你和我一样小白可以以这种方法试试,大佬嘛, 你就一笑而过吧,哈哈!
    前几天看见有人发sig3算法的帖子,帖子是好帖子写的不错;算法中对于so的保护用到了和阿里差不多的技术,技术细节这里不在赘述了;但看见有人用临时账户留言说是四年前的技术,于是勾起了我的好奇心;回想过去曾经尝试逆向sgmain三个不同版本6.3.80、6.4.36、6.4.176,我内心的感觉是老版本破解难度要远远强于新版本,老版本应用了很多技术,就混淆这块就有cfg对抗(我也不知道专业人士怎么叫)、动态跳转、跳转表、动态参数、fla、很多混淆花指令等,而新版本好像只用了fla、 cfg对抗技术。于是我下载了一个比较新的版本6.4.1229来看,发现和6.4.176没啥变化。
    那既然变化不大,看来四年前的技术不是指sgmain那一套,可能指的新技术指的是avmp吧,可是我怎么都感觉avmp和livteVM纠缠在一起,本人实在才疏学浅,就不钻牛角尖了。
    进入正题,现在我就来分享这个对抗技巧,关于它是啥原理我这里就不再描述了,想得到专业描述你最好google去;先看一下对抗前的效果图(以最新的 6.4.1229 为例):


从上面两幅图,我们可以清楚的看到ida无法给我们分析出完成的cfg了,但是别急ida要远比我们想象的聪明,你看第一幅图

ida给我们算出了一个JMMPOUT的地址,这里是F5D0,这个F5D0是不是值得思考一下,在看汇编代码

不巧,这个BX R5的最终结果就是这个 F5D0,哦,哦,哦,扫噶,看来ida还是挺聪明的,那我们把它patch成跳转到F5D0后会怎么样呢?我先给你们附上代码:
def put_unconditional_branch(source, destination):
    offset = (destination - source - 4) >> 1
    if offset > 2097151 or offset < -2097152:
        raise RuntimeError("Invalid offset")
    if offset > 1023 or offset < -1024:
        instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
        instruction2 = 0xb800 | (offset & 0x7ff)
        PatchWord(source, instruction1)
        PatchWord(source + 2, instruction2)
    else:
        instruction = 0xe000 | (offset & 0x7ff)
        PatchWord(source, instruction)



put_unconditional_branch(here(), 0xF5D0)
没错就修改代码这一行
修改后我们f5发现,ida没变化,是ida喝多了嘛?不不不,我们需要继续帮助ida分析;我们把鼠标放在JNI_OnLoad块上,点ida的edit
functions->delete function, 然后在 JNI_OnLoad起始处按p(创建函数),在f5,哦,不错哦,效果如下(屏幕太大截取一部分):

我们发现ida帮我们识别了很大一部分code,这里有个细节需要说明一下,你f5后可能没有达到我这种效果,可能是这样的:

为什么呢?原因在于ida在重新建立函数时遇到其他函数头分析就结束了,我们需要帮助它,先删除那些被ida错误分析的函数块,在通过ALT+P编辑函数修改JNI_OnLoad的函数尾;这里我就传授给你们一下ALT+P的使用大法,一般人你发现不了,哈哈
// ida alt+p 修改函数开始和结束地址;如修改结束地址,这个地址必须不再另外一个函数内,如果在需要先删除那个函数
// 在修改,才能成功

f5和我图中一样效果后,我们发现还是有一些JUMPOUT,而且这次的JUMPOUT没有给出要跳转的具体偏移;看来ida只能计算直接赋值的情况,对于间接赋值的,它无能为力,没关系,我们帮助它,看这个JUMPOUT
它给我们算出了一部分F636,但是后面的加值(v29)它不知道,我们跳转到 F636看看汇编代码

r4 = ca - b4 = 0x16,eors r4, r5,看来它不知道r5的值(这个r5就对应伪代码中的v29),r5来自r0,追溯到函数顶部r0 = 0x9d, 即0x9d ^ 0x16 = 8b, 8b + F634 = F6BF(具体追溯过程我就不讲了,都很好找),继续patch,继续删函数继续创建函数(主要thumb还是arm,注意偏移),哟,效果不错哦,只剩下一个JUMPOUT了:


继续步骤二操作,63391对应16进制数为F79F,很明显 ida算出了0xF780 + 0x1f = F79F,但它不知道r4的值,我们需要帮助它确定(也就是伪代码中v30的值)


很明显r5还是0x9d,所以F79F + 0x9d = F83C, 继续patch,继续删函数继续创建函数(主要thumb还是arm,注意偏移),哟,效果不错哦,好像没有JUMPOUT了哦:


我说这是fla,你还有什么话说,哈哈, 确实这个也是4年前的技术,哈哈,伪代码太多,这里就不截图了,但我随便截一个内部的函数伪代码的图吧:



至此完美收工,技术要点:

1、遇见JUMPOUT就patch

2、ida会帮我们解析出一些跳转的偏移,它解析不了的,我们需要帮助它

3、记得删除函数块和新建函数块,同时有些时候你需要帮助ida确定函数尾

4、我的代码不能patch所有地方,每遇到一个JUMPOUT,你需要修改偏移,然后手动patch(因为它们的JUMPOUT特征不固定,想完美patch,需要完美的patch代码,哈哈,不过它一个函数JUMPOUT的地方还不是很多,你按我的方法做也不累)

5、至于fla嘛,你随意吧,网络上对抗fla的帖子还是挺多的,另外想动态调试可以忽略它




[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2020-4-22 14:54 被angelToms编辑 ,原因:
收藏
点赞15
打赏
分享
最新回复 (31)
雪    币: 997
活跃值: (415)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
上海刘一刀 2 2020-4-22 15:34
2
0
学习了  数字壳也很多 jumpout
雪    币: 2330
活跃值: (1104)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
FraMeQ 2020-4-22 15:41
3
0
mark
雪    币: 225
活跃值: (1487)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_0xC05StackOver 2020-4-22 15:45
4
0
。。。
最后于 2020-4-22 15:52 被wx_0xC05StackOver编辑 ,原因:
雪    币: 344
活跃值: (314)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hasking 2020-4-22 15:47
5
0
学到了 谢谢。 ida把寄存器调用翻译成 jmpout 是算优化了吧
雪    币: 1759
活跃值: (2309)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
又见飞刀z 2020-4-22 15:53
6
0
几个月前的问题终于得到了解决,感谢大佬
雪    币: 758
活跃值: (78)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
壹久玖 2020-4-22 16:12
7
0
mark
雪    币: 19586
活跃值: (60093)
能力值: (RANK:125 )
在线值:
发帖
回帖
粉丝
Editor 2020-4-22 16:29
8
0
感谢分享哦~
雪    币: 29
活跃值: (499)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
万抽抽 2 2020-4-22 20:59
9
0
看好楼主!因为某些原因没能跟楼主共事,但技术能力是杠杠的,有需要逆向安全人才的大佬们,赶快联系吧。
雪    币: 3040
活跃值: (1151)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
angelToms 2 2020-4-22 21:09
10
0
万抽抽 看好楼主!因为某些原因没能跟楼主共事,但技术能力是杠杠的,有需要逆向安全人才的大佬们,赶快联系吧。
哈哈,感谢大佬抬爱
雪    币: 35
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
winkar 2020-4-23 10:21
11
0
想请教一下楼主,liteVm是什么?
之前在sgmain里看到过相关的代码,但没找到相关的调用,所以没深究。后来搜了搜也没找到相关的资料。
雪    币: 657
活跃值: (68)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
Fireeye 2020-4-23 11:08
12
0
mark
雪    币: 3509
活跃值: (17979)
能力值: ( LV12,RANK:277 )
在线值:
发帖
回帖
粉丝
0x指纹 5 2020-4-23 15:27
13
0
感谢分享!
雪    币: 224
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
感谢你曾来过 2020-4-23 16:12
14
0
求教 啥事fla和cfg 好多技术名词看不懂
雪    币: 35
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
winkar 2020-4-23 16:18
15
0
感谢你曾来过 求教 啥事fla和cfg 好多技术名词看不懂
fla是ollvm的一个混淆选项,控制流平坦化。
cfg是控制流图。IDA会把代码划分成基本块,再加上单向边组成图。这个图就是CFG。
雪    币: 3040
活跃值: (1151)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
angelToms 2 2020-4-23 19:35
16
0
winkar 想请教一下楼主,liteVm是什么? 之前在sgmain里看到过相关的代码,但没找到相关的调用,所以没深究。后来搜了搜也没找到相关的资料。
liteVM是什么,首先大佬莫笑,我也不知道,可以猜想一下:
1、有没有调用,可以试着在sdk中删除相关java代码,跑一跑
2、sdk源码暴露给我们的是它和InvocationHandler、Proxy有关,用Class.forName显示的加载了一下,没有也没关系
3、在库中你可以找到它的创建code,可能需要还关注一下bb2i34u32clsb
4、另外有些结构比较有意思,它注册了很多,例如:
// DCD aJnigetversion      ; "JNIGetVersion"
// DCD ndiu34h834f+1
// DCD 1
// DCD 1
// DCD 1
// DCD aJnifindclass       ; "JNIFindClass"
// DCD ndi3uq4fh024+1
// DCD 1
// DCD 1
// DCD 1
// DCD aFopen_0            ; "fopen"
// DCD __imp_fopen
// DCD 2
// DCD 1
// DCD 0
// DCD aFreopen_0          ; "freopen"
// DCD __imp_freopen
// DCD 3
// DCD 1
// DCD 0
// DCD a_litevm_printf     ; "_litevm_printf"
// DCD sub_9C19C+1
// DCD 3
// DCD 1
// DCD 1
// DCD a_litevm_fprint     ; "_litevm_fprintf"
// DCD sub_9C240+1
// DCD 4
// DCD 1
// DCD 0
有没有跑偏我不知道,其他就留给想象吧......
最后于 2020-4-27 09:44 被angelToms编辑 ,原因:
雪    币: 1744
活跃值: (3444)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
kzzll 2020-4-23 20:50
17
0
  太厉害了,我要努力学习,跟上大神的步伐。
雪    币: 35
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
winkar 2020-4-24 09:56
18
0
angelToms liteVM是什么,首先大佬莫笑,我也不知道,可以猜想一下: 1、有没有调用,可以试着在sdk中删除相关java代码,跑一跑 2、sdk源码暴露给我们的是它和InvocationHandler、P ...
删除Java代码去找native调用这个思路好,学到了
雪    币: 1084
活跃值: (340)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
东京不热 2020-4-25 13:19
19
0

 

def put_unconditional_branch(source, destination):
    offset = (destination - source - 4) >> 1
    if offset > 2097151 or offset < -2097152:
        raise RuntimeError("Invalid offset")
    if offset > 1023 or offset < -1024:
        instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
        instruction2 = 0xb800 | (offset & 0x7ff)
        PatchWord(source, instruction1)
        PatchWord(source + 2, instruction2)
    else:
        instruction = 0xe000 | (offset & 0x7ff)
        PatchWord(source, instruction)
put_unconditional_branch(here(), 0xF5D0)


楼主这个是python?  请问idc能实现同样的效果吗?你的代码里面好像没有发现while 是肉眼发现一个jumpuot修复一个? 而不是整个so修复 ?
最后于 2020-4-25 13:20 被东京不热编辑 ,原因:
雪    币: 122
活跃值: (1410)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
koflfy 1 2020-4-25 15:24
20
0
mark
雪    币: 259
活跃值: (283)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ZwCopyAll 2020-4-26 09:57
21
0
学习
雪    币: 493
活跃值: (860)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
_air 2020-4-26 11:27
22
0
东京不热 &nbsp;def&nbsp;put_unconditional_branch(source,&nbsp;destination): &nbsp;&nbsp; ...
https://www.anquanke.com/post/id/179080#h2-3楼主抄的这篇文章的代码也没有说一声,具体分析可以看这个文章
雪    币: 3040
活跃值: (1151)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
angelToms 2 2020-4-26 12:22
23
0
_air https://www.anquanke.com/post/id/179080#h2-3楼主抄的这篇文章的代码也没有说一声,具体分析可以看这个文章
我虽然是菜鸡,但你真高抬你自己了,我就是抄了,怎么滴吧,你写的?轮子谁不会造,拿来主义有什么不好?再说我干嘛要说,那是老毛子写的,又不是你写的,还具体分析看那篇文章, 咋能看出花呀?我随便改一下,改成idc,你就不逼逼了?有意思嘛?好像就你会搜索一样,大家连搜索都不会!
最后于 2020-4-26 12:38 被angelToms编辑 ,原因:
雪    币: 493
活跃值: (860)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
_air 2020-4-26 12:47
24
0
angelToms _air https://www.anquanke.com/post/id/179080#h2-3楼主抄的这篇文章的代码也没有说一声,具体分析可以看这个文章 ...
火药味真重
雪    币: 3383
活跃值: (3427)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2020-9-29 14:26
25
0
ida分析x86平台的程序也经常遇见jumpout,我也使用删除函数再创建函数这招,不过我是无意试出来的。。。
游客
登录 | 注册 方可回帖
返回