PWN學習整理棧溢出到堆利用(含舉例)

文章將整理從入門棧溢出到堆house系列的梳理。
0x01棧知識

call
	 將當前的IP或者CS和IP壓入棧中。
	 轉移
彙編:call xxx
	push IP
	jmp xxx
ret
	將程序的返回地址彈出到ip寄存器中
	程序繼續執行
彙編:
	pop IP

有call就要有傳參,32位系統用棧來傳參參數是倒着傳進去也就是最後的參數先push
64位系統用寄存器來傳參前三個參數是用rdi,rsi,rdx
32位函數調用(__cdecl 調用約定)

C語言函數
 write(1, "Hello, World!\n", 0xEu);

彙編語言
push    0Eh             ; n           傳遞第三個參數
push    offset aHelloWorld ; "Hello, World!\n"   第二個參數
push    1               ; fd    第一個參數
call    _write 
add     esp, 10h  			在call返回之後平衡堆棧

64位傳參

read(0, &buf,0x200uLL);

mov     edx, 200h       ; nbytes
mov     rsi, rax        ; buf
mov     edi, 0          ; fd
call    _read

在這裏插入圖片描述
運行時程序的棧:
上面高地址處存放的是環境變量和main函數的信息
往下是主調函數的棧內存,包括臨時變量和控制信息(控制信息包括返回地址和ebp等用來保存的寄存器的值)

調用約定:
每個函數調用的時候都會自己平衡自己的堆棧。

每個被調函數被調用的時候先push ebp所以棧裏面會有返回地址和ebp
兩個表
在這裏插入圖片描述plt表:函數調用的時候先使用的。PLT表中的每一項的-數據內容都是對應的GOT表中一項的地址這個是固定不變的,PLT表中的數據是跳轉到GOT表項的地址。
got表:一個指向真正運行函數首地址的指針。
注意函數

scanf函數
scanf("%d %d",&a,&b);
遇到空格(0x20)停止讀取

read函數
ssize_t read  (int fd, void *buf, size_t count);
讀取數據遇到\n(0x0a)結束,\x0a會讀進去
fd爲0從鍵盤讀取

gets函數
gets(str);
輸入遇到\n(0x0a)結束
\x0a不會讀進去

printf函數
printf("%s", i);
輸出直到\x00

write函數
ssize_t write(int fd, const void *buf, size_t nbyte);
fd爲1輸出到顯示器


puts函數
puts(char *)
相當於printf("%s\n",s)
輸出字符串(遇到\x00結束)

strcpy函數
char *strcpy(char *dst, const char *src);
一直複製直到遇到\x00

memcpy函數
void *memcpy(void *dest, const void *src, size_t n);
複製任意內容

strncpy函數
char *strncpy(char *dest,char *src,int size_t n);
如果n<src的長度,只是將src的前n個字符複製到dest的前n個字符,不自動添加'\0'。如果src的長度小於n個字節,則以NULL填充dest直到複製完n個字節

32位利用方式
在這裏插入圖片描述舉例https://blog.csdn.net/qq_38204481/article/details/80944927
64位利用方式
在這裏插入圖片描述https://blog.csdn.net/qq_38204481/article/details/80955065
通用rop作爲rop的進階

disassemble __libc_csu_init
   0x0000000000400690 <+64>:	mov    rdx,r13
   0x0000000000400693 <+67>:	mov    rsi,r14
   0x0000000000400696 <+70>:	mov    edi,r15d
   0x0000000000400699 <+73>:	call   QWORD PTR [r12+rbx*8]
   0x000000000040069d <+77>:	add    rbx,0x1
   0x00000000004006a1 <+81>:	cmp    rbx,rbp
   0x00000000004006a4 <+84>:	jne    0x400690 <__libc_csu_init+64>
   0x00000000004006a6 <+86>:	add    rsp,0x8
   0x00000000004006aa <+90>:	pop    rbx
   0x00000000004006ab <+91>:	pop    rbp
   0x00000000004006ac <+92>:	pop    r12
   0x00000000004006ae <+94>:	pop    r13
   0x00000000004006b0 <+96>:	pop    r14
   0x00000000004006b2 <+98>:	pop    r15
   0x00000000004006b4 <+100>:	ret 

https://blog.csdn.net/qq_38204481/article/details/80984318
0x02保護

  • RELRO
    介紹:got表不可寫
    繞過方法:hook函數,覆蓋返回地址,導入shellcode

  • NX
    棧內數據不可執行
    不能導入shellcode
    繞過方法:ROP

  • STACK
    介紹:程序會在棧裏面放入一個canary返回時檢測canary是否發生了改變,如果改變會輸出程序名字然後退出。
    繞過方法:leak canary,SSP(Stack Smashes Protect),爆破canary,用格式化字符串複寫check_got再觸發。

  • PIE
    程序加載地址隨機

SSP
fork函數會複製原進程的環境,然後運行新內容。
當棧被損壞canary會打印出程序的名字,如果用覆蓋掉name程序會打印出需要的數據。
但是這種方法會讓程序退出,所以一般需要伴隨着fork函數
在這裏插入圖片描述
https://blog.csdn.net/qq_38204481/article/details/82318179(GUESS)
leak canary
在這裏插入圖片描述
1.覆蓋掉canary最後的00輸出的時候會把canary輸出.但是要求在泄露之後函數返回之前要獲取shell

2.如果在設置數組數組的時候沒有清空棧空間,保留了上次調用留下的canary也可以泄露,一般需要遞歸。

擡高棧幀
在這裏插入圖片描述https://tower111.github.io/2018/09/09/%E7%BD%91%E9%BC%8E%E6%9D%AF4-impossible
執行pop之後邏輯上棧內數據不存在但是物理上依然存在。
如果直接通過覆蓋\x00泄露ret2的canary改變了打印出之後會退出,所以可以利用其它函數寫入canary,然後leakret_addr1的canary
GOT表不可寫(RELRO)
大部分函數都有一個hook函數。
以__hook_malloc爲例。

在這裏插入圖片描述
1.得到libc就能得到它的真是加載地址

默認地址設置位0,如果地址處不爲0,執行malloc之前會執行這裏的內容。(一般複寫的是_free_hook函數)


0x03格式化字符串
輸出

printf("%s %d %d %d %x %x\n",buf,a,b,c) 

在這裏插入圖片描述

%s會輸出buf指向的內容


三個%d會輸出a,b,c


二個%x會輸出繼續往下的棧空間的內容

在這裏插入圖片描述在這裏插入圖片描述
buf=test
printf(“%s %d %d %d %x %x”,buf)
如圖反映了上圖的輸出和棧的內存。
分別輸出test 1 2 3 2f 804a000
寫入
%n是一個不經常用到的格式符,它的作用是把前面已經打印的長度寫入某個內存地址
在這裏插入圖片描述可以看到我們的num值被改爲了100,
這裏可以看出1.用%.100可以控制寫入數據是十進制100(0x64)
2.寫入的地址是%n對應的參數指向的內容
補充
用%2$x(或n)可以實現定點輸出(或輸入)不加$
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200220203349743.png
利用
用%n的字符加上got表數據可以實現複寫
在這裏插入圖片描述****
0x04堆漏洞
分配過的chunk

  • 32位機,8字節對齊,64位機,16字節對齊
  • 位P指明前一個chunk的狀態 空閒(0),使用(1)
  • prev_size表示前一個chunk的大小
    當前chunk釋放時,可用於定位前一個chunk,並將兩個chunk合併爲一個更大的chunk
    當P爲1時,prev_size無意義,該區域(4B)可被前一個chunk使用
    在這裏插入圖片描述
    fast bin
    在這裏插入圖片描述- 在chunk被free的時候如果大小小於0x80會被放入fast bin
  • 需要注意的是這裏的prive_inuse位不會置0
  • 可以在這裏泄露出來heap的地址。(因爲fd指向了下一個chunk的開始)
    unsort bin
    在這裏插入圖片描述
  • 在chunk合併之後大於0x80或者是大於0x80的chunk被釋放之後會放入unsort bin
  • 這裏是雙向鏈表連接
  • 其中main_arena和libc_base之間的偏移是固定的,可以用來leak libc_base
    注意點
  • 定義的read函數
    可以輸入比size多一位。
    可以輸入size之後又加上\x00
  • free掉chunk之後指針是否清零
  • 是否存在堆溢出

利用方法fastbin attack
在這裏插入圖片描述注意在申請空間時有一個size驗證。
上圖由

malloc(0x20) malloc(0x20)
free(1)  free(2)   #到這裏形成上圖第一列
edit(2,my_addr)  #形成上圖第二列
(my_addr=0x6020xx
my_addr_size=0x31)#括號內的是說明需要的條件不是代碼
malloc(0x20)      #形成上圖第三列
malloc(0x20)     #申請到僞造chunk空間

完成上述過程需要條件:
my_addr_size需要滿足
1.0x80以內
2.prive_inuse爲1
https://blog.csdn.net/qq_38204481/article/details/82318179
補充利用FILE結構

struct _IO_FILE_plus
{
    _IO_FILE    file;
    IO_jump_t   *vtable;
}
void * vtablt[] = {
   1 NULL, // "extra word"
   2 NULL, // DUMMY
   3 exit, // finish
   4 NULL, // overflow
   5 NULL, // underflow
   6 NULL, // uflow
   7 NULL, // pbackfail
   
   8 NULL, // xsputn  #printf
   9 NULL, // xsgetn

安裝gdb的pwndbg插件用print *(struct _IO_FILE_plus*)0x6020a0命令可以輸出結構
詳情參考https://ctf-wiki.github.io/ctf-wiki/pwn/linux/io_file/introduction/
舉例參考https://blog.csdn.net/qq_38204481/article/details/82318094(blind)
利用方式double free
在這裏插入圖片描述
上圖形成過程:
free chunk1 free chunk2 free chunk1(途中三個箭頭對應三個操作)
說明

  • 所謂的free其實就是數據結構裏面的頭插。就是一些指針的變化
  • 達到上圖在經過三次malloc再次malloc就能申請到想要的空間
  • 限制:需要一個合適的size
    舉例參見https://tower111.github.io/2018/08/30/ISG-babynote/(文中提到的獲取執行流的 方法總結:https://blog.csdn.net/qq_38204481/article/details/82318227
    unlink
    在這裏插入圖片描述unlink的發生:
  • glibc 判斷這個塊是 small chunk。
  • 判斷前向合併,發現前一個 chunk 處於使用狀態,不需要前向合併。
  • 判斷後向合併,發現後一個 chunk 處於空閒狀態,需要合併。
  • 繼而對 nextchunk 採取 unlink 操作。

可見,要進行unlink的不是剛釋放的chunk而是與這個chunk物理相鄰的chunk

執行函數unlink§ 可以看出:unlink函數知道的只有一個指針,函數的第一步是找到前一個邏輯相鄰的chunk,後一個邏輯相鄰的chunk(其實就是指針的賦值操作,包括上圖描述的unlink過程)

實際上進行unlink的時候會進行一個教研P->fd->bk==P
在這裏插入圖片描述上圖三列其實佔了同一個空間,也就是地址是重合的,這樣就能滿足上述的校驗
在這裏插入圖片描述
例子參考https://blog.csdn.net/qq_38204481/article/details/82808011


0x05補充堆分配與釋放過程
內存分配
在這裏插入圖片描述內存釋放
在這裏插入圖片描述

發佈了131 篇原創文章 · 獲贊 37 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章