Differences between revisions 1 and 3 (spanning 2 versions)
Revision 1 as of 2005-01-21 17:29:25
Size: 1775
Editor: 222
Comment:
Revision 3 as of 2005-01-22 18:47:18
Size: 3359
Editor: 222
Comment:
Deletions are marked like this. Additions are marked like this.
Line 25: Line 25:
  代码是最好的教程!   1, 关于EIP: 存放进程下一步指令的地址.
Line 41: Line 42:
  为什么结果是x = 0?
  我们在调用ch_eip的时候,改变了它生存时产生的Stack里存放的eip, 使得我们的函数返回时跳过了x = 1这一步,所以我们的结果是x = 0. ch_eip动了我们的eip.
  ch_eip()的执行改变了临时存放在栈里一个的eip, 使得的ch_eip()返回时跳过了x = 1这一步,所以我们的结果是x = 0. ch_eip动了我们的eip,我们得到了x = 0的输出结果.

** 关于栈 **
  1, 定义
    /------------------\ Higer
    | | memory
    | Stack | addresses
    | |
    |------------------|
    | (Initialized) |
    | Data |
    | (Uninitialized) |
    |------------------|
    | |
    | Text | Lower
    | | memory
    \------------------/ addresses
  2, 特点
    由高往低增长, 没有边界检查,因此存在溢出,表现形式为放入预定高内存区的内容的大小由于超过预设空间,因此把低内存的一些数据给覆盖了。而由于程序调用子函数时会把函数返回后的下一步指令的地址值压入堆栈,函数完成调用后将该值弹回eip,相对函数的内部变量的存放地值来说,这个值位于内存的低区域,因此就存在溢出的可嗯给,尽管不同的版本的编译器,使得栈中存放的函数返回调用地址相对函数内部变量的位置不一样,但溢出依然是没问题的。
/*
* 谁动了我的eip: DEMO 2
* 输出结果 segment falt 41414141
*/
int main() {
    char buffer[8];
    if (argc > 1) {
        strcpy(buffer, argv[1]);
    }
}

$./demo2 `perl -e 'print "A"x16'`
Segment falt 41414141
  进程收到SIGEVL, 我们的main函数中的strcpy操作将main调用返回后的下一步指令地址更改成为0x41414141, 而此地址指向的位置的指令不可运行,所以程序中止,那么如果指向的地址可以运行呢?答案是那么将不会中止。

标 题: 谁动了我的EIP 作 者: riverfor <mailto: [email protected]> 日 期: 2005-1-22 关键词: stack, shellcode 内 容;

  • 1 -- 简介
    • 1, EIP
    2 -- 关于栈
    • 1, 栈的定义 2, 不同的栈的结构变化
    3 -- 关于shellcode
    • 1, shellcode的定义 2, 怎样写出一个基本的shellcode 3, 怎样写出一个特殊的shellcode
    4 -- 改变EIP
    • 1, 直接法 2, 间接法
    5 -- 参考文献

写在前面的前面

  • 我是一个Linux fan, 本文所讲述的系统为X86架构上的Linux, 我用的linux为Redhat ES 和 knoppix, 使用的gcc都是Version3.2, 本文的例子都是基于此. 同时,我又是一个初学者,所以本文的思想都体现的是我对我所找到的相关文档的理解, 写下这片文章的目的除了以文档的形式总结一下自己所学的东西,同时在看国内前辈的文章时,感觉到前辈们虽然很理解Stack overflow,但是没有全面地讲述出来,我才艺不精,但自认文笔清晰,谨以此文献给广大Linux初级爱好者,也感谢高手们斧正。 本文的例子中,注释带[paltform]表示不同的Linux发行版或编译器,可能需要改变

** 简介 **

  • 1, 关于EIP: 存放进程下一步指令的地址.

  • int *ret;

    ret = (int *)&ret + 2; // [paltform] (*ret) += 7; // [paltform]

} int main() {

  • int x = 0; ch_eip(); x = 1; print("x = %d\n", x);

}

  • ch_eip()的执行改变了临时存放在栈里一个的eip, 使得的ch_eip()返回时跳过了x = 1这一步,所以我们的结果是x = 0. ch_eip动了我们的eip,我们得到了x = 0的输出结果.

** 关于栈 **

  • 1, 定义
    • /


\ Higer

  • | | memory | Stack | addresses | |

    |


|

  • | (Initialized) | | Data | | (Uninitialized) |

    |


|

  • | | | Text | Lower | | memory

    \


/ addresses

  • 2, 特点
    • 由高往低增长, 没有边界检查,因此存在溢出,表现形式为放入预定高内存区的内容的大小由于超过预设空间,因此把低内存的一些数据给覆盖了。而由于程序调用子函数时会把函数返回后的下一步指令的地址值压入堆栈,函数完成调用后将该值弹回eip,相对函数的内部变量的存放地值来说,这个值位于内存的低区域,因此就存在溢出的可嗯给,尽管不同的版本的编译器,使得栈中存放的函数返回调用地址相对函数内部变量的位置不一样,但溢出依然是没问题的。

/* * 谁动了我的eip: DEMO 2 * 输出结果 segment falt 41414141 */ int main() {

  • char buffer[8];

    if (argc > 1) {

    • strcpy(buffer, argv[1]);
    }

}

$./demo2 perl -e 'print "A"x16' Segment falt 41414141

  • 进程收到SIGEVL, 我们的main函数中的strcpy操作将main调用返回后的下一步指令地址更改成为0x41414141, 而此地址指向的位置的指令不可运行,所以程序中止,那么如果指向的地址可以运行呢?答案是那么将不会中止。

eip (last edited 2009-12-25 07:12:55 by localhost)