Commit 1954c0c6 authored by Chu's avatar Chu

Initial commit

parents
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: Google
ColumnLimit: 120 # 行最大长度 120
BreakBeforeBraces: Allman # 大括号换行
IndentWidth: 4 # 缩进 4
AccessModifierOffset: -4 # 访问控制符不缩进
AllowShortLoopsOnASingleLine: false # 不允许单行循环语句
AllowShortIfStatementsOnASingleLine: false # 不允许单行 if 语句
AllowShortFunctionsOnASingleLine: Empty # 仅在函数体为空时放置在单行
FixNamespaceComments: false # 不补全命名空间注释
.idea
cmake-build-*
cmake_minimum_required(VERSION 3.13)
project(Linux_Library_Inject)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(host)
add_subdirectory(inject)
add_executable(host main.cpp)
#include <chrono>
#include <iostream>
#include <random>
#include <thread>
using namespace std::chrono_literals;
void show_message(std::string_view message);
int sum(int a, int b);
int main()
{
std::default_random_engine engine;
std::uniform_int_distribution distribution(1, 100);
while (true)
{
show_message("working...");
auto a = distribution(engine);
auto b = distribution(engine);
std::cout << a << " + " << b << " = " << sum(a, b) << std::endl;
std::this_thread::sleep_for(1s);
}
return 0;
}
void show_message(std::string_view message)
{
std::cout << "message: " << message << std::endl;
}
int sum(int a, int b)
{
return a + b;
}
add_executable(inject main.cpp process.cpp process.h elf.cpp elf.h)
\ No newline at end of file
#include "elf.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <stdexcept>
Elf::~Elf()
{
if (loaded_)
munmap(memory_, memory_length_);
}
void Elf::set_base(unsigned long base)
{
base_ = base;
}
std::size_t Elf::find_symbol_address_by_name(std::string_view name)
{
if (!loaded_)
load_to_memory();
for (auto i = 0; i != ehdr_->e_shnum; ++i)
{
if (shdr_[i].sh_type == SHT_DYNSYM)
{
auto str_tab = reinterpret_cast<char *>(&memory_[shdr_[shdr_[i].sh_link].sh_offset]);
auto sym_tab = reinterpret_cast<Elf64_Sym *>(&memory_[shdr_[i].sh_offset]);
for (auto j = 0; j != shdr_[i].sh_size / sizeof(Elf64_Sym); ++j)
{
if (&str_tab[sym_tab->st_name] == name)
return base_ + sym_tab->st_value;
++sym_tab;
}
}
}
throw std::runtime_error(std::string(name) + " not found in " + path_);
}
void Elf::load_to_memory()
{
auto fd = open(path_.c_str(), O_RDONLY);
if (fd == -1)
throw std::runtime_error(std::strerror(errno));
struct stat st = {0};
if (fstat(fd, &st) == -1)
{
close(fd);
throw std::runtime_error(std::strerror(errno));
}
memory_length_ = st.st_size;
if (memory_ = static_cast<decltype(memory_)>(mmap(nullptr, memory_length_, PROT_READ, MAP_PRIVATE, fd, 0));
memory_ == MAP_FAILED)
{
close(fd);
throw std::runtime_error(std::strerror(errno));
}
close(fd);
ehdr_ = reinterpret_cast<Elf64_Ehdr *>(memory_);
shdr_ = reinterpret_cast<Elf64_Shdr *>(memory_ + ehdr_->e_shoff);
loaded_ = true;
}
#ifndef LINUX_LIBRARY_INJECT_ELF_H
#define LINUX_LIBRARY_INJECT_ELF_H
#include <elf.h>
#include <string>
#include <string_view>
class Elf final
{
public:
explicit Elf(std::string path) : path_(std::move(path)) {}
~Elf();
void set_base(unsigned long base);
std::size_t find_symbol_address_by_name(std::string_view name);
private:
std::string path_;
unsigned long base_ = 0;
bool loaded_ = false;
std::size_t memory_length_ = 0;
unsigned char *memory_ = nullptr;
Elf64_Ehdr *ehdr_ = nullptr;
Elf64_Shdr *shdr_ = nullptr;
void load_to_memory();
};
#endif // LINUX_LIBRARY_INJECT_ELF_H
#include <sys/types.h>
#include <iostream>
#include <string>
#include <tuple>
#include "elf.h"
#include "process.h"
int main(int argc, char *argv[])
{
if (argc != 3)
{
std::cerr << "usage: " << argv[0] << " <pid> <evil.so>\n";
return 1;
}
// process
pid_t pid = 0;
try
{
pid = std::stoi(argv[1]);
}
catch (const std::exception &)
{
std::cerr << "[!] invalid pid " << argv[1] << std::endl;
return 1;
}
Process process(pid);
// find libc.so in process
std::string libc_path;
std::size_t libc_base;
try
{
std::tie(libc_path, libc_base) = process.find_libc();
}
catch (const std::exception &e)
{
std::cerr << "[!] " << e.what() << std::endl;
return 1;
}
std::cout << "[+] libc: " << libc_path << " 0x" << std::hex << libc_base << std::endl;
// find __libc_dlopen_mode in libc.so
Elf libc(libc_path);
libc.set_base(libc_base);
std::size_t libc_dlopen_mode_addr;
try
{
libc_dlopen_mode_addr = libc.find_symbol_address_by_name("__libc_dlopen_mode");
}
catch (const std::exception &e)
{
std::cerr << "[!] " << e.what() << std::endl;
return 1;
}
std::cout << "[+] __libc_dlopen_mode: 0x" << libc_dlopen_mode_addr << std::endl;
// get process' entry
// copy shellcode to process' entry
// call shellcode
// resume process
return 0;
}
#include "process.h"
#include <fstream>
#include <regex>
std::pair<std::string, std::size_t> Process::find_libc()
{
std::string filename("/proc/");
filename += std::to_string(pid_);
filename += "/maps";
std::ifstream file(filename);
std::regex pattern(R"(^([0-9a-h]+)\-.*?(/.*libc\-[0-9\.]*?\.so)$)");
std::string line;
std::smatch result;
while (std::getline(file, line))
{
if (std::regex_search(line, result, pattern))
return {result[2].str(), std::stoul(result[1].str(), nullptr, 16)};
}
throw std::runtime_error("libc.so not found in " + filename);
}
#ifndef LINUX_LIBRARY_INJECT_PROCESS_H
#define LINUX_LIBRARY_INJECT_PROCESS_H
#include <sys/types.h>
#include <string>
#include <utility>
class Process final
{
public:
explicit Process(pid_t pid) : pid_(pid) {}
std::pair<std::string, std::size_t> find_libc();
private:
pid_t pid_;
};
#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