first work towards runtime injection, not really working yet
authorMilian Wolff <mail@milianw.de>
Fri, 5 Dec 2014 23:06:19 +0000 (00:06 +0100)
committerMilian Wolff <mail@milianw.de>
Fri, 5 Dec 2014 23:06:19 +0000 (00:06 +0100)
heaptrack_inject.cpp [new file with mode: 0644]

diff --git a/heaptrack_inject.cpp b/heaptrack_inject.cpp
new file mode 100644 (file)
index 0000000..dcdb9cc
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2014 Milian Wolff <mail@milianw.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <link.h>
+#include <string.h>
+#include <stdlib.h>
+
+/**
+ * @file heaptrack_inject.cpp
+ *
+ * @brief Experimental support for symbol overloading after runtime injection.
+ */
+
+namespace {
+
+auto original_malloc = &malloc;
+
+void* overwrite_malloc(size_t size)
+{
+    auto ret = original_malloc(size);
+    printf("HALLOOOOOO! %lu %p\n", size, ret);
+    return ret;
+}
+
+template<typename T, ElfW(Sxword) AddrTag, ElfW(Sxword) SizeTag>
+struct elftable
+{
+    T* table = nullptr;
+    ElfW(Xword) size = ElfW(Xword)();
+
+    bool consume(const ElfW(Dyn) *dyn)
+    {
+        if (dyn->d_tag == AddrTag) {
+            table = reinterpret_cast<T*>(dyn->d_un.d_ptr);
+            return true;
+        } else if (dyn->d_tag == SizeTag) {
+            size = dyn->d_un.d_val;
+            return true;
+        }
+        return false;
+    }
+};
+
+using elf_string_table = elftable<const char, DT_STRTAB, DT_STRSZ>;
+using elf_jmprel_table = elftable<ElfW(Rela), DT_JMPREL, DT_PLTRELSZ>;
+using elf_symbol_table = elftable<ElfW(Sym), DT_SYMTAB, DT_SYMENT>;
+
+bool overwrite_symbols(const ElfW(Dyn) *dyn)
+{
+    elf_symbol_table symbols;
+    elf_jmprel_table jmprels;
+    elf_string_table strings;
+    for (; dyn->d_tag != DT_NULL; ++dyn) {
+        symbols.consume(dyn) || jmprels.consume(dyn) || strings.consume(dyn);
+    }
+    printf("\tfound:\tsymtab: %p = %lu, jmptab: %p = %lu, strtab %p = %lu\n",
+            symbols.table, symbols.size,
+            jmprels.table, jmprels.size,
+            strings.table, strings.size);
+
+    auto relaend = reinterpret_cast<ElfW(Rela) *>(reinterpret_cast<char *>(jmprels.table) + jmprels.size);
+    for (auto rela = jmprels.table; rela < relaend; rela++) {
+        auto relsymidx = ELF64_R_SYM(rela->r_info);
+        const char *relsymname = strings.table + symbols.table[relsymidx].st_name;
+        if (strcmp("malloc", relsymname) == 0) {
+            printf("!!!!!!!!!1 found malloc: %p\n", reinterpret_cast<void *>(rela->r_offset));
+            *reinterpret_cast<void*(**)(size_t)>(rela->r_offset) = &overwrite_malloc;
+            return true;
+        }
+    }
+    return false;
+}
+
+int iterate_phdrs(dl_phdr_info *info, size_t /*size*/, void *data)
+{
+    printf("  iterate dlpi: %s\n", info->dlpi_name);
+    for (auto phdr = info->dlpi_phdr, end = phdr + info->dlpi_phnum; phdr != end; ++phdr) {
+        if (phdr->p_type == PT_DYNAMIC && (phdr->p_flags & (PF_W | PF_R)) == (PF_W | PF_R)) {
+            printf("    try dyn with flags=%d\n", phdr->p_flags);
+            if (overwrite_symbols(reinterpret_cast<const ElfW(Dyn) *>(phdr->p_vaddr + info->dlpi_addr))) {
+//                 return 1;
+// NOTE: stopping at the first found malloc symbol makes the "simple" demo work,
+// but more complicated apps with shared libraries still don't work as expected
+            }
+        }
+    }
+    return 0;
+}
+
+struct InitializeInjection
+{
+    InitializeInjection()
+    {
+        printf("init\n");
+        dl_iterate_phdr(&iterate_phdrs, nullptr);
+    }
+} initialize;
+
+}