在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

安全開發之堆分配內存加密簡析

蛇矛實驗室 ? 來源:蛇矛實驗室 ? 2023-03-08 09:43 ? 次閱讀

前言

在安全研發的過程中,難免會使用內存分配函數 malloc、重載的運算符 new 開啟堆內存用于長時間駐留一些數據,但這些數據可能對于防御者來說比較敏感,比如有時候,這些堆內存中可能會出現回連地址等。所以有必要對這些保留在堆內存中的敏感數據進行加密。

在進入堆分配內存加密之前,首先了解以下程序中堆棧的概念;

堆和棧是程序運行時保存數據的方式。

棧:通常來說棧用于存儲臨時數據,比如局部變量和函數調用的上下文信息,棧上的數據的生命周期隨著函數的調用和返回而自動管理,一般在作用域結束后被自動釋放;

堆:堆通常用于存儲想長期駐留在內存中的數據,比如一些需要長期存在的配置信息和一些需要共享的數據,堆上的數據的生命周期不受作用域的限制,一般在整個程序運行期間都存在,直到顯示地釋放它們。

由于堆上的數據的生命周期不受限制,除非顯式地釋放它們,否則它們將一直駐留在內存中,如果我們想保護這些數據,可以在內存中將存儲這些數據的堆內存進行加密,防止數據暴露。

堆分配內存加密

枚舉堆

在對堆進行操作之前,首先需要先枚舉進程內存中堆的信息,可以通過 HeapWalk 函數枚舉指定堆中的內存塊,其函數簽名如下:

BOOL HeapWalk(
  [in]   HANDLE        hHeap,
  [in, out] LPPROCESS_HEAP_ENTRY lpEntry
);

可以使用以下代碼枚舉進程內存中堆的信息

void EnumHeaps()
{
  PROCESS_HEAP_ENTRY entry;
  SecureZeroMemory(&entry, sizeof(entry));
  while (HeapWalk(GetProcessHeap(), &entry))
   {
    printf("heap addr: %p size: %d
", (char*)entry.lpData, entry.cbData);
   }
}

獲取了進程內存中的堆信息,就可以對指定類型的堆進行操作了,一般加密已分配的堆,需要注意的是,由于堆中的數據是線程共享的,所以,在加密堆數據之前,需要掛起所有線程(除了當前執行的線程),待操作結束后,恢復所有線程的執行。

掛起線程

可以使用 SuspendThread 掛起指定線程,需要注意的是,需要排除當前執行的線程。

void DoSuspendThreads(DWORD targetProcessId, DWORD targetThreadId)
{
  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if (h != INVALID_HANDLE_VALUE)
   {
    THREADENTRY32 te;
    te.dwSize = sizeof(te);
    if (Thread32First(h, &te))
     {
      do
       {
        if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
         {
          // Suspend all threads EXCEPT the one we want to keep running
          if (te.th32ThreadID != targetThreadId && te.th32OwnerProcessID == targetProcessId)
           {
            HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
            if (thread != NULL)
             {
              SuspendThread(thread);
              CloseHandle(thread);
             }
           }
         }
        te.dwSize = sizeof(te);
       } while (Thread32Next(h, &te));
     }
    CloseHandle(h);
   }
}

恢復線程

使用 ResumeThread 函數,可以讓掛起的線程恢復。

void DoResumeThreads(DWORD targetProcessId, DWORD targetThreadId)
{
  HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if (h != INVALID_HANDLE_VALUE)
   {
    THREADENTRY32 te;
    te.dwSize = sizeof(te);
    if (Thread32First(h, &te))
     {
      do
       {
        if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))
         {
          // Suspend all threads EXCEPT the one we want to keep running
          if (te.th32ThreadID != targetThreadId && te.th32OwnerProcessID == targetProcessId)
           {
            HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
            if (thread != NULL)
             {
              ResumeThread(thread);
              CloseHandle(thread);
             }
           }
         }
        te.dwSize = sizeof(te);
       } while (Thread32Next(h, &te));
     }
    CloseHandle(h);
   }
}

在安全研發的過程中,為了降低自動化分析對代碼的敏感度,通常會使用延遲代碼的執行速度,比如使用Sleep函數。

根據以上,進程中堆分配內存的步驟如下:

掛鉤 Sleep 函數

在 HookedSleep 函數內部:

掛起當前進程內所有線程(排除當前執行線程)

對已分配的堆進行加密

調用原始 Sleep 進行睡眠操作

恢復所有線程執行

void WINAPI HookedSleep(DWORD dwMiliseconds)
{
  DWORD time = dwMiliseconds;
  if (time > 1000)
   {
    printf("HookedSleep: suspend threads, strat encrypt heaps.
");
    DoSuspendThreads(GetCurrentProcessId(), GetCurrentThreadId());
    HeapEncryptDecrypt();

    OldSleep(dwMiliseconds);

    HeapEncryptDecrypt();
    DoResumeThreads(GetCurrentProcessId(), GetCurrentThreadId());
    printf("HookedSleep: decrypt heaps success, resume threads run.
");
   }
  else
   {
    OldSleep(time);
   }
}

當代碼中存在使用堆相關函數,比如 HeapAlloc 分配內存時,再比如使用 CRT 函數 malloc 和 重載的運算符 new 開辟堆空間時(其最終也是通過HeapAlloc函數分配),都可通過堆分配內存加密保護我們的數據。

c460339a-bcca-11ed-bfe3-dac502259ad0.png

下圖是在掛鉤了 Sleep 后,程序進入HookedSleep 函數未進行對加密之前我們在程序中分配的堆空間的原始數據。

c4790410-bcca-11ed-bfe3-dac502259ad0.png

在進行堆加密后,效果如下,可以看到,我們堆分配的內存已被加密。

c49c4e66-bcca-11ed-bfe3-dac502259ad0.png

目標線程堆分配空間加密

上文可以看到通過 HeapWalk 遍歷了進程中所有的堆信息,并在堆加密之前比如掛起所有的線程,這樣有一個缺點,就是只能針對自己寫的程序。

有時候我們的需要執行的功能代碼是通過注入到其它進程實現的,如果這樣冒然的將所有線程掛起,這有太多的不可預料性,可能會導致宿主程序崩潰。

所以需要有一種方式來實現只加密我們執行功能線程代碼中分配的堆內存。

由于通過注入 shellcode/dll 的方式執行功能,所以首要目標是獲取執行功能的線程ID,之后就是在代碼中 Hook 堆分配/釋放相關的函數,RtlAllocateHeap,RtlReAllocateHeap,RtlFreeHeap 函數,這樣就可以跟蹤線程代碼中堆分配釋放的狀態了。

獲取了線程堆分配釋放的情況,目標線程堆分配內存加密的代碼思路如下:

獲取當前執行線程ID

Hook RtlAllocateHeap,RtlReAllocateHeap,RtlFreeHeap

在 HookedRtlAllocateHeap、HookedRtlReAllocateHeap 函數內部

執行原始 OldRtlAllocateHeap、OldRtlReAllocateHeap,并記錄堆分配的地址和大小

篩選出我們的線程分配的堆內存:將堆分配信息添加進維護的堆分配信息數組中

HookedRtlFreeHeap 函數內部

得到需要釋放的地址

執行原始 OldRtlFreeHeap

篩選出我們的線程釋放的堆內存:將其移除維護的堆分配信息信息數組

當篩選出目標線程堆分配的內存信息時,就可以通過在 HookedSleep 函數中對填充好堆分配信息數組進行操作了。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • crt
    crt
    +關注

    關注

    2

    文章

    82

    瀏覽量

    36302
  • 加解密
    +關注

    關注

    0

    文章

    18

    瀏覽量

    6609

原文標題:安全開發之堆分配內存加密

文章出處:【微信號:蛇矛實驗室,微信公眾號:蛇矛實驗室】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Linux應用開發內存分配

    是長度可變的連續虛擬內存,始于進程未初始化數據段的末尾,將當前的內存邊界稱為 "program break"。
    發表于 05-08 11:17 ?636次閱讀
    Linux應用<b class='flag-5'>開發</b>之<b class='flag-5'>內存</b><b class='flag-5'>分配</b>

    【原創】內存的那些事

    作者:蔡琰老師(張飛實戰電子高級工程師)上一篇我們分享了棧內存的概念,現在我們分享下內存的概念。在一般的編譯系統中,內存
    發表于 07-12 09:48

    freertos與STM32如何分配堆棧空間

    freertos與STM32分棧、、全局區、常量區、代碼區、RAM、ROM,及如何分配堆棧空間基于STM32分棧、、全局區、常量區、
    發表于 08-03 06:36

    請問使用動態內存分配安全嗎?

    在使用完畢后,需要顯式的釋放,這就要求程序員對動態分配內存了然于胸。在非常重視安全(safety-critical)的嵌入式C語言程序開發
    發表于 12-15 06:10

    使用動態內存分配安全

    安全嗎?”為了更加安全穩定,美國軍方禁止在C語言程序中使用malloc()使用動態內存分配安全嗎?在C語言程序
    發表于 12-15 07:44

    關于RT-Thread內存管理的內存

    這篇文章繼續介紹 RT-Thread 內存管理剩下的部分——內存池。為何引入內存池?內存雖然方便靈活,但是存在明顯的缺點:
    發表于 04-06 17:02

    關于RT-Thread的動態內存管理

    管理算法只能啟用一個,但是提供給用戶的接口完全相同。注意事項:內存管理為了滿足多線程場景下的安全分配,考慮多線程間的互斥問題。因此,不要
    發表于 04-06 17:11

    有關RT-Thread操作系統的內存管理模塊基本知識

    塊大小將不能再做調整。  動態內存管理  動態內存管理是一個真實的(Heap)內存管理模塊。動態內存管理,即在
    發表于 05-11 15:14

    Armv8.1-M PAC和BTI擴展

    1、Armv8.1-M PAC和 BTI 擴展Armv8-M通過Trustzone for Armv8-M, Memory Protection Unit (MPU) 和Privileged
    發表于 08-05 14:56

    如何使用鏈接腳本刪除分配

    的 heap_symbol),這對我來說會更好,因為否則這個符號會得到它的地址,并且可以使用它的地址覆蓋內存。我的問題是,當我只是丟棄它時,我得到了期望此引用的 gcc 文件 (_cr_sbrk.c) 的引用錯誤。我想尋求幫助來實現我的目標,即安全地從鏈接器中刪除
    發表于 03-23 07:05

    鼠標HID例程(中)

    鼠標 HID 例程 緊接《鼠標 HID 例程(上)》一文,繼續向大家介紹鼠 標 HID 例程的未完的內容。
    發表于 07-26 15:18 ?0次下載

    Java開發者必須了解的內存技術

    先來看一個 Demo:在 Demo 中分配內存用的是 allocateDirect 方法,但其內部調用的是 DirectByteBuffer,換言之,DirectByteBuffer 才是實際操作
    發表于 07-01 10:19 ?3849次閱讀
    Java<b class='flag-5'>開發</b>者必須了解的<b class='flag-5'>堆</b>外<b class='flag-5'>內存</b>技術

    什么是內存內存是如何分配的?

    在一般的編譯系統中,內存分配方向和棧內存是相反的。當棧內存從高地址向低地址增長的時候,
    的頭像 發表于 07-05 17:58 ?1w次閱讀

    貿澤開售面向安全應用的英飛凌OPTIGA Trust M物聯網安全開發套件

    2023 年 5 月 11 日 – 專注于引入新品的全球半導體和電子元器件授權代理商貿澤電子 (Mouser Electronics) 即日起供貨英飛凌的OPTIGA? Trust M物聯網安全開發
    發表于 05-12 17:05 ?698次閱讀
     貿澤開售面向<b class='flag-5'>安全</b>應用的英飛凌OPTIGA Trust M物聯網<b class='flag-5'>安全開發</b>套件

    什么是內存?存儲方式是什么樣的?

    只有在內存里面才會發生內存泄漏的問題,在棧內存中不會發生內存泄漏。因為棧內存在自動
    的頭像 發表于 06-22 10:29 ?1371次閱讀
    什么是<b class='flag-5'>堆</b><b class='flag-5'>內存</b>?存儲方式是什么樣的?
    主站蜘蛛池模板: 美女黄网站 | 九九福利视频 | 99热官网| 拍拍拍拍拍拍拍无挡大全免费 | 免费看欧美一级特黄a大片 免费看欧美一级特黄a大片一 | xxxx性欧美高清 | 天天爱天天做天天爽夜夜揉 | 种子天堂bt | 让她爽的喷水叫爽乱 | 性久久久久久久久久 | 亚洲精品456人成在线 | 曰本性l交片视频视频 | bt天堂资源在线种子 | 高清成年美女黄网站色大 | 欧美中字 | 在线天堂网 | 精品少妇一区二区三区视频 | 国产色片| 中文字幕日本一区波多野不卡 | 亚洲人成网站色在线观看 | 激情综合婷婷丁香六月花 | 色综合婷婷 | 开心丁香婷婷深爱五月 | h小视频在线观看 | 成人免费精品视频 | 欧美视频一区在线观看 | 亚洲jizzjizz妇女 | 亚洲色图综合图区 | 伊人精品久久久大香线蕉99 | 午夜在线播放视频 | 亚洲三级在线免费观看 | 色多多高清在线观看视频www | 四虎影院新网址 | 日本三级理论 | 嘿嘿嘿视频在线观看 | 色婷婷亚洲综合五月 | japanese日本护士xx亚洲 | 日本国产黄色片 | 色狠狠狠狠综合影视 | 久久免 | 亚洲高清免费观看 |