android掉用c的so包就是通过jni
,
应该给你的jar包就是用来调用so包的
。不会让你直接掉so包的放心。so包一般都是为了保证核心代码不被反编译
,另外就是效率高才会用,或者就是开发游戏
。
他们说够用应该是jar包已经和so包的jni调用接口都调好了
,
你用jar包就行了
B. 什么是SO文件
SO文件是linux下共享库文件,它的文件格式被称为ELF文件格式。由于Android操作系统的底层基于Linux系统,所以SO文件可以运行在Android平台上。
Android系统也同样开放了C/C++接口供开发者开发Native程序。由于基于虚拟机的编程语言JAVA更容易被人反编译,因此越来越多的应用将其中的核心代码以C/C++为编程语言,并且以SO文件的形式供上层JAVA代码调用,以保证安全性。
(2)反编译so调用方法扩展阅读:
so文件使用方法:
(1)动态库的编译。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。
命令:$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so不用该标志外部程序无法连接。相当于一个可执行文件。
(2)动态库的链接这里有个程序源文件 test.c 与动态库 libtest.so 链接生成执行文件 test:命令:$ gcc test.c -L. -ltest -o test命令:$ ldd test执行test,可以看到它是如何调用动态库中的函数的。
参考资料来源:网络—SO(软件编程)
C. Linux .so库的使用
新建一个sort.c文件,写一个最简单的排序
使用 gcc -o libsort.so -fPIC -shared sort.c 产生libsort.so库。
.so库有两种调用方法:
新建main.c文件:
使用命令 gcc -o main main.c -lsort -L. 编译。
新建main2.c文件:
使用命令 gcc -o main2 main2.c -ldl 编译。动态加载.so库的话需要-ldl。
运行./main2后输出递增序列,调用成功。
D. 请问安卓的SO文件是怎么回事,可以反编译出源码吗 是如何生成的用JAVA还是C代码生成的
如何JAVA代码调用?
jni吧?
安卓的SO文件是linux下的文件,用c或者c++写的。
E. Android如何调用反编译得到的so
反编译不可以,反汇编可以,这个网络一下你就知道了。反汇编,这没点功力肯定不行的。
如果你改不了这个so文件,要调用此so文件。那么你必须按之前工程的包名、类名、方法名来调用,也就是方法路径必须与原来的一致,因为如果不一致,native方法就不可用了,找不到。
F. 怎样动态调用.so文件中的类方法
相关接口:
#include <dlfcn.h>void *dlopen(const char *filename, int flag);char *dlerror(void);void *dlsym(void *handle, const char *symbol);int dlclose(void *handle);123456789
eg:
dlapi.c
/*
[root@localhost eg]# gcc main.c -Wl,-rpath=./ -ldl -D_TEST
[root@localhost eg]# g++ main.c -Wl,-rpath=./ -ldl -D_TEST
*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <dlfcn.h>#ifdef __cplusplusextern "C" {#endiftypedef int (*PCall_func0)();typedef int (*PCall_func1)(void *);typedef int (*PCall_func2)(void *, void *);typedef int (*PCall_func3)(void *, void *, void *);typedef int (*PCall_func4)(void *, void *, void *, void *);int dynamic_call_library_func0(char *libName, char *funcName)
{
void *handle; void *error;
PCall_func0 selffunc=NULL; int ret; if(libName == NULL)return -9000; if(funcName == NULL)return -9001; //打开动态链接库
handle = dlopen(libName, RTLD_LAZY); if (!handle) { printf("%s\n", dlerror()); return -9000;
}
dlerror(); //获取一个函数
selffunc = (PCall_func0)dlsym(handle, funcName); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); return -9001;
}
ret = selffunc(); //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlclose(handle); return ret;
}int dynamic_call_library_func1(char *libName, char *funcName, void *argv1)
{
void *handle; void *error;
PCall_func1 selffunc=NULL; int ret; if(libName == NULL)return -9000; if(funcName == NULL)return -9001; //打开动态链接库
handle = dlopen(libName, RTLD_LAZY); if (!handle) { printf("%s\n", dlerror()); return -9000;
}
dlerror(); //获取一个函数
selffunc = (PCall_func1)dlsym(handle, funcName); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); return -9001;
}
ret = selffunc(argv1); //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlclose(handle); return ret;
}int dynamic_call_library_func2(char *libName, char *funcName, void *argv1, void *argv2)
{
void *handle; void *error;
PCall_func2 selffunc=NULL; int ret; if(libName == NULL)return -9000; if(funcName == NULL)return -9001; //打开动态链接库
handle = dlopen(libName, RTLD_LAZY); if (!handle) { printf("%s\n", dlerror()); return -9000;
}
dlerror(); //获取一个函数
selffunc = (PCall_func2)dlsym(handle, funcName); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); return -9001;
}
ret = selffunc(argv1, argv2); //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlclose(handle); return ret;
}int dynamic_call_library_func3(char *libName, char *funcName, void *argv1, void *argv2, void *argv3)
{
void *handle; void *error;
PCall_func3 selffunc=NULL; int ret; if(libName == NULL)return -9000; if(funcName == NULL)return -9001; //打开动态链接库
handle = dlopen(libName, RTLD_LAZY); if (!handle) { printf("%s\n", dlerror()); return -9000;
}
dlerror(); //获取一个函数
selffunc = (PCall_func3)dlsym(handle, funcName); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); return -9001;
}
ret = selffunc(argv1, argv2, argv3); //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlclose(handle); return ret;
}int dynamic_call_library_func4(char *libName, char *funcName, void *argv1, void *argv2, void *argv3, void *argv4)
{
void *handle; void *error;
PCall_func4 selffunc=NULL; int ret; if(libName == NULL)return -9000; if(funcName == NULL)return -9001; //打开动态链接库
handle = dlopen(libName, RTLD_LAZY); if (!handle) { printf("%s\n", dlerror()); return -9000;
}
dlerror(); //获取一个函数
selffunc = (PCall_func4)dlsym(handle, funcName); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); return -9001;
}
ret = selffunc(argv1, argv2, argv3, argv4); //dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
dlclose(handle); return ret;
}#ifdef _TESTint main(int rgvs, char **rgva)
{char buff[]="asdfasdf";int x=8;printf("main gcc build\n");printf("g_path gcc libeggcc.so char *\n");
dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show1", buff);printf("g_path g++ libegg++.so char *\n");
dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show1", buff);printf("../lib path gcc libeggcc.so char *\n");
dynamic_call_library_func1("libeggcc.so", "show1", buff);printf("../lib path g++ libegg++.so char *\n");
dynamic_call_library_func1("libegg++.so", "show1", buff);printf("g_path gcc libeggcc.so int\n");
dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show2", &x);printf("g_path g++ libegg++.so int\n");
dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show2", &x);printf("../lib path gcc libeggcc.so int\n");
dynamic_call_library_func1("libeggcc.so", "show2", &x);printf("../lib path g++ libegg++.so int\n");
dynamic_call_library_func1("libegg++.so", "show2", &x); return 0;
}#endif#ifdef __cplusplus}#
dlapi.h
#ifndef _DL_API_H#define _DL_API_H#ifdef __cplusplusextern "C" {#endif/*
使用g++编译的.so库中,函数前必须添加 exter "C"
函数参数类型为指针,不或以为引用
*/int dynamic_call_library_func0(char *libName, char *funcName) ;int dynamic_call_library_func1(char *libName, char *funcName, void *argv1) ;int dynamic_call_library_func2(char *libName, char *funcName, void *argv1, void *argv2) ;int dynamic_call_library_func3(char *libName, char *funcName, void *argv1, void *argv2, void *argv3) ;int dynamic_call_library_func4(char *libName, char *funcName, void *argv1, void *argv2, void *argv3, void *argv4) ;#ifdef __cplusplus}#endif#
eg.c
/*
[root@localhost eg]# gcc eg.c -fPIC -shared -o libeggcc.so[root@localhost eg]# g++ eg.c -fPIC -shared -o libegg++.so*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>int show1(char *src)
{ printf("%s\n", src); return 100;
}int show2(int *x)
{ printf("%2d\n", *x); return 101;
}
eg.cpp
/*
[root@localhost eg]# gcc eg.c -fPIC -shared -o libeggcc.so
[root@localhost eg]# g++ eg.c -fPIC -shared -o libegg++.so
*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>extern "C" int show1(char *src)
{ printf("%s\n", src); return 100;
}extern "C" int show2(int *x)
{ printf("%2d\n", *x); return 101;
}
main.c
/*
[root@localhost eg]# gcc main.c -Wl,-rpath=./ -ldl -D_TEST
[root@localhost eg]# g++ main.c -Wl,-rpath=./ -ldl -D_TEST
*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <dlfcn.h>#include "dlapi.h"int main(int rgvs, char **rgva)
{char buff[]="asdfasdf";int x=8;int ret;printf("main gcc build\n");printf("\ng_path gcc libeggcc.so char *\n");
ret = dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show1", buff);printf("\ng_path g++ libegg++.so char *\n");
dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show1", buff);printf("\ncur lib path gcc libeggcc.so char *\n");
dynamic_call_library_func1("libeggcc.so", "show1", buff);printf("\ncur lib path g++ libegg++.so char *\n");
dynamic_call_library_func1("libegg++.so", "show1", buff);printf("\ng_path gcc libeggcc.so int\n");
dynamic_call_library_func1("/home/workspace/eg/libeggcc.so", "show2", &x);printf("\ng_path g++ libegg++.so int\n");
dynamic_call_library_func1("/home/workspace/eg/libegg++.so", "show2", &x);printf("\ncur lib path gcc libeggcc.so int\n");
dynamic_call_library_func1("libeggcc.so", "show2", &x);printf("\ncur path g++ libegg++.so int\n");
dynamic_call_library_func1("libegg++.so", "show2", &x); return 0;
}
makefile
all:
gcc eg.c -fPIC -shared -o libeggcc.so
g++ eg.cpp -fPIC -shared -o libegg++.so
gcc dlapi.c -ldl -fPIC -shared -o libdlapi.so
g++ main.c -L. -ldlapi -Wl,-rpath=./ -Wl,-rpath=./lib
123456
引用:
网络dlopen(3) - Linux man page
http://tldp.org/HOWTO/C++-dlopen/
错误:
未找到符合
该函数的定义没有链接进.so文件中时,在链接时加上-Wl,-z -Wl,defs参数,可以避免这个问题
G. 安卓软件包内的.so文件如何反编译,重编译
*.so文件是linux平台下的动态链接库,反编译动态链接库参见windows下*.dll文件的反编译,类似的。
H. JavaScript能调用Jar包或者.so库中的代码吗
1.将SO文件直接放到libs/armeabi下,然后代码中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下来就可以直接调用xxx_xxx_xxx()方法;
2.第二种方案,创建自己的SO文件,在自己的SO文件里调用第三方SO,再在程序中调用自己的SO,这种比较复杂,需要建java类文件,生成.h文件,编写C源文件include之前生成的.h文件并实现相应方法,最后用android NDK开发包中的ndk-build脚本生成对应的.so共享库。
2. DEX加壳保护,DEX指令动态加载保护和高级源码混淆保护。其中DEX加壳保护是“爱加密”主推的卖点,该技术通过将DEX文件隐藏,并生成一个类似于虚像的壳文件,阻止黑客利用反编译工具获取App源码。另外,使得C/C++ 层面的代码安全也得到防护。加上资源文件保护(图片、音频等文件的防查看和防修改)、xml 主配文件保护(对主配文件进行二次签名)、内存保护等措施,可以基本保证App的动态和静态安全。
I. 请教一下,SO文件如何反编译最好是WIN环境下搭建。谢谢。
谢谢。。。以前玩过CD版的,我去找找。。。另外SO库和DLL库的逆向近似吗?貌似我查了下,我关注的这个软件转码算法网上还木有。。。是不是也有壳的说法,或者密钥?但离线阅读能实现的功能应该可以逆向,而且是不分文本、通用型转码。