Reverse Engineering

When dealing with Webpack JavaScript source code, I think I need to follow these steps:

  • Run js-beautify for beautifying the code.
  • If there is code snippet that has "use strict", then it should be a module. Try to write a script to extract the modules. Additionally, write a script for asking LLM about which module is custom code (non-library code).
  • Comment out the code snippet that is library-related or Webpack-related.

For example, when dissecting the JavaScript source code of MyOPSWAT, there are two valuable sections that contain modules. The first one is the __webpack_modules__ variable:

Inside this, the modules are clearly standout with the numeric keys.

The second one is the last self-invoking function:

Inside this function, there are custom code mixed with library code.

When Tokens and Cookies Are Set

There are some arrays like this in the last self-invoking function:

const l = [{
	path: "/",
	component: (0, Ze.jsx)(Qc, {}),
	index: true
  }, {
	path: se,
	component: a ? (0, Ze.jsx)(wu, {}) : (0, Ze.jsx)(Qc, {})
  }, {
	path: le,
	component: (0, Ze.jsx)(Bg, {})
  }, {
	path: ce,
	component: (0, Ze.jsx)(wv, {})
  }, {
	path: ue,
	component: (0, Ze.jsx)(We, {})
  }, {
	path: de,
	component: (0, Ze.jsx)(Ge, {})
  }, {
	path: pe,
	component: (0, Ze.jsx)(bv, {})
  }, {
	path: fe,
	component: (0, Ze.jsx)(ade, {})
  }, {
	path: "/changePassword"
  }, {
	path: he,
	component: (0, Ze.jsx)(Ue, {})
  }, {
	path: "/auth-successfully",
	component: (0, Ze.jsx)(Sv, {})
}];

It looks like an array for routing the paths to associated components.

When searching for URLSearchParams, I found the following function:

function Sv() {
  const e = (0, z.s0)();
  const t = (0, z.TH)();
  const n = new URLSearchParams(t.search);
  (0, i.useEffect)(() => {
	(0, Re.f3)({
	  accessToken: n.get("token"),
	  refreshToken: n.get("refresh"),
	  csrfToken: n.get("csrf"),
	  ocmToken: n.get("ocm")
	}, "localstorage", "VkhWaGJqRXlNelExTmpjNA==").then(() => {
	  e(ae);
	});
  }, [n]);
  return (0, Ze.jsx)(z.j3, {});
}

As we can see, this function is used for the "/auth-successfully" route.

The Re variable is a module:

var Re = __webpack_require__(26861);

Because we did extract the modules so we can search for the 26861.js file. The t3 function return a function that will eventually return another function:

t.f3 = function (e, t, n) {
	return ze(undefined, undefined, undefined, function () {
	  var r;
	  var o;
	  var i;
	  var a;
	  var s;
	  return Be(this, function (l) {
		switch (l.label) {
		  case 0:
			if (e) {
			  return [4, Xa(e == null ? undefined : e.accessToken) * 1000];
			} else {
			  return [2, false];
			}
		  case 1:
			r = l.sent();
			return [4, new Date().getTime()];
		  case 2:
			o = l.sent();
			i = o + r;
			return [4, Fe((e == null ? undefined : e.ocmToken) || "", n || "")];
// ...

As we can see, the final returned function do something with the tokens.

There are some cases that use the constants such as TOKEN_KEY, OCM_TOKEN_KEY, etc:

  case 5:
	return [4, ui(Ii.TOKEN_KEY, e == null ? undefined : e.accessToken)];
  case 6:
	l.sent();
	l.label = 7;
  case 7:
	return [4, ui(Ii.OCM_TOKEN_KEY, a)];
  case 8:
	l.sent();
	return [4, ui(Ii.REFRESH_TOKEN_KEY, e == null ? undefined : e.refreshToken)];
  case 9:
	l.sent();
	return [4, ui(Ii.CSRF_TOKEN_KEY, e == null ? undefined : e.csrfToken)];
  case 10:
	l.sent();
	return [4, ui(Ii.TOKEN_EXPIRED_TIME, `${r}`)];
  case 11:
	l.sent();
	return [4, li(Ii.IDAAS_SESSION_KEY, Gn(e == null ? undefined : e.ssoMeta, Ii.IDAAS_SESSION_KEY), s)];
  case 12:
	l.sent();
	return [4, li(Ii.IDAAS_REFRESH_KEY, Gn(e == null ? undefined : e.ssoMeta, Ii.IDAAS_REFRESH_KEY), s)];
  case 13:
	l.sent();
	return [4, li(Ii.IDAAS_PAYLOAD_KEY, Gn(e == null ? undefined : e.ssoMeta, Ii.IDAAS_PAYLOAD_KEY), s)];
  case 14:
	l.sent();
	return [4, li(Ii.IDAAS_LOGIN_KEY, Gn(e == null ? undefined : e.ssoMeta, Ii.IDAAS_LOGIN_KEY), Ne(Ne({}, s), {
	  sameSite: "lax"

The values of those constants:

var Ii = {
	COOKIE: "cookie",
	OCM_TOKEN_KEY: "ocmJwtToken",
	TOKEN_KEY: "__opswat-my-tk",
	REFRESH_TOKEN_KEY: "__opswat-my-rt",
	CSRF_TOKEN_KEY: "__opswat-my-ct",
	IDAAS_LOGIN_KEY: "__opswat-login",
	IDAAS_PAYLOAD_KEY: "__opswat-payload-login",
	IDAAS_REFRESH_KEY: "__opswat-refresh-login",
	IDAAS_SESSION_KEY: "__opswat-session-login",
	FIRST_NAME_DEFAULT: "First name - need input",
	LAST_NAME_DEFAULT: "Last name - need input",
	TOKEN_EXPIRED_TIME: "__opswat-my-tet",
	SAML_SESSION: "saml_session",
	BOTPRESS_WEBCHAT: "botpress-webchat"
};

Some cases invoke the ui function, which sets a local storage item:

function ui(e, t) {
	if (e) {
	  return window.localStorage.setItem(e, t);
	} else {
	  return null;
	}
}

Meanwhile, the li function will invoke the set method of the si object:

var si = xo.withConverter({
	read: function (e, t) {
	  return e;
	},
	write: function (e, t) {
	  return e;
	}
});
function li(e, t, n) {
	if (e) {
	  return si.set(e, t, n);
	} else {
	  return null;
	}
}

Where xo is a function defined like this:

var xo = function e(t, n) {
	function r(e, r, o) {
	  if (typeof document != "undefined") {
		if (typeof (o = yo({}, n, o)).expires == "number") {
		  o.expires = new Date(Date.now() + o.expires * 86400000);
		}
		o.expires &&= o.expires.toUTCString();
		e = encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/[()]/g, escape);
		var i = "";
		for (var a in o) {
		  if (o[a]) {
			i += "; " + a;
			if (o[a] !== true) {
			  i += "=" + o[a].split(";")[0];
			}
		  }
		}
		return document.cookie = e + "=" + t.write(r, e) + i;
	  }
	}
	return Object.create({
	  set: r,

As we can see, the set function is the r function and the r function will used for setting the cookies. So, the li function will set the cookies.

Hidden REST API Endpoints

Found some REST API endpoints:

const H = "personal-information";
const U = "preferences";
const W = "/my-information";
const q = `${W}/security`;
const Y = `${W}/${U}`;
const G = `${W}/${H}`;
const X = "/license-management";
const K = `${X}/my-organization`;
const Q = `${X}/customer-organizations`;
`/iframe-pages/licensed-products/:tabPath`;
const J = "/my-organization";
const $ = `${J}/general-information`;
const ee = `${J}/groups`;
const te = `${J}/users`;
const ne = `${J}/application-roles`;
const re = `${J}/security`;
const oe = `${J}/event-history`;
const ie = `${J}/critical-alert-users`;
const ae = "/home";
const se = "/login";
const le = "/register";
const ce = "/reset-password";
const ue = "/change-password";
const de = "/confirm-email";
const pe = "/resend-email";
const fe = "/verify-otp";
const he = "/active";
const me = "/accepted-invite";
const ge = "/mfa";
const ve = "/prduct-downloads";
const ye = "/anti-malware-engine-status/windows";
const xe = "/anti-malware-engine-status/linux";
const be = "/anti-malware-engine-status/packages";
const we = "/no-permission";
const Ce = "/dialog";
const Se = "/payment";
const ke = "/nlv/payment";
const je = "/report-false-detection";
const Ee = `${je}/:tabPath`;
const Ae = `${je}/submit`;
const Te = `${je}/history`;
const Pe = "/support";
const Oe = `${Pe}/all-cases`;
const Me = `${Pe}/submit-case`;
const Ie = "/test-iframe";
const _e = {
	"/portal/products": ae,
	"/portal/oem": ae,
	"/user-management/roles": ne,
	"/user-management/users": te,
	"/user-profile/personal-information": G,
	"/user-profile/product-subscription": Y,
	"/inventory/metadefender-kiosk-l1001/instances": "/product-management/inventory/metadefender-kiosk/l-series/instances",
	"/inventory/metadefender-kiosk-l1001/groups": "/product-management/inventory/metadefender-kiosk/l-series/groups",
	"/home/opswat-neuralyzer": "/home/metadefender-ot-security",
	"/home/opswat-client": "/home/metadefender-endpoint",
	"/home/endpoint-clients": "/home/metadefender-endpoint-solution",
	"/home/metaaccess": "/home/metadefender-it-ot-access",
	"/home/metadefender-it-ot-access": "/home/metadefender-it-access",
	"/home/metaaccess-nac": "/home/nac",
	"/home/secure-ot-access": "/home/metadefender-ot-access-on-premise",
	"/home/nac": "/home/metadefender-nac",
	"/home/ot-drive-tool-kit": "/home/metadefender-drive-tool-kit",
	"/home/opswat-filescan-sandbox": "/home/metadefender-sandbox",
	"/home/opswat-endpoint-security-sdk": "/home/metadefender-endpoint-security-sdk",
	"/home/opswat-netwall": "/home/metadefender-netwall",
	"/home/netwall-tp": "/home/transfer-guard",
	"/home/netwall-tp-blue": "/home/transfer-guard-blue",
	"/home/netwall-tp-red": "/home/transfer-guard-red",
	"/home/vulnerability-definitions-for-central-management": "/home/vulnerability-definitions",
	"/home/opswat-otfuse": "/home/otfuse",
	"/home/metadefender-industrial-firewall-ips": "/home/otfuse",
	"/home/endpoint-standalone": "/home/endpoint-validation",
	"/my-licenses": K,
	"/support-service": Pe,
	"/support-services": Pe,
	"/support-service/submit-case": Me,
	"/support-service/all-cases": Oe,
	"/support-services/submit-case": Me,
	"/support-services/all-cases": Oe

Resources