
Esta herramienta extrae y muestra datos de la función Recall en Windows 11, proporcionando una manera fácil de acceder a información sobre las instantáneas de actividad de tu PC.
Rompiendo Windows Recall. Otra vez.
image
Cuando Microsoft rediseñó Recall con enclaves VBS, cifrado AES-256-GCM, autenticación Windows Hello y un host de Proceso Ligero Protegido, el mensaje fue claro: los datos están bloqueados en una bóveda.
La bóveda es sólida. El camión de reparto no.
AIXHost.exe, el proceso que renderiza la línea de tiempo de Recall, no tiene PPL, ni AppContainer, ni cumplimiento de integridad de código. Cualquier proceso que se ejecute como el usuario conectado puede inyectar código en él y llamar a las mismas API COM que usa la interfaz legítima. Una vez que el usuario se autentica con Windows Hello, las capturas de pantalla descifradas, el texto OCR y los metadatos fluyen a través de AIXHost.exe como objetos COM en vivo. TotalRecall Reloaded se coloca dentro de ese proceso y extrae todo.
No se requiere administrador. Usuario estándar. Sin exploit de kernel. Sin bypass criptográfico. Solo llamadas COM.
TotalRecall Reloaded consta de dos archivos: un inyector (totalrecall.exe) y una DLL de carga útil (totalrecall_payload.dll).
El inyector encuentra AIXHost.exe mediante CreateToolhelp32Snapshot, asigna memoria en el destino con VirtualAllocEx, escribe la ruta de la DLL con WriteProcessMemory y genera un hilo remoto apuntando a LoadLibraryW. Inyección DLL clásica. Nada sofisticado, porque no se necesita nada sofisticado. AIXHost.exe no tiene ninguna protección contra esto.
Esto funciona desde un usuario estándar sin privilegios. Sin elevación, sin SeDebugPrivilege. La DACL predeterminada de Windows permite que los procesos del mismo usuario tengan acceso completo entre sí. Verificado: el token se ejecuta en nivel obligatorio Medio con BUILTIN\Administrators establecido como solo denegación.
El enclave VBS no descifrará nada sin Windows Hello. La herramienta no lo evita. Hace que el usuario lo haga, viaja silenciosamente cuando el usuario lo hace, o espera a que el usuario lo haga.
--launch simula Win+J mediante keybd_event, el atajo de teclado que abre la línea de tiempo de Recall. El usuario ve un mensaje de Hello (rostro, huella digital o PIN), se autentica y el enclave comienza a servir datos descifrados. Desde la perspectiva del usuario, Recall se abrió normalmente. Desde la nuestra, la carga útil ya está dentro, esperando.
--stealth es el modo completamente silencioso. Funciona así:
AIXHost.exe (siempre en ejecución) y parchea DiscardDataAccess para que sea un no-opAIXHost.exe muere y se reinicia. La herramienta detecta el reinicio y se reinyecta en el nuevo procesoaihost.exe (la revocación fue bloqueada). La extracción comienza de inmediato--wait es la contraparte pasiva de --launch. En lugar de simular Win+J, la herramienta permanece inactiva mientras el usuario abre Recall por su cuenta — desde la barra de tareas, un acceso directo o cualquier otra ruta. Cuando aparece AIXHost.exe y el usuario completa Hello de forma natural, se inyecta la carga útil y comienza la extracción. Útil en una máquina que está siendo observada, o cuando la sesión de Recall debe parecer completamente iniciada por el usuario sin entrada de teclado sintética.
Una vez dentro de AIXHost.exe, la carga útil inicializa un apartamento COM con CoInitializeEx(COINIT_APARTMENTTHREADED) y configura el reenvío de identidad del proxy con CoSetProxyBlanket(EOAC_DYNAMIC_CLOAKING). Esto es crítico. Sin el encubrimiento dinámico, el proxy COM no lleva la identidad autenticada al servidor.
La extracción sigue el mismo camino que utiliza la interfaz legítima de Recall:
Inicialización del enclave: DataManager.Load() desencadena la carga de la clave del enclave. DataStoreManager.DecryptDatabase() (slot 37) prepara vistas descifradas. La carga útil consulta DataManager.DataStatus hasta que devuelve 3 (desbloqueado).
Enumeración de entidades: MemoryEntityStatics.GetLightMemoryItemsBefore() (slot 9) devuelve un vector de referencias de entidades ligeras. Cada una lleva un ID de contexto en el offset +8. En una máquina típica, esto devuelve cientos de entidades que abarcan días o semanas de actividad.
Extracción por entidad: Para cada ID de contexto, la carga útil carga la entidad completa mediante ContextEngine2.TryGetEntityForId() (slot 6), la desenvuelve a través de IEntityWrapper (slot 6) y QueryInterface a IMemoryEntity. A partir de ahí:
TryGetBitmapCaptureAsync() (slot 19) devuelve un SoftwareBitmap. QueryInterface a ISoftwareBitmapNative, llamar a GetData(IID_IWICBitmap) para obtener un mapa de bits WIC, codificar como PNG mediante IWICBitmapEncoderContextEngine2.TryGetMemoryEntityDetailsForIdAsync() (slot 8) devuelve los detalles de la entidad. QI a IMemoryEntityDetails para OcrLines (slot 7), IMemoryEntityDetails2 para entidades de texto NER (personas, correos electrónicos, direcciones) e IMemoryEntityDetails4 para descripciones de actividad de IARondas de reintento: Baker.dll (la biblioteca de la interfaz de Recall) llena la caché de ContextEngine de forma asíncrona. Después del pase inicial, la carga útil bombea mensajes de Windows durante 3 segundos (bucle PeekMessage/DispatchMessage) y reintenta cualquier entidad que no estuviera disponible. Cada ronda suele producir ~12 entidades adicionales. Hasta 10 rondas de reintento.
Cada llamada está envuelta en __try/__except porque una sola violación de acceso en una llamada al proxy COM mata permanentemente el canal RPC hacia aihost.exe. No hay recuperación. Tendrías que reiniciar AIXHost.exe. Los envoltorios SEH atrapan bloqueos causados por tipos de parámetros incorrectos y mantienen la sesión viva.
Varias operaciones funcionan sin ninguna autenticación de Hello:
Extracción de capturas de pantalla: RecallPrivacyIndicatorSettings (CLSID {42C63551-...}) expone GetRecentCaptureThumbnail(width, height) en el slot 13. El nombre del método dice "miniatura", pero el servidor no impone un límite de resolución. Pasar 3840x3840 devuelve la captura de Recall más reciente a resolución completa. El resultado IRandomAccessStream se convierte a un IStream mediante CreateStreamOverRandomAccessStream (shcore.dll) y se vuelca como BMP.
Destrucción de datos: IDataStoreManager::DeleteEvents() (slot 12) borra todo el historial de capturas. Sin parámetros, sin autenticación. El análisis en Ghidra confirmó: el manejador de eliminación en FUN_1802ddd10 contiene cero llamadas a la función de puerta de autorización. La verificación de autenticación nunca se conectó.