-
Website
http://www.matasano.com/log -
Original page
http://www.matasano.com/log/1100/what-ive-been-doing-on-my-summer-vacation-or-it-has-to-work-otherwise-gdb-wouldnt/ -
Subscribe
All Comments -
Community
-
Top Commenters
-
Press Controls
3 comments · 2 points
-
ChrisMtso
12 comments · 1 points
-
Eric Monti
11 comments · 1 points
-
StatlerAndWaldorf
12 comments · 3 points
-
Dave G.
7 comments · 1 points
-
-
Popular Threads
See for instance and its followup .
In short, some process are (made) "untraceable" in Mac OS X.
Loic said, "Regarding your remark about iTunes in point 8, iTunes does not seem to interfere with DTrace (and ptrace(), truss, …), it actually interferes.
See for instance and its followup .
In short, some process are (made) “untraceable” in Mac OS X."
I think this may have to do with the PT_DENY_ATTACH problem, which I have run into numerous times now. See here: http://landonf.bikemonkey.org/code/macosx/ptrac...
See here: http://developer.apple.com/documentation/MacOSX...
Nate
The Mach "debugger interface" is much nicer than ptrace, though.
Outstanding work, and very good writing and commentary on it. Makes me want to poke around in OS X myself now.
Boss: "We have this spit-and-baling-wire router OS that needs some work."
Me: "Um... I just now learned what a socket is."
Boss: "Here's Ethereal. Go look at what such-and-such a thread is actually putting on the wire."
Me: "... Thread?"
Those were the days. Congrats on some worthy hacking, Timur!
Thomas is right on this one. OS X is the epitome of the phrase "Unix like OS." It has parts from Unix (mostly BSD), Mach, and some things pulled from Linux.
Secret Intern X had originally suggested a second "stealth" debugger for OS X written entirely in Mach system calls. In researching and implementing DebuggerX, I was unable to find a Mach replacement for PT_STEP. Also, as far as I could find there is no way to prevent the traced process from performing its default signal handling without attaching with ptrace. For the debugger to work the parent process has to handle the trap raised when the process hits the breakpoint.
http://www.matasano.com/log/628/rafal-wojtczuks...
(Of course, you have the conditional logic problem, and if you're stealth debugging you can't use ptrace to resolve it).
If I knew how that gdb/rosetta setup worked I'd be all over it.
I think the code I wrote would work to debug the process. However, you'd really be debugging Rosetta while it runs something else. Which would only work well if Rosetta doesn't call DENY_ATTACH.
My guess is that setup uses the Mac message ports to allow gdb to hook into Rosetta.
Definitely something I will look into more as I have time.
Also, kernel panic from userland, you say?
You're using just procmod privs?
grep -ri ptrace /usr/include :)
This was a poc I wrote a while ago, you might find it useful; it deals with thread_set_exception_ports().
I am running this sudo'd and as procmod. Leopard requires code to be signed or run as root to use task_for_pid().
Yes, kernel panic. I have a little more testing to narrow it down fully, though.
While I did see those exception port functions, I didn't wan to spend the time just yet to get them working through Ruby/DL. I seem to remember them requiring callback functions, which I'm still not sure how to setup from Ruby/DL.
As far as I was able to tell, the ptrace call you're thinking of that takes four arguments is a higher level wrapper for a Mach version of the function. Nate McFeters linked to an analysis of that function. The source code for it is located:
http://fxr.watson.org/fxr/source/bsd/kern/mach_...
Unfortunately, I was unable to find source code for the four argument version to verify this.
About the only way I can think to get around the PT_DENY_ATTACH problem from Ruby would be to overwrite the function in memory and fork a child to debug.
Or, installing the kernel extension linked above.
If you are going to Black Hat this year, try to find me or Tiller and David. I think that getting it all working with Rosetta is a bit more complicated then it seems, since they've struggled with it. Of course, who knows with Mac, it's like a black hole.
I agree with @Jesse, it would be desirable to have PT_DENY_ATTACH just handled by the debugger. There is kernel patches (I believe this is what I used) and of course there's the methods that @Snagg mentioned, but it would just be so nice to not have to deal with that at all. At a minimum, maybe mention of it in any release notes you put out once this thing is done. It's pretty simple to fix once you know it's the problem, but I banged my head against the wall for a bit.
If you guys are doing much Mac vuln research, you should really look into RE:Trace by David Weston and Tiller Beauchamp (see http://poppopret.org/). I've found it to be the most useful tool you can get.
-Nate
Funny thing is, I had heard of it long before, maybe even in an uninformed paper, but when I got to doing some research, totally forgot it, bashed my head against the wall for hours till I remembered.
-Nate
For Ruby you might also want to read "Inspecting a live Ruby process"!
http://weblog.jamisbuck.org/2006/9/22/inspectin...
I don't quite get what you mean by "Unfortunately, I was unable to find source code for the four argument version to verify this.". Anyhow yes, it is something like a "wrapper" but still not entirely done with Mach, for example single stepping is done by setting the trap flag in EFLAGS.
To be honest I'm not that much a ruby guru, but I guess you can set up callback function somehow.
As you may notice reading the code, PTRACE_DENY_ATTACH basically drop exceptions ports from the process. But you should be able to attach a new one, providing you're root. So I guess using exceptions ports is the only "clean" method to avoid DENY_ATTACH at runtime.
About died when I saw the use of such fowl language in a technical post... but after reading the post, I understand!
You were given a blit of a task and you didn't bloit it off!
I would love to work on that with you at Black Hat. Alas, I cannot attend this year.
I am, however, working toward a version that forks, calls TRACE_ME, then breaks on ptrace to jump past it. I'll let you know how it goes.
-Nate
Tell ecopeland that the next time he wants to publish something for a later date, he should not hit Publish before setting the future date (I'm sure it was an honest mistake). Stuff that goes through RSS stays cached on users' disks.
Therefore, I (along with probably thousands of other people) have the DNS vuln article. Very cool work. Point 5. really surprised me; I never knew DNS code for BIND and co. was so braindead as to not perform such a simple and urgently-needed sanity check. Sometimes it's easy to skimp on data structures and algorithms if you're going for the quick fix... sometimes one pays dearly because one didn't look beyond 1995.
-Nate
I managed to get the fork version to work and set a breakpoint in at ptrace before I running exec().
Didn't work, at least not after Kernel#exec was called. I had worried exec would completely create a new environment for the new process. I was right. I'm going to look into exaclty what gdb is doing in that case. It seems like it can't really be using exactly the fork/exec model.
Perhaps it's manipulating its own child process instead of using exec.
I'll be at Chisec wednesday if you'd like to discuss this in person.
http://fusil.hachoir.org/trac/wiki/Ptrace
It's not only a ptrace binding: it also contains a basic debugger similar to gdb but writing only in Python, and strace.py: system call tracer with argument parser/formatter.
The problem with a debugger is that you have to change constants for each OS/CPU. So I use different methods to get registers, read process memory, etc.
ptrace/binding/func.py and ptrace/debugger/process.py are the most interesting files.
Sometimes I just don't get you [Matasano in general] and your [Matasano's] apparent hatred for this language.
There's a zillion great reasons to have a debugger in a high level language, starting with "you can write a special-purpose debugger for a new project in 5-10 minutes".
This debugger also will debug any process, not just those written in C.
The C functions were wrapped because they are what the OS uses and were the most accessible. Many of the functions in this ruby object were tested in a small C program as well since I was having problems getting the Ruby to work and there is little written about some of the calls.
I don't know that much Python, so I could be wrong here.
One thing you could do to get around having a specialized object per platform would be to build a core object and add to is by selectively loading files based on architecture and OS.
That way on the user's end all they have to do is say they want a debugger object and the code does the heavy lifting to determine what that object needs to look like.
@Jesse
Yesterday, I was able to figure out my fork and exec approach did, in fact, work. I managed to successfully break on ptrace and return immediately from it. The current method skips all ptrace calls by the child so it still needs some work.
This was a fascinating post. I hope you'll have time to document your next interesting project that you learn a bunch on, that's always the most fun stuff to read.
@Thomas
I'm a total n00b when it comes to some of this stuff, static analysis, etc. Can you expand more on why you would want a purpose-written debugger for a binary? I was under the impression that debuggers kind of all did the same thing...I'm guessing that's not the case. Could you explain further what you mean and why it's advantageous to do in Ruby (really, what kind of things can you do now that it is templated out in a high-level easy to write language)?
Cool, good work. It's probably rare that a typical application will call ptrace() for anything other than PTRACE_DENY_ATTACH, so blindly returning instantly will probably be sufficient...but for completeness, it would be good to verify.
You should take a look at nemo's paper from uninformed if you haven't already, he's got a lot of info you might find interesting.
Does anyone know if a process can undo a PT_DENY_ATTACH request that it has made previously?