Frida高级用法

Frida高级用法

首页角色扮演无情剑客更新时间:2024-05-01
多台设备

连接多台设备还是很简单的,使用Frida作者oleavr(很多人称他是大胡子,以后就用这个称呼了)为我门提供的python binding功能。当然前提是相应设备的frida-server已经开了。

根据设备id就可以获取相应设备的device。使用的函数是get_device。

互联互通

互联互通是指把app中捕获的内容传输到电脑上,电脑上处理结束后再发回给app继续处理。看似很简单的一个功能,目前却仅有Frida可以实现。后面的这句话我不清楚是否真假,就我所知道的,它是真的,不过通过这句话也能感受到Firda的强大。

预备知识

•recv([type, ]callback): request callback to be called on the next message received from your Frida-based application. Optionally type may be specified to only receive a message where the type field is set to type. This will only give you one message, so you need to call recv() again to receive the next one.•send(message[, data]): send the JavaScript object message to your Frida-based application (it must be serializable to JSON). If you also have some raw binary data that you’d like to send along with it, e.g. you dumped some memory using NativePointer#readByteArray, then you may pass this through the optional data argument. This requires it to either be an ArrayBuffer or an array of integers between 0 and 255.

App页面

简单的登陆页面如下图:

功能

admin账户不能用来登陆,这个只是在前台进行的校验。对账户密码进行base64编码发送给服务器。

源代码

功能代码:

package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.Base64; import android.view.View; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends AppCompatActivity { EditText username_et; EditText password_et; TextView message_tv; // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { // super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); // Example of a call to a native method //TextView tv = findViewById(R.id.sample_text); //tv.setText(stringFromJNI()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); password_et = (EditText) this.findViewById(R.id.password); username_et = (EditText) this.findViewById(R.id.username); message_tv = ((TextView) findViewById(R.id.textView)); this.findViewById(R.id.login).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (username_et.getText().toString().compareTo("admin") == 0) { message_tv.setText("You cannot login as admin"); return; } //我们hook的目标就在这里 message_tv.setText("Sending to the server :" Base64.encodeToString((username_et.getText().toString() ":" password_et.getText().toString()).getBytes(), Base64.DEFAULT)); } }); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); }

布局代码:

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_height="match_parent" android:layout_width="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="用户名" android:textSize="24sp" /> <EditText android:id="@ id/username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入您的用户名"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="密码" android:textSize="24sp" /> <EditText android:id="@ id/password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入您的密码"/> <TextView android:id = "@ id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请输入用户名和密码" android:textAlignment="center" android:textSize="24sp" /> <Button android:id="@ id/login" android:layout_height="60dp" android:layout_width="wrap_content" android:text="登录" android:layout_gravity="center" android:textAlignment="center" android:textSize="18sp" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

布局类介绍: A ConstraintLayout is a android.view.ViewGroup which allows you to position and size widgets in a flexible way. LinearLayout is a layout that arranges other views either horizontally in a single column or vertically in a single row.

通过hook修改逻辑

(1)实现能够让admin登陆,绕过前台的校验。 (2)将setText中文本发送给电脑端,通过电脑端对数据进行修改,然后把修改后的内容再次发送给手机。也就是互联互通。

python代码(python3.8):

import time import frida import sys import base64 def my_message_handler(message, payload): print(message) print(payload) if message["type"] == "send": print(message["payload"]) data = message["payload"].split(":")[1].strip() print('message:', message) print("burning data:" data) data = str(base64.b64decode(data), "utf-8")# 解码 user, pw = data.split(":") # 提取用户名和密码 data = str(base64.b64encode(("admin" ":" pw).encode("utf-8")), "utf-8") # 组成新的组合并编码,这是使用admin登陆 print("encoded data:", data) script.post({"my_data": data}) # 将JSON对象发送回去 print("Modified data sent") device = frida.get_usb_device() pid = device.spawn(["com.example.myapplication"]) device.resume(pid) time.sleep(1) session = device.attach(pid) with open("conn.js") as f: script = session.create_script(f.read()) script.on("message", my_message_handler) # 注册消息处理函数 script.load() sys.stdin.read()

conn.js代码:

Java.perform(function () { var tv_class = Java.use("android.widget.TextView"); tv_class.setText.overload("java.lang.CharSequence").implementation = function (x) { var string_to_send = x.toString(); var string_to_recv; console.log("send" string_to_send); send(string_to_send); // 将数据发送给PC端 recv(function (received_json_object) { string_to_recv = received_json_object.my_data console.log("string_to_recv: " string_to_recv); }).wait(); //收到数据之后,再执行下去 var string = Java.use("java.lang.String"); string_to_recv = string.$new(string_to_recv);//将收到的数据转化为String类型 return this.setText(string_to_recv); } });

又很多数据通过JavaScript处理起来可能比较麻烦,那么可以考虑把数据发送给PC端,在PC端用python对数据处理就容易多了,处理完成之后再把数据发送回去。

远程调用(RPC)

在 Frida API使用(1) 对RPC进行了介绍。在文章中把js和python代码写在了一个文件中,最好是把他们分开写,这里不再举例。

这个定义还是很重要的: rpc.exports is empty object that you can either replace or insert into to expose an RPC-style API to your application. The key specifies the method name and the value is your exported function.

写在最后

再前面的apk中,通过hook技术很容易绕过了前台的校验,由此可见,前台的校验是多么的不靠谱.这种校验最好都放在后台,

公众号

更多Frida的内容,欢迎关注我的微信公众号:无情剑客.

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved