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 061 #include 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