用C来调用so

 

0x0 创建工程html

  1. 创建Android.mk

配置好NDK环境后,直接使用ndk-build来快速生成原生程序。其中mk的配置以下linux

  • LOCAL_PATH := $(call my-dir)   //默认
  • include $(CLEAR_VARS)       //默认
  • LOCAL_ARM_MODE := arm    //arm表示使用32位指令系统
  • LOCAL_MODULE := openso    //生成的原生程序名
  • LOCAL_SRC_FILES := openso.c  //源文件名称
  • include $(BUILD_EXECUTABLE) 

// BUILD_EXECUTABLE表示生成可执行文件(无后缀)shell

// BUILD_SHARED_LIBRARY生成动态库.so文件数组

// BUILD_STATIC_LIBRARY生成静态库.a文件架构

  2. 创建openso.c(注意跟mk里面命名一致)函数

    记录几个比较容易错的地方,ui

  • 由于是利用SO,咱们通常是看IDA里面的伪C代码,

  好比spa

  这里为RC4流密码指针

   

 

  这里的char v4;code

  __gnu_Unwind_2((int)&v1, 10, (int)&v4);

  假如也像IDA这样用,假如真的是访问(&v4)这个地址的一个字节,是没问题的(但也没有初始化),可是这里并非只访问一个字节的内容,还会访问接下来的内容,且会对接下来的内存作改变。这样写代码多半会引起Segmentation fault,有关这个错误,更多可访问Segmentation Fault in Linux

  

因此须要本身分配内存,char * v4 = (char *)malloc(0x102);将&v4替换为v4;

  • 大端小端

  大端模式是指高字节数据MSB存放在低地址处,低字节数据放在高地址处。

  小端模式是指低字节数据LSB存放在低地址处,高字节数据放在高地址处。

 

  这里的key保存为

  v1 = 0x89884546; [sp+4h]

  v2 = 0x87879998; [sp+8h]

  v3 = 0x8765u; [sp+Ch]      //v3的地址最高

  那么写程序时key以小端形式保存,就须要变为

  unsigned char key[] = { 0x46,0x45,0x88,0x89,0x98,0x99,0x87,0x87,0x65,0x87 };

  //数组入栈,从右往左压

 

  具体这方面的知识参考,函数调用方式,CPU中的字节序

  • dlsym的问题

  void * dlsym(void * handle,char * symbol)

  若查找的符号是个函数,那么就返回函数的地址;

  如果个变量,它返回变量的地址;

  若是这个符号是个常量,那么它返回的是该常量的值。

 

  在IDA中须要看Exports表,才是真实的符号

  也能够经过在linux环境下,objdump -T myELFfile  来查看符号表

  • 有关于调用sub_开头的函数

  这个彷佛是没有导出符号的,具体缘由暂时不知道,可是咱们能够经过有符号的函数与它的偏移量来调用它

  好比:                          .text :  00001234 exportfunc

           而sub_1818为:     .text :00001818 sub_1818

  sub_1818 = exportfunc + 0x5E4

  (大体就是这个意思)

  3. ndk-build

  • 将上述的两个文件,放到一个jni文件夹下,cd 到该目录,直接ndk-build,可自动识别,编译。
  • 成功后会发现新出现两个目录libs, obj,所须要的文件就在libs下,这里自动生成了全部的平台的ELF文件,能够根据手机所支持的CPU架构来选择相应ELF
  •  能够用adb shell getprop | grep cpu查看手机所支持的架构

 

  4. 代码

  a)         方案一 是运行解密函数,还须要本身找秘钥

  b)         方案二 运行函数后,直接dump内存就行

方案1:

#include<stdio.h>

#include<stdlib.h>

#include<dlfcn.h>

 

int main()

{

    void *handle;

    char *error;

    int (*func2) (int, signed int, int);

    char * (*func3) (char *, int, int);

    char *v4 = malloc(0x102);

    unsigned char key[] = { 0x46,0x45,0x88,0x89,0x98,0x99,0x87,0x87,0x65,0x87 };

   

   

    handle = dlopen("/data/local/tmp/runso.so", RTLD_LAZY);

    if ((error = dlerror()) != NULL)

    {

        printf("%s",error);

        printf("open so error!\n");

        return -1;

    }

 

 

    func2 = dlsym(handle, "_Z14__gnu_Unwind_2PhiP5str_1");

    if ((error = dlerror()) != NULL)

    {

        printf("open func2 error!\n");

        return -1;

    }

    func2((int)key, 10, (int)v4);

 

 

    char * data = dlsym(handle, "__gnu_Unwind_15");

    if ((error = dlerror()) != NULL)

    {

        printf("open data error!\n");

        return -1;

    }

 

 

    func3 = dlsym(handle, "_Z14__gnu_Unwind_3PhiP5str_1");

    if ((error = dlerror()) != NULL)

    {

        printf("open func3 error!\n");

        return -1;

    }

    func3(data, 0x55BF, (int)v4);

   

 

    FILE * outfile = fopen("/data/local/tmp/out.jar", "wb");

    if (outfile != NULL)

    {

        fwrite(data, 1, 0x55BF, outfile);

    }

    else

    {

        printf("can't create file");

        return -1;

    }

 

    return 0;

}

 

 

方案二:

    #include<stdio.h>

#include<dlfcn.h>

 

int main()

{

    void *handle;

    char *error;

    void *(*func)();//创建一个函数指针

    void *(*sub_func)();

 

    handle = dlopen("/data/local/tmp/runso.so", RTLD_LAZY);

    if ((error = dlerror()) != NULL)

    {

        printf("%s", error);

        printf("open so error!\n");

        return -1;

    }

 

 

    func = dlsym(handle, "_Z15__gnu_Unwind_16v");//随意找了个函数,来定位sub开头的函数

    if ((error = dlerror()) != NULL)

    {

        printf("%s", error);

        printf("open offset func error!\n");

        return -1;

    }

 

 

    int offset = 0x160;//计算出偏移量

    sub_func = func - offset;

    sub_func();//调用sub_1818

 

    char * data = dlsym(handle, "__gnu_Unwind_15");

    if ((error = dlerror()) != NULL)

    {

        printf("open data error!\n");

        return -1;

    }

 

 

    FILE * outfile = fopen("/data/local/tmp/out.jar", "wb");

    if (outfile != NULL)

    {

        fwrite(data, 1, 0x55BF, outfile);

    }

    else

    {

        printf("can't create file");

        return -1;

    }

    return 0;

}
相关文章
相关标签/搜索