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