浅谈被加壳ELF文件的DUMP修复
【文章摘要】 本文只讨论如何调试壳体ELF文件包括调试过程中可能遇到的技能应用和解决方案,以及如何恢复加固DEX本文将以加壳程序和加固为目的。注:本文只讨论如何调试壳体ELF文件包括调试过程中可能遇到的技能应用和解决方案,以及如何恢复加固DEX本文将以加壳程序和加固为目的。
一、ELF花样简介
ELF全称:ExecutableandLinkableFormat,是Linux下一种可执行文件模式。
这种文件图案和WINDOWS通常分为两种类型:
1.可执行文件(ExecutableFile),对应PE子类型:EXE
2.共享目的文件(SharedObjectFile),后缀名:.so,对应PE子类型:DLL
二、ELF文件加载可能是一个过程
1.通过SectionHeader或者ProgramHeader加载所需的镜像数据
和WINDOWSPE加载机制不同,ELF内存镜像中不会加载一些文件数据。
2.加载SONEEDLIB和SYM
类似PE的Import_table
3.重定位执行(如有)
类似PE的Reloc_table
4.执行INIT_ARRAY段或者INIT如果有,数组中的地址不等于0xffffffff,0表示完成)
类似PE的TLS,已知的加壳ELF,这两段都泛起了壳代码。
PE中的TLS壳内也经常出现,比如Vmprotect,Execryptor等。
5.执行入口点代码(如有)
所有上述加载过程代码都包括在内linker.so可以参考安卓源码或逆向linker.so
三、ARMCPU简介
1.指令集简介
ARMCPU接纳RISC(简化指令集)架构(X86是CISC,指令等长,相对较大CISC架构加倍省电,执行效率更高。
2.ARM三种类型的指令集
ARM(4字节等长),THUMB(2字节等长),THUMB2(4字节等长)。这三个指令集可以在统一执行程序中切换,切换原则是:
ARM<–>THUMB,THUMB<–>ARM(PC指令集的最高位确定类型:1THUMB;0为ARM)
THUMB<–>THUMB2(由27-31位决议)
thumb2实在就是thumb扩展的目的是完成一个4字节指令的多个2字节指令
3.寄存器
通用寄存器:r0-r15
特殊寄存器:r13=SP(栈地址),r14=LR(函数返回地址),r15=PC(当前指令流地址)
还包罗CPSR,APSR,浮点等寄存器可以详细参考ARM指令集手册。
四、加壳SO的调试
1.ELF代码执行顺序
上面先容了,加壳的SO壳代码都在INIT_ARRAY段和INIT段。
那我们先来看看下一个加壳后的。SO,在linux下面用readelf-a下令查看ELF信息:
在ELF-HEADER里我们看到有Entry,地址为0x22a8。
在动态段看到INIT_ARRAY数组,数组地址为0×21000,巨细是12 BYTES。
用IDA看数组内容:
上面说的,-1无效,0代表竣事,那INIT只有有用地址0×2418这个地址。
也就是说,这个SO加载后会先从0×2418该地址首先执行,执行完成后再执行Entry。
我们来看看某个加固。ELF信息:
在ELF-HEADER我们在里面看到了Entry,地址为0×3860:
IDA打开加固文件时,会提醒错误,不能打开,后面是AntiAntiDebugger会讲为什么。
在动态段看到INIT_ARRAY数组,数组地址为0x28CA4,巨细是8BYTES。
我们也看到了INIT段,地址是0×11401。
在这里,我们总结了执行顺序:
凭据linker的代码,当INIT段和INIT_ARRAY当段都存在时,先运行INIT段,再运行INIT_ARRAY段,否则单独运行相应的指向函数,最终执行ENTRY:
2.自己准备SO_LOADER
调试SO和PE_DLL真正的原则是一样的,都需要宿主的过程,在这里写一篇SO_LOADER,参考代码如下,可通过NDK编译。
3.环境准备
我在这里选择IDA6.6作为调试器。
第一步:将调试器复制到安卓手机上:
下令:adbpushandroid_server/data/local/tmp/and
为什么要把它放在这里?android_server更名成and呢~~~,实在就是为了制止被检测出调试器,后面我在AntiAntiDebugger本部门的内容将详细介绍。
第二步:启动调试器
adbshell回车,进/data/local/tmp/目录,启动调试器,启动后画面。
第三步:重定向调试端口
adbforwardtcp:23946tcp:23946
到目前为止,手机端已经设置好了。让我们看看IDA如何设置内部?
IDA加载我们自己写的so_loader,在854C处,按F2下断点:
在菜单栏中选择Debuger-SelectDebugger,选择RemoteArmlinux/Andoiddebugger
点击OK,然后F9运行:
腾讯哈勃:警惕毕业照短信骗局 暑假安全
在设置内,Hostname内里填入127.0.0.1,点击OK。
如果手机里没有这个文件,会提醒你COPY,点击确定。如果有这个文件,下面的选择就会出现,和平时一样USEFOUND如果您想修改调试程序,请选择COPYNEW笼罩一个新的进去。
然后一起OK,调试状态开始~~,当前PC我们是适才F2设定的断点:
4.若何断住SO的INIT_ARRAY段和INIT段
上面说的,SO的加载在linker.so我们要做的就是把断点设置在里面linker.so内里。
先找代码,IDA打开linker.so,在string窗口里找。
call_constructors_recursive,双击并查看引用:
双击第二个引用处,然后向上找blxr3(init挪用段),b.wxxxxxxxx(init_array段落挪用):
嗯,现在我们找到了地址0x54d0,0x3af0这两个地方,回到适才调试IDA内里。
选择菜单栏debugger-Debuggerwindows-modulelist打开过程模块列表:
linker.so的base是40002000,002000,分为:
0×40002000 0x54d0=0x400074d0
0×40002000 0x3af0=0x40005af0
我们在IDAView-PC窗口GO已往:
在0x74d0处,按C键,酿成代码.新鲜,为什么没有反应?!!底部outputwindow提醒如下:
这是我说的主要问题。正如我上面提到的,调试程序可以在三个指令集之间切换,此时IDA不知道目前要酿成代码的地址是什么ARM照样THUMB,此时,我们需要比较静态,或者你绝对熟悉指令集,看到BYTECODE知道哪种指令集:
静态,显然IDA给2字节指令,一定是THUMB,我们需要将当前地址改为当前地址THUMB。
方法:按键盘ALT G,叫出窗口:
T,DS不用担心,我们只需要VALUE改成1就是THUMB指令集,导致1点击OK以后。
在原地址上泛起CODE16,然后我们再去C一次:
C之后,代码泛起了。!!!ARM和THUMB就这样切换,记住,记住:
看看另一个地址,0x400a5af0,以同样的方式再次:
问题又来了,新鲜,为什么下面不是指令?!这个是IDA的BUG,6.6版本对THUMB2指令在调试状态的剖析就是有问题。。,不外没关系,我们往下看:
这个代码是最重要的,执行每个代码init_array中地址函数,就在blxr2这句。
至此,如何断住?INIT段和INIT_ARRAY段落结束了,剩下的人自己调试。!
五、AntiAntiDebugger
1.AntiIDA
这个问题是真的IDA剖析ELF和linker剖析ELF不一致造成的,IDA加倍严酷。
用ida打开某加固so,提醒:
这个提醒意味着有一个数据形状是无效的。让我们看看是哪个。
SHT说的就是SectionTable,来看看ELF头部数据如下:
shoff就是这个值,我们已经用16进制编辑器看了看:
都是0,显然这里有问题,我们必须先把这个值清除0,保留文件。
再次加载,另有问题,提醒如下:
通过调试IDA的ELF发现插件PROGRAMHEADER当物理偏移大于文件的大小时,就会出现错误。
显然,ProgramHeader第一组数据,p_offset超过文件的大小,凭证ELF将数据偏移定位为0,IDA加载乐成。
2.AntiDebugger
通过调试加壳程序,总结他使用的方法。
方式1:检测父历程的文件名
挪用getppid,获得父亲的过程id,open("/proc/ppid/cmdline")获取父历程名称,检测常用调试器的名字,这就是上面的我COPY为什么要把它放在文件中?android_server造成任何文件名的原因。
对策:修改getppid随便给一个可以用的返回值。
还有其他方法可以获得ppid,好比open("/proc/pid/status"),read这个handle内容,寻找内容ppid也行。
方法2:异常陷阱
和WINDOWS类似的方法,设置一个trap,检测调试器。
对策:IDA默认所有的trap都交给调试器处理,需要修改相应的设置。菜单选择debugger-debuggeroptions,点击editexceptions按钮。
在trap上面,右键编辑可以改成以下内容:
当然,检测调试器的方法有很多,见招拆招就可以了,这里就不详细说明了。
你不知道的黑客世界:近一半单身 10%是处女座