Đọc chồng của quá trình khác?


16

Tôi đang cố đọc ngăn xếp của một quá trình con nhưng không có may mắn. Tôi biết có thể sử dụng ptrace, nhưng ptracegiao diện của nó cho phép bạn chỉ đọc một từ một lần và tôi đang cố quét một phần lớn hơn của ngăn xếp.

Tôi cũng đã thử đọc /proc/$pid/memtừ các ràng buộc của ngăn xếp như được trích xuất từ /proc/$pid/mapstệp sau lần đầu tiên sử dụng ptrace để đính kèm với nó (như được đề xuất ở đây ) nhưng việc đọc vẫn không thành công (ngay cả khi chạy bằng root) mặc dù cùng một mã đã thành công khi thử đọc từ các phần khác nhau của quá trình (ví dụ heap).

Tôi đang làm gì sai? Có lựa chọn nào khác?


Bạn đã gọi waitpidgiữa ptrace(PTRACE_ATTACH,…)read(nếu không có một điều kiện cuộc đua có thể)? Lỗi gì readtrở lại? Có phải đứa trẻ đang làm bất cứ điều gì đặc biệt với ánh xạ bộ nhớ của nó - bạn có thể thử mã của mình với một đứa trẻ đơn giản như thế sleepnào không?
Gilles 'SO- ngừng trở nên xấu xa'

Tôi đã sử dụng chờ đợi sau ptrace và tôi đã đặt một scanf vào đứa trẻ để buộc nó phải chờ.
dùng4537

Đây chỉ là trên Linux? Solaris cũng có hệ thống tập tin / Proc, nhưng nó hoàn toàn khác với Linux, về mặt triết học. Rất nhiều "tệp nhị phân".
Bruce Ediger

chỉ cần làm một hệ thống ("pstack pid ") và phân tích đầu ra ..
vrdhn

Xem ps: lệnh đầy đủ quá dài đối với một số ví dụ
Stéphane Chazelas

Câu trả lời:


5

ptraceGiao diện cho phép bạn chỉ đọc một từ một lần và tôi đang cố quét một phần lớn hơn của ngăn xếp

Vâng, chỉ cần sử dụng một vòng lặp, sau đó. Thành thật tôi không thấy vấn đề đó cấu thành vấn đề như thế nào ptrace, tôi luôn sử dụng nó để truy cập các quy trình từ xa.

Tôi sử dụng một cái gì đó như thế này:

static int memcpy_from_target(pid_t pid, char *dest, long src, size_t n)
{
    static int const align = sizeof(long) - 1;

    while (n)
    {
        size_t todo = MIN(n, sizeof(long) - (src & align));
        long data = ptrace(PTRACE_PEEKTEXT, pid, src - (src & align), 0);
        if (errno)
        {
            perror("ptrace_peektext (memcpy_from_target)");
            return -1;
        }
        memcpy(dest, (char *)&data + (src & align), todo);

        dest += todo; src += todo; n -= todo;
    }

    return 0;
}

Xin chào Sam, trong khi mã của bạn sẽ làm (và thực tế đó là những gì tôi hiện đang làm), nó có hiệu năng lớn.
dùng4537

@ user4536: Tôi hiểu rồi. Tôi có một chiến lược khác trong tâm trí mà tôi sẽ đăng khi tôi có thời gian viết nó xuống. Kích thước ngăn xếp điển hình của bạn là gì?
sam hocevar

Thật khó để nói thực sự vì nghiên cứu của tôi không giả định kích thước ngăn xếp cụ thể, nhưng vì lý do của cuộc tranh luận này, hãy nói ít nhất một vài trang dài Bạn có thể bỏ một gợi ý về chiến lược của mình không? Cảm ơn sự giúp đỡ!
dùng4537

1

Đây là một chiến lược khác có thể cần điều chỉnh nhưng sẽ hiệu quả hơn với khối dữ liệu lớn. Ý tưởng là thực thi các tòa nhà trong quy trình từ xa để lấy nội dung ngăn xếp. Nó sẽ cần mã kiến ​​trúc cụ thể nhưng nếu bạn chỉ nhắm mục tiêu x86 / x86_64 thì điều đó không quá rắc rối.

  1. Tạo một đường ống có tên như "/tmp/fifo"trong quá trình gọi điện của bạn.
  2. Bước vào quy trình theo dõi cho đến khi nó trở về từ một tòa nhà, sử dụng PTRACE_SYSCALLđể bước, waitpid()để chờ và PTRACE_GETREGS/ PTRACE_PEEKTEXTđể kiểm tra opcode hiện được thực thi.
  3. Sao lưu các thanh ghi của tiến trình từ xa và một vùng nhỏ trong ngăn xếp của nó.
  4. Thực thi các tòa nhà trên quy trình từ xa bằng cách ghi đè ngăn xếp của nó bằng dữ liệu của riêng bạn : open("/tmp/fifo"), write()nội dung ngăn xếp, close()bộ mô tả.
  5. Khôi phục trạng thái của quá trình từ xa.
  6. Đọc dữ liệu fifo từ quá trình gọi điện của bạn.

Có thể có những lựa chọn thay thế thanh lịch hơn cho đường ống được đặt tên, nhưng tôi không thể nghĩ ra bất kỳ điều gì ngay bây giờ. Lý do tôi chỉ sử dụng các tòa nhà chọc trời là vì việc tiêm mã từ xa khá không đáng tin cậy trên các hệ thống hiện đại do các biện pháp bảo vệ khác nhau. Hạn chế là nó sẽ bị treo cho đến khi quá trình từ xa thực hiện một tòa nhà (có thể là một vấn đề đối với một số chương trình chủ yếu là tính toán).

Bạn có thể thấy một số mã miễn phí thực hiện hầu hết các công việc trong tệp nguồn này . Phản hồi về mã được chào đón!



1

Bạn có thể dễ dàng đọc ngăn xếp của một quá trình khác bằng hệ thống tệp Proc (Bạn sẽ cần quyền truy cập root cho việc này). Trước khi tự ý đọc từ / Proc / pid / mem, bạn cần tham khảo / Proc / pid / maps. Một đọc đơn giản trong tập tin này cho thấy rất nhiều mục. Chúng tôi quan tâm đến các mục được đánh dấu là ngăn xếp. Một khi bạn nhận được điều này, bạn cần đọc giới hạn dưới và trên của ngăn xếp. Bây giờ chỉ cần mở tệp / Proc / pid / mem, tìm đến giới hạn dưới của ngăn xếp và đọc kích thước chính xác của dữ liệu.


1
Bạn có chắc là bạn có ý nghĩa memshay không maps? (Tôi không thể thấy bất kỳ memsmục nào trong /prochệ thống tệp của mình .) OP đã đề cập đến việc đọc ranh giới ngăn xếp từ /proc/$pid/maps- bạn đang đề nghị họ làm gì khác nhau?
JigglyNaga

Chỉnh sửa lỗi đánh máy. Tôi đã làm chính xác những gì tôi đã đề cập trong câu trả lời của mình và nó đã đổ 132 KB dữ liệu ngăn xếp. Chúng tôi cần thêm thông tin về những gì OP đã làm sai. Có lẽ OP có thể chia sẻ mã mà anh ta đã sử dụng để đọc ranh giới ngăn xếp. Nếu anh ấy không trả lời, tôi sẽ chia sẻ của tôi.
Ajay Brahmakshatriya

0

Bạn có thể thử lsstack . Nó sử dụng ptrace, giống như mọi chương trình "đọc ngăn xếp quá trình" thành công khác. Tôi không thể có được một chương trình sử dụng / Proc / $ pid / mem đọc để làm việc. Tôi tin rằng bạn không thể làm theo cách đó, mặc dù, về mặt logic, bạn nên làm.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.