Обход защиты cloudflare на запросах, C++ и QT.

Не так давно я интересовался вопросом по поводу, как обойти cloudflare и единственное что я нашел в сети это методы, которые помогают вычислить ip сайта стоящего за cloudflare. Их смысл состоял в том, чтобы узнать реальный ip сервера, на котором расположен сайт, и далее уже коннектится напрямую к нему. Но у этих способов есть недостатки. Не всегда, получается, узнать ip и редко можно встретить сервер, который неправильно настроен, под словом неправильно имеется в виду следующие — как правило, чтобы обеспечить максимальную защиту, админ сервера должен его настроить так чтобы сервер принимал запросы только от ip cloudflare сервера, а все остальные игнорировал.

Нужно то, что сработает всегда и наверняка. У людей есть плохая особенность они боятся того чего не знают, я почему-то думал что пройти защиту программно невозможно, в голове были мысли – “куда там мне”, считал  что там все так сложно придумано.  Но блин, какое было мое разочарование, когда я увидел в исходном коде страницы защиту, основанную на несчастном джаваскрипте который был немного обфусцирован.

Ну, в общем, хватит болтать, поехали. Сразу предупреждаю работать мы будем на QT. Перед нами страшный джаваскрипт который генерирует число передаваемое в параметрах формы.

 
(function(){
 var a = function() {try{return !!window.addEventListener} catch(e) {return !1} },
 b = function(b, c) {a() ? document.addEventListener("DOMContentLoaded", b, c) : document.attachEvent("onreadystatechange", b)};
 b(function(){
 var a = document.getElementById('cf-content');a.style.display = 'block';
 setTimeout(function(){
 var s,t,o,p,b,r,e,a,k,i,n,g,f, yLAlvso={"FVh":+((!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]))};
 t = document.createElement('div');
 t.innerHTML="<a href='/'>x</a>";
 t = t.firstChild.href;r = t.match(/https?:\/\//)[0];
 t = t.substr(r.length); t = t.substr(0,t.length-1);
 a = document.getElementById('jschl-answer');
 f = document.getElementById('challenge-form');
 ;yLAlvso.FVh*=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh+=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+!![]));yLAlvso.FVh-=!+[]+!![]+!![]+!![]+!![];yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+[]));yLAlvso.FVh*=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]));a.value = parseInt(yLAlvso.FVh, 10) + t.length; '; 121'
 f.submit();
 }, 4000);
 }, false);
 })();

из этого кода можно половину удалить, в этом куске просто парсится домен сайта

 
t = document.createElement('div');
 t.innerHTML="<a href='/'>x</a>";
 t = t.firstChild.href;r = t.match(/https?:\/\//)[0];
 t = t.substr(r.length); t = t.substr(0,t.length-1);

остальное просто управляет формой, нас интересует только эти две строки

 var s,t,o,p,b,r,e,a,k,i,n,g,f, yLAlvso={"FVh":+((!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]))};
yLAlvso.FVh*=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh+=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+!![]));yLAlvso.FVh-=!+[]+!![]+!![]+!![]+!![];yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+[]));yLAlvso.FVh*=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]));a.value = parseInt(yLAlvso.FVh, 10) + t.length;
Что делаем поэтапно: 

1) Парсим первую строку
 var s,t,o,p,b,r,e,a,k,i,n,g,f, yLAlvso={"FVh":+((!+[]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]))};
2) К тому что спарсили дописываем
t = "домен сайта"; 

3) Парсим вторую строку

yLAlvso.FVh*=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]));yLAlvso.FVh-=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh+=+((+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]));yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+!![]));yLAlvso.FVh-=!+[]+!![]+!![]+!![]+!![];yLAlvso.FVh*=+((!+[]+!![]+!![]+!![]+[])+(+[]));yLAlvso.FVh*=+((!+[]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]));a.value = parseInt(yLAlvso.FVh, 10) + t.length;

4) QT имеет в своем арсенале класс QJSEngine для выполнения джаваскрипт кода, мы просто пихаем в него то что спарсили и получаем число которое надо вставить в форму запроса, все, парсим поля в форме, ждем 5 сек и отправляем, вот так выглядит рабочий код.

QString Url = "satoshiwars.com", tempString;
QByteArray VAR_$request;

 if(!qmc.UrlGetContens(Url,VAR_$request)){
 lastError = "ошибка при получении результата запроса";
 return 0;
 }
 //==============Получили страницу сервера============
 int af1 = 0,af2=0;
 af1 = VAR_$request.indexOf("var s,t,o,p");
 if(af1 == -1){
 lastError = "не удалось пройти cloud flare";
 return 0;
 }
 af2 = VAR_$request.indexOf(";",af1);
 af2++;
 tempString += VAR_$request.mid(af1,af2-af1); 
 
 //==============Спарсили первую строку============

 QUrl sqrl(Url);
 tempString += "t = \""+sqrl.host()+"\";";
 
 //==============Дописали домен в переменную t============

 af1 = VAR_$request.indexOf("ge-form');");
 if(af1 == -1){
 lastError = "не удалось пройти cloud flare";
 return 0;
 }
 af1+=20;
 af2 = VAR_$request.indexOf("t.length;",af1);
 af2+=9;
 tempString += VAR_$request.mid(af1,af2-af1);
 tempString.replace("a.value","a");
 
 //==============Спарсили вторую строку, a.value заменили на а чтобы в нее записать результат вычисления============

 QJSEngine myEngine;
 tempString = myEngine.evaluate(tempString).toString();
 
 //==============Выполнили джаваскрипт - получили зашифрованное число============

 QString jschl_vc,pass;

 af1 = VAR_$request.indexOf("jschl_vc\" value=\"");
 if(af1 == -1){
 lastError = "не удалось пройти cloud flare";
 return 0;
 }
 af1+=17;
 af2 = VAR_$request.indexOf("\"",af1);
 jschl_vc = VAR_$request.mid(af1,af2-af1);

 af1 = VAR_$request.indexOf("pass\" value=\"");
 if(af1 == -1){
 lastError = "не удалось пройти cloud flare";
 return 0;
 }
 af1+=13;
 af2 = VAR_$request.indexOf("\"",af1);
 pass = VAR_$request.mid(af1,af2-af1);
 
 //==============Спарсили поля формы jschl_vc и pass============

 QThread::sleep(5000);
 
 //==============Подождали 5 сек============

 sqrl.setPath("/cdn-cgi/l/chk_jschl?jschl_vc="+jschl_vc+"&pass="+pass+"&jschl_answer="+tempString);
 if(!qmc.UrlGetContens(sqrl.toString(),VAR_$request)){
 lastError = "ошибка при получении результата запроса";
 return 0;
 }
 
//==============Отправили запрос, получили куки, и получаем далее уже сможем получить страницу сайта============

Проголосовать за статью

2 thoughts on “Обход защиты cloudflare на запросах, C++ и QT.

  1. Супер, спасибо 🙂 Не пришлось голову ломать что там к чему, сразу все разжевано 🙂

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *