Commit 8538104c authored by Chu's avatar Chu

call shellcode in target process

parent 943c9a0b
......@@ -18,7 +18,7 @@ int main()
auto a = distribution(engine);
auto b = distribution(engine);
std::cout << a << " + " << b << " = " << sum(a, b) << std::endl;
std::this_thread::sleep_for(1s);
std::this_thread::sleep_for(5s);
}
return 0;
}
......
......@@ -19,25 +19,25 @@ int main(int argc, char *argv[])
Process process(std::stoi(argv[1]));
// find libc.so in target process
std::cout << "[*] try to find libc.so in target process\n";
std::cout << "[*] find libc.so in target process\n";
auto [libc_path, libc_base] = process.find_libc();
std::cout << "[+] libc: " << libc_path << " 0x" << std::hex << libc_base << std::endl;
// find __libc_dlopen_mode in libc.so
std::cout << "[*] try to find __libc_dlopen_mode in " << libc_path << std::endl;
std::cout << "[*] find __libc_dlopen_mode in " << libc_path << std::endl;
Elf libc(libc_path);
libc.set_base(libc_base);
auto libc_dlopen_mode = libc.find_symbol_address_by_name("__libc_dlopen_mode");
std::cout << "[+] __libc_dlopen_mode: 0x" << libc_dlopen_mode << std::endl;
// call shellcode in target process
std::cout << "[*] try to get shellcode in current process\n";
// call __libc_dlopen_mode in target process
std::cout << "[*] get shellcode in current process\n";
auto call_libc_dlopen_mode_addr = reinterpret_cast<unsigned char *>(&call_libc_dlopen_mode);
auto call_libc_dlopen_mode_size =
Elf(argv[0]).get_func_size(reinterpret_cast<std::size_t>(call_libc_dlopen_mode_addr));
std::cout << "[+] shellcode: 0x" << reinterpret_cast<std::size_t>(call_libc_dlopen_mode_addr) << " " << std::dec
<< call_libc_dlopen_mode_size << std::endl;
std::cout << "[*] try to call shellcode in target process\n";
std::cout << "[*] call __libc_dlopen_mode in target process\n";
process.call_shellcode(
std::vector(call_libc_dlopen_mode_addr, call_libc_dlopen_mode_addr + call_libc_dlopen_mode_size));
std::cout << "[+] injected\n";
......@@ -47,5 +47,11 @@ int main(int argc, char *argv[])
void call_libc_dlopen_mode()
{
std::cout << "call_libc_dlopen_mode\n";
asm volatile(R"(
mov $1, %rdi
mov $94068852580352, %rsi
mov $4, %rdx
mov $1, %rax
syscall
)");
}
......@@ -63,25 +63,44 @@ void Process::call_shellcode(std::vector<unsigned char> shellcode)
{
attach();
std::cout << "[*] try to get target process's entry point\n";
std::cout << "[*] get target process's entry point\n";
auto entry_point = get_entry_point();
std::cout << "[+] entry point: 0x" << std::hex << entry_point << std::endl;
// int3
shellcode.emplace_back(0xcc);
// replace `ret` with `int3`
shellcode[shellcode.size() - 1] = 0xcc;
// align
while (shellcode.size() % sizeof(void *) != 0)
shellcode.emplace_back(0x90);
std::cout << "[*] try to backup original code\n";
// backup original code
std::cout << "[*] backup original code\n";
auto original_code = read_memory(entry_point, shellcode.size());
std::cout << "[+] done\n";
std::cout << "[*] try to backup original registers\n";
// backup original registers
std::cout << "[*] backup original registers\n";
auto original_registers = get_registers();
std::cout << "[+] done\n";
std::cout << "[*] try to write shellcode to target process's entry point\n";
// write shellcode to entry point
std::cout << "[*] write shellcode to target process's entry point\n";
write_memory(entry_point, shellcode);
std::cout << "[+] done\n";
// set %rip to entry point
auto registers = original_registers;
registers.rip = entry_point;
std::cout << "[*] set %rip to target process's entry point\n";
set_registers(registers);
std::cout << "[+] done\n";
// wait for trap
std::cout << "[*] continue and wait for trap\n";
continue_and_wait_for_trap();
std::cout << "[+] done\n";
// restore original code
std::cout << "[*] restore original code\n";
write_memory(entry_point, original_code);
std::cout << "[+] done\n";
// restore original registers
std::cout << "[*] restore original registers\n";
set_registers(original_registers);
std::cout << "[+] done\n";
detach();
}
......@@ -144,4 +163,18 @@ user_regs_struct Process::get_registers()
return registers;
}
void Process::set_registers(user_regs_struct registers) {}
void Process::set_registers(const user_regs_struct &registers)
{
if (ptrace(PTRACE_SETREGS, pid_, nullptr, &registers))
throw std::runtime_error(std::strerror(errno));
}
void Process::continue_and_wait_for_trap()
{
if (ptrace(PTRACE_CONT, pid_, nullptr, nullptr) == -1)
throw std::runtime_error(std::strerror(errno));
int status;
wait(&status);
if (WSTOPSIG(status) != SIGTRAP)
throw std::runtime_error(std::strerror(errno));
}
......@@ -27,7 +27,8 @@ private:
std::vector<unsigned char> read_memory(std::size_t address, std::size_t size);
void write_memory(std::size_t address, std::vector<unsigned char> data);
user_regs_struct get_registers();
void set_registers(user_regs_struct registers);
void set_registers(const user_regs_struct &registers);
void continue_and_wait_for_trap();
};
#endif // LINUX_LIBRARY_INJECT_PROCESS_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment