DASCTF X SU RE方向 stargate easyre


解出情况:

年轻人的第一个一血()

easyre

跑一下 提示wrong

ida32打开函数很少 没有wrong字符

但是有

vmp壳

scyllahide插件调一下

x32dbg动调 一路run到输入

然后暂停 然后alt+f9运行到用户代码

scylla

点dump

ida32分析dump出文件 字符串定位到right

finger插件分析一下里面的函数(或者肉眼看

拿到dword_492940即可

一个异或加法 比对

构造DASCTF{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}

让x32dbg断在004017CA 并打印ecx的值

最后脚本

enc = [0] * 42
enc[0] = 0xFFFFFFC3;
enc[1] = 0xFFFFFF80;
enc[2] = 0xFFFFFFD5;
enc[3] = 0xFFFFFFF2;
enc[4] = 0xFFFFFF9B;
enc[5] = 0x30;
enc[6] = 0xB;
enc[7] = 0xFFFFFFB4;
enc[8] = 0x55;
enc[9] = 0xFFFFFFDE;
enc[10] = 0x22;
enc[11] = 0xFFFFFF83;
enc[12] = 0x2F;
enc[13] = 0xFFFFFF97;
enc[14] = 0xFFFFFFB8;
enc[15] = 0x20;
enc[16] = 0x1D;
enc[17] = 0x74;
enc[18] = 0xFFFFFFD1;
enc[19] = 1;
enc[20] = 0x73;
enc[21] = 0x1A;
enc[22] = 0xFFFFFFB2;
enc[23] = 0xFFFFFFC8;
enc[24] = 0xFFFFFFC5;
enc[25] = 0x74;
enc[26] = 0xFFFFFFC0;
enc[27] = 0x5B;
enc[28] = 0xFFFFFFF7;
enc[29] = 0xF;
enc[30] = 0xFFFFFFD3;
enc[31] = 1;
enc[32] = 0x55;
enc[33] = 0xFFFFFFB2;
enc[34] = 0xFFFFFFA4;
enc[35] = 0xFFFFFFAE;
enc[36] = 0x7B;
enc[37] = 0xFFFFFFAC;
enc[38] = 0x5C;
enc[39] = 0x56;
enc[40] = 0xFFFFFFBC;
enc[41] = 0x23;
d = [0x38,
     0x78,
     0xDD,
     0xE8,
     0x0,
     0xAF,
     0xBF,
     0x3A,
     0x6B,
     0xFB,
     0xB8,
     0xC,
     0x85,
     0x35,
     0x15C,
     0xAD,
     0xE6,
     0x0,
     0xE0,
     0x8A,
     0x1D,
     0xBD,
     0x146,
     0xFFFFFFD2,
     0x2B,
     0x0,
     0x15,
     0x24,
     0xC6,
     0xAD,
     0xA1,
     0xC9,
     0x7B,
     0x12,
     0x28,
     0x0,
     0x5,
     0x0,
     0x72,
     0x3E,
     0x10,
     0xA1, ]
for index in range(42):
    print(chr(((enc[index] - 71) ^ (d[index])) & 0xff), end="")

stargate

一血!

真恶心啊( 每次连上靶机的文件 地址 字符串 路径都不一样 而且只有两分钟时间解

nc连上靶机之后给一个base64字符串 解密dump下来

ida64分析

main函数这样

别的函数都形如这样 输入一个字符串进入下一个函数 并将一个dword置零

你能通过字符串cat flag找到一个形如这样的特殊函数

易知道这是个图 是个一笔画问题 寻找欧拉路径即可

每个函数是点

上面的dword 随便交叉应用一个会发现是边

有几个难点

1.2分钟靶机时间 复制base64字符串再dump太慢 所以上pwntool

2.每次生成的文件不一样 所以必须能解析所有形式 所以决定用ida dump c 再拿正则表达式匹配

3.点有几百个 边有512条 (大概 所以只能自动化提交

4.因为大一还没学到欧拉路径算法 所以网上偷一个相关脚本(

#autosolve.py
from pwn import *
import work
import base64
context(log_level="DEBUG")
io=remote("node4.buuoj.cn",27463)
io.recvuntil("Gate")
code=io.recvuntil("==end==")
with open("stargate",'wb') as f:
    f.write(base64.b64decode(code[:-8]))
print("when ready, press enter to continue.")
raw_input()
work.work()
with open("res.txt") as f:
    #因为找出来的路径可能首尾顺序不对
    print("select mode: 1.normal 2.reverse")
    mode=raw_input()
    res=f.readlines()
    if mode=='2':res=res[::-1]
    for line in res:
        io.sendline(line.strip())
        io.recvuntil(":")
io.interactive()
#work.py
import re
from copy import copy


def is_connected(G):
    start_node = list(G)[0]
    color = {v: 'white' for v in G}
    color[start_node] = 'gray'
    S = [start_node]
    while len(S) != 0:
        u = S.pop()
        for v in G[u]:
            if color[v] == 'white':
                color[v] = 'gray'
                S.append(v)
            color[u] = 'black'
    return list(color.values()).count('black') == len(G)


def odd_degree_nodes(G):
    odd_degree_nodes = []
    for u in G:
        if len(G[u]) % 2 != 0:
            odd_degree_nodes.append(u)
    return odd_degree_nodes


def from_dict(G):
    links = []
    for u in G:
        for v in G[u]:
            links.append((u, v))
    return links


def fleury(G):
    '''
        checks if G has eulerian cycle or trail
    '''
    odn = odd_degree_nodes(G)
    if len(odn) > 2 or len(odn) == 1:
        return 'Not Eulerian Graph'
    else:
        g = copy(G)
        trail = []
        if len(odn) == 2:
            u = odn[0]
        else:
            u = list(g)[0]
        while len(from_dict(g)) > 0:
            current_vertex = u
            for u in g[current_vertex]:
                g[current_vertex].remove(u)
                g[u].remove(current_vertex)
                bridge = not is_connected(g)
                if bridge:
                    g[current_vertex].append(u)
                    g[u].append(current_vertex)
                else:
                    break
            if bridge:
                g[current_vertex].remove(u)
                g[u].remove(current_vertex)
                g.pop(current_vertex)
            trail.append((current_vertex, u))
    return trail


def work():
    with open("stargate.c", "r") as f:
        t = f.read()
    a___AAAA = re.findall('  if \( !strcmp\(".*?", s2\) \)\n    sub_[0123456789abcdefABCDEF]{6}\(\);', t)
    for index in range(len(a___AAAA)):
        a___AAAA[index] = a___AAAA[index].replace(" ", "")
        a___AAAA[index] = a___AAAA[index].replace(r'",s2))', "")
        a___AAAA[index] = a___AAAA[index].replace(r'if(!strcmp("', "")
        a___AAAA[index] = a___AAAA[index].replace(r'();', "")
    a = []
    for x in a___AAAA:
        x = x.split()
        a.append(x[0])
        a.append(x[1])
    # 这俩字典都是找函数名字和输入字符串对应的
    func_dic0 = {}
    func_dic1 = {}
    for index in range(0, len(a), 2):
        func_dic0[a[index]] = a[index + 1]
        func_dic1[a[index + 1]] = a[index]
    func_name = []
    for x in func_dic1:
        func_name.append(x)
    with open("stargate.c", "r") as f:
        t = f.read()
    func_dots = {}
    funcs = re.findall(
        '__int64 sub_[0123456789abcdefABCDEF]{6}\(\)\n{\n  char s2\[40\]; // \[rsp\+0h\] \[rbp\-30h\] BYREF\n  unsigned __int64 v2; // \[rsp\+28h\] \[rbp\-8h\].*?Wrong password!',
        t, re.DOTALL)
    ttttt = {}
    for func in funcs:
        tname = re.findall("sub_[0123456789abcdefABCDEF]{6}", func)[0]
        tid = func_name.index(tname)
        # 用ttttt来表示点与点的联通关系
        ttttt[tid] = []
        tinfo = re.findall("    dword_[0123456789abcdefABCDEF]{6} = 0;\n    sub_[0123456789abcdefABCDEF]{6}\(\);", func)
        for x in tinfo:
            tsub = re.findall("sub_[0123456789abcdefABCDEF]{6}", x)[0]
            tttid = func_name.index(tsub)
            ttttt[tid].append(tttid)
    # fleury只接受这样的参数 {0: [1, 6], 1: [0, 2, 9, 45, 58, 100, 136, 142]...} 表示从第几个点到第几个点
    r = fleury(ttttt)
    with open("res.txt", "w")as f:
        for x in r:
            f.write(func_dic1[func_name[x[0]]])
            f.write("\n")
        f.write(func_dic1[func_name[r[-1][1]]])d

先连上靶机 然后等文件夹下出现stargate文件

然后ida64分析

选择creat c file

然后回车脚本继续运行

会生成res.txt

手动看一眼头尾顺序对不对

然后再自动提交

getflag!

wp