• 周五. 3月 29th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

魔改 Rizzo 恢复二进制符号

admin

11月 28, 2021

简介

由于其他几种恢复符号的方法不是特别可靠,所以就有了这个魔改 Rizzo 的项目

STL 模板中大部分函数的实现和具体的实例化类型无关,只要编译选项相同即可正常匹配

在编译选项对应的前提下,用这个 Rizzo 脚本匹配的成功率大于 95%

其他方案的缺点

  • BinaryAI:要求有网络环境,上传样本数据后需要额外等待一段时间,服务端上完成训练后才能正常匹配,而且匹配成功率不高
  • BinDiff:无法正常分析部分程序,分析过程中可能会报错退出
  • Lumina:可以本地搭建 Lumina 服务器,但是匹配成功率过低

改进功能

  1. 针对 STL 模板函数的匹配进行优化
  2. 不丢弃重复的函数签名
    1. 对于重复的签名按容器优先级匹配函数名称
    2. 默认优先级为 ['vector','map','set','queue','deque','list','array','stack']
  3. 签名按模糊程度分成三个等级,按优先级进行匹配
    1. Formal:对所有助记符,所有操作数进行签名
    2. Fuzzy:对所有助记符,部分操作数进行签名
      1. 忽略可能与实例化类型的空间大小有关的操作数
      2. 以下指令的操作数可能与实例化类型的空间大小有关 ['shr','shl','sar','sal','lea','add','sub']
    3. Slim:对所有助记符进行签名,忽略所有操作数
  4. 以函数为单位进行签名,而不是以基本块为单位进行签名
  5. 可能会出现匹配错误的情况,可以根据上下文进行判断
  6. 函数指令数越多,结构越复杂,匹配的可信度越高

编译选项

  • Ox
    • -O0:做一些不显著增加编译时间的优化
    • -O1:显著提升编译时间,提升代码性能
    • -O2:进一步优化,显著增加可执行文件大小,做不包含 space-speed tradeoff 的所有优化
    • -O3:优化性能同时不增加可执行文件大小,包含 O2 选项中不增加代码大小的优化项
    • -Os:优化性能同时不增加可执行文件大小,包含 O2 选项中不增加代码大小的优化项
    • -Og:优化性能同时不损害可调试性,包含 O1 选项中不损害可调试性的优化项
  • -mno-sse:禁用 SSE 指令集
  • -static:静态链接
  • -shared:编译动态库
  • -fPIC:生成位置无关代码
  • -fvisibility=hidden:编译动态库时不导出 extern 变量,寻址时不需要查找 GOT 表
  • -nostartfiles:不包含入口点 main 函数

配置样例

下面以编译 Capstone 为例,由于项目自带的 Cmake 配置文件会引入一些额外的编译选项,不方便控制,所以这里自己配置 gcc 选项

  • 宏定义:-DCAPSTONE_HAS_X86 -DCAPSTONE_DIET
  • 优化选项:-Os
  • 输入:./arch/X86/*.c ./*.c
  • 输出:-o ./libcapstone.so

然后加上 -shared -fPIC -fvisibility=hidden 编译动态库

gcc ./arch/X86/*.c ./*.c -o ./libcapstone.so -DCAPSTONE_HAS_X86 -DCAPSTONE_DIET -I./include -Os -shared -fPIC -fvisibility=hidden

或者加上 -nostartfiles 编译可执行文件

gcc ./arch/X86/*.c ./*.c -o ./libcapstone.so -DCAPSTONE_HAS_X86 -DCAPSTONE_DIET -I./include -Os -nostartfiles

两者编译的指令序列大部分情况下是完全一样的,可能极少数的函数会有细微差别

PS:前者编译的结果和正常静态链接编译的结果完全一样,后者编译的结果和正常静态链接编译的结果有一些细微差别

rizzo.py

from __future__ import print_function
import idc
import idaapi
import idautils

import os
import time
import pickle
import collections
import hashlib

import ida_shims


class RizzoSignatures(object):

    def __init__(self):
        self.slim = {}
        self.fuzzy = {}
        self.formal = {}
        self.functions = {}


class RizzoFunctionDescriptor(object):

    def __init__(self, signatures, functions, key):
        self.ea = signatures[key]
        self.name = None

        for key in ['vector','map','set','queue','deque','list','array','stack']:
            for ea in self.ea:
                if key in functions[ea][0] and self.name == None:
                    self.name = functions[ea][0]
                    break
        
        if self.name == None:
            self.name = functions[self.ea[0]][0]
        self.blocks = functions[self.ea[0]][1]


class Rizzo(object):

    DEFAULT_SIGNATURE_FILE = "rizzo.sig"

    def __init__(self, sigfile=None):
        if sigfile:
            self.sigfile = sigfile
        else:
            self.sigfile = self.DEFAULT_SIGNATURE_FILE

        start = time.time()
        self.signatures = self.generate()
        end = time.time()

        print("Generated %d formal signatures for %d " 
              "functions in %.2f seconds." % (len(self.signatures.formal),
                                              len(self.signatures.functions),
                                              (end-start)))

    def save(self):
        print(("Saving signatures to %s..." % self.sigfile), end=' ')
        fp = open(self.sigfile, "wb")
        pickle.dump(self.signatures, fp)
        fp.close()
        print("done.")

    def load(self):
        print(("Loading signatures from %s..." % self.sigfile), end=' ')
        fp = open(self.sigfile, "rb")
        sigs = pickle.load(fp)
        fp.close()
        print("done.")
        return sigs

    def sighash(self, value):
        h = hashlib.md5()
        h.update(value.encode("utf-8"))
        hash_value = h.hexdigest()
        del(h)
        return hash_value

    def block(self, block):
        formal = []
        fuzzy = []
        slim = []

        ea = ida_shims.start_ea(block)
        while ea < ida_shims.end_ea(block):
            insn = ida_shims.decode_insn(ea)

            drefs = [x for x in idautils.DataRefsFrom(ea)]
            crefs = [x for x in idautils.CodeRefsFrom(ea, False)]

            mnem = ida_shims.print_insn_mnem(ea)
            formal.append(mnem)
            fuzzy.append(mnem)
            slim.append(mnem)

            if crefs:
                for cref in crefs:
                    formal.append("coderef")
                    fuzzy.append("coderef")
                    slim.append("coderef")
           
            elif drefs:
                for dref in drefs:
                    formal.append("dataref")
                    fuzzy.append("dataref")
                    slim.append("dataref")
           
            elif not drefs and not crefs:
                ops = ida_shims.get_operands(insn)
                for n in range(0, len(ops)):
                    opnd_text = ida_shims.print_operand(ea, n)
                    formal.append(opnd_text)
                    if mnem not in ['shr','shl','sar','sal','lea','add','sub']:
                        fuzzy.append(opnd_text)

            ea = ida_shims.next_head(ea)

        print(''.join(formal),end='')
        print(''.join(fuzzy),end='')
        print(''.join(slim),end='')

        return (formal,fuzzy,slim)

    def function(self, func):
        blocks = []

        for block in idaapi.FlowChart(func):
            blocks.append(self.block(block))

        return blocks

    def generate(self):
        signatures = RizzoSignatures()

        for ea in idautils.Functions():
            func = idaapi.get_func(ea)
            if func:
                print('
func 0x%x' % ea, idaapi.get_name(ea))

                raw_formal = []
                raw_fuzzy = []
                raw_slim = []

                blocks = self.function(func)
                for (e, f, s) in blocks:
                    raw_formal.extend(e)
                    raw_fuzzy.extend(f)
                    raw_slim.extend(s)

                formal = self.sighash(''.join(raw_formal))
                fuzzy = self.sighash(''.join(raw_fuzzy))
                slim = self.sighash(''.join(raw_slim))

                print('')
                print('hash 0x%x' % ea, formal)
                print('hash 0x%x' % ea, fuzzy)
                print('hash 0x%x' % ea, slim)

                start_ea = ida_shims.start_ea(func)
                signatures.functions[start_ea] = (ida_shims.get_name(start_ea), blocks)

                if formal not in signatures.formal:
                    signatures.formal[formal]=[]
                signatures.formal[formal].append(ida_shims.start_ea(func))

                if fuzzy not in signatures.fuzzy:
                    signatures.fuzzy[fuzzy]=[]
                signatures.fuzzy[fuzzy].append(ida_shims.start_ea(func))

                if slim not in signatures.slim:
                    signatures.slim[slim]=[]
                signatures.slim[slim].append(ida_shims.start_ea(func))

        return signatures

    def match(self, extsigs):
        slim = {}
        fuzzy = {}
        formal = {}

        start = time.time()

        for (extsig, ext_func_ea) in extsigs.formal.items():
            if extsig in self.signatures.formal:
                new_fun = RizzoFunctionDescriptor(
                    extsigs.formal, extsigs.functions, extsig)
                curr_fun = RizzoFunctionDescriptor(
                    self.signatures.formal, self.signatures.functions, extsig)
                formal[curr_fun] = new_fun

        for (extsig, ext_func_ea) in extsigs.fuzzy.items():
            if extsig in self.signatures.fuzzy:
                new_fun = RizzoFunctionDescriptor(
                    extsigs.fuzzy, extsigs.functions, extsig)
                curr_fun = RizzoFunctionDescriptor(
                    self.signatures.fuzzy, self.signatures.functions, extsig)
                fuzzy[curr_fun] = new_fun

        for (extsig, ext_func_ea) in extsigs.slim.items():
            if extsig in self.signatures.slim:
                new_fun = RizzoFunctionDescriptor(
                    extsigs.slim, extsigs.functions, extsig)
                curr_fun = RizzoFunctionDescriptor(
                    self.signatures.slim, self.signatures.functions, extsig)
                slim[curr_fun] = new_fun

        end = time.time()
        print("Found %d formal matches in %.2f seconds." % (len(formal),
                                                            (end-start)))

        return (formal, fuzzy, slim)

    def rename(self, ea, name):

        curname = ida_shims.get_name(ea)

        if curname.startswith('sub_') and 
                name.split('_')[0] not in 
                ['sub', 'loc', 'unk', 'dword', 'word', 'byte']:

            if ida_shims.get_name_ea_simple(name) == idc.BADADDR:
                if ida_shims.set_name(ea, name):
                    ida_shims.set_func_flags(
                        ea, (ida_shims.get_func_flags(ea) | idc.FUNC_LIB))
                    return 1
        return 0

    def apply(self, extsigs):
        count = 0
        rename = {}
        name_count = {}

        start = time.time()

        (formal, fuzzy, slim) = self.match(extsigs)

        for (curfunc, newfunc) in list(formal.items())+list(fuzzy.items())+list(slim.items()):
            print('main ',newfunc.name)
            for ea in curfunc.ea:
                if ea not in rename:
                    print('	ea 0x%x' % ea)
                    name_root = newfunc.name
                    if name_root not in name_count:
                        name_count[name_root] = 0
                    newname = '%s_%d' % (name_root, name_count[name_root])
                    rename[ea] = newname
                    self.rename(ea, newname)
                    count += 1
                    name_count[name_root] += 1

        end = time.time()
        print("Renamed %d functions in %.2f seconds." % (count, (end-start)))


def RizzoBuild(sigfile=None):
    print("Building Rizzo signatures, this may take a few minutes...")
    start = time.time()
    r = Rizzo(sigfile)
    r.save()
    end = time.time()
    print("Built signatures in %.2f seconds" % (end-start))


def RizzoApply(sigfile=None):
    print("Applying Rizzo signatures, this may take a few minutes...")
    start = time.time()
    r = Rizzo(sigfile)
    s = r.load()
    r.apply(s)
    end = time.time()
    print("Signatures applied in %.2f seconds" % (end-start))


def rizzo_produce(arg=None):
    fname = ida_shims.ask_file(1, "*.riz", "Save signature file as")
    if fname:
        if '.' not in fname:
            fname += ".riz"
        RizzoBuild(fname)


def rizzo_load(arg=None):
    fname = ida_shims.ask_file(0, "*.riz", "Load signature file")
    if fname:
        RizzoApply(fname)

try:
    class ProduceRizzoAction(idaapi.action_handler_t):
        def __init__(self):
            idaapi.action_handler_t.__init__(self)

        def activate(self, ctx):
            rizzo_produce()
            return 1

        def update(self, ctx):
            return idaapi.AST_ENABLE_ALWAYS


    class LoadRizzoAction(idaapi.action_handler_t):
        def __init__(self):
            idaapi.action_handler_t.__init__(self)

        def activate(self, ctx):
            rizzo_load()
            return 1

        def update(self, ctx):
            return idaapi.AST_ENABLE_ALWAYS
except AttributeError:
    pass


class RizzoPlugin(idaapi.plugin_t):
    flags = 0
    comment = "Function signature"
    help = ""
    wanted_name = "Rizzo"
    wanted_hotkey = ""
    produce_action_name = 'producerizzo:action'
    load_action_name = 'loadrizzo:action'
    menu_name = "Rizzo signature file..."
    produce_tooltip = "Produce rizzo signature file."
    load_tooltip = "Load rizzo signature file."
    menu_tab = 'File/'
    menu_context = []

    def init(self):
        if idaapi.IDA_SDK_VERSION >= 700:
            produce_desc = idaapi.action_desc_t(self.produce_action_name,
                                                self.menu_name,
                                                ProduceRizzoAction(),
                                                self.wanted_hotkey,
                                                self.produce_tooltip,
                                                199)

            load_desc = idaapi.action_desc_t(self.load_action_name,
                                             self.menu_name,
                                             LoadRizzoAction(),
                                             self.wanted_hotkey,
                                             self.load_tooltip,
                                             199)

            idaapi.register_action(produce_desc)
            idaapi.register_action(load_desc)

            idaapi.attach_action_to_menu(
                os.path.join(self.menu_tab, 'Produce file/'),
                self.produce_action_name,
                idaapi.SETMENU_APP)
            idaapi.attach_action_to_menu(
                os.path.join(self.menu_tab, 'Load file/'),
                self.load_action_name,
                idaapi.SETMENU_APP)
        else:
            self.menu_context.append(
                idaapi.add_menu_item(
                    os.path.join(self.menu_tab, 'Load file/'),
                    "Rizzo signature file...", "", 0, rizzo_load, (None,)))

            self.menu_context.append(
                idaapi.add_menu_item(
                    os.path.join(self.menu_tab, 'Produce file/'),
                    "Rizzo signature file...", "", 0, rizzo_produce, (None,)))

        return idaapi.PLUGIN_KEEP

    def term(self):
        if idaapi.IDA_SDK_VERSION >= 700:
            idaapi.detach_action_from_menu(
                self.menu_tab, self.produce_action_name)
            idaapi.detach_action_from_menu(
                self.menu_tab, self.load_action_name)
        else:
            if self.menu_context is not None:
                idaapi.del_menu_item(self.menu_context)
        return None

    def run(self, arg):
        return None

    def rizzo_script(self):
        idaapi.IDAPython_ExecScript(self.script, globals())


def PLUGIN_ENTRY():
    return RizzoPlugin()

stl_container.cpp

#include <iostream>
#include <array>
#include <queue>
#include <forward_list>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <algorithm>
#include <random>

using namespace std;

struct s{
    int s1;
    int s2;
    friend bool operator<(s a,s b){
        return true;
    }
    friend bool operator>(s a,s b){
        return true;
    }
    friend bool operator==(s a,s b){
        return true;
    }
    friend s operator+(s a,s b){
        return s{0,0};
    }
}s0;

#define a(x) if (a) x;
int a;

int main ()
{
    if (a){
        std::array<int,5> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.empty())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())a(c.data())
        a(c.fill(0))a(c.swap(c))
    }
    if (a){
        std::deque<int> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.resize(0))a(c.empty())a(c.shrink_to_fit())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())
        a(c.assign(0,0))a(c.push_back(0))a(c.push_front(0))a(c.pop_back())a(c.pop_front())a(c.insert(c.begin(),0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),0))a(c.emplace_front(0))a(c.emplace_back(0))
        a(c.get_allocator())
    }
    if (a){
        std::list<int> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.front())a(c.back())
        a(c.assign(0,0))a(c.push_back(0))a(c.push_front(0))a(c.pop_back())a(c.pop_front())a(c.insert(c.begin(),0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),0))a(c.emplace_front(0))a(c.emplace_back(0))a(c.resize(0))
        a(c.splice(c.begin(),c))a(c.remove(0))a(c.remove_if([](int){return true;}))a(c.unique(greater<int>()))a(c.merge(c))a(c.sort(greater<int>()))a(c.reverse())
        a(c.get_allocator())
    }
    if (a){
        std::map<int,int> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.operator[](0))a(c.at(0))
        a(c.insert(pair<int,int>(0,0)))a(c.erase(0))a(c.swap(c))a(c.clear())a(c.emplace(0,0))a(c.emplace_hint(c.begin(),0,0))
        a(c.key_comp())a(c.value_comp())a(c.find(0))a(c.count(0))a(c.lower_bound(0))a(c.upper_bound(0))a(c.equal_range(0))
        a(c.get_allocator())
    }
    if (a){
        std::queue<int> c;
        a(c.empty())a(c.size())a(c.front())a(c.back())a(c.push(0))a(c.emplace(0))a(c.pop())a(c.swap(c))
    }
    if (a){
        std::set<int> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.insert(0))a(c.erase(0))a(c.swap(c))a(c.clear())a(c.emplace(0))a(c.emplace_hint(c.begin(),0))
        a(c.key_comp())a(c.value_comp())a(c.find(0))a(c.count(0))a(c.lower_bound(0))a(c.upper_bound(0))a(c.equal_range(0))
        a(c.get_allocator())
    }
    if (a){
        std::stack<int> c;
        a(c.empty())a(c.size())a(c.top())a(c.push(0))a(c.emplace(0))a(c.pop())a(c.swap(c))
    }
    if (a){
        std::vector<int> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.resize(0))a(c.empty())a(c.shrink_to_fit())a(c.reserve(0))a(c.capacity())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())a(c.data())
        a(c.assign(0,0))a(c.push_back(0))a(c.pop_back())a(c.insert(c.begin(),0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),0))a(c.emplace_back(0))
        a(c.get_allocator())
        all_of(c.begin(),c.end(),[](int){return true;});
        any_of(c.begin(),c.end(),[](int){return true;});
        none_of(c.begin(),c.end(),[](int){return true;});
        for_each(c.begin(),c.end(),[](int){return true;});
        find(c.begin(),c.end(),0);
        find_if(c.begin(),c.end(),[](int){return true;});
        find_if_not(c.begin(),c.end(),[](int){return true;});
        adjacent_find(c.begin(),c.end(),greater<int>());
        count(c.begin(),c.end(),0);
        count_if(c.begin(),c.end(),[](int){return true;});
        copy(c.begin(),c.end(),c.begin());
        move(c);
        swap(c,c);
        transform(c.begin(),c.end(),c.begin(),[](int x){return x;});
        transform(c.begin(),c.end(),c.begin(),c.begin(),plus<int>());
        replace(c.begin(),c.end(),0,0);
        fill(c.begin(),c.end(),0);
        generate(c.begin(),c.end(),[](){return 0;});
        remove(c.begin(),c.end(),0);
        unique(c.begin(),c.end(),greater<int>());
        reverse(c.begin(),c.end());
        rotate(c.begin(),c.end(),c.begin());
        random_shuffle(c.begin(),c.end());
        shuffle(c.begin(),c.end(),std::default_random_engine(0));
        sort(c.begin(),c.end());
        lower_bound(c.begin(),c.end(),0);
        upper_bound(c.begin(),c.end(),0);
        equal_range(c.begin(),c.end(),0);
        binary_search(c.begin(),c.end(),0);
        min(0,0);
        max(0,0);
        minmax({0});
        min_element(c.begin(),c.end(),greater<int>());
        max_element(c.begin(),c.end(),greater<int>());
        minmax_element(c.begin(),c.end(),greater<int>());
        lexicographical_compare(c.begin(),c.end(),c.begin(),c.end());
        next_permutation(c.begin(),c.end());
        prev_permutation(c.begin(),c.end());
    }

    if (a){
        std::array<s,5> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.empty())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())a(c.data())
        a(c.fill(s0))a(c.swap(c))
    }
    if (a){
        std::deque<s> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.resize(0))a(c.empty())a(c.shrink_to_fit())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())
        a(c.assign(0,s0))a(c.push_back(s0))a(c.push_front(s0))a(c.pop_back())a(c.pop_front())a(c.insert(c.begin(),s0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),s0))a(c.emplace_front(s0))a(c.emplace_back(s0))
        a(c.get_allocator())
    }
    if (a){
        std::list<s> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.front())a(c.back())
        a(c.assign(0,s0))a(c.push_back(s0))a(c.push_front(s0))a(c.pop_back())a(c.pop_front())a(c.insert(c.begin(),s0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),s0))a(c.emplace_front(s0))a(c.emplace_back(s0))a(c.resize(0))
        a(c.splice(c.begin(),c))a(c.remove(s0))a(c.remove_if([](s){return true;}))a(c.unique(greater<s>()))a(c.merge(c))a(c.sort(greater<s>()))a(c.reverse())
        a(c.get_allocator())
    }
    if (a){
        std::map<s,s> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.operator[](s0))a(c.at(s0))
        a(c.insert(pair<s,s>(s0,s0)))a(c.erase(s0))a(c.swap(c))a(c.clear())a(c.emplace(s0,s0))a(c.emplace_hint(c.begin(),s0,s0))
        a(c.key_comp())a(c.value_comp())a(c.find(s0))a(c.count(s0))a(c.lower_bound(s0))a(c.upper_bound(s0))a(c.equal_range(s0))
        a(c.get_allocator())
    }
    if (a){
        std::queue<s> c;
        a(c.empty())a(c.size())a(c.front())a(c.back())a(c.push(s0))a(c.emplace(s0))a(c.pop())a(c.swap(c))
    }
    if (a){
        std::set<s> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.empty())a(c.size())a(c.max_size())
        a(c.insert(s0))a(c.erase(s0))a(c.swap(c))a(c.clear())a(c.emplace(s0))a(c.emplace_hint(c.begin(),s0))
        a(c.key_comp())a(c.value_comp())a(c.find(s0))a(c.count(s0))a(c.lower_bound(s0))a(c.upper_bound(s0))a(c.equal_range(s0))
        a(c.get_allocator())
    }
    if (a){
        std::stack<s> c;
        a(c.empty())a(c.size())a(c.top())a(c.push(s0))a(c.emplace(s0))a(c.pop())a(c.swap(c))
    }
    if (a){
        std::vector<s> c;
        a(c.begin())a(c.end())a(c.rbegin())a(c.rend())a(c.cbegin())a(c.cend())a(c.crbegin())a(c.crend())
        a(c.size())a(c.max_size())a(c.resize(0))a(c.empty())a(c.shrink_to_fit())a(c.reserve(0))a(c.capacity())
        a(c.operator[](0))a(c.at(0))a(c.front())a(c.back())a(c.data())
        a(c.assign(0,s0))a(c.push_back(s0))a(c.pop_back())a(c.insert(c.begin(),s0))a(c.erase(c.begin()))a(c.swap(c))a(c.clear())a(c.emplace(c.begin(),s0))a(c.emplace_back(s0))
        a(c.get_allocator())
        all_of(c.begin(),c.end(),[](s){return true;});
        any_of(c.begin(),c.end(),[](s){return true;});
        none_of(c.begin(),c.end(),[](s){return true;});
        for_each(c.begin(),c.end(),[](s){return true;});
        find(c.begin(),c.end(),s0);
        find_if(c.begin(),c.end(),[](s){return true;});
        find_if_not(c.begin(),c.end(),[](s){return true;});
        adjacent_find(c.begin(),c.end(),greater<s>());
        count(c.begin(),c.end(),s0);
        count_if(c.begin(),c.end(),[](s){return true;});
        copy(c.begin(),c.end(),c.begin());
        move(c);
        swap(c,c);
        transform(c.begin(),c.end(),c.begin(),[](s x){return x;});
        transform(c.begin(),c.end(),c.begin(),c.begin(),plus<s>());
        replace(c.begin(),c.end(),s0,s0);
        fill(c.begin(),c.end(),s0);
        generate(c.begin(),c.end(),[](){return s0;});
        remove(c.begin(),c.end(),s0);
        unique(c.begin(),c.end(),greater<s>());
        reverse(c.begin(),c.end());
        rotate(c.begin(),c.end(),c.begin());
        random_shuffle(c.begin(),c.end());
        shuffle(c.begin(),c.end(),std::default_random_engine(0));
        sort(c.begin(),c.end());
        lower_bound(c.begin(),c.end(),s0);
        upper_bound(c.begin(),c.end(),s0);
        equal_range(c.begin(),c.end(),s0);
        binary_search(c.begin(),c.end(),s0);
        min(s0,s0);
        max(s0,s0);
        minmax({s0});
        min_element(c.begin(),c.end(),greater<s>());
        max_element(c.begin(),c.end(),greater<s>());
        minmax_element(c.begin(),c.end(),greater<s>());
        lexicographical_compare(c.begin(),c.end(),c.begin(),c.end());
        next_permutation(c.begin(),c.end());
        prev_permutation(c.begin(),c.end());
    }
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注