encoder.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. use crate::cpu_data::{x64, Arch as EncArch};
  2. use keystone::*;
  3. pub struct Encoder {
  4. arch: EncArch,
  5. shellcode: Vec<u8>,
  6. num_rounds: i32,
  7. reorder: bool,
  8. }
  9. impl Encoder {
  10. pub fn new(arch: EncArch, payload: Vec<u8>) -> Self {
  11. Encoder {
  12. arch: arch,
  13. shellcode: payload,
  14. num_rounds: 10,
  15. reorder: false,
  16. }
  17. }
  18. // main method for encoding the payload
  19. pub fn encode(&self) -> Vec<u8> {
  20. let mut payload = self.shellcode.clone();
  21. for i in 0..self.num_rounds {
  22. println!("[*] Encoding Round {}", i);
  23. // Generate random key
  24. let key: u8 = rand::random();
  25. // encode the payload
  26. let mut encoded_payload = self.encode_payload(payload.clone(), key);
  27. //println!("[*] Generating Stub...");
  28. let mut stub = self.get_decoder_stub(key, encoded_payload.len());
  29. // Append the encoded_payload to the stub
  30. stub.append(&mut encoded_payload);
  31. // Set the [stub+payload] as the new raw payload
  32. payload = stub.clone();
  33. }
  34. Vec::new()
  35. }
  36. /// This function does the plain shellcode encoding (XOR)
  37. pub fn encode_payload(&self, payload: Vec<u8>, seed: u8) -> Vec<u8> {
  38. // Buffer for the encoded payload
  39. let mut encoded_payload: Vec<u8> = Vec::new();
  40. let mut key = seed;
  41. for byte in payload {
  42. let new_byte = byte ^ key;
  43. //println!("Original Byte: 0x{:x}", byte);
  44. encoded_payload.push(new_byte);
  45. key = byte;
  46. }
  47. encoded_payload
  48. }
  49. /// Generates a decoder stub, each with using different registers
  50. fn get_decoder_stub(&self, seed: u8, payload_size: usize) -> Vec<u8> {
  51. // Maintain a blacklist for all the registers that are already used
  52. let mut blacklist: Vec<x64::Register> =
  53. vec![x64::Register::RSP, x64::Register::RBP, x64::Register::RDI];
  54. // generate a register for the COUNTER & add it to the blacklist
  55. let counter_register = x64::get_random_reg(&blacklist);
  56. blacklist.push(counter_register.register);
  57. // generate a register for the length of the payload
  58. let length_register = x64::get_random_reg(&blacklist);
  59. blacklist.push(length_register.register);
  60. // generate a register for the key of the payload (byte)
  61. let key_register = x64::get_random_reg(&blacklist);
  62. blacklist.push(key_register.register);
  63. //let key_register = key_register.byte;
  64. let dc1 = x64::generate_dead_code();
  65. let dc2 = x64::generate_dead_code();
  66. // Stub Prototype for x64
  67. let stub = "
  68. XOR {LENREG}, {LENREG}\n\
  69. XOR {KEYREG}, {KEYREG}\n\
  70. MOV {KEYREG},{K}\n\
  71. XOR {COUNTER}, {COUNTER}\n\
  72. MOV {LENREG},{S}\n\
  73. LEA RDI,[RIP+data]\n\
  74. decode:\n\
  75. XOR BYTE [RDI+{COUNTER}*1],{KEYREG}\n\
  76. MOV {KEYREG}, [RDI+{COUNTER}*1]\n\
  77. INC {COUNTER}\n\
  78. CMP {COUNTER}, {LENREG}\n\
  79. JLE decode\n\
  80. data:";
  81. // Replace the registers/keys/sizes to achieve a unique stub
  82. let stub = stub.replace("{KEYREG}", &key_register.byte);
  83. let stub = stub.replace("{COUNTER}", &counter_register.full);
  84. let stub = stub.replace("{LENREG}", &length_register.full);
  85. let stub = stub.replace("{K}", &format!("0x{:x}", seed));
  86. let stub = stub.replace("{S}", &format!("0x{:x}", payload_size));
  87. let stub = stub.replace("{DEAD_CODE_1}", &dc1);
  88. let stub = stub.replace("{DEAD_CODE_2}", &dc2);
  89. // return the stub string
  90. return assemble_asm(String::from(stub), OptionValue::SYNTAX_NASM).unwrap();
  91. }
  92. }
  93. /// The function uses capstone to assemble the stub and retrieve the raw bytes
  94. pub fn assemble_asm(stub: String, asm_syntax: OptionValue) -> Result<Vec<u8>, keystone::Error> {
  95. let engine =
  96. Keystone::new(Arch::X86, Mode::MODE_64).expect("Could not initialize Keystone engine");
  97. engine
  98. .option(OptionType::SYNTAX, asm_syntax)
  99. .expect("Could not set option to nasm syntax");
  100. // Assemble the stub and return the bytes
  101. let result = match engine.asm(stub, 0) {
  102. Ok(v) => Ok(v.bytes),
  103. Err(msg) => Err(msg),
  104. };
  105. return result;
  106. }
  107. /// This is the corresponding `decoder()`. This function is implemented
  108. /// in the decoder stub
  109. #[allow(dead_code)]
  110. fn decode(payload: Vec<u8>, seed: u8) -> Vec<u8> {
  111. let mut decoded_payload: Vec<u8> = Vec::new();
  112. // initialize the key
  113. let mut key = seed;
  114. for byte in payload {
  115. let orig_byte = byte ^ key;
  116. println!("0x{:x} ^ 0x{:x} -> 0x{:x}", byte, key, orig_byte);
  117. decoded_payload.push(orig_byte);
  118. key = orig_byte;
  119. }
  120. decoded_payload
  121. }