失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > java获取内存基址_安卓逆向|菜鸟的FRIDA学习笔记:内存读写

java获取内存基址_安卓逆向|菜鸟的FRIDA学习笔记:内存读写

时间:2021-04-05 05:20:58

相关推荐

java获取内存基址_安卓逆向|菜鸟的FRIDA学习笔记:内存读写

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

样本地址:

链接:/s/1y3kIXcBv25QqKjAVzq39CQ提取码:wzqa

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

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

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

this.this$0.null_securityCheck

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

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

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

Java_com_yaotong_crackme_MainActivity_securityCheck000011A8

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

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

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

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

思路:

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

functionmain(){Java.perform(function(){console.log("InsideJavaperform");//读取基址并加上偏移,就是该字符串在内存中的地址varsoAddr=Module.findBaseAddress("libcrackme.so");varpasswordAddr=soAddr.add(0x628c);//菜鸡的我想要一步一步的观察内存中的值console.log(hexdump(passwordAddr,{offset:0,length:64,header:true,ansi:true,}));})}setImmediate(main)

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

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

functionmain(){Java.perform(function(){console.log("InsideJavaperform");//读取基址并加上偏移,就是该字符串在内存中的地址varsoAddr=Module.findBaseAddress("libcrackme.so");varpasswordAddr=soAddr.add(0x628c);//菜鸡的我想要一步一步的观察内存中的值console.log(hexdump(passwordAddr,{offset:0,length:64,header:true,ansi:true,}));console.log(hexdump(newptr(0xca733450),{offset:0,length:64,header:true,ansi:true,}));})}setImmediate(main)

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

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

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

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

运行结果如下:

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

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

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

学习内容:hexdump打印内存

new ptr 构造地址

Memory.readPointer读取指针

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

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

如果觉得《java获取内存基址_安卓逆向|菜鸟的FRIDA学习笔记:内存读写》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。