Main Page Modules Data Structures File List Data Fields Globals Related Pages

# 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 #endif
    00650         return NULL;
    00651     }
    00652
    00653     return Filter;
    00654
    00655 }
    00656
    00658
    00659 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
    00660
    00661 #ifdef NTKERNEL
    00662     ExFreePool(Filter->mem);
    00663     ExFreePool(Filter->Function);
    00664     ExFreePool(Filter);
    00665 #else
    00666     free(Filter->mem);
    00667     free(Filter->Function);
    00668     free(Filter);
    00669 #endif
    00670
    00671 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.