Arşiv
EN

Aynı JPEG, farklı piksel

Bir JPEG'in yalnızca bir bölümünü çözmek, bütün görüntüyü çözüp o bölümü kesmekle aynı pikselleri vermiyor.

CSINT-NEWS-2026-011Arşivde aç

Belgeler

Sarı vurgular sonradan eklendi, özgün görüntü değişmedi.

574 piksel farklı, hepsi kenarda

Aynı dosya tam ve bölge olarak çözüldü. x=200 istendi, kütüphane blok sınırı yüzünden bölgeyi 192'den başlattı.

  1. İstenen ve dönen bölge
  2. Farklar yalnız kenarda

Göstermediği. Sayılar bu test deseni ve bu bölge için. Başka görüntülerde farkın sayısı ve büyüklüğü değişir.

Testin terminal kaydıHam kayıt 1, 0:5517 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Aynı nokta, iki renk

Bölgenin ilk sütunu, rengin keskin değiştiği satırlardan itibaren iki yolda farklı, yanındaki sütunlar aynı.

  1. Tam çözme, x=192
  2. Kısmi çözme, x=192

Göstermediği. Kesit yalnızca sol kenarı gösteriyor. Sağ kenardaki 244 fark bu kesitte yok.

Testin çözülmüş çıktıları, 2. çalıştırmamain_simd/r_full.ppm ve r_B_crop.ppm17 Ekim 2026

Çıktı CSINT'in. Kesit en yakın komşu ile 40 kat büyütüldü, piksel değerleri değişmedi. İki kesit arasında düz gri bir şerit var.

Ton iki pikselde bir saklanıyor

Kodla üretilen test deseni libjpeg-turbo'nun kendi cjpeg aracıyla 4:2:2 JPEG'e çevrildi.

  1. 4:2:2 örnekleme

Testin terminal kaydıHam kayıt 1, 0:3017 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

İki yol aynı dosyayı okuyor

İki çözme yolunun girdisi tek bir dosya.

  1. Karşılaştırılan JPEG

Testin terminal kaydıHam kayıt 1, 0:4517 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Belge bunu söylüyor

libjpeg-turbo 2.1.5 belgesi bu davranışı açıkça anlatıyor, yani yeni bir açık değil.

  1. Bölge kenarı, görüntü kenarı gibi

Testin terminal kaydıHam kayıt 1, 0:1417 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Ton satırı 384'ten 154'e iniyor

Çalışma anında ton dolduran fonksiyon ve onun gördüğü satır uzunluğu okundu.

  1. Tam çözmede 384
  2. Ton fonksiyonları
  3. Kırpınca 154

Göstermediği. Bu, işaretçinin seçildiğini gösterir. Her çağrı hata ayıklayıcıyla izlenmedi.

Testin terminal kaydıHam kayıt 2, 0:1017 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

DLL REA ile açılıyor

SIMD'siz derlemedeki jpeg62.dll, REA üzerinden Ghidra 12.1.4 ile çözümlendi.

  1. Yükleme adresi

Testin terminal kaydıHam kayıt 2, 1:2117 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

0x3f2a0'daki fonksiyon

SIMD'siz derlemede yoklamanın gösterdiği adres 249 baytlık tek bir fonksiyon.

  1. Ton fonksiyonu

Testin terminal kaydıHam kayıt 2, 1:2517 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

İlk örnek olduğu gibi kopya

Satırın ilk tonu komşuya bakılmadan yazılıyor, satırın uzunluğu 0x28 ofsetinden okunuyor.

  1. Komşusuz ilk çıktı
  2. Uzunluk 0x28 alanından

Testin terminal kaydıHam kayıt 2, 1:3917 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

İçeride karışım, sonda kopya

Fonksiyon satırın iki ucunu görüntünün kenarı sayıyor, ötesinde görüntü olup olmadığını bilmiyor.

  1. Komşuyla karışım
  2. Son örnek kopya

Testin terminal kaydıHam kayıt 2, 1:5317 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

x blok sınırına çekiliyor

Kırpma fonksiyonu başlangıcı yuvarlıyor ve ton satırının uzunluk alanını hedef alıyor.

  1. 200, 192 oluyor
  2. Aynı 0x28 alanı

Testin terminal kaydıHam kayıt 2, 2:1717 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Kısa uzunluk alana yazılıyor

Ton dolduran fonksiyonun okuduğu uzunluk buradan geliyor.

  1. Yeni genişlik, 154

Testin terminal kaydıHam kayıt 2, 2:2917 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Varsayılan C fonksiyonu

Seçici, SIMD kontrolü sıfır dönerse C fonksiyonunu kullanıyor.

  1. Seçim

Testin terminal kaydıHam kayıt 2, 3:1717 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Bu derlemede SIMD hiç yok

SIMD'siz derlemede kontrol her zaman sıfır döndürüyor, yani hep C fonksiyonu çalışıyor.

  1. Hep sıfır

Testin terminal kaydıHam kayıt 2, 3:4717 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Hızlı yol aynı alanı okuyor

Ölçümün yapıldığı SIMD'li derlemede de satır uzunluğu aynı 0x28 alanından geliyor.

  1. Kısalan genişlik
  2. AVX2 seçimi

Göstermediği. 0x18000bb00'daki SSE2 yolu incelenmedi.

Testin terminal kaydıHam kayıt 2, 4:5517 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

AVX2 son örneği yanına kopyalıyor

Son örneğin sağ komşusu kendisi oluyor, formül aynı değeri geri veriyor.

  1. Son örnek, sağ komşu yerine

Testin terminal kaydıHam kayıt 3, 1:2817 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Aynı formülün sabitleri

Vektör kodu C fonksiyonundaki x3 çarpımını ve +1, +2 yuvarlamasını 16 değere birden uyguluyor.

  1. 1, 2 ve 3

Testin terminal kaydıHam kayıt 2, 5:2817 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Fancy kapalıyken fark yok

Ton komşuyla karıştırılmayınca iki yol bayt bayt aynı.

  1. Fancy kapalı
  2. 0 piksel

Testin terminal kaydıHam kayıt 1, 1:1017 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Üç derleme, aynı sonuç

Sayım ham PPM dosyalarından Python ile ayrıca yapıldı ve C programıyla aynı çıktı.

  1. Fancy açıkken 574
  2. Kontrollerde 0

Testin terminal kaydıHam kayıt 1, 1:4317 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

djpeg de aynısını yapıyor

libjpeg-turbo'nun kendi komut satırı aracı da kenarda aynı pikselleri veriyor.

  1. Kısmi çözme = djpeg -crop

Testin terminal kaydıHam kayıt 3, 0:1117 Ekim 2026

Ekran kaydı CSINT'in. Kare kırpıldı, piksellere dokunulmadı.

Kısa sonuç

133.056 pikselden 574'ü farklı ve hepsi bölgenin ilk ya da son sütununda. jpeg_crop_scanline ton satırının uzunluğunu bölgeye göre kısaltıyor, ton dolduran kod da satırın uçlarını görüntünün kenarı sayıp komşu yerine kenar örneğini kopyalıyor.

Sınır

Bu kendi bilgisayarımda yaptığım bir test. Davranış libjpeg-turbo belgesinde yazıyor, yeni bir açık ya da hata bildirimi değil.

Ayrıntılı anlatım ve kaynak dökümüYöntem, zaman çizelgesi ve tam metin. Bulgular yukarıdaki belgelerde.

İncelenen iddia

4:2:2 bir JPEG'de bölgeyi jpeg_crop_scanline ile çözmek, bölgenin kenarındaki tonu değiştirebiliyor. Soru, bunun nerede ve neden olduğu.

Testin sınırları

  • Tek sürüm (2.1.5), MSVC ile yapılmış tek Windows derlemesi, tek test deseni ve yalnızca 4:2:2 denendi.
  • 4:2:0, jpeg_skip_scanlines ile dikey kırpma, yeni sürümler ve başka çözücüler ölçülmedi.
  • Her çağrı hata ayıklayıcıyla izlenmedi. Sonucu çalışma anı yoklaması, okunan kod ve bayt bayt aynı çıktılar birlikte destekliyor.
  • Bu bir güvenlik açığı değil. Farklar kanal başına 1 ile 55 arasında ve yalnızca kenar sütunlarında.

Işık ve ton

JPEG her pikseli ışık (Y) ve ton (Cb, Cr) olarak saklar. Göz ışıktaki ayrıntıyı tondakinden çok daha iyi gördüğü için ton çoğu zaman daha az saklanır. Bu dosyada ışık her piksel için, ton yan yana iki piksel için bir kez var. Buna 4:2:2 deniyor.

Çözerken eksik ton doldurulur. libjpeg-turbo varsayılan olarak en yakın ton örneğinden 3 pay, komşu örnekten 1 pay alır ve 4'e böler. Görüntünün tam kenarında komşu olmadığı için kenar örneği olduğu gibi kopyalanır.

Bölge çözülünce kütüphane ton satırını bölgenin genişliğine indiriyor. Ton dolduran kod satırın ötesini görmediği için bölgenin kenarını da görüntünün kenarı sayıyor.

Deney

Kodla 768 x 432 piksellik bir test deseni üretildi. Üstte yumuşak geçişler, altta keskin renk şeritleri var. Desen libjpeg-turbo'nun kendi cjpeg aracıyla -quality 90 -sample 2x1 -dct int ayarlarıyla JPEG'e çevrildi.

Küçük bir C programı dosyayı iki yoldan çözdü. Önce bütün görüntüyü çözüp x 192 ile 499 arasını kesti, sonra jpeg_crop_scanline ile yalnızca o bölgeyi çözdü. İki çıktı piksel piksel karşılaştırıldı ve sayım ham PPM dosyalarından Python ile ayrıca yapıldı.

x=200 istendi, kütüphane 16 piksellik blok sınırı yüzünden x=192 ve 308 genişlik döndürdü. Bu yüzden iki çıktıda aynı sütunlar karşılaştırıldı.

En büyük fark x=192, y=216 noktasında. Saklı Cb örnekleri 215 ve 91. Tam çözme (3 x 91 + 215 + 1) >> 2 = 122 hesaplıyor, kısmi çözmede 215 bölgenin dışında kaldığı için 91 kopyalanıyor. Işık iki yolda da 127, piksel RGB 44, 171, 116 yerine 27, 190, 61 oluyor.

Sağ kenarda x=499 noktasında gerçek sonraki örnek 177. Tam çözme (3 x 180 + 177 + 2) >> 2 = 179 veriyor, AVX2 yolu sonraki hücreye 180'in kopyasını yazdığı için 180 çıkıyor.

Kodu nasıl okudum

SIMD'li derleme, JSIMD_FORCENONE=1 ile aynı derleme ve SIMD'siz derleme karşılaştırıldı. Üçü de bayt bayt aynı çıktıyı verdi. Okuması en kolay olan SIMD'siz derlemeydi.

Küçük bir yoklama programı kütüphanenin seçtiği ton fonksiyonunun adresini ve gördüğü satır uzunluğunu yazdırdı. DLL, REA adlı MCP sunucusu üzerinden Ghidra 12.1.4 ile açıldı. Hata ayıklama sembolü yüklenmediği için iç fonksiyonların adı FUN_ ile başlıyor.

REA ile open_binary, binary_overview, resolve_containing_procedure, procedure_pseudo_code, xrefs, procedure_assembly, inspect_native_instruction, read_bytes ve export_evidence_bundle araçları kullanıldı. Her çağrının isteği ve yanıtı ayrı JSON dosyası olarak saklandı.

Kimin işine yarar

Kısmi çözmeyle küçük resim ya da karo üretip bunları tam çözmeyle karşılaştıran testler, önbellekler veya özet kontrolleri kenarda tutmayabilir.

Bu testte bölge kenarından uzak her piksel tuttu. Her yandan bir blok fazla çözüp fazlalığı kesmek, fancy upsampling'i kapatmak ya da farkı olduğu gibi kabul etmek mümkün seçenekler.

Yolda bozulanlar

libjpeg-turbo 2.1.5, CMake 4.1 ile ancak -DCMAKE_POLICY_VERSION_MINIMUM=3.5 eklenince derlendi. Ghidra'nın arka plan çözümleyicisi kullanıcı klasörünün adındaki ö harfi yüzünden başlamadı, kısa 8.3 yollarıyla çalıştı. İlk iki ölçüm betiği PowerShell'in stderr davranışı ve bir JSON kaçış hatası yüzünden bozuldu. Başarısız denemeler silinmedi.

Sürümler ve özetler

Windows 11 Home 26300, Intel Core Ultra 7 155H. libjpeg-turbo 2.1.5 (git 3b19db4e), MSVC 19.29.30159, NASM 2.16.03. REA rea-agents 6.5.0, Ghidra 12.1.4, Python 3.10.11.

test_422.jpg SHA-256 72721589ae3fa7c665080f1334544cba0c6d69394cffcb0d931fe34c711630c2. İncelenen SIMD'siz jpeg62.dll 8d8fd33f ile, ölçümde kullanılan SIMD'li jpeg62.dll 02057234 ile başlıyor. Karelerin özetleri docs/research/jpeg-kenar-pikselleri.json dosyasında.

Kaynaklar