/ OSX / libsecurity_codesigning / dtrace / codesign-watch.d
codesign-watch.d
  1  #!/usr/sbin/dtrace -q -s
  2  /*
  3   * Demonstration D script for watching Code Signing activity in the system
  4   *
  5   * As presented, this script will record and report all Code Signing activity
  6   * in one process (argument=pid), or all processes (argument='*').
  7   * You are encouraged to modify it as you will. (A good start is to comment out
  8   * the print statements you don't like to see.)
  9   */
 10  typedef uint64_t DTHandle;		/* generic API handle (NOT a pointer) */
 11  typedef uint8_t Hash[20];		/* SHA-1 */
 12  
 13  typedef struct {				/* from implementation */
 14  	uint32_t cputype;
 15  	uint32_t cpusubtype;
 16  	off_t offset;
 17  	uint8_t fileOnly;
 18  } DiskRepContext;
 19  
 20  
 21  /*
 22   * Local variables used for suitable casting (only)
 23   */
 24  self uint8_t *hash;
 25  
 26  
 27  /*
 28   * Startup (this may take a while)
 29   */
 30  :::BEGIN
 31  {
 32  	printf("Ready...\n");
 33  }
 34  
 35  
 36  /*
 37   * Finishing (add statistics tracers here)
 38   */
 39  :::END
 40  {
 41  }
 42  
 43  
 44  /*
 45   * Track kernel-related objects.
 46   * Each process has their own, and they're usually created very early.
 47   */
 48  struct {
 49  	DTHandle rep;				/* DiskRep */
 50  	DTHandle staticCode;		/* static code */
 51  	DTHandle code;				/* dynamic code */
 52  } kernel[pid_t];
 53  
 54  
 55  /*
 56   * Track DiskRep objects.
 57   * DiskReps are drivers for on-disk formats. Beyond their natural concerns,
 58   * they also carry the path information for StaticCode objects.
 59   */
 60  typedef struct {
 61  	DTHandle me;				/* own handle, if valid */
 62  	string path;				/* canonical path */
 63  	string type;				/* type string */
 64  	DiskRepContext ctx;			/* construction context, if any */
 65  	DTHandle sub;				/* sub-DiskRep if any */
 66  } DiskRep;
 67  DiskRep rep[DTHandle];			/* all the DiskReps we've seen */
 68  
 69  self uint64_t ctx;				/* passes construction context, NULL if none */
 70  
 71  codesign$1:::diskrep-create-*	/* preset none */
 72  { self->ctx = 0; }
 73  
 74  codesign$1:::diskrep-create-kernel
 75  {
 76  	rep[arg0].me = kernel[pid].rep = arg0;
 77  	rep[arg0].path = "(kernel)";
 78  	rep[arg0].type = "kernel";
 79  	printf("%8u %s[%d]%s(%p,KERNEL)\n",
 80  		timestamp, execname, pid, probename, arg0);
 81  }
 82  
 83  codesign$1:::diskrep-create-macho
 84  {
 85  	rep[arg0].me = arg0;
 86  	rep[arg0].path = copyinstr(arg1);
 87  	rep[arg0].type = "macho";
 88  	self->ctx = arg2;
 89  	printf("%8u %s[%d]%s(%p,%s)\n",
 90  		timestamp, execname, pid, probename, arg0, rep[arg0].path);
 91  }
 92  
 93  codesign$1:::diskrep-create-bundle-path
 94  {
 95  	rep[arg0].me = arg0;
 96  	rep[arg0].path = copyinstr(arg1);
 97  	rep[arg0].type = "bundle";
 98  	self->ctx = arg2;
 99  	rep[arg0].sub = arg3;
100  	printf("%8u %s[%d]%s(%p,%s,%p)\n",
101  		timestamp, execname, pid, probename,
102  		arg0, rep[arg0].path, rep[arg0].sub);
103  }
104  
105  codesign$1:::diskrep-create-bundle-ref
106  {
107  	rep[arg0].me = arg0;
108  	rep[arg0].path = "(from ref)";
109  	rep[arg0].type = "bundle";
110  	self->ctx = arg2;
111  	rep[arg0].sub = arg3;
112  	printf("%8u %s[%d]%s(%p,%s,%p)\n",
113  		timestamp, execname, pid, probename,
114  		arg0, rep[arg0].path, rep[arg0].sub);
115  }
116  
117  codesign$1:::diskrep-create-file
118  {
119  	rep[arg0].me = arg0;
120  	rep[arg0].path = copyinstr(arg1);
121  	rep[arg0].type = "file";
122  	printf("%8u %s[%d]%s(%p,%s)\n",
123  		timestamp, execname, pid, probename, arg0, rep[arg0].path);
124  }
125  
126  self DiskRepContext *ctxp;
127  
128  codesign$1:::diskrep-create-*
129  / self->ctx /
130  {
131  	self->ctxp = (DiskRepContext *)copyin(self->ctx, sizeof(DiskRepContext));
132  	rep[arg0].ctx = *self->ctxp;
133  	printf("%8u %s[%d] ...context: arch=(0x%x,0x%x) offset=0x%x file=%d\n",
134  		timestamp, execname, pid,
135  		self->ctxp->cputype, self->ctxp->cpusubtype,
136  		self->ctxp->offset, self->ctxp->fileOnly);
137  }
138  
139  codesign$1:::diskrep-destroy
140  {
141  	printf("%8u %s[%d]%s(%p,%s)\n",
142  		timestamp, execname, pid, probename, arg0, rep[arg0].path);
143  	rep[arg0].me = 0;
144  }
145  
146  
147  /*
148   * Track Code Signing API objects
149   */
150  typedef struct {
151  	DTHandle me;
152  	DTHandle host;
153  	DTHandle staticCode;	/* lazily acquired */
154  	uint8_t *hash;			/* dynamic hash from identify() */
155  } Code;
156  Code code[DTHandle];
157  
158  typedef struct {
159  	DTHandle me;
160  	DTHandle rep;
161  	uint8_t *hash;			/* static hash from ...::cdHash() */
162  } StaticCode;
163  StaticCode staticCode[DTHandle];
164  
165  
166  codesign$1:::static-create
167  / arg1 == kernel[pid].rep /
168  {
169  	staticCode[arg0].me = kernel[pid].staticCode = arg0;
170  	staticCode[arg0].rep = arg1;
171  	printf("%8u %s[%d]%s(%p=KERNEL[%p])\n",
172  		timestamp, execname, pid, probename, arg0, arg1);
173  }
174  
175  codesign$1:::static-create
176  / arg1 != kernel[pid].rep /
177  {
178  	staticCode[arg0].me = arg0;
179  	staticCode[arg0].rep = arg1;
180  	printf("%8u %s[%d]%s(%p,%s[%p])\n",
181  		timestamp, execname, pid, probename, arg0, rep[arg1].path, arg1);
182  }
183  
184  codesign$1:::dynamic-create
185  / arg1 == 0 /
186  {
187  	code[arg0].me = kernel[pid].code = arg0;
188  	printf("%8u %s[%d]%s(%p=KERNEL)\n",
189  		timestamp, execname, pid, probename, arg0);
190  }
191  
192  codesign$1:::dynamic-create
193  / arg1 == kernel[pid].code /
194  {
195  	code[arg0].me = arg0;
196  	printf("%8u %s[%d]%s(%p,<KERNEL>)\n",
197  		timestamp, execname, pid, probename, arg0);
198  }
199  
200  codesign$1:::dynamic-create
201  / arg1 != 0 && arg1 != kernel[pid].code /
202  {
203  	code[arg0].me = arg0;
204  	code[arg0].host = arg1;
205  	printf("%8u %s[%d]%s(%p,%p)\n",
206  		timestamp, execname, pid, probename, arg0, arg1);
207  }
208  
209  security_debug$1:::sec-destroy
210  / code[arg0].me == arg0 /
211  {
212  	code[arg0].me = 0;
213  	printf("%8u %s[%d]destroy code(%p)\n",
214  		timestamp, execname, pid, arg0);
215  }
216  
217  security_debug$1:::sec-destroy
218  / staticCode[arg0].me == arg0 /
219  {
220  	staticCode[arg0].me = 0;
221  	printf("%8u %s[%d]destroy staticCode(%p)\n",
222  		timestamp, execname, pid, arg0);
223  }
224  
225  
226  /*
227   * Identification operations
228   */
229  codesign$1:::guest-identify-*
230  {
231  	printf("%8u %s[%d]%s(%p,%d,%s[%p])\n",
232  		timestamp, execname, pid, probename,
233  		arg0, arg1, rep[staticCode[arg2].rep].path, arg2);
234  	code[arg0].staticCode = arg2;
235  }
236  
237  codesign$1:::guest-cdhash-*
238  {
239  	self->hash = code[arg0].hash = (uint8_t *)copyin(arg1, sizeof(Hash));
240  	printf("%8u %s[%d]%s(%p,H\"%02x%02x%02x...%02x%02x\")\n",
241  		timestamp, execname, pid, probename, arg0,
242  		self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]);
243  }
244  
245  codesign$1:::static-cdhash
246  {
247  	self->hash = staticCode[arg0].hash = (uint8_t *)copyin(arg1, sizeof(Hash));
248  	printf("%8u %s[%d]%s(%p,H\"%02x%02x%02x...%02x%02x\")\n",
249  		timestamp, execname, pid, probename, arg0,
250  		self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]);
251  }
252  
253  
254  /*
255   * Guest registry/proxy management in securityd
256   */
257  typedef struct {
258  	DTHandle guest;
259  	string path;
260  	uint32_t status;
261  	uint8_t *hash;
262  } SDGuest;
263  SDGuest guests[DTHandle, DTHandle];		/* host x guest */
264  
265  securityd*:::host-register
266  {
267  	printf("%8u HOST DYNAMIC(%p,%d)\n",
268  		timestamp, arg0, arg1);
269  }
270  
271  securityd*:::host-proxy
272  {
273  	printf("%8u HOST PROXY(%p,%d)\n",
274  		timestamp, arg0, arg1);
275  }
276  
277  securityd*:::host-unregister
278  {
279  	printf("%8u HOST DESTROYED(%p)\n",
280  		timestamp, arg0);
281  }
282  
283  securityd*:::guest-create
284  {
285  	guests[arg0, arg2].guest = arg2;
286  	guests[arg0, arg2].path = copyinstr(arg5);
287  	guests[arg0, arg2].status = arg3;
288  	printf("%8u GUEST CREATE(%p,%s[0x%x],host=0x%x,status=0x%x,flags=%d)\n",
289  		timestamp,
290  		arg0, guests[arg0, arg2].path, arg2, arg1, arg3, arg4);
291  }
292  
293  securityd*:::guest-cdhash
294  / arg2 != 0 /
295  {
296  	self->hash = guests[arg0, arg1].hash = (uint8_t *)copyin(arg2, sizeof(Hash));
297  	printf("%8u GUEST HASH(%p,%s[0x%x],H\"%02x%02x%02x...%02x%02x\")\n",
298  		timestamp,
299  		arg0, guests[arg0, arg1].path, arg1,
300  		self->hash[0], self->hash[1], self->hash[2], self->hash[18], self->hash[19]);
301  }
302  
303  securityd*:::guest-cdhash
304  / arg2 == 0 /
305  {
306  	printf("%8u GUEST HASH(%p,%s[0x%x],NONE)\n",
307  		timestamp, arg0, guests[arg0, arg1].path, arg1);
308  }
309  
310  securityd*:::guest-change
311  {
312  	printf("%8u GUEST CHANGE(%p,%s[0x%x],status=0x%x)\n",
313  		timestamp,
314  		arg0, guests[arg0, arg1].path, arg1, arg2);
315  }
316  
317  securityd*:::guest-destroy
318  {
319  	printf("%8u GUEST DESTROY(%p,%s[0x%x])\n",
320  		timestamp,
321  		arg0, guests[arg0, arg1].path, arg1);
322  }
323  
324  
325  /*
326   * Signing Mach-O allocation tracking
327   */
328  codesign$1:::allocate-arch
329  {
330  	printf("%8u %s[%d]%s(%s,%d)\n",
331  		timestamp, execname, pid, probename, copyinstr(arg0), arg1);
332  }
333  
334  codesign$1:::allocate-archn
335  {
336  	printf("%8u %s[%d]%s((0x%x,0x%x),%d)\n",
337  		timestamp, execname, pid, probename, arg0, arg1,  arg2);
338  }
339  
340  codesign$1:::allocate-write
341  {
342  	printf("%8u %s[%d]%s(%s,offset 0x%x,%d of %d)\n",
343  		timestamp, execname, pid, probename,
344  		copyinstr(arg0), arg1, arg2, arg3);
345  }
346  
347  codesign$1:::allocate-validate
348  {
349  	printf("%8u %s[%d]%s(%s,%d)\n",
350  		timestamp, execname, pid, probename, copyinstr(arg0), arg1);
351  }
352  
353  
354  /*
355   * Evaluation tracking
356   */
357  codesign$1:::eval-dynamic-start
358  {
359  	printf("%8u %s[%d]%s(%p,%s)\n",
360  		timestamp, execname, pid, probename, arg0, copyinstr(arg1));
361  }
362  
363  codesign$1:::eval-dynamic-end
364  {
365  	printf("%8u %s[%d]%s(%p)\n",
366  		timestamp, execname, pid, probename, arg0);
367  }
368