admin 管理员组

文章数量: 1087675

I'm trying to load a shared library (controller process) into another process (target) using ptrace.

NOTE: Both the controller and target are using the same version of libc. /usr/lib/libc.so.6

I'm doing the following:

  1. Finding the dlopen address in libc in the target process - Placing this in register r8.
  2. Copying the name of the library into a memory location using ptrace POKEDATA. Setting this address in rdi.
  3. Settingthe mode as 2 in rsi register.
  4. I'm setting the rip to a location where I've placed the following code - trampCodeAddr in this example - See point 5.
  asm(
      "nop \n"
      "nop \n"
      "nop \n"
      "nop \n"
      "nop \n"
      "nop \n"
      "nop \n"
      "nop \n"
      "callq *%r8 \n"
      "int $3"
   );

This is what gets written into the memory:

Writing: 0x9090909090909090 to 0x401400
Writing: 0x1f0fc3ccd0ff41 to 0x401408
  1. At this point, I'm setting these registers using the ptrace SETREGS.
   regs.r8 = targetdlopenAddr;
   regs.rdi = libNameBuf;
   regs.rsi = 2; // RTLD_NOW
   regs.rip = trampCodeAddr + 2;
   status = ptraceWriteRegs(targetPid, &regs);

When I issue a ptrace continue, and then check the signal info, I see the signal number is set to 11. SIGSEGV.

But, when I read the registers, I've an address in rax, and when I do check /proc/<pid>/maps, I see the .so loaded.

I'm expecting a SIGTRAP, and not a SIGSEGV.

What could be going on here?

I tried the same method to call malloc. But, in that case, I'm getting a SIGTRAP as expected. What could be going wrong with dlopen()? Is there any other register which could be giving me more info?

Thanks for your time.

EDIT 1: The data I set in the registers seem fine to me: (One instance, for example): r8 : 7f92c5885d00 rdi: 401420 rsi:0x2 rip:0x401402

rdi points to a null terminated string:

Writing: 0x63656a6e6962696c to 0x401420
Writing: 0x6f6c6c6568646574 to 0x401428
Writing: 0x6a6e490a006f732e to 0x401430

/proc//maps output in this instance:

7f92c5800000-7f92c5828000 r--p 00000000 fd:00 68452742                   /usr/lib64/libc.so.6
7f92c5828000-7f92c599d000 r-xp 00028000 fd:00 68452742                   /usr/lib64/libc.so.6
7f92c599d000-7f92c59f5000 r--p 0019d000 fd:00 68452742                   /usr/lib64/libc.so.6
7f92c59f5000-7f92c59f6000 ---p 001f5000 fd:00 68452742                   /usr/lib64/libc.so.6
7f92c59f6000-7f92c59fa000 r--p 001f5000 fd:00 68452742                   /usr/lib64/libc.so.6
7f92c59fa000-7f92c59fc000 rw-p 001f9000 fd:00 68452742                   /usr/lib64/libc.so.6

EDIT 2: Updated point number 4 with the actual code and what gets written.

When I get the control back to the controller program, the rip is 0x7ffff7fcee95. This should have been 0x40140c. That is what I see after my malloc returns successfully. For some reason, the call to dlopen goes wild.

I checked that I'm writing the correct dlopen address in r8 before callq *%r8 is called.

EDIT 3: When ptrace gets the SIGSEGV, the RIP has 0x7f9e88bf0e95. At this time, the maps has:

7f9e88beb000-7f9e88c11000 r-xp 00002000 fd:00 68452740                   /usr/lib64/ld-linux-x86-64.so.2

So, the offset is 0x%5e95.

This seems to be in the open_path. How do I narrow it down further?

EDIT 4: I sent a SIGSTOP to the target just before I know where it would crash. Then continued in GDB. This is the stacktrace I got:

(gdb) bt
#0  _dl_map_object_from_fd (name=name@entry=0x401420 "/tmp/satish/libinjectedhello.so", origname=origname@entry=0x0, fd=-1, fbp=fbp@entry=0x7ffc73974008, realname=<optimized out>, 
    loader=loader@entry=0x0, l_type=<optimized out>, mode=<optimized out>, stack_endp=<optimized out>, nsid=<optimized out>) at dl-load.c:1431
#1  0x00007f9f5e2b689f in _dl_map_object (loader=0x0, loader@entry=0x7f9f5e2e5220, name=name@entry=0x401420 "/tmp/satish/libinjectedhello.so", type=type@entry=2, 
    trace_mode=trace_mode@entry=0, mode=mode@entry=-1879048190, nsid=<optimized out>) at dl-load.c:2286
#2  0x00007f9f5e2ba3ba in dl_open_worker_begin (a=0x7ffc739746c8) at dl-open.c:577
#3  0x00007f9f5e156148 in _dl_catch_exception () from /lib64/libc.so.6
#4  0x00007f9f5e2b9afa in dl_open_worker (a=0x7ffc739746c8) at dl-open.c:796
#5  0x00007f9f5e156148 in _dl_catch_exception () from /lib64/libc.so.6
#6  0x00007f9f5e2b9f5f in _dl_open (file=<optimized out>, mode=-2147483646, caller_dlopen=0x401405, nsid=-2, argc=1, argv=0x7ffc73974af8, env=0x7ffc73974b08) at dl-open.c:898
#7  0x00007f9f5e085cbc in dlopen_doit () from /lib64/libc.so.6
#8  0x00007f9f5e156148 in _dl_catch_exception () from /lib64/libc.so.6
#9  0x00007f9f5e156213 in _dl_catch_error () from /lib64/libc.so.6
#10 0x00007f9f5e08578e in _dlerror_run () from /lib64/libc.so.6
#11 0x00007f9f5e085d71 in dlopen@GLIBC_2.2.5 () from /lib64/libc.so.6
#12 0x0000000000401405 in ?? ()
#13 0x00007f9f5e0d8c87 in nanosleep () from /lib64/libc.so.6
#14 0x00007f9f5e0d8bbe in sleep () from /lib64/libc.so.6
#15 0x000000000040124f in main ()

本文标签: assemblyCalling dlopen by setting the registers using ptrace throws SIGSEGVIntel 64Stack Overflow