001 ###########################################
002 package WriteTracer;
003 use strict;
004 use POSIX;
005 use Inline "C";
006 use Fcntl;
007
008 use Sys::Ptrace qw(ptrace
009 PTRACE_SYSCALL PTRACE_TRACEME);
010
011 ###########################################
012 sub run {
013 ###########################################
014 my($prg, @params) = @_;
015
016 my @files = ();
017 my %files = ();
018
019 if((my $pid = fork()) < 0) {
020 die "fork failed";
021
022 } elsif($pid == 0) {
023 # child
024 ptrace(PTRACE_TRACEME, $$, 0, 0);
025 exec($prg, @params);
026
027 } else {
028 # parent
029 {
030 my $rc = waitpid($pid, 0);
031 last if $rc < 0;
032
033 if( WIFSTOPPED($?) ) {
034 my($eax, $orig_eax, $ebx, $ecx,
035 $edx) = ptrace_getregs($pid);
036
037 if($eax == -ENOSYS()) {
038 if($orig_eax == 5 and
039 $ecx & O_WRONLY) {
040 my $str = ptrace_string_read(
041 $pid, $ebx);
042 push @files, $str
043 unless $files{$str}++;
044 }
045 }
046
047 ptrace(PTRACE_SYSCALL, $pid,
048 undef, undef);
049 redo;
050 }
051 }
052 }
053 return @files;
054 }
055
056 1;
057
058 __DATA__
059 __C__
060 #include <sys/ptrace.h>
061 #include <asm/user.h>
062
063 #define IVPUSH(x) Inline_Stack_Push( \
064 sv_2mortal(newSViv(x)));
065
066 /* ------------------------------------- */
067 void ptrace_getregs(int pid) {
068 int rc;
069 struct user_regs_struct registers;
070 Inline_Stack_Vars;
071
072 rc = ptrace(PTRACE_GETREGS, pid,
073 0, ®isters);
074 if(rc == -1) {
075 return;
076 }
077
078 if( registers.eax == -ENOSYS ) {
079 Inline_Stack_Reset;
080 IVPUSH(registers.eax);
081 IVPUSH(registers.orig_eax);
082 IVPUSH(registers.ebx);
083 IVPUSH(registers.ecx);
084 IVPUSH(registers.edx);
085 Inline_Stack_Done;
086 }
087 }
088
089 /* ------------------------------------- */
090 int ptrace_aligned_word_read_c(int pid,
091 void *addr, char *buf, int *len) {
092 char *aligned_addr;
093 long word;
094 void *ptr;
095
096 aligned_addr = (char *) (
097 (long)addr & ~ (sizeof(long) - 1) );
098
099 word = ptrace(PTRACE_PEEKDATA, pid,
100 aligned_addr, NULL);
101
102 if(word == -1) {
103 return -1;
104 }
105
106 *len = sizeof(long) - ( (long) addr -
107 (long) aligned_addr );
108 ptr = &word;
109 ptr += (sizeof(long) - *len);
110 memcpy(buf, ptr, *len);
111
112 return 0;
113 }
114
115 /* ------------------------------------- */
116 void ptrace_string_read(int pid,
117 void *addr) {
118 char word_buf[ sizeof(long) ];
119 int word_len;
120 SV *pv;
121 int rc;
122 int i;
123 Inline_Stack_Vars;
124
125 pv = newSVpv((const char *)"", 0);
126
127 while(1) {
128 rc = ptrace_aligned_word_read_c(pid,
129 addr, word_buf, &word_len);
130 if(rc < 0) {
131 return;
132 }
133
134 for(i=0; i<word_len; i++) {
135 if(word_buf[i] == '\0') {
136 goto FINISH;
137 }
138 sv_catpvn(pv, (const char *)
139 &word_buf[i], 1);
140 }
141 addr += word_len;
142 }
143
144 FINISH:
145 Inline_Stack_Reset;
146 Inline_Stack_Push(sv_2mortal(pv));
147 Inline_Stack_Done;
148 }