Herkese selamlar,
Bu yazımda gönderilen 2 PNG dosyasından 1 tanesi içinde herhangi bir zararlı amaç olup olmadığını inceleyeceğiz. Diğer dosyayı da inceledim benzer sonuçlar aldım.
Amaç burada kendim için not defteri oluşturmak ve bu bilgiler üzerinden kendime daha detaylı çalışma alanları açmak. Ne kadar derine inebilirim sorusunun peşinden gitmekti. Burada yaptığım çalışmalar C ve Assembly tarafında yapmak istediğim çalışmalar için bir ön hazırlık oluşturuyor. Dosya bana aslında güvenilir bir kaynaktan geldi fakat ben prensip gereği dosyaları tararım.
Bu analiz, gönderilen bir PNG dosyasının steganografi, veri gizleme veya zararlı payload içerip içermediğini doğrulamak amacıyla yapılmıştır. Öncelikle PNG, PDF veya benzer dosyalar silahlandırılabiliyor. Tek seferlik bile olsa shell açmak için tetikleme amaçlı kullanılabilir. Dosya örneğimiz bir PNG olduğu için incelemelere başlıyoruz. Dosya temiz görünmekte ancak nelere dikkat edilmesi gerektiğini anlatmaya çalışacağım.
Bu makale Creative Commons (CC BY-NC-ND 4.0) lisansı ile korunmaktadır. Kullanım koşullarını makalenin en aşağısından inceleyebilirsiniz.

TweakPNG Analizinden Başlayalım

Burada öncellikle tarih detayı, text formatı ve chunklara bakıyoruz. Burası kritiktir. Epoch saat ve tarih bilgisi verir doğruluk payını teyit etmemize yarar.
Bunun için

Epoch datasını kontrol ediyoruz peki neden? Eğer dosya üzerinde oynama yapıldıysa burada saat ve zaman kayması olabiliyor bazen yani oluşturulan tarih ile epoch datası tamamen birbirini tutmalıdır. Genelde dosya içerisinde gelecekten gelen veya bazen saatlik zaman sapmaları bile aslında ipucu verebilir. IHDR ilk olmalı, IEND son olmalı, CRC doğru olmalı, IEND sonrası veri olmamalı Anormal chunk adı olmamalı PNG chunk yapısında dikkat edilmesi gereken detaylar: Length (4 byte) Type (4 byte) Data (Length kadar) CRC (4 byte) ae426082 IEND 0 olarak bitiyor bu oldukça önemli bir detaydır genelde dosyanın bize temiz olabileceğine dair işaretler gösterir ancak çabuk pes etmiyoruz. Belki de öyle olması düşündürülmüştür? Çünkü dosyanın farklı kısımlarına bazı işlemler uygulanmış olabilir. zTXt, iTXt ve oRnT analizleri yapılması gerekecektir. zTXt analizinde şüphelenilmesi gereken yerler 5MB zTXt varsa bazen boyut biraz daha şişkin olabilir, içinden executable çıkarsa, base64 blob varsa, entropi aşırı yüksekse genelde şüphe etmemiz gerekir yani burada pis bir şeyler dönüyor olabileceğine dair bir izlenim verebilir. iTXt analizi: iTXT tarafında şüphelenmemiz gereken yerler genelde: Çok uzun metin, script embed, UTF-8 injection, HTML, JavaScript, Base64 encoded payload ve benzeri URL injection tipleri olması gerekir. oRnT Analizi: Çok büyük boyut, IDAT sonrası, CRC mismatch, İsmi anlamsız veya binary dump gibi data varsa şüphe edilmesi gerekebilir. Genelde dosyanın üzerinde oynama yapıldığına dair ipucu olabilecek veriler verir. Genelde saldırganlar iTXT veya Ztxt tarafını çok tercih eder. oRnT tarafı custom chunk olarak geçtiğinden şüpheleri arttıracaktır. Peki ilk izlenimde bunun temiz olabileceğini nasıl anladık? Chunk sırası doğru CRC'ler tutarlı Boyutlar mantıklı IEND canonical IEND sonrası veri yok IDAT boyutları makul No embedded archive signature No secondary file header Metadata tutarlı Timestamp consistent Zararlı bir şey olsa nasıl olurdu? IDAT sonrası gizli ZIP IEND sonrası appended payload CRC intentionally broken Polyglot signature Overlapping chunk trick Ancak bunlar yeterli değildir. Yine de incelemeye devam ettim. Hex editör üzerinden incelemelere devam ediyorum Burada ilk bakmamız gereken yerler başlangıç ve bitiş bitleri. 89 50 4E 47 0D 0A 1A 0A ilk önce burayı kontrol ediyorum. 89: Dosyanın metin dosyası olmadığını belirten ASCII dışı bir değerdir. 50 4E 47: ASCII karşılığı doğrudan "PNG" harfleridir. 0A 0D: Satır sonu (DOS/Windows stilinde CRLF) karakterleridir. 1A: Eski sistemlerde "dosya sonu" (EOF) anlamına gelir; dosyanın yanlışlıkla bir metin dosyası gibi okunmasını engeller. 0A: UNIX tarzı satır sonu (LF) karakteridir.
HxD İncelemesi

Herhangi bir problem görülmüyor.

Şimdi burada CTRL + F ile ZTXT formatını arattık 7A 54 58 74 bitlerinden 4 bit geriye gidiyoruz ve karşımıza 00 00 0E 51 çıkıyor. Bu aslında chunk uzunluğunu getirir.
Decimal olarak çevirirsek: 3665 byte eder. Yani bu oldukça düşük bir veridir. Burada dikkat edilmesi gereken başka bir detay daha var CRC 4 bit olarak veri eklemesi yaptığından eğer veri gelmiyorsa burada bir manipülasyon olabilir veya dosya bozulmuş olabilir. Ancak boyut az olması demek değildir ki:
gizli script, encoded data, shellcode veya benzeri beacon config İçermez. Ztxt kısmını ASCII hale getirdim ve tüm datayı zlib olarak dışarı çıkardım.

Bu yolu izleyerek file kısmından dışarı save selection olarak test.zlib olarak kaydettim. Amaç burada gizli bir sıkıştırma var mı 7.zip gibi bir araç ile açmayı denemek. Burada herhangi bir zlib headır'ı yok ama varmış gibi davranıyoruz. Şayet varsa 7zip gibi bir araç açacaktır.
78 9C Genelde zlib için bizlere uyarı verecek değerlerdir hexadecimal olarak hatta şunu da söyleyebilirim gizli zlib varsa bunlar recursive olarakta gizlenebilir yani 1 tane zlib varmış gibi görünür ancak dosya işleme alındığında browser veya herhangi bir görüntü işleyici tarafından bunlar decompress edildiğinde payload açığa çıkabilir.
Dışarı aktardığım ham dosyayı 7-Zip ile açmayı denediğimde başarısız oldum. Devam ediyoruz.
78 9C bitlerine odaklandım burada genelde zlib'i belirtirler.

Burada chunk değerlerini kontrol ediyoruz. Değerlerde bir anormallik görülmüyor. Sadece orNT tarafında bir göze çarpan var. Genelde orNT metadata taşır.

Offset mantığı nasıl hesaplanır? Offset Hesaplama Mantığını Elle Öğrenelim PNG Chunk yapısı: 4 byte → Length (Big Endian) 4 byte → Type N byte → Data 4 byte → CRC zTXt Length: 3665 Offset: 3290 12 + 3665 = 3677 3290 + 3677 = 6967

ChunkToplam = 12 + Length , SonrakiChunkOffset = MevcutOffset + 12 + Length
Chunklarda bir problem görülmüyor.

PNG dosyasının bittiğini belirten yer her zaman IEND chunk'ıdır. Dosyanın sonu şu 12 baytlık dizi ile biter: 00 00 00 00 49 45 4E 44 AE 42 60 82 Bu diziyi parçalarsak: 00 00 00 00: IEND chunk'ının veri uzunluğunu (Length) belirtir. Veri içermediği için 0'dır. 49 45 4E 44: ASCII olarak "IEND" yazısıdır. AE 42 60 82: IEND chunk'ının hata kontrol (CRC) kodudur. Eğer hala IEND sonunda veri geliyorsa burada bir anormallik olduğuna dair işaret vardır. Ayrıca decoded text içerisinde de herhangi bir anormallik görünmüyor. zTXt Chunk Yapısını Anlama Keyword (ASCII) 00 (null separator) Compression method (1 byte) Compressed data (zlib)
keyword + 00 + 1 byte + compressed blob ve keyword arama:

Sıkıştırılmış boyut:

Zlip Genel kontrol scripti:

Burada amaç gizli zlip varsa çıkarmak. Çıktıda herhangi bir matruşka veya recursive zlip dosyası yok. 6170706c = ASCII karşılığı appl 616373704150504c = ASCII karşılığı acspAPPL Sonuç: Apple colorsync ICC profiline bağlı. İlk bakışta içeride bir zlib yokmuş veya sahte (false header) başlıklar varmış gibi görünebilir. Ancak adli bilişimde standart araçların başarısız olduğu yerde manuel ayrıştırma (parsing) başlar. PowerShell ile Zlib başlığını manuel olarak kesip DeflateStream ile zorladığımda, içerideki Apple ICC profiline ulaşmayı başardım Peki neden Zlip recursive aradık? Bunu C üzerinden temsili bir kod ile anlatacağım. Ek bilgi:
#include <stdio.h>
#include <string.h>
// Eğitim amaçlı, zafiyetli recursive (özyinelemeli) fonksiyon
void vulnerable_recursive_payload(char *malicious_input, int depth) {
// Hafızada (Stack'te) sadece 64 byte'lık yer ayırıyoruz.
char local_buffer[64];
// ZAFİYET BURADA: strcpy, girdinin boyutunu kontrol etmez.
// Gelen malicious_input 64 byte'tan büyükse, yanındaki hafıza alanlarını ezer.
strcpy(local_buffer, malicious_input);
printf("Recursion Derinliği: %d | Buffer adresi: %p\n", depth, (void*)local_buffer);
// Kasıtlı olarak fonksiyonu tekrar çağırıyoruz (Recursion)
// Her çağrıda stack'te yeni bir 64 byte'lık alan açılır.
if (depth < 5) {
vulnerable_recursive_payload(malicious_input, depth + 1);
}
}
int main(int argc, char *argv[]) {
printf("Hedef program calisti...\n");
if (argc > 1) {
// Kullanıcıdan veya başka bir payload'dan gelen veriyi doğrudan fonksiyona iletiyoruz.
vulnerable_recursive_payload(argv[1], 1);
} else {
printf("Kullanim: %s <payload_stringi>\n", argv[0]);
}
printf("Program normal bir sekilde sonlandi.\n");
return 0;
}
Temsili bir C kodu yazdık. Recursive fonksiyonlar aslında oldukça tehlikelidir bellek manipülasyonu yapmak konusunda çok ciddi felaketlere ve güvenlik sorunlarına neden olurlar. Genelde aynı mantık arşivleme dosyalarında kullanılır fakat burada mantık biraz farklıdır. Peki bu neden olur? Recursive fonksiyonlar aslında bellekte kendilerini sürekli çağırmak için yeni alan açarlar, döngüler ise genelde bir kere alan açarlar ve bu alan içinde hareket ederler. Recursive fonksiyon kullanılırsa genelde payload sıkıştırmak ve çalıştırmak için oldukça el verişli yerlerdir. AV ve EDR yazılımları genelde statik tarama yapmaya ve loglamaya elverişlidir. AV'yi atlatmanın en klasik yolu aslında imzayı iç içe geçmiş yapılar içinde saklamaktır. Sıkıştırılmış dosyalar açılırken genelde işlenmek zorundadır görüntü işleme konusunda. Bu da aslında payload'un sinsice işlenmesi anlamına gelir. IDAT Entropi Analizi: Entropi analizi, dosya içerisindeki veri rastgeleliğini (randomness) matematiksel olarak ölçerek yapısal bütünlüğü doğrulamak amacıyla gerçekleştirilir. Şifrelenmiş payload'lar veya sıkıştırılmış zararlı yazılımlar (packed malware), bulundukları veri bloğunun entropisini maksimum sınıra (8.0) yaklaştırır. Zlib ile sıkıştırılmış standart bir IDAT bloğunun 7.9 civarında istatistiksel bir dağılım sergilemesi beklenirken, bu değerdeki ani sapmalar, dosya yapısının manipüle edildiğine ve içeriye steganografik yöntemlerle yabancı bir veri kümesi gömüldüğüne dair en güçlü (anomaly detection) göstergelerden biridir. 32768 Byte: Birinci IDAT bloğunun boyutudur (Length). 16119 Byte: İkinci IDAT bloğunun boyutudur. 48887 Byte: Bu iki bloğun birleştirilmiş (concatenate) toplam sıkıştırılmış ham veri (zlib stream) boyutudur. 32768 + 16119 = 48887 byte


Entropi neden burada önemli? Dosya içerisinde bir payload varsa entropi aslında 8 ve üzerine yaklaşır. Şu an sınırda ancak bu normal bir değere yakındır. Ancak 7.9 entropi PNG için normaldir çünkü zlib compressed stream'tir. PNG üzerinde olan saldırılar genelde 3 tip olur: 1 Parser exploit (libpng bug vs.) 2 Steganografi 3 Polyglot (PNG + JS / ZIP / PE) Şu ana kadar bu yapılan çalışmalar aslında bize dosyanın büyük ölçüde temiz olduğunu gösteriyor. Fakat durmak yok.
CRC Doğrulama CRC = CRC32( ChunkType + ChunkData )

Burada CRC tarafında bir hata olmadığını görüyoruz. False olsaydı sorun var diyebilirdik. Amaç burada bir bozulma var mı yok mu onu görmeye çalıştık.
IEND Kontrolü

Şimdi burada biz neyi aradık appended payload veya trojan var mı? Yani dosya içerisinde kapanış düzgün mü? Bir kitap düşünün kitabın tüm sayfalarının nizami olarak kapanması gerekir ancak bazen o sayfalar katlanır arada ucundan. Biz onu arıyoruz burada, 0 çıkması iyiye işaret. IEND offset: 54000 Bytes after IEND: 2000 Yukarıda olan değerlere benzer bir şey olsaydı gizli bir payload olduğundan şüphelenebilirdik yani kitap kapanmış ama sayfalar ucundan katlanmış burada bir anormallik var derdik.
IDAT Kontrolü
Değer: 78 5E Şimdi buraya geldik, burada IDAT gerçekten doğru decompress oluyor mu bunun peşindeyiz.


Burada ne yaptık? IDAT'ı decompress ettik 2 değerinin çıkmasını bekledik ve concat gerekiyor. Peki bu ne demek? IDAT sayısının kaç tane olduğunu bulmaya çalıştık. RAW data boyutunu gördük.
RGBA Kontrolü:

Elimizde olan bilgilerle bir kontrol daha yapalım. Row size = 1 + (1008 × 4) = 1 + 4032 = 4033 byte Total = 4033 × 282

Matematiksel olarak burada hesaplamalar da doğru çıktı. Zlib stream düzgün, PNG yapısı bozulmamış, stego için fazladan pixel eklenmemiş, Polyglot ihtimali ciddi şekilde düşer.
LSB Analizi: Amaç burada en alt bitleri çıkarmak.

1101000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000 Bitleri kontrol ettiğimizde düzgün bir yapı var. Tekrarlı bir yapı yok yani burada payload veya trojan olma ihtimali çok düşük.
χ² (Chi-Square) LSB Testi
Burada chi square ile gizli bir payload olup olmadığını arıyoruz. Görsel üzerinde olan dağılım normal mi değil mi bakıyoruz.

Normalde bir görselde değerlerin %50 civarında dağılması gerekir bu aslında matematiksel olarak bir sapma olduğunu gösterir. Biraz daha yakından inceleyelim. Bunun nedeni aslında dosyanın üzerinde biraz oynama olmasından ve halinden.
PS C:\Users\Administrator> # ---- PNG LOAD ----
PS C:\Users\Administrator> $path = "C:\v2.png"
PS C:\Users\Administrator> $bytes = [System.IO.File]::ReadAllBytes($path)
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- IHDR PARSE ----
PS C:\Users\Administrator> $ihdrData = $bytes[16..(16+12)]
PS C:\Users\Administrator>
PS C:\Users\Administrator> $wBytes = $ihdrData[0..3]; [Array]::Reverse($wBytes)
PS C:\Users\Administrator> $width = [BitConverter]::ToUInt32($wBytes,0)
PS C:\Users\Administrator>
PS C:\Users\Administrator> $hBytes = $ihdrData[4..7]; [Array]::Reverse($hBytes)
PS C:\Users\Administrator> $height = [BitConverter]::ToUInt32($hBytes,0)
PS C:\Users\Administrator>
PS C:\Users\Administrator> $bitDepth = $ihdrData[8]
PS C:\Users\Administrator> $colorType = $ihdrData[9]
PS C:\Users\Administrator>
PS C:\Users\Administrator> $bpp = 4 # RGBA 8bit
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "Width:" $width
Width: 1008
PS C:\Users\Administrator> Write-Host "Height:" $height
Height: 282
PS C:\Users\Administrator> Write-Host "BitDepth:" $bitDepth
BitDepth: 8
PS C:\Users\Administrator> Write-Host "ColorType:" $colorType
ColorType: 6
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- IDAT COLLECT ----
PS C:\Users\Administrator> $idatData = @()
PS C:\Users\Administrator> $offset = 8
PS C:\Users\Administrator>
PS C:\Users\Administrator> while ($offset -lt $bytes.Length) {
>>
>> $lenBytes = $bytes[$offset..($offset+3)]
>> [Array]::Reverse($lenBytes)
>> $length = [BitConverter]::ToUInt32($lenBytes,0)
>>
>> $type = [Text.Encoding]::ASCII.GetString($bytes[($offset+4)..($offset+7)])
>>
>> if ($type -eq "IDAT") {
>> $dataStart = $offset + 8
>> $dataEnd = $dataStart + $length - 1
>> $idatData += $bytes[$dataStart..$dataEnd]
>> }
>>
>> $offset += 12 + $length
>> }
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "IDAT size:" $idatData.Length
IDAT size: 48887
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- ZLIB HEADER REMOVE ----
PS C:\Users\Administrator> $deflateData = $idatData[2..($idatData.Length-1)]
PS C:\Users\Administrator>
PS C:\Users\Administrator> $ms = New-Object IO.MemoryStream(,$deflateData)
PS C:\Users\Administrator> $ds = New-Object IO.Compression.DeflateStream($ms,[IO.Compression.CompressionMode]::Decompress)
PS C:\Users\Administrator>
PS C:\Users\Administrator> $out = New-Object IO.MemoryStream
PS C:\Users\Administrator> $ds.CopyTo($out)
PS C:\Users\Administrator> $raw = $out.ToArray()
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "Raw decompressed size:" $raw.Length
Raw decompressed size: 1137306
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- UNFILTER ----
PS C:\Users\Administrator> $rowDataSize = $width * $bpp
PS C:\Users\Administrator> $rowSize = $rowDataSize + 1
PS C:\Users\Administrator>
PS C:\Users\Administrator> $recon = New-Object byte[] ($height * $rowDataSize)
PS C:\Users\Administrator>
PS C:\Users\Administrator> for ($row=0; $row -lt $height; $row++) {
>>
>> $rowStart = $row * $rowSize
>> $filter = $raw[$rowStart]
>>
>> for ($col=0; $col -lt $rowDataSize; $col++) {
>>
>> $rawByte = $raw[$rowStart + 1 + $col]
>>
>> $left = 0
>> if ($col -ge $bpp) {
>> $left = $recon[($row*$rowDataSize) + $col - $bpp]
>> }
>>
>> $up = 0
>> if ($row -gt 0) {
>> $up = $recon[(($row-1)*$rowDataSize) + $col]
>> }
>>
>> $upLeft = 0
>> if ($row -gt 0 -and $col -ge $bpp) {
>> $upLeft = $recon[(($row-1)*$rowDataSize) + $col - $bpp]
>> }
>>
>> switch ($filter) {
>>
>> 0 { $value = $rawByte }
>>
>> 1 { $value = ($rawByte + $left) -band 0xFF }
>>
>> 2 { $value = ($rawByte + $up) -band 0xFF }
>>
>> 3 { $value = ($rawByte + [math]::Floor(($left + $up)/2)) -band 0xFF }
>>
>> 4 {
>> $p = $left + $up - $upLeft
>> $pa = [math]::Abs($p - $left)
>> $pb = [math]::Abs($p - $up)
>> $pc = [math]::Abs($p - $upLeft)
>>
>> if ($pa -le $pb -and $pa -le $pc) { $pr = $left }
>> elseif ($pb -le $pc) { $pr = $up }
>> else { $pr = $upLeft }
>>
>> $value = ($rawByte + $pr) -band 0xFF
>> }
>>
>> }
>>
>> $recon[($row*$rowDataSize) + $col] = $value
>> }
>> }
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "Reconstruction complete."
Reconstruction complete.
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- LSB ANALYSIS ----
PS C:\Users\Administrator> $zero = 0
PS C:\Users\Administrator> $one = 0
PS C:\Users\Administrator>
PS C:\Users\Administrator> foreach ($byte in $recon) {
>> if (($byte -band 1) -eq 0) { $zero++ }
>> else { $one++ }
>> }
PS C:\Users\Administrator>
PS C:\Users\Administrator> $total = $zero + $one
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "Zero:" $zero
Zero: 75473
PS C:\Users\Administrator> Write-Host "One:" $one
One: 1061551
PS C:\Users\Administrator> Write-Host "Zero Ratio:" ($zero/$total)
Zero Ratio: 0,0663776666103794
PS C:\Users\Administrator>
PS C:\Users\Administrator> # ---- CHI SQUARE ----
PS C:\Users\Administrator> $expected = $total / 2
PS C:\Users\Administrator>
PS C:\Users\Administrator> $chi = (($zero - $expected)*($zero - $expected) / $expected) +
>> (($one - $expected)*($one - $expected) / $expected)
PS C:\Users\Administrator>
PS C:\Users\Administrator> Write-Host "Chi-Square:" $chi
Chi-Square: 855170,886528341
Burada yaptığımız şey aslında dosya üzerinde olan anomaliyi incelemek. Normal, gürültüye sahip bir fotoğrafta bitlerin (0 ve 1) dağılımı %50 civarında olmalıdır. Ancak filtreyi kaldırıp ham piksellerin LSB dağılımına baktığımızda 75.473 adet Sıfır (Zero) ve 1.061.551 adet Bir (One) bulduk. Dağılımın %93'ünden fazlası sadece 1'lerden oluşuyor. Chi-Square (χ2) değerimiz ise 855.170 gibi garip bir değere fırladı. Standart bir analiz aracı bu tabloyu görse kırmızı alarm verir ve içeride devasa bir şifrelenmiş veri veya payload olduğunu false positive olarak verebilirdi. Bu aslında gürültüdür.
Bitplane Analizi ve ICCP Chunk Kontrolü
Burada aslında yaptığımız işlemde tekrar dağılımları bit düzeyinde incelemek ve orana baktığımızda %50 civarına yakın bir dağılım var bu normaldir.

Chunk kontrolünü tekrar yapıyoruz halen gizli bir Zlip bloğu var mı yok mu bunu kontrol ediyoruz. Sonrasında ise daha önceden bulduğumuz 5 adet bit anomalisinin konumlarını buluyoruz.

Konum bilgilerine baktığımızda aslında burada bir rastgelelik var. Düzenli bir dağılım yok. Payload veya trojan benzeri bir yapı olduğunda genelde düzenli olurdu. Peki halen bir zararlı ihtimali var mı? Neyden bahsediyorum? Matris gömme ve bu matriste kriptografi veya payload barınması. Yani bunu saklamak için bu rastgeleliği üretmek çok zordur ileri düzey matematiksel ifadeler gerekir. STC taktiği ile bypass yapılabilir. Peki bu görsel neydi? Aslında bu görsel bir sansürlenmiş bir görüntüydü. Fırça aleti ile sansürlenmiş bir görüntü, chi square testinde anomali bulmamızın sebebi bu denebilir, fırca genelde burada yakın bölgeleri hedef aldığından burada bir bozulma varmış gibi gösterdi. Fakat içim rahat etmediği için basit bir STC analizi yapmayı istedim.
STC Analizi

Şayet Ratio ≈ 0.5 civarıysa STC şüphesi artar
Ratio aşırı dengesiz durumda.

Burada ise aşırı deterministik bir yapı görüyoruz. Aslında fırça darbesinden kaynaklı. Yani LSB'nin %93–96 civarı 1'lerden oluşuyor denebilir. Pikselleri gerçek renklerine döndürmek için manuel bir Unfilter algoritması yazdım. Gerçek piksellerin LSB'sine baktığımızda %93 oranında 1 (One) olduğunu gördük. Bu durum, anomali teorimizi çürütmez. Şu ana kadar bulduklarımız aslında dosyanın büyük ölçüde temiz olduğunu gösteriyor ama bu demek değildir ki tamamen temiz. Bu analiz, klasik LSB ve yapısal stego tekniklerine karşı yüksek güven verir; ancak ileri seviye adaptif veya ML tabanlı gömme tekniklerini tamamen dışlamak mümkün değildir. SPAM/SRM feature extraction yok, CNN ML steganaliz yok, p-value formalizasyonu yok, çoklu veri seti yok, referans baseline yok, natural image LSB distribution modeli yok, alpha channel masking analizi yok, local variance map görselleştirme yok False positive/negative tartışması yok ve daha derine inecek düzeyde analizler yok. Burada biraz pratik olması için manuel olarak inceleme yaptım. Bu kadar derine şu an inmeye gerek var mı? Yani dosyayı aldığım kişi bunları çok rahat atlatabilecek birisi zaten fakat ben burada kendimi sınamak aynı zamanda eğitmek için kendi kendime bir challenge başlattım kimse gidip o dosyaya bak demedi. Basit bir sohbette gönderilen görseldi. Yazı çok uzadı aslında daha da derine inebilirim ama burada durmam gerek. İnersem makale çok uzayacak. Tool olsa bu kadar analiz kısmı için yormazdım kendimi. Yazımı burada noktalıyorum, bu çalışma aslında aklımda olan dijital kale içerisinde zamanla deneyeceğim işler için hafif antremanlardan ibaret.
Şu felsefe ile ilerlerim her zaman:
tek bildiğim şey hiçbir şey bilmediğimdir - Sokrates
Lisans ve Kullanım Koşulları Metin İçeriği: Bu makale Creative Commons (CC BY-NC-ND 4.0) lisansı ile korunmaktadır. Kaynak göstermek ve yazar (Hakan ÇEVİK) adını belirtmek şartıyla paylaşılabilir; ancak ticari amaçla kullanılamaz ve içerik değiştirilerek dağıtılamaz.
Kod ve Betikler: Makale içerisinde paylaşılan tüm PowerShell betikleri ve C kodları MIT Lisansı altında açık kaynak olarak sunulmuştur. Laboratuvar ortamlarınızda dilediğiniz gibi kullanabilir, değiştirebilir ve geliştirebilirsiniz.