安卓逆向|菜鸟的FRIDA学习笔记:内存读写

举报
悦来客栈的老板 发表于 2020/12/28 22:38:40 2020/12/28
【摘要】 这是我自己的学习笔记,比较水,大佬勿喷。 假设你的手机已经root,并已开启frida服务,电脑端已安装好Python,frida,IDA,GDA。 样本地址: 链接: https://pan.baidu.com/s/1y3kIXcBv25QqKjAVzq39CQ 提取码: wzqa 打开软件,界面是这样的: 随便输入"123456",提示"验证码校验失...

这是我自己的学习笔记,比较水,大佬勿喷。

假设你的手机已经root,并已开启frida服务,电脑端已安装好Python,frida,IDA,GDA。

样本地址:

链接: https://pan.baidu.com/s/1y3kIXcBv25QqKjAVzq39CQ 提取码: wzqa

  

打开软件,界面是这样的:

随便输入"123456",提示"验证码校验失败",将APK拖入GDA,查找该字符串,定位到这里:

逻辑很简单,如果执行的是if语句,只校验成功,关键的也就是:

this.this$0.null_securityCheck

  

这个函数,跟进去发现是个native函数:


   
  1. //Package com.yaotong.crackme.MainActivity;
  2. import java.lang.String;
  3. native public boolean MainActivity.null_securityCheck() //method@0016
  4. {
  5. }

将apk中的so拖入到ida,导出函数中发现了这个:

Java_com_yaotong_crackme_MainActivity_securityCheck  000011A8  

  

双击跟进,并按F5,查看C伪码:

导入jni.h,将第一个形参设置为 _JNIEnv 类型,第二个形参设置为 jobject,第三个形参设置为 jstring 类型,对相关函数一波 force call 操作后,代码变成这样:

while循环很明显的就是 字符串的逐个比较,只需要找出 v6位置处的字符串即可,双击 off_628C 跟进:

发现一个"wojiushidaan"的字符串,输入试试,还是提示"验证码校验失败",说明这不是答案,真正的答案应该是动态加载的。如果用IDA调试,会发现它会有反调试,真正考察的也是过反调试。不过我们既然有frida,就不用管这个反调试了。

思路:

既然我们知道了静态时的偏移,那我们通过基址 + 偏移,就是动态时的内存地址,将其读取出来,看看该位置的字符串到底是啥。


   
  1. function main()
  2. {
  3. Java.perform(function() {
  4. console.log("Inside Java perform");
  5. //读取基址并加上偏移,就是该字符串在内存中的地址
  6. var soAddr = Module.findBaseAddress("libcrackme.so");
  7. var passwordAddr = soAddr.add(0x628c);
  8. //菜鸡的我想要一步一步的观察内存中的值
  9. console.log(hexdump(passwordAddr, {
  10. offset: 0,
  11. length: 64,
  12. header: true,
  13. ansi: true,
  14. }));
  15. })
  16. }
  17. setImmediate(main)

用frida Hook后的结果是这样的:

这。。。很明显不是答案啊。不过我们看前四个字节,会发现和内存地址很像(请原谅我还没有学习frida的相关api),因此我们还需要打印下 0xca733450 处的内存,看看是啥:


   
  1. function main()
  2. {
  3. Java.perform(function() {
  4. console.log("Inside Java perform");
  5. //读取基址并加上偏移,就是该字符串在内存中的地址
  6. var soAddr = Module.findBaseAddress("libcrackme.so");
  7. var passwordAddr = soAddr.add(0x628c);
  8. //菜鸡的我想要一步一步的观察内存中的值
  9. console.log(hexdump(passwordAddr, {
  10. offset: 0,
  11. length: 64,
  12. header: true,
  13. ansi: true,
  14. }));
  15. console.log(hexdump(new ptr(0xca733450) ,{
  16. offset: 0,
  17. length: 64,
  18. header: true,
  19. ansi: true,
  20. }));
  21. })
  22. }
  23. setImmediate(main)

新增打印0xca733450内存处的代码后,frida自动运行,结果:

我们将这个 "aiyou,bucuoo"输入后(00是字符串的终止符),结果正确:

我们可以用frida自带的api进行内存的读写,直接帮我们把答案吐出来:


   
  1. function main()
  2. {
  3. Java.perform(function() {
  4. console.log("Inside Java perform");
  5. //读取基址并加上偏移,就是该字符串在内存中的地址
  6. var soAddr = Module.findBaseAddress("libcrackme.so");
  7. var passwordAddr = soAddr.add(0x628c);
  8. var pwd = Memory.readUtf8String(Memory.readPointer(passwordAddr));
  9. console.log(pwd);
  10. })
  11. }
  12. setImmediate(main)

运行结果如下:

如果我们想要在输入"123456"也能成功呢?这时候我们可以修改内存里面的内容,将"aiyou,bucuoo"变成"123456",可以这么操作:


   
  1. function main()
  2. {
  3. Java.perform(function() {
  4. console.log("Inside Java perform");
  5. //读取基址并加上偏移,就是该字符串在内存中的地址
  6. var soAddr = Module.findBaseAddress("libcrackme.so");
  7. var passwordAddr = soAddr.add(0x628c);
  8. Memory.writeUtf8String(Memory.readPointer(passwordAddr),"123456");
  9. var pwd = Memory.readUtf8String(Memory.readPointer(passwordAddr));
  10. console.log(pwd);
  11. })
  12. }
  13. setImmediate(main)

运行后,再此输入 "aiyou,bucuoo",会发现校验失败,如果输入"123456",则会提示成功。这样,我们就顺利的修改了答案。

学习内容:

  1. hexdump打印内存

  2. new ptr 构造地址

  3. Memory.readPointer 读取指针

  4. Memory.readUtf8String 读取参数位置处的字符串(UTF8方式)

  5. Memory.writeUtf8String 将第二个参数(字符串)写入第一个参数位置,修改内存。

参考文章:

https://www.52pojie.cn/thread-608505-1-1.html

https://www.anquanke.com/post/id/195215

文章来源: blog.csdn.net,作者:悦来客栈的老板,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq523176585/article/details/109508049

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。