起因是某客户的服务器上,只有一启动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 ./wiELF 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: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000001ca78b 0x00000000001ca78b R E 200000 LOAD 0x0000000000000000 0x00000000005cb000 0x00000000005cb000 0x0000000000000000 0x0000000000597d58 RW 1000 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 10There 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 binaryDisassembly of section .data:00000000 <.data>: 0: 7f 45 jg 0x47 2: 4c dec %esp 3: 46 inc %esi 4: 02 01 add (%ecx),%al 6: 01 00 add %eax,(%eax) ... 10: 02 00 add (%eax),%al 12: 3e 00 01 add %al,%ds:(%ecx) 15: 00 00 add %al,(%eax)
另外,strace,gdb等工具也有肯定的帮忙。当然,上IDA这种大型武器就更无效了。
这只是浅尝辄止,就算dump出了这么一堆汇编代码,又有什么用,没那么容易看懂。
我又凭啥让他人置信这货色不是个失常的二进制文件?仅仅凭它各种肮脏的暗藏行为还不够。
所以,好端端的一个ELF可执行文件,怎么就没了section table呢?很简略,脚本小子就是喜爱玩些小把戏,很容易就想到是加壳了,Linux下最容易想到的壳就是UPX。
[root@localhost ~]# strings ./wi |grep UPXnUPX!($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!uUPX!UPX!
脚本小子做事还是毛糙,也不知道暗藏一下壳。把它的王八壳子扒了
[root@localhost ~]# ./upx -d wi Ultimate Packer for eXecutables Copyright (C) 1996 - 2020UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020 File size Ratio Format Name -------------------- ------ ----------- ----------- 5011080 <- 1878380 37.48% linux/amd64 wiUnpacked 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。
呵呵,脚本小子。