ptrace
August 8th, 2004, 19:58
Hi all, my first post here. After doing a search and reading through the few posts on interlok that are here (the only real usefull info on the whole net actaully) I thought I would post some of my findings reguarding the v5 interlok protection running on OS X.
First things first, as per usual, there is a piece of anti-debugging code playing around with gdb, a nice suprise though is its monumentally simple, which is why I got past this part so quickly. It is done with the ptrace() function, this can be used in linux too, but what is passed to the function differs. Here is a small piece of code illustrating it.
when this is compiled and run from the shell, it works just fine
./ad
Hello
when you attempt to load it into gdb you get this (notice no Hello)
(gdb) r
Starting program: ad
Reading symbols for shared libraries . done
Program exited with code 055.
simple enough, so all that was needed to bypass the anti-debugging in the target was to patch the args passed to ptrace to something benign. For example;
0x00001d64 <main+28>: li r3,31
0x00001d68 <main+32>: li r4,-1
0x00001d6c <main+36>: li r5,0
0x00001d70 <main+40>: li r6,-1
0x00001d74 <main+44>: bl 0x1f3c <dyld_stub_ptrace>
A quick look at /usr/include/sys/ptrace.h shows the various other values that one can use. The bytes for the above args are this
3860001f
3880ffff
38a00000
38c0ffff
So all thats needed is to swap out 3860001f (li r3,31) with 38600001 (li r3,1).
on a side note, A poke into /darwinsource/Current/xnu-517.3.7/bsd/kern/mach_process.c will show you what the call to ptrace actually does.
Ok now that the debugger is functional there is something of use. I esentially am going into interlok completely blind, I have no past experience with it and have no idea how it does its thing (yet).
From what I can tell, the specific target im playing with still uses the older CFM/PEF executable format, ie. code fragments like in OS9/8 and after some exploration it seems that interlok builds dynamic stub tables at run time. Incidentally using ptrace() as a breakpoint to get into the interlok code is very usefull FYI. At this point im still clueless as to what the kernel extention PACESupport.kext does, allthough im guessing its decryption (for PC people, PACESupport.kext should be on par with Tpkd.sys). I fired up a little utility called PEFViewer and was able to see a fair amount of the unencrypted pace code inside the target (which will remain nameless for the time being).
I did some tracing for awhile and stumbled upon what I think is the spot where code is either called after its decrypted, or something along those lines, but still cant quite visualize the whole picture of how interlok is working (v5 on PPC) in my head, so if anyone has anything at all they can add or suggest it would be great! documentation, experience from the PC side, whatever. Naturally if I find out anythign else I'll post it.
ptrace
First things first, as per usual, there is a piece of anti-debugging code playing around with gdb, a nice suprise though is its monumentally simple, which is why I got past this part so quickly. It is done with the ptrace() function, this can be used in linux too, but what is passed to the function differs. Here is a small piece of code illustrating it.
Code:
#include <sys/types.h>
#include <sys/ptrace.h>
int main()
{
ptrace(PT_DENY_ATTACH,-1,0,-1);
printf("Hello\n";
return 0;
}
when this is compiled and run from the shell, it works just fine
./ad
Hello
when you attempt to load it into gdb you get this (notice no Hello)
(gdb) r
Starting program: ad
Reading symbols for shared libraries . done
Program exited with code 055.
simple enough, so all that was needed to bypass the anti-debugging in the target was to patch the args passed to ptrace to something benign. For example;
0x00001d64 <main+28>: li r3,31
0x00001d68 <main+32>: li r4,-1
0x00001d6c <main+36>: li r5,0
0x00001d70 <main+40>: li r6,-1
0x00001d74 <main+44>: bl 0x1f3c <dyld_stub_ptrace>
A quick look at /usr/include/sys/ptrace.h shows the various other values that one can use. The bytes for the above args are this
3860001f
3880ffff
38a00000
38c0ffff
So all thats needed is to swap out 3860001f (li r3,31) with 38600001 (li r3,1).
on a side note, A poke into /darwinsource/Current/xnu-517.3.7/bsd/kern/mach_process.c will show you what the call to ptrace actually does.
Ok now that the debugger is functional there is something of use. I esentially am going into interlok completely blind, I have no past experience with it and have no idea how it does its thing (yet).
From what I can tell, the specific target im playing with still uses the older CFM/PEF executable format, ie. code fragments like in OS9/8 and after some exploration it seems that interlok builds dynamic stub tables at run time. Incidentally using ptrace() as a breakpoint to get into the interlok code is very usefull FYI. At this point im still clueless as to what the kernel extention PACESupport.kext does, allthough im guessing its decryption (for PC people, PACESupport.kext should be on par with Tpkd.sys). I fired up a little utility called PEFViewer and was able to see a fair amount of the unencrypted pace code inside the target (which will remain nameless for the time being).
I did some tracing for awhile and stumbled upon what I think is the spot where code is either called after its decrypted, or something along those lines, but still cant quite visualize the whole picture of how interlok is working (v5 on PPC) in my head, so if anyone has anything at all they can add or suggest it would be great! documentation, experience from the PC side, whatever. Naturally if I find out anythign else I'll post it.
ptrace