1. // ==UserScript==
  2. // @name Bypass FileCrypt (Improved)
  3. // @namespace IA
  4. // @version 1.0.4b
  5. // @description Bypass FileCrypt with improved link extraction
  6. // @author IA (with improvements)
  7. // @license MIT
  8. // @match http://filecrypt.cc/*
  9. // @match http://www.filecrypt.cc/*
  10. // @match http://filecrypt.co/*
  11. // @match http://www.filecrypt.co/*
  12. // @match https://filecrypt.cc/*
  13. // @match https://www.filecrypt.cc/*
  14. // @match https://filecrypt.co/*
  15. // @match https://www.filecrypt.co/*
  16. // @run-at document-end
  17. // @connect dcrypt.it
  18. // @connect self
  19. // @grant GM.xmlHttpRequest
  20. // ==/UserScript==
  21. (function() {
  22. 'use strict';
  23. // Determine if dark theme is used
  24. const isDarkTheme = document.head.querySelector('meta[name="theme-color"]') !== null ||
  25. document.body.classList.contains('dark') ||
  26. window.getComputedStyle(document.body).backgroundColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)/)?.[1] < 100;
  27. // Add basic stylesheet
  28. addStylesheet(isDarkTheme);
  29. // Remove ads
  30. removeAds();
  31. // Apply main functionality based on URL
  32. if (document.location.href.includes("/Link/")) {
  33. getSingleLink();
  34. } else if (document.location.href.includes("/Container/")) {
  35. waitForCaptchaSolved();
  36. }
  37. })();
  38. // Add basic stylesheet
  39. function addStylesheet(isDarkTheme) {
  40. const style = document.createElement('style');
  41. const colors = isDarkTheme ? {
  42. background: '#1e1e2e',
  43. text: '#cdd6f4',
  44. accent: '#cba6f7',
  45. border: '#313244',
  46. error: '#f38ba8'
  47. } : {
  48. background: '#ffffff',
  49. text: '#333333',
  50. accent: '#4f46e5',
  51. border: '#e5e7eb',
  52. error: '#ef4444'
  53. };
  54. style.textContent = `
  55. .fc-container {
  56. background-color: ${colors.background};
  57. color: ${colors.text};
  58. border: 1px solid ${colors.border};
  59. border-radius: 10px;
  60. padding: 1em;
  61. margin: 1em auto;
  62. max-width: 600px;
  63. position: relative;
  64. z-index: 10;
  65. font-size: 14px;
  66. }
  67. .fc-container span {
  68. cursor: pointer;
  69. color: ${colors.accent};
  70. }
  71. .fc-container span:hover {
  72. text-decoration: underline;
  73. }
  74. .fc-error {
  75. color: ${colors.error};
  76. }
  77. .fc-loading {
  78. text-align: center;
  79. padding: 1em;
  80. }
  81. `;
  82. document.head.appendChild(style);
  83. }
  84. // Remove ads
  85. function removeAds() {
  86. const usenetAds = document.querySelectorAll('a[href*="/pink/"]');
  87. for (const ad of usenetAds) {
  88. if (ad.parentNode) ad.parentNode.remove();
  89. }
  90. }
  91. // Check if captcha is solved
  92. function waitForCaptchaSolved() {
  93. function isCaptchaSolved() {
  94. return document.querySelectorAll('.dlcdownload, .download, [href*="/DLC/"]').length > 0;
  95. }
  96. if (isCaptchaSolved()) {
  97. processContainerPage();
  98. return;
  99. }
  100. const captchaObserver = new MutationObserver((mutations, observer) => {
  101. if (isCaptchaSolved()) {
  102. observer.disconnect();
  103. processContainerPage();
  104. }
  105. });
  106. captchaObserver.observe(document.body, {
  107. childList: true,
  108. subtree: true
  109. });
  110. }
  111. // Process container page
  112. function processContainerPage() {
  113. const containerSection = findBestContainer();
  114. const container = createLinkBox();
  115. containerSection.insertBefore(container, containerSection.firstChild);
  116. const dlcButtons = document.querySelectorAll('.dlcdownload, [href*="/DLC/"]');
  117. if (dlcButtons.length > 0) {
  118. const dlcId = dlcButtons[0].getAttribute('onclick')?.split("'")[1] ||
  119. dlcButtons[0].getAttribute('href')?.match(/\/DLC\/(.+)\.dlc/)?.[1];
  120. if (dlcId) {
  121. fetchDlcAndDecrypt(dlcId, container);
  122. return;
  123. }
  124. }
  125. xhrLinkExtract(container);
  126. }
  127. // Find the best container
  128. function findBestContainer() {
  129. const selectors = [
  130. '.content .window',
  131. '.download',
  132. '.content',
  133. 'main',
  134. 'article',
  135. '.container',
  136. '#container'
  137. ];
  138. for (const selector of selectors) {
  139. const element = document.querySelector(selector);
  140. if (element) return element;
  141. }
  142. return document.body;
  143. }
  144. // Create link box
  145. function createLinkBox() {
  146. const container = document.createElement('div');
  147. container.className = 'fc-container';
  148. container.id = 'fc-container';
  149. const loading = document.createElement('div');
  150. loading.className = 'fc-loading';
  151. loading.textContent = 'Decrypting links...';
  152. container.appendChild(loading);
  153. return container;
  154. }
  155. // Fetch and decrypt DLC
  156. function fetchDlcAndDecrypt(dlcId, container) {
  157. container.querySelector('.fc-loading').textContent = 'Fetching DLC file...';
  158. GM.xmlHttpRequest({
  159. method: 'GET',
  160. url: `https://${document.location.hostname}/DLC/${dlcId}.dlc`,
  161. headers: {
  162. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  163. },
  164. onload: function(response) {
  165. container.querySelector('.fc-loading').textContent = 'Decrypting via dcrypt.it...';
  166. GM.xmlHttpRequest({
  167. method: 'POST',
  168. url: 'http://dcrypt.it/decrypt/paste',
  169. headers: {
  170. 'Content-Type': 'application/x-www-form-urlencoded',
  171. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  172. },
  173. data: 'content=' + encodeURIComponent(response.responseText),
  174. onload: function(res) {
  175. try {
  176. const result = JSON.parse(res.responseText);
  177. if (result.success && result.success.links && result.success.links.length > 0) {
  178. displayLinks(result.success.links, container);
  179. } else {
  180. console.error('No links from dcrypt.it:', result);
  181. xhrLinkExtract(container);
  182. }
  183. } catch (e) {
  184. console.error('Error parsing dcrypt.it response:', e);
  185. xhrLinkExtract(container);
  186. }
  187. },
  188. onerror: function() {
  189. console.error('Error connecting to dcrypt.it');
  190. xhrLinkExtract(container);
  191. }
  192. });
  193. },
  194. onerror: function() {
  195. console.error('Error fetching DLC file');
  196. xhrLinkExtract(container);
  197. }
  198. });
  199. }
  200. // Process single link page
  201. function getSingleLink() {
  202. if (document.body.getElementsByTagName('SCRIPT').length === 0) {
  203. window.stop();
  204. let htmlContent = document.body.innerHTML;
  205. if (document.body.children.length === 0) {
  206. GM.xmlHttpRequest({
  207. method: 'GET',
  208. url: document.location.href,
  209. headers: {
  210. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  211. },
  212. onload: function(response) {
  213. extractAndResolveLink(response.responseText);
  214. },
  215. onerror: function() {
  216. console.error('Failed to fetch page content');
  217. }
  218. });
  219. } else {
  220. extractAndResolveLink(htmlContent);
  221. }
  222. }
  223. }
  224. function extractAndResolveLink(htmlContent) {
  225. const urlMatch = htmlContent.match(/https?:\/\/[^\s'"]+/);
  226. if (urlMatch) {
  227. let intermediateLink = urlMatch[0].replace(/&amp;/g, '&');
  228. resolveFinalLink(intermediateLink);
  229. } else {
  230. console.error('No valid URL found in HTML');
  231. }
  232. }
  233. function resolveFinalLink(intermediateLink) {
  234. GM.xmlHttpRequest({
  235. method: 'GET',
  236. url: intermediateLink,
  237. headers: {
  238. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  239. },
  240. timeout: 5000,
  241. onload: function(response) {
  242. let finalUrl = response.finalUrl || intermediateLink;
  243. console.log('Resolved final URL:', finalUrl);
  244. top.location.href = finalUrl;
  245. },
  246. onerror: function() {
  247. console.error('Error resolving link:', intermediateLink);
  248. top.location.href = intermediateLink;
  249. }
  250. });
  251. }
  252. // Extract links directly
  253. function xhrLinkExtract(container) {
  254. const loading = container.querySelector('.fc-loading');
  255. loading.textContent = 'Extracting links directly...';
  256. console.log('Starting xhrLinkExtract');
  257. const encLinks = document.querySelectorAll('[onclick^=openLink], a[href*="/Link/"], [data-link], .download-link');
  258. console.log('Found links:', encLinks.length);
  259. if (encLinks.length === 0) {
  260. showError('No links found on this page.', container);
  261. return;
  262. }
  263. const finalLinksDiv = document.createElement('div');
  264. finalLinksDiv.style.backgroundColor = isDarkTheme ? '#1e1e2e' : '#ffffff';
  265. finalLinksDiv.style.color = isDarkTheme ? '#cdd6f4' : '#333333';
  266. finalLinksDiv.style.padding = '1em';
  267. finalLinksDiv.innerHTML = '<span>Decrypted links:</span><br><br>';
  268. container.replaceChild(finalLinksDiv, loading);
  269. function processLinks(index = 0) {
  270. if (index >= encLinks.length) {
  271. if (!finalLinksDiv.querySelector('a')) {
  272. showError('Failed to extract any valid links.', container);
  273. }
  274. return;
  275. }
  276. const link = encLinks[index];
  277. let linkUrl;
  278. if (link.getAttribute('href')?.includes('/Link/')) {
  279. linkUrl = link.getAttribute('href');
  280. } else if (link.getAttribute('onclick')?.startsWith('openLink')) {
  281. const passA = link.getAttribute('onclick');
  282. const passB = passA.split("'")[1];
  283. const passC = link.getAttribute(passB);
  284. linkUrl = `http://${document.location.hostname}/Link/${passC}.html`;
  285. } else {
  286. linkUrl = link.getAttribute('data-link') || link.getAttribute('href');
  287. }
  288. if (!linkUrl) {
  289. console.error('No valid URL for link:', link);
  290. setTimeout(() => processLinks(index + 1), 100);
  291. return;
  292. }
  293. console.log('Processing URL:', linkUrl);
  294. GM.xmlHttpRequest({
  295. method: 'GET',
  296. url: linkUrl,
  297. headers: {
  298. 'Content-Type': 'application/x-www-form-urlencoded',
  299. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  300. },
  301. timeout: 5000,
  302. onload: function(response) {
  303. let parser = new DOMParser();
  304. let doc = parser.parseFromString(response.responseText, 'text/html');
  305. let scripts = doc.getElementsByTagName('SCRIPT');
  306. console.log('Scripts found for', linkUrl, ':', scripts.length);
  307. for (let s of scripts) {
  308. if (s.innerHTML.includes('top.location.href=')) {
  309. getFinalLink(s.innerHTML.split("'")[1], finalLinksDiv);
  310. setTimeout(() => processLinks(index + 1), 100);
  311. return;
  312. }
  313. }
  314. let metaRefresh = doc.querySelector('meta[http-equiv="refresh"]');
  315. if (metaRefresh) {
  316. let content = metaRefresh.getAttribute('content');
  317. let urlMatch = content.match(/url=(.+)$/i);
  318. if (urlMatch) {
  319. getFinalLink(urlMatch[1], finalLinksDiv);
  320. setTimeout(() => processLinks(index + 1), 100);
  321. return;
  322. }
  323. }
  324. console.error('No redirect found for:', linkUrl);
  325. setTimeout(() => processLinks(index + 1), 100);
  326. },
  327. onerror: function() {
  328. console.error('Error fetching:', linkUrl);
  329. setTimeout(() => processLinks(index + 1), 100);
  330. }
  331. });
  332. }
  333. processLinks();
  334. }
  335. // Display final link
  336. function getFinalLink(encLink, finalLinksDiv) {
  337. GM.xmlHttpRequest({
  338. method: 'GET',
  339. url: encLink,
  340. headers: {
  341. 'Content-Type': 'application/x-www-form-urlencoded',
  342. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
  343. },
  344. timeout: 5000,
  345. onload: function(response) {
  346. let finalUrl = response.finalUrl || encLink;
  347. // Rimuovi la parte "login?redirect=" se presente
  348. finalUrl = finalUrl.replace(/login\?redirect=/, '');
  349. console.log('Decrypted locally:', finalUrl);
  350. let linkElement = document.createElement('a');
  351. linkElement.href = finalUrl;
  352. linkElement.textContent = finalUrl;
  353. linkElement.style.color = isDarkTheme() ? '#cba6f7' : '#4f46e5';
  354. linkElement.addEventListener('click', function(e) {
  355. e.preventDefault();
  356. window.open(finalUrl, '_blank');
  357. });
  358. linkElement.addEventListener('contextmenu', function(e) {
  359. e.preventDefault();
  360. navigator.clipboard.writeText(finalUrl).then(() => {
  361. linkElement.textContent = '✓ Copied: ' + finalUrl;
  362. setTimeout(() => {
  363. linkElement.textContent = finalUrl;
  364. }, 2000);
  365. });
  366. });
  367. finalLinksDiv.appendChild(linkElement);
  368. finalLinksDiv.appendChild(document.createElement('br'));
  369. },
  370. onerror: function() {
  371. console.error('Error resolving link:', encLink);
  372. let errorElement = document.createElement('span');
  373. errorElement.textContent = `${encLink} (Failed to resolve)`;
  374. errorElement.className = 'fc-error';
  375. finalLinksDiv.appendChild(errorElement);
  376. finalLinksDiv.appendChild(document.createElement('br'));
  377. }
  378. });
  379. }
  380. // Display links
  381. function displayLinks(links, container) {
  382. const finalLinksDiv = document.createElement('div');
  383. finalLinksDiv.style.backgroundColor = isDarkTheme ? '#1e1e2e' : '#ffffff';
  384. finalLinksDiv.style.color = isDarkTheme ? '#cdd6f4' : '#333333';
  385. finalLinksDiv.style.padding = '1em';
  386. finalLinksDiv.innerHTML = '<span>Decrypted links:</span><br><br>';
  387. links.forEach(link => {
  388. // Rimuovi la parte "login?redirect=" se presente
  389. let cleanedLink = link.replace(/login\?redirect=/, '');
  390. let linkElement = document.createElement('a');
  391. linkElement.href = cleanedLink;
  392. linkElement.textContent = cleanedLink;
  393. linkElement.style.color = isDarkTheme ? '#cba6f7' : '#4f46e5';
  394. linkElement.addEventListener('click', function(e) {
  395. e.preventDefault();
  396. window.open(cleanedLink, '_blank');
  397. });
  398. linkElement.addEventListener('contextmenu', function(e) {
  399. e.preventDefault();
  400. navigator.clipboard.writeText(cleanedLink).then(() => {
  401. linkElement.textContent = '✓ Copied: ' + cleanedLink;
  402. setTimeout(() => {
  403. linkElement.textContent = cleanedLink;
  404. }, 2000);
  405. });
  406. });
  407. finalLinksDiv.appendChild(linkElement);
  408. finalLinksDiv.appendChild(document.createElement('br'));
  409. });
  410. container.replaceChild(finalLinksDiv, container.querySelector('.fc-loading'));
  411. }
  412. // Show error message
  413. function showError(message, container) {
  414. const errorDiv = document.createElement('div');
  415. errorDiv.className = 'fc-error';
  416. errorDiv.textContent = message;
  417. container.replaceChild(errorDiv, container.querySelector('.fc-loading'));
  418. }
  419. // Helper to detect dark theme
  420. function isDarkTheme() {
  421. return document.head.querySelector('meta[name="theme-color"]') !== null ||
  422. document.body.classList.contains('dark') ||
  423. window.getComputedStyle(document.body).backgroundColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)/)?.[1] < 100;
  424. }