Native开发与逆向第一篇-字符串

news2024/11/17 7:10:09

开发

Android studio新建项目

Android studio新建一个Native C++项目。
默认代码就是调用Native 方法stringFromJNI 返回一个字符串。

public native String stringFromJNI();

C++ 代码

stringFromJNI 函数的代码,默认使用的是静态注册的方式,静态注册是函数格式就是Java_函数路径。
代码很简单,定义一个字符串hello,调用NewStringUTF转成java字符串返回。
注意看参数,java方法是不带参数的,native函数里面有2个参数,一个是JNIEnv ,一个是jobject 。
如何java层是静态方法,那这里第二个参数就不是jobject 而是 jclass了。
参数这个点是逆向的时候需要注意的。
JNI的基础知识感兴趣的自行学习,这里不展开讲了。

extern "C" JNIEXPORT jstring JNICALL
Java_com_mycode_nativehello_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

动态注册

相对静态注册,动态注册的方式函数名字就可以是自定义的。
逆向的话就需要找动态注册的地方,比静态注册稍微安全一点。

jstring xxaa(JNIEnv *env, jobject instance) {
    std::string hello = "Hello from C++ , 这是动态注册";
    return env->NewStringUTF(hello.c_str());
}

jint RegisterNatives(JNIEnv *env) {
    jclass clazz = env->FindClass("com/mycode/nativehello/MainActivity");
    if (clazz == NULL) {
        return JNI_ERR;
    }

    JNINativeMethod methods_MainActivity[] = {
            {"stringFromJNI", "()Ljava/lang/String;", (void *) xxaa}
    };

    return env->RegisterNatives(clazz, methods_MainActivity,
                                sizeof(methods_MainActivity) / sizeof(methods_MainActivity[0]));
}

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    jint result = RegisterNatives(env);
    return JNI_VERSION_1_6;
}

逆向

ida反编译so

将上面的demo编译好之后apk的lib目录下会生成so文件,分别是arm 和 x86的 32位和64位。
这里主要分析arm64

arm64 汇编

在这里插入图片描述
主要代码就下面三行
ADR指令将内存中的值取到寄存器,这个字符串 ida 已经自动识别出来。
然后是调用std::string::basic_string 和 NewStringUTF ,和源码都能一一对上。

ADR             X1, aHelloFromC ; "Hello from C++"
...
BL              ._ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2B7v170000IDnEEPKc ; std::string::basic_string<decltype(nullptr)>(char const*)
...
BL              ._ZN7_JNIEnv12NewStringUTFEPKc ; _JNIEnv::NewStringUTF(char const*)

F5伪代码

TAB切换到伪代码界面,伪代码里面没有"Hello from C++" 字符串。这是为什么呢?

__int64 __fastcall Java_com_mycode_nativehello_MainActivity_stringFromJNI(_JNIEnv *a1)
{
  const char *v1; // x0
  __int64 v3; // [xsp+18h] [xbp-48h]
  char v5[24]; // [xsp+40h] [xbp-20h] BYREF
  __int64 v6; // [xsp+58h] [xbp-8h]

  v6 = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  std::string::basic_string[abi:v170000]<decltype(nullptr)>(); 
  v1 = sub_248A4(v5);
  v3 = _JNIEnv::NewStringUTF(a1, v1);
  std::string::~string(v5);
  _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
  return v3;
}

对比下x86的so
x86的so 正常有"Hello from C++" 字符串,对比上面的arm伪代码区别就在于basic_string的参数。
std::string::basic_string[abi:v170000]<decltype(nullptr)>(v4, “Hello from C++”);

__int64 __fastcall Java_com_mycode_nativehello_MainActivity_stringFromJNI(_JNIEnv *a1)
{
  const char *v1; // rsi
  __int64 v3; // [rsp+18h] [rbp-48h]
  char v4[24]; // [rsp+40h] [rbp-20h] BYREF
  unsigned __int64 v5; // [rsp+58h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  std::string::basic_string[abi:v170000]<decltype(nullptr)>(v4, "Hello from C++");
  v1 = sub_23AF0(v4);
  v3 = _JNIEnv::NewStringUTF(a1, v1);
  std::string::~string(v4);
  return v3;
}

回到arm 伪代码界面,按Y确定。就ok了。
伪代码几乎是和源码差不多的,非常方便逆向分析,主要是有些解析的问题。
在这里插入图片描述

__int64 __fastcall Java_com_mycode_nativehello_MainActivity_stringFromJNI(_JNIEnv *a1)
{
  const char *v1; // x0
  __int64 v3; // [xsp+18h] [xbp-48h]
  char v5[24]; // [xsp+40h] [xbp-20h] BYREF
  __int64 v6; // [xsp+58h] [xbp-8h]

  v6 = *(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  std::string::basic_string[abi:v170000]<decltype(nullptr)>(v5, "Hello from C++");
  v1 = sub_248A4(v5);
  v3 = _JNIEnv::NewStringUTF(a1, v1);
  std::string::~string(v5);
  _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
  return v3;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2052681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】链式结构实现:二叉树

二叉树 一.快速创建一颗二叉树二.二叉树的遍历1.前序、中序、后序遍历&#xff08;深度优先遍历DFS&#xff09;2.层序遍历&#xff08;广度优先遍历BFS&#xff09; 三.二叉树节点的个数四.二叉树叶子节点的个数五.二叉树的高度六.二叉树第k层节点个数七.二叉树查找值为x的节点…

C++ //练习 17.23 编写查找邮政编码的正则表达式。一个美国邮政编码可以由五位或九位数字组成。前五位数字和后四位数字之间可以用一个短横线分隔。

C Primer&#xff08;第5版&#xff09; 练习 17.23 练习 17.23 编写查找邮政编码的正则表达式。一个美国邮政编码可以由五位或九位数字组成。前五位数字和后四位数字之间可以用一个短横线分隔。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#x…

【CTF | WEB】004、攻防世界WEB题目之simple_js

文章目录 simple_js题目描述:题目场景&#xff1a;解题思路 simple_js 题目描述: 小宁发现了一个网页&#xff0c;但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} ) 题目场景&#xff1a; 解题思路 尝试了一下随便输入密码&#xff0c;显示如下&#xff1a; 按下F1…

【高阶数据结构】图

图 1. 图的基本概念2. 图的存储结构2.1 邻接矩阵2.2 邻接表2.3 邻接矩阵的实现2.4 邻接表的实现 3. 图的遍历3.1 图的广度优先遍历3.2 图的深度优先遍历 4. 最小生成树4.1 Kruskal算法4.2 Prim算法 5. 最短路径5.1 单源最短路径--Dijkstra算法5.2 单源最短路径--Bellman-Ford算…

CVE-2024-34982 LyLme Spage六零导航页 任意文件上传漏洞漏洞分析

代码分析 文件位于/lylme_spage/include/file.php。 这是用于图片文件处理的 <?php /** Description: 图片文件处理* FilePath: /lylme_spage/include/file.php* Copyright (c) 2024 by LyLme, All Rights Reserved.*/ header(Content-Type:application/json); require_o…

【Linux基础】Linux中的开发工具(3)--make/makefile和git的使用

目录 前言一&#xff0c;Linux项目自动化构建工具-make/makefile1. 背景2. 依赖关系和依赖方法3. 项目清理4. 使用方法和原理5. .PHONY的作用6. makefile中符号的使用 二&#xff0c;进度条的实现1. 理解回车换行2. 理解行缓冲区3. 版本14. 版本2 三&#xff0c;Linux上git的使…

文件包含漏洞(一)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 一&#xff0c;漏洞简述。 文件包含漏洞&#xff0c;通常发生在Web应用程序中&#xff0c;特别是那些使用用户输入动态生成内容的部分。这种漏洞允许攻击者通过提交恶意的文件路径请…

AI预测福彩3D采取888=3策略+和值012路或胆码测试8月19日新模型预测第61弹

经过60期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;60期一共只错了6次&#xff0c;这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0c;大部…

【Neo4j系列】简化Neo4j数据库操作:一个基础工具类的开发之旅

作者&#xff1a;后端小肥肠 在Neo4j系列我打算写一个Neo4j同步关系数据库、增删改查及展示的基础小系统&#xff0c;这篇文件先分享系统里面的基础工具类&#xff0c;感兴趣的可以点个关注&#xff0c;看了文章的jym有更好的方法可以分享在评论区。 创作不易&#xff0c;未经允…

《勇敢的哈克》开发商:为Xbox移植游戏是一场噩梦

国产类银河恶魔城游戏《勇敢的哈克》开发商Blingame在尝试将游戏移植到Xbox上时&#xff0c;遭遇让人头痛的技术障碍&#xff0c;最终他们只能放弃。《勇敢的哈克》是一款融合了类银河恶魔城元素的末日废土风平台动作游戏。你需要利用多功能能量钩爪组合出独特技能&#xff0c;…

Jenkins使用Publish Over SSH插件远程部署程序到阿里云服务器

前言 使用Jenkins远程构建springboot服务到阿里云上&#xff0c;Jenkins版本&#xff1a;Version 2.462.1 1、准备 在可选插件中&#xff0c;搜索Maven Integration &#xff0c;Gitlab和 Publish Over SSH 三个插件&#xff1a; 如果需要多用户管理那就安装&#xff1a;Ro…

【MySQL进阶之路】表结构的操作

目录 创建表 查看表 查看数据库有哪些表 查看表结构 查看表的详细信息 修改表 表的重命名 添加一列 修改某一列的属性 删除某一列 对列进行重命名 删除表 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 【MySQL进阶之路】MySQL基础——从零认识MySQL-CSDN博客 创…

LLM技术揭秘:Qwen的Function Calling实现解析

简介 Function Calling 是一种让 Chat Completion 模型调用外部函数的能力&#xff0c;可以让模型不仅仅根据自身的数据库知识进行回答&#xff0c;而是可以额外挂载一个函数库&#xff0c;然后根据用户提问去函数库检索&#xff0c;按照实际需求调用外部函数并获取函数运行结…

授权cleanmymac访问全部磁盘 Mac授权访问权限 cleanmymac缺少权限

CleanMyMac是Mac系统下的一款专业的苹果电脑清理软件&#xff0c;同时也是一款优秀的电脑系统管理软件。它能有效清理系统垃圾&#xff0c;快速释放磁盘内存&#xff0c;缓解卡顿现象&#xff0c;保障系统顺畅地运行。 全磁盘访问权限&#xff0c;就好比机场内进行的安全检查。…

Vue3页面组件化开发

本节讲解Vue3页面组件化开发的原因和操作 1.原因 1.业务需求 2.页面展示 根据菜单选项展示不同的页面布局和页面信息 3.页面源码 <template><div class"box"><div class"UserInfo"><div class"UserImg"><img src&…

云计算第三阶段---DBA数据库管理

Day1 一.数据库概述 计算机中数据存放的仓库&#xff0c;可以按数据类型划分数据库&#xff0c;又可以在数据库中划分更细节的分类存放到相应的表中。 抽象来说就是生活中的菜市场、五金店之类的场所&#xff0c;根据用途开设&#xff1b;划分广泛的还有百货商场、批发市场等…

HarmonyOS应用程序访问控制探究

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 一、引言 随着信息技术的飞速发展&#xff0c;移动应用程序已经成为…

【C++】实现日期类相关接口

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇 本篇将介绍实现日期类中众多接口&#xff0c;同时这其中涉及到很多知识&#xff0c;务必将类和对象相关内容掌握再来实现日期类…

【数据结构】详细介绍栈和队列,解析栈和队列每一处细节

目录 一. 栈 1. 栈的概念 2. 栈的实现 2.1 栈的结构 2.2 初始化栈 2.3 入栈 2.4 出栈 2.5 获取栈顶元素 2.6 获取栈中有效个数 2.7 判断栈是否为空 2.8 销毁栈 二. 队列 1. 队列的概念 2. 队列的实现 2.1 队列的结构 2.2 队列初始化 2.3 销毁队列 2.4 入…

聊聊适配器模式

目录 适配器模式概念 主要实现方式 主要组成 UML用例图 代码示例 生活场景 应用场景 适配器模式概念 适配器模式属于结构型设计模式&#xff0c;它的主要目的是将一个类的接口转换成客户端所期望的另一种接口形式&#xff0c;使得原本接口不兼容的类可以一起工作。 主…