2026-11-11

PDF dosyalarında zararlı kod analizi

Epostalar ile her gün çeşitli zararlı kodlar geliyor. Bunları açmadan (çift tıklayıp ilgili program ile görüntülenmesini sağlamadan) içeriğinde zararlı kodlar olup olmadığını anlayabilir miyim? Şu sayfadaki bilgiler hoşuma gitti, paylaşmak istedim.

PDF dosya yapısı şu şekilde tarif edilmiş:

Başlık

Gördüğüğüm kadarıyla tek satırlık, % işareti ile başlayıp dosya sürümünü gösteren bir veri. 

%PDF-1.7

Gövde

Belgenin içinde yer alan bir dizi nesnenin listelendiği bölüm. Şu şekilde bir yapı:

1 0 obj
...
2 0 obj
...
3 0 obj
...

Çapraz Başvuru

Belge içinde farklı nesnelerin konumlarının yer aldığı bölüm. xref anahtar kelimesi ile başlayan şöyle bir yapı:

xref
...

Son bölüm

Belgenin kapanışının yapıldığı bölüm. trailer anahtar kelimesi ile başlıyor. Birden fazla trailer olabiliyor. En sonda da %%EOF gibi bir son bölüm oluyor.

trailer
...
%%OEF 

Tehlikeli olabilecek bölümler

/JavaScript or /JS: Belgede javascript kodu olduğunu gösterir. Bu kod belge açıldığında çalışabilir.

/Names: Dosyanın bir eki veya nesnesi olduğunu gösterir.

/OpenAction or /AA (Additional Action): Dosyanın otomatik bazı kodlar/nesneler çalıştırabileceğini gösterir.

/EmbeddedFile: Bu da dosyanın bir gömülü script/kod/dosya içerdiğini gösterir.

/URI or /SubmitForm: Dosyanın başka bir web adresine erişebileceğini veya harici HTML-form öğesine veri gönderebileceğini (post) gösterir

/Launch: PDF görüntüleyicinin başka bir program veya dosyayı çalıştırmasını ister. Dosyaya gömülü olmayan harici dosya veya programlar için.

Bunların herhangi biri net bir zararlı kod olduğunu tek başına göstermeyebilir. Ama bir /URI olması ve bunun dosya açıldığında tetiklenmesi, uzak bir komuta kontrol merkezindeki sunucudan zararlı bir kod indirdiğinin göstergesi olabilir.

İnceleme araçları

PDF dosyalarının meta verilerini incelemek için exiftool faydalı olabilir. Aracın geliştiricisi Phil Harvey. winget ile indirilebilecek kopya Oliver Betz'in paketlemesi gibi.

exiftool p.pdf
ExifTool Version Number         : 13.59
File Name                       : p.pdf
Directory                       : .
File Size                       : 188 kB
File Modification Date/Time     : 2026:11:06 15:32:35+03:00
File Access Date/Time           : 2026:11:06 17:50:34+03:00
File Creation Date/Time         : 2026:11:06 15:32:36+03:00
File Permissions                : -rw-rw-rw-
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.7
Linearized                      : No
Page Count                      : 1
Language                        : en
Tagged PDF                      : Yes
XMP Toolkit                     : 3.1-701
Producer                        : Microsoft® Word 2024
Creator                         : Heritage Abajesude
Creator Tool                    : Microsoft® Word 2024
Create Date                     : 2026:11:05 11:12:02+01:00
Modify Date                     : 2026:11:05 11:12:02+01:00
Document ID                     : uuid:FF8B01BC-ED4C-4316-842C-634C4A670C36
Instance ID                     : uuid:FF8B01BC-ED4C-4316-842C-634C4A670C36
Author                          : Heritage Abajesude

Sysinternals strings aracı da pdf dosyasının içindeki yapının çalıştırılmadan görüntülenmesini sağlayabilir.


strings64 .\p.pdf

Powershell ile komutun çıktısı içinde aramalar yapılabilir, sonuçlar filtrelenebilir:


strings64 .\p.pdf | sls "\d 0 obj"

Bir de strings'e satır numarası ekleyerek (dosyanın içindeki offset değerleri değil, sadece strings64 komutunun çıktısının içindeki satır numarası), bulunan ilgili satırın 5 öncesi ve 5 sonrasını da dahil ederek arama genişletilebilir.


$satir=0;strings64 .\p.pdf | % {"$satir $_";$satir++} | sls "/UR|/NAME|/JAVAS|/JS|/EMBED|/OpenAc|/AA|/Launch|eval|export" -context 5,5

Belgede dosyanın hash'inin hesaplanarak virustotal.com gibi bir sitede aratılması da önerilmiş.


Get-FileHash -path .pdf -Algorithm SHA256

Sıkça kullanılan pdfid.py ve pdfparser.py gibi araçlardan faydalanılabileceği de anlatılmış. Bu araçlar


pip install pdfid

gibi araçlarla edinilebileceği gibi


git clone https://github.com/DidierStevens/DidierStevensSuite.git

şeklinde Didier Stevens'ın Github'dan reposundan da indirilebilir

Riskli bölümler hakkında bir özet almak için pdfid.py kullanılabilir


pdfid.py supheli.pdf
 PDF Header: %PDF-1.4
 obj                   23
 endobj                23
 stream                 5
 endstream              5
 xref                   1
 trailer                1
 startxref              1
 /Page                  1
 /URI                   2
Ama bunların hiçbiri, dosyanın aslında içinde kullanıcıyı yanlış yönlendirmek için ne gibi bir kurmaca hazırladığını göstermez. Açmadan dosyanın için görmek için pdf'i bir resim dosyasına dönüştürecek araçlar kullanılabilir. Windows tarafında:


winget install --id oschwartz10612.Poppler -e

Veya linux tarafında:


sudo apt install poppler-utils

sudo apt install mupdf-tools

Örneğin aşağıdaki komutlar, supheli.pdf dosyasından supheli-1.png, supheli-2.png gibi resim dosyaları üretir:


pdftoppm -png -r 100 -f 1 -l 1 supheli.pdf sayfa

mutool draw -o sayfa-%d.png -r 100 supheli.pdf 1

Ama bu işlemlerin hepsinin bir sanal makinede yapılması önemle tavsiye edilir. PDF'i resme dönüştürecek araç bile istenmeden, sinsice tasarlanmış bir tuzak ile bazı mekanizmaları tetikleyebilir, zararlı yazılımı aktive edebilir.

---
[1] https://zeltser.com/analyzing-malicious-documents
[2] https://sansorg.egnyte.com/dl/YrwOdFIm1I
[3] https://amr-git-dot.github.io/malware%20analysis/Mal-Docs/
[3] https://medium.com/@alaamansouraliahmed/is-that-pdf-safe-how-to-spot-malicious-documents-before-you-open-them-de890ca10eac

2026-11-10

Out-Gridview

Powershell'de bir cmdlet'in sonuçlarını kendine özgü başka bir pencerede tablo biçiminde görüntülemeye yarayan bir aracı var. En basit kullanım ile

Get-Process | Out-Gridview

Alias'larla kullanmayı istersek

ps | ogv

Birden fazla grid kullandıysam ve arka planda açık kaldıysa hangi tablonun hangi komutun çıktısı olduğunu karıştırmamak için başlık eklenebilir


Invoke-Command -Computername sunucu01 -ScriptBlock {Get-Service | Where-Object {$_.Status -eq "Running"}} | Out-Gridview -Title "Sunucu01 - çalışan hizmetler"

icm -cn sunucu01 {gsv | ? Status -eq "Running" | ogv -t "Sunucu01 - çalışan hizmetler"

Grid nesnesi sütunlara göre sıralama ve filtreleme yapabilen yetenekli bir nesne. Burada gerekli işlemleri yapıp bir veya daha fazla satırı "seçip" çıktı dışarıya verilebilir (-PassThru).


Get-Process | Out-Gridview -Title "Süreçler" -PassThru

ps | ogv -t "Süreçler" -p

PassThru'ya çok benzeyen bir de OutputMode parametresi var. Tek farkı tekli/çoklu seçim yapmayı mümkün kılması.


Get-Process | Out-Gridview -Title "Süreçler" -OutputMode Multiple

ps | ogv -t "Süreçler" -o m

Bu özellikler farklı amaçlarla kullanılabilir. Örneğin, hem ekranda gösterip hem de bir dosyaya yazmak:


Get-Process | Out-Gridview -Title "Süreçler" -PassThru | Export-Csv -Path "D:\surecler.csv"

ps | ogv -t "Süreçler" -p | epcsv D:\surecler.csv

Ya da eski dosyaları silmek:


Get-ChildItem -Path D:\dosyalar | Out-GridView -Title "Dosyalar" -OutputMode Multiple | Foreach-Object {Remove-Item $_}

gci | ogv -t "Dosyalar" -o m | % {ri $_}

Sanki

-PassThru
ile
-OutputMode Multiple
aynı şey gibi.

2026-11-09

Fedora 44 ve dnf5

Fedora 44'ü terminalden 45'e yükseltmek için uyguladığım adımlar:

Önce 44 içinde en son güncelleştirmelerin yüklü olduğundan emin oldum.

sudo dnf5 upgrade

Yükseltme öncesinde sürüm sorunlarının olmadığından emin oldum.

sudo dnf5 distro-sync --refresh

sorun ile karşılaşılırsa bu satırda --allowerasing gerekebilir. Silme olacak durumlarda komutu işletmeden önce --assumeno kullanmak mantıklı olur.

yerel paket veritabanındaki tutarsızlıkları kontrol etmek için

sudo dnf5 check

kullanılabilir.  Eksik bağımlılıklar ve sürüm uyuşmazlıkları için --dependencies --obsoleted parametreleri eklenebilir.

İndirmelere başlamadan önce kök (ve eğer ayrı bir disk bölümündeyse /var) disk bölümünün boyutunu kontrol edip en az 3 GB boş yer olduğundan emin oldum.

df -h / /var

Sonrasında indirmeye başladım.

sudo dnf5 system-upgrade download --releasever=45

İndirme bittiğinde kurmak için

sudo dnf5 offline reboot

kullandım ve herşey bitip sistem açıldıntan sonra indirilmiş dosyaları kaldırmak için

sudo dnf5 offline clean

satırı ile temizlik yaptım.

2026-11-06

Önceki komutun parametresini kullanmak

Bash'in klavye kısayollarını incelerken çok faydalı bir kısayol buldum.

Diyelim ki profil klasörümdeyim ve Belgelerim klasöründe bir alt klasör oluşturacağım.

mkdir ./Belgelerim/veri

sonraki adımda da bu klasöre geçmek istiyorum. Bunun için yapmam gereken 

cd ./Belgelerim/veri

ama cd komutundan sonra ./Belgelerim/veri parametresini tekrar yazmak istemiyorum. Bunun için Alt+. kısayolu (alt ve nokta) var. Sadece cd yazdıktan sonra Alt ve . (nokta) kombinasyonunu kullanarak bir önceki komutun parametresini almak mümkün.

Bunu powershell'de yapmam mümkün mü diye merak ettim. Gördüm ki PSReadline'ın YankLastArg işlemi için de aynı Alt+. klavye kısayolu oluşturulmuş ve o da  aynı işi yapıyor:

Get-PSReadLineKeyHandler | ? Function -eq "YankLastArg"
Key   Function    Description
---   --------    -----------
Alt+. YankLastArg Copy the text of the last argument to the input

2026-11-03

Powershell betiklerine kullanıcı adı ve parola vermenin yolları

Bir yol Get-Credential cmdlet'i ile.


$crd=Get-Credential "ETKIALANI\kullaniciadi"

Bu satır sonunda $crd değişkeninde bir kullanıcı adı ve parola bilgisi oluştu. Bunu örneğin


Invoke-Command -computername uzakpc -ScriptBlock { ... } -Credential $crd

şeklinde kullanabiliriz.

Bu $crd değişkeninin tipine baktığımda


$crd | Get-Member

Typename olarak System.Management.Automation.PSCredential gözüküyor. Doğrudan bunu New-Object cmdlet'iyle birlikte kullanabilirim:


$crd = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password

Bu da aynı işi görür.

2026-10-26

Ev klasörü konumunu değiştirmek

Linux'ta olduğu gibi Powershell'de de tilda "~" karakteri ev konumunu ($HOME) gösteriyor. cd komutuyla doğrudan C:\Users\metin konumuna gitmek mümkün

cd ~

Ben ev konumumu C:\users\metin klasöründen başka bir yer olmasını istiyorum. Ama oturum açtığımda profil verilerimin depolanacağı C:\Users\metin klasörünün değişmesini istemiyorum. Sadece powershell'de tilda karakteri ile ifade edilen yerin D:\klasor gibi bir yer olmasını istiyorum.

Görünüşe göre bunu $HOME değişkeninin içeriğini değiştirerek yapamıyorum, çünkü bu değişken değiştirilemeyen, read-only bir yapıda.

Şurada ve burada gördüm ki, Get-PSDrive ile Filesystem sağlayıcısının Home adında bir alanı var ve bu değiştirilebiliyor.

(Get-PSProvider FileSystem).Home = "D:\klasor"

Bunu $profile dosyamın içine koyarsam istediğim olur. 

2026-10-24

netcat ile sunucu ve dinleyici

Linux altında nc, Windows altında ncat ile yerel ağda küçük bir sunucu ve dinleyici kurulabilir. Basit bir yapı için Linux üzerinde bir sunucu oluşturayım.

nc -l 1234

1234/tcp portu ile dinleme başladı. Ya güvenlik duvarı kapalı olmalı, ya da 1234/tcp için kural oluşturulmalı. Benzer şekilde Windows istemci üzerinde de ncat ile bu porta bağlanalım.

ncat 192.168.7.7 1234

Herşey yolunda giderse bu aşamada karşı tarafa bağlantı gerçekleşir. İki bilgisayardan da bu terminallere girilen karakterler karşı tarafa gönderilir. Yani basit bir chat platformu gibi.

Bir de dosya göndermeyi deneyelim. En basit hali ile sunucuyu alıcı olarak yapılandırıp gelen verileri bir dosyaya kaydetmesini isteyelim. Dosyanın şu an için bir txt dosyası olduğunu varsayıyorum.

ncat -l 1234 > dosya.txt

Gönderen Windows makinede de bir dosya seçip gönderelim. Bunu yapmanın iki yolu var. İlki cmd.exe ile.

ncat.exe 192.168.7.7 1234 < D:\dosya.txt

İkinci powershell ile.


Start-Process "D:\Nmap\ncat.exe" -ArgumentList "192.168.7.7 1234" `
    -NoNewWindow `
    -RedirectStandardInput "D:\dosya.txt"

Bir adım öteye gidiyorum; dosyayı gönderen sunucu olsun. Sunucunun linux olması durumundan başlayalım. Linux'ta bash ile bir oluştalım.


while true; do
    {  	printf 'HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Disposition: attachment;
        filename="dosya.zip"\r\nContent-Length: ';
        stat -c %s dosya.zip | tr -d '\n';
        printf '\r\nConnection: close\r\n\r\n'; cat dosya.zip; } | nc -l -p 8080
done

Bu yapılandırma ile linux sunucu üzerinde mevcut klasörde bulunan dosya.zip'i indirmek isteyen karşı tarafın yapması gereken, web tarayıcısının adres satırına

http://192.168.7.7:8080

gibi bir ifade yazmak. Üstteki bash dosyasında yapılandırmayı 8080 portu üzerinden yaptım. Tarayıcı bağlanır bağlanmaz bir dosya indirecek. Metin verisi olmasına gerek yok, binary dosyalar da aktarılabilir.

Sunucunun Windows olması durumunda işi powershell ile yürütebiliriz.



$file = 'D:\dosya.zip'
$port = 8080

$listener = [System.Net.Sockets.TcpListener]::new(
    [System.Net.IPAddress]::Any, $port
)
$listener.Start()

Write-Host "Dosya: $file"
Write-Host "Port: $port"
Write-Host "Durdurmak icin Ctrl+C"

while ($true) {
    $client = $listener.AcceptTcpClient()

    try {
        $stream = $client.GetStream()

        $reader = [System.IO.StreamReader]::new(
            $stream, [System.Text.Encoding]::ASCII
        )
        $request = $reader.ReadLine()
        while ($reader.ReadLine() -ne '') {}

        $name = [System.IO.Path]::GetFileName($file)
        $length = (Get-Item -LiteralPath $file).Length

        $header = "HTTP/1.1 200 OK`r`n"
        $header += "Content-Type: application/octet-stream`r`n"
        $header += "Content-Disposition: attachment; filename=`"$name`"`r`n"
        $header += "Content-Length: $length`r`n"
        $header += "Connection: close`r`n`r`n"

        $bytes = [System.Text.Encoding]::ASCII.GetBytes($header)
        $stream.Write($bytes, 0, $bytes.Length)

        $fs = [System.IO.File]::OpenRead($file)
        try {
            $fs.CopyTo($stream)
        }
        finally {
            $fs.Dispose()
        }

        Write-Host "Gonderildi: $request"
    }
    catch {
        Write-Warning $_
    }
    finally {
        $client.Close()
    }
}

netcat demiştim, konunun biraz dışına çıktım.

---

https://anto.online/netcat-command-line-cheat-sheet/
https://anto.online/nmap-command-line-cheat-sheet/