Programación General > ASM (Ensamblador)
Problema Tonto En Ring 0
Eternal Idol:
Lo que querias hacer ya se habia entendido, sino queres mostrar lo que estas haciendo exactamente no hay problema pero no esperes que te ayude.
G.Owl:
Perdon, creia que no se me entendia.
Aqui pongo el code y digo donde me falla:
Gracias por la ayuda
--- Código: Text --- .386p.model flat,stdcalloption casemap :none include windows.inc include user32.incinclude kernel32.incinclude advapi32.inc includelib user32.libincludelib kernel32.libincludelib 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,pNewDaclnoneed: 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 0fwh: 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
Eternal Idol:
Me traiciono la memoria evidentemente, hubiera jurado que PhysicaMemory estaba vedado en XP pero veo que es de 2003 Server en adelante.
Al codigo le faltaba la parte en la cual llamaba a la funcion aunque la encontre rapidamente en Internet.
¿Cual es la razon por la cual pensas que tiene algun sentido llamar a una funcion de modo Usuario desde modo Kernel? La amplia mayoria de ellas intentan pasar a modo Kernel justamente. GetStdHandle es una excepcion ya que usa el PEB (RTL_USER_PROCESS_PARAMETERS) para devolver esos valores.
En fin, si se comporta tal como en mi maquina virtual la excepcion se produce por una razon muy simple, esa funcion no esta en memoria y el Kernel se encarga de manejar el page-fault (si lo depuraras verias como justo despues de la ejecucion de MmAccessFault si esta disponible el codigo de la funcion en memoria) :D Si llamaras a WriteConsoleA antes no daria una excepcion aunque seguiria siendo inutil por supuesto. En modo Kernel hay que usar las funciones ofrecidas por el Kernel y no por la API de Windows de modo Usuario.
G.Owl:
mm El WinDbg es feo. Me baje incluso una interfaz para él pero sigo sin conocerlo muy bien todavia.
La razon de llamar apis de modo usuario ? Pues porque si hay apis en modo kernel que hacen lo mismo no se cuales son.
Tengo un pdf de la api nativa de Windows Xp pero si existen las apis equivalentes no se cuales son. No creas que no las estoy buscando.
Si consiguiera cargar la libreria kernel32.dll en modo kernel podria acceder a sus apis ?
Hay alguna forma de hacer esto ?
Es que tenia entendido que en modo kernel tienes acceso a todas las direcciones.
Gracias
Eternal Idol:
El WinDbg permite depurar en modo Usuario y modo Kernel, el OllyDbg no asi que no hay punto de comparacion.
¿Y cual es la razon para hacer en modo Kernel lo que en modo Usuario? No tiene sentido ...
La API nativa de XP es la NTDLL.dll - una libreria dinamica comun y corriente de modo Usuario - que en su mayoria de funciones solo transforma unos parametros y pasa a modo Kernel.
La DLL - Kernel32 - ya esta cargada en tu proceso y GetStdHandle es ejecutada correctamente, si llamaras antes desde modo Usuario a esa funcion - WriteConsoleA - como te dije no daria una excepcion al no tener que resolver el page-fault el Kernel - cuando lo hace vuelve a modo Usuario -.
En modo Kernel hay que usar las funciones ofrecidas por el Kernel y no por la API de Windows de modo Usuario.
Navegación
[#] Página Siguiente
[*] Página Anterior
Ir a la versión completa