应很多粉丝说到的脱壳,现在就分享一个简单的脱壳图文教程,大家也可以先了解一下,对于有加固的软件都是需要先脱壳才能做逆向分析。
那我们就先看一下这个加固是怎样脱壳的。
首先直接看这个so库:
![50f7fc2e0d8c0641cbe6b533f1b29bf0.png](https://i-blog.csdnimg.cn/blog_migrate/191842888566cd5a9afb438ad0b23101.jpeg)
拖入IDA静态看一下:发现看不到什么信息,原因很简单,因为被处理了;
![c48c69ba1cd27f423a87824b74a2b2d9.png](https://i-blog.csdnimg.cn/blog_migrate/216dbc86aaea2f79ed9332aee1ceb76c.jpeg)
怎么办呢?通过010进行对so简单修改:
拖入IDA,使用ELF.b进行识别:
![85fb9d96d422d755d99d8f1fa78340ac.png](https://i-blog.csdnimg.cn/blog_migrate/5fdc278f33c1334a1d9c2637a6463162.jpeg)
识别效果:
![04784b56dfcb11e3764e883f83dc2ef2.png](https://i-blog.csdnimg.cn/blog_migrate/6930fc733a9e5aaa1522e448b64e5f45.jpeg)
头里面描述了有关节的信息:
![a23c8f4ae164845dca3d57bacd94083e.png](https://i-blog.csdnimg.cn/blog_migrate/7c3a98a645fac200541c022a9ac49fdd.jpeg)
先修改节的偏移:
![8b060f367b06b46bc3afea508d19638a.png](https://i-blog.csdnimg.cn/blog_migrate/ab8d14c86acd99af55e1126544d7f83f.jpeg)
这个三个:
![adaea6b8745d228c7da332d438fad02a.png](https://i-blog.csdnimg.cn/blog_migrate/8e4cf03e658c82f9c0f40fb39bbaa0f1.jpeg)
保存之后,然后继续拖入IDA:发现没报异常,可以识别一些东西:
![4fee640b84f1532c43487981c86a116e.png](https://i-blog.csdnimg.cn/blog_migrate/f7c31a8ecce0dea6c216910ec9352a42.jpeg)
为什么这样就能成功呢?因为我们把节有关的信息去除之后,他开始解析段的信息;
看导出函数列表,发现函数名称也是被处理过的,但是JNI_Load还是可以看到的:
![cd13770b56e9e622fc72aadd319e00fd.png](https://i-blog.csdnimg.cn/blog_migrate/bd21919d3f82d2611647f93e27c78608.jpeg)
双击过来,还是可以看到一些信息的;
![be631b23760c383aae07b373934da1bc.png](https://i-blog.csdnimg.cn/blog_migrate/8c3701340097ca3d4db3a3d7f8822bdb.jpeg)
ctrl+S ,来到这里,看一下:
![8f9b96f4605670903664506d8682a005.png](https://i-blog.csdnimg.cn/blog_migrate/3d0e0c88338b31d81cdd6721a202cb81.jpeg)
点击sub_1AD8:发现也没什么信息~
![cdb70b87be2f2eabed4893c21f84c62e.png](https://i-blog.csdnimg.cn/blog_migrate/5a25d3992230806f28f1954d8d89c1a7.jpeg)
直接F5,看JNI_Load的信息:
![b6e2c1fe237e8d8ba4abbf6c06a2577f.png](https://i-blog.csdnimg.cn/blog_migrate/ebf1d4be56280cb314d93c2883c34e3b.jpeg)
修改一下参数:
![f4f5533e14e5758ef92598504eda0829.png](https://i-blog.csdnimg.cn/blog_migrate/17f06452228ca9c25f78e2860d62d5df.jpeg)
点进去看一下下面的那个函数也看不出来什么;
回到汇编窗口:
![4d8112533a5c6ee359916b5fa374e8bb.png](https://i-blog.csdnimg.cn/blog_migrate/c2a305cf77fcb54e7c8b4a7d71664c01.jpeg)
双击进去后:
![6ff8b1d59428537f21753cad741e72c5.png](https://i-blog.csdnimg.cn/blog_migrate/0b941ee78f6cd118be167697796dc046.jpeg)
继续跟:
![a517997fabbad98f63db7550ebf3b675.png](https://i-blog.csdnimg.cn/blog_migrate/ee6ebda3db93e8c9f63260c5439c778a.jpeg)
过来后:
![66018f388ab2ce32f896d54d7ceb9b35.png](https://i-blog.csdnimg.cn/blog_migrate/8d9e8d027f60a7caaa2a6bbbd68adebd.jpeg)
发现是一个switch循环;
![5995380dc3b59a95c567f30fdfcb400c.png](https://i-blog.csdnimg.cn/blog_migrate/be7af74a0253dbf931f278c60f797fb3.jpeg)
F5一下:
![c9dd815fe20f4c1829f8d1d275613971.png](https://i-blog.csdnimg.cn/blog_migrate/1dbf5c9f6b92e60e83e899fbe471e83f.jpeg)
分支挺长的,看不出来啥;直接动态分析;
这个函数的分析,同样的在open函数下断:
F9之后,加载进来这个so:
![7591d140bd966d057d645600fd9c4076.png](https://i-blog.csdnimg.cn/blog_migrate/8b4ac3b9735ffd6043a3973f2877a6ba.jpeg)
linker处下断:
![b1d73b0583f0cfd692a5f2577f751dd7.png](https://i-blog.csdnimg.cn/blog_migrate/3af95e82ae78341875aedc12eef8b546.jpeg)
libdvm下断:
![28ab396ff56141c9ae12a0373344ada8.png](https://i-blog.csdnimg.cn/blog_migrate/012caa762067438da044aaba538f5e95.jpeg)
F9后,linker处断下:
![8b51e95e749e84ea17b2cfbc66c93115.png](https://i-blog.csdnimg.cn/blog_migrate/547da6d5d6ef6ac998bc8d51f8688ed6.jpeg)
F7进去,发现没什么;
![3b90b42f8b012174f126b931c25b437f.png](https://i-blog.csdnimg.cn/blog_migrate/2328d947918369c1404c471d79bdfebd.jpeg)
继续F9linker断下,然后F7:
![37838c8f356e9b3ae4d2ad012064a921.png](https://i-blog.csdnimg.cn/blog_migrate/a1e2267db152630e5edee9360c363192.jpeg)
F7往下走,发现有个函数:
![7ceb66f7561ff26ead13d5c914091c2b.png](https://i-blog.csdnimg.cn/blog_migrate/9c6119c08425422fc654ef050aa683ac.jpeg)
进入后来到libdvm.so,与getenv有关;
![600987aeca8f34c53e46ea9fcddb9df8.png](https://i-blog.csdnimg.cn/blog_migrate/8d415ff5dc057fd0c667375e35842d93.jpeg)
回来后,继续F7,这里有个函数:
![6028403b7303d49564dea6a742e643a0.png](https://i-blog.csdnimg.cn/blog_migrate/60a6da64380733638c3b08b6b8496e1a.jpeg)
F7进去:往下跟:
![37bb29eae8065eb983000bee06ea5582.png](https://i-blog.csdnimg.cn/blog_migrate/0cf2b45d60b48aebec4bb1c12d87a901.jpeg)
过来后:
![500a95e319f4fb7949cb9771078613a0.png](https://i-blog.csdnimg.cn/blog_migrate/435c873d37506912a210b94ae3c604f5.jpeg)
F7往下,这里有个函数,
![a4763804f0feb294a7a86b98186ac52c.png](https://i-blog.csdnimg.cn/blog_migrate/fed77d34a20b252b3615f5c9d01c5696.jpeg)
进去:F7往下,发现这里是一个循环:一直比较R2和R3的值;
![a71d73ef225d7ad588fe8d1d06bc2b36.png](https://i-blog.csdnimg.cn/blog_migrate/5a33789cb33c774b38048e39ca39f92d.jpeg)
F4后F7往下走,来到了跳转表这里:
![d89db9b5460ec4f80c85a89f666e769a.png](https://i-blog.csdnimg.cn/blog_migrate/efd49ac9e4ef8cf247f4fb039a15985d.jpeg)
继续F7往下,来到了case26分支:
![1b17f806bb9d626285926a6aaa76eb5f.png](https://i-blog.csdnimg.cn/blog_migrate/578e25163bef66395f1673ea69ddbbf4.jpeg)
一路F7往下,这里有一个BLX函数:
![537981e43d7a7c42d20a4699b3a838d9.png](https://i-blog.csdnimg.cn/blog_migrate/d23223d7fed28593d7e9acc2db7b38bf.jpeg)
F7往下,同步R1寄存器;发现有关键字眼;
![7e94a0d9fbcfa79da5a066cebaddcc7e.png](https://i-blog.csdnimg.cn/blog_migrate/d2958042121c13bbed1d7b9417c675c0.jpeg)
再往下是一个循环,同时同步R3寄存器,是在解密字符串:
![6cfa1408fc71ccbed65714343c06cbfb.png](https://i-blog.csdnimg.cn/blog_migrate/0c814807e44b3c8a55c5d33a4c4acb7d.jpeg)
再往下,又一个亦或循环:通过R2寄存器
![5dcc666cca06e402d62ca4132ab37d95.png](https://i-blog.csdnimg.cn/blog_migrate/af9a2ac6ff90e24dcc184c56fa0e29ab.jpeg)
继续F7,
![26ab7ad1b3855a864d033f0c673d75cb.png](https://i-blog.csdnimg.cn/blog_migrate/a81d422f664fa4a3d8b4e6b42ee0f3a7.jpeg)
继续F8往下:来到这里:
![4107dfff3a55920297906c89143438e9.png](https://i-blog.csdnimg.cn/blog_migrate/5ec7b08d83ed897d4bca60b50955c46c.jpeg)
继续F7往下;这里是一个循环,一直在读取,然后一直比较R0的值;
![a43a9c55ad01ef023399df8adffa160a.png](https://i-blog.csdnimg.cn/blog_migrate/a251685db6b665f36da74d9ad2a16386.jpeg)
如果这里BEQ相等的话,就会直接跳到这里:
![bffafa160b63f3e6bc15efd6494e3bda.png](https://i-blog.csdnimg.cn/blog_migrate/10a583a439829985efe835d30b13777a.jpeg)
上面的是从linker到JNI_Load,说明在linker里面没有进行操作,所以,可以换一种,直接在libdvm哪里找到JNI_onload也行;
重新使用一种方法,使用open函数,往上回溯;
跳到open函数, 然后F2下断,然后F9运行,然后Ctrl+F7回溯:
同步R0窗口,出现这个,说明在遍历tracepid,
![03c7cf160d5744c06c14a3b27230a069.png](https://i-blog.csdnimg.cn/blog_migrate/b4b9492fb3288613014e76253ce129bb.jpeg)
继续回溯:
![e5f16ecc7d0579e9b07bb98fab7da7e6.png](https://i-blog.csdnimg.cn/blog_migrate/061acc1fbeb1648c5fad26928c126f27.jpeg)
继续回溯:
![ae9c729dc2a83e5fe032218863ff2073.png](https://i-blog.csdnimg.cn/blog_migrate/c85fd651574992ef635010e362ce6bf9.jpeg)
为什么之前又一次运行道这里程序就崩溃了?
原因是程序此时R1寄存器的值:
![2a568a4d311d0083a017cd001857814e.png](https://i-blog.csdnimg.cn/blog_migrate/29ec9e96dfc0bec4fcfa51e1335869d3.jpeg)
这个值什么意思?
我们先把4A24转化成10进制:18980
执行一个adb命令:这个就是当前as的进程;说明他当前已经检测到我们在调试该程序;
![89e5c1acd99089f5c8f10c653a47aedc.png](https://i-blog.csdnimg.cn/blog_migrate/84473698ea2595953be7fa976875b4c2.jpeg)
所以我们需要把这个反调试干掉:
![6536135f9ea6d0905fef266d0303e153.png](https://i-blog.csdnimg.cn/blog_migrate/eb6bfa88103afe1ebd9c775118a8a3a1.jpeg)
也就是说,case26就是反调试的分支;
![97fd61100319ac4fff4ce1d2eecb3a17.png](https://i-blog.csdnimg.cn/blog_migrate/4220a18f851774f0cf1bf066b7eb6578.jpeg)
改了之后继续往上回溯:
![4e32125dcab16e93ac43c4f7d9e1c5a4.png](https://i-blog.csdnimg.cn/blog_migrate/ab703b3e3aa1f3971e1958ee67d34200.jpeg)
继续回溯,此时来到这个位置;
![45594a585fc64e90951cabbbf6ccaf03.png](https://i-blog.csdnimg.cn/blog_migrate/863fd170485ed141b06e83f0997dbfcb.jpeg)
继续 往上回溯:
此时R0和0进行比较,此时R0的值依然是as的进程号;
![c0063aa3f1244aeebf44c34b3ba34590.png](https://i-blog.csdnimg.cn/blog_migrate/29a546b34089c8cf27c0cb02b0dc757c.jpeg)
如果不相等,就跳转到这里
![9c0c009bb24f019e36dbda0e811e1205.png](https://i-blog.csdnimg.cn/blog_migrate/8e976b68cb9780cfb07d6fbe8271cd94.jpeg)
点进去,发现是kill:
![261707b3899a0df863450b60b0e561fb.png](https://i-blog.csdnimg.cn/blog_migrate/28904aeb3b834a77f35c8d96a6f523ed.jpeg)
会来,往上p一下,是一个函数,
![c15479e9c99cf055b9c024a5bd645870.png](https://i-blog.csdnimg.cn/blog_migrate/a84d2373da645d11788d7acea3259bb6.jpeg)
进去:p一下:
明显和这个就是反调试的逻辑,这个分支代码比较多;
![bc4557f5b2e1613b392f3c691f8f667a.png](https://i-blog.csdnimg.cn/blog_migrate/cc338b82bb1e4c53046376d784fe2fea.jpeg)
我们怎么修改呢,只需要让这个函数返回固定的值即可;
修改代码之前,先把这里置零;
![6f69e76b021c66913a136a8cac28057f.png](https://i-blog.csdnimg.cn/blog_migrate/36605c5c5f8df4aa8536100e438b6d7d.jpeg)
同步一下反汇编窗口,点击前面的这里会显示下面对应的十六进制:
![6f6426b29bccb98f771f4e79d3047f01.png](https://i-blog.csdnimg.cn/blog_migrate/3e3822ca547ef851c5dfde920f92bbb0.jpeg)
这个是arm指令,
执修改指令:第一条:
![68a34ee0744eba07a9e2b5438ae5abea.png](https://i-blog.csdnimg.cn/blog_migrate/2453faa7e77057702d6fce868677d56e.jpeg)
选取后8位,F2进行修改:
![c49d876e9e6bf319d26803e1061c5941.png](https://i-blog.csdnimg.cn/blog_migrate/83a87d036c2db86e8245a7980b5912cc.jpeg)
继续修改第二条:
![2e3b555ac5abd7b9b96f3608612378f2.png](https://i-blog.csdnimg.cn/blog_migrate/4e67462744aa65216cb30964487ff1bd.jpeg)
修改后效果:
![9e9d0e1932e4927be60915193358c502.png](https://i-blog.csdnimg.cn/blog_migrate/56a932b109f773b49c2dd80985017210.jpeg)
过掉反调试后,在mmap处下断:mmap尾部处也下一个断点;
![5eee3ec8ab3802636955f82914bcdf2c.png](https://i-blog.csdnimg.cn/blog_migrate/2533e2a8d11a66bdfa9497c747855b6f.jpeg)
好,F9运行程序:使其在mmap处函数段下来;
![bb2925cba729b1a1684497e57c4ac2fc.png](https://i-blog.csdnimg.cn/blog_migrate/2dd60517236e3906ee4d25953fafef3a.jpeg)
这里mmap如何查看呢?至二级F9运行到mmap函数尾部,然后F7进去下一步,就是不同的函数调用的地方、遇到libdvm.so的不用管,h直接F9继续在mmap处蹲下,只观察jiagu.so;
注意在mmap处的操作:不能直接F9从头部执行尾部断下,要单步跟一下,即将进去的so也要单步跟一半,然后在F9;
继续执行上面操作首先会在这里出现apk信息:
![6d6749d082e4a3081965ac99d90d44ed.png](https://i-blog.csdnimg.cn/blog_migrate/f44b749309ba746136be66c15eda6d66.jpeg)
继续操作,出现了这个:
![7fbc945bc0c7551e1e5cbf770bb41353.png](https://i-blog.csdnimg.cn/blog_migrate/cf716e4e1186caaf138d5f478e21320c.jpeg)
继续:下面R0窗口出现了dey036;
![10b3b92dc7853ce73c3e850975132362.png](https://i-blog.csdnimg.cn/blog_migrate/90116fde72e0f9485427e4b5e75a57aa.jpeg)
继续操作,这里出现了与dex有关的信息:
![2111d9cb90c5f5b8b92a1e8476fa1ab7.png](https://i-blog.csdnimg.cn/blog_migrate/447ee31c6e7428a11e4fa3dc96fac32e.jpeg)
看他地址,我们来到他的区间:
过来后,这几就是他解密后的dex
![8b2a5b425a662cb46cf9ceccacfc3e14.png](https://i-blog.csdnimg.cn/blog_migrate/db353211a9d2241cc411ef6c9168e961.jpeg)
这里是这个dex文件的大小:
![fb3ceb1b0a22077397139d579fbad720.png](https://i-blog.csdnimg.cn/blog_migrate/ffce84a2e921017bd48fd24f9e32ab42.jpeg)
知道起始地址和大小后,使用脚本:
![97721da3932569d0a30c0c689d30ff7b.png](https://i-blog.csdnimg.cn/blog_migrate/f38a5985e4d63dffc3e43b59740c2aac.jpeg)
dump可能需要时间;
也就是说,出现相关dex文件的时候,如果没有出现太多信息,我们可以ctrl+s查看模块信息,一般他会把dex相关信息放到其他区域;
一般会把解密后的dex放到内存里面,比如这个是放在debug里面:
![403fb4d048f08aefe7b0a58b4f546368.png](https://i-blog.csdnimg.cn/blog_migrate/15facc904842b42bfdf1427304facb9c.jpeg)
好,找到dump出来的文件;
![1a1799dcfabc559bf57e50c14a85d811.png](https://i-blog.csdnimg.cn/blog_migrate/dcdd012dd11299f3fea667696f2fc371.jpeg)
拖入jdax,这就是一些相关的代码;
![0edb480eefbca9221bd3c597939a868f.png](https://i-blog.csdnimg.cn/blog_migrate/4b94da22986296fc13cd7396035333be.jpeg)
点看看一下相关的逻辑,发现都有,说明脱壳挺成功的;