Skip to content

rbmm/ExportPolicy

Repository files navigation


How to export certificate private key ( assume it not on smartcard but stored in file) even if it marked as not exportable ?

really this is possible and not too complex. are key is exportable or not saved in file/container, where private key is located too. all what we need - hook data after decrypt and set exportable flag

here 2 case exist - cert can use legacy CSP or CNG storage providers. (look for CRYPT_KEY_PROV_INFO Structure )

in case CSP we need hook CryptUnprotectData api in current process ( usually this is mmc.exe if user use UI )

and look for magic value in pOptionalEntropy - "Hj1diQ6kpUx7VC4m"

look for UnprotectExportabilityFlag

and

#define STUFF_TO_GO_INTO_MIX "Hj1diQ6kpUx7VC4m"

in case CNG is used we need inject dll to lsass. of course if it is PPL process, this is separate topic. but if not - no any problem do this

here we need hook CryptUnprotectDataNoUI from dpapi.dll and look for another magic

char DPAPI_ENTROPY_CNG_KEY_PROPERTIES[] = "6jnkd5J3ZdQDtrsu";

by fact we change result of call to NCryptGetProperty with NCRYPT_EXPORT_POLICY_PROPERTY (L"Export Policy") and set NCRYPT_ALLOW_EXPORT_FLAG|NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG (3)

and this is all.

so screenshots from debugger

CNG 1 1

CSP

1

code of DLL which do hooks/unhooks in src project. look for Entropy.cpp

for load/unload dll i use very simply project Inject this is console application, which inject dll to already runnig lsass/mmc and wait on key press. after this unload dll and exit


say we want use some api, but it not in any lib file. because lib for this DLL not exist at all, or exist, but this api not included for it

of course we can resolve api address at runtime, by LoadLibrary/GetProcAddress. but what if we want "static" link ? say we need use many functions ( as example certca.dll / certcli.dll export very many useful api and no exist lib files for both) we can build lib file, with this api by self. really this is not hard. we need only correct definitions of this api in DEF/OBJ file for build. the implementation can be empty

how is linker use DEF/OBJ for produce LIB/EXP (in DLL) ?

assume [p]AAA[s] is C/C++ decorated name , where [p] prefix and [s] suffix. and AAA undecorated form.

as example

in _ChrCmpIAStub@8 [p] is _, AAA is ChrCmpIAStub and [s] is @8

or in case ?HRGN_UserUnmarshal64@@YAPEAEPEAKPEAEPEAPEAUHRGN__@@@Z this is ? + HRGN_UserUnmarshal64 + @@YAPEAEPEAKPEAEPEAPEAUHRGN__@@@Z

logic of linker is next


  DEF          │  OBJ        │  LIB               │  EXP
───────────────┼─────────────┼────────────────────┼───────
AAA            │     AAA     >  __imp_AAA         │  AAA
AAA = BBB      │     BBB     >  __imp_AAA         │  AAA
AAA = mod.BBB  │     BBB     >  __imp_AAA         │  AAA ─> mod.BBB
AAA            │  [p]AAA[s]  >  __imp_[p]AAA[s]   │  AAA
AAA = BBB      │  [p]BBB[s]  >  __imp_[p]AAA[s]   │  AAA
AAA = mod.BBB  │  [p]BBB[s]  >  __imp_[p]AAA[s]   │  AAA ─> mod.BBB


examples with input (DEF/OBJ) and output (LIB/EXP)

DEF: ChrCmpIA = ChrCmpIAStub ───┐     ┌──        ChrCmpIA   : EXP
                                ├──>──┤ 
OBJ:           _ChrCmpIAStub@8──┘     └── __imp__ChrCmpIA@8 : LIB


DEF: HRGN_UserUnmarshal = HRGN_UserUnmarshal64 ────────────────────────────────────┐     ┌──        HRGN_UserUnmarshal                                  : EXP                    														   
                                                                                   ├──>──┤ 
OBJ:                     ?HRGN_UserUnmarshal64@@YAPEAEPEAKPEAEPEAPEAUHRGN__@@@Z ───┘     └── __imp_?HRGN_UserUnmarshal@@YAPEAEPEAKPEAEPEAPEAUHRGN__@@@Z : LIB


DEF: D3DKMTCreateDCFromMemory = NtGdiDdDDICreateDCFromMemory ─────┐     ┌──        D3DKMTCreateDCFromMemory   : EXP
                                                                  ├──>──┤ 
OBJ:                           _NtGdiDdDDICreateDCFromMemory@4 ───┘     └── __imp__D3DKMTCreateDCFromMemory@4 : LIB

while manually create LIB for 1-2 known api not hard ( if it not C++ decorated ), if we want create LIB for all api from some dll(s) ?

for this i write special project, MakeLib which parce DLL and produce .DEF/.ASM file. it also produce .H file if C++ api is found. look for certca.h and certcli.h as example also i just drop and ready .vcxproj files for this, with all ready settings - we need only open project in VS2022+ and build i build for test 17 lib projects ( with build.bat ) for different system dlls ( in Lib.sln )

all is builded without any manual fix. despite some dlls is very complex here - shlwapi, certcli - used many forward exports, ordinals, etc. forward to forward ( shlwapi.#56 -> USER32.DefWindowProcW -> NTDLL.NtdllDialogWndProc_W ) kernel32 used many API-..dlls, some of it recursive point to kernel32.dll back (so need not go to infinite loop while resolve forwards) , some to kernelbase or ntdll

and only in h files was one funny case - myDoesDSExist@209

resulted name ?myDoesDSExist@209@@YAJH@Z can not be undecorated due @ however long __cdecl myDoesDSExist(int); if remove @209 (more exactly only @)

for parsing mandatory have PDB files for dll itself and all it forwards export dll ( you can use my tool getpdb for easy download this)

for process with PDB itself i use own static lib project UPDB. for do this from kernel mode - KPDB can be used

About

Export not exported private key

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published