FridaHook框架学习(2)
FridaHook框架学习(2)
前言
学习过程参考https://bbs.pediy.com/thread-227233.htm。
逆向分析
安装并运行例子程序,可以看到这个例子是一个验证注册码的程序。
使用jadx解析这个APK。
通过类名以及AndroidManifest可以猜测以及知道LauncherActivity是这个程序的启动类。先看看LauncherActivity的代码。
public class LauncherActivity extends AppCompatActivity {
/* access modifiers changed from: protected */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView((int) R.layout.activity_launcher);
}
public void verifyClick(View v) {
try {
InputStream in = new URL("http://broken.license.server.com/query?license=" + ((EditText) findViewById(R.id.text_license)).getText().toString()).openConnection().getInputStream();
StringBuilder responseBuilder = new StringBuilder();
byte[] b = new byte[0];
while (in.read(b) > 0) {
responseBuilder.append(b);
}
String response = responseBuilder.toString();
if (response.equals("LICENSEKEYOK")) {
String activatedKey = new String(MainActivity.xor(getMac().getBytes(), response.getBytes()));
SharedPreferences.Editor editor = getApplicationContext().getSharedPreferences("preferences", 0).edit();
editor.putString("KEY", activatedKey);
editor.commit();
new AlertDialog.Builder(this).setTitle((CharSequence) "Activation successful").setMessage((CharSequence) "Activation successful").setIcon(17301543).show();
return;
}
new AlertDialog.Builder(this).setTitle((CharSequence) "Invalid license!").setMessage((CharSequence) "Invalid license!").setIcon(17301543).show();
} catch (Exception e) {
new AlertDialog.Builder(this).setTitle((CharSequence) "Error occured").setMessage((CharSequence) "Server unreachable").setNeutralButton((CharSequence) "OK", (DialogInterface.OnClickListener) null).setIcon(17301543).show();
}
}
private String getKey() {
return getApplicationContext().getSharedPreferences("preferences", 0).getString("KEY", "");
}
private String getMac() {
try {
return ((WifiManager) getApplicationContext().getSystemService("wifi")).getConnectionInfo().getMacAddress();
} catch (Exception e) {
return "";
}
}
public void showPremium(View view) {
Intent i = new Intent(this, MainActivity.class);
i.putExtra("MAC", getMac());
i.putExtra("KEY", getKey());
startActivity(i);
}
}
可以通过方法名猜测verifyClick方法应该就是VERIFY按钮的点击事件,showPremium应该就是另一个按钮的点击事件。可以看到程序的逻辑大概为通过网络验证license的正确性,若正确就调用MainActivity的xor方法通过MAC和response生成密钥并保存在本地的preference中。
其中InputStream是Java一个用于读取流的类。SharedPreferences是一个类似Python中字典的一种数据结构。
再来看看MainActivity的代码
public class MainActivity extends AppCompatActivity {
public native String stringFromJNI(String str, String str2);
public static byte[] xor(byte[] val, byte[] key) {
byte[] o = new byte[val.length];
for (int i = 0; i < val.length; i++) {
o[i] = (byte) (val[i] ^ key[i % key.length]);
}
return o;
}
public void onCreate(Bundle savedInstanceState) {
String key = getIntent().getStringExtra("KEY");
String mac = getIntent().getStringExtra("MAC");
if (key == "" || mac == "") {
key = "";
mac = "";
}
super.onCreate(savedInstanceState);
setContentView((int) R.layout.activity_main);
((TextView) findViewById(R.id.sample_text)).setText(stringFromJNI(key, mac));
}
static {
System.loadLibrary("native-lib");
}
}
可以看到显示flag的函数写在了So中,通过密钥KEY和MAC生成。
可以得到Hook思路:Hook getKey方法直接使用MAC和LICENSEOK构造密钥并返回,之后点击PREMIUMCONTENT按钮即可
Hook代码编写
import frida
import sys
jscode = """
Java.perform(function(){
function stringToBytes(str){
var javaString = Java.use('java.lang.String');
var bytes = [];
bytes = javaString.$new(str).getBytes();
return bytes;
}
function bytesToString(bytes){
var javaString = Java.use('java.lang.String');
return javaString.$new(bytes);
}
var launcheractivity = Java.use('de.fraunhofer.sit.premiumapp.LauncherActivity');
var main = Java.use('de.fraunhofer.sit.premiumapp.MainActivity');
var license = "LICENSEKEYOK";
launcheractivity.getKey.implementation = function() {
var mac = this.getMac();
var macbyte = stringToBytes(mac);
var licensebyte = stringToBytes(license);
var xor = main.xor(macbyte,licensebyte);
send(xor)
var key = bytesToString(xor);
send(key.toString());
return key;
}
launcheractivity.verifyClick.implementation = function(v) {
this.showPremium(v);
}
});
"""
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
process = frida.get_usb_device().attach('de.fraunhofer.sit.premiumapp')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()
运行结果
总结
编写js代码的时候是真的累,因为要写在字符串里,没法自动补全,有些变量名就打错了,还全部都是绿绿的很难看出来,终于也看懂了一点js的报错才找出来了。Js中可以通过Java.use使用Java中的一些基类用于灵活转换类型。
FridaHook框架学习(2)的更多相关文章
- FridaHook框架学习(1)
FridaHook框架学习(1) 前言 本次学习过程参考https://bbs.pediy.com/thread-227232.htm Frida安装与使用 Windows端安装 pip instal ...
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...
- Hadoop学习笔记—18.Sqoop框架学习
一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据移植过去并不容易.Apache Sqoop正在加 ...
- Spring框架学习一
Spring框架学习,转自http://blog.csdn.net/lishuangzhe7047/article/details/20740209 Spring框架学习(一) 1.什么是Spring ...
- EF框架学习手记
转载: [ASP.NET MVC]: - EF框架学习手记 1.EF(Entity Framework)实体框架EF是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架 ...
- web框架学习列表
转载自鲁塔弗的博客,原文网址:http://lutaf.com/148.htm web framework层出不穷,特别是ruby/python,各有10+个,php/java也是一大堆 根据我自己的 ...
- 2013 最新的 play web framework 版本 1.2.3 框架学习文档整理
Play framework框架学习文档 Play framework框架学习文档 1 一.什么是Playframework 3 二.playframework框架的优点 4 三.Play Frame ...
- SSH 框架学习之初识Java中的Action、Dao、Service、Model-收藏
SSH 框架学习之初识Java中的Action.Dao.Service.Model-----------------------------学到就要查,自己动手动脑!!! 基础知识目前不够,有感性 ...
- 各种demo——CI框架学习
各种demo——CI框架学习 寒假学习一下CI框架,请各位多多指教! 一.CI的HelloWorld! 注意:CI禁止直接通过文件目录来访问控制器. ./application/controlle ...
随机推荐
- VS2015配置环境支持opencv3库(网络方法总结)
今天安装了opencv3.4.1的版本,之前一直是在ubuntu上做的,本次在windows10上使用VS2015来开发. VS2015是之前安装的,能正常的编译程序. 1. 安装opencv,下载o ...
- ASP.NET Core路由中间件[2]: 路由模式
一个Web应用本质上体现为一组终结点的集合.终结点则体现为一个暴露在网络中可供外界采用HTTP协议调用的服务,路由的作用就是建立一个请求URL模式与对应终结点之间的映射关系.借助这个映射关系,客户端可 ...
- hdp、cdh版本大数据maven仓库
Hdp版本: <repositories> <repository> <id>nexus</id> <name>local private ...
- 建立索引和创建视图(结合YGGL.sql)
一.请按要求对YGGL库建立相关索引 (1)使用create index 语句创建索引 1.对employees表中的员工部门号创建普通索引depart_ind. mysql> create i ...
- 【原创】Linux PCI驱动框架分析(三)
背 景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本 ...
- k8s之API Server认证
集群安全性 在生产环境中,必须保障集群用户的角色以及权限问题,不能给所有用户都赋予管理员权限. 1.集群的安全性必须考虑如下几个目标 (1)保证容器与其所在宿主机的隔离 (2)限制容器给基础设置或其他 ...
- 【对线面试官】Java 反射&&动态代理
// 抽象类,定义泛型<T> public abstract class BaseDao<T> { public BaseDao(){ Class clazz = this.g ...
- Go语言从入门到放弃(设置 go get 为国内源)
前言 Go语言学到 Gin 框架了, 其实每天学习是比较辛苦的事情, 坚持下去! 在使用 Go 过程中发现, 最无奈的是Go的一些模块下不下来, 即便挂了V, 油管2k不卡的那种, 依旧是 time ...
- 【JDBC核心】数据库事务
数据库事务 概述 事务是逻辑上的一组操作,或者说一个独立的工作单元.事务内的语句,要么全部执行成功,要么全部执行失败. 事务处理 数据一旦提交,就不可回滚.数据意味着提交的情况: 当一个连接对象被创建 ...
- LeetCode747 至少是其他数字两倍的最大数
在一个给定的数组nums中,总是存在一个最大元素 . 查找数组中的最大元素是否至少是数组中每个其他数字的两倍. 如果是,则返回最大元素的索引,否则返回-1. 示例 1: 输入: nums = [3, ...