用ndk制作一个安卓so

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用ndk制作一个安卓so相关的知识,希望对你有一定的参考价值。

做个记录
打开Eclips
File->New->Project
技术图片
选择安卓应用
技术图片
填写名称mytest2ndk
技术图片
然后一路点下去就行,不用选什么,注意不要勾选 Mark this project as a library,生成so的事情在其他地方处理。

然后工程就建好了,接下来右键工程选择android Tools,再选择Add Native Support
技术图片
给so文件起一个名字。
接下来开始写java的native方法,这里有2种方法
技术图片
一种是直接在MainActivity里面写,这里不推荐,因为后面会有坑。
所以建议生成一个新的文件,选择NEW一个CLASS
技术图片
修改NativeClass.java内容

package com.example.my2testndk;

public class NativeClass 
    static
        System.loadLibrary("mytest2ndk");
        

        public native String getTraceIP(String strace_ip);

然后进入工作目录
在win的cmd命令行里面运行javah -classpath bin/classes -d jni com.example.my2testndk.NativeClass
就可以生成头文件
技术图片
注意如果写在MainActivity文件里面,这里会报错不过去,只有把bin/classes改成src或者是绝对路径,很麻烦,还是建立一个新文件好了。
然后jni目录下建一个.cpp文件

#include <jni.h>
#include "com_example_my2testndk_NativeClass.h"

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

char buftext[100] = 0;
const char* getRawSocket(const char* domainIP)

    int recvsockfd = -1;

    if ((recvsockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)/*socket(PF_PACKET,  SOCK_DGRAM, htons(ETH_P_ALL))*/)== -1)  //ipdata recv and send
    
        sprintf(buftext,"error! %d %s\n",errno,strerror(errno));
        return buftext;
    
    sprintf(buftext,"SOCK_RAW ok!\n");
    return buftext;


JNIEXPORT jstring JNICALL Java_com_example_my2testndk_NativeClass_getTraceIP
    (JNIEnv *env, jobject thiz,jstring domainIP) 

    const char* strdomainIP = env->GetStringUTFChars(domainIP, 0);

    return env->NewStringUTF(getRawSocket(strdomainIP));
    

然后打开Cygwin-Terminal,进入工作目录
运行$NDK/ndk-build DK_DEBUG=1 -B V=1

有时候会出现 multiple target patterns. Stop.
把obj下面的删除再编译就行
编译成功后,在libs\armeabi下面会出现so。

然后修改MainActivity.java

package com.example.my2testndk;

import android.app.Activity;
import android.os.Bundle;

import android.widget.TextView;

public class MainActivity extends Activity 
    NativeClass nativeClass;

    @Override
    protected void onCreate(Bundle savedInstanceState) 

        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        setContentView(tv);     
        nativeClass = new NativeClass();
        tv.setText(nativeClass.getTraceIP("8.8.8.8"));
    

这时候我们运行run as/Android application
技术图片
显示权限错误,因为安卓不允许调用runsocket这种底层的功能。
看代码能够理解,这里是想做一个trace的功能,函数无权限,此路不通。

以上是关于用ndk制作一个安卓so的主要内容,如果未能解决你的问题,请参考以下文章

安卓逆向 -- 调用其他APK的SO文件

ndk编译生成so

安卓逆向 -- NDK开发实现MD5算法

制作一个异常的 so 包,并利用 ndk-stack 分析 native 层的 Crash 日志

用NDK生成so给第三方用

将 so|JNI|NDK 之间的关系说明白