Google Translation API Hacking

Google, Google Cloud'un bir parçası olarak Google Translation API'yi kullanıma dayalı bir maliyet yapısıyla sunmaktadır . Ayrıca, anahtarsız kullanılabilen, ancak yalnızca birkaç istekten sonra çalışmayı reddeden belgelenmemiş bir API vardır. Google Chrome'un web sitesi çeviri işlevini kullanırken, sayfaların herhangi bir sınırlama olmaksızın çok iyi kalitede çevrilebildiği fark edilir.


Görünüşe göre gelişmiş nmt modeli zaten burada kullanılıyor. Ancak Google Chrome, içeriği çevirmek için dahili olarak hangi API'yi kullanıyor ve bu API, sunucu tarafında bile doğrudan adreslenebilir mi? Ağ trafiğini analiz etmek için şifreli trafiği de analiz edebilen Wireshark veya Telerik Fiddler gibi araçlar önerilir. Ancak Chrome, sayfa çevirisi için gönderdiği istekleri de ücretsiz olarak sunar: Bunlar, Chrome DevTools kullanılarak kolayca görüntülenebilir:

Bir çeviri gerçekleştirirseniz, "Kopyala> cURL (bash) olarak kopyala" yoluyla https://translate.googleapis.com için önemli POST isteğini yakalayın ve bunu Postman gibi bir araçta yürütün, örneğin, isteği olmadan gönderebilirsiniz Sorunları yeniden gönderin:

URL parametrelerinin anlamı da büyük ölçüde açıktır:

AnahtarÖrnek değerAnlamı
anno3Ek açıklama modu (dönüş biçimini etkiler)
müşterite_libMüşteri bilgileri (değişiklik gösterir, değer, Google Translate'in web arayüzü üzerinden "webapp" dır; iade biçimi ve oran sınırlaması üzerinde etkisi vardır)
biçimhtmlDize biçimi (HTML etiketlerini çevirmek için önemlidir)
v1.0Google Translate sürüm numarası
anahtarAIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgwAPI anahtarı (aşağıya bakın)
logldvTE_20200210_00Protokol versiyonu
sldeKaynak dil
tlenHedef dil
spnmtML modeli
tc1Bilinmeyen
sr1Bilinmeyen
tk709408.812158Jeton (aşağıya bakın)
Moda1Bilinmeyen

Bazı istek başlıkları da ayarlanmıştır - ancak bunlar çoğunlukla göz ardı edilebilir. Kullanıcı aracısından olanlar da dahil olmak üzere tüm başlıkların seçimi manuel olarak kaldırıldıktan sonra, özel karakterler girilirken bir kodlama sorunu keşfedilir (burada " Merhaba Dünya " çevrilirken):

Kullanıcı aracısını yeniden etkinleştirirseniz (bu genellikle herhangi bir zarar vermez), API UTF-8 kodlu karakterler sunar:

Zaten orada mıyız ve bu API'yi Google Chrome dışında kullanmak için tüm bilgilere sahip miyiz? Çevrilecek karakter dizesini (POST isteğinin veri alanı q ), örneğin "Merhaba dünya" dan "Merhaba dünya ! ", Ancak bir hata mesajı alıyoruz:

Şimdi bu değişikliği Google Chrome'da web sitesi çeviri işlevi yardımıyla tekrar çeviriyoruz ve q parametresine ek olarak tk parametresinin de değiştiğini gördük (diğer tüm parametreler aynı kaldı):

Açıkçası, dizgeye bağlı, yapısı görülmesi kolay olmayan bir belirteçtir. Web sitesi çevirisini başlatırsanız, aşağıdaki dosyalar yüklenir:

  • 1 CSS dosyası: translateelement.css
  • 4 grafik: translate_24dp.png (2x), gen204 (2x)
  • 2 JS dosyası: main_de.js , element_main.js

İki JavaScript dosyası gizlenmiş ve küçültülmüştür. JS Nice ve de4js gibi araçlar artık bu dosyaları daha okunaklı hale getirmemize yardımcı oluyor. Bunlarda canlı olarak hata ayıklamak için, uzaktaki dosyaları anında yerel olarak tünelleyen Chrome Uzantı İsteği'ni öneririz:

Artık kodda hata ayıklayabiliriz ( CORS önce yerel sunucuda etkinleştirilmelidir). Belirteci oluşturmak için ilgili kod bölümü, bu bölümdeki element_main.js dosyasında gizli görünüyor:

b7739bf50b2edcf636c43a8f8910def9

Burada metin, bazı bit kaydırmalarının yardımı ile karma hale getirilir. Ne yazık ki, bulmacanın bir parçasını hala kaçırıyoruz: a argümanına ek olarak (çevrilecek metin), başka bir b argümanı Bp () fonksiyonuna geçirildi - zaman zaman değişiyor gibi görünen ve aynı zamanda şunları da içeren bir tür tohum hashing içine akar. Ama nereden geliyor? Bp () işlev çağrısına atlarsak aşağıdaki kod bölümünü buluruz:

b7739bf50b2edcf636c43a8f8910def9

Hq işlevi önceden şu şekilde bildirilir:

b7739bf50b2edcf636c43a8f8910def9

Deobfuscater burada biraz çöp bıraktı; String.fromCharCode ('...') 'yi ilgili karakter dizeleriyle değiştirdikten sonra, kullanılmayan a () ' yı kaldırın ve [c (), c ()] işlev çağrılarını bir araya getirin, sonuç:

b7739bf50b2edcf636c43a8f8910def9

Veya daha da kolay:

b7739bf50b2edcf636c43a8f8910def9

Yq işlevi daha önce şu şekilde tanımlanmıştır:

b7739bf50b2edcf636c43a8f8910def9

Çekirdek , çalışma zamanında kullanılabilen google.translate._const._ctkk genel nesnesinde görünüyor. Ama nereye yerleştirildi? Diğerinde , önceden yüklenmiş JS dosyası main_de.js, en azından başlangıçta da mevcuttur. Aşağıdakileri başlangıca ekliyoruz:

b7739bf50b2edcf636c43a8f8910def9

Konsolda aslında mevcut tohumu alıyoruz:

Bu, son seçenek olarak görünüşe göre tohumu sağlayan Google Chrome'un kendisini bırakır. Neyse ki, kaynak kodu (Chromium, Translate bileşeni dahil) açık kaynaktır ve bu nedenle halka açıktır. Depoyu yerel olarak çekiyoruz ve Components / translate / core / browser klasöründeki translate_script.cc dosyasında TranslateScript :: GetTranslateScriptURL işlevinin çağrısını buluyoruz:

b7739bf50b2edcf636c43a8f8910def9

URL'li değişken aynı dosyada sabit olarak tanımlanmıştır:

b7739bf50b2edcf636c43a8f8910def9

Şimdi element.js dosyasını daha yakından incelersek (tekrar gizlendikten sonra), sabit ayarlanmış c._ctkk girişini buluruz - google.translate nesnesi de buna göre ayarlanır ve daha önce keşfetmiş olduğumuz tüm ilgili varlıkların yüklenmesi tetiklenir. :

b7739bf50b2edcf636c43a8f8910def9

Şimdi parametre anahtarı dikkate alınmak üzere kalır (AIzaSyBOti4mM-6x9WDnZIjIeyEU21OpBXqWBgw değeriyle). Bu, genel bir tarayıcı API anahtarı gibi görünüyor (bazı Google sonuçlarında da bulunabilir). Chromium'da, components / translate / core / browser klasöründeki translate_url_util.cc dosyasında ayarlanır:

b7739bf50b2edcf636c43a8f8910def9

Anahtar, google_apis / google_api_keys.cc'de sahte bir değerden oluşturulur:

b7739bf50b2edcf636c43a8f8910def9

Ancak bir test, API çağrılarının bu anahtar parametresi olmadan aynı şekilde çalıştığını gösterir. API ile deneme yaparsanız, başarılı olursanız 200 durum kodunu geri alırsınız. Daha sonra bir sınırla karşılaşırsanız, 411 durum kodunu " POST istekleri bir içerik uzunluğu başlığı gerektirir " mesajıyla geri alırsınız. Bu nedenle , bu başlığın dahil edilmesi önerilir (bu, otomatik olarak Postman'da geçici bir başlık olarak ayarlanır).

Tercüme edilen dizelerin dönüş biçimi, bir istekte birden fazla cümle olduğunda olağandışıdır. Tek tek cümleler i- / b-HTML etiketlerinin içine alınır:

Ayrıca, Google Chrome HTML'nin tamamını API'ye göndermez, ancak istekte href gibi öznitelik değerlerini kaydeder (ve bunun yerine etiketlerin daha sonra istemci tarafında atanabilmesi için indeksler ayarlar):

POST anahtar istemcisinin değerini te_lib'den (Google Chrome) değiştirirseniz webapp (on yapıldı web sitesi ), son çevrilen dize olsun:

Sorun şu ki, te_lib üzerinden oran sınırlamasıyla karşılaşma olasılığınız çok daha yüksektir (karşılaştırma için: webapp ile buna 40.000 karakterden sonra ulaşılır, te_lib ile hız sınırlaması yoktur). Bu nedenle, Chrome'un sonucu nasıl ayrıştırdığına daha yakından bakmamız gerekiyor. Bunu burada element_main.js'de bulacağız :

b7739bf50b2edcf636c43a8f8910def9

HTML kodunun tamamını API'ye gönderirseniz, öznitelikleri çevrilmiş yanıtta bırakır. Bu nedenle, tüm ayrıştırma davranışını taklit etmemiz gerekmez, yanıttan yalnızca son, çevrilmiş dizeyi çıkarırız. Bunu yapmak için <i >, içerikleri dahil en</i> dıştaki <i >etiketleri atan ve</i> en dıştaki <i >etiketleri <b >kaldıran</b></i> küçük bir HTML etiket ayrıştırıcısı oluşturuyoruz <i >. Bunu aklımızda tutarak, artık çeviri API'sinin sunucu tarafı bir sürümünü oluşturabiliriz:</i>

b7739bf50b2edcf636c43a8f8910def9

Aşağıdakiler, farklı bant genişliklerine ve IP adreslerine sahip beş farklı sistemde gerçekleştirilen ilk testin sonuçlarıdır:

Karakterİstek başına karakterSüreHata oranıResmi API üzerinden maliyet
13.064.662~25003: 36: 17h0%237,78€
24.530.510~25011: 09: 13h0%446,46€
49.060.211~25020: 39: 10h0%892,90€
99.074.487~100061: 24: 37h0%1803,16€
99.072.896~100062: 22: 20h0%1803,13€
Σ284.802.766~Ø550159: 11: 37h0%Σ5183,41€

Not: Tüm komut dosyalarını içeren bu blog gönderisi yalnızca test amaçlı yazılmıştır. Komut dosyalarını kullanın Değil verimli kullanım için, ancak bunun yerine resmi olanla çalışın Google Translation API.

Geri