Skip to content

Commit

Permalink
Outline path model which will be used to differentiate detection item…
Browse files Browse the repository at this point in the history
…s in rich detal

Rework results model to use the new path system, begin layout of standard scanning.
  • Loading branch information
Col-E committed Jul 8, 2023
1 parent 9ad71e9 commit 472f75a
Show file tree
Hide file tree
Showing 27 changed files with 692 additions and 333 deletions.
1 change: 1 addition & 0 deletions concoction-lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
api asm_util
api cafedude
api lljzip
api collections
api jackson
api slf4jLogging

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
package info.mmpa.concoction;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import info.mmpa.concoction.result.ArchiveScanResults;

public class Concoction {
public static Map<String, ArchiveScanResults> scanDirectory(File file) {
HashMap<String, ArchiveScanResults> results = new HashMap<>();
// TODO
return results;
}
}
public class Concoction {}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class ClassesAndFiles {
*/
public void addClass(@Nonnull String path, @Nonnull byte[] raw) throws NotAClassException {
try {
verifyAndAddClass(path, raw);
verifyAndAddClass(raw);
} catch (Throwable t) {
// Class was not parsed fully by ASM.
// Maybe its using anti-asm exploits? Attempt to fix with cafedue.
Expand All @@ -42,20 +42,21 @@ public void addClass(@Nonnull String path, @Nonnull byte[] raw) throws NotAClass
byte[] patched = writer.write(file);

// Should be good to go now.
verifyAndAddClass(path, patched);
verifyAndAddClass(patched);
} catch (Throwable t2) {
// Still not valid. Either this is not a class,
// or we have a new anti-asm exploit to fix upstream in cafedude.
throw new NotAClassException(t2);
throw new NotAClassException(path, t2);
}
}
}

private void verifyAndAddClass(@Nonnull String path, @Nonnull byte[] raw) {
private void verifyAndAddClass(@Nonnull byte[] raw) {
// Our classes must be parsed with ASM for later SSVM integration.
ClassReader reader = new ClassReader(raw);
String className = reader.getClassName();
reader.accept(new ClassWriter(0), 0);
classes.put(path, raw);
classes.put(className, raw);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
package info.mmpa.concoction.input;

import javax.annotation.Nonnull;

/**
* Exception to outline an input to {@link ClassesAndFiles#addClass(String, byte[])} was not actually a class.
*/
public class NotAClassException extends Exception {
private final String name;

/**
* @param name
* File path that is not a class.
* @param cause
* Parent exception thrown by class validation.
*/
public NotAClassException(Throwable cause) {
public NotAClassException(@Nonnull String name, @Nonnull Throwable cause) {
super(cause);
this.name = name;
}

/**
* @return File path that is not a class.
*/
@Nonnull
public String getName() {
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* the accuracy of the scan if needed.
*
* @see ModelSource Single component type that builds up the model.
* @see ModelBuilder For creating new {@link ApplicationModel} instances.
*/
public interface ApplicationModel {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package info.mmpa.concoction.model;

import info.mmpa.concoction.input.archive.ArchiveLoadContext;
import info.mmpa.concoction.model.impl.BasicModelBuilder;

import javax.annotation.Nonnull;
import java.io.IOException;
Expand Down Expand Up @@ -54,4 +55,12 @@ public interface ModelBuilder {
*/
@Nonnull
ApplicationModel build() throws InvalidModelException;

/**
* @return New builder instance.
*/
@Nonnull
static ModelBuilder create() {
return new BasicModelBuilder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package info.mmpa.concoction.model.path;

/**
* Common outline of path elements, declaring shared behaviors.
*/
public abstract class AbstractPathElement implements PathElement {
@Override
public int compareTo(PathElement o) {
return fullDisplay().compareTo(o.fullDisplay());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package info.mmpa.concoction.model.path;

import info.mmpa.concoction.model.ModelSource;
import org.objectweb.asm.tree.MethodNode;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* A path to a class within a {@link ModelSource}.
*/
public class ClassPathElement extends AbstractPathElement {
private final Map<String, MethodPathElement> children = new HashMap<>();
private final SourcePathElement parent;
private final String className;

/**
* @param parent
* Parent path element.
* @param className
* Name of the class.
*/
public ClassPathElement(@Nonnull SourcePathElement parent, @Nonnull String className) {
this.parent = parent;
this.className = className;
}

/**
* @param methodName
* Method name.
* @param methodDesc
* Method desc.
*
* @return New child path to a method within this class.
*/
@Nonnull
public MethodPathElement child(@Nonnull String methodName, @Nonnull String methodDesc) {
return children.computeIfAbsent(methodName + methodDesc, k -> new MethodPathElement(this, methodName, methodDesc));
}

/**
* @param method
* Method declaration.
*
* @return New child path to a method within this class.
*/
@Nonnull
public MethodPathElement child(@Nonnull MethodNode method) {
return child(method.name, method.desc);
}

@Nullable
@Override
public PathElement parent() {
return parent;
}

@Nonnull
@Override
public Collection<MethodPathElement> children() {
return children.values();
}

@Nonnull
@Override
public String fullDisplay() {
return parent.fullDisplay() + " : " + localDisplay();
}

@Nonnull
@Override
public String localDisplay() {
return className;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

ClassPathElement that = (ClassPathElement) o;

return className.equals(that.className);
}

@Override
public int hashCode() {
return className.hashCode();
}

@Override
public String toString() {
return localDisplay();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package info.mmpa.concoction.model.path;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;

/**
* A path to a method within a class.
*/
public class MethodPathElement extends AbstractPathElement {
private final ClassPathElement parent;
private final String methodName;
private final String methodDesc;

/**
* @param parent
* Parent path element.
* @param methodName
* Name of the method.
* @param methodDesc
* Descriptor of the method.
*/
public MethodPathElement(@Nonnull ClassPathElement parent, @Nonnull String methodName, @Nonnull String methodDesc) {
this.parent = parent;
this.methodName = methodName;
this.methodDesc = methodDesc;
}

@Nullable
@Override
public PathElement parent() {
return parent;
}

@Nonnull
@Override
public Collection<? extends PathElement> children() {
return Collections.emptyList();
}

@Nonnull
@Override
public String fullDisplay() {
return parent.fullDisplay() + "." + localDisplay();
}

@Nonnull
@Override
public String localDisplay() {
return methodName + methodDesc;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

MethodPathElement that = (MethodPathElement) o;

if (!methodName.equals(that.methodName)) return false;
return methodDesc.equals(that.methodDesc);
}

@Override
public int hashCode() {
int result = methodName.hashCode();
result = 31 * result + methodDesc.hashCode();
return result;
}

@Override
public String toString() {
return localDisplay();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package info.mmpa.concoction.model.path;

import info.mmpa.concoction.model.ApplicationModel;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;

/**
* Outline of a modular path to point to different locations in a {@link ApplicationModel}.
*/
public interface PathElement extends Comparable<PathElement> {
/**
* @return Parent path element. Will be {@code null} for the root.
*/
@Nullable
PathElement parent();

/**
* @return Collection of child paths.
*/
@Nonnull
Collection<? extends PathElement> children();

/**
* @return Full path display, which includes all display parts of parents.
*/
@Nonnull
String fullDisplay();

/**
* @return Local display of the current element.
*/
@Nonnull
String localDisplay();
}
Loading

0 comments on commit 472f75a

Please sign in to comment.