【學習筆記】《逆向工程核心原理》03.abex‘crackme-2、函數的調用約定、視頻講座-Tut.ReverseMe1

文章目錄

  • abex'crackme-2
    • 1. Visual Basic文件的特征
      • 1.1. VB專用引擎
      • 1.2. 本地代碼與偽代碼
      • 1.3. 事件處理程序
      • 1.4. 未文檔化的結構體
    • 2. 開始調試
      • 2.1. 間接調用
      • 2.2. RT_MainStruct結構體
      • 2.3. ThunRTMain()函數
    • 3. 分析crackme
      • 3.1. 檢索字符串
      • 3.2. 查找字符串地址
      • 3.3. 生成Serial的算法
      • 3.4. 預測代碼
      • 3.5. 讀取name字符串的代碼
      • 3.6. 加密循環
      • 3.7. 加密方法
  • 函數的調用約定
    • 1. 函數調用約定
      • 1.1. cdecl
      • 1.2. stdcall
      • 1.3. fastcall
  • 視頻講座-Tut.ReverseMe1
    • 1. 運行
    • 2. 分析
      • 2.1. 去除消息框
      • 2.2. 打補丁去除消息框
        • 2.2.1. 第一次嘗試
        • 2.2.2. 第二次嘗試
        • 2.2.3. 如何查看401C17 函數的參數個數
      • 2.3. 查找注冊碼

思維導圖
在這里插入圖片描述

abex’crackme-2

運行這個程序
Pasted image 20250312125103
要求我們輸入正確的賬戶與序列號

1. Visual Basic文件的特征

Visual Basic(VB)文件現在已經不太常見了,尤其是在現代開發環境中。微軟早在 2008 年就停止了對 VB6(經典 Visual Basic)的官方支持,而 VB.NET 作為 .NET 生態的一部分,雖然仍然在維護,但在開發者社區中的使用率已經大幅下降

此crackme是由 Visual Basic編寫而成的。所以我們可以先了解一下其特征

1.1. VB專用引擎

VB文件使用名為MSVBVM60.dll(MicrosoftVisual BasicVirtual Machine6.0)的VB專用引擎(也稱為TheThunder Runtime Engine)。
舉個使用VB引擎的例子,顯示消息框時,VB代碼中要調用 MsgBox 函數。其實,VB編輯器真正調用的是 MSVBVM60.dll 里的 rtcMsgBox 函數,在該函數內部通過調用 user32.dll 里的 MessageBoxW 函數(Win32API)來工作(也可以在VB代碼中直接調用 user32.dll 里的 MessageBoxW

1.2. 本地代碼與偽代碼

根據使用的編譯選項的不同,VB文件可以編譯為本地代碼(Ncode)與偽代碼(Pcode)。
本地代碼一般使用易于調試器解析的IA-32指令
偽代碼是一種解釋器(Interpreter)語言,它使用由VB引擎實現虛擬機并可自解析的指令(字節碼)。因此,若想準確解析VB的偽代碼,就需要分析VB引擎并實現模擬器。

1.3. 事件處理程序

VB主要用來編寫GUI程序,IDE用戶界面本身也最適合于GUI編程。由于VB程序采用Windows操作系統的事件驅動方式工作,所以在mainWinMain中并不存在用戶代碼(希望調試的代碼),用戶代碼存在于各個事件處理程序(eventhandler)之中。
就上述abex’crackme ,用戶代碼在點擊Check按鈕時觸發的事件處理程序內。

1.4. 未文檔化的結構體

VB中使用的各種信息(Dialog、Control、Form、Module、Function等)以結構體形式保存在文件內部。由于微軟未正式公開這種結構體信息,所以調試VB文件會難一些。

2. 開始調試

首先在EP代碼中找到調用VB引擎的主函數 ThunRTMain()
Pasted image 20250312130223

00401232   $- FF25 A0104000 jmp     dword ptr ds:[0x4010A0]          ;  msvbvm60.ThunRTMain
00401238 > $  68 141E4000   push    0x401E14
0040123D   .  E8 F0FFFFFF   call    00401232                         ;  <jmp.&MSVBVM60.#100>

分析一下幾條命令
00401238 是EP的地址、命令 push 0x401E14RT_MainStruct 結構體的地址 401E14 壓入棧。
然后 call 00401232 調用 401232 處的指令。 即會跳轉到VB引擎的主函數 ThunRTMain() (前面壓入棧的401E14 的值作為 ThunRTMain() 的參數)

這就是VB文件的全部啟動代碼,非常簡單

2.1. 間接調用

40123D 地址處的 CALL 401232 命令用于調用 ThunRTMain 函數,這里使用了較為特別的技法。不是直接轉到 MSVBVM60.dll 里的 ThunRTMain 函數,而是通過中間 401232 地址處的 JMP 命令跳轉

這是VC++ 、VB編譯器中常用的間接調用法

4010A0 地址是IAT(Import Address Table,導入地址表)區域,包含著 MSVBVM60.ThunRTMain 函數的實際地址Pasted image 20250312131429

2.2. RT_MainStruct結構體

要注意的是 ThunRTMain 函數的參數 RT_MainStruct 結構體。這里,RT_MainStruct 結構體存在于 401E14 地址處,如圖所示。
Pasted image 20250312131808
微軟未公開 RT_MainStruct,但是有國外的逆向分析高手已經完成了對 RTMainStruct 結構體的分析,并公布在網絡上。
RT_MainStruct 結構體的成員是其他結構體的地址。也就是說,VB引擎通過參數傳遞過來的 RT_MainStruct 結構體獲取程序運行需要的所有信息。此處省略對RT_MainStruct結構體的詳細說明。

2.3. ThunRTMain()函數

圖中顯示了 ThunRTMain 代碼的開始部分,可以看到內存地址完全不同了。這是 MSVBVM60.dII 模塊的地址區域。換言之,我們分析的不是程序代碼,而是VB引擎代碼(現在還不需要分析如此龐大的代碼)
Pasted image 20250312132133

3. 分析crackme

當前我們很難直接去分析 RT_MainStruct 結構體。 需要找一個更簡單的方法
我們可以通過程序提示的字符串入手。因為程序會提示錯誤后的信息
Pasted image 20250312132335

3.1. 檢索字符串

查找->所有參考字符串
Pasted image 20250312132920
雙擊跳轉
Pasted image 20250312133052
我們這里找到了消息提示的調用函數
根據邏輯判斷。看到是會根據我們的 name 生成一個序列號。然后判斷是否正確,然后回顯信息
這里我們往上翻 去找一下那個判斷語句,而判斷語句一般就是一個跳轉命令
Pasted image 20250312135505
通過上面 call dword ptr ds:[0x401058] 命令調用 __vbaVarTstEq 函數比較(TEST命令)返回值(AX)后,由403332地址的條件轉移指令(JE指令)決定執行“真”代碼還是“假”代碼。

TEST:邏輯比較(Logical Compare)
與bit-wiselogical“AND’一樣(僅改變EFLAGS寄存器而不改變操作數的值)若2個操作數中一個為0,則AND運算結果被置為0->ZF=1。

JE:條件轉移指令(Jumpif equal)
若ZF=1,則跳轉。

3.2. 查找字符串地址

我們現在已經找到了比較函數 __vbaVarTstEq 的地址,那么上面的兩個push 就是傳入的函數參數
Pasted image 20250312135935
我們先調試到比較函數地址 403329
我們觀察上面的兩處指令
Pasted image 20250312144711
這里 SS:[EBP-44] 指的是棧內地址。它恰好就是函數聲明中的局部對象的地址(局部對象存儲再棧區)
下面信息顯示了棧內地址為 19f288

我們可以通過 選中地址,然后在數據框中跟隨地址 即可查看對應的內存地址
Pasted image 20250312145117
查看存儲在棧中的內存地址
Pasted image 20250312145220
這里與C++的string類一樣,VB 字符串使用可變長度的字符串類型。 如圖,直接顯示的不是字符串,而是16字節大小的數據(這就是VB中使用的字符串對象)
不同的值被這樣統一起來,僅方框顯示的值是不同的,看上去就像內存地址一樣(可變長度字符串類型內部持有實際動態分配的字符串緩存地址)

我們右鍵選擇ASCII數據類型 即可查看到我們實際輸入的值進行對比的值
Pasted image 20250312145934
切回來選擇這個
Pasted image 20250312150014

Pasted image 20250312150408
如圖
EAX 19f298 是我們輸入的值 123456 字符串所在的地址是 66145c
EDX 19f288 是實際的序列號 C795D8D6 字符串所在地址是 6615c4
我們可以查看一下
Pasted image 20250312150812

VB默認使用基于Unicode的可變長度字符串對象。可變長度字符串對象會根據需要在內部隨時動態分配/釋放內存。因此,每次運行時字符串的地址會有所不同。此外,調試時無法一眼看全實際字符串,這也是調試的困難之一。

下面我們運行程序 輸入對應的名字與序列號即可彈出正確的信息
Pasted image 20250312151122

3.3. 生成Serial的算法

這里我們探討一下生成序列號的算法。 我們只知道了 c1trus 對應的序列號是 C795D8D6
那我們想批量生成序列號,肯定需要知道其算法

查找函數開始部分
我們上面找到了一個條件轉移的代碼。 那個應該就是check后進行的操作。當我們點擊check后,這個計算序列號的函數就會被調用執行。然后就會進行對比,并彈出消息框

所以我們應該往上一點點找函數開始的部分。
而且結合 [[07.棧幀]]中的知識。我們知道在執行函數之前會生成棧幀
通常命令是 PUSH EBP 然后 MOV EBP,ESP
那我們就著重看這個命令,也可以直接查找。
很容易就找到了生成棧幀的代碼
Pasted image 20250312152114
可以發現上面有大量的 nop命令

VB文件的函數之間存在著NOP指令(圖8-14的402ECC~402ECF地址區)。NOP:NoOperation,不執行任何動作的指令(只消耗CPU時鐘)。

為了方便分析代碼。我們先在此處下斷點

3.4. 預測代碼

如果你有經驗,就可以預測出生成序列號的方法,若是win32API程序
則一般有一下特點

  • 讀取Name字符串(使用 GetWindowsTextGetDlgItemText 等API)
  • 啟動循環,對字符進行加密(XOR ADD SUB 等)
    VB引擎編寫的文件也有類似的規律,如果正確的化,我們從斷點處開始調試,查找到讀取 name 字符串的那部分后,緊接著就是加密循環

3.5. 讀取name字符串的代碼

開始調試后我們會遇到好幾個 call
直到調試到第四個 call
Pasted image 20250312153525
上面的 lea edx,dword ptr ss:[ebp-0x88] 指令把函數的局部對象 ss:[ebp-0x88] 地址傳遞給了函數的參數。 我們可以看一下這個地址
Pasted image 20250312160419

因為要查找的是Name字符串,在VB中,字符串使用字符串對象(這與C語言使用char數組不同)我們很難認出實際的字符串,所以需要調整一下地址視圖的模式

然后繼續調試到 call 函數之后
Pasted image 20250312160732
這里我們可以可以看到 name 字符串的值了。 其地址就是 19F244 就是 EBP-88

3.6. 加密循環

繼續調試就會遇到以下循環。一系列的循環語句
Pasted image 20250312161137
Pasted image 20250312161215
Pasted image 20250312161305

簡單講解上述循環的動作原理,就像在鏈表中使用next指針引用下一個元素一樣,
__vbaVarForInit__vbaVarForNext 可以使逆向分析人員在字符串對象中逐個引I用字符。并且設置loopcount(EBX)使其按指定次數運轉循環。

實測僅使用接收的Name字符串中的前4個字符。在代碼內檢查字符串的長度,若少于4個字符,就會彈出錯誤消息框。

3.7. 加密方法

這里太難整了。我先跳過了。等以后再來分析

函數的調用約定

1. 函數調用約定

CallingConvention譯成中文是“函數調用約定”,它是對函數調用時如何傳遞參數的一種約定
通過前面的學習已經知道,調用函數前要先把參數壓人棧然后再傳遞給函數。棧就是定義在進程中的一段內存空間,向下(低地址方向)擴展,且其大小被記錄在PE頭中。也就是說,進程運行時確定棧內存的大小(與malloc/new動態分配內存不同)。

提問1.函數執行完成后,棧中的參數如何處理?
回答1.不用管。
由于只是臨時使用存儲在棧中的值,即使不再使用,清除工作也會浪費CPU資源。下一次再向棧存人其他值時,原有值會被自然覆蓋掉,并且棧內存是固定的,所以既不能也沒必要釋放內存。
提問2.函數執行完畢后,ESP值如何變化?
回答2.ESP值要恢復到函數調用之前,這樣可引用的棧大小才不會縮減。棧內存是固定的,ESP用來指示棧的當前位置,若ESP指向棧底,則無法再使用該棧。函數調用后如何處理ESP,這就是函數調用約定要解決的問題。主要的函數調用約定如下。
cdecl
stdcall
fastcall
應用程序的調試中,cdecl與stdcall的區別非常明顯。不管采用哪種方式,通過棧來傳遞參數的基本概念都是一樣的。

調用者——調用函數的一方。
被調用者——被調用的函數。
比如在 main 函數中調用 printf 函數時,調用者為 main,被調用者為 printf

1.1. cdecl

cdecl是主要在C語言中使用的方式,調用者負責處理棧
示例代碼

#include "stdio.h"
int add(int a ,int b)
{return a+b;
}
int main(int argc , char* argv[])
{return add(1,2);
}

編譯后進行調試
Pasted image 20250312184125從圖中401013~40101C地址間的代碼可以發現,add函數的參數1、2以逆序方式壓人棧,
調用 add 函數(401000)后,使用 ADD ESP,8 命令整理棧。調用者 main 函數直接清理其壓人棧的函數參數,這樣的方式即是cdecl

cdecl方式的好處在于,它可以像C語言的 printf 函數一樣,向被調用函數傳遞長度可變的參數。這種長度可變的參數在其他調用約定中很難實現。

1.2. stdcall

stdcall方式常用于Win32API,該方式由被調用者清理棧。前面講解過C語言默認的函數調用方式為cdecl。若想使用stdcall方式編譯源碼,只要使用 _stdcall 關鍵字即可
示例代碼

#include "stdio.h"
int _stdcall add(int a ,int b)
{return a+b;
}
int main(int argc , char* argv[])
{return add(1,2);
}

生成exe然后進行調試
從圖中的代碼可以看到,在 main 函數中調用 add 函數后,省略了清理棧的代碼ADD ESP,8)。棧的清理工作由 add 函數中最后(40100A)的 RETN 8 命令來執行。RETN 8 命令的含義為 RETN+POP 8 字節,即返回后使ESP增加到指定大小
Pasted image 20250312184056

像這樣在被調用者 add 函數內部清理棧的方式即為stdcall方式
stdcall方式的好處在于,被調用者函數內部存在著棧清理代碼,與每次調用函數時都要用 ADD ESP,XXX 命令的cdecl方式相比,代碼尺寸要小
雖然Win32API是使用C語言編寫的庫,但它使用的是stdcall方式,而不是C語言默認的cdecl方式。這是為了獲得更好的兼容性,使C語言之外的其他語言(Delphi(Pascal)、VisualBasic等)也能直接調用API。

1.3. fastcall

fastcall方式與stdcall方式基本類似,但該方式通常會使用寄存器(而非棧內存)去傳遞那些需要傳遞給函數的部分參數(前2個)。若某函數有4個參數,則前2個參數分別使用ECX、EDX寄存器傳遞。
顧名思義,fastcall方式的優勢在于可以實現對函數的快速調用(從CPU的立場看,訪問寄存器的速度要遠比內存快得多)。單從函數調用本身來看,fastcall方式非常快,但是有時需要額外的系統開銷來管理ECX、EDX寄存器。倘若調用函數前ECX與EDX中存有重要數據,那么使用它們前必須先備份。此外,如果函數本身很復雜,需要把ECX、EDX寄存器用作其他用途時,也需要將它們中的參數值存儲到另外某個地方。

視頻講座-Tut.ReverseMe1

一位名叫Lena的人在 http://www.tuts4you.com/ 公示板上貼了40個crackme講座,以幫助初學者學習代碼逆向分析技術。這些講座非常受歡迎,因為所有講座都以Flash視頻形式呈現出來,且讓學習者感到非常親切。各位可以鏈接到tuts4you網站觀看這些視頻講座,這對學習代碼逆向分析技術非常有幫助。

1. 運行

運行要破解的程序 給我們了兩條信息
Pasted image 20250312185009
就是說叫我們 去除提示框 并找到正確的注冊碼

2. 分析

2.1. 去除消息框

打開后發現也是用VB編寫的軟件,因為我們在EP中發現了 ThunRTMain
Pasted image 20250312185606

而且我們知道VB中調用消息框的函數是 rtcMsgBox
然后我們在調用模塊中去查找,可以發現有三次調用此函數
Pasted image 20250312190237
在每一處調用都設置一個斷點
Pasted image 20250312190333
然后運行程序
發現程序在 402CFE 處斷了下來,此時應該就是要調用函數進行顯示消息了。那么上面多半就有要顯示的消息。果不其然,上面確實可以發現將要顯示的消息
Pasted image 20250312190608

然后我們繼續運行,我們找一下程序中點擊 nag? 按鈕后的斷點在哪里
發現還是斷在了 402CFE 處。那么我們只要對這一處進行修復即可
Pasted image 20250312190941

2.2. 打補丁去除消息框

2.2.1. 第一次嘗試

我們先修改 402CFE 處的call命令
原來的
Pasted image 20250312191210
修改后的
Pasted image 20250312191249
402CFE 地址處的ADD ESP,14命令的含義是,按照傳遞給rtcMsgBox參數的大小(14)清理棧。并用NOP填充其余2個字節,以保證代碼不會亂(原來CALL命令的大小為5字節,ADD命令用3個字節,還余下2個字節)。
看上去沒有什么問題,但結果卻“發生錯誤”。原因在于沒有正確處理 rtcMsgBox 函數的返回值(EAX寄存器)。

如圖,在 402CFE 地址處調用 rtcMsgBox 函數后,402D0C 地址處將返回值(EAX)存儲到特定變量(EBP-9C)。此處消息框的返回值應該是1(表示“確定”按鈕)。若存儲的為1之外的值,則表示程序終止。那么最好試試其他方法。
Pasted image 20250312191746

(1)可以修改402CFE地址處的指令,如下所示。
ADD ESP,14 (Instruction:83C414)
MOV EAX,1 (Instruction:B801000000)

以上兩行匯編代碼產生的結果與調用 rtcMsgBox 函數后用戶按“確定”按鈕的結果相同(棧與返回值相同)。之所以沒有這樣做是因為指令長度不合適源文件 402CFE 地址處的命令長度為5字節,但上面2行匯編命令的長度為8個字節,因此會侵占到后面的代碼

(2)x86(IA-32)系統中使用EAX寄存器傳遞函數的返回值。

2.2.2. 第二次嘗試

在斷點處向上看可以發現 402C17 處表示函數開始的棧幀
Pasted image 20250312192122
402CFErtcMsgBox 函數調用代碼也是屬于其他函數內部的代碼。所以如果上層函數無法調用,或直接返回,最終將不會調用 rtcMsgBox 函數。像下面這樣修改401C17處的指令(使用AssembleSpace指令)。
原來的
Pasted image 20250312192226
修改后
Pasted image 20250312192322

要根據傳遞給函數的參數大小跳轉棧 (RETN XX)

然后運行 發現就去除了消息框

2.2.3. 如何查看401C17 函數的參數個數

首先找到 402C17 處函數的返回地址,在 402C17 下個斷點,并運行到這里
Pasted image 20250312195055
然后可以在棧空間看到返回的地址是 7401E5A9
goto過去看返回地址上一條命令。即執行此命令后就完成 402C17 函數。并返回地址到 7401E5A9
Pasted image 20250312195415
如圖所示 返回地址 (7401E5A9)。該代碼區域是 MSVBVM50.dll 模塊區域。執行 7401E5A7 地址處的 CALL EAX 指令后即返回 7401E5A9 地址處。再次運行調試器(Ctrl+F2),在 7401E5A7 地址處設置斷點后運行程序(F9),可以得知EAX的值為402656
Pasted image 20250312195550

此時會進入一個函數內部,并跳轉到 402656 地址處,
Pasted image 20250312195843
然后我們使用 ctrl+f9 發現最后會回到 402C17 地址處
所以調用 call eax 就是在調用 402c17 地址處的函數,那么我們只要確認 CALL EAX 命令(7401E5A7)調用前后的棧地址即可得知 402C17 函數參數的個數(因使用的是stdcall調用方式,所以棧由被調用者負責清理)

調用之前的地址 19fab8
Pasted image 20250312200339
調用之后的地址 19fab4
Pasted image 20250312200433
相差4

2.3. 查找注冊碼

首先先定位到注冊碼判斷的命令位置處
字符串找關鍵字符
Pasted image 20250312200613
跳轉過去,往上找判斷語句
Pasted image 20250312200804
這里發現調用了 __vbaStrCmp 函數。 __vbaStrCmp API是VB中用于比較字符串的函數。這里大概率就是與上面壓入棧中的參數 I'mlena151 進行比較
我們輸入進行驗證
Pasted image 20250312201027
成功了

PS:筆記僅記錄自己學習。里面有大量書中原文。如有侵權,請聯系我刪除。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/73403.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/73403.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/73403.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入解析Go語言Channel:源碼剖析與并發讀寫機制

文章目錄 Channel的內部結構Channel的創建過程有緩沖Channel的并發讀寫機制同時讀寫的可能性發送操作的實現接收操作的實現 并發讀寫的核心機制解析互斥鎖保護環形緩沖區等待隊列直接傳遞優化Goroutine調度 實例分析&#xff1a;有緩沖Channel的并發讀寫性能優化與最佳實踐緩沖…

初識Linux(14)Ext系列?件系統

之前談論的都是已打開文件在操作系統的中的管理&#xff0c;但是還有更多的文件沒有被打開&#xff0c;被存在磁盤中&#xff0c;如何管理這些磁盤中的文件&#xff0c;就是本篇的學習目標。 目錄 1.理解硬件 磁盤結構 扇區的讀寫 CHS地址定位 磁盤的邏輯結構 2. 引??件…

電機控制常見面試問題(十二)

文章目錄 一.電機鎖相環1.理解鎖相環2.電機控制中的鎖相環應用3.數字鎖相環&#xff08;DPLL&#xff09; vs 模擬鎖相環&#xff08;APLL&#xff09;4.鎖相環設計的關鍵技術挑戰5.總結 二、磁鏈觀測1.什么是磁鏈&#xff1f;2.為什么要觀測磁鏈&#xff1f;3.怎么觀測磁鏈&am…

Android `%d` 與 `1$%d` 格式化的區別

在 Android 開發中&#xff0c;我們經常需要對字符串進行格式化處理&#xff0c;比如動態填充數字、日期、字符等。 其中&#xff0c;%d 和 1$%d 都是格式化占位符&#xff0c;但它們在使用上有一些不同。 本文將詳細解析這兩者的區別&#xff0c;并結合 Kotlin 代碼示例幫助你…

SpringBoot中使用kaptcha生成驗證碼

簡介 kaptcha是谷歌開源的簡單實用的驗證碼生成工具。通過設置參數&#xff0c;可以自定義驗證碼大小、顏色、顯示的字符等等。 Maven引入依賴 <!-- https://mvnrepository.com/artifact/pro.fessional/kaptcha --><dependency><groupId>pro.fessional<…

如何在PHP中實現數據加密與解密:保護敏感信息

如何在PHP中實現數據加密與解密&#xff1a;保護敏感信息 在現代Web開發中&#xff0c;數據安全是一個至關重要的議題。無論是用戶的個人信息、支付數據&#xff0c;還是其他敏感信息&#xff0c;都需要在存儲和傳輸過程中進行加密&#xff0c;以防止數據泄露和惡意攻擊。PHP作…

單元測試、系統測試、集成測試、回歸測試的步驟、優點、缺點、注意點梳理說明

單元測試、系統測試、集成測試、回歸測試的梳理說明 單元測試 步驟&#xff1a; 編寫測試用例&#xff0c;覆蓋代碼的各個分支和邊界條件。使用測試框架&#xff08;如JUnit、NUnit&#xff09;執行測試。檢查測試結果&#xff0c;確保代碼按預期運行。修復發現的缺陷并重新測…

C++能力測試題

以下是一些C能力測試題&#xff0c;涵蓋了從基礎語法到高級特性的多個方面&#xff1a; 選擇題 1. 下面關于RTTI的說法&#xff0c;正確的是&#xff1f; A. 使用typeid前必須包含<type_info>頭文件。 B. typeid只能用于多態類型或表達式。 C. typeid可以用于不完整類型…

模擬類似 DeepSeek 的對話

以下是一個完整的 JavaScript 數據流式獲取實現方案&#xff0c;模擬類似 DeepSeek 的對話式逐段返回效果。包含前端實現、后端模擬和詳細注釋&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…

【訓練細節解讀】文本智能混合分塊(Mixtures of Text Chunking,MoC)引領RAG進入多粒度感知智能分塊階段

RAG系統在處理復雜上下文時,傳統和語義分塊方法的局限性,文本分塊的質量限制了檢索到的內容,從而影響生成答案的準確性。盡管其他算法組件有所進步,但分塊策略中的增量缺陷仍可能在一定程度上降低整體系統性能。如何直接量化分塊質量?如何有效利用大型語言模型(LLMs)進行…

IMA+DeepSeekR1+本地知識庫撰寫NOIP2008普及組T3【傳球游戲】題解

目錄 一、提問詞 二、DeepSeekR1回復 題目描述 解題思路 實現代碼 代碼說明 三、說明 【IMADeepSeekR1本地知識庫】撰寫NOIP2008普及組復賽題解系列 1、IMADeepSeekR1本地知識庫撰寫NOIP2008普及組T1【ISBN 號碼】題解-CSDN博客 2、IMADeepSeekR1本地知識庫撰寫NOIP200…

Nginx正向代理HTTPS配置指南(僅供參考)

要使用Nginx作為正向代理訪問HTTPS網站&#xff0c;需通過CONNECT方法建立隧道。以下是操作詳細步驟&#xff1a; 1. 安裝Nginx及依賴模塊 需要模塊&#xff1a;ngx_http_proxy_connect_module&#xff08;支持CONNECT方法&#xff09;。 安裝方式&#xff1a;需重新編譯Nginx…

Python 實現機器學習的 房價預測回歸項目

項目目標&#xff1a; 基于房屋特征&#xff08;如房間數、地理位置等&#xff09;預測加州地區的房價中位數。 使用 Python 實現機器學習的 房價預測回歸項目&#xff08;使用 California Housing 數據集&#xff09; 環境準備 # 安裝必要庫&#xff08;若未安裝&#xff09…

聚力·突破·共贏|修飾組學服務聯盟正式成立,共啟協同發展新篇章

2025年3月13日&#xff0c;上海——由中科新生命、杭州微米生物、廣科安德、承啟生物、派森諾生物、胡珀生物等十余家行業標桿企業共同發起的“修飾組學服務聯盟”成立儀式在上海紫竹新興產業技術研究院隆重舉行。聯盟以“聚力突破共贏”為主題&#xff0c;致力于整合修飾組學全…

【Docker項目實戰】使用Docker部署serverMmon青蛇探針(詳細教程)

【Docker項目實戰】使用Docker部署serverMmon青蛇探針 一、serverMmon介紹1.1 serverMmon 簡介1.2 主要特點二、本次實踐規劃2.1 本地環境規劃2.2 本次實踐介紹三、本地環境檢查3.1 檢查Docker服務狀態3.2 檢查Docker版本3.3 檢查docker compose 版本四、下載serverMmon鏡像五、…

力扣刷題(數組篇)

日期類 #pragma once#include <iostream> #include <assert.h> using namespace std;class Date { public:// 構造會頻繁調用&#xff0c;所以直接放在類里面&#xff08;類里面的成員函數默認為內聯&#xff09;Date(int year 1, int month 1, int day 1)//構…

【通縮螺旋的深度解析與科技破局路徑】

通縮螺旋的深度解析與科技破局路徑 一、通縮螺旋的形成機制與惡性循環 通縮螺旋&#xff08;Deflationary Spiral&#xff09;是經濟學中描述價格持續下跌與經濟衰退相互強化的動態過程&#xff0c;其核心邏輯可拆解為以下鏈條&#xff1a; 需求端萎縮&#xff1a;居民消費信…

單一責任原則在Java設計模式中的深度解析

在軟件開發中&#xff0c;設計模式提供了一種解決特定問題的思路。在眾多的設計原則中&#xff0c;單一責任原則&#xff08;Single Responsibility Principle&#xff0c;SRP&#xff09;是一個非常重要的概念。它主要強調一個類應該只有一個責任&#xff0c;也就是說&#xf…

開源后臺管理系統推薦

前言 在當今數字化時代&#xff0c;企業和組織對于管理和運營資源的需求日益增加。開源后臺管理系統應運而生&#xff0c;為用戶提供了一個靈活、可定制化的管理平臺。本文將介紹開源后臺管理系統的概念和優勢&#xff0c;探討常見的開源后臺管理系統&#xff0c;以及如何選擇…

原生微信小程序實現導航漫游(Tour)

效果&#xff1a; 小程序實現導航漫游 1、組件 miniprogram/components/tour/index.wxml <!--wxml--> <view class"guide" wx:if"{{showGuide}}"><view style"{{guideStyle}}" class"guide-box"><view class&quo…