线段树转载记录
原文章(线段树)
0x01 种一颗线段树假如我现在有一个数组A,总共有n个元素,我既想实现区间修改,又想单个修改,这时候种一颗线段树来维护这个数组,能平衡收益。
0x02 怎么建立?线段树是一颗平衡二叉树,双亲结点是区间的和,左右子节点是双亲区间分两半的区间
每个节点 p 的左右子节点的编号分别为 2p 和 2p+1,假设 双亲结点p 的为区间 [l , r]的和。
设 mid = [(l + r)/2],那么两个子节点分别存储[l , mid] 和 [mid+1 , r]的和。可以发现,左节点对应的区间长度,与右节点相同或者比之恰好多1。
知道这些后,便可以用递归的方法来种一颗线段树了。大体的思想就是,从叶子结点开始,从下往上逐步建立。这便是递归的思想
12345678910111213141516void build(elem l = 1, elem r = n, elem p = 1){ // 到达叶子节点 if (l == r){ // 到达叶子节点 tree[p] = A[l]; // 用数组中的数据赋值 ...
C++容器初识和string容器
0x01 vector容器1234567891011121314151617#include<iostream>#include<vector>int main(){ //创建vector容器 std::vector<int> v; //存入数据 for(int i = 0;i < 10;i ++){ v.push_back(i); } //通过迭代器遍历 //it可看成指针,begin()是起始迭代器,存放容器第一个数据的地址 for(std::vector<int>::iterator it = v.begin(); it != v.end();it ++){ std::cout << *it << " "; } return 0;}//运行结果:0 1 2 3 4 5 6 7 8 9
简单的使用方法。。
vector类模板,除了int以外还能定义其他数据类型。
容器是可以嵌套容器的,可以将内层的容器看成一个数据类型,
...
VNCTF2024
0x01 TBXO只会看了这一道,应该也只会这一道了。
打开后f5,发现全是这种无意义的也不是函数的东西,感觉是经过防止反汇编的处理,无奈只能看汇编代码。
shift+f12找有用的字符串,发现有一个welcome 和wrong right等字眼的字符,点进去查找引用看看,能很快定位到main函数,当然是没法f5的,动调一步一步调试看会去哪里
发现这个是scanf函数,要输入flag,不知道flag是多少位,发现输入错误后程序会直接中断。当时在调试的时候无意间发现了一些类似加密函数的汇编代码,因为就在这个scanf函数下面,也是多看了几眼,然后发现是一个tea加密,不过f5后的代码是有问题的,不够全面,而且有很多差错。
如图,首先先不谈这些v1,v4,v2的是什么东西,关是这个a1 什么什么的就反汇编得很糟糕了,点进去这个unk_CC3004,发现是一个长度40char的数据,盲猜是enc密文,再动调试一下输入长度40 的flag,发现能调试到这一个函数了,直接看汇编。
不难发现这个v1 就是 (a - 1),v4就是 a,然后edi是存储sum 的 寄存器,每次循环加上 -0 ...
广义表和二叉树的性质
0x01 广义表的定义广义表是n(n>=0)个元素的有限序列,其中每一个元素或者是原子,或者是一个广义表。
广义表通常记为
1LS = (a1,a2,...,an)
其中LS为表名,n为表的长度,每一个ai为表的元素
习惯上用大写字母表示广义表,小写字母表示原子
表头:若LS非空,则其中第一个元素a1就是表头,记为
1head(LS) = a1
表头可以是原子也可以是子表
表尾:除表头之外的其他元素组成的表
1tail(LS) = (a2,...,an)
表尾表示最后一个元素,而是一个子表
0x02 广义表的性质广义表中的数据有相对次序,一个直接前驱和一个直接后继
广义表的长度定义位最外层所包含的元素的个数
广义表的深度定义为该广义表展开后所含括号的重数
广义表可以为其他广义表共享
广义表可以是一个递归的表,递归表的深度是无穷值
广义表是多层次结构,可以用图形象地表示
0x03 树的定义树(Tree) 是n (n≥0) 个结点的有限集。
若n=0,称为空树
若n>0,则它满足如下两个条件:
有且仅有一个特定的称为根(Root)的结点
其余结点可分为 m( ...
hgame_wp
0x01 babyre这个程序的关键在于几个线程的调用,和key的值。
首先key 的值在主函数的异或前是先赋值过的,不是原本静态存储的那个值,可以通过动调得到
10x77, 0x74, 0x78, 0x66, 0x65, 0x69
然后关于这个线程的调用我也不是很懂,大概就是创建四个线程,每个线程里存有各自的函数的地址,然后按顺序依次调用,调用了一个线程后该线程对应的信号量减一(wait),下一个线程的信号量加一(post),这时就调用下一个线程的函数,依次循环,直到全局变量 i 为31停止,最后退出线程,四个线程总共循环8次(按理来说,因为flag是32位,全部加密一轮需要8*4=32次),按照这个思路写出逆向脚本,结果也是没问题的。
一开始做题的时候是通过调试发现四个线程一轮只调用一次,于是猜测是逐个逐个进行。
123456789101112131415161718192021222324#include<iostream>#include<string.h>__int32 enc[33] = {12052,78,20467,109,13016, ...
picoCTF
0x01 packerelf的upx打包,我用windows的upx解不出来,开了个虚拟机在linux下就可以解包了,一开始就有flag串,十六进制转一下字符串就得到了。
picoCTF{U9X_UnP4ck1N6_B1n4Ri3S_1a5a3f39}
0x02 FactCheckcpp程序,反编译出来很多很长,看了一下逻辑就是创建很多个字符变量,然后根据最后的逻辑按一定顺序的将这些字符append到半成品flag上,耐心看看就好了。
picoCTF{wELF_d0N3_mate_2394047a}
0x03 WinAntiDbg0x100介绍说是一个反调试,点进去我感觉是这个阻碍我调试了,被调试时这个函数返回result=1,外部有个if接收了这个1后会导致程序退出,我们单步调试时在外部那个if前停下,然后修改ZF标志位,就能使程序跑向解密的二进制文件的代码了,直接查看内存里的密文就能得到flag。
picoCTF{d3bug_for_th3_Win_0x100_e70398c9}
0x04 Classic Crackme 0x100elf程序用ida打开后是一串50个字符串的有与 ...