Cara Memecahkan GeeTest v3 di C#

solve geetest in c# - How to Solve GeeTest v3 in C# and Post the Result Back

GeeTest mematahkan model berpikir yang mendasari sebagian besar kode CAPTCHA. Tidak ada satu token untuk dimasukkan ke kolom formulir. Satu pemecahan mengembalikan tiga nilai yang harus dikirim kembali bersama-sama, dan challenge yang Anda mulai kedaluwarsa dalam sekitar satu menit. Salah pada salah satu bagian dan permintaannya gagal tanpa error yang berguna.

Inilah keseluruhan alurnya dalam C#, termasuk bagian-bagian yang mudah salah.

Dua input, dan hanya satu di antaranya yang stabil

GeeTest v3 mengidentifikasi situs dengan gt dan satu percobaan dengan challenge. Keduanya berperilaku sangat berbeda.

NilaiSeumur hidupDari mana asalnya
gtStatis untuk situs tersebut. Aman untuk di-hard-code atau di-cacheRespons init GeeTest milik situs tersebut
challengeSekali pakai, kedaluwarsa dalam kurang lebih 60 detikRespons init yang sama, selalu baru setiap kali

Masa kedaluwarsa itu adalah penyebab tunggal paling umum kegagalan GeeTest. Jika Anda mengambil sepasang nilai, mengantrekan pekerjaannya, lalu memecahkannya tiga puluh detik kemudian di belakang pekerjaan lain, challenge itu mungkin sudah mati. Ambil tepat sebelum memecahkan, jangan pernah dari cache.

Penyiapan

# Targets .NET Standard 2.0, so Framework 4.6.1+ and .NET 6-9 all work.
dotnet add package CapSkip

CapSkip berjalan di komputer Anda sendiri, jadi jalankan dulu aplikasinya lalu arahkan client ke port yang tercantum di pengaturannya:

using CapSkip;

var solver = new CapSkipClient(
    apiKey: "capskip",        // any string when key validation is off
    host: "127.0.0.1",
    port: 8080,
    recaptchaTimeout: 300);   // seconds, and this one covers GeeTest too

Perhatikan bahwa GeeTest menggunakan recaptchaTimeout, bukan defaultTimeout. Yang terakhir hanya berlaku untuk CAPTCHA gambar.

Memecahkannya

Tiga argumen posisional, dalam urutan ini:

var result = await solver.GeetestAsync(
    "81388ea1fc187e0c335c0a8907ff2625",   // gt, static per site
    "7cf6a8b1a2c34d5e6f7089abcdef0123",   // challenge, fetched seconds ago
    "https://example.com/login");

Console.WriteLine(result.Challenge);
Console.WriteLine(result.Validate);
Console.WriteLine(result.Seccode);

Ketiga properti itulah jawabannya. result.Code juga terisi, tetapi untuk GeeTest isinya adalah string JSON mentah, bukan token yang bisa dipakai, sehingga mengambil Code karena kebiasaan adalah kesalahan. Pada SolveResult, Challenge, Validate dan Seccode hanya untuk GeeTest dan bernilai null untuk semua jenis lainnya.

Perlu diketahui: challenge yang dikembalikan tidak selalu sama dengan yang Anda kirim. Gunakan nilai yang dikembalikan, bukan input Anda.

Mengirim balik jawabannya

Kirim ketiganya persis seperti yang akan dilakukan front end situs itu sendiri. Sebagian besar integrasi GeeTest v3 menggunakan nama kolom ini, meskipun sebuah situs dapat mengganti namanya, jadi periksa formulir yang sebenarnya sebelum berasumsi:

using System.Net.Http;
using System.Collections.Generic;

using var http = new HttpClient();

var form = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("geetest_challenge", result.Challenge),
    new KeyValuePair<string, string>("geetest_validate",  result.Validate),
    new KeyValuePair<string, string>("geetest_seccode",   result.Seccode),
    new KeyValuePair<string, string>("username", "..."),
    new KeyValuePair<string, string>("password", "..."),
});

var response = await http.PostAsync("https://example.com/login", form);

Mengirim dua dari tiga, atau memasangkan versi baru validate dengan challenge, akan ditolak dengan cara yang sama seperti jawaban yang salah.

Seluruh alur, secara berurutan

Pengambilan pasangan dan pemecahan harus berdampingan. Bentuk kode ini menjaga keduanya tetap begitu:

using System;
using System.Net.Http;
using System.Text.Json;
using CapSkip;

// 1. Fetch a fresh gt/challenge pair from the site's own init endpoint.
using var http = new HttpClient();
var initJson = await http.GetStringAsync(
    "https://example.com/geetest/init?t=" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());

using var doc = JsonDocument.Parse(initJson);
var gt        = doc.RootElement.GetProperty("gt").GetString();
var challenge = doc.RootElement.GetProperty("challenge").GetString();

// 2. Solve immediately. Do not queue this or await anything slow in between.
var result = await solver.GeetestAsync(gt, challenge, "https://example.com/login");

// 3. Post all three values together.
Console.WriteLine($"{result.Challenge} {result.Validate} {result.Seccode}");

Timestamp cache-busting pada panggilan init lebih penting daripada kelihatannya. Endpoint init GeeTest sering di-cache oleh perantara, dan respons yang di-cache memberi Anda tantangan yang sudah terpakai.

Ketika gagal

using System;
using CapSkip;

try
{
    var result = await solver.GeetestAsync(gt, challenge, pageUrl);
}
catch (CapSkip.ValidationException) { /* missing gt or challenge */ }
catch (NetworkException)            { /* CapSkip is not running */ }
catch (ApiException)                { /* API error, often a dead challenge */ }
catch (CapSkip.TimeoutException)    { /* exceeded recaptchaTimeout */ }
catch (CapSkipError)                { /* anything else from the SDK */ }

Qualify ValidationException dan TimeoutException dengan CapSkip namespace. Kedua nama juga ada di System, dan dengan kedua namespace diimpor, catch tanpa kualifikasi terikat ke System tipe dan diam-diam tidak pernah terpicu. Menangkap kelas dasar CapSkipError menghindari masalah itu sepenuhnya.

Dalam praktiknya sebagian besar kegagalan GeeTest muncul sebagai ApiException dan berarti tantangan sudah mati sebelum pemecahan selesai. Perbaikannya adalah mengambil lebih lambat, bukan mencoba ulang dengan nilai yang sama.

Proxy dan konkurensi

GeeTest adalah salah satu dari tiga tipe yang menerima proxy, bersama reCAPTCHA dan Turnstile. CAPTCHA gambar tidak, karena tidak pernah menyentuh situs target.

using System.Collections.Generic;

var result = await solver.GeetestAsync(gt, challenge, pageUrl,
    new Dictionary<string, object?>
    {
        ["proxy"] = new Proxy("HTTPS", "user:[email protected]:3128"),
    });

Menjalankan beberapa secara paralel memang bisa, tetapi masing-masing memerlukan pasangan yang baru diambil sendiri. Jangan mengambil sekumpulan tantangan di awal lalu memecahkannya bersamaan, karena yang terakhir akan kedaluwarsa sebelum tiba gilirannya.

// Correct: fetch and solve inside the same task.
var tasks = urls.Select(async url =>
{
    var (gt, challenge) = await FetchPairAsync(url);
    return await solver.GeetestAsync(gt, challenge, url);
});

var results = await Task.WhenAll(tasks);

Pertanyaan yang sering diajukan

Mengapa result.Code bukan token yang bisa dipakai?

Karena jawaban GeeTest terdiri dari tiga nilai, bukan satu. Code menyimpan string JSON mentah demi kelengkapan, sementara SDK menguraikan bagian yang berguna menjadi Challenge, Validate dan Seccode. Gunakan ketiganya.

Bisakah saya menyimpan challenge di cache untuk menghemat satu permintaan?

Tidak. Nilainya sekali pakai dan kedaluwarsa dalam sekitar satu menit. Menyimpannya di cache adalah alasan paling umum integrasi GeeTest berhasil saat pengujian dan gagal saat beban tinggi, karena penundaan antrean mendorong pemecahan melewati jendela kedaluwarsa. gt nilai aman untuk di-cache.

Apakah ini bekerja untuk GeeTest v4?

The GeetestAsync metode ini menargetkan v3, versi puzzle geser yang dibangun di sekitar gt dan challenge pasangan. v4 mengubah model parameternya, jadi periksa versi terkini dari dokumentasi API untuk mengetahui apa yang didukung sebelum menganggap panggilan yang sama berfungsi.

Apakah saya perlu proxy?

Hanya ketika situs sensitif terhadap lokasi atau sudah menganggap alamat Anda mencurigakan. Pecahkan dan kirim dari jalur jaringan yang sama saat Anda memang memakainya, jika tidak, ketidakcocokan itu sendiri dapat memicu tantangan ulang.

Ringkasan

Ambil gt dan challenge tepat sebelum memecahkan, panggil GeetestAsync dengan keduanya ditambah URL halaman, lalu kirim Challenge, Validate dan Seccode kembali bersama-sama. Perlakukan tantangan sebagai sesuatu yang cepat kedaluwarsa, gunakan challenge yang dikembalikan alih-alih input Anda, dan tangkap CapSkipError untuk menghindari benturan namespace.

Signature metode untuk bahasa lainnya ada di pemecah GeeTest , cakupan .NET lengkap ada di halaman pemecah CAPTCHA C# , dan Anda dapat mencoba puzzle langsung di halaman kami Demo GeeTest v3. CapSkip menangani bypass captcha secara lokal, sehingga volume pemecahan tidak memakan biaya per permintaan.