修改函数的返回地址

这篇随笔源自今天看的这篇文章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.mzph.cn/news/377340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从源码角度剖析VC6下的内存分配与切割的运作

目录前言1、heap初始化2、第一次分配内存&#xff0c;计算真正区块大小3、new_region管理中心4、__sbh_alloc_new_group()切割第一次分配好的内存5、开始切割内存前言 malloc与free带来的内存管理是应付小区块的&#xff0c;即SBH(small block heap)&#xff0c;这点也可以从源…

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

最长公共子序列求序列模板提Description: 描述&#xff1a; This question has been featured in interview rounds of Amazon, MakeMyTrip, VMWare etc. 这个问题在亚马逊&#xff0c;MakeMyTrip&#xff0c;VMWare等访谈轮次中都有介绍。 Problem statement: 问题陈述&…

求根号m(巴比伦算法)

巴比伦算法是针对求根号m的近似值情况的&#xff0c;它的思想是这样的&#xff1a; 设根号mX0,则如果枚举有答案X(X<X0)&#xff0c;则m/X>X0,当精度要求不高的时候&#xff0c;我们可以看成Xm/XX0,而如果精度要求比较高&#xff0c;我们只需取X和m/X的平均值作为新的枚举…

算法题复习(快排、链表、二分、哈希、双指针)

目录1、快速排序复习2、链表部分复习203. 移除链表元素707. 设计链表206. 反转链表142.环形链表 II3、二分法复习4、哈希法复习5、双指针复习**15. 三数之和****18. 四数之和****27. 移除元素****344. 反转字符串**,简单&#xff0c;双指针从两侧往中间靠拢&#xff0c;并随时s…

码农干货系列【4】--图像识别之矩形区域搜索

简介 定位某个图片的矩形区域是非常有用的&#xff0c;这个可以通过手动的选择某个区域来实现定位&#xff0c;图片相关的软件都提供了这个功能&#xff1b;也可以像本篇一个通过程序来实现智能定位。前者会有误差&#xff0c;效率低下&#xff1b;后者选区精度高&#xff0c;效…

Android中的广播Broadcast详解

今天来看一下Android中的广播机制&#xff0c;我们知道广播Broadcast是Android中的四大组件之一&#xff0c;可见他的重要性了&#xff0c;当然它的用途也很大的&#xff0c;比如一些系统的广播&#xff1a;电量低、开机、锁屏等一些操作都会发送一个广播&#xff0c;具体的And…

.NET线程池

摘要 深度探索 Microsoft .NET提供的线程池&#xff0c; 揭示什么情况下你需要用线程池以及 .NET框架下的线程池是如何实现的&#xff0c;并告诉你如何去使用线程池。 内容 介绍 .NET中的线程池 线程池中执行的函数 使用定时器 同步对象的执行 异步I/O操作 监视线程池 死锁 有关…

《c++特性》

目录多态构造函数和析构函数存在多态吗&#xff1f;虚函数表虚析构函数纯虚函数和抽象类运行时多态和编译时多态的区别继承设计实例指针对象和普通对象的区别正确初始化派生类方式继承和赋值的兼容规则protected 和 private 继承基类与派生类的指针强制转换如何用C实现C的三大特…

Scala中的while循环

在Scala中的while循环 (while loop in Scala) while loop in Scala is used to run a block of code multiple numbers of time. The number of executions is defined by an entry condition. If this condition is TRUE the code will run otherwise it will not run. Scala中…

牛客网与leetcode刷题(高频题中简单or中等的)

目录1、反转链表2、排序3、先序中序后序遍历4、最小的k个数5、子数组的最大累加和6、 用两个栈实现队列7、142. 环形链表 II8、20. 有效的括号9、最长公共子串(动态规划),磕磕绊绊10、二叉树之字形层序遍历11、重建二叉树12、LRU缓存13、合并两个有序链表15、大数加法16、一个二…

AMUL的完整形式是什么?

AMUL&#xff1a;阿南德牛奶联盟有限公司 (AMUL: Anand Milk Union Limited) AMUL is an abbreviation of Anand Milk Union Limited. It is an Indian milk product cooperative dairy organization that is based in the small town of Anand in the state of Gujarat. AMUL …

mochiweb 源码阅读(十一)

大家好&#xff0c;今天周六&#xff0c;继续接着上一篇&#xff0c;跟大家分享mochiweb源码。上一篇&#xff0c;最后我们看到了mochiweb_socket_server:listen/3函数&#xff1a; listen(Port, Opts, State#mochiweb_socket_server{sslSsl, ssl_optsSslOpts}) ->case moch…

Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能 (转)

转载请注明出处&#xff1a;http://blog.csdn.net/guolin_blog/article/details/9255575 最 近项目中需要用到ListView下拉刷新的功能&#xff0c;一开始想图省事&#xff0c;在网上直接找一个现成的&#xff0c;可是尝试了网上多个版本的下拉刷新之后发现效果都不怎么理 想。有…

红黑树的实现

目录1、红黑树原理1、红黑树性质2、变换规则&#xff08;从插入结点的角度来讲&#xff09;1.变色2.左旋3.右旋3、删除结点需要注意的地方2、代码1、定义结点以及构造函数2、定义红黑树类以及声明它的方法3、左旋4、右旋5、插入操作6、修正操作7、删除操作3、参考链接1、红黑树…

118 - ZOJ Monthly, July 2012

http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId339 都是赛后做的。。。弱爆了 A题是找由2和5组成的数字的个数 直接打个表就行了 只是比赛的时候不知道怎么打表啊。。 View Code #include<cstdio> #include<cstring> #include<algorith…

edp1.2和edp1.4_EDP​​的完整形式是什么?

edp1.2和edp1.4EDP​​&#xff1a;电子数据处理 (EDP: Electronic Data Processing) EDP is an abbreviation of Electronic Data Processing. It alludes to the functioning of operations of commercial data, documents processing of storing, with the use of a compute…

css链接样式_CSS中的样式链接

css链接样式CSS样式链接 (CSS Styling Links) The links in CSS can be styled in various ways to make our website more presentable and attractive. The links can also be styled depending on their states e.g. visited, active, hover, etc. CSS中的链接可以通过各种方…

css中的媒体查询_CSS中的媒体查询

css中的媒体查询CSS | 媒体查询 (CSS | Media Queries) Creating a web page is not an easy task as it requires loads of content and data so that it becomes strongly responsive to the users. To do that various contents are even added e.g.: resources, informativ…

SharePoint2013安装组件时AppFabric时出现1603错误,解决方法:

采用PowerShell命令批量下载必备组件: 下载完成后&#xff0c;采用批处理命令安装必备组件。 注&#xff1a;SPS2013安装必备组件及批处理下载地址&#xff1a; 需要将必备组件放在安装文件的PrerequisiteInstallerFiles文件夹中&#xff0c;将PreReq2013.bat放在安装文件根目录…

《MySQL——数据表设计三大范式》

目录数据表设计范式第一范式第二范式第三范式数据表设计范式 第一范式 数据表中的所有字段都是不可分割的原子值。 字段值还可以继续拆分的&#xff0c;就不满足第一范式&#xff0c;如下&#xff1a; 下面这个&#xff0c;更加贴合第一范式&#xff1a; 范式设计得越详细&…