AWDPwn 漏洞加固總結


AWD簡介

AWD(Attack With Defense,攻防兼備) 模式需要在一場比賽里要扮演攻擊方和防守方,利用漏洞攻擊其他隊伍進行得分,修復漏洞可以避免被其他隊伍攻擊而失分。也就是說,攻擊別人的靶機可以獲取 Flag 分數時,別人會被扣分,同時也要保護自己的主機不被別人攻陷而扣分。

Patch-PWN

各家 awd 平台檢查機制各不相同,原則上是只針對漏洞點進行 patch 加固,也就是最小修改加固。以下總結不需要改動文件大小、針對漏洞點進行 patch 的幾種漏洞類型。

Patch資料

跳轉指令

  • 無符號跳轉

    匯編指令 描述
    JA 無符號大於則跳轉
    JNA 無符號不大於則跳轉
    JAE 無符號大於等於則跳轉(同JNB)
    JNAE 無符號不大於等於則跳轉(同JB)
    JB 無符號小於則跳轉
    JNB 無符號不小於則跳轉
    JBE 無符號小於等於則跳轉(同JNA)
    JBNE 無符號不小於等於則跳轉(同JA)
  • 有符號跳轉

    匯編指令 描述
    JG 有符號大於則跳轉
    JNG 有符號不大於則跳轉
    JGE 有符號大於等於則跳轉(同JNL)
    JNGE 有符號不大於等於則跳轉(同JL)
    JL 有符號小於則跳轉
    JNL 有符號不小於則跳轉
    JLE 有符號小於等於則跳轉(同JNG)
    JNLE 有符號不小於等於則跳轉(同JG)

Patch-整數溢出

image-20210710154128227

Scanf 以 long int 長整形讀取輸入到 unsigned int 變量 v2 中,然后將 v2 強制轉為 int 再與int 48 比較。

但從 scanf 讀入一個負數時,最高位為 1 ,從 unsigned int 強制轉換為 int 結果是負數,必定比 48 小,在后面 read 讀入會造成棧溢出。

Patch方法

將第 9 行的 if 跳轉匯編指令 patch 為無符號的跳轉指令,具體指令參考跳轉指令

使用 keypatach 進行修改

jle --> jbe

image-20210710155953262

image-20210710160006943

Patch-棧溢出

對於棧溢出加固,x64 更容易一些,因為是使用寄存器傳參,而x86 使用棧傳參,需要用 nop 等保持加固前后的空間不變。

x64

image-20210715165543609

Patch方法

100 是第三個參數,存儲寄存器是 rdx ,找到給 rdx 傳參的匯編指令進行 patch

使用 ida 默認修改插件修改(Edit-Patch Program-Change word),也可以用 keypatach :

0x64 是長度

0xBA 是操作符

image-20210710183002548

0x64 --> 0x20

image-20210710183212767

x86

不需要對齊

image-20210711004750198

找到壓棧的指令,修改壓入的數值

 

  • 修改數值需要補上 0x

  • 這里修改前 size 為 2 ,修改后 size 也為 2 ,所以這題 patch 不需要用 nop 保持 size

需要對齊

image-20210711180331314

找到壓棧的指令,修改壓入的數值

 

直接修改 0x20 后,size 長度不對齊,會引起棧空間變化,需要用 nop 進行對齊:

 

更方便快捷方法是勾選 NOPs padding until next instruction boundary 進行自動填充。

Patch-格式化字符串

image-20210711234054628

修改函數

將 printf 改為 puts ,將 call 的地址改為 puts plt 地址:

image-20210711234209674

這個方法局限性在於:puts 會在原字符串多加 \n ,主辦方 check 可能會因此而不通過

修改printf參數

printf(format) 修改為 printf("%s",format)

修改 printf 前面的傳參指令:

image-20210712000236624

mov edi, offset 0x400c01;
mov esi,offset format;

image-20210712000422524

Patch-UAF

image-20210713134230716

修改邏輯是劫持 call 指令跳轉到 .eh_frame 段上寫入的自定義匯編程序。

先在 .eh_frame 段上寫入代碼,首先是 call free 完成釋放,然后對 chunk_list 進行置零。取 chunk_list 地址的匯編可以從 call free 前面抄過來:

call 0x900;           #調用free函數(plt地址)

mov     eax, [rbp-0xc]; #取出下標值
cdqe;
lea     rdx, ds:0[rax*8];
lea rax, qword ptr [heap];

mov r8,0; #段地址不能直接賦予立即數
mov [rdx+rax],r8;
jmp 0xD56; #跳回原來的地址

image-20210713134459423

Patch-if范圍

假設需要將圖上第二個 if 放到 if 結構內,修改跳轉的地址即可:

image-20210719113705210

原始跳轉代碼:

image-20210719114103511

js 0x40081C --> js 0x400845

image-20210719114649963

Patch-更換危險函數

類似與 uaf 一樣寫匯編實現功能調用,將危險函數替換為其他函數,如果程序中沒有目標函數,就通過系統調用方式調用。

將 gets 替換為 read 輸入

image-20210720042111225

.eh_frame 寫入匯編,將 rdi 的寫入地址移動到 rsi ,把其他寄存器也傳參之后進行系統調用:

image-20210720042440884

image-20210720042425944

image-20210720042503413

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM