Skip to content

Commit ca836eb

Browse files
committed
Resolving libdl symbols in libc
1 parent 1359441 commit ca836eb

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

elf.c

+83
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <stdbool.h>
2424
#include <stdio.h>
2525
#include <stdlib.h>
26+
#include <string.h>
2627
#include <elf.h>
2728

2829
#include "procfs.h"
@@ -424,3 +425,85 @@ void free_symbol_table(struct symbol_table *table)
424425
{
425426
free(table);
426427
}
428+
429+
static Elf64_Word elf_hash(const char *name)
430+
{
431+
Elf64_Word h = 0;
432+
433+
while (*name) {
434+
h = (h << 4) + *name++;
435+
436+
Elf64_Word g = h & 0xF0000000;
437+
438+
if (g)
439+
h ^= g >> 24;
440+
441+
h &= ~g;
442+
}
443+
444+
return h;
445+
}
446+
447+
static const char* symbol_name(const Elf64_Sym *symbol,
448+
struct symbol_table *symbols)
449+
{
450+
if (!symbol->st_name)
451+
return "";
452+
453+
return &symbols->dynstr.strings[symbol->st_name];
454+
}
455+
456+
static unsigned long symbol_address(const char *name,
457+
const Elf64_Sym *symbol, struct symbol_table *symbols)
458+
{
459+
uint8_t bind = ELF64_ST_BIND(symbol->st_info);
460+
uint8_t type = ELF64_ST_TYPE(symbol->st_info);
461+
462+
if (symbol->st_shndx == STN_UNDEF) {
463+
fprintf(stderr, "[!] undefined symbol: %s\n", name);
464+
return 0;
465+
}
466+
467+
if ((bind != STB_GLOBAL) && (bind != STB_WEAK)) {
468+
fprintf(stderr, "[!] local symbol: %s\n", name);
469+
return 0;
470+
}
471+
472+
if ((type != STT_FUNC) && (type != STT_OBJECT)) {
473+
fprintf(stderr, "[!] not a runtime object: %s\n", name);
474+
return 0;
475+
}
476+
477+
return symbols->base_vaddr + symbol->st_value;
478+
}
479+
480+
unsigned long resolve_symbol(const char *name, struct symbol_table *symbols)
481+
{
482+
Elf64_Word nbucket = symbols->hash.table->nbucket;
483+
const Elf64_Word *buckets = &symbols->hash.table->entries[0];
484+
const Elf64_Word *chains = &symbols->hash.table->entries[nbucket];
485+
486+
Elf64_Word hash = elf_hash(name);
487+
Elf64_Word bucket = hash % nbucket;
488+
Elf64_Word index = buckets[bucket];
489+
490+
for (;;) {
491+
if (index > symbols->dynsym.count) {
492+
fprintf(stderr, "[*] invalid hash index: %d (> %ld)\n",
493+
index, symbols->dynsym.count);
494+
return 0;
495+
}
496+
497+
const Elf64_Sym *symbol = &symbols->dynsym.symbols[index];
498+
499+
if (strcmp(symbol_name(symbol, symbols), name) == 0)
500+
return symbol_address(name, symbol, symbols);
501+
502+
index = chains[index];
503+
504+
if (index == STN_UNDEF) {
505+
fprintf(stderr, "[!] symbol not found: %s\n", name);
506+
return 0;
507+
}
508+
}
509+
}

elf.h

+10
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,14 @@ struct symbol_table* find_dynamic_symbol_table(struct library *mapping);
4242
*/
4343
void free_symbol_table(struct symbol_table *table);
4444

45+
/**
46+
* resolve_symbol() - resolve a remote symbol
47+
* @name: symbol name to resolve
48+
* @table: symbol table to use
49+
*
50+
* Returns: virtual address of the requested symbol, or zero if the symbol
51+
* could not be resolved.
52+
*/
53+
unsigned long resolve_symbol(const char *name, struct symbol_table *table);
54+
4555
#endif /* LINUX_CRT_ELF_H */

inject-thread.c

+13
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@ int main(int argc, char *argv[])
113113

114114
printf("[+] found dynamic symbol table\n");
115115

116+
printf("[-] resolving necessary symbols from libc...\n");
117+
118+
unsigned long dlopen =
119+
resolve_symbol("__libc_dlopen_mode", libc_symbols);
120+
unsigned long dlsym =
121+
resolve_symbol("__libc_dlsym", libc_symbols);
122+
if (!dlopen || !dlsym)
123+
goto free_symbols;
124+
125+
printf("[+] resolved __libc_dlopen_mode(): %lx\n", dlopen);
126+
printf("[+] resolved __libc_dlsym(): %lx\n", dlsym);
127+
128+
free_symbols:
116129
free_symbol_table(libc_symbols);
117130

118131
unmap_libc:

0 commit comments

Comments
 (0)