Main Page   Modules   Data Structures   File List   Data Fields   Globals  

jitter.c

Go to the documentation of this file.
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.