Removed padding characters from all base64 encoded strings.

Removed RegExp that trims padding characters from `base64` encoded strings from `atob` code helper to prevent mutation of `RegExp.$1` value during calls to the `stringArray`. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/829
This commit is contained in:
sanex
2021-01-01 16:47:44 +03:00
parent bba709f412
commit 04be75e27b
19 changed files with 244 additions and 162 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ export enum ServiceIdentifiers {
ICodeTransformerNamesGroupsBuilder = 'ICodeTransformerNamesGroupsBuilder',
ICodeTransformersRunner = 'ICodeTransformersRunner',
ICryptUtils = 'ICryptUtils',
ICryptUtilsSwappedAlphabet = 'ICryptUtilsSwappedAlphabet',
ICryptUtilsStringArray = 'ICryptUtilsStringArray',
ICustomCodeHelper = 'ICustomCodeHelper',
ICustomCodeHelperGroup = 'ICustomCodeHelperGroup',
IControlFlowReplacer = 'IControlFlowReplacer',
+5 -5
View File
@@ -3,14 +3,14 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { IArrayUtils } from '../../../interfaces/utils/IArrayUtils';
import { ICryptUtils } from '../../../interfaces/utils/ICryptUtils';
import { ICryptUtilsSwappedAlphabet } from '../../../interfaces/utils/ICryptUtilsSwappedAlphabet';
import { ICryptUtilsStringArray } from '../../../interfaces/utils/ICryptUtilsStringArray';
import { IEscapeSequenceEncoder } from '../../../interfaces/utils/IEscapeSequenceEncoder';
import { ILevelledTopologicalSorter } from '../../../interfaces/utils/ILevelledTopologicalSorter';
import { IRandomGenerator } from '../../../interfaces/utils/IRandomGenerator';
import { ArrayUtils } from '../../../utils/ArrayUtils';
import { CryptUtils } from '../../../utils/CryptUtils';
import { CryptUtilsSwappedAlphabet } from '../../../utils/CryptUtilsSwappedAlphabet';
import { CryptUtilsStringArray } from '../../../utils/CryptUtilsStringArray';
import { EscapeSequenceEncoder } from '../../../utils/EscapeSequenceEncoder';
import { LevelledTopologicalSorter } from '../../../utils/LevelledTopologicalSorter';
import { RandomGenerator } from '../../../utils/RandomGenerator';
@@ -31,9 +31,9 @@ export const utilsModule: interfaces.ContainerModule = new ContainerModule((bind
.to(CryptUtils)
.inSingletonScope();
// crypt utils with swapped alphabet
bind<ICryptUtilsSwappedAlphabet>(ServiceIdentifiers.ICryptUtilsSwappedAlphabet)
.to(CryptUtilsSwappedAlphabet)
// crypt utils for string array
bind<ICryptUtilsStringArray>(ServiceIdentifiers.ICryptUtilsStringArray)
.to(CryptUtilsStringArray)
.inSingletonScope();
// escape sequence encoder
@@ -1,6 +1,8 @@
import { base64alphabetSwapped } from '../../../../constants/Base64AlphabetSwapped';
/**
* This atob logic completely ignores padding characters
*
* @returns {string}
*/
export function AtobTemplate (): string {
@@ -8,11 +10,10 @@ export function AtobTemplate (): string {
var {atobFunctionName} = function (input) {
const chars = '${base64alphabetSwapped}';
const str = String(input).replace(/=+$/, '');
let output = '';
for (
let bc = 0, bs, buffer, idx = 0;
buffer = str.charAt(idx++);
buffer = input.charAt(idx++);
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
@@ -1,4 +1,4 @@
/* eslint-disable @typescript-eslint/no-empty-interface */
import { ICryptUtils } from './ICryptUtils';
export interface ICryptUtilsSwappedAlphabet extends ICryptUtils {}
export interface ICryptUtilsStringArray extends ICryptUtils {}
@@ -5,7 +5,7 @@ import { TIdentifierNamesGeneratorFactory } from '../../types/container/generato
import { TStringArrayEncoding } from '../../types/options/TStringArrayEncoding';
import { IArrayUtils } from '../../interfaces/utils/IArrayUtils';
import { ICryptUtilsSwappedAlphabet } from '../../interfaces/utils/ICryptUtilsSwappedAlphabet';
import { ICryptUtilsStringArray } from '../../interfaces/utils/ICryptUtilsStringArray';
import { IEncodedValue } from '../../interfaces/IEncodedValue';
import { IIdentifierNamesGenerator } from '../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
import { IOptions } from '../../interfaces/options/IOptions';
@@ -60,9 +60,9 @@ export class StringArrayStorage extends MapStorage <`${string}-${TStringArrayEnc
private readonly arrayUtils: IArrayUtils;
/**
* @type {ICryptUtilsSwappedAlphabet}
* @type {ICryptUtilsStringArray}
*/
private readonly cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet;
private readonly cryptUtilsStringArray: ICryptUtilsStringArray;
/**
* @type {IIdentifierNamesGenerator}
@@ -104,7 +104,7 @@ export class StringArrayStorage extends MapStorage <`${string}-${TStringArrayEnc
* @param {IArrayUtils} arrayUtils
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {ICryptUtilsSwappedAlphabet} cryptUtilsSwappedAlphabet
* @param {ICryptUtilsStringArray} cryptUtilsStringArray
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
@@ -112,13 +112,13 @@ export class StringArrayStorage extends MapStorage <`${string}-${TStringArrayEnc
@inject(ServiceIdentifiers.IArrayUtils) arrayUtils: IArrayUtils,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.ICryptUtilsSwappedAlphabet) cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet
@inject(ServiceIdentifiers.ICryptUtilsStringArray) cryptUtilsStringArray: ICryptUtilsStringArray
) {
super(randomGenerator, options);
this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
this.arrayUtils = arrayUtils;
this.cryptUtilsSwappedAlphabet = cryptUtilsSwappedAlphabet;
this.cryptUtilsStringArray = cryptUtilsStringArray;
this.rc4Keys = this.randomGenerator.getRandomGenerator()
.n(
@@ -303,7 +303,7 @@ export class StringArrayStorage extends MapStorage <`${string}-${TStringArrayEnc
*/
case StringArrayEncoding.Rc4: {
const decodeKey: string = this.randomGenerator.getRandomGenerator().pickone(this.rc4Keys);
const encodedValue: string = this.cryptUtilsSwappedAlphabet.btoa(this.cryptUtilsSwappedAlphabet.rc4(value, decodeKey));
const encodedValue: string = this.cryptUtilsStringArray.btoa(this.cryptUtilsStringArray.rc4(value, decodeKey));
const encodedValueSources: string[] = this.rc4EncodedValuesSourcesCache.get(encodedValue) ?? [];
let encodedValueSourcesLength: number = encodedValueSources.length;
@@ -326,7 +326,7 @@ export class StringArrayStorage extends MapStorage <`${string}-${TStringArrayEnc
case StringArrayEncoding.Base64: {
const decodeKey: null = null;
const encodedValue: string = this.cryptUtilsSwappedAlphabet.btoa(value);
const encodedValue: string = this.cryptUtilsStringArray.btoa(value);
return { encodedValue, encoding, decodeKey };
}
@@ -1,7 +1,7 @@
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
import { ICryptUtilsSwappedAlphabet } from '../interfaces/utils/ICryptUtilsSwappedAlphabet';
import { ICryptUtilsStringArray } from '../interfaces/utils/ICryptUtilsStringArray';
import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
import { base64alphabetSwapped } from '../constants/Base64AlphabetSwapped';
@@ -9,7 +9,7 @@ import { base64alphabetSwapped } from '../constants/Base64AlphabetSwapped';
import { CryptUtils } from './CryptUtils';
@injectable()
export class CryptUtilsSwappedAlphabet extends CryptUtils implements ICryptUtilsSwappedAlphabet {
export class CryptUtilsStringArray extends CryptUtils implements ICryptUtilsStringArray {
/**
* @type {string}
*/
@@ -23,4 +23,16 @@ export class CryptUtilsSwappedAlphabet extends CryptUtils implements ICryptUtils
) {
super(randomGenerator);
}
/**
* Removes base64 encoded string without padding characters and with swapped alphabet
*
* @param {string} string
* @returns {string}
*/
public btoa (string: string): string {
const output = super.btoa(string);
return output.replace(/=+$/, '');
}
}