Linux恶意ELF文件分析

起因是某客户的服务器上,只要一启动server,过不了几秒就被kill,然后错误日志也看不出啥。
server是基于jvm的,怎么看一个进程被哪个进程杀死,这个可以写一篇文章了。
自信一点,这肯定不是我们代码的问题导致JVM崩溃啊,毫无疑问是那些做安全的脚本小子搞的。
找啊找,套路无非是crontab,mount伪装这些玩意。至于篡改ps,top隐藏进程这类,我相信大部分脚本小子也没这能力,当然了,干这一行很多都是有传承的,扛不住其所在的家族雄厚,有祖传神器也难说。
好吧,最后找到是一个放到.log目录起名为x86-64的可执行程序。是我以小人之心度君子之腹了,人家也没搞隐藏ps的操作,就是每秒钟起来杀一次占用CPU最多的程序以免影响它干活。。这心机婊,还起个这么有迷惑性的名字,我就信了你是系统文件不去碰?
cp一份,保留备份,killall,然后分析下。vim一看,不是脚本,那就是elf喽。
Linux下用来快速分析elf文件有几个工具,一个是readelf,一个是objdump,另外一个是ldd。
通常用ldd来分析动态加载的库,objdump用来反编译。但是这几个工具面对一些恶意文件并不总是有效。
比如对于静态编译的程序,或者变种脚本,ldd就无效了。
对于没有section table的程序,objdump也就可能无法得出结果了。

#objdump -d ./wi ./wi:file format elf64-x86-64

因为objdump需要依赖code sections或section table,可以用readelf看看
[root@localhost ~]# readelf -a ./wi ELF Header: Magic:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class:ELF64 Data:2's complement, little endian Version:1 (current) OS/ABI:UNIX - System V ABI Version:0 Type:EXEC (Executable file) Machine:Advanced Micro Devices X86-64 Version:0x1 Entry point address:0x5c9e70 Start of program headers:64 (bytes into file) Start of section headers:0 (bytes into file) Flags:0x0 Size of this header:64 (bytes) Size of program headers:56 (bytes) Number of program headers:3 Size of section headers:64 (bytes) Number of section headers:0 Section header string table index: 0There are no sections in this file.There are no sections to group in this file.Program Headers: TypeOffsetVirtAddrPhysAddr FileSizMemSizFlagsAlign LOAD0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000001ca78b 0x00000000001ca78bR E200000 LOAD0x0000000000000000 0x00000000005cb000 0x00000000005cb000 0x0000000000000000 0x0000000000597d58RW1000 GNU_STACK0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000RW10There is no dynamic section in this file.There are no relocations in this file.The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.Dynamic symbol information is not available for displaying symbols.No version information found in this file.

所以这种情况下,可以这么来,-D表示对全部文件进行反汇编,-b表示二进制,-m表示指令集架构
[root@localhost ~]# objdump -b binary -D -m i386 ./wi./wi:file format binary Disassembly of section .data:00000000 <.data>: 0:7f 45jg0x47 2:4cdec%esp 3:46inc%esi 4:02 01add(%ecx),%al 6:01 00add%eax,(%eax) ... 10:02 00add(%eax),%al 12:3e 00 01add%al,%ds:(%ecx) 15:00 00add%al,(%eax)

另外,strace,gdb等工具也有一定的帮助。当然,上IDA这种大型武器就更有效了。
这只是浅尝辄止,就算dump出了这么一堆汇编代码,又有什么用,没那么容易看懂。
我又凭啥让别人相信这东西不是个正常的二进制文件?仅仅凭它各种龌龊的隐藏行为还不够。
所以,好端端的一个ELF可执行文件,怎么就没了section table呢?很简单,脚本小子就是喜欢玩些小把戏,很容易就想到是加壳了,Linux下最容易想到的壳就是UPX。
[root@localhost ~]# strings ./wi |grep UPX nUPX!( $Info: This file is packed with the UPX executable packer http://upx.sf.net $ $Id: UPX 3.95 Copyright (C) 1996-2018 the UPX Team. All Rights Reserved. $ UPX!u UPX! UPX!

脚本小子做事还是毛糙,也不晓得隐藏一下壳。把它的王八壳子扒了
[root@localhost ~]# ./upx -d wi Ultimate Packer for eXecutables Copyright (C) 1996 - 2020 UPX 3.96Markus Oberhumer, Laszlo Molnar & John ReiserJan 23rd 2020File sizeRatioFormatName ------------------------------------------------ 5011080 <-187838037.48%linux/amd64wiUnpacked 1 file.

要是脚本小子把UPX壳的信息给隐藏了,那么UPX自带的-d命令就没法脱壳了,这个时候就得用IDA了。加壳的本质就是把原来的程序的数据全部压缩加密了,在静态文件中无法分析,随着程序的执行,运行时会将代码释放到内存中。我们可以用ida远程调试test程序,找到upx自解壳后的 OEP,再把内存给dump出来,就可以实现手动脱壳了。怎样找OEP,这就得看经验了。
脱壳之后呢,继续用strings,strace,netstat等命令做定性分析。
其实到了这一步,strings命令已经足够分析出其行为了。
[1; 37monnection * COMMANDS'h' hashrate, 'p' pause, 'r' resume, 's' results, 'c' connection >wz *ctz>3>c) :w 3 [32m|| [31m ERROR [32m|| [37m Invalid Port Use In This Range [36m'1-65535' [37me.g [31m ( ./xmrig -p 3333 ) [32m|| [31m ERROR [32m|| [37m Invalid Class You Can Use Only These Classes [36m'192.168' [32m, [36m'172' [32m, [36m'100' [32m, [36m'10' [37m e.g [31m ( ./xmrig -lan 192.168.0.1 ) [32m|| [31m ERROR [32m|| [37m Empty Or Invalid Pool Address

还能分析出是C++写的木马。想要反汇编出C++源文件,你吃屁呢。objdump得依赖debug信息才行,脚本小子再菜鸡也不会这么做啊。要C++源文件,那只能用IDA dump了,这也得出近似的源文件。
当然了,最简单的就是直接上传到virustotal,最后得出的结果果然是一个Linux.Risk.Bitcoinminer.Tbix。
呵呵,脚本小子。
【Linux恶意ELF文件分析】Linux恶意ELF文件分析
文章图片

    推荐阅读