MichaelXF / js-confuser

JS-Confuser is a JavaScript obfuscation tool to make your programs *impossible* to read.
https://js-confuser.com
MIT License
204 stars 32 forks source link

TypeError: this[o] is not a function #118

Open Probabilities opened 10 months ago

Probabilities commented 10 months ago

Describe the bug:

Unable to obfuscate my script since I get this error

`TypeError: this[o] is not a function`

The syntax of the code is correct. I can run it without the obfuscation.

Code:

const uuid = require('uuid').v4;
const { createHash, createCipheriv, createDecipheriv } = require('crypto');
const { request } = require('undici');
const { execSync } = require('child_process');
const os = require('os');

class keyauth {
    constructor (name, ownerid, secret, version, hash_to_check) {
        if(!(name && ownerid && secret && version && hash_to_check) ) {
            console.log('Make sure you fill out all fields')
            process.exit(1)
        }

        this.name = name

        this.ownerid = ownerid

        this.secret = secret

        this.version = version
        this.hash_to_check = hash_to_check
    };

    initialize = () => new Promise(async(resolve) => {
        this.enckey = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');
        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('init').toString('hex'),
            'ver': Encryption.encrypt(this.version, this.secret, init_iv),
            'hash': this.hash_to_check,
            'enckey': Encryption.encrypt(this.enckey, this.secret, init_iv),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.secret, init_iv)

        const parsed = JSON.parse(decrypted)

        if(!parsed.success || parsed.success == false){
            return resolve(false)
        }

        this.sessionid = parsed.sessionid
        this.initialized = true

        resolve(parsed)
    });

    upgrade = (username, license) => new Promise(async(resolve) => {
        this.check_initialize()

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('upgrade').toString('hex'),
            'username': Encryption.encrypt(username, this.enckey, init_iv),
            'key': Encryption.encrypt(license, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        return resolve(parsed)
    })

    register = (user, password, license, hwid = null) => new Promise(async(resolve) => {
        this.check_initialize()

        if(!hwid) {
            hwid = Misc.get_hwid()
            global.hwid = hwid
        }

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('register').toString('hex'),
            'username': Encryption.encrypt(user, this.enckey, init_iv),
            'pass': Encryption.encrypt(password, this.enckey, init_iv),
            'key': Encryption.encrypt(license, this.enckey, init_iv),
            'hwid': Encryption.encrypt(hwid, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        return resolve(parsed)
    })

    login = (username, password, hwid = null) => new Promise(async(resolve) => {
        this.check_initialize()

        if(!hwid) {
            hwid = Misc.get_hwid()
            global.hwid = hwid
        }

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('login').toString('hex'),
            'username': Encryption.encrypt(username, this.enckey, init_iv),
            'pass': Encryption.encrypt(password, this.enckey, init_iv),
            'hwid': Encryption.encrypt(hwid, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        return resolve(parsed)
    })

    webhook = (webid, body = '', param = '', type = 'application/json') => new Promise(async(resolve) => {
        this.check_initialize()

        if(type == 'application/json') body = JSON.stringify(body)

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('webhook').toString('hex'),
            'webid': Encryption.encrypt(webid, this.enckey, init_iv),
            'params': Encryption.encrypt(param, this.enckey, init_iv),
            'body': Encryption.encrypt(body, this.enckey, init_iv),
            'conttype': Encryption.encrypt(type, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        if(parsed.success && parsed.success == true) {
            return resolve(parsed)
        }

        resolve(parsed)
    })

    globalVar = (variable_name) => new Promise(async(resolve) => {
        this.check_initialize()

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('var').toString('hex'),
            'varid': Encryption.encrypt(variable_name, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        if(parsed.success && parsed.success == true) {
            return resolve(parsed?.message)
        }

        resolve(parsed.message)
    })

    getvar = (variable_name) => new Promise(async(resolve) => {
        this.check_initialize()

        const init_iv = createHash('sha256').update(uuid().substring(0, 8)).digest('hex');

        const post_data = {
            'type': Buffer.from('getvar').toString('hex'),
            'var': Encryption.encrypt(variable_name, this.enckey, init_iv),
            'sessionid': Buffer.from(this.sessionid).toString('hex'),
            'name': Buffer.from(this.name).toString('hex'),
            'ownerid': Buffer.from(this.ownerid).toString('hex'),
            'init_iv': init_iv
        }

        const response = await Misc.make_request(post_data)
        const decrypted = Encryption.decrypt(response, this.enckey, init_iv)

        const parsed = JSON.parse(decrypted)

        resolve(parsed)
    })

    check_initialize() {
        if(!this.initialized) {
            console.log('Not initialized')
            return process.exit(1)
        }

        return true
    };
}

class Encryption {
    static encrypt(message, enc_key, iv) {
        try{
            const _key = createHash('sha256').update(enc_key).digest('hex').substring(0, 32)

            const _iv = createHash('sha256').update(iv).digest('hex').substring(0, 16)

            return this.encrypt_string(message, _key, _iv)
        }catch(err){
            process.exit(1)
        }
    };

    static encrypt_string(plain_text, key, iv) {
        const cipher = createCipheriv('aes-256-cbc', key, iv)
        let crypted = cipher.update(plain_text, 'utf-8', 'hex')
        crypted += cipher.final('hex')
        return crypted
    };

    static decrypt(message, key, iv) {
        try{
            const _key = createHash('sha256').update(key).digest('hex').substring(0, 32)

            const _iv = createHash('sha256').update(iv).digest('hex').substring(0, 16)

            return this.decrypt_string(message, _key, _iv)
        }catch(err) {
            return JSON.stringify({ success: false, message: 'Failed to decrypt' })
        }
    };

    static decrypt_string(cipher_text, key, iv) {
        const decipher = createDecipheriv('aes-256-cbc', key, iv)
        let decrypted = decipher.update(cipher_text, 'hex', 'utf-8')
        decrypted += decipher.final('utf-8')
        return decrypted
    }
}

class Misc {
    static get_hwid() {
        if(os.platform() != 'win32') return false

        const cmd = execSync('wmic useraccount where name="%username%" get sid').toString('utf-8')

        const system_id = cmd.split('\n')[1].trim()
        return system_id
    };

    static make_request = (data) => new Promise(async(resolve) => {
        const { body } = await request('https://keyauth.win/api/1.0/', {
            method: 'POST', 
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams(data).toString()
        }).catch(() => {
            return resolve(false)
        })

        try{
            var response = await body.text()
        }catch{
            return resolve(false)
        }

        resolve(response)
    })
}

module.exports = keyauth

Expected behavior

no errors I guess lol

Actual behavior

doesnt obfuscate

Additional context

Failed to find the issue.

MichaelXF commented 10 months ago

Hi can share your config

Probabilities commented 10 months ago

Hi can share your config

Hi, I used the medium preset and that didn't work so I reverted to disabling all the options where also that did not work

MichaelXF commented 10 months ago

Oh this is because of the class properties being used. Unfortunately, escodegen, has not been updated in a while to support this.

I would rewrite your class fields to regular class methods if your code is small enough.

In the future, a better generator will be used by JS-Confuser that supports this

Probabilities commented 10 months ago

Oh this is because of the class properties being used. Unfortunately, escodegen, has not been updated in a while to support this.

I would rewrite your class fields to regular class methods if your code is small enough.

In the future, a better generator will be used by JS-Confuser that supports this

is this from the encryption class when i call this.decrypt_string etc?

Probabilities commented 10 months ago

can you please show me an example?

MichaelXF commented 10 months ago

Change all class properties to method definitions

initialize = () => new Promise(…

to

initialize() { return new Promise(… }

Probabilities commented 10 months ago

thanks, working now :)

CABrouwers commented 5 months ago

I ran into the same issue. It'd be great to add a warning that the ()=> constuct is not allowed, at least until the scrambler is updated.