อ่านสแต็คของกระบวนการอื่นได้หรือไม่


16

ฉันพยายามอ่านสแต็กของกระบวนการลูก แต่ไม่มีโชค ฉันรู้ว่ามันเป็นไปได้ที่จะใช้ptraceแต่ptraceอินเทอร์เฟซของอนุญาตให้คุณอ่านเพียงหนึ่งคำในแต่ละครั้งและฉันพยายามสแกนส่วนที่ใหญ่กว่าของสแต็ก

ฉันได้ลองอ่าน/proc/$pid/memจากขอบเขตของสแต็คที่แยกออกมาจาก/proc/$pid/mapsไฟล์หลังจากใช้ ptrace เพื่อเชื่อมต่อกับมันเป็นครั้งแรก (ตามที่แนะนำไว้ที่นี่ ) แต่การอ่านทำให้ล้มเหลว (แม้ในขณะทำงานในฐานะรูท) อ่านจากส่วนต่าง ๆ ของกระบวนการ (เช่นกอง)

ผมทำอะไรผิดหรือเปล่า? มีตัวเลือกอื่น ๆ อีกไหม?


คุณโทรwaitpidระหว่างptrace(PTRACE_ATTACH,…)และread(มิฉะนั้นจะมีเงื่อนไขการแข่งขันที่เป็นไปได้)? เกิดข้อผิดพลาดreadอะไรขึ้น เด็ก ๆ ทำอะไรแปลก ๆ ด้วยการแม็ปหน่วยความจำ - คุณลองใช้โค้ดกับเด็กง่าย ๆ ได้sleepไหม?
Gilles 'หยุดชั่วร้าย'

ฉันใช้รอหลังจาก ptrace และฉันวาง scanf ไว้ในเด็กเพื่อบังคับให้รอ
user4537

นี่สำหรับ Linux เท่านั้นหรือ โซลาริสยังมีระบบไฟล์ / proc แต่มันแตกต่างจาก Linux อย่างสิ้นเชิง "ไบนารีไฟล์" มากมาย
Bruce Ediger

เพียงทำระบบ ("pstack pid ") และแยกวิเคราะห์ผลลัพธ์ ..
vrdhn

ดูps: คำสั่งแบบเต็มยาวเกินไปสำหรับบางตัวอย่าง
Stéphane Chazelas

คำตอบ:


5

ptraceอินเทอร์เฟซของอนุญาตให้คุณอ่านทีละหนึ่งคำเท่านั้นและฉันพยายามสแกนส่วนที่ใหญ่กว่าของสแต็ก

ก็แค่ใช้วงวนแล้ว ฉันไม่เห็นวิธีการที่ก่อให้เกิดปัญหาโดยสุจริตptraceฉันใช้มันตลอดเวลาเพื่อเข้าถึงกระบวนการจากระยะไกล

ฉันใช้สิ่งนี้:

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;
}

สวัสดีแซมในขณะที่รหัสของคุณจะทำ (และที่จริงแล้วคือสิ่งที่ฉันกำลังทำอยู่) แต่ก็มีค่าใช้จ่ายที่มีประสิทธิภาพสูง
4537

@ user4536: ฉันเห็น ฉันมีกลยุทธ์อื่นในใจที่ฉันจะโพสต์เกี่ยวกับเมื่อฉันมีเวลาเขียนมันลง ขนาดสแต็กทั่วไปของคุณคืออะไร
sam hocevar

เป็นการยากที่จะพูดจริง ๆ เพราะงานวิจัยของฉันไม่ได้กำหนดขนาดสแต็กเฉพาะ แต่เพื่อเหตุผลของข้อโต้แย้งนี้สมมติว่าอย่างน้อยสองหน้ายาวคุณช่วยบอกใบ้ถึงกลยุทธ์ของคุณได้ไหม? ขอบคุณสำหรับความช่วยเหลือต่อไป!
user4537

1

นี่คือกลยุทธ์อื่นที่อาจต้องมีการปรับแต่ง แต่ควรมีประสิทธิภาพมากขึ้นด้วยข้อมูลจำนวนมาก แนวคิดคือการเรียกใช้ syscalls ในกระบวนการรีโมตเพื่อดึงเนื้อหาสแต็ก มันจะต้องมีรหัสสถาปัตยกรรมที่เฉพาะเจาะจง แต่ถ้าคุณกำหนดเป้าหมายเฉพาะ x86 / x86_64 มันไม่ควรจะยุ่งยากมากเกินไป

  1. สร้างไปป์ที่มีชื่อเช่น"/tmp/fifo"ในกระบวนการโทรของคุณ
  2. เข้าสู่กระบวนการติดตามจนกว่ามันจะส่งคืนจาก syscall โดยใช้PTRACE_SYSCALLเป็นขั้นตอนwaitpid()เพื่อรอและPTRACE_GETREGS/ PTRACE_PEEKTEXTเพื่อตรวจสอบ opcode ที่ดำเนินการในปัจจุบัน
  3. สำรองข้อมูลรีจิสเตอร์กระบวนการรีโมตและพื้นที่เล็ก ๆ ของสแต็ก
  4. ดำเนินการ syscalls เกี่ยวกับกระบวนการระยะไกลโดยเอาชนะกองกับข้อมูลของคุณเอง: open("/tmp/fifo"), write()เนื้อหากองclose()อธิบาย
  5. กู้คืนสถานะของกระบวนการรีโมต
  6. อ่านข้อมูล Fifo จากกระบวนการโทรของคุณ

อาจมีทางเลือกที่ไพเราะกว่าไพพ์ที่มีชื่อ แต่ฉันไม่สามารถนึกถึงตอนนี้ได้ เหตุผลที่ฉันใช้ syscalls ก็เพราะว่าการฉีดรหัสระยะไกลนั้นไม่น่าเชื่อถือในระบบที่ทันสมัยเนื่องจากการป้องกันความปลอดภัยที่หลากหลาย ข้อเสียเปรียบคือมันจะหยุดทำงานจนกว่ากระบวนการรีโมตจะใช้ syscall (ซึ่งอาจเป็นปัญหาสำหรับบางโปรแกรมที่ส่วนใหญ่ทำการคำนวณ)

คุณสามารถเห็นรหัสฟรีบางส่วนที่ใช้งานส่วนใหญ่ในไฟล์ต้นฉบับนี้ ข้อเสนอแนะเกี่ยวกับรหัสยินดีต้อนรับ!


1

ข้อเสนอแนะอื่น

เมื่อ / หากได้รับการยอมรับในต้นไม้เคอร์เนลหลักคุณจะสามารถใช้แพทช์Cross Memory Attachของ Christopher Yeoh ได้ ดูเอกสารประกอบสำหรับprocess_vm_readvตัวอย่างเช่น


1

คุณสามารถอ่านสแต็คของกระบวนการอื่นได้อย่างง่ายดายโดยใช้ระบบไฟล์ proc (คุณจะต้องเข้าถึงรูทสำหรับสิ่งนี้) ก่อนที่จะอ่านจาก / proc / pid / mem โดยพลการคุณต้องปรึกษา / proc / pid / maps การอ่านไฟล์นี้อย่างง่ายจะแสดงรายการจำนวนมาก เราสนใจรายการที่ทำเครื่องหมายว่าเป็นสแต็ก เมื่อคุณได้รับสิ่งนี้คุณจะต้องอ่านขอบเขตด้านล่างและด้านบนของสแต็ก ตอนนี้เพียงแค่เปิดไฟล์ / proc / pid / mem หาขอบเขตที่ด้านล่างของสแต็กและอ่านขนาดที่ถูกต้องของข้อมูล


1
คุณแน่ใจว่าคุณหมายถึงmemsและไม่ได้maps? (ฉันไม่เห็นmemsรายการใด ๆภายใต้/procระบบไฟล์ของฉัน) OP ได้กล่าวถึงการอ่านขอบเขตสแต็กจาก/proc/$pid/maps- คุณแนะนำให้พวกเขาทำอะไรแตกต่างกันอย่างไร
JigglyNaga

แก้ไขการพิมพ์ผิด ฉันทำสิ่งที่ฉันพูดถึงในคำตอบของฉันและทิ้งข้อมูลสแต็ก 132 KBs เราต้องการข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ OP ทำผิด บางที OP สามารถแชร์รหัสที่เขาใช้เพื่ออ่านขอบเขตสแต็ก หากเขาไม่ตอบฉันจะแบ่งปันของฉัน
Ajay Brahmakshatriya

0

คุณอาจจะลองlsstack มันใช้ ptrace เช่นเดียวกับโปรแกรม "read stack ของกระบวนการอื่น" ที่ประสบความสำเร็จ ฉันไม่สามารถรับโปรแกรมโดยใช้ / proc / $ pid / mem การอ่านเพื่อใช้งาน ฉันเชื่อว่าคุณไม่สามารถทำเช่นนั้นได้แม้ว่าคุณจะมีเหตุผล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.