- Bir geliştirici, web’de gördüğü ASCII art bileşeninin nasıl uygulandığını anlamak için küçültülmüş JavaScript’i ChatGPT’ye verdi ve araç, karmaşık akışı okunabilir bir yapıya dönüştürdü
- Asıl kod, React bileşeninin pencere boyutuna göre sütun ve satırları hesaplayıp
setIntervalile 60fps hızında metin ızgarasını güncellemesi üzerine kuruluydu - ChatGPT, karakter kümesi seçimini, koordinat ve zaman tabanlı karakter hesaplamasını ve
div.textContentgüncelleme akışını açıkladıktan sonra bunu eşdeğer TypeScript/React kodu olarak yeniden yazdı - İlk başta
░▒▓█gibi blok karakterler eksik olduğu için uygulamanın farklı olduğu düşünüldü, ancak orijinal betik yeniden incelendiğinde bunun bir kopyala-yapıştır kodlama sorunu olduğu anlaşıldı - Doğru karakter kümesiyle güncellendiğinde çıktı, orijinal bileşenle aynı hale geldi ve bunun, küçültülmüş kodu anlama ve yeniden uygulama için ChatGPT’nin pratik biçimde kullanılabileceğini gösterdi
Küçültülmüş JavaScript’te ASCII art uygulamasını bulmak
- reactive.network hackathon sayfasındaki ASCII art bloğunun nasıl uygulandığını görmek için kaynak kod incelendi
- İlgili kod küçültülmüş olduğu için insanın doğrudan okuması zordu; normalde ya elle çözmek ya da orijinali geri yüklemek için
.mapdosyası aramak gerekirdi - Bu kez küçültülmüş kodun tamamı ChatGPT’ye yapıştırıldı ve kodun ne yaptığını açıklaması istendi
Küçültülmüş kodun ortaya çıkardığı yapı
- Kod, JavaScript ve React kullanarak dinamik metin içeriği üreten bir yapıdaydı
- Başlıca unsurlar şunlardı
Math.floor,Math.abs,Math.mingibi matematik fonksiyonları kısa takma adlarla kullanılıyordu"reactive.network REACTIVE.NETWORK"ile özel ve blok karakterlerden oluşan bir karakter kümesi bulunuyordu- Kullanılacak karakter kümesi,
Date.now() % 3sonucuna göre seçiliyordu - Seçilen karakter kümesinin uzunluğuna göre her koordinat için gösterilecek karakterin indeksi hesaplanıyordu
- Temel fonksiyon olan
eT, konum koordinatlarını ve zaman değerini alıp gösterilecek tek bir karakter döndürüyordu- Zaman değeri
t.time * 8e-5ile dönüştürülüyordu - Koordinatlar, sütun ve satırlardan küçük olan değer ile ekran oranı kullanılarak düzeltiliyordu
- Karakter indeksi,
Math.cos(position.x * position.x - position.y * position.y)hesabının sonucu ile zaman değeri birleştirilerek belirleniyordu
- Zaman değeri
React bileşeninin render yöntemi
- Bileşen, metnin yerleştirileceği
diviçinuseRef, pencerenin height ve width değerlerini tutmak içinuseStatekullanıyordu - İlk
useEffect, başlangıç boyutunuwindow.innerHeightvewindow.innerWidthile ayarlıyor,resizeolayı oluştuğunda boyutları güncelliyordu - İkinci
useEffect, ekran boyutuna göre ASCII ızgarasının boyutunu hesaplıyorducols,Math.floor(width / 12) * 1.6rows,Math.floor(height / 12)aspect,cols / rows
setInterval,1_000 / 60aralığında çalışarak 60fps için metni yeniden oluşturuyordu- Her karede tüm satır ve sütunlar dolaşılıp hesaplanan karakterler birleştiriliyor, ardından son metin
element.textContentiçine yazılıyordu
TypeScript ile daha okunabilir kod olarak yeniden yazma
- Geliştirici daha sonra eşdeğer kodun TypeScript ile, insanların daha rahat okuyabileceği biçimde yazılmasını istedi
- ChatGPT’nin ürettiği kod, küçültülmüş kodun işlevlerini şu adlarla açığa çıkardı
selectedCharacterSetcharacterSetLengthcalculateCharacterSizetürüAsciiArtGeneratorReact bileşeni
- Anlaşılması zor değişken adları, uygulamanın amacını açık eden adlarla değiştirildi
calculateCharacter, koordinatları, sütun ve satırları, ekran oranını ve zaman değerini alarak gösterilecek karakteri hesaplıyordutextRef, gerçek metnin yer alacağıdivöğesini gösteriyordusizevesetSize, pencere boyutu durumunu ifade ediyordu
- Yeniden yazılan kod, orijinal küçültülmüş koda göre çok daha kolay okunuyordu ve bileşenin nasıl uygulandığını öğrenmek için yeterli düzeydeydi
Karakter eksikliği yanılgısı ve kodlama sorunu
- İlk karşılaştırmada LLM’nin bazı uygulama ayrıntılarını kaçırmış olabileceği düşünüldü
- Özellikle orijinal bileşende görülen
░▒▓█gibi karakterlerin ChatGPT çıktısında eksik olduğu sanıldı - Daha sonra HN forumundaki bir kullanıcı bunun bir kopyala-yapıştır sorunu olabileceğini belirtti ve ek inceleme sonucunda orijinal kodda ChatGPT’ye yapıştırılan karakterlerden farklı karakterler bulunduğu ortaya çıktı
- Betik doğrudan indirildiğinde doğru karakterler elde edildi ve sorunun nedeninin kodlama farkı olduğu doğrulandı
- Karakter kümesi düzeltildikten sonra çıktı, orijinal bileşenle aynı hale geldi
1 yorum
Hacker News yorumları
HumanifyJS’i yapan kişiyim; bu amaç için ayrıca LLM tabanlı bir araç geliştirdim
LLM’i AST düzeyinde kullanarak, obfuscation kaldırıldıktan sonra bile kodun çalışmaya devam etmesini garanti ediyor: https://github.com/jehna/humanify
Normal kodda kullanıcının anlamlı isimlerinin tamamını sildikten sonra, algoritmaya ve kalan isimlere, örneğin yerleşik isimlere dayanarak yeni isimler seçen bir özellikten bahsediyorum
Refactoring yaparken bunu bazen LLM ile elle yapıyorum;
parallel_line_opposite_directionyerineantiparallel_linegibi daha standart bir terim bulmak ya dafind_animal_instance_in_animalsyerinefind_instance_in_listgibi daha genellenebilir bir isim keşfetmek için faydalı oluyorAçıkçası hâlâ AST düzeyinde sürüm kontrolü bekliyorum
Tüm fonksiyonu verip “Nelerin adı değiştirilmeli?” diye her şey değişene kadar tekrar tekrar sorduğun bir yöntem mi, yoksa tamamını tek seferde yaptırıp çıktıyı parse ederek AST’nin hâlâ eşleştiğini doğruladığın bir yöntem mi merak ediyorum
Yaklaşık 50 bin satırdan bahsediyorum
Düzenleme: Şu anda yalnızca 1,2 bin satırlık bir JS dosyasını openai modunda çalıştırıyorum; 20 dakika geçmesine rağmen sadece %70’i bitti. Teorik olarak 50 bin satırlık dosyada çalışsa bile denememek daha iyi olur gibi
JS sıkıştırması epey mekanik ve basit, bu yüzden geri alma işi de görece kolay olmalı
Elbette genel olarak bir insanın elle yapması için yeterince sıkıcıdır, ama dönüşümün kendisi oldukça sınırlı olduğu için obfuscate edilmiş tanımlayıcıları takip eden notlar olduğu sürece okumak mümkün
Daha genel minification kaldırma ya da obfuscation kaldırma hâlâ açık bir problem gibi görünüyor. Eskiden özellikle obfuscate edilmiş birkaç program yazmıştım; deneyimime göre ChatGPT bunları yüzeysel düzeyde bile anlayamadı
Örneğin C ile yazılmış 160 baytlık bir Brainfuck yorumlayıcısı gist’inde, GPT-4 ile kodu açıklamaya çalışan bir yorum vardı [1]; o “netleştirilmiş sürüm” özgün koda hiç benzemiyordu
[1] https://gist.github.com/lifthrasiir/596667#gistcomment-47512...
Örnek olarak çarpma/asal çarpanlara ayırma, türev/integral, geçmişi hatırlama/geleceği tahmin etme verilebilir
Kod obfuscation’ını kaldırmak kesinlikle bu zor ters problemlerden biri ve hatalar, kullanılmayan ya da alakasız rutinler, tesadüfen doğru sonuç veren yanlış implementasyonlar yüzünden kolayca daha da zorlaşabilir
Bu anlamda ChatGPT obfuscation kaldırmada iyi sonuç veriyorsa bu sevindirici bir şey; önceden bunun böyle olmasını beklememiz gerektiği söylenemez. ChatGPT’nin sınırlarını daha zor bir problemle görmüş olman iyi, ama bulduğunun yalnızca bir üst sınır olduğunu düşünüyorum. Orijinal metindeki örneği önemsiz görmüyorum
let userSignedInTimestamp = new Date()ifadesinilet x = new Date()yapmak önemsizdir; ama tersine gitmek içinx’in hangi bağlamda kullanıldığını görmek üzere çevredeki kodu okuyup anlamak gerekme olasılığı yüksekÜstelik kodun geri kalanı da sıkıştırılmış olduğundan daha zor; her şeyi doğru yapsan bile sonuçta bu kayıplı bir dönüşüm ve değişken adı, kodda açıkça belirtilmeyen özellikler taşıyor olabilir
Bunun nedeni süreçte verinin kaybolmuş olmasıdır
Sıkıştırma da aynı şekilde çalışır. Kodu anlamak için gereken bilginin büyük kısmı kaybolur ve bu bilgiyi geri kazanmak çok zor olabilir
timeFactor’ı çok daha kısaiile değiştirmek mekanik ve basit olabilir, ama bu süreç yıkıcıdır ve geri çevirmek görece kolay değildirKodun gerçekte ne yaptığını oldukça incelikli biçimde anlamadan imkânsızdır. LLM’in burada yaptığı şey tam da bu kısım ve şaşırtıcı olmasa da güzel bir iş. Bu kadar anında küçümseyen tavır pek hoş değil
PC başında olmadığım için test edemedim
Başlıkta şirket adı olan OpenAI yerine ChatGPT ya da model adı olan GPT-4 kullanılmalı değil mi?
LLM’ler metin dönüşümünde mükemmeldir
Bence temel güçlü yönleri bu, ama yeterince kullanılmıyor.
Akıl yürütme ya da bilgiyi koruma gibi diğer yetenekler, amaçlanan anlamı “anlamadan” metni yeniden üretmedeki bu insanüstü yeteneğin yan etkilerinden ibarettir.
Örneğin liste sıralayamazlar ama dil çevirisi yapabilirler. Çünkü neredeyse doğru sıralanmış bir liste yanlıştır, ama neredeyse doğru bir çeviriyi çoğu zaman kabul ederiz.
Bir ekip Python kodunun büyük bir parçasını Elixir’e dönüştürmeye değip değmeyeceğini düşünüyorsa artık yalnızca tahmin yürütmek zorunda değil.
Kısa süre önce bir Python script’ini JavaScript’e çevirmeyi denedim; kusursuzdu ve biraz guardrail ile ölçeği büyütülebilir gibi görünüyor.
Biz çoğunlukla başka biçimlerden yapılandırılmış veri çıkarmak için kullanıyoruz.
Üstelik bunu awk, Python, Perl vb. ile daha hızlı halledecek bilgi ya da beceriden de yoksun olmanız gerekir.
Sıkıştırmayı obfuscation aracı olarak kullanan geliştiricilerin bir kısmı kesinlikle kızacak gibi görünüyor.
Eski ColdFusion sürümlerinde bir kod “şifreleme” aracı olduğu zamanı hatırlatıyor. Algoritma çok zayıftı; birinin bir çözme aracı yazması uzun sürmedi.
Yine de bazıları bu aracın güvenli olduğuna inanıyor ve kaynak kodu açmadan kod satarken kullanıyordu; bu yüzden hoşlanmamışlardı. Açık kaynağın ezici biçimde varsayılan seçenek hâline gelmesinden önceki, 90’ların sonu/2000’lerin başı döneminden bahsediyorum.
Web sitesi, kısmen obfuscate edilmiş istemci tarafı koda dayanan yarışmalar sunar; zeki katılımcılar da artık kazanma şanslarını artırmak için bunu ChatGPT’ye koyabilir.
Daha yeni başlıyoruz.
Bu, insandan üstün entelektüel performans örneği.
Bunu inkâr etmek mümkün değil. Bu iş entelektüel bir iş ve basit ezberle ilgisi yok. Web’de LLM’lerin öğrenebileceği kadar çok sıkıştırılmış kod/sıkıştırması açılmış kod çifti de yok.
LLM, sıkıştırmasını açtığı şeyi anlıyor ve bu belirli konuda genel olarak insandan üstün.
Web’de çok fazla sıkıştırılmış kod ve sıkıştırılmamış kod çifti olmadığından emin olabilir miyiz? Mevcut JS’ten kolayca üretip eğitim seti olarak kullanılabilir; ayrıca zaten eğitimde kullanılmış muazzam miktarda sıkıştırılmamış JS de var.
İnsanların sıkıştırılmış kodu anlamakta zorlanmasının nedeni opak değişken adları, garip döngüler, minimize edilmiş boşluklar vb. şeylerdir. Bilgisayarlar bunlarda zorlanmaz; zaten sıkıştırmayı yapmamızın nedeni de bu. Attention yapısının bu tür işlerde iyi olması gerekir.
Sıkıştırılmış/sıkıştırılmamış kodun da çok fazla olduğunu düşünüyorum. Source map dosyalarının amacı tam olarak bu. OpenAI’ın web tarama ve yazılım geliştirmeye yaptığı yatırımı düşününce, eğitimde sıkıştırılmış/sıkıştırılmamış verileri kullanmış olmaları şaşırtıcı olmaz.
Bir bilgisayarın 1000 basamaklı sayıları anında çarpması, insanların önce böyle bir araç yapıp çarpmayı başardığı bir örnektir. Orada entelektüel olarak başarılı olan başka ne var? Bilgisayar da kendini kendi yapmadı.
İnsan zekâsının sınırını kafatasında kesip, o zekânın yaptığı ve kullandığı araçları problem çözme sürecinin adımları saymazsak, insanların uzaya uçacak, ameliyat yapacak ya da yemeklerin çoğunu pişirecek kadar zeki olmadığını da kabul etmemiz gerekir.
Değişken adları çıkarılmış kodun soyut biçimini tanıyıp, devasa internette gördüğü benzer örüntülere insanın okuyabileceği değişken adlarını eşlemesi absürt görünmüyor.
İlginç ve bayağı iyileşmiş gibi görünüyor.
Bir yılı biraz aşkın süre önce, hack’lenmiş bir WordPress sitesindeki özel bir eklenti için yardım isteyen bir e-posta almıştım ve kötü amaçlı kod obfuscation’ını çözmek için GPT kullanmayı denemiştim. O zaman kodu adım adım kendim takip etmek çok daha hızlı ilerletmişti.
Bu yazıyı okuyunca tekrar denedim [0]. Anlaşılır şeyler verdi ama Window nesnesi üzerinden okunamayan bir string’i fiilen eval edecek şekilde obfuscate edilmişti; bu yüzden tek başına yeterli olmadı.
O dönemde gönderdiğim raporun bir kısmı şöyleydi: Ağır biçimde obfuscate edilmiş JavaScript kodunu inceleyip, sayfa yüklenmesini algılayan, teoride sabit olan bir hesaplama kisvesini çağıran ve ardından sayfayı kötü amaçlı bir siteye yönlendiren mantığı çözebildiğimi anlatıyordu.
[0] https://chatgpt.com/share/f51fbd50-8df0-49e9-86ef-fc972bca6b...
Decompiler LLM üzerinde çalışan var mı?
Tüm kodları açık kaynak gibi yapabilecek gibi görünüyor
Bu durumda eğitim verisi oluşturmak kolay. Ücretsiz GitHub kodlarını çeşitli derleyicilerle toplu şekilde derleyip, derlemeyi geri çevirmeyi öğretebilirsiniz. Sentetik eğitim verisinin uygun ve oldukça kolay üretilebilir olduğu bir durum
Decompiler yalnızca derlemeyi geri çevirmeye eğitilir; yorum ekleme gibi işler için mevcut daha büyük kod LLM’leri kullanılabilir
Açık kaynaklaştırmanın yanı sıra, kapalı kaynak uygulamaları kolayca decompile edip değiştirerek hataları düzeltmeyi ya da özellik eklemeyi hayal edebilirsiniz. Özellikle uzun zaman önce ölmüş programlar için büyük bir özgürleşme alanı olabilir
Hukuki nedenlerle büyük modellerde bu davranışın engellenmiş bir özellik olma olasılığı yüksek
Bu hakları yalnızca kodun yazarı verebilir
Yapay zeka kodu gerçekten iyi anlıyorsa doğrudan binary üretir ya da düzeltir
Gerçek bir yapay zeka programcı ortaya çıktığında, insanın okuyabileceği kodu umursamayıp her şeyi makine dilinde kodlayacağına inanıyorum. Mevcut bir sistemi bakımını yapma görevi verilirse, yazılım ve donanım yığınının tamamını bir bütün olarak anlayacaktır
Bu, görüntü üreten diffusion modellerinin gerçek çizim tekniklerini öğrenmeyi umursamamasına benziyor
Daha çok değişken ve fonksiyon adlarını değiştirmeye ve satır sonları eklemeye benzer
Benim LLM’leri sık kullanma biçimime çok benziyor [0]
Kodu kendi çabamla okumam gerektiğinde, çözümlemenin ilk adımı olarak kullanıyorum
Spagetti gibi darmadağın kodu verip daha okunur hâle getirmesini istemek ve oradan başlayabilmek inanılmaz özgürleştirici
Yazarın da fark ettiği gibi LLM bazen ayrıntıları kaçırıyor, ama o kısımları ben kendim yakalayabiliyorum
Bir diğer kullanım alanı, kodun ne yaptığını anladığım ama neden o şekilde yazıldığını kafamda oturtamadığım durumlar. Özellikle de o kodu yazan kişi artık şirkette değilse. O zaman metodu LLM sohbetine koyup ne yaptığını açıklıyorum, ardından bazı şeylerin neden belirli bir şekilde yapılmış olabileceğini soruyorum
Her zaman mükemmel değil, ama oldukça sık gerçekten mantıklı gelen, incelemeden de sağlam çıkan ve yeni içgörü sağlayan açıklamalar üretiyor. Bir iki kez, daha sonra başımı ağrıtacak biçimde refactor etmeme de engel oldu
[0] chatGPT ve son zamanlarda, başta Claude türevleri olmak üzere çeşitli başka modelleri frontend olarak kullanan openwebUI ile farkları görmek için kullanıyorum. Farklı modellerin birbirlerinin yanıtlarını incelemesini sağlayan ilginç kurulumlar da mümkün
Açılmış kod sıkıştırılmış kodla eşleşmiyorsa, sondaki “LLM yanıtı bazı uygulama ayrıntılarını kaçırmış gibi görünüyor” kısmında olduğu gibi, kullanışlılığı ciddi ölçüde azalır
Özellikle de birçok durumda, yazıdaki gibi kodu basitçe çalıştırıp farkı doğrulamak mümkün olmadığı için
Düzenleme: Aşağıdaki thread’e bakınca bunun bir encoding sorunu olduğu anlaşılıyor. Yine de doğruluk konusunda hâlâ biraz endişeliyim
Bazı durumlarda ChatGPT, açmanın yanı sıra kendi refactoring işlemini de yapmış
Orijinal kod
handleResizeı hemen çağırmıyor, onun içeriğini inline olarak barındırıyor. Muhtemelen minifier gerçek bir inline etme yapmıştı. Buradaki tek gerçek farkif (typeof window < "u")koşulunun eksik olmasıÖzellikle blok karakterlerden bahsediyorum; HN Unicode karakterleri yapıştırmaya izin vermiyor gibi. Orijinal sürümde görünüyorlar ama ChatGPT’nin ürettiği sürümde görünmüyorlar
Yine de gerekli bağlamın tamamını eklememiş olmam da gayet mümkün
Birkaç karakter eksik diye çıktının tamamını küçümsemek fazla titiz bir kusur arama gibi. Bunun dışında bana göre çıktı aynı
Yalnızca değişken ve metot adlarını değiştirmesini söyleseydim, muhtemelen orijinale daha yakın olurdu