Skip to content

Instantly share code, notes, and snippets.

@dimkr
Last active February 1, 2016 20:52
Show Gist options
  • Save dimkr/89c081935cbafaa70156 to your computer and use it in GitHub Desktop.
Save dimkr/89c081935cbafaa70156 to your computer and use it in GitHub Desktop.
How to replace a dependency shared object of an ELF executable
/*
* Copyright (c) 2016 Dima Krasner
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <elf.h>
int main(int argc, char *argv[])
{
struct stat stbuf;
unsigned char *data, *sectend;
const Elf32_Ehdr *hdr;
const Elf32_Shdr *sect, *dynamic, *dynstr;
Elf32_Dyn *ent;
char *strtab, *lib;
Elf32_Half i;
int fd, found;
fd = open(argv[1], O_RDWR);
if (fd < 0)
return EXIT_FAILURE;
if (fstat(fd, &stbuf) < 0) {
close(fd);
return EXIT_FAILURE;
}
data = mmap(NULL,
(size_t)stbuf.st_size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0);
if (!data) {
close(fd);
return EXIT_FAILURE;
}
hdr = (const Elf32_Ehdr *)data;
sect = (const Elf32_Shdr *)(data + hdr->e_shoff);
/* this points to the section header string table - it contains the section
* names */
strtab = (char *)(data + sect[hdr->e_shstrndx].sh_offset);
/* iterate over all sections until we find the .dynstr and .dynamic
* sections */
dynamic = dynstr = NULL;
for (i = 0; i < hdr->e_shnum; ++i) {
if (!dynstr && strcmp(strtab + sect[i].sh_name, ".dynstr") == 0)
dynstr = &sect[i];
if (!dynamic && sect[i].sh_type == SHT_DYNAMIC)
dynamic = &sect[i ];
if (dynamic && dynstr)
goto found;
}
munmap(data, (size_t)stbuf.st_size);
close(fd);
return EXIT_FAILURE;
found:
ent = (Elf32_Dyn *)(data + dynamic->sh_offset);
sectend = (unsigned char *)(data + dynamic->sh_offset + dynamic->sh_size);
found = 0;
do {
/* iterate over all entries in the .dynamic section - these are sonames
* of dependency shared objects */
if (ent->d_tag == DT_NEEDED) {
/* this points to the soname */
lib = (char *)(data + dynstr->sh_offset + ent->d_un.d_val);
if (strcmp(lib, argv[2]) == 0) {
strcpy(lib, argv[3]);
found = 1;
break;
}
}
++ent;
} while ((unsigned char *)ent < sectend);
munmap(data, (size_t)stbuf.st_size);
close(fd);
return found ? EXIT_SUCCESS : EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment