有人提出问题,以下汇编f5结果缺失代码:

.text:00000C18 Java_com_a_b_c
.text:00000C18 PUSH {R3,LR}
.text:00000C1A CMP R2, #2
.text:00000C1C BEQ loc_C38
.text:00000C1E CMP R2, #3
.text:00000C20 BEQ loc_C2C
.text:00000C22 CMP R2, #1
.text:00000C24 BNE loc_C32
.text:00000C26 LDR R1, =(aGoldVip - 0xC2C)
.text:00000C28 ADD R1, PC ; "Gold Vip"
.text:00000C2A B loc_C3C
.text:00000C2C ; ---------------------------------------------------------------------------
.text:00000C2C
.text:00000C2C loc_C2C ; CODE XREF: Java_com_a_b_c+8 j
.text:00000C2C LDR R1, =(aCopperVip - 0xC32)
.text:00000C2E ADD R1, PC ; "Copper Vip"
.text:00000C30 B loc_C3C
.text:00000C32 ; ---------------------------------------------------------------------------
.text:00000C32
.text:00000C32 loc_C32 ; CODE XREF: Java_com_a_b_c+C j
.text:00000C32 LDR R1, =(aNormalUser - 0xC38)
.text:00000C34 ADD R1, PC ; "Normal User"
.text:00000C36 B loc_C3C
.text:00000C38 ; ---------------------------------------------------------------------------
.text:00000C38
.text:00000C38 loc_C38 ; CODE XREF: Java_com_a_b_c+4 j
.text:00000C38 LDR R1, =(aSilveryVip - 0xC3E)
.text:00000C3A ADD R1, PC ; "Silvery Vip"
.text:00000C3C
.text:00000C3C loc_C3C ; CODE XREF: Java_com_a_b_c+12 j
.text:00000C3C ; Java_com_a_b_c+18 j ...
.text:00000C3C LDR R2, [R0]
.text:00000C3E MOVS R3, #0x29C
.text:00000C42 LDR R3, [R2,R3]
.text:00000C44 BLX R3 ; NewStringUTF
.text:00000C46 POP {R3,PC}
.text:00000C46 ; End of function Java_com_a_b_c

很容易从汇编看出,这是个简单的 switch…case{} 代码块。在break时,跳转到 loc_C3C 处。

但f5,其结果如下,明显代码缺失:

int __fastcall Java_com_a_b_c(int a1)
{
return (*(int (**)(void))(*(_DWORD *)a1 + 668))();
}

下面分析,为什么代码缺失。

由于 Java_com_a_b_c 是一个 jni 函数,所以 r0 为 JNIEnv*, r1 为 jobject。loc_C3C 位置有个blx r3的跳转,分析一下这是个什么调用。

首选将 r0 指向地址内容即 JNIEnv 赋值 r2,接着 ldr r3, [r2, r3] 将 r3 指向 JNIEnv + 0x29c 偏移的位置(JNINativeInterface 中第167个函数)。

通过查看 jni.h,此时 r3 实际指向的是 NewStringUTF 函数,这个函数有2个变量,分别是 r0:JNIEnv* 和 r1:char* 。其返回值是一个jstring类型。

也就是上面汇编代码大致伪C是这样:

jstring Java_com_a_b_c(JNIEnv *env, jobject thiz, jint x)  {
char *str = NULL;
switch(x) {
case 1:
str = "Gold Vip";
break;
case 2:
str = "Silvery Vip";
break;
case 3:
str = "Copper Vip";
break;
default:
str = "Normal User";
break;
}
return (*env)->NewStringUTF(env, str);
}

switch…case {} 结构去哪儿了? 其实这是ida f5插件的一个特性:***代码优化***。由于使用了 blx r3寄存器跳转,ida并不知道r3即NewStringUTF函数的原型,参数情况。也就不知道str参数会被NewStringUTF函数所使用。因此它认为switch…case {}中对str的赋值(如str = “Copper Vip”;)并没有用,可以优化掉。

因此f5就找不到这段汇编对应的C了。

验证一下f5是否存在代码优化(与-O3编译选项类似):

kiiim@ubuntu:~/Android_prj/re/jni_test$ cat test.c
int main()
{
int x = a();
}
int a()
{
int a = 123;
int b = 22; return 123;
}

对应汇编:

.text:00008304                 EXPORT a
.text:00008304 a ; CODE XREF: main+C p
.text:00008304
.text:00008304 var_C = -0xC
.text:00008304 var_8 = -8
.text:00008304 var_s0 = 0
.text:00008304
.text:00008304 STR R11, [SP,#-4+var_s0]!
.text:00008308 ADD R11, SP, #0
.text:0000830C SUB SP, SP, #0xC
.text:00008310 MOV R3, #0x7B #### int a = 123;
.text:00008314 STR R3, [R11,#var_8]
.text:00008318 MOV R3, #0x16 ### int b = 22; 明显存在2个变量赋值代码
.text:0000831C STR R3, [R11,#var_C]
.text:00008320 MOV R3, #0x7B
.text:00008324 MOV R0, R3
.text:00008328 SUB SP, R11, #0
.text:0000832C LDR R11, [SP+var_s0],#4
.text:00008330 BX LR
.text:00008330 ; End of function a

f5:

signed int a()
{
return 123;
}

那怎么办呢?其实很简单,首先导入 JNINativeInterface 结构的函数原型信息。然后在f5窗口里面, 重新设置 NewStringUTF 函数参数。

在函数上右键 ,*** Force call type ***:

一个简单的 IDA f5插件问题分析的更多相关文章

  1. Arachnid包含一个简单的HTML剖析器能够分析包含HTML内容的输入流

    Arachnid是一个基于Java的web spider框架.它包含一个简单的HTML剖析器能够分析包含HTML内容的输入流.通过实现Arachnid的子类就能够开发一个简单的Web spiders并 ...

  2. 一个简单的MariaDB认证插件demo

    代码地址如下:http://www.demodashi.com/demo/13076.html 一.前言 众所周知(其实可能很多人不知道)MariaDB支持插件认证.在MariaDB中新建用户,常见的 ...

  3. 从0开始写一个简单的vite hmr 插件

    从0开始写一个简单的vite hmr 插件 0. 写在前面 在构建前端项目的时候,除开基本的资源格式(图片,json)以外,还常常会需要导入一些其他格式的资源,这些资源如果没有第三方vite插件的支持 ...

  4. 一个简单web系统的接口性能分析及调优过程

    在测试一个简单系统接口性能压力时,压到一定数量,程序总是崩溃,查看相关机器相关数据时,CPU.内存.IO占用均不高,问题自然出现在其它地方先介绍下系统部件架构 Resin版本为:[root@local ...

  5. 自己写的一个简单的jQuery提示插件

    代码: /** * 2014年11月13日 * 提示插件 */ (function ($) { $.fn.tips = function (text) { var divtipsstyle = &qu ...

  6. 一个简单C程序的汇编代码分析

    几个重要的寄存器 eip - 用于存放当前所执行的指令地址 esp - 栈(顶)指针寄存器 ebp - 基址(栈底)指针寄存器 简单的C程序 int g(int x) { ; } int f(int ...

  7. jquery一个简单的菜单小插件

    刚学会封装插件,先来封装一个小的菜单插件 html部分 <ul class="zong"> <li class="yiji"> < ...

  8. 一个简单的页面弹窗插件 jquery.pageMsgFrame.js

    页面弹窗是网站中常用的交互效果,它可以强提示网站的某些信息给用户,或者作用于某些信息的修改等等功能. 这几天在做一个项目的时候,就顺捎把这个插件写一下,栽棵树,自己乘凉吧. 原创博文,转载请注明出处: ...

  9. 一个简单的Android木马病毒的分析

    一.样本信息 文件名称: 一个安卓病毒木马.apk 文件大小:242867 byte 文件类型:application/jar 病毒名称:Android.Trojan.SMSSend.KS 样本MD5 ...

随机推荐

  1. Python的time和datetime

    #python中时间日期格式化符号 %y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数( ...

  2. Hive的用法

    1.Hive是Hadoop的一个子项目 利用MapReduce编程技术,实现了部分SQL语句.而且还提供SQL的编程接口.Hive推进Hadoop在数据仓库方面的发展. Hive是一个基于Hadoop ...

  3. cpu-z for ubuntu 12.04 64bit : cpu-g

    wget https://launchpad.net/~phantomas/+archive/ppa/+files/cpu-g_0.9.0_amd64.deb sudo dpkg -i cpu-g*. ...

  4. 逆袭之旅DAY14.东软实训.Oracle.多表连接、分组函数、子查询

    2018-07-10 08:29:55 思考应用场景 异常数据的测试 6.显示能挣得奖金的雇员的姓名.工资.奖金,并以工资和奖金降序排列.select ename,sal,commfrom empWH ...

  5. linux入门经验之谈

     一. 选择适合自己的linux发行版 谈到linux的发行版本,太多了,可能谁也不能给出一个准确的数字,但是有一点是可以肯定的,linux正在变得越来越流行, 面对这么多的Linux 发行版,打 ...

  6. linux文件查看

    查看目录 #查看文件 使用  ls  命令,加上参数 -l 表示查看详细信息,-a 表示查看包含隐藏文件在内的文件.也可使用通配符,*代表任意个字符,? 表示单个字符. $ ls ch*.doc #表 ...

  7. 完全卸载vs2013 2015

    /uninstall /force 解压你的vs2013的安装包(iso格式). cd到解压后的文件夹 vs_ultimate.exe /uninstall /force 或者创建一个快捷方式到桌面 ...

  8. 对仿真glbl.v文件的理解

    Simulation, UniSim, SimPrim - How do I use the "glbl.v" module in a Verilog simulation? De ...

  9. IDEA中不同项目配置不同JDK

    安装JDK后,选择其中一个配置环境变量,在IDEA中可以给不同项目选择不同的JDK版本.如下图两个项目:

  10. 多War包合并,jetty测试

    模块间的相互依赖引用配置在pom.xml中加入要依赖的模块即可<dependency>    <groupId>com.exayong</groupId>    & ...