[关闭]
@rg070836rg 2016-11-01T15:15:51.000000Z 字数 964 阅读 1776

栈溢出原理和实践

网络安全


一 修改领接变量

1.1 原理

函数的局部变量在栈中,一个挨着一个排列,如果有缓冲区,那么可能 就存在数组越界的可能,比如破坏相邻的变量值,或者破坏EBP,返回地址等。

1.2 示例

  1. #include "stdafx.h"
  2. #include <iostream>
  3. using namespace std;
  4. #define PASSWORD "12345"
  5. int verify(char * psw)
  6. {
  7. int auth;
  8. char buffer[8];
  9. auth = strcmp(PASSWORD, psw);
  10. strcpy(buffer, psw);//缓冲区溢出点
  11. return auth;
  12. }
  13. int main(int argc, _TCHAR* argv[])
  14. {
  15. int flag = 0;
  16. char psw[1024];
  17. while (1)
  18. {
  19. cout << "输入密码" << endl;
  20. cin >> psw;
  21. flag = verify(psw);
  22. if (flag)
  23. {
  24. cout << "密码错误" << endl;
  25. }
  26. else
  27. {
  28. cout << "验证成功" << endl;
  29. }
  30. }
  31. return 0;
  32. }

我们来观察auth的地址以及buffer的地址
&auth:0x0019FAC8
image_1b0f8sops9vb1mq61bov1bi36hi9.png-3.4kB

&buffer:0x0019FAC0
image_1b0f8uh2l14ro2vk1na519k8dnfm.png-3.4kB

image_1b0f90e2r14v1v12iio1btv3jb13.png-3kB

很容易发现auth刚好在buffer的下方,这样我们可以利用这个缓冲区,来替换auth的内容。

我们试着输入abcdefghijk:
image_1b0f96qeb1j1u12hug0o1j6910il1g.png-1.2kB
在执行过strcpy之后,我们观察内存:
image_1b0f96qeb1j1u12hug0o1j6910il1g.png-1.2kB

很容易发现,0x0019FAC8 中间的值被修改了。

那我们只要构造,让溢出的时候,让其为0即可

12.png-1.6kB

测试结果:
2.png-41.2kB

二 修改返回地址

这是函数栈帧的起始点与结束部分
image_1b0faoj979k67tehru10p11s7q1h.png-2.5kB
4.png-1.3kB

我们通过寄存器可以看到 EBP的地址:
EBP = 0019FACC
3.png-2.1kB

EBP上下文:
5.png-3.6kB
我们发现EBP在auth下方记下来一行就是我们函数的返回地址
这边记录的是我们的返回地址,对应着main函数(调用者)的EIP寄存器值。

main函数(调用者)
image_1b0fb4k4tg3kctarqv1evd1m8536.png-3.1kB

那么我们只需要修改EBP下方的内容,就可以重新定位返回点,来执行其他的代码,所以我们只需要找到一个有效的指令地址,就可以跳转到任意地方去执行代码。

从反汇编中,我们找到 验证成功的地址,我们只需要,将这个地址给构造进输入,那么就可以跳过验证,直接进入main中的else分支。
image_1b0fbag8q51r1jf67sl1vtlofj3j.png-4.2kB

这边由于某些地址对应的ASSIC字符,比较难输入(需要从文本读入比较方便),所以不去实验了。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注