第六届强网杯全国网络安全挑战赛 Re WriteUp

  1. GameMaster
  2. deeprev
  3. easyre
    1. Easyre
      1. sub_401F2F
      2. sub_4017E5
    2. re3
      1. sub_2490
      2. loc_21F9
    3. SMC
  4. find_basic
  5. 总结

GameMaster

老样子先查壳

一个C#的程序,可以用dnspy反编译

画圈部分是读取gamemessage文件,其他的都是游戏的初始化之类的

当我们按下ESC ,会进入verifyCode(arrayList, game)函数

进去发现将输入的字符变成字符串,然后进入goldFunc

进去发现是对我们的输入进行比较,然后进行相应的操作,类似小时候玩的GTA里面作弊码

简单分析一下,这里的操作主要有对读取的gamemessage文件先进行xor34,然后进行AES解密,我们可以自己解密,也可以重新利用反汇编代码。dnspy可以导入工程到vs里。把一些没用的比较都删了,只留下对文件操作的部分

using System;
using System.Collections;
using System.Configuration;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;
using Blackjack;

namespace Game
{
	internal class Program
	{
        private static byte[] memory;
        private static byte[] m;

        private static void Main(string[] args)
		{
			ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true");
			FileStream fileStream = File.OpenRead("gamemessage");
			int num = (int)fileStream.Length;
			Program.memory = new byte[num];
			fileStream.Position = 0L;
			fileStream.Read(Program.memory, 0, num);
			for (int i = 0; i < Program.memory.Length; i++)
			{
				byte[] array = Program.memory;
                array[i] ^= 34;
			}
			byte[] key = new byte[]{66,114,97,105,110,115,116,111,114,109,105,110,103,33,33,33};
			ICryptoTransform cryptoTransform = new RijndaelManaged{Key = key,Mode = CipherMode.ECB, Padding = PaddingMode .Zeros}.CreateDecryptor();
			Program.m = cryptoTransform.TransformFinalBlock(Program.memory, 0, Program.memory.Length);
			File.WriteAllBytes("aa.out", Program.m);	
		}
	}
}		

这是解密完的样子,里面搜到MZ标志,发现有可执行文件特征

把前面都删了,将可执行文件分离出来

又是一个C#文件,拖入dnspy分析

num,num2,num3是环境变量,然后传入check,传出一个array2数组,与first比较

分析一波check

通过变化生成KeyStream,然后与first比较,这里可以通过Z3反求num,num2,num3

from z3 import *
def check(x, y, z):
    num = -1
    keystream = [0] * 40

    for i in range(320):
        x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
        y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
        z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
        if i % 8 == 0:
            num += 1

        keystream[num] = ((((keystream[num] << 1) | (((z >> 32) & 1 & ((x >> 30) & 1)) ^ ((((z >> 32) & 1) ^ 1) & ((y >> 31) & 1))))))&0xff
    return keystream

def getxyz():
    s = Solver()
    x = BitVec('x', 64)
    y = BitVec('y', 64)
    #x = 156324965
    #y = 868387187
    z = BitVec('z', 64)
    num = -1
    keystream = [0] * 40

    for i in range(320):
        x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
        y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
        z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
        if i % 8 == 0:
            num += 1

        keystream[num] = ((((keystream[num] << 1) | (((z >> 32) & 1 & ((x >> 30) & 1)) ^ ((((z >> 32) & 1) ^ 1) & ((y >> 31) & 1))))))

    s.add(keystream[0] == 101)
    s.add(keystream[1] == 5)
    s.add(keystream[2] == 80)
    s.add(keystream[3] == 213)
    s.add(keystream[4] == 163)
    s.add(keystream[5] == 26)
    s.add(keystream[6] == 59)
    s.add(keystream[7] == 38)
    s.add(keystream[8] == 19)
    s.add(keystream[9] == 6)
    s.add(keystream[10] == 173)
    s.add(keystream[11] == 189)
    s.add(keystream[12] == 198)
    s.add(keystream[13] == 166)
    s.add(keystream[14] == 140)
    s.add(keystream[15] == 183)
    s.add(keystream[16] == 42)
    s.add(keystream[17] == 247)
    s.add(keystream[18] == 223)
    s.add(keystream[19] == 24)
    s.add(keystream[20] == 106)
    s.add(keystream[21] == 20)
    s.add(keystream[22] == 145)
    s.add(keystream[23] == 37)
    s.add(keystream[24] == 24)
    s.add(keystream[25] == 7)
    s.add(keystream[26] == 22)
    s.add(keystream[27] == 191)
    s.add(keystream[28] == 110)
    s.add(keystream[29] == 179)
    s.add(keystream[30] == 227)
    s.add(keystream[31] == 5)
    s.add(keystream[32] == 62)
    s.add(keystream[33] == 9)
    s.add(keystream[34] == 13)
    s.add(keystream[35] == 17)
    s.add(keystream[36] == 65)
    s.add(keystream[37] == 22)
    s.add(keystream[38] == 37)
    s.add(keystream[39] == 5)

    print(s.check())

    if (s.check() == sat):
        print(s.model())


#getxyz()
key=[156324965,868387187,3131229747]

encflag=[60,100,36,86,51,251,167,108,116,245,207,223,40,103,34,62,22,251,227]
Key=[0]*12

for i in range(3):
	for j in range(4):
		Key[i * 4 + j] = (key[i] >> j * 8 & 255)

print(Key)

for i in range(len(encflag)):
	encflag[i]=encflag[i]^Key[i%len(Key)]

for k in range(len(encflag)):
	print(chr(encflag[k]),end="")

num,num2,num3都是八字节,64位注意一下。得到num=156324965,num2=868387187,num3=3131229747,然后传入ParseKey生成key,最后就是一个很简单xor。

deeprev

这题是谷歌ctf2022的模板题,我是直接对着那题的wp复现的

https://ctf.harrisongreen.me/2022/googlectf/eldar/

# Author: hgarrereyn
# Desc: Lifter solution for GoogleCTF 2022 eldar

import lief
from collections import namedtuple
from dataclasses import dataclass
from typing import Any
from capstone import *



md = Cs(CS_ARCH_X86, CS_MODE_64)

b = None
try:
    b = lief.ELF.parse('./deeprev')
except:
    raise Exception('Must have the ./eldar binary in cwd')

rela = [x for x in b.sections if x.name == '.rela.dyn'][0]
print(rela)
dynsym = [x for x in b.sections if x.name == '.dynsym'][0]


@dataclass
class Symbol(object):
    idx: int
    def __repr__(self):
        return f's{self.idx}'
        
@dataclass
class Reloc(object):
    idx: int
    def __repr__(self):
        return f'r{self.idx}'

@dataclass
class Ref(object):
    val: Any
    def __repr__(self):
        return f'&{self.val}'

@dataclass
class SymAddr(object):
    sym: Symbol
    field: str
    def __repr__(self):
        return f'{self.sym}.{self.field}'

@dataclass
class RelocAddr(object):
    reloc: Reloc
    field: str
    def __repr__(self):
        return f'{self.reloc}.{self.field}'

    def vaddr(self):
        off = 0
        match self.field:
            case 'r_address':off = 0
            case 'r_info': off = 8
            case 'r_addend': off = 16
        
        return (self.reloc.idx * 24) + off + rela.virtual_address
    
@dataclass
class FlagAddr(object):
    idx: int
    def __repr__(self):
        return f'flag[{self.idx}]'

@dataclass
class OutAddr(object):
    idx: int
        
    def __repr__(self):
        return f'out[{self.idx}]'
    
@dataclass
class ArrAddr(object):
    idx: int
        
    def __repr__(self):
        return f'arr[{self.idx}]'

BaseAddr = namedtuple('baseaddr', [])
FailAddr = namedtuple('fail', [])

def format_addr(addr: int):
    if addr >= rela.virtual_address and addr < rela.virtual_address + rela.size:
        offset = addr - rela.virtual_address
        r_offset = (offset // 24)
        r_rem = offset % 24
        
        if r_offset >= 3 and r_offset <= 88:
            arr_idx = (r_offset - 3) * 3 + (r_rem // 8)
            return ArrAddr(arr_idx)
        elif r_offset == 89:
            return OutAddr(r_rem)
        
        match r_rem:
            case 0: return RelocAddr(Reloc(r_offset), 'r_address')
            case 8: return RelocAddr(Reloc(r_offset), 'r_info')
            case 16: return RelocAddr(Reloc(r_offset), 'r_addend')
            case _: return RelocAddr(Reloc(r_offset), r_rem)
    elif addr > dynsym.virtual_address and addr < dynsym.virtual_address + dynsym.size:
        offset = addr - dynsym.virtual_address
        r_offset = (offset // 24)
        r_rem = offset % 24
        
        match r_rem:
            case 0: return SymAddr(Symbol(r_offset), 'st_name')
            case 8: return Symbol(r_offset)
            case 16: return SymAddr(Symbol(r_offset), 'st_size')
            case _: return SymAddr(Symbol(r_offset), r_rem)
    elif addr >= 0x404040 and addr < 0x404040+33:
        off = addr-0x404040
        return FlagAddr(off)
    elif addr == 0x804000:
        return BaseAddr()
    elif addr == 0x404064:
        return FailAddr()
    else:
        return addr

def to_sym(name):
    assert len(name) == 1
    return Symbol(ord(name[0]))

Rel = namedtuple('REL', ['dst','val','ridx'])
Copy = namedtuple('CPY', ['dst', 'symbol', 'ridx'])
R64 = namedtuple('R64', ['dst','symbol','addend','ridx'])
R32 = namedtuple('R32', ['dst','symbol','addend','ridx'])

def parse(b) -> list:
    print('[*] Loading relocations...')
    relocs = list(b.relocations)
    
    print('[*] Parsing...')
    instructions = []
    for i in range(3, len(relocs)):
        r = relocs[i]
        match r.type:
            case 1: # R64
                instructions.append(R64(format_addr(r.address), to_sym(r.symbol.name), format_addr(r.addend), i))
            case 5: # CPY
                instructions.append(Copy(format_addr(r.address), to_sym(r.symbol.name), i))
            case 8: # REL
                instructions.append(Rel(format_addr(r.address), format_addr(r.addend), i))
            case 10: # R32
                instructions.append(R32(format_addr(r.address), to_sym(r.symbol.name), format_addr(r.addend), i))
                
    return instructions

Mov = namedtuple('mov', ['dst', 'src', 'sz', 'ridx'])
Add = namedtuple('add', ['dst', 'src', 'addend', 'ridx'])

def lift_mov_add(instructions):
    idx = 0
    
    sizes = []
    curr = [8] * 8
    sizes.append(curr)

    for instr in instructions:
        c = list(curr)
        match instr:
            case Rel(SymAddr(Symbol(idx), 'st_size'), val, ridx):
                c[idx] = val
        sizes.append(c)
    
    while idx < len(instructions):
        match instructions[idx]:
            case Rel(dst, val, ridx):
                instructions[idx] = Mov(dst, Ref(val), 8, ridx)
            case Copy(dst, sym, ridx):
                instructions[idx] = Mov(dst, sym, sizes[idx][sym.idx], ridx)
            case R64(dst, sym, add, ridx):
                instructions[idx] = Add(dst, sym, add, ridx)
        idx += 1
    return instructions

def remove_sizes(instructions):
    # Sizes are now nops
    idx = 0
    while idx < len(instructions):
        match instructions[idx]:
            case Mov(SymAddr(Symbol(s), 'st_size'), _, _, _) if s != 3:
                instructions[idx:idx+1] = []

        idx += 1
    return instructions

def lift_indirect(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+3]:
            case [
                Mov(RelocAddr(Reloc(rel_1), 'r_addend'), Symbol(sidx_1), sz_1, ridx_1),
                Add(dst_2, sym_2, _, ridx_2),
                Mov(RelocAddr(Reloc(rel_3), 'r_addend'), Ref(0), sz_3, _),
            ] if (
                (rel_1 == ridx_2) and (rel_3 == ridx_2)
            ):
                instructions[idx:idx+3] = [
                    Add(dst_2, sym_2, Symbol(sidx_1), ridx_1)
                ]

        idx += 1
    return instructions

Block = namedtuple('block', ['arr', 'flag', 'ridx'])
Output = namedtuple('output', ['out', 'arr', 'ridx'])

def lift_block(instructions):
 
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+18]:
            case [
                Mov(_,arr,_,ridx),
                Add(_,_,_,_),
                Mov(_,flag,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                R32(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
            ]:
                instructions[idx:idx+18] = [
                    Block(arr, flag, ridx)
                ]
        idx += 1
    return instructions

Reset = namedtuple('reset', ['ridx'])
ShuffleBlock = namedtuple('shuffleblock', ['f1', 'f2', 'ridx'])

def lift_reset(instructions):
    idx = 0
    while idx < len(instructions) - 256:
        good = True

        for i in range(256):
            op = instructions[idx+i]
            if type(op) == Mov:
                dst, src, _, _ = op
                if dst != ArrAddr(i) or src != Ref(i):
                    good = False
                    break
            else:
                good = False
                break

        if good:
            instructions[idx:idx+256] = [Reset(instructions[idx].ridx)]

        idx += 1
    return instructions

def lift_shuffle_block(instructions):
    idx = 0
    while idx < len(instructions) - 256:
        good = True

        for i in range(256):
            op = instructions[idx+i]
            if type(op) == Block:
                arr, flag, ridx = op
                if arr != Ref(ArrAddr(i)):
                    good = False
                    break
            else:
                good = False
                break

        if good:
            instructions[idx:idx+256] = [ShuffleBlock(instructions[idx].flag, instructions[idx+1].flag, instructions[idx].ridx)]

        idx += 1
    return instructions

Output = namedtuple('output', ['out', 'arr', 'ridx'])

def lift_output(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+26]:
            case [
                Mov(_,arr,_,ridx),
                Add(_,_,_,_),
                R32(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                R32(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Mov(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Add(_,_,_,_),
                Mov(out,_,_,_),
            ]:
                instructions[idx:idx+26] = [Output(out, arr, ridx)]
        idx += 1
    return instructions

MultAdd = namedtuple('multadd', ['out', 'val', 'k', 'ridx'])

def lift_multadd(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+3]:
            # block prefix
            case [
                Mov(Symbol(2), out, _, ridx),
                Mov(Symbol(5), Symbol(2), _, _),
                Mov(Symbol(6), Ref(0), _, _),
            ]:
                k = 0
                double = False

                ptr = idx + 3

                good = True
                while ptr < len(instructions):
                    match instructions[ptr]:
                        case Mov(Symbol(2), Ref(Symbol(6)), _, _):
                            double = True
                        case Mov(Symbol(2), Ref(Symbol(5)), _, _):
                            double = False
                        case Add(Symbol(6), Symbol(6), Symbol(2), _):
                            k = (k * 2) if double else (k + 1)
                        case Add(Symbol(7), Symbol(7), Symbol(2), _):
                            ptr += 1
                            break
                        case _:
                            good = False
                            break

                    ptr += 1
                
                if good:
                    instructions[idx:ptr] = [
                        MultAdd(Symbol(7), out, k, ridx)
                    ]

        idx += 1

    return instructions

Trunc = namedtuple('trunc', ['val', 'k', 'ridx'])

def lift_truncate(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+2]:
            case [
                Mov(Symbol(2), Ref(SymAddr(Symbol(5), 11)), _, ridx),
                Mov(SymAddr(Symbol(7), 11), Symbol(2), 5, _)
            ]:
                instructions[idx:idx+2] = [
                    Trunc(Symbol(7), 0xffffff, ridx)]
        idx += 1
    return instructions

ArraySlots = namedtuple('arr', ['values', 'ridx'])

def lift_array_slots(instructions):
    idx = 0
   
    while idx < 1300:
        match instructions[idx]:
            case Mov(BaseAddr(), Ref(0), _, ridx):
                ptr = idx+1
                while ptr < len(instructions):
                    op = instructions[ptr]
                    if type(op) != Mov or op.dst != BaseAddr():
                        break
                    ptr += 1

                start = idx
                end = ptr

                data = []

                # Check for movs into array.
                vstart = RelocAddr(Reloc(ridx), 'r_address').vaddr()
                offset = 0
                while end + offset < len(instructions) and offset < ((end - start) * 3):
                    op = instructions[end + offset]
                    if type(op) == Mov and type(op.dst) is RelocAddr and op.dst.vaddr() == vstart + (offset * 8):
                        data.append(op.src.val)
                    else:
                        break
                    offset += 1

                if len(data) > 0:
                    data += [0] * (((end - start) * 3) - len(data))   
                    instructions[idx:end+offset] = [
                        ArraySlots(data, ridx)
                    ]

        idx += 1
    return instructions

Shellcode = namedtuple('shellcode', ['dst', 'code', 'ridx'])

def lift_shellcode(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+6]:
            case [
                ArraySlots(values, ridx),
                Mov(Symbol(3), Ref(RelocAddr(Reloc(rel2), 'r_address')), _, _),
                Mov(SymAddr(Symbol(3), 'st_name'), _, _, _),
                Add(dst, Symbol(3), _, _),
                Mov(Symbol(2), _, _, _),
                Mov(RelocAddr(Reloc(rel6), 'r_address'), Symbol(2), _, _)
            ] if (rel2 == ridx) and (rel6 == ridx):
                instructions[idx:idx+6] = [
                    Shellcode(dst, b''.join([(x & 0xffffffffffffffff).to_bytes(8, 'little') for x in values]), ridx)
                ]
        idx += 1
    return instructions

Aop = namedtuple('aop', ['dst', 'op', 'val', 'k', 'ridx'])

def lift_aop(instructions):
    idx = 0
    while idx < len(instructions):
        match instructions[idx:idx+5]:
            case [
                Mov(Symbol(2), val, _, ridx),
                Mov(Symbol(5), Symbol(2), _, _),
                Shellcode(_, data, _),
                Mov(Symbol(2), Ref(Symbol(5)), _, _),
                Add(dst, dst2, Symbol(2), _)
            ] if len(data) == 24 and (dst == dst2):
                op = next(md.disasm(data, 0))

                t = op.mnemonic
                k = int(op.op_str.split(', ')[-1], 16)

                instructions[idx:idx+5] = [
                    Aop(dst, t, val, k, ridx)
                ]

        idx += 1
    return instructions






def dump(instructions):
    for op in instructions:
        match op:
            case Mov(SymAddr(sym, 'st_name'), Ref(val), 8, ridx) if type(val) is int:
                name = val & 0xffffffff
                info = (val >> 4) & 0xff
                other = (val >> 5) & 0xff
                shndx = (val >> 6) & 0xffff
                print(f'[{ridx:04d}] :: setinfo {sym}, name=0x{name:x}, info=0x{info:x}, other=0x{other:x}, shndx=0x{shndx:x}')
            case Mov(BaseAddr(), Ref(0), _, ridx):
                print(f'[{ridx:04d}] :: [ARRAY SLOT]')
            case Mov(dst, src, 8, ridx):
                print(f'[{ridx:04d}] :: mov {dst}, {src}')
            case Mov(dst, src, sz, ridx):
                print(f'[{ridx:04d}] :: mov({sz}) {dst}, {src}')
            case Add(dst, src, add, ridx):
                print(f'[{ridx:04d}] :: add {dst}, {src}, {add}')
            case R32(dst, src, add, ridx):
                print(f'[{ridx:04d}] :: r32 {dst}, {src}, {add}')
            case Block(arr, flag, ridx):
                print(f'[{ridx:04d}] :: shuffle {arr}, {flag}')
            case Output(out, arr, ridx):
                print(f'[{ridx:04d}] :: output {out}, {arr}')
            case ShuffleBlock(f1, f2, ridx):
                print(f'[{ridx:04d}] :: shuffleblock {f1}, {f2}')
            case MultAdd(dst, val, k, ridx):
                print(f'[{ridx:04d}] :: madd {dst} += ({val} * {k})')
            case Aop(dst, op, val, k, ridx):
                print(f'[{ridx:04d}] :: aop {dst} += ({val} {op} {k})')
            case Reset(ridx):
                print(f'[{ridx:04d}] :: reset')
            case Trunc(val, k, ridx):
                print(f'[{ridx:04d}] :: trunc {val} &= 0x{k:x}')
            case ArraySlots(values, ridx):
                print(f'[{ridx:04d}] :: array [{", ".join([hex(x) for x in values])}]')
            case Shellcode(dst, code, ridx):
                print(f'[{ridx:04d}] :: exec {dst} <- {code.hex()}')
                print('-' * 20)
                for i in md.disasm(code, 0):
                    if i.mnemonic == 'ret':
                        break
                    print("    0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str.replace('0x8040e4', 's5').replace('0x8040cc', 's4')))
                print('-' * 20)
            case _:
                print(op)

LIFTS = [
    lift_mov_add,
    remove_sizes,
    lift_indirect,
    lift_block,
    lift_reset,
    lift_shuffle_block,
    lift_output,
    lift_multadd,
    lift_truncate,
    lift_array_slots,
    lift_shellcode,
    lift_aop,
]

def lift(instructions):
    for lift_fn in LIFTS:
        print(f'[*] {lift_fn.__name__}...')
        instructions = lift_fn(instructions)
    return instructions

instructions = parse(b)
instructions = lift(instructions)
dump(instructions)

这题主要是把opcode和data都放到了重定位表里,而lief解析重定位数据和符号引用非常好。跑出来大概有1300行左右的伪代码,然后再转成汇编的样子。

因为伪代码到汇编的转换只需要1300行就够了,后面都是无用指令,所以lift_array_slots函数需要把循环条件缩小到1300行就行了,要不然会去翻译十万行指令,比较浪费时间

.rela.dyn           RELA           804272    24fd08    4272      0.767243  ALLOC                         LOAD           
[*] Loading relocations...
[*] Parsing...
[*] lift_mov_add...
[*] remove_sizes...
[*] lift_indirect...
[*] lift_block...
[*] lift_reset...
[*] lift_shuffle_block...
[*] lift_output...
[*] lift_multadd...
[*] lift_truncate...
[*] lift_array_slots...
[*] lift_shellcode...
[*] lift_aop...
REL(dst=baseaddr(), val=0, ridx=3)
REL(dst=baseaddr(), val=0, ridx=4)
[0005] :: mov s2, &flag[0]
[0007] :: mov(1) s4, s2
[0008] :: [ARRAY SLOT]
[0009] :: mov arr[15], &1585408084625667200
[0010] :: mov arr[16], &195

xor	byte ptr [s4], 0x16

[0011] :: mov s3, &arr[15]
[0012] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0013] :: add arr[15], s3, 0
[0014] :: mov s2, &r101002.r_address
[0016] :: mov(24) arr[15], s2
[0017] :: [ARRAY SLOT]
[0018] :: mov arr[42], &141015791240320
[0019] :: mov arr[43], &195

add byte ptr [s4],0

[0020] :: mov s3, &arr[42]
[0021] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0022] :: add arr[42], s3, 0
[0023] :: mov arr[42], s2
[0024] :: mov s2, &s4
[0026] :: mov(1) arr[0], s2
[0027] :: mov s2, &flag[1]
[0028] :: mov s4, s2
[0029] :: [ARRAY SLOT]
[0030] :: mov arr[78], &1657465678663595136
[0031] :: mov arr[79], &195

xor	byte ptr [s4], 0x17

[0032] :: mov s3, &arr[78]
[0033] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0034] :: add arr[78], s3, 0
[0035] :: mov s2, &r101002.r_address
[0037] :: mov(24) arr[78], s2
[0038] :: [ARRAY SLOT]
[0039] :: mov arr[105], &72198609829168256
[0040] :: mov arr[106], &195

add byte ptr [s4],1

[0041] :: mov s3, &arr[105]
[0042] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0043] :: add arr[105], s3, 0
[0044] :: mov arr[105], s2
[0045] :: mov s2, &s4
[0047] :: mov(1) arr[0], s2
[0048] :: mov s2, &flag[2]
[0049] :: mov s4, s2
[0050] :: [ARRAY SLOT]
[0051] :: mov arr[141], &1153062520398099584
[0052] :: mov arr[142], &195

xor	byte ptr [s4], 0x10

[0053] :: mov s3, &arr[141]
[0054] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0055] :: add arr[141], s3, 0
[0056] :: mov s2, &r101002.r_address
[0058] :: mov(24) arr[141], s2
[0059] :: [ARRAY SLOT]
[0060] :: mov arr[168], &144256203867096192
[0061] :: mov arr[169], &195

add byte ptr [s4],2

[0062] :: mov s3, &arr[168]
[0063] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0064] :: add arr[168], s3, 0
[0065] :: mov arr[168], s2
[0066] :: mov s2, &s4
[0068] :: mov(1) arr[0], s2
[0069] :: mov s2, &flag[3]
[0070] :: mov s4, s2
[0071] :: [ARRAY SLOT]
[0072] :: mov arr[204], &1297177708473955456
[0073] :: mov arr[205], &195

xor	byte ptr [s4], 0x12

[0074] :: mov s3, &arr[204]
[0075] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0076] :: add arr[204], s3, 0
[0077] :: mov s2, &r101002.r_address
[0079] :: mov(24) arr[204], s2
[0080] :: [ARRAY SLOT]
[0081] :: mov arr[231], &216313797905024128
[0082] :: mov arr[232], &195

add byte ptr [s4],3

[0083] :: mov s3, &arr[231]
[0084] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0085] :: add arr[231], s3, 0
[0086] :: mov arr[231], s2
[0087] :: mov s2, &s4
[0089] :: mov(1) arr[0], s2
[0090] :: mov s2, &flag[4]
[0091] :: mov s4, s2
[0092] :: exec r92.r_address <- 803425cc40800010c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x10
--------------------
[0101] :: array [0x4008040cc250480, 0xc3, 0x0]
[0104] :: mov s3, &r101.r_address
[0105] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0106] :: add r101.r_address, s3, 0
[0107] :: mov r101.r_address, s2
[0108] :: mov s2, &s4
[0110] :: mov(1) arr[0], s2
[0111] :: mov s2, &flag[5]
[0112] :: mov s4, s2
[0113] :: exec r113.r_address <- 803425cc40800011c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x11
--------------------
[0122] :: array [0x5008040cc250480, 0xc3, 0x0]
[0125] :: mov s3, &r122.r_address
[0126] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0127] :: add r122.r_address, s3, 0
[0128] :: mov r122.r_address, s2
[0129] :: mov s2, &s4
[0131] :: mov(1) arr[0], s2
[0132] :: mov s2, &flag[6]
[0133] :: mov s4, s2
[0134] :: exec r134.r_address <- 803425cc40800012c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x12
--------------------
[0143] :: array [0x6008040cc250480, 0xc3, 0x0]
[0146] :: mov s3, &r143.r_address
[0147] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0148] :: add r143.r_address, s3, 0
[0149] :: mov r143.r_address, s2
[0150] :: mov s2, &s4
[0152] :: mov(1) arr[0], s2
[0153] :: mov s2, &flag[7]
[0154] :: mov s4, s2
[0155] :: exec r155.r_address <- 803425cc40800013c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x13
--------------------
[0164] :: array [0x7008040cc250480, 0xc3, 0x0]
[0167] :: mov s3, &r164.r_address
[0168] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0169] :: add r164.r_address, s3, 0
[0170] :: mov r164.r_address, s2
[0171] :: mov s2, &s4
[0173] :: mov(1) arr[0], s2
[0174] :: mov s2, &flag[8]
[0175] :: mov s4, s2
[0176] :: exec r176.r_address <- 803425cc40800014c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x14
--------------------
[0185] :: array [0x8008040cc250480, 0xc3, 0x0]
[0188] :: mov s3, &r185.r_address
[0189] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0190] :: add r185.r_address, s3, 0
[0191] :: mov r185.r_address, s2
[0192] :: mov s2, &s4
[0194] :: mov(1) arr[1], s2
[0195] :: mov s2, &flag[9]
[0196] :: mov s4, s2
[0197] :: exec r197.r_address <- 803425cc40800015c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x15
--------------------
[0206] :: array [0x9008040cc250480, 0xc3, 0x0]
[0209] :: mov s3, &r206.r_address
[0210] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0211] :: add r206.r_address, s3, 0
[0212] :: mov r206.r_address, s2
[0213] :: mov s2, &s4
[0215] :: mov(1) arr[1], s2
[0216] :: mov s2, &flag[10]
[0217] :: mov s4, s2
[0218] :: exec r218.r_address <- 803425cc40800016c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x16
--------------------
[0227] :: array [0xa008040cc250480, 0xc3, 0x0]
[0230] :: mov s3, &r227.r_address
[0231] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0232] :: add r227.r_address, s3, 0
[0233] :: mov r227.r_address, s2
[0234] :: mov s2, &s4
[0236] :: mov(1) arr[1], s2
[0237] :: mov s2, &flag[11]
[0238] :: mov s4, s2
[0239] :: exec r239.r_address <- 803425cc40800017c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x17
--------------------
[0248] :: array [0xb008040cc250480, 0xc3, 0x0]
[0251] :: mov s3, &r248.r_address
[0252] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0253] :: add r248.r_address, s3, 0
[0254] :: mov r248.r_address, s2
[0255] :: mov s2, &s4
[0257] :: mov(1) arr[1], s2
[0258] :: mov s2, &flag[12]
[0259] :: mov s4, s2
[0260] :: exec r260.r_address <- 803425cc40800018c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x18
--------------------
[0269] :: array [0xc008040cc250480, 0xc3, 0x0]
[0272] :: mov s3, &r269.r_address
[0273] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0274] :: add r269.r_address, s3, 0
[0275] :: mov r269.r_address, s2
[0276] :: mov s2, &s4
[0278] :: mov(1) arr[1], s2
[0279] :: mov s2, &flag[13]
[0280] :: mov s4, s2
[0281] :: exec r281.r_address <- 803425cc40800019c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x19
--------------------
[0290] :: array [0xd008040cc250480, 0xc3, 0x0]
[0293] :: mov s3, &r290.r_address
[0294] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0295] :: add r290.r_address, s3, 0
[0296] :: mov r290.r_address, s2
[0297] :: mov s2, &s4
[0299] :: mov(1) arr[1], s2
[0300] :: mov s2, &flag[14]
[0301] :: mov s4, s2
[0302] :: exec r302.r_address <- 803425cc40800024c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x24
--------------------
[0311] :: array [0xe008040cc250480, 0xc3, 0x0]
[0314] :: mov s3, &r311.r_address
[0315] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0316] :: add r311.r_address, s3, 0
[0317] :: mov r311.r_address, s2
[0318] :: mov s2, &s4
[0320] :: mov(1) arr[1], s2
[0321] :: mov s2, &flag[15]
[0322] :: mov s4, s2
[0323] :: exec r323.r_address <- 803425cc4080002cc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x2c
--------------------
[0332] :: array [0xf008040cc250480, 0xc3, 0x0]
[0335] :: mov s3, &r332.r_address
[0336] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0337] :: add r332.r_address, s3, 0
[0338] :: mov r332.r_address, s2
[0339] :: mov s2, &s4
[0341] :: mov(1) arr[1], s2
[0342] :: mov s2, &flag[16]
[0343] :: mov s4, s2
[0344] :: exec r344.r_address <- 803425cc40800026c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x26
--------------------
[0353] :: array [0x10008040cc250480, 0xc3, 0x0]
[0356] :: mov s3, &r353.r_address
[0357] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0358] :: add r353.r_address, s3, 0
[0359] :: mov r353.r_address, s2
[0360] :: mov s2, &s4
[0362] :: mov(1) arr[2], s2
[0363] :: mov s2, &flag[17]
[0364] :: mov s4, s2
[0365] :: exec r365.r_address <- 803425cc4080001ec3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x1e
--------------------
[0374] :: array [0x11008040cc250480, 0xc3, 0x0]
[0377] :: mov s3, &r374.r_address
[0378] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0379] :: add r374.r_address, s3, 0
[0380] :: mov r374.r_address, s2
[0381] :: mov s2, &s4
[0383] :: mov(1) arr[2], s2
[0384] :: mov s2, &flag[18]
[0385] :: mov s4, s2
[0386] :: exec r386.r_address <- 803425cc4080001fc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x1f
--------------------
[0395] :: array [0x12008040cc250480, 0xc3, 0x0]
[0398] :: mov s3, &r395.r_address
[0399] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0400] :: add r395.r_address, s3, 0
[0401] :: mov r395.r_address, s2
[0402] :: mov s2, &s4
[0404] :: mov(1) arr[2], s2
[0405] :: mov s2, &flag[19]
[0406] :: mov s4, s2
[0407] :: exec r407.r_address <- 803425cc40800020c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x20
--------------------
[0416] :: array [0x13008040cc250480, 0xc3, 0x0]
[0419] :: mov s3, &r416.r_address
[0420] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0421] :: add r416.r_address, s3, 0
[0422] :: mov r416.r_address, s2
[0423] :: mov s2, &s4
[0425] :: mov(1) arr[2], s2
[0426] :: mov s2, &flag[20]
[0427] :: mov s4, s2
[0428] :: exec r428.r_address <- 803425cc40800020c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x20
--------------------
[0437] :: array [0x14008040cc250480, 0xc3, 0x0]
[0440] :: mov s3, &r437.r_address
[0441] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0442] :: add r437.r_address, s3, 0
[0443] :: mov r437.r_address, s2
[0444] :: mov s2, &s4
[0446] :: mov(1) arr[2], s2
[0447] :: mov s2, &flag[21]
[0448] :: mov s4, s2
[0449] :: exec r449.r_address <- 803425cc40800021c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x21
--------------------
[0458] :: array [0x15008040cc250480, 0xc3, 0x0]
[0461] :: mov s3, &r458.r_address
[0462] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0463] :: add r458.r_address, s3, 0
[0464] :: mov r458.r_address, s2
[0465] :: mov s2, &s4
[0467] :: mov(1) arr[2], s2
[0468] :: mov s2, &flag[22]
[0469] :: mov s4, s2
[0470] :: exec r470.r_address <- 803425cc40800023c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x23
--------------------
[0479] :: array [0x16008040cc250480, 0xc3, 0x0]
[0482] :: mov s3, &r479.r_address
[0483] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0484] :: add r479.r_address, s3, 0
[0485] :: mov r479.r_address, s2
[0486] :: mov s2, &s4
[0488] :: mov(1) arr[2], s2
[0489] :: mov s2, &flag[23]
[0490] :: mov s4, s2
[0491] :: exec r491.r_address <- 803425cc40800027c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x27
--------------------
[0500] :: array [0x17008040cc250480, 0xc3, 0x0]
[0503] :: mov s3, &r500.r_address
[0504] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0505] :: add r500.r_address, s3, 0
[0506] :: mov r500.r_address, s2
[0507] :: mov s2, &s4
[0509] :: mov(1) arr[2], s2
[0510] :: mov s2, &flag[24]
[0511] :: mov s4, s2
[0512] :: exec r512.r_address <- 803425cc40800024c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x24
--------------------
[0521] :: array [0x18008040cc250480, 0xc3, 0x0]
[0524] :: mov s3, &r521.r_address
[0525] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0526] :: add r521.r_address, s3, 0
[0527] :: mov r521.r_address, s2
[0528] :: mov s2, &s4
[0530] :: mov(1) arr[3], s2
[0531] :: mov s2, &flag[25]
[0532] :: mov s4, s2
[0533] :: exec r533.r_address <- 803425cc40800025c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x25
--------------------
[0542] :: array [0x19008040cc250480, 0xc3, 0x0]
[0545] :: mov s3, &r542.r_address
[0546] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0547] :: add r542.r_address, s3, 0
[0548] :: mov r542.r_address, s2
[0549] :: mov s2, &s4
[0551] :: mov(1) arr[3], s2
[0552] :: mov s2, &flag[26]
[0553] :: mov s4, s2
[0554] :: exec r554.r_address <- 803425cc40800026c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x26
--------------------
[0563] :: array [0x1a008040cc250480, 0xc3, 0x0]
[0566] :: mov s3, &r563.r_address
[0567] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0568] :: add r563.r_address, s3, 0
[0569] :: mov r563.r_address, s2
[0570] :: mov s2, &s4
[0572] :: mov(1) arr[3], s2
[0573] :: mov s2, &flag[27]
[0574] :: mov s4, s2
[0575] :: exec r575.r_address <- 803425cc40800027c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [s4], 0x27
--------------------
[0584] :: array [0x1b008040cc250480, 0xc3, 0x0]
[0587] :: mov s3, &r584.r_address
[0588] :: setinfo s3, name=0x1a, info=0x1, other=0x0, shndx=0x0
[0589] :: add r584.r_address, s3, 0
[0590] :: mov r584.r_address, s2
[0591] :: mov s2, &s4
[0593] :: mov(1) arr[3], s2
[0594] :: mov s4, &0
[0595] :: mov fail(), &0
[0596] :: mov s5, &0
[0597] :: mov s2, &arr[0]
[0599] :: mov s6, s2
[0600] :: exec r600.r_address <- 803425fc40800070c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x70
--------------------
[0609] :: mov s2, &s6
[0611] :: add s5, s5, s2
[0614] :: mov s6, &0
[0615] :: mov s2, &arr[0]
[0616] :: mov s6, s2
[0617] :: exec r617.r_address <- 803425fc4080007cc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x7c
--------------------
[0626] :: mov s2, &s6
[0628] :: add s5, s5, s2
[0631] :: mov s6, &0
[0632] :: mov s2, &arr[0]
[0633] :: mov s6, s2
[0634] :: exec r634.r_address <- 803425fc40800073c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x73
--------------------
[0643] :: mov s2, &s6
[0645] :: add s5, s5, s2
[0648] :: mov s6, &0
[0649] :: mov s2, &arr[0]
[0650] :: mov s6, s2
[0651] :: exec r651.r_address <- 803425fc40800078c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x78
--------------------
[0660] :: mov s2, &s6
[0662] :: add s5, s5, s2
[0665] :: mov s6, &0
[0666] :: mov s2, &arr[0]
[0667] :: mov s6, s2
[0668] :: exec r668.r_address <- 803425fc4080006fc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x6f
--------------------
[0677] :: mov s2, &s6
[0679] :: add s5, s5, s2
[0682] :: mov s6, &0
[0683] :: mov s2, &arr[0]
[0684] :: mov s6, s2
[0685] :: exec r685.r_address <- 803425fc40800027c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x27
--------------------
[0694] :: mov s2, &s6
[0696] :: add s5, s5, s2
[0699] :: mov s6, &0
[0700] :: mov s2, &arr[0]
[0701] :: mov s6, s2
[0702] :: exec r702.r_address <- 803425fc4080002ac3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2a
--------------------
[0711] :: mov s2, &s6
[0713] :: add s5, s5, s2
[0716] :: mov s6, &0
[0717] :: mov s2, &arr[0]
[0718] :: mov s6, s2
[0719] :: exec r719.r_address <- 803425fc4080002cc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2c
--------------------
[0728] :: mov s2, &s6
[0730] :: add s5, s5, s2
[0733] :: mov s6, &0
[0734] :: mov s2, &arr[1]
[0735] :: mov s6, s2
[0736] :: exec r736.r_address <- 803425fc4080007fc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x7f
--------------------
[0745] :: mov s2, &s6
[0747] :: add s5, s5, s2
[0750] :: mov s6, &0
[0751] :: mov s2, &arr[1]
[0752] :: mov s6, s2
[0753] :: exec r753.r_address <- 803425fc40800035c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x35
--------------------
[0762] :: mov s2, &s6
[0764] :: add s5, s5, s2
[0767] :: mov s6, &0
[0768] :: mov s2, &arr[1]
[0769] :: mov s6, s2
[0770] :: exec r770.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2d
--------------------
[0779] :: mov s2, &s6
[0781] :: add s5, s5, s2
[0784] :: mov s6, &0
[0785] :: mov s2, &arr[1]
[0786] :: mov s6, s2
[0787] :: exec r787.r_address <- 803425fc40800032c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x32
--------------------
[0796] :: mov s2, &s6
[0798] :: add s5, s5, s2
[0801] :: mov s6, &0
[0802] :: mov s2, &arr[1]
[0803] :: mov s6, s2
[0804] :: exec r804.r_address <- 803425fc40800037c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x37
--------------------
[0813] :: mov s2, &s6
[0815] :: add s5, s5, s2
[0818] :: mov s6, &0
[0819] :: mov s2, &arr[1]
[0820] :: mov s6, s2
[0821] :: exec r821.r_address <- 803425fc4080003bc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x3b
--------------------
[0830] :: mov s2, &s6
[0832] :: add s5, s5, s2
[0835] :: mov s6, &0
[0836] :: mov s2, &arr[1]
[0837] :: mov s6, s2
[0838] :: exec r838.r_address <- 803425fc40800022c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x22
--------------------
[0847] :: mov s2, &s6
[0849] :: add s5, s5, s2
[0852] :: mov s6, &0
[0853] :: mov s2, &arr[1]
[0854] :: mov s6, s2
[0855] :: exec r855.r_address <- 803425fc40800059c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x59
--------------------
[0864] :: mov s2, &s6
[0866] :: add s5, s5, s2
[0869] :: mov s6, &0
[0870] :: mov s2, &arr[2]
[0871] :: mov s6, s2
[0872] :: exec r872.r_address <- 803425fc40800053c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x53
--------------------
[0881] :: mov s2, &s6
[0883] :: add s5, s5, s2
[0886] :: mov s6, &0
[0887] :: mov s2, &arr[2]
[0888] :: mov s6, s2
[0889] :: exec r889.r_address <- 803425fc4080008ec3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x8e
--------------------
[0898] :: mov s2, &s6
[0900] :: add s5, s5, s2
[0903] :: mov s6, &0
[0904] :: mov s2, &arr[2]
[0905] :: mov s6, s2
[0906] :: exec r906.r_address <- 803425fc4080003dc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x3d
--------------------
[0915] :: mov s2, &s6
[0917] :: add s5, s5, s2
[0920] :: mov s6, &0
[0921] :: mov s2, &arr[2]
[0922] :: mov s6, s2
[0923] :: exec r923.r_address <- 803425fc4080002ac3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2a
--------------------
[0932] :: mov s2, &s6
[0934] :: add s5, s5, s2
[0937] :: mov s6, &0
[0938] :: mov s2, &arr[2]
[0939] :: mov s6, s2
[0940] :: exec r940.r_address <- 803425fc40800059c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x59
--------------------
[0949] :: mov s2, &s6
[0951] :: add s5, s5, s2
[0954] :: mov s6, &0
[0955] :: mov s2, &arr[2]
[0956] :: mov s6, s2
[0957] :: exec r957.r_address <- 803425fc40800027c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x27
--------------------
[0966] :: mov s2, &s6
[0968] :: add s5, s5, s2
[0971] :: mov s6, &0
[0972] :: mov s2, &arr[2]
[0973] :: mov s6, s2
[0974] :: exec r974.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2d
--------------------
[0983] :: mov s2, &s6
[0985] :: add s5, s5, s2
[0988] :: mov s6, &0
[0989] :: mov s2, &arr[2]
[0990] :: mov s6, s2
[0991] :: exec r991.r_address <- 803425fc40800029c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x29
--------------------
[1000] :: mov s2, &s6
[1002] :: add s5, s5, s2
[1005] :: mov s6, &0
[1006] :: mov s2, &arr[3]
[1007] :: mov s6, s2
[1008] :: exec r1008.r_address <- 803425fc40800034c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x34
--------------------
[1017] :: mov s2, &s6
[1019] :: add s5, s5, s2
[1022] :: mov s6, &0
[1023] :: mov s2, &arr[3]
[1024] :: mov s6, s2
[1025] :: exec r1025.r_address <- 803425fc4080002dc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x2d
--------------------
[1034] :: mov s2, &s6
[1036] :: add s5, s5, s2
[1039] :: mov s6, &0
[1040] :: mov s2, &arr[3]
[1041] :: mov s6, s2
[1042] :: exec r1042.r_address <- 803425fc40800061c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x61
--------------------
[1051] :: mov s2, &s6
[1053] :: add s5, s5, s2
[1056] :: mov s6, &0
[1057] :: mov s2, &arr[3]
[1058] :: mov s6, s2
[1059] :: exec r1059.r_address <- 803425fc40800032c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x8040fc], 0x32
--------------------
[1068] :: mov s2, &s6
[1070] :: add s5, s5, s2
[1073] :: mov s6, &0
[1074] :: mov s2, &flag[28]
 s2 = flag[28]
[1075] :: mov s6, s2
 s6 = s2 = flag[28]
[1076] :: mov s2, &flag[29]
 s2 = flag[29]
[1077] :: mov s7, s2
 s7 = s2 = flag[29]
[1078] :: mov s8, &0
 s8 = 0
[1079] :: mov s2, &s8
 s2 = s8 =0
[1080] :: add s8, s8, s2
 s8 = s8 + s2 = 0
[1083] :: mov s2, &s6
 s2 = s6
[1084] :: add s8, s8, s2
 s8 = s8 + s2 = flag[28]
[1087] :: mov s9, &0
 s9 = 0
[1088] :: mov s2, &s9
 s2 = s9 = 0
[1089] :: add s9, s9, s2
 s9 = s9 + s2 = 0
[1092] :: mov s2, &s7
 s2 = s7 = flag[29]
[1093] :: add s9, s9, s2
 s9 = s9 + s2 = flag[29]
[1096] :: mov s2, &s9
 s2 = s9 = flag[29]
[1097] :: add s10, s8, s2
 s10 = s8 + s2 = flag[28] + flag[29]
[1100] :: exec r1100.r_address <- 8034255c4180006cc3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x80415c], 0x6c
--------------------
[1109] :: mov s2, &s10
[1111] :: add s5, s5, s2
[1114] :: mov s6, &0
[1115] :: mov s7, &0
[1116] :: mov s8, &0
[1117] :: mov s9, &0
[1118] :: mov s10, &0
[1119] :: mov s2, &flag[28]
 s2 = flag[28]
[1120] :: mov s6, s2
 s6 = s2 = flag[28]
[1121] :: mov s2, &flag[29]
 s2 = flag[29]
[1122] :: mov s7, s2
 s7 = s2 = flag[29]
[1123] :: mov s8, &0
 s8 = 0
[1124] :: mov s2, &s8
 s2 = s8 =0
[1125] :: add s8, s8, s2
 s8 = s8 + s2 = 0
[1128] :: mov s2, &s6
 s2 = s6
[1129] :: add s8, s8, s2
 s8 = s8 + s2 = flag[28]
[1132] :: mov s2, &s8
 s2 = s8 = flag[28]
[1133] :: add s8, s8, s2
 s8 = s8 + s2 = flag[28] + flag[28]
[1136] :: mov s9, &0
 s9 = 0
[1137] :: mov s2, &s9
 s2 = s9 = 0
[1138] :: add s9, s9, s2
 s9 = s9 + s2 = 0
[1141] :: mov s2, &s7
 s2 = s7 = flag[29]
[1142] :: add s9, s9, s2
 s9 = s9 + s2 = flag[29]
[1145] :: mov s2, &s9
 s2 = s9 = flag[29]
[1146] :: add s10, s8, s2
 s10 = s8 + s2 = 2*flag[28] + flag[29]
[1149] :: exec r1149.r_address <- 8034255c418000a1c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x80415c], 0xa1
--------------------
[1158] :: mov s2, &s10
[1160] :: add s5, s5, s2
[1163] :: mov s6, &0
[1164] :: mov s7, &0
[1165] :: mov s8, &0
[1166] :: mov s9, &0
[1167] :: mov s10, &0
[1168] :: mov s2, &flag[30]
 s2 = flag[30]
[1169] :: mov s6, s2
 s6 = s2 = flag[30]
[1170] :: mov s2, &flag[31]
 s2 = flag[31]
[1171] :: mov s7, s2
 s7 = s2 = flag[31]
[1172] :: mov s8, &0
 s8 = 0
[1173] :: mov s2, &s8
 s2 = s8 = 0
[1174] :: add s8, s8, s2
 s8 = s8 + s2 = 0
[1177] :: mov s2, &s6
 s2 = s6 = flag[30]
[1178] :: add s8, s8, s2
 s8 = s8 + s2 = flag[30]
[1181] :: mov s9, &0
 s9 = 0
[1182] :: mov s2, &s9
 s2 = s9 = 0
[1183] :: add s9, s9, s2 
 s9 = s9 + s2 = 0
[1186] :: mov s2, &s7
 s2 = s7 = flag[31]
[1187] :: add s9, s9, s2
 s9 = s9 + s2 = flag[31]
[1190] :: mov s2, &s9
 s2 = s9 = flag[31]
[1191] :: add s10, s8, s2
 s10 = s8 + s2 = flag[31] + flag[30]
[1194] :: exec r1194.r_address <- 8034255c418000b1c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x80415c], 0xb1
--------------------
[1203] :: mov s2, &s10
[1205] :: add s5, s5, s2
[1208] :: mov s6, &0
[1209] :: mov s7, &0
[1210] :: mov s8, &0
[1211] :: mov s9, &0
[1212] :: mov s10, &0
[1213] :: mov s2, &flag[30]
 s2 = flag[30]
[1214] :: mov s6, s2
 s6 = s2 = flag[30]
[1215] :: mov s2, &flag[31]
 s2 = flag[31]
[1216] :: mov s7, s2
 s7 = s2 = flag[31]
[1217] :: mov s8, &0
 s8 = 0
[1218] :: mov s2, &s8
 s2 = s8 = 0
[1219] :: add s8, s8, s2
 s8 = s8 + s2 = 0 
[1222] :: mov s2, &s6
 s2 = s6 = flag[30]
[1223] :: add s8, s8, s2
 s8 = s8 + s2 = flag[30]
[1226] :: mov s2, &s8
 s2 = s8
[1227] :: add s8, s8, s2
 s8 = s8 + s2 = 2*flag[30] 
[1230] :: mov s9, &0
 s9 = 0
[1231] :: mov s2, &s9
 s2 = s9 = 0 
[1232] :: add s9, s9, s2
 s9 = s9 + s2 = 0
[1235] :: mov s2, &s7
 s2= s7
[1236] :: add s9, s9, s2
 s9= s9 + s2 = flag[31]
[1239] :: mov s2, &s9
 s2 =s9
[1240] :: add s10, s8, s2
 s10 = s8 + s2 = 2*flag[30] + flag[31]
[1243] :: exec r1243.r_address <- 8034255c418000e5c3000000000000000000000000000000
--------------------
    0x0:	xor	byte ptr [0x80415c], 0xe5
--------------------
[1252] :: mov s2, &s10
[1254] :: add s5, s5, s2
[1257] :: mov s6, &0
[1258] :: mov s7, &0
[1259] :: mov s8, &0
[1260] :: mov s9, &0
[1261] :: mov s10, &0
[1262] :: mov s2, &s5
[1264] :: mov(1) fail(), s2

我直接ctrl+c停止的,后面打印的都没有用,当然也可以修改脚本里面的dump函数

195的十六进制是C3,也就是汇编指令的ret

所以怀疑这一段常数都是机器码,转成十六进制看看

1585408084625667200转成16进制1600 8040 CC25 3480,小端序转一下803425CC40800016

和这条比较像,27对应的是xor 0x27,那么16应该对应的是xor 16

141015791240320转成十六进制800425CC4080

最后总结一下前面的机器码的功能

xor      byte ptr [s4], 0x16
add      byte ptr [s4],0
xor      byte ptr [s4], 0x17
add      byte ptr [s4],1
xor      byte ptr [s4], 0x10
add      byte ptr [s4],2
xor	     byte ptr [s4], 0x12
add      byte ptr [s4],3

伪代码大致可以分为三部分:第一部分对输入前28个字节进行异或和加常数;第二部分异或固定值来进行比较;第三部分可以通过题目提示进行hash爆破

keystream=[0x16,0x17,0x10,0x12,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x24,0x2c,0x26,0x1e,0x1f,0x20,0x20,0x21,0x23,0x27,0x24,0x25,0x26,0x27]
enc=[0x70,0x7c,0x73,0x78,0x6f,0x27,0x2a,0x2c,0x7f,0x35,0x2d,0x32,0x37,0x3b,0x22,0x59,0x53,0x8e,0x3d,0x2a,0x59,0x27,0x2d,0x29,0x34,0x2d,0x61,0x32]
print(len(keystream))
print(len(enc))
t=[0]*28
for i in range(len(keystream)):
   t[i]=(enc[i]-i)^keystream[i]
for i in range(len(t)):
    print(chr(t[i]),end="")

得到flag{366c950370fec47e34581a0,然后爆破hash

import hashlib

xor=[0x16,0x17,0x10,0x12,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x24,0x2c,0x26,0x1e,0x1f,0x20,0x20,0x21,0x23,0x27,0x24,0x25,0x26,0x27]
print(len(xor))
encflag=[0x70,0x7c,0x73,0x78,0x6f,0x27,0x2a,0x2c,0x7f,0x35,0x2d,0x32,0x37,0x3b,0x22,0x59,0x53,0x8e,0x3d,0x2a,0x59,0x27,0x2d,0x29,0x34,0x2d,0x61,0x32]
print(len(encflag))

for i in range(len(encflag)):
    print(chr((encflag[i]-i)^xor[i]),end="")

print("\n")

s = "flag{366c950370fec47e34581a0"
l = "1234567890abcdef"
for a in l:
    for b in l:
        for c in l:
            flag = s+a+b+c+"}"
            sha = hashlib.sha256(flag.encode("utf-8")).hexdigest()
            if sha[0:16] == "f860464d767610bb":
                print(flag)
                break

当然我们也可以分析flag最后一部分,详细解析都在上面的伪代码里

其实就是一个方程组求解,可以用z3

from z3 import *
s = Solver()
flag_end = [BitVec('f%d'%i,8) for i in range(4)]
s.add(flag_end[0] + flag_end[1] == 0x6c)
s.add(2*flag_end[0] + flag_end[1] == 0xa1)
s.add(flag_end[2] + flag_end[3] == 0xb1)
s.add(2*flag_end[2] + flag_end[3] == 0xe5)
if s.check() == sat:
   print(s.model())

t=[53,55,52,125]
for i in t:
    print(chr(i),end="")

easyre

Easyre

这个文件是没有符号的,我们可以利用插件finger去恢复一下

安装教程:https://www.anquanke.com/post/id/256461

跑了一段时间可以恢复大部分的函数

首先分析一下sub_402150

这里是释放一个elf文件,名字为re3,我们可以自己dump,可以动调然后提取文件,elf的长度存放在dword_4C2070中

在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

父进程执行sub_401F2F后就删除了释放的文件,而子进程会执行sub_44CC50和sub_44B680操作

sub_401F2F

有些函数一开始识别不出来,需要进去进行分析底层调用,上图为修改完的效果

关于ptrace的一些介绍https://bbs.pediy.com/thread-265924.htm#msg_header_h2_1

这里使用ptrace函数实现父进程与子进程之间的通信

long ptrace(enum _ptrace_request request,pid_t pid,void * addr ,void *data);

ptrace最重要的就是第一个参数

sub_4017E5

这里只是把a39872382055541数据提取出来由字符串转为数字,然后存放到v6数组里

一共有39条数据,sub_401F2F的v8指向这个数组

有些数据直接静态分析不好分析,我们还是利用动调比较方便

sub_401F2F的主要操作就是先把某组数据转成数字存放在数组里,然后复制子进程的寄存器到父进程,还有就是一些数据,通过读取的数据比对0xCAFEB055BFCC和0xCAFE1055BFC走不同的条件语句,我们先分析一下子进程附件。

re3

子进程一进来有很多无法识别的数据,我以为这一块被SMC了,结果ida按c后可以正常识别,再p创建函数,成功F5

sub_2490

这个函数是对输入的一些判断

一个25*25的数组,判断输入是否是0或1的ASCII,然后成立后减48转成0或1的数字,再存入byte_55C0

loc_21F9

这也是个函数,但是有加密,无法直接识别为指令,参数有sub_2490操作后的数组,还有v9和v8

突然发现这一块的数字似曾相识,好像在哪见过!原来是easyre附件的if判断那一块出现过

这里通过int 3断点向父进程发生通知,这个时候父进程就会进入条件语句执行sub_401BB1了

函数末尾还有个int 3

这个数据对应的是父进程if语句中的else部分,此时我的大脑中的想法就是:

1、父进程创建子进程,父进程处于wait状态
2、子进程得到输入,遇到int 3 ,向父进程发送通知
3、父进程接收到通知,执行SMC
4、SMC结束后,子进程再次遇到int 3,向父进程发送通知
5、父进程结束SMC,执行else部分

SMC

现在我们只要知道SMC的加密过程,就可以写脚本解密,或者直接动调解密

smc在父进程中,我们分析一下加密逻辑

首先分析一下sub_401AC2函数,发现是把re3里面的SMC数据部分取到easyre中

动调完发现SMC的逻辑就是把re3的数据xor 上面分析的a39872382055541MD5后的结果

我们可以先尝试把所有的MD5都提取出来,先在转完16进制函数后下个断点,然后编辑断点

已经提取到数据了,接下来就是手工patch子进程

xorKey = {8723: 2533025110152939745, 8739: 5590097037203163468, 8755: 17414346542877855401, 8771: 17520503086133755340, 8787: 12492599841064285544, 8803: 12384833368350302160, 8819: 11956541642520230699, 8835: 12628929057681570616, 8851: 910654967627959011, 8867: 5684234031469876551, 8883: 6000358478182005051, 8899: 3341586462889168127, 8915: 11094889238442167020, 8931: 17237527861538956365, 8947: 17178915143649401084, 8963: 11176844209899222046, 8979: 18079493192679046363, 8995: 7090159446630928781, 9011: 863094436381699168, 9027: 6906972144372600884, 9043: 16780793948225765908, 9059: 7086655467811962655, 9075: 13977154540038163446, 9091: 7066662532691991888, 9107: 15157921356638311270, 9123: 12585839823593393444, 9139: 1360651393631625694, 9155: 2139328426318955142, 9171: 2478274715212481947, 9187: 12876028885252459748, 9203: 18132176846268847269, 9219: 17242441603067001509, 9235: 8492111998925944081, 9251: 14679986489201789069, 9267: 13188777131396593592, 9283: 5298970373130621883, 9299: 525902164359904478, 9315: 2117701741234018776, 9331: 9158760851580517972}

addr = 0x2213

while True:
    data = get_qword(addr)
    key = xorKey[addr]
    dec = data ^ key
    idc.patch_qword(addr, dec)
    addr += 16

修复完有些地方需要我们nop掉,才能正常F5,同时把最后的int 3 也nop了,因为我们用不到了

这是一个数织游戏,我们只要找到对应的数据,通过网站就可以跑

我们的比较应该是一个25*25的矩阵

这里对矩阵做了一些操作,直接dump就行了

row
5  1  3  2  1  1
1  1  1  1  1  1  1  1
3  1  3  1  4  1 1
1  1  1  2  1  1  1  1
1  4  1  3  2  1 3

4  4  4  1  1  1
1 2 2 1 2 1 2 1
1 1 1 1 3 4 3 1
1 1 1 1 1 1 1 1 1 1
3 1 3 1 4 1 1
2
1 1 4 1 1 4
8 1 1 1 1 2 1
1 1 1 1 1 1 1 4
2 2 1 2 1 1 1 1 1 1
2 5 1 1 3

12 2 1 1 1 1
2 1 1 1 1 1 1 1 1
4 7 2 1 1 1 1
1 1 2 1 1 1 1 1 1
12 2
1 1 1 1
4 2 1 1
col
5 5 3 1 3
1 1 1 1 1 1 1 1 1 1
1 1 5 1 3 1 1
1 2 4 5 1
5 2 1 1 1 1 1 
1 1 1 1 5
1 2 6 1 3
2 2 1 1 1 1 1
2 5 1 3 1 1
1 1 1 1 1 1 1 3 1
2 1 1 1 1 1 1
2 5 3 1
3 5 1 1 1
1 1 1 1 1 1 1 1
1 1 1 3 5 5
1 3 5 1 1 1
1 1 3
5 1 2 4 1
1 1 4 3
1 1 2 4 1
5 4 3
2 5 4 1
5 3 1 1 1
1 2 1 1 1 4 1
1 1 1

最后的效果FLAG{I LOVE PLAY ctf_QWB2022}

find_basic

首先运行看看

特殊字符串:basic secret,等会去IDA看看

搜到了,但是无法交叉引用到主函数逻辑,观察代码发现这题使用了类似虚拟保护的switch混淆执行逻辑分析

每个handler自己又作为分发器

结构都比较类似,handler的结构体为

.text:5661743E                 cmp     dl, 0E0h             判断控制码
.text:56617441                 jnz     short sub_5661745C   跳转到下一个handler或者分发器
.text:56617443                 popa						 	弹出通用寄存器
.text:56617444                 popf							弹出标志寄存器
.text:56617445                 push    0               ; buf
.text:56617447                 push    eax             ; stream
.text:56617448                 call    j__setvbuf			该handler实际执行的指令
.text:5661744D                 jmp     short loc_56617454   跳转到下一个handler或者分发器

现在开始调试

我们逐个函数分析,首先把cl赋值0X3F,然后进入函数sub_5658D4FA

进去继续分析sub_5658D7D6和sub_5658D782

off_5661506C的值自增1就没了

这个函数就是获取一个rand值,然后v3判断是否大于随机数,貌似只是一段垃圾代码,交叉引用发现这个函数被调用多次,我改个名字randfunc,方便之后分析的识别

这里把上层的ecd,也就是0x3F传进来就行比较,一直单步调试,走到0x3F的判断语句

好像并没有执行什么东西,然后继续走就到了这

sub_5658D360没啥用,也是一个rand函数

下面一个函数有点变化,貌似和sub_5658D7D6对应,这里是-1

当我单步步过sub_5658D360,会发生报错,怀疑是死循环,建议patch掉循环,然后就又回到了main了

到这我怀疑每一次的比较都类似opcode和function的对应,也就是之前说的加了switch混淆的vm,下面的opcode也是类似的分析方法

这里执行完会打印——–obf_xx_find v1.0———

这就是对应的打印basic secret:

0E对应的是scanf,此时程序卡住,等待我们输入,同时可以得知eax是存flag的地址

现在我可以在flag上下断点,看谁访问了他

cl为3A的时候触发了flag,把flag[0]取出来乘上42B45h

这里把我们的flag[0]*0x42B45然后减去0x1A93D7E,类似汇编里面cmp的功能,我们通过这个等式反求一下flag[0],0x1A93D7E/0x42B45=0x66,也就是f的ASCII码。

同理我们再给flag[1]也下上断点,并把数据记录下来

这里发现又是flag[0]*0x1E4E0,然后又加上了edx,而edx是flag[1]*0x3B10F

减去0x24FE394,整理第二轮就是flag[1]*0x3B10F+flag[0]*0x1E4E0==0x24FE394,验证一下flag[1]为0x6c,确实是l的ASCII码

下面就慢慢调就行了,流程太多就不贴出来了,原理一样

也可以用trace,具体教程可以参考这位师傅https://www.bilibili.com/video/BV1Wt4y137qG?spm_id_from=333.337.search-card.all.click&vd_source=b9e4755863227a308257fcc956a9e9e7

from z3 import *
flag = [BitVec('flag[%d]' % i, 8) for i in range(0x1c)]
solver = Solver()
for i in range(0x1c):
 solver.add(flag[i] >= 32)
 solver.add(flag[i] <= 127)
solver.add(flag[0] == ord('f'))
solver.add(flag[1] == ord('l'))
solver.add(flag[2] == ord('a'))
solver.add(flag[3] == ord('g'))
solver.add(flag[4] == ord('{'))
solver.add(flag[-1] == ord('}'))
solver.add(flag[0] * 0x42b45 - 0x1a93d7e == 0)
solver.add(flag[1] * 0x3b10f + flag[0] * 0x1e4e0 - 0x24fe394 == 0)
solver.add(flag[0] * 0x31fc4 + flag[1] * 0xfffdb038 + flag[2] * 0x1390f - 0xbb9e67 == 0)
solver.add(flag[0] * 0x32494 + flag[3] * 0xfffe5a07 + flag[1] * 0xa4e6 + flag[2] * 0x6ba7 - 0x1052718 == 0)
solver.add(flag[1] * 0xfffe0c3f + flag[2] * 0x43e32 + flag[0] * 0x3f49d + flag[3] * 0xc094 + flag[4] * 0xfffb7eff - 0x7fb225 == 0)
solver.add(flag[5] * 0x33e5b + flag[1] * 0x157f8 + flag[4] * 0xd4eb + flag[2] * 0xfffc9ad6 + flag[3] * 0x9c95 + flag[0] * 0xfffd8c2e - 0x6a31d == 0)
solver.add(flag[6] * 0x6d8c + flag[4] * 0xfffedd66 + flag[5] * 0x46fd4 + flag[1] * 0xfffc79bb + flag[3] * 0xfffbe7f5 + flag[2] * 0x14cde + flag[0] * 0xfffc4acd + 0x3083b63 == 0)
solver.add(flag[4] * 0x129fd + flag[7] * 0x2a3cd + flag[5] * 0x52a1 + flag[6] * 0x87de + flag[3] * 0x357c1 + flag[0] * 0xfffbe625 + flag[1] * 0xfffec17b + flag[2] * 0x8039 - 0xd3b6ed == 0)
solver.add(flag[4] * 0xfffe590f + flag[6] * 0xfffc6bb7 + flag[0] * 0x2aec8 + flag[7] * 0xfffd58b1 + flag[3]* 0xfffcf131 + flag[8] * 0xfffc0fae + flag[1] * 0xfffcf46a + flag[2] * 0xfffbbb98 + flag[5] * 0xfffc9913 + 0x7a4d9d3 == 0)
solver.add(flag[6] * 0x3cb6 + flag[5] * 0xfffc5201 + flag[9] * 0xfffdec99 + flag[8] * 0x195a8 + flag[4] * 0xfffbcea6 + flag[7] * 0xfffd4f63 + flag[0] * 0x3852e + flag[3] * 0x36c09 + flag[2] * 0xfffdffc6 + flag[1] * 0xffffbb8f + 0x27b7033 == 0)
solver.add(flag[8] * 0xfffb7a1c + flag[10] * 0xffff35fe + flag[4] * 0xfffe5693 + flag[3] * 0xfffdb9f4 + flag[5] * 0xbd38 + flag[1] * 0x25b89 + flag[2] * 0x3074d + flag[7] * 0xfffe5f6f + flag[9] * 0x1400e + flag[0] *0xfffcd14c + flag[6] * 0x4036d + 0xa8256 == 0)
solver.add(flag[7] * 0x2da7a + flag[2] * 0xfffbfd56 + flag[9] * 0xffff0011 + flag[0] * 0xfffce077 + flag[3]* 0x34d5d + flag[5] * 0xfffb8def + flag[10] * 0xffff2d4e + flag[4] * 0x237a3 + flag[1] * 0x386e1 + flag[6] *0xfb89 + flag[8] * 0x2e485 + flag[11] * 0x42574 - 0x24df62a == 0)
solver.add(flag[10] * 0x21c5e + flag[1] * 0x32144 + flag[11] * 0x420e3 + flag[3] * 0x3f6d0 + flag[0] * 0x1a459 + flag[2] * 0xfffc900e + flag[8] * 0x3fd03 + flag[7] * 0x43d16 + flag[5] * 0xfffe4105 + flag[6] * 0xfffd400a + flag[9] * 0xffffc29b + flag[4] * 0x2f9f0 + flag[12] * 0x19432 - 0x6f9b293 == 0)
solver.add(flag[1] * 0xfffca694 + flag[0] * 0xfffce151 + flag[9] * 0x30418 + flag[11] * 0x2f6aa + flag[4] *0x1b619 + flag[8] * 0x22e4 + flag[7] * 0xfffe1384 + flag[10] * 0xffffa664 + flag[3] * 0x13e07 + flag[2] * 0xfffc46de + flag[5] * 0x79d6 + flag[12] * 0x4372b + flag[13] * 0x3d1d + flag[6] * 0x4d41 - 0x176513c == 0)
solver.add(flag[7] * 0x29b04 + flag[3] * 0xfffd2684 + flag[2] * 0xfffd9a2f + flag[10] * 0xfffd79fc + flag[13] * 0x2594e + flag[12] * 0x41c45 + flag[6] * 0xfffc9c57 + flag[5] * 0xfffc5f95 + flag[11] * 0xfffec65c + flag[14] * 0xffffb642 + flag[1] * 0xfffcb527 + flag[0] * 0x2792e + flag[4] * 0xfffe1bb7 + flag[8] * 0x445a1 + flag[9] * 0xfffd25cc + 0x5338cd6 == 0)
solver.add(flag[14] * 0xfffd399c + flag[3] * 0xffff3edb + flag[11] * 0x26b94 + flag[13] * 0xfffcee81 + flag[4] * 0xfffefe93 + flag[5] * 0xfffcdfa4 + flag[6] * 0xfffe2a42 + flag[0] * 0x10ba4 + flag[10] * 0x38e1d + flag[12] * 0x14c1e + flag[7] * 0xffffce4a + flag[8] * 0xfffd2a4b + flag[9] * 0x41fc + flag[1] * 0xfffedbac + flag[2] * 0xfffeab6a + flag[15] * 0xfffe4e59 + 0x299ff72 == 0)
solver.add(flag[14] * 0xfffdc67b + flag[1] * 0xffffb1fc + flag[12] * 0xffff59be + flag[8] * 0x3684 + flag[5]* 0x202c2 + flag[10] * 0x2e43 + flag[6] * 0xffff3a46 + flag[7] * 0x6a23 + flag[2] * 0xebfb + flag[0] * 0xfffbb78a + flag[15] * 0xd44a + flag[13] * 0x385eb + flag[11] * 0xfffee046 + flag[9] * 0xfffeb282 + flag[4] * 0xfffde639 + flag[3] * 0xfffd6738 + flag[16] * 0xffff1aa3 + 0x4728350 == 0)
solver.add(flag[1] * 0x28c9c + flag[4] * 0xfffdc4ae + flag[3] * 0x278ad + flag[17] * 0x326ca + flag[7] * 0xfffd423d + flag[15] * 0xfffc96fc + flag[10] * 0xfffeeb1a + flag[9] * 0xfffc2ee0 + flag[5] * 0x106be + flag[6]* 0xffff5d67 + flag[8] * 0x27 + flag[11] * 0xfffbc3b6 + flag[12] * 0xfffd163c + flag[13] * 0xfffb9b47 + flag[2] * 0x1e6ed + flag[0] * 0xfffc6c6f + flag[16] * 0x3b32b + flag[14] * 0x2feea + 0x48d1119 == 0)
solver.add(flag[3] * 0xfffc2bb3 + flag[0] * 0xfffce76f + flag[4] * 0xfffca692 + flag[1] * 0xfffdf4bc + flag[14] * 0x192f9 + flag[17] * 0xfffe5a1e + flag[15] * 0xfffed4f3 + flag[7] * 0xffff94f8 + flag[6] * 0xfffc717e+ flag[9] * 0xfffed29b + flag[10] * 0xfffd28d9 + flag[8] * 0x218df + flag[2] * 0x28e00 + flag[12] * 0xfffdd0af + flag[13] * 0x25d22 + flag[11] * 0x42ebb + flag[5] * 0xffff1382 + flag[18] * 0x7404 + flag[16] * 0xfffe2dff + 0x60245a5 == 0)
solver.add(flag[5] * 0x21061 + flag[0] * 0xfffbcb01 + flag[19] * 0xffff7442 + flag[3] * 0x24568 + flag[6] *0x1b201 + flag[13] * 0x2d232 + flag[14] * 0x13777 + flag[7] * 0xfffee013 + flag[8] * 0xfffc7505 + flag[2] *0x264ed + flag[1] * 0x33b4f + flag[11] * 0x286d8 + flag[17] * 0x33e8b + flag[12] * 0x21529 + flag[16] * 0xfffb7c1a + flag[18] * 0xfffd07a3 + flag[10] * 0xffff8453 + flag[4] * 0x9754 + flag[9] * 0xfffd603d + flag[15]* 0xfffdd85b - 0x254e142 == 0)
solver.add(flag[0] * 0xfffe206e + flag[12] * 0x2f048 + flag[8] * 0xfffc19fa + flag[4] << 6 + flag[7] * 0x370d + flag[13] * 0xfffd9c2f + flag[6] * 0xfffdb413 + flag[20] * 0x30e0a + flag[18] * 0xfffe07f8 + flag[9] * 0xfffedfd5 + flag[10] * 0xfffee6f6 + flag[3] * 0x46247 + flag[1] * 0x2b8ed + flag[16] * 0x2d291 + flag[5] * 0xfffdc54d + flag[15] * 0xfffc5b55 + flag[14] * 0xfffb8061 + flag[11] * 0x43913 + flag[2] * 0xffffe191 + flag[17] * 0xfffd276e + flag[19] * 0xfffe5841 + 0xce53e7 == 0)
solver.add(flag[20] * 0xfffed971 + flag[21] * 0x46741 + flag[18] * 0xfffbac8c + flag[1] * 0xfffeb4e7 + flag[13] * 0x1026b + flag[12] * 0xfffe7d86 + flag[6] * 0xfffd5fec + flag[3] * 0x48ddb + flag[16] * 0xfffc6bc1 + flag[17] * 0x37ece + flag[8] * 0x41105 + flag[2] * 0xfffe6667 + flag[19] * 0xfffe75b2 + flag[4] * 0x61b0 + flag[14] * 0xffffd602 + flag[11] * 0xfffbce29 + flag[0] * 0xffff07d7 + flag[5] * 0x34c8e + flag[15] * 0x32996+ flag[10] * 0x49530 + flag[7] * 0x33822 + flag[9] * 0xfffce161 + 0x42666b == 0)
solver.add(flag[8] * 0xfffe06e8 + flag[12] * 0xfffd0441 + flag[2] * 0x16357 + flag[3] * 0x1d95f + flag[22] *0xffff89d3 + flag[1] * 0xfffba022 + flag[16] * 0x46180 + flag[4] * 0xffff4240 + flag[5] * 0x199c5 + flag[21] * 0xffff442c + flag[17] * 0xfffc2fac + flag[10] * 0x32600 + flag[19] * 0x1d03a + flag[9] * 0x19435 + flag[15] * 0xfffd1667 + flag[18] * 0x35d1d + flag[0] * 0x96c4 + flag[11] * 0x2fa24 + flag[7] * 0xb20c + flag[6] *0xebee + flag[20] * 0x428a6 + flag[14] * 0xfffceb8a + flag[13] * 0x22784 - 0x3604a63 == 0)
solver.add(flag[0] * 0x1e3e2 + flag[9] * 0x1cfb9 + flag[6] * 0xc3f7 + flag[10] * 0x94cd + flag[22] * 0xfffc7fd0 + flag[2] * 0x21165 + flag[23] * 0xfffcfb41 + flag[14] * 0xffff819d + flag[5] * 0xfffbeb76 + flag[1] * 0x16751 + flag[19] * 0xe1a + flag[17] * 0x238a0 + flag[12] * 0x28f99 + flag[8] * 0x45bc + flag[20] * 0xffffcb18 + flag[15] * 0x32d58 + flag[11] * 0xffffe4bc + flag[16] * 0xfffeea95 + flag[13] * 0x44f3a + flag[18] * 0xb047 + flag[7] * 0xfffcfc36 + flag[21] * 0x1719 + flag[4] * 0x1b011 + flag[3] * 0xfffea265 - 0x2918269 == 0)
solver.add(flag[15] * 0xfffbf307 + flag[8] * 0xffff2847 + flag[6] * 0xfffcfd31 + flag[2] * 0x40f96 + flag[22] * 0x2b265 + flag[5] * 0xfffc7802 + flag[3] * 0x1b103 + flag[4] * 0x42452 + flag[14] * 0x3c5d + flag[1] * 0x15b55 + flag[9] * 0xfffeb722 + flag[13] * 0x1d9a9 + flag[23] * 0x28df + flag[12] * 0xfffc89eb + flag[10] *0xfffe1221 + flag[7] * 0x4462a + flag[19] * 0x23353 + flag[21] * 0x3c514 + flag[0] * 0x316a4 + flag[11] * 0x176e1 + flag[20] * 0xcf0e + flag[18] * 0x46b55 + flag[24] * 0xffffbcc1 + flag[17] * 0xf2a7 + flag[16] * 0x1d33c - 0x5df35b6 == 0)
solver.add(flag[3] * 0xfffbf624 + flag[22] * 0xfffec87a + flag[2] * 0x19aaa + flag[23] * 0x5f14 + flag[20] *0xfffcfc43 + flag[16] * 0xfffbe879 + flag[15] * 0xfffdfc92 + flag[14] * 0xffffc258 + flag[0] * 0xfffd02fd + flag[5] * 0x12560 + flag[13] * 0xae46 + flag[7] * 0xfffeb6f5 + flag[12] * 0x30c11 + flag[17] * 0xfffcb4ae + flag[24] * 0x2a00a + flag[6] * 0xfffc76de + flag[21] * 0x4162 + flag[10] * 0xfffe95b2 + flag[25] * 0xfffe60e7 + flag[19] * 0xffff908d + flag[4] * 0xfffb7f42 + flag[11] * 0x1c31 + flag[1] * 0xffff900c + flag[8] * 0x2ad6e + flag[9] * 0xfffd7c6d + flag[18] * 0xc499 + 0x83646cd == 0)
solver.add(flag[12] * 0x26b02 + flag[3] * 0xfffb92e5 + flag[17] * 0x30dd1 + flag[18] * 0xfffe4c7b + flag[0]* 0xffff0433 + flag[1] * 0x276b1 + flag[9] * 0xfffc241e + flag[5] * 0xfffe3fdc + flag[8] * 0xfffee787 + flag[10] * 0x230c + flag[21] * 0xfffd53f8 + flag[4] * 0xfffc108c + flag[14] * 0xffffbac1 + flag[26] * 0xffff0bdb+ flag[15] * 0xfffbc5e2 + flag[19] * 0xa1f6 + flag[16] * 0x1e758 + flag[22] * 0x1725f + flag[23] * 0x3387e+ flag[20] * 0x87b + flag[2] * 0xfffd8475 + flag[13] * 0x3776a + flag[24] * 0xffff4515 + flag[11] * 0x1a454+ flag[6] * 0xfffbf3a1 + flag[25] * 0x25174 + flag[7] * 0xfffbccc2 + 0x52dfb3f == 0)
solver.add(flag[25] * 0x2f139 + flag[20] * 0x21b53 + flag[15] * 0x2ad74 + flag[9] * 0xfffba19b + flag[16] *0x1ac4e + flag[27] * 0x2208e + flag[13] * 0xfffdd738 + flag[11] * 0xfffdfb9f + flag[8] * 0xfffe4b65 + flag[5] * 0x10937 + flag[10] * 0xfffbfdf3 + flag[12] * 0x3cc1a + flag[23] * 0xfffe93ee + flag[2] * 0xfffe3b8a + flag[14] * 0xfffe792c + flag[6] * 0x3e9ff + flag[21] * 0x128e6 + flag[3] * 0x574b + flag[24] * 0x16707 + flag[19] * 0x3fe4c + flag[17] * 0xfffed658 + flag[7] * 0x3cc8c + flag[22] * 0x458b4 + flag[1] * 0xfffd74d0 + flag[18] * 0x22e02 + flag[4] * 0xffff098d + flag[0] * 0x30b99 + flag[26] * 0xfffba5e9 - 0x38186f4 == 0)
flag_str = ''
if solver.check() == sat:
 m = solver.model()
 for i in range(0x1c):
    flag_str += chr(m[flag[i]].as_long())

print(flag_str)

后来看Chamd5的大哥直接写了一个去混淆的脚本,等有空再看看了。

总结

强网杯先复现到这里,还有三道题还没复现,看做出来的人不是很多,应该有些难度,等后面有时间再搞了,最近有点忙。这四道题复现下来给我的收获挺多的,学会了一些插件的使用还有就是做题上面的思路的改变,混淆在ctf逆向中也越来越多了,得弄个专题专门学习一下混淆。不得不说,强网杯的体验还是可以的,虽然只写出来两题。今年比去年好一点,去年只有110多名,今年39名,差一点就进总决赛了,明年加油。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 767778848@qq.com