m00dy's place

An Analysis of ShellShock Malware

TL;DR I had this malware from a gist which i dont really remember right now. I downloaded it and started to analyse what this is all about. As i analyzed so far, it's somehow broken. May be i am late ?

Ok lets start with file command.

eren@lisa:~$ file nginx
nginx: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.18, stripped
eren@lisa:~$

file program tells us that it's statically linked and stripped. So, Most of its dependencies are inside the code and we will have difficulties while debugging it because the debug informations have been removed.

We'll fire up gdb and start to debug the malware from its starting point.

eren@lisa:~$ gdb nginx 
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/eren/nginx...(no debugging symbols found)...done.
(gdb) info file
Symbols from "/home/eren/nginx".
Local exec file:
    `/home/eren/nginx', file type elf32-i386.
    Entry point: 0x8048160

I'll put a breakpoint to 0x8048160

b * 0x8048160

and then i'll run the executable and it'll will stop in its entry point.

(gdb) b * 0x8048160
Breakpoint 1 at 0x8048160
(gdb) r
Starting program: /home/eren/nginx 

Breakpoint 1, 0x08048160 in ?? ()
=> 0x08048160:    31 ed    xor    ebp,ebp
(gdb) x/20i $pc
=> 0x8048160: xor    ebp,ebp
   0x8048162:   pop    esi
   0x8048163:   mov    ecx,esp
   0x8048165:   and    esp,0xfffffff0
   0x8048168:   push   eax
   0x8048169:   push   esp
   0x804816a:   push   edx
   0x804816b:   push   0x804be00
   0x8048170:   push   0x804be40
   0x8048175:   push   ecx
   0x8048176:   push   esi
   0x8048177:   push   0x804b2cc
   0x804817c:   call   0x804b7c0
   0x8048181:   hlt

From 0x8048160 to 0x8048181, the code blocks are standart way of glibc execution. Therefore, the malware programmer didnt modified the entry point. If you compile an empty helloworld program, you would see the same starting code like above. Xoring ebp to ebp means nothing but this type of practices come from ABI (Application Binary Interface Specs). In the address of 0x804817c, the calls refers to <_libcstart_main@plt> function.

You can look at the details here So, first paramether to libcstartmain function is actually the last one pushed on the stack. Therefore, 0x804b2cc is our main function. Let's put a breakpoint there and go on.

b * 0x804b2cc
Breakpoint 2, 0x0804b2cc in ?? ()
=> 0x0804b2cc:    8d 4c 24 04  lea    ecx,[esp+0x4]
(gdb) x/30i $pc
=> 0x804b2cc: lea    ecx,[esp+0x4]
   0x804b2d0:   and    esp,0xfffffff0
   0x804b2d3:   push   DWORD PTR [ecx-0x4]
   0x804b2d6:   push   ebp
   0x804b2d7:   mov    ebp,esp
   0x804b2d9:   push   edi
   0x804b2da:   push   esi
   0x804b2db:   push   ebx
   0x804b2dc:   push   ecx
   0x804b2dd:   sub    esp,0x1464
   0x804b2e3:   push   0x0
   0x804b2e5:   call   0x8056ce0
   0x804b2ea:   mov    ebx,eax
   0x804b2ec:   call   0x8057430
   0x804b2f1:   xor    eax,ebx
   0x804b2f3:   mov    DWORD PTR [esp],eax
   0x804b2f6:   call   0x804cb90
   0x804b2fb:   mov    DWORD PTR [esp],0x0
   0x804b302:   call   0x8056ce0
   0x804b307:   mov    ebx,eax
   0x804b309:   call   0x8057430
   0x804b30e:   xor    eax,ebx
   0x804b310:   mov    DWORD PTR [esp],eax
   0x804b313:   call   0x8048240
   0x804b318:   call   0x8048fd5
   0x804b31d:   movzx  eax,BYTE PTR ds:0x80cc2b5
   0x804b324:   add    esp,0xc
   0x804b327:   push   eax
   0x804b328:   movzx  eax,BYTE PTR ds:0x80cc2b4
   0x804b32f:   push   eax
(gdb)

As you may see, the main function has a lot of calls to other functions. I'll not go into every call but cover most important aspects of its actions.

0x8074fd0: mov    edx,ebx
   0x8074fd2:   mov    ebx,DWORD PTR [esp+0x4]
   0x8074fd6:   mov    eax,0x7a
   0x8074fdb:   call   DWORD PTR ds:0x80cbfd0

In the forth line, i see a call to somewhere over a pointer. I need to deference it.

(gdb) p/x *0x80cbfd0
$1 = 0xf7ffd420
(gdb) x/10i 0xf7ffd420
   0xf7ffd420 <__kernel_vsyscall>:    push   ecx
   0xf7ffd421 <__kernel_vsyscall+1>:  push   edx
   0xf7ffd422 <__kernel_vsyscall+2>:  push   ebp
   0xf7ffd423 <__kernel_vsyscall+3>:  mov    ebp,esp
   0xf7ffd425 <__kernel_vsyscall+5>:  sysenter

After deferencing, It becomes our gate to the kernel. I wrote the address of 0x80cbfd0 somewhere to keep in my mind. We need to analyze the registers before it goes through syscall gate.

(gdb) info reg
eax            0x7a 122
ecx            0xffffffff   -1
edx            0x0  0
ebx            0xffffd5f6   -10762
esp            0xffffd5e0   0xffffd5e0
ebp            0xffffd7c8   0xffffd7c8
esi            0x0  0
edi            0x804be00    134528512
eip            0x8074fdb    0x8074fdb
eflags         0x286    [ PF SF IF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x0  0

We need to look up syscall table for 0x7a (eax value). You can find syscall table here

122 belongs to uname syscall.

(gdb) x/20c $ebx
0xffffd5f6: 76 'L'   105 'i'  110 'n'  117 'u'  120 'x'  0 '\000' 0 '\000' 0 '\000'
0xffffd5fe: 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000' 0 '\000'
0xffffd606: 0 '\000' 0 '\000' 0 '\000' 0 '\000'

So the malware got the information about my system.At least it knows which operating system im running :)

It uses several times of brk syscall to allocate some space from the heap.

0x8056ce6: push   ebx
   0x8056ce7:   xor    ebx,ebx
=> 0x8056ce9: mov    eax,0xd
   0x8056cee:   call   DWORD PTR ds:0x80cbfd0

Another syscall for getting time and later it will get also pid number.I'll skip these until socket things come up.

0x805864f: nop
   0x8058650:   mov    edx,ebx
   0x8058652:   mov    eax,0x66
   0x8058657:   mov    ebx,0x1
=> 0x805865c: lea    ecx,[esp+0x4]
   0x8058660:   call   DWORD PTR ds:0x80cbfd0

This is very important, the malware creates a socket with socket syscall.This time, eax is 102 and it is sys_socketcall in linux syscall table (i386).

When we look at the parameters,

(gdb) info reg
eax            0x66 102
ecx            0xffffb2b0   -19792
edx            0x54302d33   1412443443
ebx            0x1  1
esp            0xffffb2ac   0xffffb2ac
ebp            0xffffc338   0xffffc338
esi            0x2e5fd200   778031616
edi            0x804be00    134528512
eip            0x8058660    0x8058660
eflags         0x282    [ SF IF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99

Ebx is really important, 0x1 tells us that it is a syssocket and it will go down just right there. Ecx is our pointer which is being passed into syssocket function.

And then, after syscall execution, the kernel should give us a file descriptor that we can write to or read from it.

I go to my proc file system to see which file descriptor are mapped to my process adress space.

eren@lisa:/proc/30480/fd$ ls -la
total 0
dr-x------ 2 eren eren  0 Oct  4 18:03 .
dr-xr-xr-x 8 eren eren  0 Oct  4 17:24 ..
lrwx------ 1 eren eren 64 Oct  4 18:04 0 -> /dev/pts/0
lrwx------ 1 eren eren 64 Oct  4 18:04 1 -> /dev/pts/0
lrwx------ 1 eren eren 64 Oct  4 18:03 2 -> /dev/pts/0
lrwx------ 1 eren eren 64 Oct  4 18:04 3 -> socket:[324793]
lrwx------ 1 eren eren 64 Oct  4 18:04 4 -> socket:[324794]
lr-x------ 1 eren eren 64 Oct  4 18:04 5 -> pipe:[324795]
l-wx------ 1 eren eren 64 Oct  4 18:04 6 -> pipe:[324795]
lrwx------ 1 eren eren 64 Oct  4 18:04 7 -> socket:[327132]

Yeah there it is.

0x805844c: mov    eax,0x66
   0x8058451:   mov    ebx,0x3
   0x8058456:   lea    ecx,[esp+0x4]
=> 0x805845a: call   DWORD PTR ds:0x80cbfd0

This time, Ebx is 0x3 that means SYSCONNECT. Ecx now points to paramethers that we pushed into sysconnect. Let's examine the parameter.

2515         case SYS_CONNECT:
2516                 err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
2517                 break;

The code above is from kernel source.Paramethers are a0,a pointer and another a2. These are all 12 bytes. So ecx should point to 12 bytes.

(gdb) x/3wx $ecx
0xffffb2b0: 0x00000007  0xffffc30c  0x00000010
(gdb)

Now, a0 => 0x07, sockaddr pointer is => 0xffffc30c and last paramether is 0x00000010.

We want to find where this malware connects. We know that sockaddr structure holds this information. Sockaddr structure is here

typedef unsigned short sa_family_t;
struct sockaddr {
    sa_family_t sa_family; /* address family, AF_xxx */
    char sa_data[14]; /* 14 bytes of protocol address   */
};

We can do our estimation that 1 short + 14 char => 16 bytes. So i'll skip the first 2 bytes and print the others.

(gdb) x/14bu 0xffffc30e
0xffffc30e: 0   80  108 162 197 26  0   0
0xffffc316: 0   0   0   0   0   0

So, it's clear that the malware wants to connect to 108.162.197.26 through 80 port.

Malware then tries to get the ip of host machine by executing getsockname.

It then reads "/proc/net/route" here to parse network interface and uses ioctl syscall to get its MAC address (SIOCGIFHWADDR).

Later, It forks itself and quit.

The forked process also tries to connect somewhere(89.238.150.154) but it cannot. I don't know why.

root@lisa:~/blog# tcpdump -v -X dst 89.238.150.154
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
18:52:50.373950 IP (tos 0x0, ttl 64, id 46732, offset 0, flags [DF], proto TCP (6), length 60)
    95.85.48.36.51746 > 89.238.150.154.5: Flags [S], cksum 0x8030 (incorrect -> 0x9be6), seq 3399773995, win 14600, options [mss 1460,sackOK,TS val 113698896 ecr 0,nop,wscale 8], length 0
    0x0000:  4500 003c b68c 4000 4006 042e 5f55 3024  E..<..@.@..._U0$
    0x0010:  59ee 969a ca22 0005 caa4 6f2b 0000 0000  Y...."....o+....
    0x0020:  a002 3908 8030 0000 0204 05b4 0402 080a  ..9..0..........
    0x0030:  06c6 e850 0000 0000 0103 0308            ...P........

Anyway, this malware looks harmless now :)

comments powered by Disqus