免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 思一克

一个所谓的全局变量地址改变的例子 [复制链接]

论坛徽章:
0
发表于 2010-02-02 15:47 |显示全部楼层
学与思的这个很好。
能否介绍一下函数的跳转表细节?
思一克 发表于 2010-02-02 14:20


详细内容可以参考 <elf文件格式> , 还有一篇alert7写的动态库符号解析过程

大概是这样的:

对于32位的x86,调用动态库中的函数,比如 printf(); 调用的其实是plt中的一小段代码,这一小段代码如:
address + 0: jmp *0xXXXXXXXX
address + 6 : push 一个常数
jmp 0xYYYYYYYY

第一次调用printf时地址0xXXXXXXXX中的值就是address + 6, 也就是第一次jmp会跳到 address + 6的地方,然后下一个jmp进行如号解析,然后在0xXXXXXXXX中写入真实的printf函数的地址,之后再调用printf时就会直接跳到printf函数去了。
我前面那个代码就是在0xXXXXXXXX中放入evil_code()函数的地址,address + 0: jmp *0xXXXXXXXX 这条指令占用6个字节,前面两个是操作码,后面就是地址,所以有代码中"  + 2"

论坛徽章:
0
发表于 2010-02-02 15:54 |显示全部楼层
[test]$ cat a.c
#include
#include

int evil_code(char *s)
{
        printf("hi, I am he ...
baicj 发表于 2010-02-02 14:47


估计是偏移有误,没有平台,不能帮你试

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2010-02-05 12:58 |显示全部楼层
俺跑出 code dump 了.

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2010-02-05 17:21 |显示全部楼层
&pid
了解一下栈的布局? 我不了解我能写出那些代码吗?
anchor不是必须的?  你看明白它的作用以及为什么需 ...
OwnWaterloo 发表于 2010-01-30 15:57


恩, 经检验, 有道理,

0x0040135e <begin_hack+0>:      push   %ebp
0x0040135f <begin_hack+1>:      mov    %esp,%ebp
0x00401361 <begin_hack+3>:      sub    $0x18,%esp --- 注意这一句
0x00401364 <begin_hack+6>:      call   0x40133c <hack>
0x00401369 <begin_hack+11>:     lea    -0x4(%ebp),%eax
0x0040136c <begin_hack+14>:     add    $0x8,%eax
0x0040136f <begin_hack+17>:     lea    -0x4(%ebp),%edx
0x00401372 <begin_hack+20>:     sub    $0x4,%edx
0x00401375 <begin_hack+23>:     mov    (%edx),%edx
0x00401377 <begin_hack+25>:     mov    %edx,(%eax)
0x00401379 <begin_hack+27>:     leave  
0x0040137a <begin_hack+28>:     ret   

所以, 在gcc下是这样的

return addr
ebp
int a
int b
...
padding
...
return addr
ebp
int c
int d

所以以下代码能够正常退出

  1.   1 #include <stdio.h>
  2.   2
  3.   3
  4.   4 void hack(){
  5.   5     fprintf(stderr, "hack\n");
  6.   6 }
  7.   7
  8.   8 void begin_hack(){
  9.   9     int addr;
  10. 10
  11. 11     hack();
  12. 12
  13. 13   [color=Red]  *(&addr + 2) = *(&addr - 1);[/color]  // 如果没有padding, 那么这里将会破坏 f 函数中压栈的 ebp, 肯定会crash
  14. 14 }
  15. 15
  16. 16 void f()
  17. 17 {
  18. 18     int i = *(&i + 2);
  19. 19     *(&i + 2) = (int)((int *) begin_hack);
  20. 20 }
  21. 21
  22. 22 void test()
  23. 23 {
  24. 24     int i = 0;
  25. 25
  26. 26     f();
  27. 27
  28. 28     fprintf(stderr, "returned\n");
  29. 29 }
  30. 30
  31. 31 int main(int a, char** b)
  32. 32 {
  33. 33     test();
  34. 34     return 0;
  35. 35 }
  36. 36
  37. ~         
复制代码

论坛徽章:
0
发表于 2010-02-06 08:57 |显示全部楼层
我举个极端的例子:

fflush函数部分代码 , gcc编译 , powerpc架构


.text0:8001DB78             ...
老手 发表于 2010-01-29 00:22



我觉得你说的应该不是楼主的意思,按你说的那样就跟CPU架构相关了,但是楼主什么条件都没给

论坛徽章:
0
发表于 2010-02-06 09:26 |显示全部楼层
另外,术语栈(stack)的确是一个硬件相关的东西,C语言标准里是不会提到这个的。
并且栈的增长方面如同大 ...
cjaizss 发表于 2010-01-30 19:33




恩...应该说栈布局(stack layout)才比较准确,这个东东跟arch、compiler甚至有时跟OS都有关系,但是楼主什么限制条件都没给的嘛,莫非是我脑筋太死了?

论坛徽章:
0
发表于 2010-02-10 09:13 |显示全部楼层
  1. *(&i+4) = (int)("addr = %p value = %d\n");
  2. *(&i+5) = (int)(&gi+1);
  3. *(&i+6) = gi+1;
  4. *(&i+2) = (int)((int*)printf);
复制代码
*(&i+2)是修改栈中的返回地址,*(&i+4)我不明白,我以为是*(&i+3),但是测试结果就是*(&i+4)。
请问为什么?

论坛徽章:
0
发表于 2010-02-10 09:21 |显示全部楼层
*(&i+2)是修改栈中的返回地址,*(&i+4)我不明白,我以为是*(&i+3),但是测试结果就是*(&i+4)。
请问为什么 ...
rainballdh 发表于 2010-02-10 09:13


是让控制返回到printf后,给printf合适的参数,让printf自己能正常工作。
printf("addr = %p value = %d\n", &gi, gi);
&i+4 就是给这个format串的(第一个参数)。&i+5是第二,&i+6是第三个。

论坛徽章:
0
发表于 2010-02-10 09:35 |显示全部楼层
是让控制返回到printf后,给printf合适的参数,让printf自己能正常工作。
printf("addr = %p value =  ...
思一克 发表于 2010-02-10 09:21

第一个参数应该是ebp+8,就应该是*(&i+3),我认为。但是测试结果就是&(i+4).这点不明白

论坛徽章:
0
发表于 2010-02-10 09:43 |显示全部楼层
第一个参数应该是ebp+8,就应该是*(&i+3),我认为。但是测试结果就是&(i+4).这点不明白
rainballdh 发表于 2010-02-10 09:35


你用EBP做参考系也可以。用&i也可以。
甚至自己在定义一个局部变量a, 以&a也可以。
参考系不同,位置的数值就不同了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP