用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;

}
相關文章
相關標籤/搜索