免费注册 查看新帖 |

Chinaunix

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

这个最基础的注入为什么会出错啊? [复制链接]

论坛徽章:
0
发表于 2009-12-15 02:04 |显示全部楼层
按照mik老大的指点,从foo()中ret后,应该是这样的:

----------------------------
ret_value                                    <--------------------- main() 地址
----------------------------
%ebp
---------------------------

下面是attack():
push %ebp
mov %esp, %ebp
sub $0x8, %esp
....
leave
ret

也就是说attack()自己还会压入一个%ebp:

----------------------------
ret_value                                    <--------------------- main() 地址
----------------------------
%ebp
---------------------------
%ebp
---------------------------

那么当执行leave时,把pop出最顶上的%ebp,然后ret的时候....貌似再也回不去了(segment fault)

我已经崩溃了~~~~

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2009-12-15 04:55 |显示全部楼层

这个好玩

lz的代码造成segment fault可能是因为堆栈没有平衡。 实际上是多出栈了一次。
修改了foo的返回地址, 使得foo返回到attack而非main。
当foo返回到attack时, 再加上最终会在main中执行的foo调用的epilogue, 堆栈已经平衡。
而attack本身也会返回, 就多返回一次, 多出栈一次, 堆栈就完蛋了。


我也来一段吧
#include <stdio.h>

void g() { printf("call g\n"); }

void epilogue(void) {}

void prologue(void* anchor)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void** top = &anchor - 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void** end = anchor;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top[0] = g;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ( ++top != end )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*top = epilogue;
}

void f(void* anchor)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void (*noinline)(void*) = prologue;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;noinline(&anchor - 1);
}

int main(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void (*noinline)(void* ) = f;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("enter\n");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;noinline(0);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("leave\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}



prologue:
1. 将prologue的返回地址填为g, 使得prologue返回后,会执行g。
2. 在返回之前,将prologue的返回地址与f的返回地址(不包含f的返回地址)之间填为epilogue。
3. "返回到g"后, g的返回地址就是epilogue。

epilogue :
1. 在epilogue 中一直返回到自身, 用于平衡堆栈。
2. 重复1 直到最终返回到f的返回地址。 f调用完毕。

mingw 3.4.5
是否使用-O3 -fomit-frame-pointer都没有关系。

msvc
release没有问题。
debug会开启堆栈帧检查/RTCs。 虽然,其实堆栈是正确平衡了的。
f 中有将esp保存到esi的代码, 但恢复esi的代码, 却因为prologue函数不再返回f而得不到执行。 epilogue 返回main后,esp的值是调用前的值,但esi没有被正确回复。
去掉/RTCs, 会在代码最后形成一个奇怪的无限循环, 原因不明……

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
发表于 2009-12-15 04:59 |显示全部楼层
不过……  上面的代码, 以及下面的代码:

原帖由 iLRainyday 于 2009-12-8 22:34 发表
...
#define ARRAY_SIZE(arr)
   (sizeof(arr) / sizeof(((typeof(arr)){})[0]))
...


除了好玩, 真能派上什么用场???

论坛徽章:
0
发表于 2009-12-15 07:57 |显示全部楼层
原帖由 iLRainyday 于 2009-12-15 02:04 发表
按照mik老大的指点,从foo()中ret后,应该是这样的:
----------------------------
ret_value                                    

应该没错的,试过没?

[ 本帖最后由 mik 于 2009-12-15 08:04 编辑 ]

论坛徽章:
0
发表于 2009-12-15 11:05 |显示全部楼层
GOD!!!Jesus Christ!!!!这代码也太绕了吧,本来推算堆栈的位置就够费神了,这个连二级指针都能出来了。不过通过参数来确定eip的位置的方法不错,比起用局部变量似乎要清晰。

不过发现两件事情:
1. 如果有 void *ptr_v,肯定是不能对ptr_v进行算术运算,因为没有指向的type信息。但是竟然可以对&ptr_v进行算术运算,而且+1的步长和int *ptr_i是一样的

2.在prologue中,进行
  
while ( ++top != end )
            *top = epilogue;

的时候,会将f()用于返回时的ebp给覆盖掉,这样子没有问题吗?

另外,#define ARRAY_SIZE(arr) \
   (sizeof(arr) / sizeof(((typeof(arr)){})[0])) 就是为了防止不小心将指针作为参数传入,别的貌似也没了

论坛徽章:
0
发表于 2009-12-15 11:06 |显示全部楼层
应该没错的,试过没?

老大,这个试过的,真的不行

论坛徽章:
0
发表于 2009-12-15 15:28 |显示全部楼层
把汇编代码贴出来才能看出问题

论坛徽章:
0
发表于 2009-12-15 15:44 |显示全部楼层
按照老大的指点该成这样子了:


#include <stdio.h>

void attack() {
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;printf("hi,attacked!n");
&nbsp;&nbsp;
}


void foo() {
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;int c_foo;
&nbsp;&nbsp;&nbsp;&nbsp;int main_eip = (int) *(&c_foo + 3);
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;*(&c_foo + 3) = (int)attack;
&nbsp;&nbsp;&nbsp;&nbsp;*(&c_foo + 4) = (int) *(&c_foo + 2);
&nbsp;&nbsp;&nbsp;&nbsp;*(&c_foo + 5) = main_eip;
&nbsp;&nbsp;&nbsp;&nbsp;
}

void main()
{
&nbsp;&nbsp;int var;
&nbsp;&nbsp;foo();
&nbsp;&nbsp;printf("I am retrun!n");
&nbsp;
}

论坛徽章:
0
发表于 2009-12-15 15:50 |显示全部楼层
那对了没

论坛徽章:
0
发表于 2009-12-15 16:28 |显示全部楼层
那对了没

没有呀,还是segment fault
如果不觉得麻烦的话,您可以编译一下试试
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP