The threat is improving. Now the obfuscation technique. This explanation is in this real PoC.
Sample: (attached)
Code: Select all-rwxr--r-- 1 mmd mmd 2492148 Jul 20 06:47 txmap*
$ md5 txmap
MD5 (txmap) = 917a2a3d8c30282acbe7b1ff121a4336
https://www.virustotal.com/en/file/92c8 ... 406605801/
Static analysis:
Code: Select allFile size 2.4 MB ( 2492148 bytes )
File type ELF, Magic literal
ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, for GNU/Linux 2.6.9, stripped
FileAccessDate
2014:07:20 00:17:03+01:00
FileCreateDate
2014:07:20 00:17:03+01:00
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048130
Start of program headers: 52 (bytes into file)
Start of section headers: 2491188 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 5
Size of section headers: 40 (bytes)
Number of section headers: 24
Section header string table index: 23
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .note.ABI-tag NOTE 080480d4 0000d4 000020 00 A 0 0 4
[ 2] .init PROGBITS 080480f4 0000f4 000030 00 AX 0 0 4
[ 3] .text PROGBITS 08048130 000130 0bde0c 00 AX 0 0 16
[ 4] __libc_freeres_fn PROGBITS 08105f40 0bdf40 000ffa 00 AX 0 0 16
[ 5] .fini PROGBITS 08106f3c 0bef3c 00001c 00 AX 0 0 4
[ 6] .rodata PROGBITS 08106f60 0bef60 018720 00 A 0 0 32
[ 7] __libc_subfreeres PROGBITS 0811f680 0d7680 00002c 00 A 0 0 4
[ 8] __libc_atexit PROGBITS 0811f6ac 0d76ac 000004 00 A 0 0 4
[ 9] .eh_frame PROGBITS 0811f6b0 0d76b0 0195b0 00 A 0 0 4
[10] .gcc_except_table PROGBITS 08138c60 0f0c60 004725 00 A 0 0 4
[11] .tdata PROGBITS 0813e388 0f5388 000010 00 WAT 0 0 4
[12] .tbss NOBITS 0813e398 0f5398 000020 00 WAT 0 0 4
[13] .ctors PROGBITS 0813e398 0f5398 000024 00 WA 0 0 4
[14] .dtors PROGBITS 0813e3bc 0f53bc 00000c 00 WA 0 0 4
[15] .jcr PROGBITS 0813e3c8 0f53c8 000004 00 WA 0 0 4
[16] .data.rel.ro PROGBITS 0813e3e0 0f53e0 000814 00 WA 0 0 32
[17] .got PROGBITS 0813ebf4 0f5bf4 000078 04 WA 0 0 4
[18] .got.plt PROGBITS 0813ec6c 0f5c6c 00000c 04 WA 0 0 4
[19] .data PROGBITS 0813ec80 0f5c80 16a0f4 00 WA 0 0 32
[20] .bss NOBITS 082a8d80 25fd74 007748 00 WA 0 0 32
[21] __libc_freeres_pt NOBITS 082b04c8 25fd74 000014 00 WA 0 0 4
[22] .comment PROGBITS 00000000 25fd74 0004da 00 0 0 1
[23] .shstrtab STRTAB 00000000 26024e 0000e4 00 0 0 1
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0xf5385 0xf5385 R E 0x1000
LOAD 0x0f5388 0x0813e388 0x0813e388 0x16a9ec 0x172154 RW 0x1000
NOTE 0x0000d4 0x080480d4 0x080480d4 0x00020 0x00020 R 0x4
TLS 0x0f5388 0x0813e388 0x0813e388 0x00010 0x00030 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
Section to Segment mapping:
Segment Sections...
00 .note.ABI-tag .init .text __libc_freeres_fn .fini .rodata __libc_subfreeres __libc_atexit .eh_frame .gcc_except_table
01 .tdata .ctors .dtors .jcr .data.rel.ro .got .got.plt .data .bss __libc_freeres_ptrs
02 .note.ABI-tag
03 .tdata .tbss
There are no section groups in this file.
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Notes at offset 0x000000d4 with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_VERSION (version)
Source code filenames:
Code: Select allFake.cpp
Global.cpp
main.cpp
Manager.cpp
ServerIP.cpp
StatBase.cpp
ThreadAttack.cpp
ThreadHostStatus.cpp
ThreadTaskManager.cpp
ThreadTimer.cpp
AutoLock.cpp
FileOp.cpp
Log.cpp
Md5.cpp
Media.cpp
NetBase.cpp
ThreadCondition.cpp
Thread.cpp
ThreadMutex.cpp
Utility.cpp
path accessed:
Code: Select all/bin/sh
/cpuinfo
/dev/console
/dev/full
/dev/log
/dev/null
/dev/tty
/etc/fstab
/etc/host.conf
/etc/ld.so.cache
/etc/localtime
/etc/mtab
/etc/nsswitch.conf
/etc/resolv.conf
/etc/suid-debug
/gcof
/lib/
/lib/obsolete/linuxthreads/
/loc
/locale.alias
/meminfo
/proc
/proc/
/proc/%d/exe
/proc/cpuinfo
/proc/cpuinfo
/proc/meminfo
/proc/net
/proc/net/dev
/proc/self/exe
/proc/self/exe
/proc/self/maps
/proc/self/maps
/proc/stat
/proc/stat
/proc/sys/kernel/ngroups_max
/proc/sys/kernel/ngroups_max
/proc/sys/kernel/osrelease
/proc/sys/kernel/osrelease
/proc/sys/kernel/rtsig-max
/proc/sys/kernel/rtsig-max
/proc/sys/kernel/version
/staf
/usr
/usr/lib/
/usr/lib/gconv
/usr/lib/gconv/gconv-modules.cache
/usr/lib/locale
/usr/lib/locale/locale-archive
/usr/libexec/getconf
/usr/lib/gconv/gconv-modules.cache
/usr/lib/locale
/usr/lib/locale/locale-archive
/usr/libexec/getconf
/usr/share/locale
/usr/share/zoneinfo
/var/profile
/var/run/nscd/socket
/var/tmp
Compilation & dependency
Code: Select all// Where it was compiled:
GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)
GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)
GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)
GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)
GCC: (GNU) 4.0.0 20050519 (Red Hat 4.0.0-8)
// And the compat:
GCC: (GNU) 4.2.1
// Libs needed:
ld.so-1.7.0
/etc/ld.so.cache
glibc-ld.so.cache1.1
Same lang traces, same environment:
Code: Select all.data:08223C38 aINZD db 'エエスィヤュハシフラスモラヨハァーワ(%d)',0Dh,0Ah,0
In reversing this type. You cannot see what it is without a good disassembler tool. Not as per previous post.
Because functions are-address based, it is obfuscated (tons of tools can make it, donno which one is used, but who cares..)
If you go to EP: start() to be hammered by these pushed subroutines:
Code: Select all xor ebp, ebp
pop esi
mov ecx, esp
and esp, 0FFFFFFF0h
push eax
push esp
push edx
push offset sub_80A9700
push offset sub_80A9740
push ecx
push esi
push offset sub_804826
This is a kind of signature, for me.
In my way, figured each function one by one, trail it until you meet the static call of kernel syscall and make the table of it.
Put it back the table of syscall to the opcodes addess, you can trail how it works like;
Code: Select allGo to: sub_80A8FC0 start! ;; obviously.. a start.
Go to: sub_80D8380 switch ;; 31 cases: 0x21, 0x20, 17, 11, 6, 10, E, D , C ,B , 5, 3
Go to: sub_80D4290 LINUX - sys_newuname
Go to: loc_80A91E8 Read: "/proc/sys/kernel/osrelease"
Go to: sub_80D5450 LINUX - sys_read
(and so on..)
This way I can confirm the similarity to confirm this family.
I use many breakpoint to debug the malware (sorry, since crooks maybe read this I cant explain "how")
The concept is launched the parrent, put the break point right after the forking about to be started:
Code: Select allexecve("./MALWARE", ["./MALWARE"], [/* 16 vars */]) = 0
uname({sys="Linux", node="1x111", ...}) = 0
brk(0) = 0x90fc000
brk(0x90fccb0) = 0x90fccb0
set_thread_area(0xfff95c2c) = 0
brk(0x911dcb0) = 0x911dcb0
brk(0x911e000) = 0x911e000
readlink("/proc/self/exe", "../mmd/test/MALWARE", 1024) = 18
rt_sigaction(SIGINT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0xfff94ff4) = 28481
waitpid(28481, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 28481
rt_sigaction(SIGINT, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0) = 28483
rt_sigaction(SIGINT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], 0}, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0xfff94ff4) = 28484
waitpid(28484, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 28484
rt_sigaction(SIGINT, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {SIG_DFL, [], 0}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0) = 28486
exit_group(0) // <==== Put breakpoint before forking started
Make sure the new process:
Code: Select all// examine:
// new process forked:
29547 ? Ssl 0:00 (MALWARE)
Let it run abit after you see list of files sockets goes like this:
Code: Select allMALWARE 28756 mmd cwd DIR 9,2 4096 29757163 /home/mmd/test
MALWARE 28756 mmd rtd DIR 9,2 4096 2 /
MALWARE 28756 mmd txt REG 9,2 1480387 29763093 /home/mmd/test/MALWARE (deleted)
MALWARE 28756 mmd 0u CHR 1,3 0t0 1027 /dev/null
MALWARE 28756 mmd 1u CHR 1,3 0t0 1027 /dev/null
MALWARE 28756 mmd 2u CHR 1,3 0t0 1027 /dev/null
Break it here to record the registers.
And then release the breakpoint, and you will see the INET connection started in debug codes, and also in monitor like below, question is ...what's the different with the process above?? See below too:
Code: Select allMALWARE 29547 mmd 3u IPv4 7932614 0t0 TCP serpico.malwaremustdie.org:60162->183.60.202.59:10991 (ESTABLISHED)
Confirm it by checking the socket:
Code: Select alltcp 0 27 x.x.x.x:60224 183.60.202.59:10991 ESTABLISHED 29547/
Voila! you see the same PID shown in the next fork that had just started. This shows INET won't be started as parent mode but as child, good reversing information.
PS: CNC Information: China!
Code: Select all$ echo 183.60.202.59 | bash /malware/checkdomains/origin.sh
183.60.202.59||4134 | 183.0.0.0/10 | CHINANET | CN | CHINATELECOM.COM.CN | CHINANET GUANGDONG PROVINCE NETWORK
And after waiting a little while some attacks will start, one of the type is DNS AMP:
DDoS PoC recorded, you'll see tons of these in action :)
Code: Select all1 11018 11020 mmd 3u IPv4 19591952 0t0 TCP x.x.x.x:44103->1.1.1.1:sunrpc (SYN_SENT)
Analysis