Temel seviye dinamik analizde zararlı çalıştırılarak ağ, dosya sistemi, süreçler ve diğer işletim sistemi bileşenleri üzerindeki etkileri gözlemlenir. Zararlının çalıştığı sistemde ve ağda kalıcı etkileri olabileceğinden dolayı dinamik analizin izole bir ortamda yapılması önerilir. Örneklere “Temel Seviye Statik Analiz” (http://blog.bga.com.tr/2014/12/linux-sistemlerde-zararl-yazlm-analizi.html) yazısında kullanılan zararlı ile devam edilmiştir.
Zararlı çalıştırıldığında “ps” komutu ile sistem süreçleri listelenir, “-ef” parametreleri verilerek süreçlerin PPID (parent process id) gibi detayları da listelenir. Bu sayede grep komutunun da yardımı ile dosya isminden yola çıkarak ilk süreç, ilk sürecin PID değerinden yola çıkarak da başlattığı diğer süreçler bulunur.
ps -ef |grep elknot |grep -v grep
remnux 1702 1 0 04:00 ? 00:00:00 ./elknot
ps -ef|grep 1702|grep -v grep
remnux 1702 1 0 04:00 ? 00:00:00 ./elknot
ps çıktısında zararlının başlattığı başka bir süreç bulunmadığı görülüyor.
Daha sonra “strace" komutuyla sürecin yaptığı sistem çağrıları izlenir. Bu sayede yaptığı işlemler hakkında oldukça fazla bilgi edinilebilir.
strace ./elknot
execve("./elknot", ["./elknot"], [/* 44 vars */]) = 0
…..
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
stat64("/home/remnux/Desktop/elknot", {st_mode=S_IFREG|0755, st_size=1223123, ...}) = 0
getppid() = 1850
readlink("/proc/1850/exe", "/usr/bin/strace", 255) = 15
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x9476878) = 1852
exit_group(0) = ?
Örnekte zararlı çalışmasını “fork” ile dallandırdığı için “strace” çıktısı faydalı bir bilgi sağlamıyor. Böyle durumlarda fork edilen süreçleri de takip etmek için “-f” parametresi kullanılır.
strace -f ./elknot
….
open("/dev/null", O_RDWR) = 3
fstat64(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
dup2(3, 0) = 0
dup2(3, 1) = 1
dup2(3, 2) = 2
close(3) = 0
open("/tmp/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
getdents64(3, /* 14 entries */, 4096) = 496
getdents64(3, /* 0 entries */, 4096) = 0
close(3) = 0
nanosleep({1, 0}, NULL) = 0
open("/tmp/moni.lod", O_RDWR) = -1 ENOENT (No such file or directory)
nanosleep({1, 0}, NULL) = 0
open("/tmp/bill.lock", O_RDWR) = -1 ENOENT (No such file or directory)
unlink("/tmp/bill.lock") = -1 ENOENT (No such file or directory)
access("/tmp/gates.lod", F_OK) = 0
open("/tmp/gates.lod", O_RDWR) = 3
flock(3, LOCK_EX|LOCK_NB) = 0
flock(3, LOCK_UN) = 0
close(3) = 0
access("/tmp/gates.lod", F_OK) = 0
open("/tmp/gates.lod", O_RDWR) = 3
…..
Process 1898 resumed (parent 1897 ready)
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7768938) = 1898
[pid 1898] execve("/sbin/insmod", ["insmod", "/home/remnux/Desktop/xpacket.ko"], [/* 44 vars */]) = 0
[pid 1898] brk(0) = 0x81a9000
[pid 1898] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
[pid 1898] mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779a000
…
[pid 1907] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
[pid 1907] setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
[pid 1907] setsockopt(4, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0
[pid 1907] time(NULL) = 1419240360
[pid 1907] fcntl64(4, F_GETFL) = 0x2 (flags O_RDWR)
[pid 1907] fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
[pid 1907] connect(4, {sa_family=AF_INET, sin_port=htons(25000), sin_addr=inet_addr("23.251.63.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 1907] fcntl64(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
[pid 1907] fcntl64(4, F_SETFL, O_RDWR) = 0
[pid 1907] getsockname(4, {sa_family=AF_INET, sin_port=htons(41238), sin_addr=inet_addr("172.16.63.160")}, [16]) = 0
[pid 1907] open("/home/remnux/Desktop/conf.n", O_RDWR|O_CREAT, 0644) = 5
[pid 1907] flock(5, LOCK_EX) = 0
[pid 1907] write(5, "E\0\0\0", 4) = 4
[pid 1907] write(5, "\0\364\1\0\0002\0\0\0\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\1\2\0\0\0"..., 69) = 69
[pid 1907] flock(5, LOCK_UN) = 0
[pid 1907] close(5) = 0
[pid 1907] open("/proc/net/route", O_RDONLY) = 5
…
Çıktı yorumlandığında zararlının dikkate değer aktiviteleri şu şekilde sıralanabilir:
Strace’in yanısıra “ltrace” komutuyla zararlının harici kütüphanelere yaptığı çağrılar takip edilebilir.
ltrace ./elknot
ltrace: Couldn't find .dynsym or .dynstr in “./elknot"
Örnek zararlı harici kütüphaneleri statik olarak bağladığı için (static linking) ltrace başarılı olamamıştır.
Süreçlerin ağ bağlantıları ve hangi aşamada oldukları bilgisine “netstat" komutula ulaşılır, buna alternatif olarak lsof komutu da kullanılabilir. Örneğin, TCP bağlantıları ve bağlantıyı açan süreç “-tp" parametreleriyle görüntülenir. İstenilirse “-n” parametresi eklenerek reverse dns çözümlemesi yapılması engellenir. Süreç isimlerini ve tüm bağlantıları listeleyebilmek için komutu tam yetkili olarak çalıştırmak gerekir.
sudo netstat -ntp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 1 172.16.63.160:41218 23.251.63.37:25000 SYN_SENT 1702/elknot
Strace çıktısında görülen bağlantı netstat ile de doğrulanmıştır. State değerinin “SYN_SENT” olması bağlantı açma isteğinin sunucuya gönderildiği ancak henüz cevap dönmediği anlamına gelir. Başarıyla açılan bir bağlantıda bu değer “ESTABLISHED” olarak değişecektir.
Ağ trafiğinin detaylı analizi, “Zararlı Yazılım Trafiğinin Sahte Servislerle Yönetimi” (http://blog.bga.com.tr/2014/02/zararl-yazlm-trafiginin-sahte.html) ve “SSL Kullanan Zararlı Yazılımın Trafiğini Yönlendirme ve İnceleme” (http://blog.bga.com.tr/2014/04/ssl-kullanan-zararl-yazlmn-trafigini.html) yazılarında anlatıldığı gibi yapılabilir.
Her ne kadar bu yazılarda hedef sistem Windows olsa da, linux için farklılık gösteren tek bölüm trafiğin yönlendirilme kısmıdır. Mesela DNS isteklerine sahte cevaplar vererek trafiği yönlendirmek için “fakedns” aracı kullanılabilir. Tüm DNS isteklerine 10.10.10.10 cevabını dönmek için:
sudo fakedns 10.10.10.10
pyminifakeDNS:: dom.query. 60 IN A 10.10.10.10
Respuesta: google.com. -> 10.10.10.10
Tüm trafiği 10.10.10.10 makinesi üzerinden yönlendirmek için:
sudo route add default gw 10.10.10.10
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.10 0.0.0.0 UG 0 0 0 eth1
0.0.0.0 172.16.63.2 0.0.0.0 UG 100 0 0 eth0
172.16.63.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
…
Komut ve parametreleri kullanılır.
Zararlı çalıştırıldığında “ps” komutu ile sistem süreçleri listelenir, “-ef” parametreleri verilerek süreçlerin PPID (parent process id) gibi detayları da listelenir. Bu sayede grep komutunun da yardımı ile dosya isminden yola çıkarak ilk süreç, ilk sürecin PID değerinden yola çıkarak da başlattığı diğer süreçler bulunur.
ps -ef |grep elknot |grep -v grep
remnux 1702 1 0 04:00 ? 00:00:00 ./elknot
ps -ef|grep 1702|grep -v grep
remnux 1702 1 0 04:00 ? 00:00:00 ./elknot
ps çıktısında zararlının başlattığı başka bir süreç bulunmadığı görülüyor.
Daha sonra “strace" komutuyla sürecin yaptığı sistem çağrıları izlenir. Bu sayede yaptığı işlemler hakkında oldukça fazla bilgi edinilebilir.
strace ./elknot
execve("./elknot", ["./elknot"], [/* 44 vars */]) = 0
…..
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
stat64("/home/remnux/Desktop/elknot", {st_mode=S_IFREG|0755, st_size=1223123, ...}) = 0
getppid() = 1850
readlink("/proc/1850/exe", "/usr/bin/strace", 255) = 15
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
readlink("/proc/1851/exe", "/home/remnux/Desktop/elknot", 1024) = 27
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x9476878) = 1852
exit_group(0) = ?
Örnekte zararlı çalışmasını “fork” ile dallandırdığı için “strace” çıktısı faydalı bir bilgi sağlamıyor. Böyle durumlarda fork edilen süreçleri de takip etmek için “-f” parametresi kullanılır.
strace -f ./elknot
….
open("/dev/null", O_RDWR) = 3
fstat64(3, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
dup2(3, 0) = 0
dup2(3, 1) = 1
dup2(3, 2) = 2
close(3) = 0
open("/tmp/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 3
fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
getdents64(3, /* 14 entries */, 4096) = 496
getdents64(3, /* 0 entries */, 4096) = 0
close(3) = 0
nanosleep({1, 0}, NULL) = 0
open("/tmp/moni.lod", O_RDWR) = -1 ENOENT (No such file or directory)
nanosleep({1, 0}, NULL) = 0
open("/tmp/bill.lock", O_RDWR) = -1 ENOENT (No such file or directory)
unlink("/tmp/bill.lock") = -1 ENOENT (No such file or directory)
access("/tmp/gates.lod", F_OK) = 0
open("/tmp/gates.lod", O_RDWR) = 3
flock(3, LOCK_EX|LOCK_NB) = 0
flock(3, LOCK_UN) = 0
close(3) = 0
access("/tmp/gates.lod", F_OK) = 0
open("/tmp/gates.lod", O_RDWR) = 3
…..
Process 1898 resumed (parent 1897 ready)
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb7768938) = 1898
[pid 1898] execve("/sbin/insmod", ["insmod", "/home/remnux/Desktop/xpacket.ko"], [/* 44 vars */]) = 0
[pid 1898] brk(0) = 0x81a9000
[pid 1898] access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
[pid 1898] mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb779a000
…
[pid 1907] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 4
[pid 1907] setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
[pid 1907] setsockopt(4, SOL_SOCKET, SO_LINGER, {onoff=1, linger=0}, 8) = 0
[pid 1907] time(NULL) = 1419240360
[pid 1907] fcntl64(4, F_GETFL) = 0x2 (flags O_RDWR)
[pid 1907] fcntl64(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
[pid 1907] connect(4, {sa_family=AF_INET, sin_port=htons(25000), sin_addr=inet_addr("23.251.63.37")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 1907] fcntl64(4, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
[pid 1907] fcntl64(4, F_SETFL, O_RDWR) = 0
[pid 1907] getsockname(4, {sa_family=AF_INET, sin_port=htons(41238), sin_addr=inet_addr("172.16.63.160")}, [16]) = 0
[pid 1907] open("/home/remnux/Desktop/conf.n", O_RDWR|O_CREAT, 0644) = 5
[pid 1907] flock(5, LOCK_EX) = 0
[pid 1907] write(5, "E\0\0\0", 4) = 4
[pid 1907] write(5, "\0\364\1\0\0002\0\0\0\350\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\1\2\0\0\0"..., 69) = 69
[pid 1907] flock(5, LOCK_UN) = 0
[pid 1907] close(5) = 0
[pid 1907] open("/proc/net/route", O_RDONLY) = 5
…
Çıktı yorumlandığında zararlının dikkate değer aktiviteleri şu şekilde sıralanabilir:
- /tmp dizini altında bill veya gates ile başlayan dosyaları açmaya çalışıyor.
- xpacket.ko isimli bir kernel modülü yüklemeye çalışıyor.
- 23.251.63.37 IP’sinin 25000’inci portuna bir TCP bağlantısı açıyor.
- Çalıştığı dizinde “conf.n” isimli bir dosya oluşturup içine bir takım değerler yazıyor.
Strace’in yanısıra “ltrace” komutuyla zararlının harici kütüphanelere yaptığı çağrılar takip edilebilir.
ltrace ./elknot
ltrace: Couldn't find .dynsym or .dynstr in “./elknot"
Örnek zararlı harici kütüphaneleri statik olarak bağladığı için (static linking) ltrace başarılı olamamıştır.
Süreçlerin ağ bağlantıları ve hangi aşamada oldukları bilgisine “netstat" komutula ulaşılır, buna alternatif olarak lsof komutu da kullanılabilir. Örneğin, TCP bağlantıları ve bağlantıyı açan süreç “-tp" parametreleriyle görüntülenir. İstenilirse “-n” parametresi eklenerek reverse dns çözümlemesi yapılması engellenir. Süreç isimlerini ve tüm bağlantıları listeleyebilmek için komutu tam yetkili olarak çalıştırmak gerekir.
sudo netstat -ntp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 1 172.16.63.160:41218 23.251.63.37:25000 SYN_SENT 1702/elknot
Strace çıktısında görülen bağlantı netstat ile de doğrulanmıştır. State değerinin “SYN_SENT” olması bağlantı açma isteğinin sunucuya gönderildiği ancak henüz cevap dönmediği anlamına gelir. Başarıyla açılan bir bağlantıda bu değer “ESTABLISHED” olarak değişecektir.
Ağ trafiğinin detaylı analizi, “Zararlı Yazılım Trafiğinin Sahte Servislerle Yönetimi” (http://blog.bga.com.tr/2014/02/zararl-yazlm-trafiginin-sahte.html) ve “SSL Kullanan Zararlı Yazılımın Trafiğini Yönlendirme ve İnceleme” (http://blog.bga.com.tr/2014/04/ssl-kullanan-zararl-yazlmn-trafigini.html) yazılarında anlatıldığı gibi yapılabilir.
Her ne kadar bu yazılarda hedef sistem Windows olsa da, linux için farklılık gösteren tek bölüm trafiğin yönlendirilme kısmıdır. Mesela DNS isteklerine sahte cevaplar vererek trafiği yönlendirmek için “fakedns” aracı kullanılabilir. Tüm DNS isteklerine 10.10.10.10 cevabını dönmek için:
sudo fakedns 10.10.10.10
pyminifakeDNS:: dom.query. 60 IN A 10.10.10.10
Respuesta: google.com. -> 10.10.10.10
Tüm trafiği 10.10.10.10 makinesi üzerinden yönlendirmek için:
sudo route add default gw 10.10.10.10
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.10 0.0.0.0 UG 0 0 0 eth1
0.0.0.0 172.16.63.2 0.0.0.0 UG 100 0 0 eth0
172.16.63.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
…
Komut ve parametreleri kullanılır.