内容简介:上周日给Real World CTF 2018出了一道forensics题ccls-fringe,向解出此题的31支队伍表达祝贺。上一次出题已是2016年,一直没有人教我pwn、reverse、web所以只能从平常接触的东西里勉强抽出要素弄成题目。kelwya找我来出题,他说forensics也可以,阻止了我说另请高明。另外也想给自己的项目打广告,萌生了从
上周日给Real World CTF 2018出了一道forensics题ccls-fringe,向解出此题的31支队伍表达祝贺。
上一次出题已是2016年,一直没有人教我pwn、reverse、web所以只能从平常接触的东西里勉强抽出要素弄成题目。
kelwya找我来出题,他说forensics也可以,阻止了我说另请高明。另外也想给自己的项目打广告,萌生了从 ccls 的cache弄一道forensics的想法,因为惰性拖了两个星期没有动手。之前一次LeetCode Weekly前在和一个学弟聊天,就想把他的id嵌入了flag。LeetCode第一题Leaf-Similar Trees没有叫成same-fringe,所以我的题目就带上fringe字样“科普”一下吧。
下载 ccls-fringe.tar.xz
后解压得到 .ccls-cache/@home@flag@/fringe.cc.blob
。这是存储的cache文件。
这里体现了ccls和cquery的一个不同点。ccls默认使用 "cacheFormat":"binary"
了,这个自定义的简单序列化格式,cquery仍在使用JSON。
写段程序读入文件,用 ccls::Derialize
反序列化成 IndexFile
,用 ToString
可以转成JSON字串,阅读可以发现其中一个变量 int b
:
{ "usr": 7704954053858737267, "detailed_name": "int b", "qual_name_offset": 4, "short_name_offset": 4, "short_name_size": 1, "hover": "", "comments": "flag is here", "declarations": [], "spell": "16:80-16:81|1935187987660993811|3|2", "extent": "16:76-16:81|1935187987660993811|3|0", "type": 52, "uses": [], "kind": 13, "storage": 0 },
clang -fparse-all-comments
会把非Doxygen注释也嵌入AST,注释暗示了我们应该找和它类似的变量。 spell
差不多表示spelling SourceRange,第80列很奇怪。写一段程序收集位于80列的其他单字符变量,按行号排序:
#include"indexer.h" const char blob[] = ".ccls-cache/@home@flag@/fringe.cc.blob"; __attribute__((constructor)) void solve(){ std::string content = *ReadContent(blob); auto file = ccls::Deserialize(SerializeFormat::Binary, blob, content, "", {}); std::vector<std::pair<int, char>> wod; for (auto &[usr, v] : file->usr2var) { Maybe<Use> spell = v.def.spell; if (spell) { Position start = spell->range.start; if (start.column == 79) wod.emplace_back(start.line, v.def.detailed_name[4]); } } sort(wod.begin(), wod.end()); for (auto t: wod) putchar(t.second); puts(""); exit(0); }
Makefile
指定编译选项和链接选项,除了LLVM只有rapidjson一个依赖了。
CCLS := $(HOME)/Dev/Util/ccls LLVM := $(HOME)/Dev/llvm LDFLAGS := -shared CXXFLAGS := -std=c++17 -fPIC -g CXXFLAGS += -I$(CCLS)/src -I$(CCLS)/third_party -I$(CCLS)/third_party/rapidjson/include CXXFLAGS += -I$(LLVM)/include -I$(LLVM)/Release/include CXXFLAGS += -I$(LLVM)/tools/clang/include -I$(LLVM)/Release/tools/clang/include solve.so: solve.cc $(LINK.cc) $^ -o $@
编译成 ccls.so
,让 ccls
吐出flag:
% LD_PRELOAD=./ccls.so ~/Dev/Util/ccls/Debug/ccls blesswodwhoisinhk
这只是这人用的id的一个子串,他教育我要多做Codeforces,是很好玩的(可惜我依然这么菜,呜呜:sob::sob::crying_cat_face::crying_cat_face:)。
把same-fringe problem写成coroutine形式也是为了纪念一个去New York City的同学,他在Stanford读研期间,给一门课当助教时曾让我校对一个课程实验Cooperative User-Level Threads。
#include <iostream> #include <vector> #include <ucontext.h> using namespace std; struct TreeNode { int val; TreeNode *left; TreeNode *right; }; struct Co { ucontext_t c; char stack[8192]; TreeNode *ret; Co(ucontext_t *link, void (*f)(Co *, TreeNode *), TreeNode *root) { {int b; /* flag is here */} getcontext(&c); {int l;} c.uc_stack.ss_sp = stack; {int e;} c.uc_stack.ss_size = sizeof stack; {int s;} c.uc_link = link; {int s;} makecontext(&c, (void(*)())f, 2, this, root); } void yield(TreeNode *x) { {int w;} ret = x; {int o;} swapcontext(&c, c.uc_link); {int d;} } }; void dfs(Co *c, TreeNode *x) { {int w;} if (!x) return; {int h;} if (!x->left && !x->right) c->yield(x); {int o;} dfs(c, x->left); {int i;} dfs(c, x->right); {int s;} } class Solution { public: bool leafSimilar(TreeNode *root1, TreeNode *root2) { {int i;} ucontext_t c; {int n;} Co c2(&c, dfs, root2), c1(&c2.c, dfs, root1); {int h;} do { {int k;} c1.ret = c2.ret = nullptr; swapcontext(&c, &c1.c); } while (c1.ret && c2.ret && c1.ret->val == c2.ret->val); return !c1.ret && !c2.ret; } }; void insert(TreeNode **x, TreeNode &y) { while (*x) x = y.val < (*x)->val ? &(*x)->left : &(*x)->right; *x = &y; } int main() { TreeNode xs[] = {{3},{1},{5},{0},{2},{4},{6}}; TreeNode ys[] = {{5},{3},{6},{1},{4},{0},{2}}; TreeNode zs[] = {{3},{1},{5},{0},{2},{6}}; TreeNode *tx = nullptr, *ty = nullptr, *tz = nullptr; for (auto &x: xs) insert(&tx, x); for (auto &y: ys) insert(&ty, y); for (auto &z: zs) insert(&tz, z); Solution s; cout << s.leafSimilar(tx, ty) << endl; cout << s.leafSimilar(tx, tz) << endl; }
假如你用clang trunk (>=7),ccls可以检索macro replacement-list中的引用。某些限定条件下template instantiation得到的引用也能索引。
代码
https://github.com/MaskRay/RealWorldCTF-2018-ccls-fringe
ccls的xref功能可以看 https://github.com/MaskRay/ccls/wiki/Emacs 里的截图。Vim/NeoVim用户也强烈建议看看Emacs能达到什么效果。最近也加了一个vscode-ccls,但我不用VSCode因此没有精力维护。 有更多精力的话可以帮我支持下 https://github.com/autozimu/LanguageClient-neovim/issues/454 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Real World CTF 2018 rwext5命题报告
- 开源等于免费?这只是你认知里的一个伪命题
- 新京报:在区块链技术加持下 数据孤岛会是个“伪命题”
- 圆桌讨论:技术为王还是落地为王?智慧安防遇冷是伪命题吗
- 为什么管理式医疗春天即将来临、复制美国PBM是个伪命题、DRG将推动医疗改革?【VB100观点】
- 网站前端性能测试报告
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。