import System; import System.Windows.Forms; import Fiddler; // INTRODUCTION // // Well, hello there! // // Don't be scared! :-) // // This is the FiddlerScript Rules file, which creates some of the menu commands and // other features of Progress Telerik Fiddler Classic. You can edit this file to modify or add new commands. // // The original version of this file is named SampleRules.js and it is in the // \Program Files\Fiddler\ folder. When Fiddler Classic first runs, it creates a copy named // CustomRules.js inside your \Documents\Fiddler2\Scripts folder. If you make a // mistake in editing this file, simply delete the CustomRules.js file and restart // Fiddler Classic. A fresh copy of the default rules will be created from the original // sample rules file. // The best way to edit this file is to install the FiddlerScript Editor, part of // the free SyntaxEditing addons. Get it here: http://fiddler2.com/r/?SYNTAXVIEWINSTALL // GLOBALIZATION NOTE: Save this file using UTF-8 Encoding. // JScript.NET Reference // http://fiddler2.com/r/?msdnjsnet // // FiddlerScript Reference // http://fiddler2.com/r/?fiddlerscriptcookbook class Handlers { // ***************** // // This is the Handlers class. Pretty much everything you ever add to FiddlerScript // belongs right inside here, or inside one of the already-existing functions below. // // ***************** // The following snippet demonstrates a custom-bound column for the Web Sessions list. // See http://fiddler2.com/r/?fiddlercolumns for more info /* public static BindUIColumn("Method", 60) function FillMethodColumn(oS: Session): String { return oS.RequestMethod; } */ // The following snippet demonstrates how to create a custom tab that shows simple text /* public BindUITab("Flags") static function FlagsReport(arrSess: Session[]):String { var oSB: System.Text.StringBuilder = new System.Text.StringBuilder(); for (var i:int = 0; i-1)) { // Case sensitive oSession.url = oSession.url.Replace(gs_ReplaceToken, gs_ReplaceTokenWith); } if ((null != gs_OverridenHost) && (oSession.host.toLowerCase() == gs_OverridenHost)) { oSession["x-overridehost"] = gs_OverrideHostWith; } if ((null!=bpRequestURI) && oSession.uriContains(bpRequestURI)) { oSession["x-breakrequest"]="uri"; } // Fixes stackpath interfering with game translation file loading by using a mirror: if (m_UseTranslationMirror && oSession.uriContains('/gettranslationxml.phtml')) { if (oSession.HTTPMethodIs("CONNECT") == false) { oSession.oRequest.headers['X-NeoFixes'] = 'get-translation'; oSession.oRequest.headers.Remove('Cookie'); oSession.host = "www.neofixes.com"; } } // Fix long delay/lag/errors from the ShockWave/Flash phone-home if (!m_swNoReply && oSession.uriContains("pinger.macromedia.com")) { oSession.utilCreateResponseAndBypassServer(); oSession.responseCode = '204'; oSession["ui-backcolor"] = "Lavender"; } if (oSession.host.Contains('swf.neopets.com') && oSession.HTTPMethodIs("CONNECT") == false) { oSession.host = "images.neopets.com"; } // Don't be tracked by Visual Studio. Also speeds the site up a lot. if (m_skipVSTracking && oSession.uriContains('dc.services.visualstudio.com/v2/track')) { oSession.utilCreateResponseAndBypassServer(); oSession.responseCode = '200'; oSession.utilSetResponseBody('{"itemsReceived":1,"itemsAccepted":1,"errors":[],"appId":"048e78a5-9e6f-49c1-b0c3-a4e8c7e7e4be"}'); oSession["ui-backcolor"] = "Pink"; } if (!m_swDisabled) { // More shockwave fixes if (oSession.uriContains('games/preloaders/ml')) { oSession["ui-backcolor"] = "Pink"; oSession["request-trickle-delay"] = '1'; oSession["response-trickle-delay"] = '1'; } if (oSession.uriContains('.dcr') && !oSession.uriContains('g313_v10_23393.dcr')) { if (oSession.oRequest.headers.Exists('If-Modified-Since')) oSession.oRequest.headers.Remove('If-Modified-Since'); if (oSession.oRequest.headers.Exists('If-None-Match')) oSession.oRequest.headers.Remove('If-None-Match'); if (oSession.uriContains('g356_v18_30330.dcr' || swGame == 'dice_escape')) { // Dice escape swGame = 'dice_escape'; oSession["request-trickle-delay"] = '2'; oSession["response-trickle-delay"] = '2'; } else if (oSession.uriContains('g430_v26_34232.dcr')) { swGame = 'castle_battle'; // Castle battles shows it's loaded before it's ready, so speed it up. oSession["request-trickle-delay"] = '1'; oSession["response-trickle-delay"] = '1'; } else if (oSession.uriContains('g386_v8')) { swGame = 'slorgs'; // Attack of the slorgs is particularly finnicky oSession["request-trickle-delay"] = '2'; oSession["response-trickle-delay"] = '2'; } else if (oSession.uriContains('g349_')) { swGame = 'pirate_caves'; oSession["request-trickle-delay"] = '10'; oSession["response-trickle-delay"] = '20'; } else if (oSession.uriContains('g473_')) { swGame = 'ice_caves'; oSession["request-trickle-delay"] = '10'; oSession["response-trickle-delay"] = '20'; } else if (oSession.uriContains('g480_')) { swGame = 'trotrods'; oSession["request-trickle-delay"] = '10'; oSession["response-trickle-delay"] = '20'; } else { swGame = ''; oSession["request-trickle-delay"] = '10'; oSession["response-trickle-delay"] = '20'; } oSession["ui-backcolor"] = "Lavender"; } if (oSession.uriContains('games/DGS_BIOS.cct')) { if (swGame != '') { oSession["request-trickle-delay"] = '1'; oSession["response-trickle-delay"] = '1'; } } if (oSession.uriContains('gaming_system/dgs_include_v2.swf')) { if (swGame == 'dice_escape') { oSession["request-trickle-delay"] = '1'; oSession["response-trickle-delay"] = '2'; } else { // This is also for attack of the slorgs. oSession["request-trickle-delay"] = '40'; oSession["response-trickle-delay"] = '100'; } oSession["ui-backcolor"] = "Lavender"; } } // End batch of shockwave fixes if (oSession.host.Contains("neopets.com") && oSession.HTTPMethodIs("CONNECT") == false) { oSession["x-OverrideSslProtocols"] = " ssl3;tls1.0;tls1.1;tls1.2"; if (m_BetterInventory) { if (oSession.uriContains("ajax/inventory.php")) { oSession.PathAndQuery = oSession.PathAndQuery.replace('Stack=1', 'Stack=0'); } } if ((oSession.PathAndQuery.Contains('/userlookup.phtml?user=') || oSession.PathAndQuery.Contains('/userlookup.phtml?randomfriend=')) && !oSession.PathAndQuery.Contains('place=')) { oSession.PathAndQuery = oSession.PathAndQuery + '&place=99999'; } if (oSession.PathAndQuery.Contains('/randomfriend.phtml?randomfriend=') || oSession.PathAndQuery.Contains('/randomfriend.phtml?user=')) { const randomfriendRegex = /randomfriend\.phtml\?(randomfriend|user)=([^&]*)$/; oSession.PathAndQuery = oSession.PathAndQuery.replace(randomfriendRegex, 'userlookup.phtml?place=99999&user=$2'); } if (m_flashMall && oSession.PathAndQuery.Contains("/mall/pet_preview_h5.phtml")) { oSession.PathAndQuery = oSession.PathAndQuery.Replace('pet_preview_h5.phtml', 'pet_preview.phtml'); } if (m_UseOldSkarl && oSession.PathAndQuery == "/medieval/grumpyking.phtml") { oSession.PathAndQuery = "/medieval/grumpyking.phtml/"; } // Fix stackpath blocking Korbat's Lab XML/CMS Data if (oSession.uriContains('/process_cms.phtml')) { // Mark for easy find for future games oSession["ui-backcolor"] = "#FFAAAA"; const klabXML = 'neopets/process_cms_klab.xml'; if (System.IO.File.Exists(klabXML)) { const reqBody = oSession.GetRequestBodyAsString(); if (decodeURI(oSession.fullUrl).Contains('item_id=64') || decodeURI(reqBody).Contains('item_id=64')) { oSession.utilCreateResponseAndBypassServer(); oSession.oResponse.headers['Content-type'] = 'text/html'; oSession.ResponseBody = System.IO.File.ReadAllBytes(klabXML); oSession["ui-backcolor"] = "#7777ff"; } } } if (oSession.uriContains('/buy_item.phtml')) { // The code below will ensure you never get expired shop items, however the ref_ck could still change causing 'directed here from the wrong place' // var expiredTs = Math.round((new Date()).getTime() / 1000) - 180; var expiredTs = 0; // Get the current timestamp from the buy_item URL (to avoid fake links) var getTsRegex = /\/buy_item.phtml.*&xhs=([0-9n-s]+).*/; if (!m_ShopTransactionsNeverExpire) { expiredTs = oSession.PathAndQuery.replace(getTsRegex, '$1'); expiredTs = expiredTs.replace(/n/g, 'a').replace(/o/g, 'b').replace(/p/g, 'c').replace(/q/g, 'd').replace(/r/g, 'e').replace(/s/g, 'f'); // Subtract 2 minutes to avoid servers being off by 90 seconds. expiredTs = parseInt(expiredTs, 16) - 120; } else { expiredTs = Math.round((new Date()).getTime() / 1000) - 120; } // Turn it back into the right format expiredTs = expiredTs.toString(16); expiredTs = expiredTs.replace(/a/g, 'n').replace(/b/g, 'o').replace(/c/g, 'p').replace(/d/g, 'q').replace(/e/g, 'r').replace(/f/g, 's'); // Rewrite the query: oSession.PathAndQuery = oSession.PathAndQuery.replace(/xhs=[0-9n-s]+/, 'xhs=' + expiredTs); } // Shortcut to resubmit score if (oSession.fullUrl.ToLower().Contains('neopets.com/fixscore')) { if (saved_score) { var resendScoreHdrs = "HTTP/1.0 302 FOUND\r\nContent-type: text/html; charset=iso-8859-1\r\nLocation: " + saved_score + "\r\n\r\n"; oSession.utilCreateResponseAndBypassServer(); oSession.ResponseHeaders.AssignFromString(resendScoreHdrs); } else { var resendScoreMsg = "Your last score wasn't blocked by Stackpath, so we cannot re-submit it. It is gone, sorry. Reload the game before you try again!"; if (saved_score_result) { resendScoreMsg += "

(Technical details) Your last score submission's result was:
" + saved_score_result + "
"; } oSession.utilCreateResponseAndBypassServer(); oSession.utilSetResponseBody(resendScoreMsg); } } // Fix 3dvia games not sending score if (oSession.uriContains('process_flash_score') && oSession.oRequest.headers.ExistsAndContains('User-Agent', 'Virtools Webserver Manager')) { //Fix cookies not sent to server because of VirtualBrowser to appease stackpath if (saved_cookies != null) { oSession.oRequest.headers["Cookie"] = saved_cookies; } } else if (oSession.HostnameIs("dev.neopets.com")) { oSession.host = "www.neopets.com"; //try to fix cookies not sent to dev to bypass stackpath if (saved_cookies != null) { oSession.oRequest.headers["Cookie"] = saved_cookies; } } else if (oSession.HostnameIs("www.neopets.com")) { saved_cookies = oSession.oRequest.headers["Cookie"]; } // Fix potato counter because it doesn't use images. for some reason if (oSession.uriContains("games/g226/config.xml")) { oSession.host = "images.neopets.com"; } //fixes games pointing to dev server that have chinese lang when offline if (oSession.uriContains("gettranslationxml.phtml") && oSession.HTTPMethodIs("POST")) { oSession.utilSetRequestBody(oSession.GetRequestBodyAsString().Replace("lang=ch", "lang=en")); } // Load any custom overrides: if ( !oSession.uriContains(".png") && !oSession.uriContains(".jpg") || !oSession.uriContains(".gif") ) { var path = "neopets" + oSession.PathAndQuery //if (oSession.oRequest.headers.Exists("x-flash-version")) { if (path.Contains('?')) { path = path.Split("?")[0]; } // Note: 3dvia installer/player javascript is mirrored in case it ever goes down if (System.IO.File.Exists(path)) { oSession['ui-backcolor'] = '#bbbbee'; oSession.utilCreateResponseAndBypassServer(); oSession.ResponseBody = System.IO.File.ReadAllBytes(path); if (path.Contains(".xml")) { oSession.oResponse.headers["Content-Type"] = "text/xml"; } if (path.Contains(".html")) { oSession.oResponse.headers["Content-Type"] = "text/html"; } } } } if ((null!=bpMethod) && (oSession.HTTPMethodIs(bpMethod))) { oSession["x-breakrequest"]="method"; } if ((null!=uiBoldURI) && oSession.uriContains(uiBoldURI)) { oSession["ui-bold"]="QuickExec"; } if (m_SimulateModem) { // Delay sends by 300ms per KB uploaded. oSession["request-trickle-delay"] = "150"; // Delay receives by 150ms per KB downloaded. oSession["response-trickle-delay"] = "50"; } if (m_DisableCaching) { oSession.oRequest.headers.Remove("If-None-Match"); oSession.oRequest.headers.Remove("If-Modified-Since"); oSession.oRequest["Pragma"] = "no-cache"; } // User-Agent Overrides if (null != sUA) { oSession.oRequest["User-Agent"] = sUA; } if (m_AlwaysFresh && (oSession.oRequest.headers.Exists("If-Modified-Since") || oSession.oRequest.headers.Exists("If-None-Match"))) { oSession.utilCreateResponseAndBypassServer(); oSession.responseCode = 304; oSession["ui-backcolor"] = "Lavender"; } } // This function is called immediately after a set of request headers has // been read from the client. This is typically too early to do much useful // work, since the body hasn't yet been read, but sometimes it may be useful. // // For instance, see // http://blogs.msdn.com/b/fiddler/archive/2011/11/05/http-expect-continue-delays-transmitting-post-bodies-by-up-to-350-milliseconds.aspx // for one useful thing you can do with this handler. // // Note: oSession.requestBodyBytes is not available within this function! static var saved_cookies; static function OnPeekAtRequestHeaders(oSession: Session) { if (oSession.host.Contains("neopets.com") && oSession.HTTPMethodIs("CONNECT") == false && oSession.HostnameIs("swf.neopets.com") == false) { oSession.oRequest.headers.UriScheme = "https"; //fixes Clara on Ice, Let it Slide, Extreme Potato Counter if (oSession.uriContains(".swf") || oSession.uriContains("/config.xml") || oSession.uriContains("/shellconfig.xml")) { oSession.host = "images.neopets.com"; oSession.url = oSession.url.Replace("/games/https://images.neopets.com/games/", "/games/").Replace("games/games", "games").Replace('/games///images.neopets.com/games/', '/games/'); } //fixes kacheek seek if (oSession.uriContains("process_hideandseek.phtml")) { oSession.oRequest.headers["Referer"] = "http://www.neopets.com/games/hidenseek"; } } } // // If a given session has response streaming enabled, then the OnBeforeResponse function // is actually called AFTER the response was returned to the client. // // In contrast, this OnPeekAtResponseHeaders function is called before the response headers are // sent to the client (and before the body is read from the server). Hence this is an opportune time // to disable streaming (oSession.bBufferResponse = true) if there is something in the response headers // which suggests that tampering with the response body is necessary. // // Note: oSession.responseBodyBytes is not available within this function! // static function OnPeekAtResponseHeaders(oSession: Session) { //FiddlerApplication.Log.LogFormat("Session {0}: Response header peek shows status is {1}", oSession.id, oSession.responseCode); if (m_DisableCaching) { oSession.oResponse.headers.Remove("Expires"); oSession.oResponse["Cache-Control"] = "no-cache"; } if ((bpStatus>0) && (oSession.responseCode == bpStatus)) { oSession["x-breakresponse"]="status"; oSession.bBufferResponse = true; } if ((null!=bpResponseURI) && oSession.uriContains(bpResponseURI)) { oSession["x-breakresponse"]="uri"; oSession.bBufferResponse = true; } // Fix access control origin if (oSession.oResponse.headers['Access-Control-Allow-Origin'].Contains("neopets.com")) { oSession.oResponse.headers['Access-Control-Allow-Origin'] = "*"; } } static function OnBeforeResponse(oSession: Session) { if (oSession.uriContains('dgs_get_game_data.phtml')) { oSession.oResponse.headers.Remove('x-sp-metadata'); oSession.oResponse.headers.Remove('X-HW'); } if (oSession.host.Contains('neofixes.com')) { if (oSession.responseCode == 404 && oSession.oRequest.headers.ExistsAndContains('X-NeoFixes', 'get-translation')) { FiddlerObject.alert("This translation doesn't exist in our database!\n\Disable:\n\tRules->Advanced->Use Translation Mirror\nand reload the game.\n\nAnd please consider enabling:\n\tRules->Advanced->Upload Translations\nto help others in your situation!"); } if (oSession.oResponse.headers.Exists('X-NF-Message')) { FiddlerObject.alert(oSession.oResponse.headers['X-NF-Message']); } } if (oSession.host.Contains("neopets.com")) { if (oSession.responseCode >= 301 && oSession.responseCode <= 302) { oSession.ResponseHeaders['Location'] = oSession.ResponseHeaders['Location'].Replace('http:', 'https:'); } // Fix Ability To Reset Petpage: if (oSession.uriContains("editpage.phtml?pet_name")) { const epParams = oSession.PathAndQuery.split('?')[1].split('&'); var petName = ''; for (var i = 0; i < epParams.length; i++) { const pair = epParams[i].split('='); if (pair[0] === 'pet_name') petName = pair[1]; } if (petName !== '') { oSession.utilDecodeResponse(); const fixCode = "
"; oSession.utilReplaceInResponse("", '
'); } } else { // Check for item gifts: var formData = oSession.GetRequestBodyAsString(); if (formData.length) { const params2 = formData.Split('&'); var removeItems = false; var giftBoxId = 0; var giftId = 0; for (var i = 0; i < params2.length; i++) { const p2 = params2[i].Split('='); if (p2[0] === 'sentPass') { removeItems = true; } else if (p2[0] === 'cash_obj_id') { giftBoxId = p2[1]; } else if (p2[0].Contains('giftItem')) { giftId = p2[1]; } } if (removeItems) { oSession.utilDecodeResponse(); const newContent = ''; const match = 'Congratulations!'; oSession.utilReplaceOnceInResponse(match, newContent + match, true); } } } } // Remove most NC + NP items on open: if (oSession.uriContains('js/inventory.js')) { oSession.utilDecodeResponse(); oSession.utilReplaceInResponse('// Display Results', '// Display Results\n\t\t\tif ((typeof cashData === "object" && cashData.action !== "gashapon") || (typeof postData === "object" && postData.action !== "auction") || typeof auctionData === "object" || (typeof gashaponData === "object" && gashaponData.confirm) || (typeof fortuneData === "object" && fortuneData.action === "confirm")) removeItem(currentItemId);'); oSession.utilReplaceInResponse('function invView2(itemId) {', 'let currentItemId = null;\n\nfunction removeItem(itemId) {\n\t$(`div.grid-item > div[id="${itemId}"]`).parent().remove();\n}\nfunction invView2(itemId) {\ncurrentItemId = itemId;'); var body = oSession.GetResponseBodyAsString(); var cursor = body.indexOf('function useInvItem'); var partial = [body.substr(cursor)]; partial.push(partial[0].substr(partial[0].indexOf('useobject.phtml'))); const replace = partial[1].replace('success: function(response) {', 'success: function(response) {\n\t\t\t\tif ((typeof postData === "object" && postData.action !== "auction") || typeof auctionData === "object") removeItem(currentItemId);'); oSession.utilReplaceInResponse(partial[1], replace); } // Prevent the forced-reload after using an item: if (oSession.uriContains('/inventory.phtml')) { oSession.utilReplaceInResponse( '
') || txFile.Contains('Neopets - Loading site...')) { // Check if this is stack path oSession["ui-backcolor"] = "red"; // FiddlerObject.alert('Stackpath blocked the translation!'); } else { // Otherwise continue with the file uplaod var boundary = "NeoFixes.com-------------aEaEaE"; var content = '--' + boundary + '\r\nContent-Disposition: form-data; name="txData"\r\n\r\n' + txData; content += '\r\n--' + boundary + '\r\nContent-Disposition: form-data; name="txURI"\r\n\r\n' + oSession.fullUrl; content += '\r\n--' + boundary + '\r\nContent-Disposition: form-data; name="txFile"; filename="translation.xml"\r\nContent-Type: text/xml\r\n\r\n' + txFile; content += '\r\n--' + boundary + '--'; // Build headers now that we have the size: headers.push('User-Agent: NeoFixer.com Autouploader'); headers.push("Content-type: multipart/form-data; boundary=" + boundary); headers.push("Content-length: " + content.length); var sRequest = uri + "\r\n" + headers.join("\r\n") + '\r\n\r\n'; try { var newReq = FiddlerObject.utilIssueRequest(sRequest + content); } catch (e) { FiddlerObject.alert(e); } } } // Store score to re-send if (oSession.uriContains('process_shockwave_score') || oSession.uriContains('process_flash_score')) { var scoreResult = oSession.GetResponseBodyAsString(); if (!scoreResult.Contains('success=')) { // Stackpath is the only reason you shouldn't see this saved_score = oSession.fullUrl; saved_score_result = null; } else { saved_score = null; saved_score_result = scoreResult; } } // Populate old King Skarl Results randomly since they aren't saved if (oSession.uriContains('/medieval/grumpyking.phtml/')) { var skarlChoices = oSession.GetResponseBodyAsString(); // Choose the avatar question: skarlChoices = skarlChoices.Replace('value="What"', 'value="What" SELECTED'); skarlChoices = skarlChoices.Replace('value="do"', 'value="do" SELECTED'); skarlChoices = skarlChoices.Replace('value="you do if"', 'value="you do if" SELECTED'); skarlChoices = skarlChoices.replace(/part 4<\/option>(\s+)