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