<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-27 07:16:51

    注冊表

    在我們的計算機里面,有一些程序是可以設置成開機自啟的,這種程序一般都是采用往注冊表里面添加鍵值指向自己的程序路徑來實現開機自啟

    在windows里面開機自啟的注冊表路徑如下

    //用戶級
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
    

    //管理員權限
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
    

    那么我們知道了計算機系統啟動程序時會自動加載注冊表里面的路徑,那么我們實現的思路就是打開Run這個目錄的注冊表,然后修改注冊表數據這個項目指向的路徑即可

    User

    首先使用RegOpenKeyEx打開Software\\Microsoft\\Windows\\CurrentVersion\\Run這個注冊表

    ::RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey)
    

    這里作一個判斷,如果不存在這個路徑則用RegCreateKeyW這個api創建注冊表路徑

    ::RegCreateKeyW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey)
    

    然后使用RegSetValueEx這個api來修改注冊表值,完成后關閉句柄即可

    ::RegSetValueEx(hKey, lpszValueName, 0, REG_SZ, (BYTE*)lpszFileName, (::lstrlenW(lpszFileName) + 16))
    ::RegCloseKey(hKey)
    

    完整代碼如下

    DWORD REUserRegedit(LPWSTR lpszValueName, LPWSTR lpszFileName)
    {
        HKEY hKey;
    if(ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_CURRENT_USER,
            L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_WRITE, &hKey))
    {
            printf("[!] RegOpenKeyEx not found, try create keyvalue");
    if(ERROR_SUCCESS != ::RegCreateKeyW(HKEY_CURRENT_USER,
                L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey))
    {
                printf("[!] RegCreateKeyW failed, error is : %d", GetLastError());
    return FALSE;
    }
    else
    {
                printf("[*] RegCreateKeyW successfully!");
    }
    }
    else
    {
            printf("[*] RegOpenKeyEx successfully!");
    }
    if(ERROR_SUCCESS != ::RegSetValueEx
    (hKey, lpszValueName, 0, REG_SZ, (BYTE*)lpszFileName, (::lstrlenW(lpszFileName) + 16)))
    {
    ::RegCloseKey(hKey);
            printf("[!] RegSetValueEx failed, error is : %d", GetLastError());
    return FALSE;
    }
    else
    {
            printf("[*] RegSetValueEx successfully!");
    }
    ::RegCloseKey(hKey);
    return TRUE;
    }
    

    這里我帶參數進去調試一下

    可以看到注冊表已經添加成功,重啟之后就會自動去運行這個路徑的exe

    Administrator

    這里我本來以為把RegOpenKeyEx改成HKEY_LOCAL_MACHINE就可以了

    但是報錯如下,說不存在這個路徑,但是我去注冊表里面看卻是存在這個路徑的

    這里百度過后發現在64位系統里面關鍵的注冊表被重定位了,修改后的路徑為

    HKEY_LOCAL_MACHINE\\Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Run
    

    修改一下即可,這列重啟后計算機就會自動去啟動

    之前我們提到有一個HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce這個路徑,也是能夠添加指向程序的路徑來實現自啟動的,這里跟之前有一點不同的就是這個路徑下的key在重啟后執行一次就會自動刪除,而Run目錄下的注冊表如果不去管他他會一直存在

    快速啟動目錄

    快速啟動目錄是一種不用修改任何系統數據,并且實現起來最為簡單的開機自啟動方法。只要把程序放入快速啟動文件夾中,系統在啟動時就會自動加載并運行相應的程序,實現開機自啟動功能。

    不過對于不同的計算機啟動目錄都是不一樣的,原因是因為進入Users這個目錄之后,賬戶的名稱都不相同,默認情況下快速啟動的路徑在C:\Users\用戶名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup,如圖所示,我們將自己的exe放到這個目錄下即可

    因為這里每臺計算機的目錄都不同,所以需要用到api來獲取路徑,使用到的是SHGetSpecialFolderPath

    BOOL SHGetSpecialFolderPath(
        HWND hwndOwner,
        LPTSTR lpszPath,
    int nFolder,
        BOOL fCreate)
    

    首先獲取當前計算機的快速啟動目錄

    ::SHGetSpecialFolderPath(NULL, szStartupPath, CSIDL_STARTUP, TRUE)
    

    使用wsprintf放入緩沖區

    ::wsprintf(szDestFilePath, (LPCWSTR)"%s\\%s", szStartupPath, lpszDestFileName);
    

    然后使用CopyFile拷貝到快速啟動路徑

    ::CopyFile(lpszSrcFilePath, szDestFilePath, FALSE)::CopyFile(lpszSrcFilePath, szDestFilePath, FALSE)
    

    完整代碼如下

    DWORD AutoSetup(char* lpszSrcFilePath, char* lpszDestFileName)
    {
        CHAR szStartupPath[MAX_PATH] = { 0};
        CHAR szDestFilePath[MAX_PATH] = { 0};
    if(FALSE == ::SHGetSpecialFolderPathA(NULL, szStartupPath, CSIDL_STARTUP, TRUE))
    {
            printf("[!] Get szStartupPath failed, error is : %d", GetLastError());
    return FALSE;
    }
    else
    {
            printf("[*] The szStartupPath is : %s", szStartupPath);
    }
    ::wsprintfA(szDestFilePath, "%s\\%s", szStartupPath, lpszDestFileName);
    if(FALSE == ::CopyFileA(lpszSrcFilePath, szDestFilePath, FALSE))
    {
            printf("[!] CopyFile failed, error is : %d", GetLastError());
    return FALSE;
    }
    else
    {
            printf("[*] CopyFile successfully!");
    }
    return TRUE;
    }
    

    實現效果如下,可以看到已經被復制到了啟動項,重啟后即會自動啟動

    計劃任務

    這部分在進行代碼實現的過程中會用到COM組件的相關知識,因為知識儲備的原因,這里我就不展開細說這部分的具體操作,只能大概說一下實現的流程

    使用COM組件之前需要調用CoInitialize來初始化COM接口環境,再使用CoCreateInstance創建服務對象ITaskService并連接到任務服務上,再從ITaskService對象中獲取根任務Root Task Folder的指針對象ITaskFolder,指向的是新注冊的任務,到這里初始化操作就已經完成,代碼實現如下

    CMyTaskSchedule::CMyTaskSchedule(void)
    {
        m_lpITS = NULL;
        m_lpRootFolder = NULL;
    // 初始化COM
        HRESULT hr = ::CoInitialize(NULL);
    if(FAILED(hr))
    {
            printf("[!] CoInitialize failed", hr);
    return FALSE;
    }
    // 創建一個任務服務(Task Service)實例
        hr = ::CoCreateInstance(CLSID_TaskScheduler,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_ITaskService,
    (LPVOID*)(&m_lpITS));
    if(FAILED(hr))
    {
            printf("[!] CoCreateInstance failed", hr);
    return FALSE;
    }
    // 連接到任務服務(Task Service)
        hr = m_lpITS->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if(FAILED(hr))
    {
            printf("[!] ITaskService Connect failed", hr);
    return FALSE;
    }
    // 獲取Root Task Folder的指針,這個指針指向的是新注冊的任務
        hr = m_lpITS->GetFolder(_bstr_t("\\"), &m_lpRootFolder);
    if(FAILED(hr))
    {
            printf("[!] ITaskService GetFolder failed", hr);
    return FALSE;
    }
    }
    

    然后是創建計劃任務的操作,首先從ITaskService創建一個任務定義對象ITaskDefinition

    ITaskDefinition*pTaskDefinition = NULL;
    HRESULT hr = m_lpITS->NewTask(0, &pTaskDefinition);
    

    設置計劃任務的注冊信息&作者信息

    IRegistrationInfo*pRegInfo = NULL;
    CComVariant variantAuthor(NULL);
        variantAuthor = lpszAuthor;
        hr = pTaskDefinition->get_RegistrationInfo(&pRegInfo);
    if(FAILED(hr))
    {
            printf("pTaskDefinition::get_RegistrationInfo failed", hr);
    return FALSE;
    }
        hr = pRegInfo->put_Author(variantAuthor.bstrVal);
        pRegInfo->Release();
    

    再設置主題信息,包括登陸類型與運行權限

    IPrincipal*pPrincipal = NULL;
        hr = pTaskDefinition->get_Principal(&pPrincipal);
    if(FAILED(hr))
    {
            printf("pTaskDefinition->get_Principal failed", hr);
    return FALSE;
    }
        hr = pPrincipal->put_LogonType(TASK_LOGON_INTERACTIVE_TOKEN);
        hr = pPrincipal->put_RunLevel(TASK_RUNLEVEL_HIGHEST);  
        pPrincipal->Release();
    

    設置其他信息

    ITaskSettings*pSettting = NULL;
        hr = pTaskDefinition->get_Settings(&pSettting);
    if(FAILED(hr))
    {
            printf("pTaskDefinition->get_Settings failed", hr);
    return FALSE;
    }
        hr = pSettting->put_StopIfGoingOnBatteries(VARIANT_FALSE);
        hr = pSettting->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
        hr = pSettting->put_AllowDemandStart(VARIANT_TRUE);
        hr = pSettting->put_StartWhenAvailable(VARIANT_FALSE);
        hr = pSettting->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
        pSettting->Release();
    

    創建執行動作,包括設置執行程序的路徑和參數

    IActionCollection*pActionCollect = NULL;
        hr = pTaskDefinition->get_Actions(&pActionCollect);
    if(FAILED(hr))
    {
    ShowError("pTaskDefinition::get_Actions", hr);
    return FALSE;
    }
    IAction*pAction = NULL;
        hr = pActionCollect->Create(TASK_ACTION_EXEC, &pAction);
        pActionCollect->Release();
    

    再設置執行程序路徑和參數

    CComVariant variantProgramPath(NULL);
    CComVariant variantParameters(NULL);
    IExecAction*pExecAction = NULL;
        hr = pAction->QueryInterface(IID_IExecAction, (PVOID *)(&pExecAction));
    if(FAILED(hr))
    {
            pAction->Release();
    ShowError("IAction::QueryInterface", hr);
    return FALSE;
    }
        pAction->Release();
        variantProgramPath = lpszProgramPath;
        variantParameters = lpszParameters;
        pExecAction->put_Path(variantProgramPath.bstrVal);
        pExecAction->put_Arguments(variantParameters.bstrVal);
        pExecAction->Release();
    

    創建觸發器,實現用戶登錄的自啟動

    ITriggerCollection*pTriggers = NULL;
        hr = pTaskDefinition->get_Triggers(&pTriggers);
    if(FAILED(hr))
    {
    ShowError("pTaskDefinition::get_Triggers", hr);
    return FALSE;
    }
    ITrigger*pTrigger = NULL;
        hr = pTriggers->Create(TASK_TRIGGER_LOGON, &pTrigger);
    if(FAILED(hr))
    {
    ShowError("ITriggerCollection::Create", hr);
    return FALSE;
    }
    

    注冊計劃任務

    IRegisteredTask*pRegisteredTask = NULL;
    CComVariant variantTaskName(NULL);
        variantTaskName = lpszTaskName;
        hr = m_lpRootFolder->RegisterTaskDefinition(variantTaskName.bstrVal,
            pTaskDefinition,
            TASK_CREATE_OR_UPDATE,
    _variant_t(),
    _variant_t(),
            TASK_LOGON_INTERACTIVE_TOKEN,
    _variant_t(""),
    &pRegisteredTask);
    if(FAILED(hr))
    {
            pTaskDefinition->Release();
    ShowError("ITaskFolder::RegisterTaskDefinition", hr);
    return FALSE;
    }
        pTaskDefinition->Release();
        pRegisteredTask->Release();
    return TRUE;
    

    這里總代碼有點長,就不貼了,然后就是計劃任務的刪除就簡單許多,只需要調用ITaskFolderDeleteTask接口函數即可,代碼如下

    BOOL CMyTaskSchedule::Delete(char*lpszTaskName)
    {
    if(NULL == m_lpRootFolder)
    {
    return FALSE;
    }
    CComVariant variantTaskName(NULL);
        variantTaskName = lpszTaskName;
        HRESULT hr = m_lpRootFolder->DeleteTask(variantTaskName.bstrVal, 0);
    if(FAILED(hr))
    {
    return FALSE;
    }
    return TRUE;
    }
    

    這里嘗試一下創建名為cs的計劃任務成功,如下所示

    系統服務

    在任務管理器里面可以發現有許多系統服務進程在后臺運行,而且有很多應用事隨著系統的啟動而啟動的,如下圖所示

    系統服務運行在session0,有點基礎的同學都有一個0環、3環的概念,在0環里面各個對話是相互獨立的,在不同的會話中相互之間是不能夠進行通信的,這也是為什么在系統服務中不能顯示程序界面的原因

    這里使用系統服務創建自啟動服務的思路應該是打開句柄判斷操作,若為StartService則啟動服務,若為ControlService則停止服務,若為DeleteService則刪除服務。

    服務程序主函數(main)

    調用系統函數StartServiceCtrlDispatcher連接程序主線程到服務控制管理程序(其中定義了服務入口點函數是ServiceMain)。服務控制管理程序啟動服務程序后,等待服務程序主函數調用StartServiceCtrlDispatcher。如果沒有調用該函數,設置服務入口點,則會報錯。

    執行服務初始化任務(同時執行多個服務的服務有多個入口點函數),首先調用RegisterServiceCtrlHandler定義控制處理程序函數(本例中是ServiceCtrlHandle),初始化后通過SetServiceStatus設定進行運行狀態,然后運行服務代碼。

    控制處理程序(Handler)

    在服務收到控制請求時由控制分發線程引用(最少要有停止服務的能力)。

    我們首先創建啟動系統服務,首先是獲取文件名的操作

    ::lstrcpyA(szName, lpszDriverPath);
    ::PathStripPathA(szName);
    

    然后使用OpenSCManager打開服務控制管理器數據庫

    OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    

    打開數據庫后我們打開一個已經存在的服務

    OpenServiceA(shOSCM, szName, SERVICE_ALL_ACCESS);
    

    這里寫一個switch...case...的分支,0為加載服務,1為啟動服務,2為停止服務,3為刪除服務,這里CreateServiceA的第四個參數有兩種方式,一種是SERVICE_AUTO_START開機自啟,另外一種是SERVICE_DEMAND_START手動啟動

    // 創建服務
    shCS = ::CreateServiceA(shOSCM, szName, szName,SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
    SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,lpszDriverPath, NULL, NULL, NULL, NULL, NULL);
    // 啟動服務
    ::StartService(shCS, 0, NULL);
    // 停止服務
    ::ControlService(shCS, SERVICE_CONTROL_STOP, &ss);
    // 刪除服務
    ::DeleteService(shCS);
    

    最后關閉句柄

    ::CloseServiceHandle(shCS);
    ::CloseServiceHandle(shOSCM);
    

    我們再進行系統服務程序的編寫,自啟動服務程序要求程序創建服務入口點函數,否則就不能創建系統服務。

    首先我們注冊服務入口函數

    SERVICE_TABLE_ENTRY stDispatchTable[] = { { g_szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, { NULL, NULL } };
    ::StartServiceCtrlDispatcher(stDispatchTable);
    

    然后就是ServiceMain入口函數如下所示

    void __stdcall ServiceMain(DWORD dwArgc, char*lpszArgv)
    {
        g_ServiceStatus.dwServiceType = SERVICE_WIN32;
        g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
        g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
        g_ServiceStatus.dwWin32ExitCode = 0;
        g_ServiceStatus.dwServiceSpecificExitCode = 0;
        g_ServiceStatus.dwCheckPoint = 0;
        g_ServiceStatus.dwWaitHint = 0;
        g_ServiceStatusHandle = ::RegisterServiceCtrlHandler(g_szServiceName, ServiceCtrlHandle);
        g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        g_ServiceStatus.dwCheckPoint = 0;
        g_ServiceStatus.dwWaitHint = 0;
    ::SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
    while(TRUE)
    {
    Sleep(5000);
    DoTask();
    }
    }
    void __stdcall ServiceCtrlHandle(DWORD dwOperateCode)
    {
    switch(dwOperateCode)
    {
    case SERVICE_CONTROL_PAUSE:
    {
    // 暫停
            g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
    break;
    }
    case SERVICE_CONTROL_CONTINUE:
    {
    // 繼續
            g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    break;
    }
    case SERVICE_CONTROL_STOP:
    {
    // 停止
            g_ServiceStatus.dwWin32ExitCode = 0;
            g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            g_ServiceStatus.dwCheckPoint = 0;
            g_ServiceStatus.dwWaitHint = 0;
    ::SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
    break;
    }
    case SERVICE_CONTROL_INTERROGATE:
    {
    // 詢問
    break;
    }
    default:
    break;
    }
    }
    

    首先編譯生成ServiceTest.exe

    這里運行主程序之后發現ServiceTest.exe已經啟動

    打開服務管理,發現ServiceTest.exe已經正常運行

    printf開機啟動項
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    注冊表在我們的計算機里面,有一些程序是可以設置成開機自啟的,這種程序一般都是采用往注冊表里面添加鍵值指向自己的程序路徑來實現開機自啟在windows里面開機自啟的注冊表路徑如下//用戶級。
    mysql提權總結
    2021-09-17 15:04:08
    使用過MySQL的人都知道,MySQL有很多內置函數提供給使用者,包括字符串函數、數值函數、日期和時間函數等,給開發人員和使用者帶來了很多方便。
    一、前言 二、Windows入侵排查 檢查系統賬號安全 檢查異常端口、進程 檢查啟動項、計劃任務、服務 檢查系統相關信息 自動化查殺 日志分析 三、Linux入侵排查 賬號安全 歷史命令 檢查異常端口 檢查異常進程 檢查開機啟動項 檢查定時任務 檢查服務 檢查異常文件 檢查系統日志
    systeminfo | findstr /B /C:"OS Name" /C:"OS Version". systeminfo | findstr /B /C:"OS 名稱" /C:"OS 版本" #中文操作系統。schtasks /query /fo LIST /v #query顯示所有計劃任務。
    入侵者在入侵成功后,往往會留下后門以便再次訪問被入侵的系統,而創建系統賬號是一種比較常見的后門方式。在做入侵排查的時候,用戶配置文件/etc/passwd和密碼配置文件/etc/shadow是需要去重點關注的地方。查詢特權用戶特權用戶> awk -F: '$3==0{print $1}' /etc/passwd. 查找遠程可以登錄的賬戶> awk '/\$1|\$5|\$6/{print $1}' /etc/shadow. $1:MD5$5:SHA-256$6:SHA-512檢查sudo權限> cat /etc/sudoers | grep -v "^#\|^$" | grep "ALL=(ALL". 檢查計劃任務利用計劃任務進行權限維持,可作為一種持久性機制被入侵者利用。
    用戶名:加密密碼:密碼最后一次修改日期:兩次密碼的修改時間間隔:密碼有效期:密碼修改到期到的警告天數:密碼過期之后的寬限天數:賬號失效時間:保留。查看下pid所對應的進程文件路徑,
    應急響應之入侵排查
    2022-07-19 17:10:59
    常見的應急響應事件分類: Web入侵:網頁掛馬、主頁篡改、Webshell 系統入侵:病毒木馬、勒索軟件、遠控后門 網絡攻擊:DDOS攻擊、DNS劫持、ARP欺騙
    當企業發生網絡安全事件時,急需第一時間進行處理,使企業的網絡信息系統在最短時間內恢復正常工作,同時還需進一步查找入侵來源,還原入侵事故過程,給出解決方案與防范措施,為企業挽回或減少經濟損失。 常見的網絡安全事件:
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类