From 04c918d092d8da1f98ef39a8614667ec2249c387 Mon Sep 17 00:00:00 2001 From: Xmader Date: Thu, 5 Nov 2020 16:47:50 -0500 Subject: [PATCH] refactor: anti-detection --- src/anti-detection.ts | 25 +++++++++++++++++++++++-- src/file.ts | 30 +++++++++++------------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/anti-detection.ts b/src/anti-detection.ts index 65ed729..2e3ee1f 100644 --- a/src/anti-detection.ts +++ b/src/anti-detection.ts @@ -7,7 +7,9 @@ export const makeNative = (() => { const l: Set = new Set() - const _toString = Function.prototype['toString'] + const target = Function.prototype + const method = 'toString' + const _toString = target[method] const toString = function () { if (l.has(this)) { // "function () {\n [native code]\n}" @@ -15,7 +17,7 @@ export const makeNative = (() => { } return _toString.call(this) as string } - Function.prototype.toString = toString + target[method] = toString // make `Function.prototype.toString` itself "native" l.add(toString) @@ -24,3 +26,22 @@ export const makeNative = (() => { l.add(fn) } })() + +export const hookNative = ( + target: T, + method: M, + hook: (originalFn: T[M], detach: () => void) => T[M], +): void => { + // reserve for future hook update + const _fn = target[method] + const detach = () => { + target[method] = _fn // detach + } + + // This script can run before anything on the page, + // so setting this function to be non-configurable and non-writable is no use. + const hookedFn = hook(_fn, detach) + target[method] = hookedFn + + makeNative(hookedFn as any) +} diff --git a/src/file.ts b/src/file.ts index 0d41ca1..c4a8ceb 100644 --- a/src/file.ts +++ b/src/file.ts @@ -2,7 +2,7 @@ import scoreinfo from './scoreinfo' import { webpackHook } from './webpack-hook' -import { makeNative } from './anti-detection' +import { hookNative } from './anti-detection' const FILE_URL_MODULE_ID = 'iNJA' const MAGIC_REG = /^\d+(img|mp3|midi)\d(.+)$/ @@ -18,25 +18,17 @@ const getApiUrl = (id: number, type: FileType, index: number): string => { * I know this is super hacky. */ let magic: Promise | string = new Promise((resolve) => { - // reserve for future hook update - const target = String.prototype - const method = 'charCodeAt' - const _fn = target[method] - - // This script can run before anything on the page, - // so setting this function to be non-configurable and non-writable is no use. - const hookFn = function (i: number) { - const m = this.match(MAGIC_REG) - if (m) { - resolve(m[2]) - magic = m[2] - target[method] = _fn // detach + hookNative(String.prototype, 'charCodeAt', (_fn, detach) => { + return function (i: number) { + const m = this.match(MAGIC_REG) + if (m) { + resolve(m[2]) + magic = m[2] + detach() + } + return _fn.call(this, i) as number } - return _fn.call(this, i) as number - } - target[method] = hookFn - - makeNative(hookFn) + }) }) export const getFileUrl = async (type: FileType, index = 0): Promise => {