修改函數的返回地址

這篇隨筆源自今天看的這篇文章http://www.cnblogs.com/bluesea147/archive/2012/05/19/2508208.html

1. 如何修改函數返回地址

今天主要寫測試程序思考和驗證了一下這個問題,先看一下這個C程序

 1 #include <stdio.h>
 2 void foo(){
 3         int a, *p;
 4         p = (void*)((long)&a + 12);
 5         *p += 20;
 6 }
 7 int main(){
 8         foo();
 9         printf("First printf call\n");
10         printf("Second printf call\n");
11         printf("Third printf call\n");
12         return 0;
13 }

在我的機子上運行這個程序,結果是:

third printf call

在foo返回后直接跳到了11去執行,這個程序和我看的那篇文章的程序稍有不同,主要是我的機子Intel64架構的,指針是用8個字節來表示的,主要不同在4行,long也是8個字節的,所以gcc沒有做任何的warning,之前在一篇隨筆中就提到過,c應該是在很早的時候就支持各種類型的指針的轉換,因為這里是對指針指向的內容操作,所以用什么類型的指針都是可以的,這里是存儲的是指令,所以就用(void *)了。 第4行代碼是讓p指向調用main調用foo()時壓入棧的那個返回地址,改變這個地址的值讓它指向一個語句的開頭,就做到了更改函數的返回地址。

怎么確定如何修改p中的值讓它是另一個指令的合法地址呢,即指向另一個指令的開始,這就要用到objdump了,編譯鏈接上面的程序生成可執行文件,然后objdump -d。得到下面的片段。

 1 00000000004004f4 <foo>:
 2   4004f4:    55                       push   %rbp
 3   4004f5:    48 89 e5                 mov    %rsp,%rbp
 4   4004f8:    48 8d 45 fc              lea    -0x4(%rbp),%rax
 5   4004fc:    48 83 c0 0c              add    $0xc,%rax
 6   400500:    48 89 45 f0              mov    %rax,-0x10(%rbp)
 7   400504:    48 8b 45 f0              mov    -0x10(%rbp),%rax
 8   400508:    8b 00                    mov    (%rax),%eax
 9   40050a:    8d 50 14                 lea    0x14(%rax),%edx
10   40050d:    48 8b 45 f0              mov    -0x10(%rbp),%rax
11   400511:    89 10                    mov    %edx,(%rax)
12   400513:    5d                       pop    %rbp
13   400514:    c3                       retq   
14 
15 0000000000400515 <main>:
16   400515:    55                       push   %rbp
17   400516:    48 89 e5                 mov    %rsp,%rbp
18   400519:    b8 00 00 00 00           mov    $0x0,%eax
19   40051e:    e8 d1 ff ff ff           callq  4004f4 <foo>                    # call foo
20   400523:    bf 3c 06 40 00           mov    $0x40063c,%edi                  # printf("first..")
21   400528:    e8 c3 fe ff ff           callq  4003f0 <puts@plt>
22   40052d:    bf 4e 06 40 00           mov    $0x40064e,%edi                  # printf("second..")
23   400532:    e8 b9 fe ff ff           callq  4003f0 <puts@plt>
24   400537:    bf 61 06 40 00           mov    $0x400661,%edi                  # printf("third..")
25   40053c:    e8 af fe ff ff           callq  4003f0 <puts@plt>
26   400541:    b8 00 00 00 00           mov    $0x0,%eax
27   400546:    5d                       pop    %rbp
28   400547:    c3                       retq   
29   400548:    90                       nop
30   400549:    90                       nop
31   40054a:    90                       nop
32   40054b:    90                       nop
33   40054c:    90                       nop
34   40054d:    90                       nop
35   40054e:    90                       nop
36   40054f:    90                       nop

call foo時壓入的返回地址應該是20行的地址,0x400523,現在把這個值加20改到0x400537,就把返回值定位到了24行的指令,從上面也可以看出各條指令的大小,push是一個字節,而上面的mov帶了參數也才5個字節。

那如何確定調foo時壓入棧的那個返回地址在存儲器中的位置而好去修改它呢,現在看一下上面c程序中foo()函數對應的gas代碼

 1 foo:
 2     pushq    %rbp
 3     movq    %rsp, %rbp
 4     leaq    -4(%rbp), %rax      # 取&a
 5     addq    $12, %rax           # &a+12
 6     movq    %rax, -16(%rbp)     # p存在-16(%rbp)中
 7     movq    -16(%rbp), %rax
 8     movl    (%rax), %eax
 9     leal    20(%rax), %edx      #  *p+20=>%edx
10     movq    -16(%rbp), %rax     #   p=>%rax
11     movl    %edx, (%rax)        #   %edx=>*p
12     popq    %rbp
13     ret

從第4行可以看出a就存在棧最開始的4個字節中,a之上的肯字是入棧的 %rbp,這占8個字節, 而這之上的就是由main壓入的返回地址,因此內存中返回地址的地址就是 ?&a+12。

?

2。gdb的簡單使用

用gdb查看一下當匯編指令剛進入foo時棧頂的值,這個值應該要是調用foo后main中下條要執行的指令的地址。

如圖可以看到,在進入foo,執行 pushq %rbp前時,棧頂的值確實是main中調用foo之后地那個指令的地址,而我們所修改的也就是這個值。

簡單的說一說這里gdb的使用,在用gcc編譯的時候帶上-g才會把源代碼的信息放在可執行文件中,如上面我是從匯編直接編譯的,帶上-g就會把匯編的源代碼信息編進可執行碼中,這樣在gdb中才可以單步執行以及在該列出源碼的時候列出源碼。b是break的簡寫,打斷點,可以指令某一行代碼,某個函數,或某個地址(地址前加上*), 若指定一個函數,則在這個函數開始的代碼執行前停住,gdb會列出下面一行要執行的代碼,n是nexti的縮寫,可以接一個參數表示執行的代碼行數,這里我說是代碼的行數,gdb確實是這么做的,我把一行放兩個語句(用;分割),一個n也就執行過了,看來在debug的信息中,行是很重要的單位,n遇到subroutine call會直接當作一行代碼跳過,而s(stepi)會進入到函數調用內部。上面有s進入到foo中,然后用x查看棧頂的內容, x是用來查看內存中內容的(examin memory),實際上x必須跟上一些信息表示你要查看多少個字節,因為地址只會指向一個字節,只用x的話,默認是上次用過的count和letter size, 圖中的x實際上是 x/1xw, 而實際上因為地址用了8個字節來存,所以我應該用 x/1xg 的, b, h(half word), w(word), g(giant)分別表示1,2,4,8個字節,前面的數是count表示看幾個,而中間那個x表示hex,以16進制顯示,除了x還有a(address), t(binary), o(octal), d(decimal), i(instruction), c(char), s(string). ?其中a(address)這個我在看虛表中內容的時候直接就把函數名給我顯示出來了,很有用

關于gdb,以后會深入的寫一些

轉載于:https://www.cnblogs.com/livingintruth/archive/2012/07/17/2594081.html

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

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

相關文章

調試JavaScript代碼

JavaScript調試代碼 (JavaScript debugging the code) Debugging is the process of finding mistakes or bugs in the program. There are several ways one can debug their JavaScript code. This article will walk you through the strict mode in JavaScript and excepti…

Delphi運算符及優先級

單目運算符 (最高優先級) 取變量或函數的地址(返回一個指針) not 邏輯取反或按位取反 乘除及按位運算符 * 相乘或集合交集 / 浮點相除 div 整數相除 mod 取模 (整數相除的余數) as 程序運行階段類型轉換 (RTTI運算符) and 邏輯或按位求和 shl 按位左移 shr 按位右移 加減運算符…

NotifyMyFrontEnd 函數背后的數據緩沖區(二)

message level 函數pq_putmessage調用 low level 函數 pq_putbytes,pq_putbytes調用 internal_putbytes。 從internal_putbyes上來看&#xff0c;就可以發現其數據發送的機制:有一個小技巧&#xff0c;如果數據緩沖區滿了&#xff0c;就發送&#xff0c;否則就先堆在那兒。如果…

從源碼角度剖析VC6下的內存分配與切割的運作

目錄前言1、heap初始化2、第一次分配內存&#xff0c;計算真正區塊大小3、new_region管理中心4、__sbh_alloc_new_group()切割第一次分配好的內存5、開始切割內存前言 malloc與free帶來的內存管理是應付小區塊的&#xff0c;即SBH(small block heap)&#xff0c;這點也可以從源…

windows常見命令整理(持續更新)

windows常見命令整理 1. 文件1.1. 實時顯示文件 logfile.txt 中新添加的內容&#xff08;類似于linux tail -f&#xff09; 2. 網絡2.1. netstat 3. 進程和任務3.1. tasklist &#xff08;用于列出當前運行的進程及其詳細信息&#xff09;3.2. wmic &#xff08;用于執行各種系…

最長公共子序列求序列模板提_最長公共子序列

最長公共子序列求序列模板提Description: 描述&#xff1a; This question has been featured in interview rounds of Amazon, MakeMyTrip, VMWare etc. 這個問題在亞馬遜&#xff0c;MakeMyTrip&#xff0c;VMWare等訪談輪次中都有介紹。 Problem statement: 問題陳述&…

洛必達法則使用條件

使用條件 1、分子分母同趨向于0或無窮大 。 2、分子分母在限定的區域內是否分別可導。 3、當兩個條件都滿足時&#xff0c;再求導并判斷求導之后的極限是否存在&#xff1a;若存在&#xff0c;直接得到答案&#xff1b;若不存在&#xff0c;則說明此種未定式無法用洛必達法則解…

求根號m(巴比倫算法)

巴比倫算法是針對求根號m的近似值情況的&#xff0c;它的思想是這樣的&#xff1a; 設根號mX0,則如果枚舉有答案X(X<X0)&#xff0c;則m/X>X0,當精度要求不高的時候&#xff0c;我們可以看成Xm/XX0,而如果精度要求比較高&#xff0c;我們只需取X和m/X的平均值作為新的枚舉…

Android面試題

http://blog.csdn.net/aomandeshangxiao/article/category/841452 http://www.cppblog.com/life02/category/18316.html轉載于:https://www.cnblogs.com/DonkeyTomy/articles/2598673.html

r語言 分類變量 虛擬變量_R語言中的變量

r語言 分類變量 虛擬變量R語言| 變數 (R Language | Variables) In the previous tutorial, we have come across the basic information that stands as a pavement for understanding the R language in depth. Now moving future let us educate ourselves about the concep…

算法題復習(快排、鏈表、二分、哈希、雙指針)

目錄1、快速排序復習2、鏈表部分復習203. 移除鏈表元素707. 設計鏈表206. 反轉鏈表142.環形鏈表 II3、二分法復習4、哈希法復習5、雙指針復習**15. 三數之和****18. 四數之和****27. 移除元素****344. 反轉字符串**,簡單&#xff0c;雙指針從兩側往中間靠攏&#xff0c;并隨時s…

Cassandra1.2文檔學習(7)—— 規劃集群部署

數據參考&#xff1a;http://www.datastax.com/documentation/cassandra/1.2/webhelp/index.html#cassandra/architecture/architecturePlanningAbout_c.html 當規劃一個Cassandra集群部署時&#xff0c;關于你初始存儲的數據的數據量你應當有一個好的想法&#xff0c;并且對于…

虛擬機設置NAT

需要開啟虛擬機網絡相關服務&#xff0c; 安裝虛擬網卡&#xff0c; 還有必須安裝 VMware ToolsVMware虛擬機下實現NAT方式上網1. 把你的虛擬網卡VMnet8設置為自動獲得IP、自動獲得DNS服務器&#xff0c;啟用。2. 把你虛擬機中操作系統的“本地連接”也設置為自動獲得IP、自動獲…

窗體震動 C# (不使用Timer控件,控制窗體震動)

private static Point plocation new Point(); public static void StartVibration(Form form)//Form 傳入需要振動的窗體 { plocation form.Location; for (int i 1; i < 41; i)//41&#xff0c;可以理解為震動的時間。…

算法題復習(棧與隊列、二叉樹)

目錄棧與隊列棧用于匹配的問題隊列用于堆二叉樹系列深度遍歷&#xff0c;遞歸與迭代層序遍歷二叉樹屬性二叉樹修改與構造二叉搜索樹公共祖先二叉搜索樹的修改與構造棧與隊列 棧用于匹配的問題 20. 有效的括號 https://leetcode-cn.com/problems/valid-parentheses/ 不匹配的三…

bpsk_BPSK的完整形式是什么?

bpskBPSK&#xff1a;二進制相移鍵控 (BPSK: Binary Phase Shift Keying) BPSK is an abbreviation of "Binary Phase Shift Keying". BPSK是“二進制相移鍵控”的縮寫 。 BPSK is also occasionally called phase reversal keying (PRK), or 2PSK, which is the el…

win7 下安裝oracle 10g

oracle 10g 在win7下安裝&#xff0c;提示程序異常終止&#xff0c;發生未知錯誤 在網上搜結果&#xff1a; 修改Oracle 10G\database\stage\prereq\db\refhost.xml 在 </SYSTEM> <CERTIFIED_SYSTEMS>后面添加 <!--Microsoft Windows 7--> <OPERAT…

poj 1703 Find them, Catch them

題目鏈接&#xff1a;http://poj.org/problem?id1703 題目大意&#xff1a;警察抓獲N個罪犯&#xff0c;這些罪犯只可能屬于兩個團伙中的一個&#xff0c;現在給出M個條件&#xff08;D a b表示a和b不在同一團伙&#xff09;&#xff0c;對于每一個詢問(A a b)確定a&#xff0…

雙向a*搜索算法_雙向搜索算法

雙向a*搜索算法什么是雙音搜索&#xff1f; (What is bitonic search?) Searching a bitonic array is known as bitonic search. An array is said to be bitonic if it has an increasing sequence of integers followed immediately by a decreasing sequence of integers.…

關于LRU緩存簡單記錄以及代碼補全。

目錄大概思路時間空間復雜度分析指針操作具體細節代碼雙向鏈表設計私有成員變量設計:構造函數和析構函數設計&#xff1a;get與put具體設計雙向指針的具體細節添加到頭節點函數刪除尾節點函數刪除節點函數刪除節點函數感想今天面試考到LRU&#xff0c;太緊張了&#xff0c;完全…