apphx 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/dist/cli.js +41 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/integrations.js +177 -91
- package/dist/integrations.js.map +1 -1
- package/dist/notify.js +267 -0
- package/dist/notify.js.map +1 -0
- package/dist/policy.js +3 -16
- package/dist/policy.js.map +1 -1
- package/dist/runner.js +119 -20
- package/dist/runner.js.map +1 -1
- package/dist/schemas.js +57 -2
- package/dist/schemas.js.map +1 -1
- package/dist/vendor/obfuscator/dist/config.js +119 -6
- package/dist/vendor/obfuscator/dist/config.js.map +1 -1
- package/dist/vendor/obfuscator/dist/dfa.js +528 -0
- package/dist/vendor/obfuscator/dist/dfa.js.map +1 -0
- package/dist/vendor/obfuscator/dist/flutter.js +3266 -0
- package/dist/vendor/obfuscator/dist/flutter.js.map +1 -0
- package/dist/vendor/obfuscator/dist/image-utils.js +335 -0
- package/dist/vendor/obfuscator/dist/image-utils.js.map +1 -0
- package/dist/vendor/obfuscator/dist/junk.js +1501 -0
- package/dist/vendor/obfuscator/dist/junk.js.map +1 -0
- package/dist/vendor/obfuscator/dist/lexicon-data.js +972 -0
- package/dist/vendor/obfuscator/dist/lexicon-data.js.map +1 -0
- package/dist/vendor/obfuscator/dist/obfuscate.js +51 -2
- package/dist/vendor/obfuscator/dist/obfuscate.js.map +1 -1
- package/dist/vendor/obfuscator/dist/objc-symbols.js +1819 -0
- package/dist/vendor/obfuscator/dist/objc-symbols.js.map +1 -0
- package/dist/vendor/obfuscator/dist/project-identity.js +852 -0
- package/dist/vendor/obfuscator/dist/project-identity.js.map +1 -0
- package/dist/vendor/obfuscator/dist/string-encrypt.js +330 -0
- package/dist/vendor/obfuscator/dist/string-encrypt.js.map +1 -0
- package/examples/android-java.factory.json +40 -5
- package/examples/expo.factory.json +68 -5
- package/examples/flutter.factory.json +40 -4
- package/examples/luggage.json +1 -0
- package/examples/multi-role-agents.md +129 -0
- package/examples/mygo.factory.json +54 -4
- package/examples/queue-loop-demo.md +146 -0
- package/examples/react-native.factory.json +58 -5
- package/examples/roles.example.json +31 -0
- package/examples/swift.factory.json +60 -5
- package/examples/uni-app.factory.json +58 -5
- package/package.json +1 -1
- package/skills/apphx/SKILL.md +39 -4
- package/skills/apphx/resources/requirement.json +1 -0
- package/skills/apphx-obfuscator/LICENSE +21 -0
- package/skills/apphx-obfuscator/SKILL.md +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexicon-data.js","names":[],"sources":["../src/lexicon-data.ts"],"sourcesContent":["// Built-in sensitive-word lexicon and filter list.\n// Keep entries in their original order; do not edit by hand.\n\n/** Comma-separated sensitive-word lexicon. */\nexport const wordFilterStr = '张福杰,赌博,gambling,gamble,彩票,lottery,raffle,ticket,博彩,bet,wager,gaming,bwin,dafabet,马甲包,waistcoat,支付,pay,defray,alipay,wechat,现金,cash,demo,fuck,sex,肏,付款,傻逼,Lottery,purchase,coupon,coupons,confusion,confound,confounded,confoundedly,obscure,blur,blurry,confuse,confused,confusedly';\n\n/** Parsed sensitive words (same order as wordFilterStr). */\nexport const wordFilterList: readonly string[] = ['张福杰', '赌博', 'gambling', 'gamble', '彩票', 'lottery', 'raffle', 'ticket', '博彩', 'bet', 'wager', 'gaming', 'bwin', 'dafabet', '马甲包', 'waistcoat', '支付', 'pay', 'defray', 'alipay', 'wechat', '现金', 'cash', 'demo', 'fuck', 'sex', '肏', '付款', '傻逼', 'Lottery', 'purchase', 'coupon', 'coupons', 'confusion', 'confound', 'confounded', 'confoundedly', 'obscure', 'blur', 'blurry', 'confuse', 'confused', 'confusedly'];\n\n/** Common ObjC property/method identifiers skipped by keyword mixing. */\nexport const filterList: readonly string[] = [\n 'enable', 'scale', 'URL', 'supportsTextureSampleCount', 'writeToFile', 'code', 'zoomScale', 'direction',\n 'videoGravity', 'textLabel', 'anonymous', 'progress', 'failure', 'cancel', 'block', 'time',\n 'enabled', 'drawRect', 'flashMode', 'newCommandQueueWithMaxCommandBufferCount', 'animateTransition', 'secureTextEntry', 'mediaType', 'fileType',\n 'device', 'animation', 'value', 'draw', 'commit', 'play', 'pause', 'hide',\n 'version', 'locale', 'parentController', 'credential', 'affinity', 'listContainerView', 'transitionDuration', 'day',\n 'context', 'accessoryType', 'detailText', 'identifier', 'object', 'length', 'path', 'array',\n 'queue', 'beginTime', 'timer', 'configuration', 'notify', 'interval', 'isEqual', 'UUID',\n 'timeRange', 'createdAt', 'containerSize', 'url', 'parameters', 'player', 'session', 'pickerView',\n 'row', 'bridge', 'section', 'hidden', 'badgeValue', 'spacing', 'rowHeight', 'systemVersion',\n 'ScriptMessage', 'toURL', 'quality', 'logout', 'hints', 'uuid', 'apple', 'cache',\n 'list', 'selectIndex', 'string', 'isSelected', 'fillColor', 'cornerRadius', 'masksToBounds', 'borderColor',\n 'delay', 'receiver', 'placeholderText', 'timeZone', 'archiveRootObject', 'exponent', 'widthIs', 'heightIs',\n 'regularExpression', 'sureBtn', 'param', 'isPlaying', 'itemSize', 'inputView', 'filter', 'strokeColor',\n 'state', 'latitude', 'longitude', 'types', 'attributed', 'suspend', 'inTransaction', 'protocol',\n 'seekToTime', 'paused', 'loadImage', 'localizable', 'standard', 'webView', 'button', 'label',\n 'orientation', 'objects', 'resources', 'meta', 'index', 'completion', 'attributedText', 'bounces',\n 'animationDuration', 'goBack', 'goForward', 'operationType', 'lastPathComponent', 'loopMode', 'animationImages', 'begin',\n 'LocationManager', 'response', 'config', 'lineSpacing', 'lineHeight', 'customView', 'backgroundView', 'volume',\n 'MD5', 'animationRepeatCount', 'exposureMode', 'appID', 'encode', 'lossless', 'sel', 'topItem',\n 'asset', 'reset', 'manager', 'userInfo', 'top', 'params', 'date', 'components',\n 'sectionInset', 'actions', 'line', 'borderUIColor', 'selector', 'scheme', 'location', 'request',\n 'openURL', 'executing', 'finished', 'beginAppearanceTransition', 'origin', 'isRecording', 'totalCount', 'totalCost',\n 'writer', 'totalSize', 'read', 'beginUpdates', 'String', 'after', 'endIndex', 'reduce',\n 'schedule', 'refresh', 'convert', 'isFileURL', 'accessibilityLabel', 'combine', 'valueChanged', 'named',\n 'canEditRowAt', 'insets', 'torchMode', 'cancelled', 'task', 'jpushNotificationCenter', 'layoutMargins', 'evaluateJavaScript',\n 'dateFromString', 'withString', 'handlers', 'calendar', 'cancelExport', 'selectItem', 'rounded', 'editingStyleForRowAt',\n 'awakeFromNib', 'alertControllerWithTitle', 'allocWithZone', 'init', 'drawMode', 'sourceType', 'substring', 'dispose',\n 'unarchiveObjectWithFile', 'preferHDAudio', 'username', 'loopCount', 'union', 'endAppearanceTransition', 'actionWithTitle', 'alert',\n 'track', 'create', 'resume', 'prepareForReuse', 'dismiss', 'normalColor', 'selectColor', 'repeating',\n 'fromJSON', 'voiceDetect', 'onSuccess', 'onError', 'reversed', 'cgPath', 'grouped', 'configurations',\n 'dateFormat', 'beginRefreshing', 'endRefreshing', 'refreshing', 'compare', 'stringFromDate', 'visibleCells', 'video',\n 'progressBlock', 'rotationAngle', 'isTouchInside', 'CC_DLL', 'isNegative', 'sizing', 'voiceToText', 'beforeSend',\n 'completed', 'instance', 'pathForResource', 'loadRequest', 'loadHTMLString', 'completionHandler', 'long', 'options',\n 'color', 'lock', 'unlock', 'format', 'body', 'description', 'streamError', 'query',\n 'openLog', 'userSig', 'resignFirstResponder', 'valueForHTTPHeaderField', 'FBlock', 'textAlignment', 'memberNumber', 'hangup',\n 'cityEntity', 'drawableSize', 'texture', 'screen', 'presentsWithTransaction', 'pixelFormat', 'framebufferOnly', 'role',\n 'isCancelled', 'item', 'toView', 'bundle', 'values', 'placeholderImage', 'targetId', 'tapGesture',\n 'handler', 'hidesForSinglePage', 'country', 'postNotification', 'right', 'lineHeightMultiple', 'textContainer', 'layoutManager',\n 'textStorage', 'items', 'phoneNumber', 'thumbnail', 'isAnimating', 'rightView', 'progressView', 'searchBar',\n 'pageControl', 'segmentedControl', 'resultBlock', 'objectAtIndex', 'highlightedColor', 'md5', 'synchronize', 'maskView',\n 'audioDenoise', 'trackTimerStart', 'trackTimerEnd', 'notificationWithName', 'localizedDescription', '_id', 'playerView', 'highlighted',\n 'speed', 'md5HashOfData', 'requestAuthorization', 'NobleInfo', 'nobleInfo', 'displayAvailable', 'struct', 'callback',\n 'newRequest', 'onReceive', 'conversationType', 'userId', 'userID', 'completionBlock', 'openid', 'window',\n 'navigationController', 'selectRow', 'inDatabase', 'timeInterval', 'autoDeactivateAudioSession', 'decodeForDisplay', 'allowPickingOriginalPhoto', 'muted',\n 'StatusBarStyle', 'refreshControl', 'editable', 'countLimit', 'region', 'coordinate', 'mediaTypes', 'stringValue',\n 'thumbImage', 'avatar', 'sort', 'prefersStatusBarHidden', 'dealloc', 'const', 'method', 'createDirectory',\n 'linkTextAttributes', 'selectable', 'clearsOnInsertion', 'textContainerInset', 'second', 'notification', 'invalidate', 'exit',\n 'radius', 'opacity', 'readOptions', 'canGoBack', 'canGoForward', 'exportAsynchronouslyWithCompletionHandler', 'animations', 'rect',\n 'save', 'change', 'makeImage', 'makeNSView', 'makeUIView', 'colorWithRed', 'createDirectoryAtPath', 'panGestureRecognizer',\n 'gestureRecognizer', 'editing', 'password', 'mode', 'uid', 'weixin_no', 'order_by', 'crc32',\n 'completeTransition', 'cost', 'screenX', 'screenY', 'screenViewX', 'screenViewY', 'screenFrame', 'allKeys',\n 'objc_setAssociatedObject', 'moveItemAtURL', 'constraintForView', 'batteryLevel', 'children', 'push_back', 'objectForKeyedSubscript', 'totalTime',\n 'close', 'bind', 'connect', 'cocos2d', 'isOn', 'weekday', 'hour', 'minute',\n 'second', 'objc', 'weixinAuthLoginInContext', 'qqAuthLoginWithDelegate', 'presentDrawable', 'nextDrawable', 'sorted', 'batteryMonitoringEnabled',\n 'defaultCenter', 'clearCache', 'round', 'fullResolutionImage', 'blue', 'red', 'green', 'now',\n 'implementationLayer', 'encoding', 'fileName', 'topLeft', 'layer', 'paragraphStyle', 'zero', 'groupId',\n 'groupID', 'groupid', 'int', 'reason', 'bytes', 'endDate', 'mute', 'one',\n 'focusMode', 'running', 'sessionPreset', 'timeStamp', 'portraitUri', 'groupName', 'extra', 'labelText',\n 'weight', 'userName', 'objectName', 'operation', 'topRight', 'displayName', 'nickName', 'gender',\n 'birthday', 'nickname', 'headerImageView', 'once', 'minSize', 'margin', 'timestamp', 'quitAfterComment',\n 'commentId', 'starValue', 'resolveStatus', 'sourceUserId', 'transform', 'phoneNumbers', 'clear', 'alpha',\n 'appendBytes', 'exp', 'phone', 'level_id', 'email', 'write', 'matrix', 'find',\n 'shake', 'complete', 'notificationWithOperation', 'parse', 'times', 'log', 'sum', 'empty',\n 'debuggerVacateOpen', 'executeUpdate', 'recordedDuration', 'requestImageWithURL', 'source', 'loadData', 'executeQuery', 'layout',\n 'managedObjectContext', 'end', 'attributes', 'timeoutInterval', 'cachePolicy', 'attribute', 'baseURL', 'port',\n 'statusCode', 'arguments', 'lineWidth', 'lineCap', 'timingFunction', 'products', 'whiteBalanceMode', 'kickUsers',\n 'endUpdates', 'statusBarStyle', 'videoMaximumDuration', 'progressHandler', 'networkAccessAllowed', 'equalTo', 'fail', 'reuseIdentifier',\n 'priority', 'normalize', 'false', 'true', 'next', 'reverse', 'order', 'loop',\n 'first', 'frames', 'awake', 'errno', 'std', 'function', 'capacity', 'evutil_socket_geterror',\n 'leading', 'trailing', 'custom', 'property', 'xml', 'trigger', 'locations', 'continuous',\n 'emotionOriginalURL', 'connection', 'magic', 'sectionTitles', 'background', 'emotionType', 'inView', 'emotionOriginalURL',\n 'sampleRate', 'category', 'translation', 'price', 'isValid', 'headerReferenceSize', 'footerReferenceSize', 'ext',\n 'backgroundImage', 'city', 'subject', 'province', 'searchDisplayController', 'appKey', 'host', 'failureBlock',\n 'cls', 'pageIndex', 'pageNum', 'horizontal', 'isHidden', 'weak', 'coverImage', 'networkActivityIndicatorVisible',\n 'launchOptions', 'event', 'info', 'leading', 'price', 'experience', 'leftMargin', 'rightMargin',\n 'topMargin', 'leadingMargin', 'trailingMargin', 'strong', 'where', 'alias', 'login', 'edges',\n 'menuRightMargin', 'triangleY', 'triangleRightMargin', 'triangleSize', 'otherMargin', 'beginMargin', 'endMargin', 'for',\n 'seq', 'subtitle', 'openId', 'sign', 'stack', 'isSuccess', 'buttonWithType', 'scene',\n 'Double', 'metrics', 'copyWithZone', 'endEditing', 'defaultManager', 'selectItemAtIndexPath', 'encodeWithCoder', 'authorizationStatus',\n 'product', 'loadingView', 'invite_code', 'resourceLoader', 'exportSessionWithAsset', 'final', 'mask', 'distance',\n 'subscriber', 'deselectItemAtIndexPath', 'dictionaryRepresentation', 'pagingEnabled', 'team_scale', 'compressQuality', 'netStatus', 'Finish',\n 'platform', 'faceView', 'tableView', 'Array', 'readData', 'rotated', 'copyItem', 'decelerationRate',\n 'isLoading', 'accessoryView', 'language', 'baseline', 'superview', 'selectionStyle', 'successBlock', 'hidesBottomBarWhenPushed',\n 'lineJoin', 'colors', 'endPoint', 'indicatorColor', 'parentVC', 'propertyName', 'socks5Type', 'page',\n 'accessoryData', 'fromType', 'result', 'scheduleRule', 'comment', 'customizedId', 'menu', 'inputAccessoryView',\n 'privilege', 'containerView', 'backSpaceButtonImage', 'intrinsicContentSize', 'accessibilityValue', 'mAveragePower', 'mPeakPower', 'badge',\n 'msg', 'DelayTime', 'categories', 'lineColor', 'isFirstResponder', 'becomeFirstResponder', 'constraint', 'inset',\n 'downloadImageWithURL', 'isWXAppSupport', 'scaleToSize', 'colorWithHexString', 'Clear', 'resetOffsetFromCenter', 'popActivity', 'bounds',\n 'responseSerializer', 'acceptableContentTypes', 'requestSerializer', 'strokeEnd', 'lineBreakMode', 'vertical', 'hudType', 'customImage',\n 'indicatorBackGroundColor', 'acceptableStatusCodes', 'readingOptions', 'automaticallyInflatesResponseImage', 'videoPath', 'cancelAllOperations', 'appendData', 'dictionary',\n 'model', 'icon', 'user', 'photo', 'controlView', 'rate', 'bezierPath', 'clearMemory',\n 'arrayWithArray', 'streamStatus', 'limit', 'post', 'AssetsManagerEx', 'undoManager', 'scheduledTimerWithTimeInterval', 'attributeText',\n 'fillWithData', 'suspended', 'operations', 'serverTrust', 'fromValue', 'toValue', 'inviterAccid', 'cacheKeyForURL',\n 'socks5Addr', 'nextObject', 'sorted', 'stretch', 'value_type', 'keyPath', 'system', 'area',\n 'resourcePath', 'decode', 'failed', 'unsigned', 'operator', 'revents', 'events', 'auto',\n 'listen', 'shutdown', 'map', 'Quaternion', 'override', 'AffineTransform', 'Rect', 'totalUnitCount',\n 'nibWithNibName', 'topAnchor', 'activityItems', 'process', 'datePickerMode', 'datePicker', 'alignmentMode', 'detailsLabel',\n 'administrativeArea', 'locality', 'thoroughfare', 'subLocality', 'horizontalEdgeLength', 'enablesReturnKeyAutomatically', 'JSONObjectWithData', 'async',\n 'isDirectory', 'adSize', 'render', 'uint', 'BytesSize', 'serializer', 'subThoroughfare', 'callStatus',\n 'groupMemberDataSource', 'videoView', 'dateInterval', 'daterRange', 'transactions', 'fetchRequest', 'audioMix', 'videoComposition',\n 'reader', 'posterImage', 'propertyType', 'blueColor', 'EVP_CIPHER', 'buffer', 'myself', 'multiplier',\n 'BN_ULONG', 'switch', 'disconnect', 'cachedResponseForRequest', 'JSONString', 'jsonString', 'FFTSetup', 'Sticker',\n 'pauseRecord', 'willRotateToInterfaceOrientation', 'GetSize', 'collection', 'localIdentifier', 'socket', 'tree', 'searchTextField',\n 'camera', 'audioMuted', 'backItem', 'isEditing', 'parent', 'videoOrientation', 'endTime', 'lastInsertRowId',\n 'names', 'active', 'isOriginal', 'handleOpenURL', 'handleOpenUniversalLink', 'openWXApp', 'toDate', 'isExist',\n '_block', 'textValue', 'rectOfInterest', 'metadataObjectTypes', 'hideHUDForView', 'ins', 'nib', 'beautyLevel',\n 'totleTime', 'invalidateLayout', 'clearDiskOnCompletion', 'willAnimateRotationToInterfaceOrientation', 'navigationBarHidden', 'navigationBar', 'repeats', 'dragging',\n 'statusBarHidden', 'beautyLevel', 'ruddinessLevel', 'isReceived', 'lineViewWithFrame', 'unreadCount', 'outputImage', 'placeholderColor',\n 'videoAsset', 'videoResolution', 'decompress', 'm_frictionIndex', 'lineView', 'timeLabel', 'avatarView', 'expirationTimeInGMTFormat',\n 'onNewMessage', 'conversationData', 'onlineUserOnly', 'inviter', 'clockwise', 'convData', 'hCenter', 'vCenter',\n 'listView', 'listScrollView', 'pagerView', 'fetchOne', 'applyTransform', 'reachabilityStatusChangeBlock', 'targetSize', 'provider',\n 'objectId', 'columnNumber', 'presetName', 'isRunning', 'frameCount', 'outputURL', 'URLCache', 'creationDate',\n 'videoSettings', 'outputSettings', 'attributedTitle', 'atIndex', 'fromView', 'inSection', 'diskCache', 'isVisible',\n 'pixelWidth', 'pixelHeight', 'md5String', 'columnExists', 'xmlChar', 'prefix', 'noMoreData', 'frameOfPresentedViewInContainerView',\n 'truncationToken', 'releaseToRefresh', 'refreshSuccess', 'refreshFailure', 'myNetworkLoggerPlugin',\n];\n"],"mappings":"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"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { basenameWithoutExtension, classifyLanguage, deriveHash, deriveToken, isGeneratedCode, isResourceFile, walkProject, writeIfChanged } from "./common.js";
|
|
1
|
+
import { basenameWithoutExtension, classifyLanguage, deriveHash, deriveToken, isGeneratedCode, isReferenceCarrier, isResourceFile, walkProject, writeIfChanged } from "./common.js";
|
|
2
2
|
import { extractDeclaredIdentifiers, generateIdentifierMappings, transformCode } from "./code.js";
|
|
3
3
|
import { applyResourceRenames, perturbImageHashes, planResourceRenames, recolorImages } from "./resources.js";
|
|
4
4
|
import { obfuscateDirectories, remapUuids, renameProjectConfig } from "./project.js";
|
|
5
5
|
import { filterSensitiveWords, recolorSourceColors } from "./content.js";
|
|
6
|
+
import { renameObjcSymbols } from "./objc-symbols.js";
|
|
7
|
+
import { renameProjectIdentity } from "./project-identity.js";
|
|
8
|
+
import { applyStringEncryption } from "./string-encrypt.js";
|
|
9
|
+
import { renameFlutterSymbols } from "./flutter.js";
|
|
10
|
+
import { wordFilterList } from "./lexicon-data.js";
|
|
11
|
+
import { DFAFilter, mixKeywords } from "./dfa.js";
|
|
12
|
+
import { cleanUnusedResources, createJunkFiles, insertJunkCode } from "./junk.js";
|
|
13
|
+
import { flattenTransparency, hexToRgb, scaleImages } from "./image-utils.js";
|
|
6
14
|
import { readFileSync } from "node:fs";
|
|
7
15
|
// src/obfuscate.ts
|
|
8
16
|
/**
|
|
@@ -26,6 +34,10 @@ function applyObfuscation(root, config, seed, framework) {
|
|
|
26
34
|
walked = walkProject(root);
|
|
27
35
|
}
|
|
28
36
|
if (config.project?.uuids) record("projectUuids", remapUuids(walked.files, seed));
|
|
37
|
+
if (config.objc?.projectIdentity) {
|
|
38
|
+
record("objcProjectIdentity", renameProjectIdentity(walked.files, config.objc.projectIdentity, seed));
|
|
39
|
+
walked = walkProject(root);
|
|
40
|
+
}
|
|
29
41
|
if (config.resources?.rename) {
|
|
30
42
|
const mappings = { ...config.resources.rename.mappings };
|
|
31
43
|
if (config.resources.rename.generated) {
|
|
@@ -40,9 +52,34 @@ function applyObfuscation(root, config, seed, framework) {
|
|
|
40
52
|
walked = walkProject(root);
|
|
41
53
|
}
|
|
42
54
|
if (config.resources?.hashPerturb) record("resourceHash", perturbImageHashes(walked.files, config.resources.hashPerturb.bytes, seed));
|
|
43
|
-
if (config.resources?.images) record("imageRecolor", recolorImages(walked.files, config.resources.images, seed));
|
|
55
|
+
if (config.resources?.images?.recolor.length || config.resources?.images?.recolorAll) record("imageRecolor", recolorImages(walked.files, config.resources.images, seed));
|
|
56
|
+
if (config.resources?.images?.scale) record("imageScale", scaleImages(walked.files, config.resources.images.scale));
|
|
57
|
+
if (config.resources?.images?.flatten) record("imageFlatten", flattenTransparency(walked.files, hexToRgb(config.resources.images.flatten.bgColor ?? "#ffffff")));
|
|
44
58
|
if (config.content?.sensitiveWords) record("sensitiveWords", filterSensitiveWords(walked.files, config.content.sensitiveWords));
|
|
45
59
|
if (config.content?.controlColors || config.content?.fontColors) record("sourceColors", recolorSourceColors(walked.files, config.content.controlColors, config.content.fontColors));
|
|
60
|
+
if (config.content?.dfa) {
|
|
61
|
+
const filter = new DFAFilter([...wordFilterList, ...config.content.dfa.words ?? []]);
|
|
62
|
+
const changedPaths = [];
|
|
63
|
+
let changed = 0;
|
|
64
|
+
for (const entry of walked.files) {
|
|
65
|
+
if (!isReferenceCarrier(entry.relative)) continue;
|
|
66
|
+
const before = readFileSync(entry.absolute, "utf8");
|
|
67
|
+
let next = filter.filter(before, config.content.dfa.replace);
|
|
68
|
+
if (config.content.dfa.keywordMix) next = mixKeywords(next, {
|
|
69
|
+
seed,
|
|
70
|
+
prefix: config.content.dfa.keywordMix.prefix
|
|
71
|
+
}).content;
|
|
72
|
+
if (next === before) continue;
|
|
73
|
+
if (writeIfChanged(entry, next)) {
|
|
74
|
+
changed += 1;
|
|
75
|
+
changedPaths.push(entry.relative);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
record("dfaFilter", {
|
|
79
|
+
changed,
|
|
80
|
+
changedPaths
|
|
81
|
+
});
|
|
82
|
+
}
|
|
46
83
|
if (config.code) {
|
|
47
84
|
let generatedMappings = {};
|
|
48
85
|
if (config.code.renameIdentifiers?.generated) {
|
|
@@ -79,6 +116,18 @@ function applyObfuscation(root, config, seed, framework) {
|
|
|
79
116
|
}
|
|
80
117
|
transforms.code = count;
|
|
81
118
|
}
|
|
119
|
+
if (config.objc?.junkCode) record("objcJunkCode", insertJunkCode(walked.files, config.objc.junkCode, seed));
|
|
120
|
+
if (config.objc?.junkFiles) {
|
|
121
|
+
record("objcJunkFiles", createJunkFiles(root, walked.files, config.objc.junkFiles, seed));
|
|
122
|
+
walked = walkProject(root);
|
|
123
|
+
}
|
|
124
|
+
if (config.objc?.symbols) record("objcSymbols", renameObjcSymbols(walked.files, config.objc.symbols, seed));
|
|
125
|
+
if (config.objc?.stringEncryption) record("objcStringEncryption", applyStringEncryption(root, {
|
|
126
|
+
...config.objc.stringEncryption,
|
|
127
|
+
seed
|
|
128
|
+
}));
|
|
129
|
+
if (config.flutter) record("flutterSymbols", renameFlutterSymbols(walked.files, config.flutter, seed));
|
|
130
|
+
if (config.objc?.cleanResources) record("objcCleanResources", cleanUnusedResources(walked.files, config.objc.cleanResources));
|
|
82
131
|
return {
|
|
83
132
|
changedFiles: changed.size,
|
|
84
133
|
transforms,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obfuscate.js","names":[],"sources":["../src/obfuscate.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport type { Framework, TransformOutcome } from './common.js';\nimport { basenameWithoutExtension, classifyLanguage, deriveHash, deriveToken, isGeneratedCode, isResourceFile, walkProject, writeIfChanged } from './common.js';\nimport type { ObfuscatorConfig } from './config.js';\nimport { extractDeclaredIdentifiers, generateIdentifierMappings, transformCode } from './code.js';\nimport { applyResourceRenames, perturbImageHashes, planResourceRenames, recolorImages } from './resources.js';\nimport { obfuscateDirectories, remapUuids, renameProjectConfig } from './project.js';\nimport { filterSensitiveWords, recolorSourceColors } from './content.js';\n\nexport interface ObfuscationReport {\n /** Distinct owned files or directories whose content, path or binary payload changed. */\n changedFiles: number;\n /** Per-feature counts of changed files (or renamed entries). */\n transforms: Record<string, number>;\n skipped: { generated: number; unsupported: number };\n}\n\n/**\n * Deterministic in-place obfuscation of an owned project directory. Pass order is fixed so\n * reference-bearing renames happen before string/code transforms consume final names:\n * project config -> resource renames -> resource payloads -> content -> code.\n */\nexport function applyObfuscation(root: string, config: ObfuscatorConfig, seed: string, framework: Framework): ObfuscationReport {\n const changed = new Set<string>();\n const transforms: Record<string, number> = {};\n let unsupported = 0;\n const record = (name: string, outcome: TransformOutcome): void => {\n transforms[name] = outcome.changed;\n unsupported += outcome.unsupported ?? 0;\n for (const relative of outcome.changedPaths) changed.add(relative);\n };\n\n let walked = walkProject(root);\n\n // 1. Project configuration transforms.\n if (config.project?.name) record('projectName', renameProjectConfig(walked.files, framework, config.project.name));\n if (config.project?.directories.length) {\n record('projectDirectories', obfuscateDirectories(root, walked.files, config.project.directories, seed));\n walked = walkProject(root);\n }\n if (config.project?.uuids) record('projectUuids', remapUuids(walked.files, seed));\n\n // 2. Resource transforms (path changes before content transforms).\n if (config.resources?.rename) {\n const mappings = { ...config.resources.rename.mappings };\n if (config.resources.rename.generated) {\n const stems = [...new Set(walked.files.filter(entry => isResourceFile(entry.relative)).map(entry => basenameWithoutExtension(entry.relative)))];\n const selected = stems\n .map(stem => ({ stem, score: deriveHash(seed, 'resource-select', stem) }))\n .sort((a, b) => a.score < b.score ? -1 : a.score > b.score ? 1 : 0)\n .slice(0, config.resources.rename.generated);\n for (const { stem } of selected) mappings[stem] = deriveToken(seed, 'resource', stem);\n }\n const plan = planResourceRenames(walked.files, mappings);\n record('resourceRename', applyResourceRenames(root, walked.files, plan));\n walked = walkProject(root);\n }\n if (config.resources?.hashPerturb) record('resourceHash', perturbImageHashes(walked.files, config.resources.hashPerturb.bytes, seed));\n if (config.resources?.images) record('imageRecolor', recolorImages(walked.files, config.resources.images, seed));\n\n // 3. Content transforms.\n if (config.content?.sensitiveWords) record('sensitiveWords', filterSensitiveWords(walked.files, config.content.sensitiveWords));\n if (config.content?.controlColors || config.content?.fontColors) {\n record('sourceColors', recolorSourceColors(walked.files, config.content.controlColors, config.content.fontColors));\n }\n\n // 4. Code transforms.\n if (config.code) {\n // Seed-generated renames need a whole-project pass first: collect declared names, pick a\n // seeded selection, then rename every reference consistently (except generated code files,\n // whose serializers must keep referencing the original names).\n let generatedMappings: Record<string, string> = {};\n if (config.code.renameIdentifiers?.generated) {\n const declared: string[] = [];\n for (const entry of walked.files) {\n if (isGeneratedCode(entry.relative)) continue;\n const language = classifyLanguage(entry.relative);\n if (language) declared.push(...extractDeclaredIdentifiers(readFileSync(entry.absolute, 'utf8'), language));\n }\n generatedMappings = generateIdentifierMappings(declared, config.code.renameIdentifiers.generated, seed);\n }\n const hasGenerated = Object.keys(generatedMappings).length > 0;\n let count = 0;\n for (const entry of walked.files) {\n const language = classifyLanguage(entry.relative);\n if (!language) continue;\n const options = hasGenerated && config.code.renameIdentifiers && !isGeneratedCode(entry.relative)\n ? { ...config.code, renameIdentifiers: { ...config.code.renameIdentifiers, mappings: { ...generatedMappings, ...config.code.renameIdentifiers.mappings } } }\n : config.code;\n const before = readFileSync(entry.absolute, 'utf8');\n const next = transformCode(before, language, options, seed, entry.relative);\n if (next !== before) {\n writeIfChanged(entry, next);\n count += 1;\n changed.add(entry.relative);\n }\n }\n transforms.code = count;\n }\n\n return { changedFiles: changed.size, transforms, skipped: { generated: walked.skipped, unsupported } };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"obfuscate.js","names":[],"sources":["../src/obfuscate.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport type { Framework, TransformOutcome } from './common.js';\nimport { basenameWithoutExtension, classifyLanguage, deriveHash, deriveToken, isGeneratedCode, isReferenceCarrier, isResourceFile, walkProject, writeIfChanged } from './common.js';\nimport type { ObfuscatorConfig } from './config.js';\nimport { extractDeclaredIdentifiers, generateIdentifierMappings, transformCode } from './code.js';\nimport { applyResourceRenames, perturbImageHashes, planResourceRenames, recolorImages } from './resources.js';\nimport { obfuscateDirectories, remapUuids, renameProjectConfig } from './project.js';\nimport { filterSensitiveWords, recolorSourceColors } from './content.js';\nimport { renameObjcSymbols } from './objc-symbols.js';\nimport { renameProjectIdentity } from './project-identity.js';\nimport { applyStringEncryption } from './string-encrypt.js';\nimport { renameFlutterSymbols } from './flutter.js';\nimport { DFAFilter, mixKeywords } from './dfa.js';\nimport { wordFilterList } from './lexicon-data.js';\nimport { createJunkFiles, cleanUnusedResources, insertJunkCode } from './junk.js';\nimport { flattenTransparency, hexToRgb, scaleImages } from './image-utils.js';\n\nexport interface ObfuscationReport {\n /** Distinct owned files or directories whose content, path or binary payload changed. */\n changedFiles: number;\n /** Per-feature counts of changed files (or renamed entries). */\n transforms: Record<string, number>;\n skipped: { generated: number; unsupported: number };\n}\n\n/**\n * Deterministic in-place obfuscation of an owned project directory. Pass order is fixed so\n * reference-bearing renames happen before string/code transforms consume final names:\n * project config -> resource renames -> resource payloads -> content -> code.\n */\nexport function applyObfuscation(root: string, config: ObfuscatorConfig, seed: string, framework: Framework): ObfuscationReport {\n const changed = new Set<string>();\n const transforms: Record<string, number> = {};\n let unsupported = 0;\n const record = (name: string, outcome: TransformOutcome): void => {\n transforms[name] = outcome.changed;\n unsupported += outcome.unsupported ?? 0;\n for (const relative of outcome.changedPaths) changed.add(relative);\n };\n\n let walked = walkProject(root);\n\n // 1. Project configuration transforms.\n if (config.project?.name) record('projectName', renameProjectConfig(walked.files, framework, config.project.name));\n if (config.project?.directories.length) {\n record('projectDirectories', obfuscateDirectories(root, walked.files, config.project.directories, seed));\n walked = walkProject(root);\n }\n if (config.project?.uuids) record('projectUuids', remapUuids(walked.files, seed));\n // iOS identity pass (project name, folders, xcassets images, xib/storyboard refs).\n if (config.objc?.projectIdentity) {\n record('objcProjectIdentity', renameProjectIdentity(walked.files, config.objc.projectIdentity, seed));\n walked = walkProject(root);\n }\n\n // 2. Resource transforms (path changes before content transforms).\n if (config.resources?.rename) {\n const mappings = { ...config.resources.rename.mappings };\n if (config.resources.rename.generated) {\n const stems = [...new Set(walked.files.filter(entry => isResourceFile(entry.relative)).map(entry => basenameWithoutExtension(entry.relative)))];\n const selected = stems\n .map(stem => ({ stem, score: deriveHash(seed, 'resource-select', stem) }))\n .sort((a, b) => a.score < b.score ? -1 : a.score > b.score ? 1 : 0)\n .slice(0, config.resources.rename.generated);\n for (const { stem } of selected) mappings[stem] = deriveToken(seed, 'resource', stem);\n }\n const plan = planResourceRenames(walked.files, mappings);\n record('resourceRename', applyResourceRenames(root, walked.files, plan));\n walked = walkProject(root);\n }\n if (config.resources?.hashPerturb) record('resourceHash', perturbImageHashes(walked.files, config.resources.hashPerturb.bytes, seed));\n if (config.resources?.images?.recolor.length || config.resources?.images?.recolorAll) {\n record('imageRecolor', recolorImages(walked.files, config.resources.images, seed));\n }\n if (config.resources?.images?.scale) record('imageScale', scaleImages(walked.files, config.resources.images.scale));\n if (config.resources?.images?.flatten) {\n record('imageFlatten', flattenTransparency(walked.files, hexToRgb(config.resources.images.flatten.bgColor ?? '#ffffff')));\n }\n\n // 3. Content transforms.\n if (config.content?.sensitiveWords) record('sensitiveWords', filterSensitiveWords(walked.files, config.content.sensitiveWords));\n if (config.content?.controlColors || config.content?.fontColors) {\n record('sourceColors', recolorSourceColors(walked.files, config.content.controlColors, config.content.fontColors));\n }\n if (config.content?.dfa) {\n // DFA lexicon filter, then optional constant-keyword mixing.\n const filter = new DFAFilter([...wordFilterList, ...(config.content.dfa.words ?? [])]);\n const changedPaths: string[] = [];\n let changed = 0;\n for (const entry of walked.files) {\n if (!isReferenceCarrier(entry.relative)) continue;\n const before = readFileSync(entry.absolute, 'utf8');\n let next = filter.filter(before, config.content.dfa.replace);\n if (config.content.dfa.keywordMix) next = mixKeywords(next, { seed, prefix: config.content.dfa.keywordMix.prefix }).content;\n if (next === before) continue;\n if (writeIfChanged(entry, next)) {\n changed += 1;\n changedPaths.push(entry.relative);\n }\n }\n record('dfaFilter', { changed, changedPaths });\n }\n\n // 4. Code transforms.\n if (config.code) {\n // Seed-generated renames need a whole-project pass first: collect declared names, pick a\n // seeded selection, then rename every reference consistently (except generated code files,\n // whose serializers must keep referencing the original names).\n let generatedMappings: Record<string, string> = {};\n if (config.code.renameIdentifiers?.generated) {\n const declared: string[] = [];\n for (const entry of walked.files) {\n if (isGeneratedCode(entry.relative)) continue;\n const language = classifyLanguage(entry.relative);\n if (language) declared.push(...extractDeclaredIdentifiers(readFileSync(entry.absolute, 'utf8'), language));\n }\n generatedMappings = generateIdentifierMappings(declared, config.code.renameIdentifiers.generated, seed);\n }\n const hasGenerated = Object.keys(generatedMappings).length > 0;\n let count = 0;\n for (const entry of walked.files) {\n const language = classifyLanguage(entry.relative);\n if (!language) continue;\n const options = hasGenerated && config.code.renameIdentifiers && !isGeneratedCode(entry.relative)\n ? { ...config.code, renameIdentifiers: { ...config.code.renameIdentifiers, mappings: { ...generatedMappings, ...config.code.renameIdentifiers.mappings } } }\n : config.code;\n const before = readFileSync(entry.absolute, 'utf8');\n const next = transformCode(before, language, options, seed, entry.relative);\n if (next !== before) {\n writeIfChanged(entry, next);\n count += 1;\n changed.add(entry.relative);\n }\n }\n transforms.code = count;\n }\n\n // 5. iOS passes: junk code/files first (they introduce new symbols), then\n // ObjC/Swift symbol renames, XOR string encryption, Flutter symbols, and resource cleaning\n // last (it scans the final code for references).\n if (config.objc?.junkCode) record('objcJunkCode', insertJunkCode(walked.files, config.objc.junkCode, seed));\n if (config.objc?.junkFiles) {\n record('objcJunkFiles', createJunkFiles(root, walked.files, config.objc.junkFiles, seed));\n walked = walkProject(root);\n }\n if (config.objc?.symbols) record('objcSymbols', renameObjcSymbols(walked.files, config.objc.symbols, seed));\n if (config.objc?.stringEncryption) {\n record('objcStringEncryption', applyStringEncryption(root, { ...config.objc.stringEncryption, seed }));\n }\n if (config.flutter) record('flutterSymbols', renameFlutterSymbols(walked.files, config.flutter, seed));\n if (config.objc?.cleanResources) record('objcCleanResources', cleanUnusedResources(walked.files, config.objc.cleanResources));\n\n return { changedFiles: changed.size, transforms, skipped: { generated: walked.skipped, unsupported } };\n}\n"],"mappings":"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"}
|