作者zeif

用伪造so的方式注入

发布于:2017-09-04 18:32:17 阅读:310 回帖:0


0x0  前言

 

   现在很多安全插件,都会用本地文件和系统的内存进行校验,来防止修改code内存的hook,

 

   或者一些其他的原因,无法注入,无法hook,又不想麻烦的编译android源码,

 

   那我要怎么办呢?

 

   用伪造so的方式注入,

 

   尤其对注入时机比较关注的玩家,这种注入方式最棒

 

   如果hook系统的so,则需要root,

  

   源码在0x5部分


   若是有图片看不清,那就下载附件吧



   

-------------------------------------------------------------------

 

0x1 选择目标so文件,得到导出函数列表

 

      比如我在android 7中,想注入dex2oat来达到不可告人的目的,

 

      我需要用ida打开dex2oat,看看dex2oat都需要哪些so

 

 

      然后选择目标so文件,遵循如下几个标准,

      如果能遵守标准,注入成功的几率就大一些

 

        a.目标so的导出函数最好全部是 C 导出(不强求)

                C++的导出:_Z32register_android_hardware_CameraP7_JNIEnv

                C导出:        register_android_hardware_Camera

 

        b.导出的函数越少越好(不强求)

 

      根据上面的标准,我认为伪造libsigchain.so,最靠谱。

 

      然后需要获得libsigchain.so的导出函数列表,步骤如下

 

      在linux用 readelf -s libsigchain.so 得到导出函数列表,

 

      或者在ida的Export窗口复制粘贴。

 


 

 

      这里要说一下,如果so中的导出函数是C++格式的,那么从ida窗口复制出来的导出函数列表,

      就是不准确的

 

      这里我用 readelf -s libsigchain.so |  grep "13 "    得到libsigchain.so的导出函数列表

 


 

用notepad++,处理一下文本

 

 

得到导出函数表

 

InvokeUserSignalHandler

ClaimSignalChain

UnclaimSignalChain

EnsureFrontOfChain

InitializeSignalChain

SetSpecialSignalHandlerFn

 

------------------------------------------------------------------------------

 

0x2 使用方法

 

    打开notepad++,新建文档,把导出函数表复制进去

 

    复制  __attribute__((visibility("default"))) JmpStruct

 

    用上面介绍的按住alt的方法,一次性粘贴到,导出函数列表前面

 

    并用同样的方法,在末尾把  分号“ ; ” 加上

 

 

    上面的步骤用excel也能轻松做到

 

     经过处理后,得到

 

__attribute__((visibility("default"))) JmpStruct InvokeUserSignalHandler;

__attribute__((visibility("default"))) JmpStruct ClaimSignalChain;

__attribute__((visibility("default"))) JmpStruct UnclaimSignalChain;

__attribute__((visibility("default"))) JmpStruct EnsureFrontOfChain;

__attribute__((visibility("default"))) JmpStruct InitializeSignalChain;

__attribute__((visibility("default"))) JmpStruct SetSpecialSignalHandlerFn;

 

     打开hook_demo.c,把上面的信息,粘贴到对应的位置

 

 

 

 

用同样的方法得到GetProcessAddress( xxxxx );

 

GetProcessAddress( InvokeUserSignalHandler );

GetProcessAddress( ClaimSignalChain );

GetProcessAddress( UnclaimSignalChain );

GetProcessAddress( EnsureFrontOfChain );

GetProcessAddress( InitializeSignalChain );

GetProcessAddress( SetSpecialSignalHandlerFn );

 

并把得到的信息,复制粘贴到,hook_demo.c的my_init(void)函数中的对应位置

 

 

并把,原始libsigchain.so,复制到/system/lib/libsigchain_me.so

 

如果要跑在Android 7上,由于android的本身的安全性的要求,还需要,把引用的so放到导入表中,具体方法参见Android.mk

 

 

----------------------------------------------------------------------------------

 

0x3 编译并替换/system/lib/libsigchain.so


    adb push进去就行了,然后重启机器,让替换生效,

    (别忘了把原始libsigchain.so,复制成/system/lib/libsigchain_me.so)

 

-----------------------------------------------------------------------------------

 

0x4 原理部分

 

    先来看一段汇编代码

 

 

push {pc}   ;把pc入栈(1)

push {r0}   ;把r0入栈,备份r0(2)

push {pc}   ;把pc入栈(3)

pop {r0}   ;把(3)处的pc值赋值给r0

ldr r0,[r0,#16]  ;读取xxxxxxx到r0,xxxxxxx之后会被替换成函数地址

str r0,[sp,#8]  ;用xxxxxxx,替换(1)处的栈中的pc

pop {r0}   ;还原r0(2)

pop {pc}   ;跳转到xxxxxxx函数开始执行

xxxxxxx    ;指向函数的地址

 

    上面的代码,执行之后,会跳转到xxxxxxx函数执行,

 

    这里假设此时的xxxxxxx,就是 原始的libsigchain.so 中的 原始函数InvokeUserSignalHandler

 

    我们在  伪造的libsigchain.so  中,导出  伪造的InvokeUserSignalHandler 函数,

 

    让伪造的InvokeUserSignalHandler在一开始就执行上面的汇编代码,

 

    那么执行之后,就自然而然的跳转到原始的InvokeUserSignalHandler中了,

 

    这样一来,我们的so也注入进去了,原始的系统函数也能得到执行,我们的目的就达到了

 

    在代码中的,JmpCode部分,就是上面的汇编

 

 

 

 

     如何伪造的InvokeUserSignalHandler函数?

 

         在代码中,我定义了一个JmpStruct结构

 

        

 

          我需要,

 

          把    JmpCode    赋值给    JmpStruct.code

 

          把  原始的InvokeUserSignalHandler地址,赋值给    JmpStruct.address

 

          然后,再在代码中,用  JmpStruct  声明  冒牌货InvokeUserSignalHandler 就好了

 


 


 

 

-----------------------------------------------------------------------------------------

 

0x5 show me the fuck code

 

链接: https://pan.baidu.com/s/1hs7WWtu 密码: 9bmy

 

------------------------------------------------------------------------------------------

 

0x6 如何hook  libEGL.so 中的  eglChooseConfig  函数?

 

   这部分由于工作原因,我就不能放源码了,见谅

 

   首先,我们把所有的libEGL.so的导出函数,都用JmpStruct声明,但是就是不声明eglChooseConfig

 


 

然后我们把所有的伪造的libEGL.so函数,都用GetProcessAddress填充一下,但是就是不填充eglChooseConfig

 

 


 

 

然后我们自己实现一个eglChooseConfig函数

 


 

-------------------------------------------------------------------------

 

0x7 完



本文由看雪论坛 zeif 原创

转载请注明来自看雪社区


返回