接着输入” chmod 777 /data/local/tmp/android_server” 给android_server加上相应的权限。
接着输入” /data/local/tmp/android_server”启动android_server。
如下图所示:
输入”adb forward tcp:23946 tcp:23946”进行tcp端口转发
命令,启动所要调试的Activity。
app会d出”Waitting for debugger”对话框,如下图所示:
点击”Debug options”按钮,在”Suspend on process entry point”, ”Suspend on thread start/exit”, ”Suspend on library load/unload” 等选项的前面打上勾,如下图所示:
点击”ok”后会在以下对话框的hostname中填上”localhost”
在d出的”Choose process to attach to”窗口中找到”comexampletestjniso”进程,选中该进程,然后点击”ok”按钮。
其中可以看到comexampletestjniso进程的端口为8700。
如下图所示:
在idad出的”Add map”窗口中,一律点击”Cancle”按钮。
点击ida中的暂停调试按钮,暂停当前的调试,如下图所示:
右击libTestJniSoso文件,在d出的框中点击”Jump to module base”,跳转到libTestJniSoso文件的起始地址。
按下Alt+T,d出查找对话框中输入” Java_com_example_testjniso_MainActivity_helloFromJni” 如下图所示:
点击”ok”按钮后,即可跳转到 Java_com_example_testjniso_MainActivity_helloFromJni 函数所在的起始地址。
然后在地址处下断点:
再按F9重新开始调试,点击app中的”点击加载so文件”按钮重新加载libTestJniSoso,即可看到程序成功地停在了断点处:
到此处就可以正常地调试so文件了。
Linker是什么?
Linker就是/system/lib/linker,它是进程启动时第一个加载的模块,它负责管理elf可执行文件以及各个so文件的加载执行,还参与了调试的一些东西。通俗地说,它是一个elf文件的解释器。它可以加载elf可执行文件及so动态库。
在android 50下,不能执行android_server是因为android50自带的linker不支持加载非pie的elf文件,但如果自己实现一个可以加载pie的linker,不就可以解决这个问题了吗?对的,就是酱紫,补上自己的自定义linker在附件
>
写在开头,引用很喜欢的一句话: 要么学!要么不学!学和不学之间没有中间值 不学就放弃,学就要去认真的学! --致选择
为了回溯编译过程(或对程序进行逆向工程),我们使用各种工具来撤销汇编和编译过程,这些工具就叫反汇编器和反编译器。反汇编器撤销汇编过程,因此我们可以得到汇编语言形式的输出结果。反编译器则以汇编语言甚至是机器语言为输入,其输出结果为高级语言。
数组的表示方式是:在基本类型前加上前中括号“[”,例如int数组和float数组分别表示为:[I、[F;对象的表示则以L作为开头,格式是 LpackageName/objectName;
(注意必须有个分号跟在最后),例如String对象在smali中为: Ljava/lang/String; ,其中 java/lang 对应 javalang 包,String就是定义在该包中的一个对象。或许有人问,既然类是用 LpackageName/objectName; 来表示,那类里面的内部类又如何在smali中引用呢?
答案是:在 LpackageName/objectName/subObjectName 的 subObjectName 前加 $ 符号。
方法的定义一般为: Func-Name (Para-Type1Para-Type2Para-Type3)Return-Type
注意参数与参数之间没有任何分隔符,同样举几个例子就容易明白
无序列表的使用,在符号"-"后加空格使用。如下:
> 密码:ftie
Demo
链接: > 密码:u1an
找到so并打开它 因为我的机型是支持arm的所以我这里打开的是armeabi文件夹下的so 如果机型是x86模式的那么这里要打开x86模式下的libJniTestso
编译过程:
按住键盘组合键 shift + f12 打开字符串窗口 这个窗口将会列举出so中所包含的所有字符串 因为上节课我们只编写了一个字符串 所以这里只有一个hello 52pojie! 如果打开的是x86的so这里还会有一些so 但是字符串只有这一个
鼠标点在hello 52pojie!字符串上,打开 Hex dump窗口,修改hello 52pojie!对应内存地址的内容
关于字符对应的16进制可以在百度百科搜索ascii码表 找到字符所对应的16进制
因为我要把hello 52pojie!修改成hello world! 是不是只要找到每个字符所对应的hex修改就好了
这里我看到 hello 52pojie!对应的hex是:68 65 6C 6C 6F 20 35 32 70 6F 6A 69 65 21
我在ascii码表上找到world所对应的十六进制是:77 6F 72 6C 64
所以hello world! 对应的十六进制是:68 65 6C 6C 6F 20 77 6F 72 6C 64 21
注意编辑的时候光标暂停的位置只有先输入字母才能更改成功,修改好后 右键Apply changes应用
退出后保存
此时已经so修改完毕
大功告成,hello 52pojie! --> hello world!
1 对比
上传demo进行加固,解包后对比下原包和加固包,发现加固包在assets文件夹下多了libjiaguso,libjiagu_x86,lib文件夹下多了libjiagu_artso,同时修改了dex文件和AndroidManifest文件
打开manifest文件,看到xxx加固对Application标签做了修改,添加了壳入口,也就是我们反编译后看到的StubApplicationsmali这个文件。
相比于之前版本的加固,自从1xxx加固版本之后,多了几次反调试,使得动态难度稍微增大了一些,不过针对脱壳机脱壳,再多了反调试也是无用。或者通过修改系统源码,也能达到消除反调试的作用。
2 动态调试
(1)把app安装到手机,以调试模式打开app
(2)以shell模式root权限打开IDA的android_server监听
(3)tcp转发
(4)打开IDA,修改配置为在进程开始时下断
(5)搜索到进程后jdwp转发,pid值即为我们进程号,并在命令行下附加。
成功附加后,可以下段了,打开Debugger Option
我们选择在线程开始和库加载时下断,修改成功后,jdb附加,点击运行
程序会断在elf头处,按下G键,搜索mmap,在mmap函数的段首和断尾下段
F9运行,来到断尾时F8单步,
来到此处时,在 BLunk_5C999C2C下断,F9一下,F7跟进去
跟进去今后在BLX LR处进行下断,此处就是进行反调试的地方,原理依然是获取TracePid的值判断当前是不是处于调试状态,建议第一次调试的人在fgets和fopen处下断,再f7跟进此调用就可以看到TracePid的值了。
跟进去之后,我们直接把方法移到最下方,就可以看到kill符号了,这就是杀进程的地方,如果当前处于调试状态,则直接结束进程。
我们在此函数的所有cmpR0,#0处下断,F9一下后即断在断点处,观察寄存器窗口的R0值,实质就是当前的TracePid的16进制的值
不确定的可以使用cat /proc/pid/status进行对比一下,我们直接把R0置0,右键选择Zero Value即可清0,继续F9
我们看到程序又来到了mmap处,继续f9
当继续断在调用反调试功能的方法时,继续F7跟进,依然在所有的cmp R0,#0处下断,断下后把R0清0后继续F9运行
目前的规律是,调用BLXLR的第一次,第二次和第四次是进行反调试判断的,第三次并不影响,可以直接f9跳过去,三次反调试搞定后,就可以愉快的F9运行并观察堆栈窗口了
当看到出现如下所示时:
说明壳已经开始解密并释放dex文件了,我们直接F8单步十几步,最后F9一下就可以看到我们需要的dex头了
直接脚本dump出来即可,最后把libjiagu的所有文件删除,并修复下Application标,如果存在则修复,不存在删除即可
创建 assembler工程然后编译生成test可执行文件
如果是进程已经存在,再去 attach则
可以看到进程test启动了,pid位19879
-找到需要打断点的地方
先找到目标进程test(23946)的段基址
段基址为0xaaaaa000,还要找到关心地址偏移,可以用ida反编译打开看
最后断点的地址 = 段基址 + 偏移 = 0xaaaaa000 + 0x0000065C
然后就可以看到断点断在了0xaaaaa65c,继续n,下一步调试
可以通过 layout reg打开寄存器窗口在强行分析了之后,还是没有办法直接f5还原成伪代码分析。 1一个问题是,用鼠标拖动整个函数,始终没有办法拖动完全,导致无法整个的创建函数。 2 即使拖动完全了,有时也没有办法创建函数,进行分析。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)