分享一个对抗JUMPOUT的小技巧
2020-04-23 14:03:35 Author: bbs.pediy.com(查看原文) 阅读量:390 收藏

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

22小时前 603

    本人小菜一枚,虽然技术不咋地,但是对一些事物比较有耐心并且善于观察,偶尔会因为自己的细心获得一些额外的小收获;今天我就来分享一个小技巧,不是什么高大上的技巧,但相信很多人在逆向过程中都遇见过;该技巧用来对抗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的帖子还是挺多的,另外想动态调试可以忽略它

[培训]《安卓高级研修班(网课)》6月班开始招生!一年后遇见不一样的自己!(现在进入看雪课程可以试看两节)

最后于 22小时前 被angelToms编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-259062.htm
如有侵权请联系:admin#unsafe.sh