Playing with PEB, listing process modules

(Article déjà paru sur nibbles)

Bonjour/Bonsoir,

Suite à l’article très intéressant de YoLeJedi où il fait des trucs et des machins de Jedi avec hFile je me suis dis qu’il devais y avoir un moyen plus simple de lister ces modules avec des techniques de padawan cette fois. Bon le contexte va être différent cette fois-ci puisque pas de session de debugging et on assistera pas en live au load des Dll cependant on pourra quand même les lister par ordre de chargement. Let’s go !


I. Stepping in PEB

J’ai décidé de m’intéresser à la struct PEB :

kd> dt nt!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 SpareBool : UChar
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
+0x014 SubSystemData : Ptr32 Void
+0x018 ProcessHeap : Ptr32 Void
+0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
+0x020 FastPebLockRoutine : Ptr32 Void
+0x024 FastPebUnlockRoutine : Ptr32 Void
+0x028 EnvironmentUpdateCount : Uint4B
+0x02c KernelCallbackTable : Ptr32 Void
+0x030 SystemReserved : [1] Uint4B
+0x034 AtlThunkSListPtr32 : Uint4B
+0x038 FreeList : Ptr32 _PEB_FREE_BLOCK
+0x03c TlsExpansionCounter : Uint4B
+0x040 TlsBitmap : Ptr32 Void
+0x044 TlsBitmapBits : [2] Uint4B
+0x04c ReadOnlySharedMemoryBase : Ptr32 Void
+0x050 ReadOnlySharedMemoryHeap : Ptr32 Void
+0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
+0x058 AnsiCodePageData : Ptr32 Void
+0x05c OemCodePageData : Ptr32 Void
+0x060 UnicodeCaseTableData : Ptr32 Void
+0x064 NumberOfProcessors : Uint4B
+0x068 NtGlobalFlag : Uint4B
+0x070 CriticalSectionTimeout : _LARGE_INTEGER
+0x078 HeapSegmentReserve : Uint4B
+0x07c HeapSegmentCommit : Uint4B
+0x080 HeapDeCommitTotalFreeThreshold : Uint4B
+0x084 HeapDeCommitFreeBlockThreshold : Uint4B
+0x088 NumberOfHeaps : Uint4B
+0x08c MaximumNumberOfHeaps : Uint4B
+0x090 ProcessHeaps : Ptr32 Ptr32 Void
+0x094 GdiSharedHandleTable : Ptr32 Void
+0x098 ProcessStarterHelper : Ptr32 Void
+0x09c GdiDCAttributeList : Uint4B
+0x0a0 LoaderLock : Ptr32 Void
+0x0a4 OSMajorVersion : Uint4B
+0x0a8 OSMinorVersion : Uint4B
+0x0ac OSBuildNumber : Uint2B
+0x0ae OSCSDVersion : Uint2B
+0x0b0 OSPlatformId : Uint4B
+0x0b4 ImageSubsystem : Uint4B
+0x0b8 ImageSubsystemMajorVersion : Uint4B
+0x0bc ImageSubsystemMinorVersion : Uint4B
+0x0c0 ImageProcessAffinityMask : Uint4B
+0x0c4 GdiHandleBuffer : [34] Uint4B
+0x14c PostProcessInitRoutine : Ptr32 void
+0x150 TlsExpansionBitmap : Ptr32 Void
+0x154 TlsExpansionBitmapBits : [32] Uint4B
+0x1d4 SessionId : Uint4B
+0x1d8 AppCompatFlags : _ULARGE_INTEGER
+0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
+0x1e8 pShimData : Ptr32 Void
+0x1ec AppCompatInfo : Ptr32 Void
+0x1f0 CSDVersion : _UNICODE_STRING
+0x1f8 ActivationContextData : Ptr32 Void
+0x1fc ProcessAssemblyStorageMap : Ptr32 Void
+0x200 SystemDefaultActivationContextData : Ptr32 Void
+0x204 SystemAssemblyStorageMap : Ptr32 Void
+0x208 MinimumStackCommit : Uint4B

Bon ici pas besoin de regarder longtemps avant de voir le paramètre +0×00c Ldr : Ptr32 _PEB_LDR_DATA
On comprends bien que cette structures va pouvoir nous donner des infos sur nos modules.

kd> dt nt!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void

C’est pas beau tout ça ?
On voit ici que trois liste nous permettent d’avoir la liste des modules dans plusieurs ordres. Celui qui a nous intéressé l’ordre de chargement : +0×00c InLoadOrderModuleList : _LIST_ENTRY.
Voyons à quoi ressemble cette struct LIST_ENTRY :

kd> dt nt!_LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY

Ok donc on a à faire à une liste double chainée. Mais vers quoi pointent Flink et Blink ? Petit tour sur la msdn et on nous informe que Flink et Blink pointent vers des structures LDR_DATA_TABLE_ENTRY :


kd> dt nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x008 InMemoryOrderLinks : _LIST_ENTRY
+0x010 InInitializationOrderLinks : _LIST_ENTRY
+0x018 DllBase : Ptr32 Void
+0x01c EntryPoint : Ptr32 Void
+0x020 SizeOfImage : Uint4B
+0x024 FullDllName : _UNICODE_STRING
+0x02c BaseDllName : _UNICODE_STRING
+0x034 Flags : Uint4B
+0x038 LoadCount : Uint2B
+0x03a TlsIndex : Uint2B
+0x03c HashLinks : _LIST_ENTRY
+0x03c SectionPointer : Ptr32 Void
+0x040 CheckSum : Uint4B
+0x044 TimeDateStamp : Uint4B
+0x044 LoadedImports : Ptr32 Void
+0x048 EntryPointActivationContext : Ptr32 Void
+0x04c PatchInformation : Ptr32 Void

Et bien voilà tout ce que nous voulions. On a deux UNICODE_STRING qui nous permettent d’avoir le nom complet ou non des modules :
+0×024 FullDllName : _UNICODE_STRING
+0×02c BaseDllName : _UNICODE_STRING

Pour ceux qui ne connaissent pas voilà à quoi ressemble la struct UNICODE_STRING :

kd> dt nt!_UNICODE_STRING
+0x000 Length : Uint2B
+0x002 MaximumLength : Uint2B
+0x004 Buffer : Ptr32 Uint2B

Un dernier petit mot concernant notre liste double-chainée, celle-ci à la particularité de former un cercle. C’est à dire que le premier pointeur Blink pointe vers la dernière structure au lieu d’être null et de même pour le dernier Flink qui pointe vers la première structure.

Alors pour récapituler on a :

PEB +0×00c Ldr : Ptr32 _PEB_LDR_DATA
—>PEB_LDR_DATA +0×00c InLoadOrderModuleList : _LIST_ENTRY
—>_LDR_DATA_TABLE_ENTRY

Alors voici deux fonctions qui permettent de faire tout celà :

BYTE GetProcessLoaderData(HANDLE hProcess, PEB peb, PPEB_LDR_DATA pPebLdrData)
{
     DWORD dwBytesRead = 0x0;

     if(!ReadProcessMemory(hProcess, peb.LoaderData, pPebLdrData, sizeof(PEB_LDR_DATA), &dwBytesRead) || dwBytesRead < sizeof(PEB_LDR_DATA))
     {
                                     DisplayError("ReadProcessMemory", 1);
                                     return 0x0;
     }

     return 0x1;
}
VOID DumpModules(HANDLE hProcess, PEB_LDR_DATA LoaderData)
{
     LDR_DATA_TABLE_ENTRY LoaderTable = {0x0};

     PLIST_ENTRY pCurrentList = NULL;
     PLIST_ENTRY pStart = NULL;

     PUNICODE_STRING pFullDllName = NULL;

     //Dump des modules par ordre de chargement

    pStart = LoaderData.InLoadOrderModuleList.Blink;
    pCurrentList = LoaderData.InLoadOrderModuleList.Flink;

    while(pCurrentList != pStart)
    {
            if(!ReadProcessMemory(hProcess, pCurrentList, &LoaderTable, sizeof(LDR_DATA_TABLE_ENTRY), NULL))
                                            DisplayError("ReadProcessMemory", 1);

            pFullDllName = VirtualAlloc(NULL, LoaderTable.FullDllName.Length, MEM_COMMIT, PAGE_READWRITE);

            if(!ReadProcessMemory(hProcess, LoaderTable.FullDllName.Buffer, pFullDllName, LoaderTable.FullDllName.Length, NULL))
                                            DisplayError("ReadProcessMemory", 1);

            printf("\nFull name : \n%ws", pFullDllName);
            printf("\nImageBase : 0x%x", LoaderTable.DllBase);
            printf("\nSizeOfImage : 0x%x\n", LoaderTable.SizeOfImage);

            VirtualFree(pFullDllName, 0, MEM_RELEASE);

            pCurrentList = LoaderTable.InLoadOrderLinks.Flink;
    }
}

II. Getting PEB

Ok c’est bien beau tout ça mais comment on le récupère ce PEB ?
Après avoir cherché dans les exports de ntdll.dll je ne trouve que l’API RtlGetCurrentPeb(). Nous on veux pouvoir obtenir le PEB de n’importe quel processus, pas seulement le notre.

Méthode 1 :
J’ai ensuite eu l’idée de m’intéresser à la structure EPROCESS :

kd> dt nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
+0x080 RundownProtect : _EX_RUNDOWN_REF
+0x084 UniqueProcessId : Ptr32 Void
+0x088 ActiveProcessLinks : _LIST_ENTRY
+0x090 QuotaUsage : [3] Uint4B
+0x09c QuotaPeak : [3] Uint4B
+0x0a8 CommitCharge : Uint4B
+0x0ac PeakVirtualSize : Uint4B
+0x0b0 VirtualSize : Uint4B
+0x0b4 SessionProcessLinks : _LIST_ENTRY
+0x0bc DebugPort : Ptr32 Void
+0x0c0 ExceptionPort : Ptr32 Void
+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE
+0x0c8 Token : _EX_FAST_REF
+0x0cc WorkingSetLock : _FAST_MUTEX
+0x0ec WorkingSetPage : Uint4B
+0x0f0 AddressCreationLock : _FAST_MUTEX
+0x110 HyperSpaceLock : Uint4B
+0x114 ForkInProgress : Ptr32 _ETHREAD
+0x118 HardwareTrigger : Uint4B
+0x11c VadRoot : Ptr32 Void
+0x120 VadHint : Ptr32 Void
+0x124 CloneRoot : Ptr32 Void
+0x128 NumberOfPrivatePages : Uint4B
+0x12c NumberOfLockedPages : Uint4B
+0x130 Win32Process : Ptr32 Void
+0x134 Job : Ptr32 _EJOB
+0x138 SectionObject : Ptr32 Void
+0x13c SectionBaseAddress : Ptr32 Void
+0x140 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK
+0x144 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY
+0x148 Win32WindowStation : Ptr32 Void
+0x14c InheritedFromUniqueProcessId : Ptr32 Void
+0x150 LdtInformation : Ptr32 Void
+0x154 VadFreeHint : Ptr32 Void
+0x158 VdmObjects : Ptr32 Void
+0x15c DeviceMap : Ptr32 Void
+0x160 PhysicalVadList : _LIST_ENTRY
+0x168 PageDirectoryPte : _HARDWARE_PTE
+0x168 Filler : Uint8B
+0x170 Session : Ptr32 Void
+0x174 ImageFileName : [16] UChar
+0x184 JobLinks : _LIST_ENTRY
+0x18c LockedPagesList : Ptr32 Void
+0x190 ThreadListHead : _LIST_ENTRY
+0x198 SecurityPort : Ptr32 Void
+0x19c PaeTop : Ptr32 Void
+0x1a0 ActiveThreads : Uint4B
+0x1a4 GrantedAccess : Uint4B
+0x1a8 DefaultHardErrorProcessing : Uint4B
+0x1ac LastThreadExitStatus : Int4B
+0x1b0 Peb : Ptr32 _PEB
+0x1b4 PrefetchTrace : _EX_FAST_REF
+0x1b8 ReadOperationCount : _LARGE_INTEGER
+0x1c0 WriteOperationCount : _LARGE_INTEGER
+0x1c8 OtherOperationCount : _LARGE_INTEGER
+0x1d0 ReadTransferCount : _LARGE_INTEGER
+0x1d8 WriteTransferCount : _LARGE_INTEGER
+0x1e0 OtherTransferCount : _LARGE_INTEGER
+0x1e8 CommitChargeLimit : Uint4B
+0x1ec CommitChargePeak : Uint4B
+0x1f0 AweInfo : Ptr32 Void
+0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
+0x1f8 Vm : _MMSUPPORT
+0x238 LastFaultCount : Uint4B
+0x23c ModifiedPageCount : Uint4B
+0x240 NumberOfVads : Uint4B
+0x244 JobStatus : Uint4B
+0x248 Flags : Uint4B
+0x248 CreateReported : Pos 0, 1 Bit
+0x248 NoDebugInherit : Pos 1, 1 Bit
+0x248 ProcessExiting : Pos 2, 1 Bit
+0x248 ProcessDelete : Pos 3, 1 Bit
+0x248 Wow64SplitPages : Pos 4, 1 Bit
+0x248 VmDeleted : Pos 5, 1 Bit
+0x248 OutswapEnabled : Pos 6, 1 Bit
+0x248 Outswapped : Pos 7, 1 Bit
+0x248 ForkFailed : Pos 8, 1 Bit
+0x248 HasPhysicalVad : Pos 9, 1 Bit
+0x248 AddressSpaceInitialized : Pos 10, 2 Bits
+0x248 SetTimerResolution : Pos 12, 1 Bit
+0x248 BreakOnTermination : Pos 13, 1 Bit
+0x248 SessionCreationUnderway : Pos 14, 1 Bit
+0x248 WriteWatch : Pos 15, 1 Bit
+0x248 ProcessInSession : Pos 16, 1 Bit
+0x248 OverrideAddressSpace : Pos 17, 1 Bit
+0x248 HasAddressSpace : Pos 18, 1 Bit
+0x248 LaunchPrefetched : Pos 19, 1 Bit
+0x248 InjectInpageErrors : Pos 20, 1 Bit
+0x248 VmTopDown : Pos 21, 1 Bit
+0x248 Unused3 : Pos 22, 1 Bit
+0x248 Unused4 : Pos 23, 1 Bit
+0x248 VdmAllowed : Pos 24, 1 Bit
+0x248 Unused : Pos 25, 5 Bits
+0x248 Unused1 : Pos 30, 1 Bit
+0x248 Unused2 : Pos 31, 1 Bit
+0x24c ExitStatus : Int4B
+0x250 NextPageColor : Uint2B
+0x252 SubSystemMinorVersion : UChar
+0x253 SubSystemMajorVersion : UChar
+0x252 SubSystemVersion : Uint2B
+0x254 PriorityClass : UChar
+0x255 WorkingSetAcquiredUnsafe : UChar
+0x258 Cookie : Uint4B

Et on voit bien un pointeur vers le PEB :
+0×1b0 Peb : Ptr32 _PEB
Voyons un peu cette structure de plus près et notamment ce paramètre :
+0×088 ActiveProcessLinks : _LIST_ENTRY
On retrouve une structure LIST_ENTRY déjà présentée plus haut. Et le nom du paramètre est assez parlant pour qu’on comprenne qu’on a une liste double-chainée des structures EPROCESS de chaque processus actif.

Essayons avec le kd de voir à quelle addresse se situe cette structure en prenant pour exemple explorer.exe :
kd> !process 0 0 explorer.exe
PROCESS 81625020 SessionId: 0 Cid: 0580 Peb: 7ffdf000 ParentCid: 0548
DirBase: 09328000 ObjectTable: e15b4978 HandleCount: 273.
Image: explorer.exe

Et là on s’aperçoit que la structure EPROCESS du processus est à l’adresse 0×81625020 et donc pas en user-land mais en kernel-land. On serait donc obligé de coder un driver pour la lire. Pour ceux qui veulent s’y essayer il suffit d’apeler la fonction IoGetCurrentProcess() et parcourir la liste des EPROCESS jusqu’à trouvé la structure voulue. Voyez plutôt le code d’0vercl0k. C’est faisable mais bon dans notre cas on va essayer de faire autrement.

Méthode 2

J’ai ensuite voulu me pencher sur la fonction NtQueryInformationProcess() :

NTSTATUS WINAPI NtQueryInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);

On voit que cette fonction permet de récupérer la structure PROCESSINFOCLASS. Structure qui restée mystérieuse jusqu’à ce que Neitsa finisse de nous divulguer ces secrets :) .

On a donc maintenant :

typedef enum _PROCESSINFOCLASS
{
ProcessBasicInformation = 0,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers, // Note: this is kernel mode only
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
MaxProcessInfoClass,
ProcessWow64Information = 26
ProcessImageFileName,//27
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,//30
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessTlsInformation,//35
ProcessCookie,
ProcessImageInformation,//dernier cas possible sous Win XP SP2
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback,
MaxProcessInfoClass
}PROCESSINFOCLASS;

Le seul paramètre qui va m’intéresser ici est ProcessBasicInformation, un pointeur vers la structure PROCESS_BASIC_INFORMATION :


typedef struct _PROCESS_BASIC_INFORMATION {
long ExitStatus;
PPEB PebBaseAddress;
unsigned long AffinityMask;
long BasePriority;
unsigned long UniqueProcessId;
unsigned long InheritedFromUniqueProcessId;
}PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

Miracle, on a enfin retrouvé notre PEB \o/ : PPEB PebBaseAddress;

Alors récapitulons tout ceci :

Récup du PEB:

IoGetCurentProcess()

—>EPROCESS + +0×1b0 Peb : Ptr32 _PEB

ou

NtQueryInformationSystem()

—> PROCESSINFOCLASS +0×01 PPROCESS_BASIC_INFORMATION ProcessBasicInformation

—> PROCESS_BASIC_INFORMATION +0x04 PPEB PebBaseAddress;

Je n’est développé que la dernière alternative et ceci donne :

typedef ULONG (NTAPI *lpfNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

BYTE GetProcessPEB(HANDLE hProcess, PPEB pPeb)
{
    SetLastError(0x0);

    lpfNtQueryInformationProcess NtQueryInformationProcess = NULL;

    PROCESS_BASIC_INFORMATION pbi = {0x0};
    NTSTATUS status;
    DWORD dwLength;
    HMODULE hModule = NULL;

    hModule = GetModuleHandleA("ntdll.dll");
    if(hModule == NULL)
    {
               DisplayError("GetModuleHandleA", 0);
               return 0x0;
    }

    NtQueryInformationProcess = (lpfNtQueryInformationProcess)GetProcAddress(hModule, "NtQueryInformationProcess");
    FreeLibrary(hModule);
    if(NtQueryInformationProcess == NULL)
    {
                                DisplayError("GetProcAddress", 0);
                                return 0x0;
    }

    //Attention : ici je ne lis que le premier paramètre de la structure PROCESSINFOCLASSS et donc directement PROCESS_BASIC_INFORMATION

    status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), &dwLength);

    if(status != 0x0)
    {
              DisplayError("NtQueryInformationProcess", 1);
              printf("\n                                [+] NTSTATUS : 0x%x", status);
    }

    printf("\n\nPEB address : 0x%x", pbi.PebBaseAddress);

    DWORD dwBytesRead = 0x0;

    if(!ReadProcessMemory(hProcess, pbi.PebBaseAddress, pPeb, sizeof(PEB), &dwBytesRead) || dwBytesRead < sizeof(PEB))
                                    DisplayError("ReadProcessMemory", 1);

    return 0x1;
}

Voilà donc comme je disais tout à l’heure le contexte est différent de celui de YoLeJedi. Bref on arrive quand même à lister nos modules dans dans l’ordre de chargement donc on pourrait très bien se dévelloper une fonction qui renvoi le nom du dernier module chargé en ayant au préalable récupérer notre PEB. Ce n’est pas très rapide, mais pas excessivement lent nonplus. Et avoir un accès au PEB peux être utile en debugging.
Je fournis le code+binaire ici.

Voilà ce que donne mon programme en le testant sur explorer.exe :


[+] Process name : explorer.exe
[+] Process id : 0x360

PEB address : 0×7ffdf000
Being Debugged : 0×0
Dumping Modules :

Full name :
C:\WINDOWS\Explorer.EXE
ImageBase : 0×1000000
SizeOfImage : 0xf2000

Full name :
C:\WINDOWS\system32\ntdll.dll
ImageBase : 0×7c910000
SizeOfImage : 0xb6000

Full name :
C:\WINDOWS\system32\kernel32.dll
ImageBase : 0×7c800000
SizeOfImage : 0×106000

Full name :
C:\WINDOWS\system32\ADVAPI32.dll
ImageBase : 0×77da0000
SizeOfImage : 0xac000

Full name :
C:\WINDOWS\system32\RPCRT4.dll
ImageBase : 0×77e50000
SizeOfImage : 0×92000

Full name :
C:\WINDOWS\system32\Secur32.dll
ImageBase : 0×77fc0000
SizeOfImage : 0×11000

Full name :
C:\WINDOWS\system32\BROWSEUI.dll
ImageBase : 0×75f10000
SizeOfImage : 0xfd000

Full name :
C:\WINDOWS\system32\GDI32.dll
ImageBase : 0×77ef0000
SizeOfImage : 0×49000

Full name :
C:\WINDOWS\system32\USER32.dll
ImageBase : 0×7e390000
SizeOfImage : 0×91000

Full name :
C:\WINDOWS\system32\msvcrt.dll
ImageBase : 0×77be0000
SizeOfImage : 0×58000

Comment are closed.