00001 /* 00002 * Copyright (c) 2002 00003 * Politecnico di Torino. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that: (1) source code distributions 00007 * retain the above copyright notice and this paragraph in its entirety, (2) 00008 * distributions including binary code include the above copyright notice and 00009 * this paragraph in its entirety in the documentation or other materials 00010 * provided with the distribution, and (3) all advertising materials mentioning 00011 * features or use of this software display the following acknowledgement: 00012 * ``This product includes software developed by the Politecnico 00013 * di Torino, and its contributors.'' Neither the name of 00014 * the University nor the names of its contributors may be used to endorse 00015 * or promote products derived from this software without specific prior 00016 * written permission. 00017 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00018 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00019 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00020 */ 00021 00022 #include "stdarg.h" 00023 #include "ntddk.h" 00024 #include "ntiologc.h" 00025 #include "ndis.h" 00026 00027 #include "packet.h" 00028 #include "win_bpf.h" 00029 00030 emit_func emitm; 00031 00032 // 00033 // emit routine to update the jump table 00034 // 00035 void emit_lenght(binary_stream *stream, ULONG value, UINT len) 00036 { 00037 (stream->refs)[stream->bpf_pc]+=len; 00038 stream->cur_ip+=len; 00039 } 00040 00041 // 00042 // emit routine to output the actual binary code 00043 // 00044 void emit_code(binary_stream *stream, ULONG value, UINT len) 00045 { 00046 00047 switch (len){ 00048 00049 case 1: 00050 stream->ibuf[stream->cur_ip]=(UCHAR)value; 00051 stream->cur_ip++; 00052 break; 00053 00054 case 2: 00055 *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value; 00056 stream->cur_ip+=2; 00057 break; 00058 00059 case 4: 00060 *((ULONG*)(stream->ibuf+stream->cur_ip))=value; 00061 stream->cur_ip+=4; 00062 break; 00063 00064 default:; 00065 00066 } 00067 00068 return; 00069 00070 } 00071 00072 // 00073 // Function that does the real stuff 00074 // 00075 BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem) 00076 { 00077 struct bpf_insn *ins; 00078 UINT i, pass; 00079 binary_stream stream; 00080 00081 00082 // Allocate the reference table for the jumps 00083 #ifdef NTKERNEL 00084 stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA'); 00085 #else 00086 stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT)); 00087 #endif 00088 if(stream.refs==NULL) 00089 { 00090 return NULL; 00091 } 00092 00093 // Reset the reference table 00094 for(i=0; i< nins + 1; i++) 00095 stream.refs[i]=0; 00096 00097 stream.cur_ip=0; 00098 stream.bpf_pc=0; 00099 00100 // the first pass will emit the lengths of the instructions 00101 // to create the reference table 00102 emitm=emit_lenght; 00103 00104 for(pass=0;;){ 00105 00106 ins = prog; 00107 00108 /* create the procedure header */ 00109 PUSH(EBP) 00110 MOVrd(EBP,ESP) 00111 PUSH(EBX) 00112 PUSH(ECX) 00113 PUSH(EDX) 00114 PUSH(ESI) 00115 PUSH(EDI) 00116 MOVodd(EBX, EBP, 8) 00117 00118 for(i=0;i<nins;i++){ 00119 00120 stream.bpf_pc++; 00121 00122 switch (ins->code) { 00123 00124 default: 00125 00126 return NULL; 00127 00128 case BPF_RET|BPF_K: 00129 00130 MOVid(EAX,ins->k) 00131 POP(EDI) 00132 POP(ESI) 00133 POP(EDX) 00134 POP(ECX) 00135 POP(EBX) 00136 POP(EBP) 00137 RET() 00138 00139 break; 00140 00141 00142 case BPF_RET|BPF_A: 00143 00144 POP(EDI) 00145 POP(ESI) 00146 POP(EDX) 00147 POP(ECX) 00148 POP(EBX) 00149 POP(EBP) 00150 RET() 00151 00152 break; 00153 00154 00155 case BPF_LD|BPF_W|BPF_ABS: 00156 00157 MOVid(ECX,ins->k) 00158 MOVrd(ESI,ECX) 00159 ADDib(ECX,sizeof(INT)) 00160 CMPodd(ECX, EBP, 0x10) 00161 JLEb(12) 00162 POP(EDI) 00163 POP(ESI) 00164 POP(EDX) 00165 POP(ECX) 00166 POP(EBX) 00167 POP(EBP) 00168 MOVid(EAX,0) //this can be optimized with xor eax,eax 00169 RET() 00170 MOVobd(EAX, EBX, ESI) 00171 BSWAP(EAX) 00172 00173 break; 00174 00175 case BPF_LD|BPF_H|BPF_ABS: 00176 00177 MOVid(ECX,ins->k) 00178 MOVrd(ESI,ECX) 00179 ADDib(ECX,sizeof(SHORT)) 00180 CMPodd(ECX, EBP, 0x10) 00181 JLEb(12) 00182 POP(EDI) 00183 POP(ESI) 00184 POP(EDX) 00185 POP(ECX) 00186 POP(EBX) 00187 POP(EBP) 00188 MOVid(EAX,0) 00189 RET() 00190 MOVid(EAX,0) 00191 MOVobw(AX, EBX, ESI) 00192 SWAP_AX() 00193 00194 break; 00195 00196 case BPF_LD|BPF_B|BPF_ABS: 00197 00198 MOVid(ECX,ins->k) 00199 CMPodd(ECX, EBP, 0x10) 00200 JLEb(12) 00201 POP(EDI) 00202 POP(ESI) 00203 POP(EDX) 00204 POP(ECX) 00205 POP(EBX) 00206 POP(EBP) 00207 MOVid(EAX,0) 00208 RET() 00209 MOVid(EAX,0) 00210 MOVobb(AL,EBX,ECX) 00211 00212 break; 00213 00214 case BPF_LD|BPF_W|BPF_LEN: 00215 00216 MOVodd(EAX, EBP, 0xc) 00217 00218 break; 00219 00220 case BPF_LDX|BPF_W|BPF_LEN: 00221 00222 MOVodd(EDX, EBP, 0xc) 00223 00224 break; 00225 00226 case BPF_LD|BPF_W|BPF_IND: 00227 00228 MOVid(ECX,ins->k) 00229 ADDrd(ECX,EDX) 00230 MOVrd(ESI,ECX) 00231 ADDib(ECX,sizeof(INT)) 00232 CMPodd(ECX, EBP, 0x10) 00233 JLEb(12) 00234 POP(EDI) 00235 POP(ESI) 00236 POP(EDX) 00237 POP(ECX) 00238 POP(EBX) 00239 POP(EBP) 00240 MOVid(EAX,0) 00241 RET() 00242 MOVobd(EAX, EBX, ESI) 00243 BSWAP(EAX) 00244 00245 break; 00246 00247 case BPF_LD|BPF_H|BPF_IND: 00248 00249 MOVid(ECX,ins->k) 00250 ADDrd(ECX,EDX) 00251 MOVrd(ESI,ECX) 00252 ADDib(ECX,sizeof(SHORT)) 00253 CMPodd(ECX, EBP, 0x10) 00254 JLEb(12) 00255 POP(EDI) 00256 POP(ESI) 00257 POP(EDX) 00258 POP(ECX) 00259 POP(EBX) 00260 POP(EBP) 00261 MOVid(EAX,0) 00262 RET() 00263 MOVid(EAX,0) 00264 MOVobw(AX, EBX, ESI) 00265 SWAP_AX() 00266 00267 break; 00268 00269 case BPF_LD|BPF_B|BPF_IND: 00270 00271 MOVid(ECX,ins->k) 00272 ADDrd(ECX,EDX) 00273 CMPodd(ECX, EBP, 0x10) 00274 JLEb(12) 00275 POP(EDI) 00276 POP(ESI) 00277 POP(EDX) 00278 POP(ECX) 00279 POP(EBX) 00280 POP(EBP) 00281 MOVid(EAX,0) 00282 RET() 00283 MOVid(EAX,0) 00284 MOVobb(AL,EBX,ECX) 00285 00286 break; 00287 00288 case BPF_LDX|BPF_MSH|BPF_B: 00289 00290 MOVid(ECX,ins->k) 00291 CMPodd(ECX, EBP, 0x10) 00292 JLEb(12) 00293 POP(EDI) 00294 POP(ESI) 00295 POP(EDX) 00296 POP(ECX) 00297 POP(EBX) 00298 POP(EBP) 00299 MOVid(EAX,0) 00300 RET() 00301 MOVid(EDX,0) 00302 MOVobb(DL,EBX,ECX) 00303 ANDib(DL, 0xf) 00304 SHLib(EDX, 2) 00305 00306 break; 00307 00308 case BPF_LD|BPF_IMM: 00309 00310 MOVid(EAX,ins->k) 00311 00312 break; 00313 00314 case BPF_LDX|BPF_IMM: 00315 00316 MOVid(EDX,ins->k) 00317 00318 break; 00319 00320 case BPF_LD|BPF_MEM: 00321 00322 MOVid(ECX,(INT)mem) 00323 MOVid(ESI,ins->k*4) 00324 MOVobd(EAX, ECX, ESI) 00325 00326 break; 00327 00328 case BPF_LDX|BPF_MEM: 00329 00330 MOVid(ECX,(INT)mem) 00331 MOVid(ESI,ins->k*4) 00332 MOVobd(EDX, ECX, ESI) 00333 00334 break; 00335 00336 case BPF_ST: 00337 00338 // XXX: this command and the following could be optimized if the previous 00339 // instruction was already of this type 00340 MOVid(ECX,(INT)mem) 00341 MOVid(ESI,ins->k*4) 00342 MOVomd(ECX, ESI, EAX) 00343 00344 break; 00345 00346 case BPF_STX: 00347 00348 MOVid(ECX,(INT)mem) 00349 MOVid(ESI,ins->k*4) 00350 MOVomd(ECX, ESI, EDX) 00351 break; 00352 00353 case BPF_JMP|BPF_JA: 00354 00355 JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc]) 00356 00357 break; 00358 00359 case BPF_JMP|BPF_JGT|BPF_K: 00360 00361 CMPid(EAX, ins->k) 00362 JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP 00363 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00364 break; 00365 00366 case BPF_JMP|BPF_JGE|BPF_K: 00367 00368 CMPid(EAX, ins->k) 00369 JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 00370 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00371 00372 break; 00373 00374 case BPF_JMP|BPF_JEQ|BPF_K: 00375 00376 CMPid(EAX, ins->k) 00377 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 00378 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00379 00380 break; 00381 00382 case BPF_JMP|BPF_JSET|BPF_K: 00383 00384 MOVrd(ECX,EAX) 00385 ANDid(ECX,ins->k) 00386 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5) 00387 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]) 00388 00389 break; 00390 00391 case BPF_JMP|BPF_JGT|BPF_X: 00392 00393 CMPrd(EAX, EDX) 00394 JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 00395 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00396 break; 00397 00398 case BPF_JMP|BPF_JGE|BPF_X: 00399 00400 CMPrd(EAX, EDX) 00401 JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 00402 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00403 00404 break; 00405 00406 case BPF_JMP|BPF_JEQ|BPF_X: 00407 00408 CMPrd(EAX, EDX) 00409 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) 00410 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]) 00411 00412 break; 00413 00414 case BPF_JMP|BPF_JSET|BPF_X: 00415 00416 MOVrd(ECX,EAX) 00417 ANDrd(ECX,EDX) 00418 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5) 00419 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]) 00420 00421 break; 00422 00423 case BPF_ALU|BPF_ADD|BPF_X: 00424 00425 ADDrd(EAX,EDX) 00426 00427 break; 00428 00429 case BPF_ALU|BPF_SUB|BPF_X: 00430 00431 SUBrd(EAX,EDX) 00432 00433 break; 00434 00435 case BPF_ALU|BPF_MUL|BPF_X: 00436 00437 MOVrd(ECX,EDX) 00438 MULrd(EDX) 00439 MOVrd(EDX,ECX) 00440 break; 00441 00442 case BPF_ALU|BPF_DIV|BPF_X: 00443 00444 CMPid(EDX, 0) 00445 JNEb(12) 00446 POP(EDI) 00447 POP(ESI) 00448 POP(EDX) 00449 POP(ECX) 00450 POP(EBX) 00451 POP(EBP) 00452 MOVid(EAX,0) 00453 RET() 00454 MOVrd(ECX,EDX) 00455 MOVid(EDX,0) 00456 DIVrd(ECX) 00457 MOVrd(EDX,ECX) 00458 00459 break; 00460 00461 case BPF_ALU|BPF_AND|BPF_X: 00462 00463 ANDrd(EAX,EDX) 00464 00465 break; 00466 00467 case BPF_ALU|BPF_OR|BPF_X: 00468 00469 ORrd(EAX,EDX) 00470 00471 break; 00472 00473 case BPF_ALU|BPF_LSH|BPF_X: 00474 00475 MOVrd(ECX,EDX) 00476 SHL_CLrb(EAX) 00477 00478 break; 00479 00480 case BPF_ALU|BPF_RSH|BPF_X: 00481 00482 MOVrd(ECX,EDX) 00483 SHR_CLrb(EAX) 00484 00485 break; 00486 00487 case BPF_ALU|BPF_ADD|BPF_K: 00488 00489 ADD_EAXi(ins->k) 00490 00491 break; 00492 00493 case BPF_ALU|BPF_SUB|BPF_K: 00494 00495 SUB_EAXi(ins->k) 00496 00497 break; 00498 00499 case BPF_ALU|BPF_MUL|BPF_K: 00500 00501 MOVrd(ECX,EDX) 00502 MOVid(EDX,ins->k) 00503 MULrd(EDX) 00504 MOVrd(EDX,ECX) 00505 00506 break; 00507 00508 case BPF_ALU|BPF_DIV|BPF_K: 00509 00510 MOVrd(ECX,EDX) 00511 MOVid(EDX,0) 00512 MOVid(ESI,ins->k) 00513 DIVrd(ESI) 00514 MOVrd(EDX,ECX) 00515 00516 break; 00517 00518 case BPF_ALU|BPF_AND|BPF_K: 00519 00520 ANDid(EAX, ins->k) 00521 00522 break; 00523 00524 case BPF_ALU|BPF_OR|BPF_K: 00525 00526 ORid(EAX, ins->k) 00527 00528 break; 00529 00530 case BPF_ALU|BPF_LSH|BPF_K: 00531 00532 SHLib(EAX, (ins->k) & 255) 00533 00534 break; 00535 00536 case BPF_ALU|BPF_RSH|BPF_K: 00537 00538 SHRib(EAX, (ins->k) & 255) 00539 00540 break; 00541 00542 case BPF_ALU|BPF_NEG: 00543 00544 NEGd(EAX) 00545 00546 break; 00547 00548 case BPF_MISC|BPF_TAX: 00549 00550 MOVrd(EDX,EAX) 00551 00552 break; 00553 00554 case BPF_MISC|BPF_TXA: 00555 00556 MOVrd(EAX,EDX) 00557 00558 break; 00559 00560 00561 00562 } 00563 00564 ins++; 00565 } 00566 00567 pass++; 00568 if(pass == 2) break; 00569 00570 #ifdef NTKERNEL 00571 stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA'); 00572 #else 00573 stream.ibuf=(CHAR*)malloc(stream.cur_ip); 00574 #endif 00575 if(stream.ibuf==NULL) 00576 { 00577 #ifdef NTKERNEL 00578 ExFreePool(stream.refs); 00579 #else 00580 free(stream.refs); 00581 #endif 00582 return NULL; 00583 } 00584 00585 // modify the reference table to contain the offsets and not the lengths of the instructions 00586 for(i=1; i< nins + 1; i++) 00587 stream.refs[i]+=stream.refs[i-1]; 00588 00589 // Reset the counters 00590 stream.cur_ip=0; 00591 stream.bpf_pc=0; 00592 // the second pass creates the actual code 00593 emitm=emit_code; 00594 00595 } 00596 00597 // the reference table is needed only during compilation, now we can free it 00598 #ifdef NTKERNEL 00599 ExFreePool(stream.refs); 00600 #else 00601 free(stream.refs); 00602 #endif 00603 return (BPF_filter_function)stream.ibuf; 00604 00605 } 00606 00607 00608 JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins) 00609 { 00610 JIT_BPF_Filter *Filter; 00611 00612 00613 // Allocate the filter structure 00614 #ifdef NTKERNEL 00615 Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA'); 00616 #else 00617 Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter)); 00618 #endif 00619 if(Filter==NULL) 00620 { 00621 return NULL; 00622 } 00623 00624 // Allocate the filter's memory 00625 #ifdef NTKERNEL 00626 Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA'); 00627 #else 00628 Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT)); 00629 #endif 00630 if(Filter->mem==NULL) 00631 { 00632 #ifdef NTKERNEL 00633 ExFreePool(Filter); 00634 #else 00635 free(Filter); 00636 #endif 00637 return NULL; 00638 } 00639 00640 // Create the binary 00641 if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL) 00642 { 00643 #ifdef NTKERNEL 00644 ExFreePool(Filter->mem); 00645 ExFreePool(Filter); 00646 #else 00647 free(Filter->mem); 00648 free(Filter); 00649 00650 return NULL; 00651 #endif 00652 } 00653 00654 return Filter; 00655 00656 } 00657 00659 00660 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){ 00661 00662 #ifdef NTKERNEL 00663 ExFreePool(Filter->mem); 00664 ExFreePool(Filter->Function); 00665 ExFreePool(Filter); 00666 #else 00667 free(Filter->mem); 00668 free(Filter->Function); 00669 free(Filter); 00670 #endif 00671 00672 }
documentation. Copyright (c) 2002 Politecnico di Torino. All rights reserved.