Как получить char* с помощью ptrace

В настоящее время я разрабатываю инструмент, в котором я должен отслеживать программу, чтобы узнать ее системные вызовы. На данный момент я могу получить числовые параметры системных вызовов, но я не могу правильно адресовать строки.

Вот как я поступаю:

  long addr = ptrace(PTRACE_PEEKDATA, pid, regs.ebx, NULL);
  printf("%s", (char *) &addr);

С помощью этого фрагмента кода я могу получить начало строки (3 или 4 первых символа), но конец поврежден, не знаю почему.

У вас есть какое-нибудь решение? Спасибо.


person Jeffrey Muller    schedule 30.04.2012    source источник
comment
@Jeffey Muller: Вы пытаетесь зафиксировать аргументы определенного системного вызова, верно? Я создал аналогичное приложение, похожее на strace, но работающее с меньшим количеством системных вызовов.   -  person kidd0    schedule 09.05.2012


Ответы (3)


Вы уверены, что не хотите этого вместо этого?

printf("%lX", addr);

person Šimon Tóth    schedule 30.04.2012
comment
Я хотел бы печатать строки буквально. Например, если двоичный файл tracee выполняет write(1, hello world, 14) , я хотел бы получить строку hello world, а не адрес. - person Jeffrey Muller; 30.04.2012
comment
@JeffreyMuller Хорошо, но код, который вы написали, не имеет особого смысла, либо вы получаете адрес строки, и в этом случае вы должны отследить этот адрес, либо вы получаете часть строки, и в этом случае вы нужно пройти через строку, используя ptrace, пока вы не прочитаете ее полностью. - person Šimon Tóth; 30.04.2012
comment
В regs.ebx, кажется, у меня есть адрес строки. Поэтому я использую PTRACE_PEEKDATA, чтобы получить данные, указанные ebx, но адрес, который мне дал ptrace, не подходит. Это ошибка сегментации. Вот пример: pastebin.com/p3rdCXDV - person Jeffrey Muller; 30.04.2012
comment
@JeffreyMuller ptrace возвращает данные, а не адрес, прочитайте справочную страницу, в частности раздел для PTRACE_PEEKDATA. - person Šimon Tóth; 01.05.2012

char *read_string (int child, unsigned long addr) {
    char *val = malloc(4096);
    if (!val)
        return NULL;

    int allocated = 4096, read = 0;
    unsigned long tmp =0;
    while(1) {
        if (read + sizeof (tmp) > allocated) {
            allocated *= 2;
            char *temp_val = realloc (val, allocated);
            if (!temp_val) {
                free(val);
                return NULL;
            }
            val = temp_val;
        }
        tmp = ptrace(PTRACE_PEEKDATA, child, addr + read);
        if(errno != 0) {
            val[read] = 0;
            break;
        }
        memcpy(val + read, &tmp, sizeof tmp);
        if (memchr(&tmp, 0, sizeof tmp) != NULL) break;
        read += sizeof tmp;
    }
    return val;
} // Don't forget to free the returned val.

Попробуйте использовать следующую функцию, она была частью того, что я написал в своем приложении:

reg_val[1] = ptrace (PTRACE_PEEKUSER, child, 4 * EBX, NULL);
char *filepath = read_string(child, reg_val[1]);

Ребенок — это pid дочернего процесса, который я отслеживаю. Если это не работает, скажите мне?

person kidd0    schedule 09.05.2012

С вашим опубликованным кодом вы читаете только 4 байта данных (т.е. 4 символа) при вызове ptrace. Вам нужно прочитать весь буфер из процесса отладки, прежде чем вы сможете распечатать строку в родительском процессе. т. е. после того, как вы прочитали адрес, вам нужно зациклиться

   ptrace(PTRACE_PEEKTEXT, child, addr, NULL)
   addr+=4;

пока не прочитаешь всю строку.

Затем вы можете распечатать его с помощью printf()

person anon    schedule 15.05.2012