2026-09-07

Unicode - UTF-8 ilişkisi

İlk başta ASCII vardı. Her karakter 8 bitlik (1 byte) verilerle kodlanmıştı. A karakterine 10'luk düzende 65 numarası verilmişti.

Keşke herşey bu kadar kolay olsaydı. Arapça, Çince vs. dillerin de bilgisayarda ifade edilebilmesi için bu standardın büyütülmesi gerekti. Örneği Japon alfabesindeki 負 karakterinin ifadesi için onluk düzende 36000 değeri belirlendi. 65535'e kadar sayıların saklanması için 2 byte gerekti. Ama her karakteri 2 byte ile saklamak istersek bir çok karakter için yüksek basamaklar 0'dan ibaret olacaktı ve dosya boyutları doğrudan 2 katına çıkacaktı. Bunun üstesinden gelebilmek için karakterleri yeterli sayıda byte ile ifade edebilmek için UTF-8, UTF-16 (unicode transformation format) gibi standartlar geliştirildi. Üstelik Unicode karakterler için 2-byte sınırı da yok.

Örneğin Japoncadaki 負 kelimesinin unicode sistemindeki karşılığı 8CA0 ve buna unicode codepoint deniyor. Bu

U+8CA0

şeklinde ifade ediliyor. Kodlama için aşağıdaki tabloya göre hareket ediyoruz.

İlk code pointSon code pointByte 1Byte 2Byte 3Byte 4
U+0000U+007F0yyyzzzz   
U+0080U+07FF110xxxyy10yyzzzz  
U+0800U+FFFF1110wwww10xxxxyy10yyzzzz 
U+010000U+10FFFF11110uvv10vvwwww10xxxxyy10yyzzzz

Bizim sayımız U+800 ile U+FFFF arasında olduğu için bu satıra göre işlem yapacağız. 3 byte ile ifade etmemiz gerek.

Önce sayımızı ikilik düzende (binary) olarak yazalım:

1000 1100 1010 0000
8    C    A    0

Tablonun 3. satırına göre bunu 3 parçaya bölmemiz gerek. Sağdan başlayarak 6 bit alalım. Sonra bunun başına, tablonun 3. satırının Byte-3 sütununda yazıdığı gibi 10 ekleyeceğiz.

10 100000 = A0

Byte-3'ü bu şekilde A0 olarak hesapladık. Benzer şekilde Byte-2'yi de yine tabloya bakarak sonraki en düşük 6 bitlik bölümü alıp başına yine 10 ekleyerek hesaplayacağız.

10 110010 = B2

Byte-2'yi de B2 olarak hesapladık. Geriye Byte-1 kaldı. Bunun için kalan 4 bit veriyi alıp başına 1110 ekleyeceğiz.

1110 1000 = E8

Sonuç: 負 karakteri, Unicode code point olarak U+36000 ifade ediliyor. UTF-8 olarak kaydedilmek istenirse diske 3 byte olarak E8 B2 A0 olarak yazılıyor.

2026-09-04

Kayıt defterine powershell ile erişim

Windows kayıt defteri (registry) erişimi grafik arayüzle yapılabildiği gibi reg.exe aracı ile de yapılabiliyor. reg.exe'nin query, add, delete, import, export (bunlarla sınırlı değil) gibi komutları var. Örneğin bir anahtarı bir dosyaya yedeklemek için

reg export HKLM\Software\Microsoft\Windows\CurrentVersion\Run reg_export.reg

gibi bir komut, bir bozulma durumunda da bu anahtarı dosyadan geri yüklemek için

reg import reg_export.reg

yeterli. Benzer şekilde Run anahtarı altındaki değerleri sorgulamak için

reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run

kullanılabilir. Bu anahtar altına yeni bir değer eklemek için

reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v YeniDeger /t REG_DWORD /d 9876

Ya da var olanı silmek için

reg delete HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v YeniDeger

Bunlar güzel, ama nesne çıktıları veren, daha yetenekli Powershell cmdlet'lerimiz de var. Bu cmdlet'ler kayıt defterine özel değil, tüm PSDrive nesneleri üzerinde kullanılabilen cmdlet'ler.

Kayıt defterindeki verileri 2 ana kategoride değerlendirelim. Anahtarlar ve bu anahtarların altındaki özellikler. Örneğin

HKLM\Software\Microsoft\Windows\CurrentVersion\Run

bir anahtar, ve bu anahtarın altında oluşturduğum

YeniDeger = (REG_DWORD) 9876

verisi de özellik.

Bir anahtarı üzerinde işlem yaparken *-Item ile biten cmdlet'leri kullanıyoruz. Özellikler için ise *-ItemProperty cmdlet'lerini. Örneğin hedefimiz HKLM\Software\Microsoft\Windows\CurrentVersion\Run anahtarını bir değişkene atmak için Get-Item'ı şu şekilde kullanabiliriz

$anahtar = Get-Item -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run"

Powershell'de HKLM bir PSDrive olduğu için bundan sonra iki nokta üst üste ":" işareti koyarak bir sürücü yolu oluşturdum.

Bu anahtarın altındaki özellikleri (değişken ve değerlerini) dönmek için Get-ItemProperty cmdlet'ini ve -Name parametresini kullanabiliriz.

Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "Program1"

Sadece bu özelliğin değerini göstermek için 

(Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run").Program1

yapmak yeterli.

Aslında bu iki cmdlet'i sadece kayıt defteri erişiminde değil, diğer konularda da kullanabiliyoruz. Örneğin Get-Item'ı ortam değişkeni ProgramData'yı okumak için

Get-Item -Path env:ProgramData

şeklinde kullanabiliriz.

Get-ItemProperty bir öğenin özelliklerini okumak için kullanılır. Bu özellikleri ayarlamak için ise Set-ItemProperty cmdlet'i var. Bir dosyayı read-only (sadece okunbilir) duruma getirmek için şu şekilde kullanım mümkün

Set-ItemProperty -Path "C:\klasor\dosya.txt" -Name IsReadOnly -Value $true

Bir bilgisayara takılmış tüm USB cihazların listesinin tutulduğu HKLM\SYSTEM\CurrentVersion\ENUM\USB altındaki tüm HardwareID değerlerini özyinelemeli olarak listelemek için, kısaltmalarla:

dir "HKLM:\SYSTEM\CurrentControlSet\ENUM\USB" -rec -ea sil | gp | ? {$_.HardwareID} | select HardwareID

 

2026-09-02

Windows ISO dosyalarının indirilmesi

Windows update hep yavaştı. Windows ISO dosyası indirme de öyle. Üstelik de düz HTTP üzerinden gerçekleşiyor. Bütün Linux dağıtımları güncellemelerini bile yüksek hızlı HTTPS bağlantıları üzerinden yaparken, Microsoft gibi bir firma bunu ~40 Mbps hızında, güvenli olmayan sunucular üzerinden yapıyor.

Bir Windows ISO dosyası indirmek için

https://www.microsoft.com/en-in/software-download/windows11

sayfasına gidip önce MediaCreationTool.exe'yi indirdikten sonra onu çalıştırıp ISO dosyası indirme süreci başladığında sorumluluk BITS'e bırakılıyor. Arka planda bu işlemi BITS yapıyor.

Get-BitsTransfer -AllUsers
JobId                                DisplayName               TransferType JobState     OwnerAccount
-----                                -----------               ------------ --------     ------------
acb23d6d-f557-4793-a84d-661a0499e879 Windows Dlp Manager       Download     Transferring metin

Kaynak izleyicisinde "Ağ" sekmesine geçip "Al" sütununu azalan şekilde sıraladıktan sonra en üstte svchost süreçlerinden biri en yüksek trafiği yapıyor gözüktü. Bu süreç kimliğini aradığımda BITS'ı buldum.

gcim win32_service | where ProcessId -eq 17730

Sonrasında da Get-BitsTransfer ile işin "Windows Dlp Manager" adı altında gerçekleştiğini buldum. En son olarak Get-NetTCPConnection ile bu sürecin hangi bağlantılarını listelediğimde 80/tcp bağlantısını gördüm.

Get-NetTCPConnection -OwningProcess 17730 | ft RemoteAddress, RemotePort, State -AutoSize
RemoteAddress          RemotePort       State
-------------          ----------       -----
92.223.40.60           80               Established

2026-08-27

Powershell'de EFS altyapısını kullanarak dosya şifreleme

EFS (encrypting file system), Windows işletim sisteminin sadece NTFS dosya sistemi üzerinde bir dosya şifreleme yöntemi.

Bilgisayarımızda 2 kullanıcımız var, user1 ve user2. İkisinin de ortak erişiminin olduğu bir klasör olsun. C:\klasor gibi. Bu klasör içinde dosya.txt adında bir dosya var. Bu dosyaya da 2 kullanıcımızın erişimi var. user1 kullanıcısı bu dosyayı aşağıdaki gibi şifrelesin.

(Get-Item -Path "C:\klasor\dosya.txt").encrypt()

Bu işlem sonunda dosya user1 tarafından erişilmeye devam eder. Açılırken bir şifre falan sormaz, ama dosyanın simgesine sarı bir asma kilit sembolü eklenir. Aşağıda biri henüz şifrelenmemiş, diğeri şifrelenmiş 2 dosyanın simgeleri var.

Bu dosyayı sistemdeki başka bir kullanıcı açamaz. Dosya sadece NTFS biriminde şifrelenmeye devam edebileceği için dosya FAT veya desteklemeyen başka bir dosya sistemi üzerine taşınamaz. Dosya gezgini üzerinde dosya özelliklerinden "Gelişmiş" tıklandığında aşağıdaki gibi "Encrypt contents to secure data" veya Türkçe olarak "Veriyi korumak için içeriği şifrele" kutusu işaretli gözükür.


Powerhshell ile dosyanın öznitelikleri arasında Encrypted bulunur:

(Get-Item -Path "C:\klasor\dosya.txt").Attributes

Archive, Encrypted

Dosyayı şifrelemek için PKI (public key infrastructure) yapısı gereği bir "sertifikaya" ihtiyaç duyulur. Yetkili bir sertifika otoritesinin bulunduğu bir Active Directory ortamında değilsek, bilgisayarda da EFS amaçlı kullanılabilecek başka bir sertifika da yoksa, bilgisayar kendi kendine bir sertifika üretecektir. Bu işlem kullanıcı müdahalesine gerek kalmadan arka planda yapılır. Böyle bir sertifikanın varlığı

cipher /y

veya Powershell ile sertifika PSDrive içeriği sorgulanarak görülebilir.

Get-ChildItem Cert:\CurrentUser\My | 
	Where-Object { $_.EnhancedKeyUsageList.FriendlyName -contains 'Encrypting File System' }

Dosyayı tekrar şifrelenmemiş haline getirmek için 

(Get-Item -Path "C:\klasor\dosya.txt").decrypt()

kullanmak gerekir. Dosyayı şifrelenmemiş hale getirmek sertifikayı silmez.

2026-08-18

Powershell'de "cannot validate argument on parameter" hatası

Uzak bir bilgisayara Powershell'in Copy-Item cmdlet'i ile, uzak oturumlar (PS remote sessions) kullanarak veri kopyalıyordum. Her zamanki gibi oturumu oluşturdum:

$oturum = New-PSSession -Computername 192.168.11.27

Var olduğunu bildiğim bir uzak klasöre, yerel bilgisayarımda var olduğunu doğruladığım bir exe dosyayı atmaya başladım.

Copy-Item -Path "C:\klasor\dosya.exe" -ToSession $oturum -Destination "C:\klasor"

Ama şu hata ile karşılaştım:

Copy-Item : Cannot validate argument on parameter 'b64Fragment'. The argument is null or empty. Provide an argument that is not n
ull or empty, and then try the command again.
Copy-Item : Failed to copy file C:\klasor\dosya.exe to remote target destination.
At line:1 char:1

Kullandığım komut tam olarak yukarıda yazdığım gibiydi, b46Fragment gibi bir parametre kullanmadım.

Aradım, ama bu hataya benzer bir hata ile karşılaşan birini bulamadım. Ama dosya karşı tarafa kopyalanmıştı. Yerel ve uzak dosya hash'lerini karşılaştırdım, fark bulamadım.

Get-FileHash -Path "C:\klasor\dosya.exe"
Invoke-Comand -Session $oturum -Script {Get-FileHash -Path "C:\klasor\dosya.exe")

Bu da böyle bir durum olarak kaldı. 

2026-08-17

Linux'ta süreçler ve PID'ler

Bash ile çalışırken mevcut bash prosesinin ID'sini öğrenmek için

echo $$

Mevcut shell bilgisini verecek olan ifade

echo $SHELL

Peki şu an hangi terminal'i kullanıyoruz dersek

echo $PPID

bash'in parent proces ID'sini verir ki o da aslında terminal'imiz olacak. Emin olmak için pstree ile işlem ağacını görebiliriz.

pstree -sp $$

Burada

-s : seçili sürecin (ki burada $$ mevcut bash ID'sini dönecek) tüm parent zincirini döner

-p : PID'leri gösterir

İsmi bilinen bir prosesin ID'sini öğrenmek için

pidof gedit

2026-08-16

Bir süreci başlatan süreç ve hizmetler ilişkileri

Daha önce kısmen bu konuyla ilgilenmiştim ama yeterli olmamıştı.

Komut satırından bir süreci başlatan süreci bulmak istiyourm. Örneğin bir notepad süreci var. Bunu başlatan süreci Get-Process ile bulmak mümkün değil. Bir WMI/CIM sorgusu lazım. Bunu da hem PID, hem de süreç ismi ile çalışacak şekilde yapmam gerek. Ben şöyle bir parent.ps1 dosyası oluşturarak yaptım:

param(
    [Parameter(Position=0,Mandatory=$true,ParameterSetName="ProcessName")]
    [string]$ProcessName,
    [Parameter(Position=0,Mandatory=$true,ParameterSetName="ProcessId")]
    [int]$ProcessId
)

switch ($PSCmdlet.ParameterSetName) {
    "ProcessName" {
        Get-CimInstance Win32_Process |
            Where-Object Name -match ${ProcessName}  |
                Format-Table -Property ProcessId, ParentProcessId, Name, CommandLine -AutoSize -Wrap
    }
    "ProcessId" {
        Get-CimInstance Win32_Process -Filter "ProcessId='$ProcessId'"  |
            Format-Table -Property ProcessId, ParentProcessId, Name, CommandLine -AutoSize -Wrap
    }
}

bunuda

.\parent.ps1 -ProcessName notepad

şeklinde çalıştırınca şöyle bir çıktı verdi:

ProcessId ParentProcessId Name        CommandLine
--------- --------------- ----        -----------
    12216            3708 Notepad.exe "C:\Windows\System32\notepad.exe" 

Buradan 3708'i sorguladığımda bana svchost döndü.

ps -id 3708
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    450      21     7576      51272              3708   0 svchost 

Bu noktada da win32_service sınıfını sogrulamak gerek, 3708'in içinde hangi hizmetler çalışıyor diye:

param(
    [Parameter(Mandatory,ParameterSetName="SearchID")][int]$Id,
    [Parameter(Mandatory,ParameterSetName="SearchName")][string]$Name,
    [Parameter(Mandatory,ParameterSetName="SearchDisplayName")][string]$DisplayName
)

if ($PSCmdlet.ParameterSetName -eq "SearchID") {
    gcim win32_service | where {$_.ProcessId -eq $Id}
}
elseif ($PSCmdlet.ParameterSetName -eq "SearchName") {
    gcim win32_service | where {$_.Name -like "*${Name}*"}
}
elseif ($PSCmdlet.ParameterSetName -eq "SearchDisplayName") {
    gcim win32_service | where {$_.Name -like "*${DisplayName}*"}
}

Bunu da serv.ps1 diye kaydedip

.\serv1.ps1 -Id 3708

şeklinde çalıştırınca

ProcessId Name     StartMode State   Status ExitCode
--------- ----     --------- -----   ------ --------
3708      Schedule Auto      Running OK     0

Notepad'i çalıştıran hizmetin görev zamanlayıcısı olduğunu buldum.