首页
社区
课程
招聘
[旧帖] [分享]最简单覆盖ret,我的学习心得 0.00雪花
发表于: 2008-7-17 16:47 4241

[旧帖] [分享]最简单覆盖ret,我的学习心得 0.00雪花

2008-7-17 16:47
4241
刚刚实验了第一个BufferOverflow Code,虽然非常简单,但是感觉自己还是收获了许多的知识,要赶快记录下来啊!子Function中的ret即使主调Function中的eip,在子 Function Return时将根据ret的值恢复eip,所以可以覆盖ret来实现跳转Program的Run!

c language code:

#include <stdio.h>
#include <string.h>

void function(char *pointer)
{
    char buffer[2]; //2 byte
    strcpy(buffer,pointer);
}

int main(void)
{
    char overflow_str[]="aaaa";
    function(overflow_str);
    printf("hello liquidworm\n");
    return 0;
}

在子Function被Call时,要负责完成以下事情:
1 按照从又至左的顺序吧参数入Stack
2 将当前eip入Stack为ret

此时控制权将友子Function接管,并且完成以下事情:
1 将当前ebp入Stack,以Save主调Function的Stack界限
2 将esp copy to ebp以重新设定子Function Stack界限
3 esp - 特定值,以为局部变量预留空间

上面code中Function被Call时,Stack结构如下:

|buffer   | <-2 byte
|ebp      | <-1 byte
|ret        | <- 1 byte
|pointer |
-----------

所以当填充4个byte时将覆盖ret,当子Function Return时,将会发生Error.
这里值得强调的是,也是我刚刚迷惑的地方就是:Buffer的生长方向是从低地址到高地址,而Stack的生长方向是从高地址到底地址,我之前忘记了这一点,当我问别人的时候才明白,所以Debug以后验证了这一点。由于偶还是只小小小鸟,所以还不知道怎么看code的address,所以没办法转移到指定code处,我会加油的。

如果以上存在error,还请高手客气的给予指正,尤其是那些步骤,我自己也不肯定!!

[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
呵呵,偶的学习心得,偶刚学习bufferoverflow,所以难免会有错误,大家可以客气的指正。呵呵,今天偶逆了点asm,找到个Address,的确可以跳过printf来,但是还是会有个框框错来哦~

#include <stdio.h>
#include <string.h>

void function(char *pointer)
{
        char buffer[2];  //2 byte
        strcpy(buffer,pointer);
}

int main(void)
{
        char overflow_str[]="aaa\\x4010c4";
        function(overflow_str);
        printf("hello liquidworm\n");
        return 0;
}

与上面code不同在于用0x4010c4覆盖ret。
我是不是覆盖错了啊?
2008-7-17 16:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你的字符串overflow_str有很多问题
首先,你的意思应该是"aaa\\x40\x10\xc4",你写掉了后面的\x
其次,小端机器里0x004010c4在内存里看起来应该是c4 10 40 00
因此你写字符串时应该反过来
再次,overflow时先覆盖的是旧的ebp值(除非你在release模式下没使用ebp),因此你覆盖时要先覆盖ebp,再才是返回地址
按你的思路,典型的字符串差不多是这样:overflow_str = "aaa\\x80\xff\x12\x00\xc4\x10\x40\x00"
其中0012ff80是旧ebp值,以保证它不被破坏,然后004010c4才是你想覆盖的返回地址
也就是跳过printf后的下一条指令地址
但是这样还是不行,因为字符串中间ebp值中含有\x00,strcpy在遇到它后会认为到达字符串末尾
因此你根本就不能覆盖后面的返回地址
如果我们把\x00改称非0值,比如\x01,则可以覆盖返回地址,执行时printf函数被跳过
但当main函数执行完后会平衡esp指针然后执行一个chkesp函数,它会检查esp指针和ebp指针是否相等
由于ebp改成了0112ff80是个错误值,因此报出一个debug错误框

2008-7-17 17:23
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢nichos的指导,说的很详细。但是你是怎么知道原始ebp应该是0x0012ff80的?
在overflow时遇到\x00将会被中止,有什么比较好的解决办法吗?
2008-7-17 19:10
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
學習學習~~~
2008-7-17 19:26
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
当然是debug时看内存阿,不清楚的话就学习下函数调用的栈帧结构
对于strcpy遇到0,没有什么办法解决,就比如写shellcode都会避免出现00字节一样,因为一旦出现在shellcode的中间某处,strcpy就会到此结束。debug下你可以直接把旧ebp值覆盖破坏掉,不理会那个debug error对话框。release下没有使用ebp时,直接覆盖返回地址,这时是没问题的

2008-7-17 19:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
release下没有使用ebp时,直接覆盖返回地址,这时是没问题的
=============
怎么理解呢?偶不明白啊,但是不是覆盖ret就一定会覆盖掉ebp吗?
我这2天正在用ollydbg看asm,尽量学习吧。
2008-7-18 07:33
0
游客
登录 | 注册 方可回帖
返回
//