Şüpheli Dosyaları Kaspersky’e Toplu Gönderme: Adım Adım Rehber

Merhaba,

Bu yazımızda Kaspersky’nin tespit edemediği malwareleri toplu olarak Kaspersky’e nasıl göndereceğimizi inceleyeceğiz.

İlk olarak tespit edilemeyen malwarelerimizi bir klasörde topluyoruz. Ben antivirüs test etmek için yayınlanan ve sürekli güncellenen koleksiyonlardan örnekler indirdim. Siz gelen maillerinizde, webde gezinirken, x.com veya telegram gibi platformlarda karşılaştığınız şüpheli dosyaları taratıp tespit edilemeyenleri gönderebilirsiniz.

Şekil-1’de görüldüğü üzere 136035 malware örneği bulunmakta. Tarama, tespit ve silinme sonrası malware örnek sayısı 10000’lere kadar düşmektedir.

Şekil-1 Taranmayı bekleyen 136035 adet 231GB zararlı yazılım örneği

Tarama yapılıp tespit edilen malwareler silinirken ara ara taramanın yavaşladığını tespit ettim. Yaptığım incelemeler sonucu avp.exe dosyasının yani Kaspersky’nin taradığı dosyalar içinde imza veritabanında olmayan ama şüpheli gördüğü dosyaları kontrol için kendi sunucularına yüklediğini anladım. Ne kadarlık bir veri trafiği oluştuğunu anlamak için aşağıdaki küçük bir powershell scriptini yazdım.

# ============================================================
# Kaspersky avp.exe - GERCEK TCP TRAFIK MONITORU
# Windows 10/11
#
# Yonetici olarak calistirin.
# ============================================================

$ErrorActionPreference = "SilentlyContinue"

# ------------------------------------------------------------
# C# TCP Extended Statistics API
# ------------------------------------------------------------

if (-not ("TcpTraffic.Native" -as [type])) {

Add-Type @"
using System;
using System.Runtime.InteropServices;

namespace TcpTraffic
{
    public static class Native
    {
        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPROW
        {
            public uint State;
            public uint LocalAddr;
            public uint LocalPort;
            public uint RemoteAddr;
            public uint RemotePort;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_TCPROW_OWNER_PID
        {
            public uint State;
            public uint LocalAddr;
            public uint LocalPort;
            public uint RemoteAddr;
            public uint RemotePort;
            public uint OwningPid;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct TCP_ESTATS_DATA_RW_v0
        {
            public byte EnableCollection;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct TCP_ESTATS_DATA_ROD_v0
        {
            public ulong DataBytesOut;
            public ulong DataSegsOut;
            public ulong DataBytesIn;
            public ulong DataSegsIn;
            public ulong SegsOut;
            public ulong SegsIn;
            public uint SoftErrors;
            public uint SoftErrorReason;
            public uint SndUna;
            public uint SndNxt;
            public uint SndMax;
            public ulong ThruBytesAcked;
            public uint RcvNxt;
            public ulong ThruBytesReceived;
        }

        [DllImport("iphlpapi.dll", SetLastError=true)]
        public static extern uint GetExtendedTcpTable(
            IntPtr pTcpTable,
            ref int dwOutBufLen,
            bool sort,
            int ipVersion,
            int tblClass,
            uint reserved
        );

        [DllImport("iphlpapi.dll", SetLastError=true)]
        public static extern uint SetPerTcpConnectionEStats(
            ref MIB_TCPROW Row,
            int EstatsType,
            ref TCP_ESTATS_DATA_RW_v0 Rw,
            uint RwVersion,
            uint RwSize,
            uint Offset
        );

        [DllImport("iphlpapi.dll", SetLastError=true)]
        public static extern uint GetPerTcpConnectionEStats(
            ref MIB_TCPROW Row,
            int EstatsType,
            IntPtr Rw,
            uint RwVersion,
            uint RwSize,
            IntPtr Ros,
            uint RosVersion,
            uint RosSize,
            ref TCP_ESTATS_DATA_ROD_v0 Rod,
            uint RodVersion,
            uint RodSize
        );

        public const int AF_INET = 2;
        public const int TCP_TABLE_OWNER_PID_ALL = 5;

        public const int TCP_ESTATS_DATA = 1;

        public const uint MIB_TCP_STATE_ESTAB = 5;

        public static MIB_TCPROW_OWNER_PID[] GetTcpTable()
        {
            int size = 0;

            uint ret = GetExtendedTcpTable(
                IntPtr.Zero,
                ref size,
                true,
                AF_INET,
                TCP_TABLE_OWNER_PID_ALL,
                0
            );

            IntPtr buffer = Marshal.AllocHGlobal(size);

            try
            {
                ret = GetExtendedTcpTable(
                    buffer,
                    ref size,
                    true,
                    AF_INET,
                    TCP_TABLE_OWNER_PID_ALL,
                    0
                );

                if (ret != 0)
                    return new MIB_TCPROW_OWNER_PID[0];

                int count = Marshal.ReadInt32(buffer);
                IntPtr rowPtr = IntPtr.Add(buffer, 4);

                int rowSize = Marshal.SizeOf(typeof(MIB_TCPROW_OWNER_PID));

                var result = new MIB_TCPROW_OWNER_PID[count];

                for (int i = 0; i < count; i++)
                {
                    result[i] =
                        Marshal.PtrToStructure<MIB_TCPROW_OWNER_PID>(rowPtr);

                    rowPtr = IntPtr.Add(rowPtr, rowSize);
                }

                return result;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }

        public static bool EnableStats(MIB_TCPROW_OWNER_PID r)
        {
            MIB_TCPROW row = new MIB_TCPROW();

            row.State = r.State;
            row.LocalAddr = r.LocalAddr;
            row.LocalPort = r.LocalPort;
            row.RemoteAddr = r.RemoteAddr;
            row.RemotePort = r.RemotePort;

            TCP_ESTATS_DATA_RW_v0 rw =
                new TCP_ESTATS_DATA_RW_v0();

            rw.EnableCollection = 1;

            uint result = SetPerTcpConnectionEStats(
                ref row,
                TCP_ESTATS_DATA,
                ref rw,
                0,
                1,
                0
            );

            return result == 0;
        }

        public static TCP_ESTATS_DATA_ROD_v0 GetStats(
            MIB_TCPROW_OWNER_PID r)
        {
            MIB_TCPROW row = new MIB_TCPROW();

            row.State = r.State;
            row.LocalAddr = r.LocalAddr;
            row.LocalPort = r.LocalPort;
            row.RemoteAddr = r.RemoteAddr;
            row.RemotePort = r.RemotePort;

            TCP_ESTATS_DATA_ROD_v0 rod =
                new TCP_ESTATS_DATA_ROD_v0();

            uint size =
                (uint)Marshal.SizeOf(typeof(TCP_ESTATS_DATA_ROD_v0));

            uint result = GetPerTcpConnectionEStats(
                ref row,
                TCP_ESTATS_DATA,
                IntPtr.Zero,
                0,
                0,
                IntPtr.Zero,
                0,
                0,
                ref rod,
                0,
                size
            );

            if (result != 0)
                return new TCP_ESTATS_DATA_ROD_v0();

            return rod;
        }

        public static string IPv4(uint addr)
        {
            byte b1 = (byte)(addr & 0xff);
            byte b2 = (byte)((addr >> 8) & 0xff);
            byte b3 = (byte)((addr >> 16) & 0xff);
            byte b4 = (byte)((addr >> 24) & 0xff);

            return b1 + "." + b2 + "." + b3 + "." + b4;
        }

        public static int Port(uint p)
        {
            return (int)(((p & 0xff) << 8) | ((p >> 8) & 0xff));
        }
    }
}
"@
}

# ------------------------------------------------------------
# Yardimci fonksiyonlar
# ------------------------------------------------------------

function Format-Bytes {
    param([double]$Bytes)

    if ($Bytes -ge 1TB) {
        return "{0:N2} TB" -f ($Bytes / 1TB)
    }

    if ($Bytes -ge 1GB) {
        return "{0:N2} GB" -f ($Bytes / 1GB)
    }

    if ($Bytes -ge 1MB) {
        return "{0:N2} MB" -f ($Bytes / 1MB)
    }

    if ($Bytes -ge 1KB) {
        return "{0:N2} KB" -f ($Bytes / 1KB)
    }

    return "{0:N0} B" -f $Bytes
}

# ------------------------------------------------------------
# Takip edilen bağlantılar
# ------------------------------------------------------------

$Connections = @{}

$TotalUpload = [UInt64]0
$TotalDownload = [UInt64]0

Write-Host ""
Write-Host "============================================================"
Write-Host "        KASPERSKY AVP.EXE NETWORK MONITOR"
Write-Host "============================================================"
Write-Host ""
Write-Host "Tum avp.exe PID'leri otomatik takip edilecek."
Write-Host "Yeni PID / yeni TCP baglantisi otomatik eklenecek."
Write-Host ""
Write-Host "Cikmak icin CTRL+C"
Write-Host ""

while ($true) {

    # --------------------------------------------------------
    # Tum avp.exe PID'lerini bul
    # --------------------------------------------------------

    $AvpProcesses = Get-Process -Name "avp" -ErrorAction SilentlyContinue

    $AvpPids = @()

    foreach ($p in $AvpProcesses) {
        $AvpPids += [uint32]$p.Id
    }

    # --------------------------------------------------------
    # TCP tablosu
    # --------------------------------------------------------

    $Table = [TcpTraffic.Native]::GetTcpTable()

    $CurrentKeys = @{}

    foreach ($row in $Table) {

        if ($row.State -ne [TcpTraffic.Native]::MIB_TCP_STATE_ESTAB) {
            continue
        }

        if ($AvpPids -notcontains $row.OwningPid) {
            continue
        }

        $localPort =
            [TcpTraffic.Native]::Port($row.LocalPort)

        $remotePort =
            [TcpTraffic.Native]::Port($row.RemotePort)

        $localIP =
            [TcpTraffic.Native]::IPv4($row.LocalAddr)

        $remoteIP =
            [TcpTraffic.Native]::IPv4($row.RemoteAddr)

        $key =
            "$($row.OwningPid)-$localIP`:$localPort-$remoteIP`:$remotePort"

        $CurrentKeys[$key] = $true

        # ----------------------------------------------------
        # Yeni bağlantı
        # ----------------------------------------------------

        if (-not $Connections.ContainsKey($key)) {

            $enabled =
                [TcpTraffic.Native]::EnableStats($row)

            $Connections[$key] = [PSCustomObject]@{
                PID          = $row.OwningPid
                LocalIP      = $localIP
                LocalPort    = $localPort
                RemoteIP     = $remoteIP
                RemotePort   = $remotePort
                LastOut      = [UInt64]0
                LastIn       = [UInt64]0
                Enabled      = $enabled
                Start        = Get-Date
            }

            # İlk çağrıdan önceki değeri almaya çalış
            $stats =
                [TcpTraffic.Native]::GetStats($row)

            $Connections[$key].LastOut =
                $stats.DataBytesOut

            $Connections[$key].LastIn =
                $stats.DataBytesIn

            continue
        }

        # ----------------------------------------------------
        # Mevcut bağlantının istatistiklerini oku
        # ----------------------------------------------------

        $stats =
            [TcpTraffic.Native]::GetStats($row)

        $newOut = $stats.DataBytesOut
        $newIn  = $stats.DataBytesIn

        $oldOut = $Connections[$key].LastOut
        $oldIn  = $Connections[$key].LastIn

        if ($newOut -ge $oldOut) {
            $TotalUpload += ($newOut - $oldOut)
        }

        if ($newIn -ge $oldIn) {
            $TotalDownload += ($newIn - $oldIn)
        }

        $Connections[$key].LastOut = $newOut
        $Connections[$key].LastIn  = $newIn
    }

    # --------------------------------------------------------
    # Ekran
    # --------------------------------------------------------

    Clear-Host

    Write-Host "============================================================"
    Write-Host "        KASPERSKY AVP.EXE NETWORK MONITOR"
    Write-Host "============================================================"
    Write-Host ""

    if ($AvpPids.Count -gt 0) {
        Write-Host "Aktif PID: $($AvpPids -join ', ')" -ForegroundColor Cyan
    }
    else {
        Write-Host "avp.exe bulunamadi." -ForegroundColor Yellow
    }

    Write-Host ""

    Write-Host ("TOPLAM UPLOAD   : {0}" -f (Format-Bytes $TotalUpload)) `
        -ForegroundColor Red

    Write-Host ("TOPLAM DOWNLOAD : {0}" -f (Format-Bytes $TotalDownload)) `
        -ForegroundColor Green

    Write-Host ""

    Write-Host "Aktif avp.exe TCP baglantilari:"
    Write-Host ""

    $Rows = @()

    foreach ($key in $Connections.Keys) {

        $c = $Connections[$key]

        if ($CurrentKeys.ContainsKey($key)) {

            $stats = $null

            $Rows += [PSCustomObject]@{
                PID       = $c.PID
                Local     = "$($c.LocalIP):$($c.LocalPort)"
                Remote    = "$($c.RemoteIP):$($c.RemotePort)"
                Upload    = Format-Bytes $c.LastOut
                Download  = Format-Bytes $c.LastIn
            }
        }
    }

    if ($Rows.Count -gt 0) {

        $Rows |
            Sort-Object PID, Remote |
            Format-Table -AutoSize
    }
    else {
        Write-Host "Aktif TCP baglantisi yok."
    }

    Write-Host ""
    Write-Host "Son guncelleme: $(Get-Date -Format 'HH:mm:ss')"

    Start-Sleep -Seconds 1
}

Şekil-2’de görüldüğü gibi 231gb malware taranması bittiği zaman 22gb malwareyi kendi sunucularına otomatik olarak göndermiştir.

Sonuç olarak, malware taramasının kendisi yavaş değildir. Tarama süresinin büyük bir bölümünü dosyaların internet üzerinden gönderilme hızı yani upload hızınız belirlemektedir.

Şekil-2 Kaspersky’nin yaptığı toplam upload miktarı

Malware örnekleri araştırırken özellikle X platformunda takip ettiğim malware analysis researcher sayfalarında yapılan araştırmalarda binlerce malwarenin Şekil-3’teki(temsili resim) gibi direkt klasör içinde olduğunu gördüm.

Şekil-3 Index dosyası olmayan herhangi bir dizindeki dosyaların görünümü

Bunların binlercesini tek tek indirmek olanaksız olduğu için toplu indirmek adına aşağıdaki powershell scriptini yazdım. Sadece $BaseUrl = “http://194.233.72.68:9999/” kısmındaki urlyi değiştirmeniz yeterli olacaktır. Tüm dosyalar İndirilenler klasörünüze inecektir. Eğer indirme işlemi yarım kalırsa tekrar scripti çalıştırdığınızda daha önce indirmiş olduğu örnekleri tekrar indirmeyecektir.

# ============================================================
# RESUME / CONTINUE RECURSIVE DOWNLOADER
# ============================================================

$BaseUrl = "http://194.233.72.68:9999/"

$DownloadRoot = Join-Path $env:USERPROFILE "Downloads"

$SiteFolder = Join-Path $DownloadRoot "194.233.72.68_9999"

New-Item -ItemType Directory -Path $SiteFolder -Force | Out-Null


# Daha önce ziyaret edilen dizinleri tut
$Visited = [System.Collections.Generic.HashSet[string]]::new()

$Downloaded = 0
$Skipped    = 0
$Errors     = 0
$Dirs       = 0


function Get-Directory {

    param(
        [string]$Url
    )

    # Aynı dizini tekrar tarama
    if ($Visited.Contains($Url)) {
        return
    }

    $Visited.Add($Url) | Out-Null

    Write-Host ""
    Write-Host "==================================================" -ForegroundColor DarkGray
    Write-Host "TARANIYOR: $Url" -ForegroundColor Cyan
    Write-Host "==================================================" -ForegroundColor DarkGray


    # --------------------------------------------------------
    # DIRECTORY LISTING'I AL
    # --------------------------------------------------------

    try {

        $Page = Invoke-WebRequest `
            -Uri $Url `
            -UseBasicParsing `
            -ErrorAction Stop

    }
    catch {

        Write-Host "[HATA] Dizin okunamadı: $Url" -ForegroundColor Red
        Write-Host $_.Exception.Message -ForegroundColor Red

        $script:Errors++

        return
    }


    # --------------------------------------------------------
    # LİNKLER
    # --------------------------------------------------------

    foreach ($Link in $Page.Links) {

        if (-not $Link.href) {
            continue
        }

        $Href = $Link.href.Trim()


        # Boş link
        if ([string]::IsNullOrWhiteSpace($Href)) {
            continue
        }


        # Parent directory
        if ($Href -eq "../" -or $Href -eq "..") {
            continue
        }


        # Anchor / query
        if ($Href.StartsWith("#") -or $Href.StartsWith("?")) {
            continue
        }


        # Javascript vb.
        if ($Href -match '^(javascript|mailto|tel):') {
            continue
        }


        # ----------------------------------------------------
        # ABSOLUTE URL
        # ----------------------------------------------------

        try {

            $Uri = [System.Uri]::new(
                [System.Uri]$Url,
                $Href
            )

        }
        catch {

            Write-Host "[ATLANDI] Geçersiz link: $Href" `
                -ForegroundColor Yellow

            continue
        }


        # ----------------------------------------------------
        # SADECE AYNI SUNUCU
        # ----------------------------------------------------

        $BaseUri = [System.Uri]$BaseUrl

        if ($Uri.Host -ne $BaseUri.Host) {
            continue
        }

        if ($Uri.Port -ne $BaseUri.Port) {
            continue
        }


        $FileUrl = $Uri.AbsoluteUri


        # ----------------------------------------------------
        # RELATIVE PATH
        # ----------------------------------------------------

        $RelativePath = [System.Uri]::UnescapeDataString(
            $Uri.AbsolutePath
        )

        $RelativePath = $RelativePath.TrimStart("/")


        # Path traversal engelle
        if ($RelativePath -match '(^|[\\/])\.\.([\\/]|$)') {

            Write-Host "[GÜVENLİK] Atlandı: $FileUrl" `
                -ForegroundColor Yellow

            continue
        }


        # ----------------------------------------------------
        # ALT DİZİN
        # ----------------------------------------------------

        if ($Uri.AbsolutePath.EndsWith("/")) {

            $SubDirectory = Join-Path `
                $SiteFolder `
                $RelativePath

            New-Item `
                -ItemType Directory `
                -Path $SubDirectory `
                -Force `
                -ErrorAction SilentlyContinue | Out-Null

            $script:Dirs++

            # Recursive devam et
            Get-Directory -Url $FileUrl

            continue
        }


        # ----------------------------------------------------
        # DOSYA
        # ----------------------------------------------------

        $FileName = [System.IO.Path]::GetFileName(
            $Uri.AbsolutePath
        )

        if ([string]::IsNullOrWhiteSpace($FileName)) {
            continue
        }


        $OutputFile = Join-Path `
            $SiteFolder `
            $RelativePath


        # Dosyanın bulunduğu klasörü oluştur
        $OutputDirectory = Split-Path `
            $OutputFile `
            -Parent

        New-Item `
            -ItemType Directory `
            -Path $OutputDirectory `
            -Force `
            -ErrorAction SilentlyContinue | Out-Null


        # ====================================================
        # DOSYA ZATEN VAR MI?
        # ====================================================

        if (Test-Path -LiteralPath $OutputFile) {

            $ExistingFile = Get-Item `
                -LiteralPath $OutputFile `
                -ErrorAction SilentlyContinue


            # 0 byte ise bozuk/yari kalmış kabul et
            if ($ExistingFile.Length -gt 0) {

                Write-Host "[VAR]     $RelativePath" `
                    -ForegroundColor DarkYellow

                $script:Skipped++

                continue
            }

            else {

                Write-Host "[0 BYTE]  Yeniden indirilecek: $RelativePath" `
                    -ForegroundColor Yellow

                Remove-Item `
                    -LiteralPath $OutputFile `
                    -Force `
                    -ErrorAction SilentlyContinue
            }
        }

# .output dosyalarını indirme
if ($FileName -match '\.output$') {

    Write-Host "[ATLANDI] .output dosyası: $RelativePath" `
        -ForegroundColor DarkGray

    continue
}
        # ====================================================
        # İNDİR
        # ====================================================

        Write-Host "[İNDİR]   $RelativePath" `
            -ForegroundColor White

        try {

            Invoke-WebRequest `
                -Uri $FileUrl `
                -OutFile $OutputFile `
                -UseBasicParsing `
                -ErrorAction Stop


            # İndirme başarılı mı?
            if (Test-Path -LiteralPath $OutputFile) {

                $DownloadedFile = Get-Item `
                    -LiteralPath $OutputFile

                if ($DownloadedFile.Length -gt 0) {

                    Write-Host "[OK]      $RelativePath" `
                        -ForegroundColor Green

                    $script:Downloaded++

                }
                else {

                    Write-Host "[UYARI]   0 byte dosya: $RelativePath" `
                        -ForegroundColor Yellow

                    $script:Errors++
                }

            }

        }
        catch {

            Write-Host "[HATA]    $RelativePath" `
                -ForegroundColor Red

            Write-Host "          $($_.Exception.Message)" `
                -ForegroundColor DarkRed

            $script:Errors++
        }

    }
}


# ============================================================
# BAŞLAT
# ============================================================

Write-Host ""
Write-Host "####################################################" `
    -ForegroundColor Cyan

Write-Host "# RESUME RECURSIVE DOWNLOADER" `
    -ForegroundColor Cyan

Write-Host "####################################################" `
    -ForegroundColor Cyan

Write-Host ""

Write-Host "Kaynak:" -ForegroundColor Gray
Write-Host $BaseUrl -ForegroundColor White

Write-Host ""

Write-Host "Hedef:" -ForegroundColor Gray
Write-Host $SiteFolder -ForegroundColor White

Write-Host ""

Write-Host "Mevcut dosyalar tekrar indirilmeyecek." `
    -ForegroundColor Green

Write-Host ""


# BAŞLAT
Get-Directory -Url $BaseUrl


# ============================================================
# SONUÇ
# ============================================================

Write-Host ""
Write-Host "####################################################" `
    -ForegroundColor Green

Write-Host "# İŞLEM TAMAMLANDI" `
    -ForegroundColor Green

Write-Host "####################################################" `
    -ForegroundColor Green

Write-Host ""

Write-Host "Yeni indirilen : $Downloaded" `
    -ForegroundColor Green

Write-Host "Mevcut atlanan : $Skipped" `
    -ForegroundColor Yellow

Write-Host "Dizin sayısı   : $Dirs" `
    -ForegroundColor Cyan

Write-Host "Hata            : $Errors" `
    -ForegroundColor Red

Write-Host ""

Write-Host "Dosyalar burada:" `
    -ForegroundColor Gray

Write-Host $SiteFolder `
    -ForegroundColor White

Write-Host ""

Virussign gibi toplu örneklerin taramaları bitince kalan malwareleri incelediğimde çalıştırılabilir dosya harici html gibi bilgisayarlara direkt zarar veremeyecek çok fazla dosya olduğunu gördüm. Bunları Kasperksy’e göndermek Kaspersky sunucularını boş yere yoracağı için bunları ayıklamak adına aşağıdaki powershell scriptini yazdım. Bu scripti çalıştığınız klasörde çalıştırılabilir dosyalar ve arşiv dosyaları hariç tüm dosyaları silmektedir.

Get-ChildItem -File | ForEach-Object {

    $bytes = [System.IO.File]::ReadAllBytes($_.FullName)

    $keep = $false

    # MZ = Windows PE
    if ($bytes.Length -ge 2 -and
        $bytes[0] -eq 0x4D -and
        $bytes[1] -eq 0x5A) {
        $keep = $true
    }

    # PK = ZIP tabanlı dosyalar
    elseif ($bytes.Length -ge 2 -and
            $bytes[0] -eq 0x50 -and
            $bytes[1] -eq 0x4B) {
        $keep = $true
    }

    if ($keep) {
        Write-Host "[KALIYOR] $($_.Name)" -ForegroundColor Green
    }
    else {
        Write-Host "[SİLİNİYOR] $($_.Name)" -ForegroundColor Red
        Remove-Item $_.FullName -Force
    }
}

Örneğin Şekil-4 te görüldüğü gibi klasörde 2 çalıştırılabilir dosya var, kalanı ise silinecek tipte dosya.

Şekil-4 Script test edilecek klasör

Scripti çalıştırdığımızda Şekil-5 teki gibi 2 çalıştırılabilir dosya hariç kalan tüm dosyalar silindi.

Şekil-5 Script test sonucu klasör durumu

Şimdi önemsiz dosyaları da sildiğimize göre kalan şüpheli dosyaları Kaspersky’e yükleme adımına geçebiliriz.

İlk olarak Kaspersky Threat Intelligence Portal‘a girip üye olup Şekil-6’da görüldüğü gibi Request Token’e basalım.

Şekil-6 Kaspersky OPENTIP Anasayfa

Şekil-7’de gözülen üstteki API Token bölümündeki request token’a basıp token api’sini oluşturalım.

Şekil-7 Kaspersky OPENTIP Request Tokens sayfası

Oluşan tokeni bir yere not alıp diğer adıma geçelim. Göz işaretine basarak görebilirsiniz.

Son aşamada bilgisayarınızda aynı klasörde KasperskyUpload.bat ve KasperskyUpload.ps1 isimlerinde iki adet dosya oluşturun.

KasperskyUpload.bat dosyasının içine aşağıdaki kodları yazıp kaydedin.

@echo off
title Kaspersky OpenTIP Bulk Upload

if "%~1"=="" (
    echo.
    echo Dosya veya dosyalar secip bu BAT dosyasinin uzerine surukleyin.
    echo.
    pause
    exit /b
)

pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "%~dp0KasperskyUpload.ps1" %*

pause

KasperskyUpload.ps1 dosyasının içine aşağıdaki kodları yazıp kaydedin. Kodlardaki $ApiToken = “***********************” değişkenindeki yıldızları silip kendi tokeninizi yazın.

# ============================================================
# Kaspersky OpenTIP - Bulk File Uploader
# PowerShell 7
# ============================================================

$ApiToken = "***********************"

# ------------------------------------------------------------
# Başlangıç kontrolleri
# ------------------------------------------------------------

if ([string]::IsNullOrWhiteSpace($ApiToken) -or
    $ApiToken -eq "BURAYA_API_TOKENINI_YAZ") {

    Write-Host ""
    Write-Host "HATA: API tokeni girilmemis!" -ForegroundColor Red
    Write-Host ""
    pause
    exit
}

if ($args.Count -eq 0) {

    Write-Host ""
    Write-Host "Dosya secilmedi." -ForegroundColor Yellow
    Write-Host ""
    pause
    exit
}

# ------------------------------------------------------------
# Sayaçlar
# ------------------------------------------------------------

$Total     = 0
$Success   = 0
$Failed    = 0
$StartTime = Get-Date

$FailedFiles = @()

# ------------------------------------------------------------
# Başlık
# ------------------------------------------------------------

Clear-Host

Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "              KASPERSKY OPENTIP BULK UPLOAD" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""

Write-Host "Toplam dosya: $($args.Count)" -ForegroundColor White
Write-Host "Gonderme modu: SIRALI" -ForegroundColor Green
Write-Host ""

# ------------------------------------------------------------
# Dosyaları tek tek gönder
# ------------------------------------------------------------

foreach ($FilePath in $args) {

    $Total++

    Write-Host "------------------------------------------------------------" -ForegroundColor DarkGray
    Write-Host "[$Total/$($args.Count)]" -ForegroundColor Cyan

    # Dosya kontrolü
    if (-not (Test-Path -LiteralPath $FilePath -PathType Leaf)) {

        Write-Host "Dosya bulunamadi!" -ForegroundColor Red
        Write-Host $FilePath -ForegroundColor DarkGray

        $Failed++

        $FailedFiles += [PSCustomObject]@{
            File   = $FilePath
            Reason = "Dosya bulunamadı"
        }

        continue
    }

    $FileName = Split-Path -Path $FilePath -Leaf

    # Dosya boyutu
    $FileInfo = Get-Item -LiteralPath $FilePath
    $FileSizeMB = [math]::Round($FileInfo.Length / 1MB, 2)

    Write-Host "Dosya : $FileName" -ForegroundColor White
    Write-Host "Boyut : $FileSizeMB MB" -ForegroundColor White
    Write-Host ""
    Write-Host "Kaspersky'ye gonderiliyor..." -ForegroundColor Yellow

    $FileStart = Get-Date

    try {

        # ----------------------------------------------------
        # API URL
        # ----------------------------------------------------

        $EncodedFileName = [uri]::EscapeDataString($FileName)

        $Uri = "https://opentip.kaspersky.com/api/v1/scan/file?filename=$EncodedFileName"

        # ----------------------------------------------------
        # Header
        # ----------------------------------------------------

        $Headers = @{
            "x-api-key" = $ApiToken
        }

        # ----------------------------------------------------
        # Dosyayı gönder
        # ----------------------------------------------------

        $Response = Invoke-WebRequest `
            -Uri $Uri `
            -Method POST `
            -Headers $Headers `
            -ContentType "application/octet-stream" `
            -InFile $FilePath `
            -TimeoutSec 300

        $FileEnd = Get-Date
        $Duration = ($FileEnd - $FileStart).TotalSeconds

        # ----------------------------------------------------
        # Başarılı
        # ----------------------------------------------------

        if ($Response.StatusCode -eq 200) {

            $Success++

            Write-Host ""
            Write-Host "BASARILI" -ForegroundColor Green
            Write-Host "HTTP : $($Response.StatusCode)" -ForegroundColor Green
            Write-Host "Sure : $([math]::Round($Duration,2)) saniye" -ForegroundColor Green

            if ($Response.Content) {

                Write-Host ""
                Write-Host "Kaspersky cevabi:" -ForegroundColor Cyan
                Write-Host $Response.Content
            }
        }
        else {

            $Failed++

            Write-Host ""
            Write-Host "BASARISIZ" -ForegroundColor Red
            Write-Host "HTTP : $($Response.StatusCode)" -ForegroundColor Red

            $FailedFiles += [PSCustomObject]@{
                File   = $FileName
                Reason = "HTTP $($Response.StatusCode)"
            }
        }

    }
    catch {

        $Failed++

        $FileEnd = Get-Date
        $Duration = ($FileEnd - $FileStart).TotalSeconds

        Write-Host ""
        Write-Host "BASARISIZ" -ForegroundColor Red

        # ----------------------------------------------------
        # HTTP hata kodunu yakala
        # ----------------------------------------------------

        $StatusCode = $null

        if ($_.Exception.Response) {

            try {
                $StatusCode = [int]$_.Exception.Response.StatusCode
            }
            catch {
                $StatusCode = $null
            }
        }

        if ($StatusCode) {

            Write-Host "HTTP : $StatusCode" -ForegroundColor Red

            switch ($StatusCode) {

                400 {
                    Write-Host "Bad Request" -ForegroundColor Yellow
                }

                401 {
                    Write-Host "Unauthorized - API token gecersiz." -ForegroundColor Yellow
                }

                413 {
                    Write-Host "Payload Too Large - Dosya boyutu cok buyuk." -ForegroundColor Yellow
                }

                429 {
                    Write-Host "Too Many Requests - Rate limit olabilir." -ForegroundColor Yellow
                }

                500 {
                    Write-Host "Kaspersky server hatasi." -ForegroundColor Yellow
                }

                502 {
                    Write-Host "Bad Gateway." -ForegroundColor Yellow
                }

                503 {
                    Write-Host "Kaspersky servisi gecici olarak kullanilamiyor." -ForegroundColor Yellow
                }

                default {
                    Write-Host "HTTP hata kodu: $StatusCode" -ForegroundColor Yellow
                }
            }

            $Reason = "HTTP $StatusCode"
        }
        else {

            $Reason = $_.Exception.Message

            Write-Host "Hata: $Reason" -ForegroundColor Red
        }

        Write-Host "Sure : $([math]::Round($Duration,2)) saniye" -ForegroundColor DarkGray

        $FailedFiles += [PSCustomObject]@{
            File   = $FileName
            Reason = $Reason
        }
    }

    # --------------------------------------------------------
    # Anlık durum
    # --------------------------------------------------------

    Write-Host ""
    Write-Host "Durum: $Success basarili / $Failed basarisiz / $Total islenen" `
        -ForegroundColor Cyan

    Write-Host ""

}

# ============================================================
# SONUÇ
# ============================================================

$EndTime = Get-Date
$TotalDuration = ($EndTime - $StartTime).TotalSeconds

Write-Host ""
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host "                     ISLEM TAMAMLANDI" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""

Write-Host "Toplam dosya     : $Total" -ForegroundColor White
Write-Host "Basarili         : $Success" -ForegroundColor Green
Write-Host "Basarisiz        : $Failed" -ForegroundColor Red
Write-Host "Toplam sure      : $([math]::Round($TotalDuration,2)) saniye" -ForegroundColor White

if ($Total -gt 0) {

    $SuccessRate = [math]::Round(($Success / $Total) * 100, 2)

    Write-Host "Basari orani     : $SuccessRate %" -ForegroundColor Cyan
}

# ------------------------------------------------------------
# Başarısız dosyalar
# ------------------------------------------------------------

if ($FailedFiles.Count -gt 0) {

    Write-Host ""
    Write-Host "============================================================" -ForegroundColor Red
    Write-Host "                 BASARISIZ DOSYALAR" -ForegroundColor Red
    Write-Host "============================================================" -ForegroundColor Red
    Write-Host ""

    foreach ($Item in $FailedFiles) {

        Write-Host "Dosya : $($Item.File)" -ForegroundColor Yellow
        Write-Host "Hata  : $($Item.Reason)" -ForegroundColor Red
        Write-Host ""
    }
}
else {

    Write-Host ""
    Write-Host "Tum dosyalar basariyla gonderildi." -ForegroundColor Green
}

Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""

pause

Artık şüpheli dosya örneklerini gönderebiliriz. Tek yapmamız gereken şüpheli dosyalarının hepsini seçip KasperskyUpload.bat dosyasının üzerine sürükleyip bırakmak. Bunu yaptığımız an aşağıdaki Şekil-8 ve Şekil-9’da görüldüğü gibi şüpheli dosyalar Kaspersky sunucularına gönderilmeye başlanacak ve gönderdiğiniz dosyada zararlı yazılım davranışı tespit edilirse, gerekli analizlerin ardından yayınlanacak ilk güncelleme ile Kaspersky uygulamalarının dünya genelinde bu zararlı yazılımı tanıması ve engellemesi sağlanacaktır.

Şekil-8 Şüpheli dosya gönderim anı
Şekil-9 Şüpheli dosya gönderim anının devamı

Sizler de şüpheli olduğunu düşündüğünüz dosyaları Kaspersky’ye göndererek daha güvenli bir internet ortamının oluşturulmasına katkıda bulunabilirsiniz.

İyi çalışmalar.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir