pwnable.kr之simple login详解

学习二进制不容易,大家要忍得住寂寞,耐得住孤独,进入正题.
总体思路:
输入更多的数据,溢出,修改main的返回值地址,使其返回到correct中,从而获取shell.
大家可能会有疑问:为什么不修改auth函数的返回值地址,跳到correct中.这是因为长度不够,我们需要输入16个字节的长度,才能覆盖返回值地址,但是程序只给了我们12个字节的长度.
main函数

int  main(int argc, const char **argv, const char **envp)
{
  int v4; // [sp+18h] [bp-28h]@1
  int16 v5; // [sp+1Eh] [bp-22h]@1
  unsigned int v6; // [sp+3Ch] [bp-4h]@1

  memset(&v5, 0, 30);
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 1, 0);
  printf("Authenticate : ");
  _isoc99_scanf("%30s", &v5);
  memset(&input, 0, 12);
  v4 = 0;
  v6 = Base64Decode(&v5, &v4);   //base64解码,v5是输入的内容,v4是解码后的内容,v6是解码后的长度
  if ( v6 > 12 )
  {
    puts("Wrong Length");
  }
  else
  {
    memcpy(&input, v4, v6);     
    if ( auth(v6) == 1 )
      correct();
  }
  return 0;
}

auth函数

bool  auth(int a1)
{
  char v2; // [sp+14h] [bp-14h]@1
  char *s2; // [sp+1Ch] [bp-Ch]@1
  int v4; // [sp+20h] [bp-8h]@1

  memcpy(&v4, &input, a1);        //将缓冲区中a1个长度的字符赋值到v4中,
  s2 = (char *)calc_md5(&v2, 12);
  printf("hash : %s\n", (char)s2);
  return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0;
}

从上述逻辑中看出,若想获得shell,必须让auth返回值为1.可是每次输入,得出的结果是不一样的.
memcpy提供了一般内存的复制(例如字符数组、整型、结构体、类等)。即memcpy对于需要复制的内容没有限制,这是条件1.
main函数中还有

if ( v6 > 12 )
  {
    puts("Wrong Length");
  }

我们输入内容,解码后长度要<=12,这是条件二.
我们构造的12个字符长度的内容如下:

  1. 前四个字符随便取
  2. 中间四个字符为:\x84\x92\x04\x08.因为0x08049284是调用system函数的代码地址,有图为证
    system调用位置
  3. 最后四个字符为:\x40\xeb\x11\x08.地址0x0811eb40是input的地址.简单点说就是你输入的内容在缓冲区的地址,memcpy函数将缓冲区的内容复制到变量的地址中去.
    缓冲区分布图
    0x0811eb40将ebp覆盖掉,当atuh函数结束后,此时的ebp为0x0811eb40.
    ebp覆盖
    当main函数结束时,由于esp=ebp+4,esp的内容存的是函数返回值地址.esp返回值地址
    so,esp=0x0811eb40+4=0x0811eb44.而我们输入的内容在缓冲区中的地址是0x0811eb40,0x0811eb44—->0x08049284.于是跳转到correct中.
    获得shell
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值