herm1t LIVE!ng room - Post a comment [entries|archive|friends|userinfo]
herm1t

[ website | twilight corner in the herm1t's cave ]
[ userinfo | ljr userinfo ]
[ archive | journal archive ]

Highway to libc Sep. 13th, 2011|01:21 pm

herm1t
Почему эта хрень работает?
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <elf.h>

/* Type for the dtv.  */
typedef union dtv
{
  size_t counter;
  struct
  {
    void *val;
    bool is_static;
  } pointer;
} dtv_t;


typedef struct
{
  void *tcb;            /* Pointer to the TCB.  Not necessarily the
                           thread descriptor used by libpthread.  */
  dtv_t *dtv;
  void *self;           /* Pointer to the thread descriptor.  */
  int multiple_threads;
  uintptr_t sysinfo;
  uintptr_t stack_guard;
  uintptr_t pointer_guard;
} tcbhead_t;

int main(int argc, char **argv)
{
        void *get_base(uint32_t addr) {
                addr &= ~4095;
                while (*(uint32_t*)addr != 0x464c457fUL)
                        addr -= 4096;
                        return (void*)addr;
        }
        tcbhead_t *tcb;
        asm ("mov %%gs:0x0,%%eax":"=a"(tcb));
        dtv_t *dtv = tcb->dtv;
        if (dtv->counter > 0) {
                uint32_t *tls = dtv[1].pointer.val;
                Elf32_Ehdr *ehdr = get_base(tls[0]);
                Elf32_Phdr *phdr = (Elf32_Phdr*)((char*)ehdr + ehdr->e_phoff);
                int i;
                Elf32_Dyn *dyn = NULL;
                int delta;
                uint32_t low;
                for (i = 0; i < ehdr->e_phnum; i++)
                        if (phdr[i].p_type == PT_DYNAMIC)
                                dyn = (Elf32_Dyn*)phdr[i].p_vaddr;
                        else
                        if (phdr[i].p_type == PT_LOAD && phdr[i].p_offset == 0)
                                delta = phdr[i].p_vaddr;
                delta = (uint32_t)ehdr - delta;
                dyn = (Elf32_Dyn*)((char*)dyn + delta);
                assert(dyn != NULL);
                char *strtab = NULL;
                int soname = 0;
                while (dyn->d_tag != DT_NULL) {
                        if (dyn->d_tag == DT_STRTAB)
                                strtab = (char*)dyn->d_un.d_ptr;
                        else if (dyn->d_tag == DT_SONAME) 
                                soname = dyn->d_un.d_val;
                        dyn++;
                }
                assert(strtab != NULL && soname != 0);
                printf("%s\n", soname + strtab);
        }
}
Собственно, хрень нужна для поиска libc из инжектированного кода (даже базовый адрес процесса не известен). Имеются и ограничения - если процесс использует треды, то индекс libc TLS в DTV поменяется. Пока не придумал, как определить наверняка. Ну, или если тредов нет вообще, то тогда сами складывайте буквы А,Ж,П,О в нужном порядке.
Link Read Comments

Reply:
From:
(will be screened)
Identity URL: 
имя пользователя:    
Вы должны предварительно войти в LiveJournal.com
 
E-mail для ответов: 
Вы сможете оставлять комментарии, даже если не введете e-mail.
Но вы не сможете получать уведомления об ответах на ваши комментарии!
Внимание: на указанный адрес будет выслано подтверждение.
Username:
Password:
Subject:
No HTML allowed in subject
Message:



Notice! This user has turned on the option that logs IP addresses of anonymous posters.