实现OS记录:启动流程终点与内核的起点
0x00我已启动 0x01 加载 kernel这里的加载有两重含义: 一是在 loader 开启分页进入虚拟地址空间后,就应该跳转到内核,由内核来接管了。但在这之前当然要先从硬盘把 kernel 读进来。 二是 kernel 是一个 ELF 文件,内核被读入到内存后,loader 还要通过分析其 elf 结构将其再加载到新的位置,所以说,内核在内存中有 两份拷贝,一份是 elf 格式的原文件 kernel.bin,另一份是 loader 解析 elf 格式的 kernel.bin 后在内存中生成的 内核映像 先说第一点,和 mbr 读入 loader 很类似,只不过是在保护模式下执行,需要注意一些细节。比如本人写出的一个bug,仍然使用了 bx 存储加载到的基地址,但 kernel 的读入地址当然大于 16 位…所以要使用 ebx。 另外为了 kernel 未来的扩展有足够的空间,将读入的原始 elf 文件放入比较高的地址处。并且原始 elf 文件在 kernel 完全加载完后被覆盖了也没关系。 再说第二点,再加载是什么意思? ELF 文件也是一种可执行文件,只不过加了一个...
实现OS记录:启用分页机制进入虚拟地址空间
0x00关于原理和机制很多我直接在注释中写明了,所以就不过多阐述,更多的是总体上简单提一嘴。 0x01 为何分页在有新进程需要内存而连续内存不够时,要么等某个进程使用内存完毕再给新进程使用,要么把某些进程使用的某些段内存先换出到硬盘,腾出一片连续内存来给新进程使用。 当然不可能采取第一种方法,不然新进程要等半天才能运行。第二种方法的思想是正确的,但是受限于段式内存管理,十分笨重,一次就要换出一整段,效率不高。并且如果内存很小甚至装不下任何一个进程的全部段,那不是啥都运行不了? 直接引用《操作系统真象还原》的原话: 问题的本质是在目前只分段的情况下,CPU 认为线性地址等 于物理地址。而线性地址是由编译器编译出来的,它本身是连续的,所以物理地址也必须要连续才行,但 我们可用的物理地址不连续。换句话说,如果线性地址连续,而物理地址可以不连续,不就解决了吗。 所以分页机制产生了。每一页不大不小 0x1000...
实现OS记录:从实模式进入保护模式
0x00这学期开始上操作系统原理的课,本人此前学过许多关于操作系统的知识但是却没有完整地串联起来过。于是决定实现一个简单操作系统。 跟着《操作系统真象还原》来进行实现。但是不使用书中教程使用的 bochs,本人使用 qemu 来进行运行调试。有关环境如下 123456789101112131415161718192021222324252627282930❯ qemu-system-i386 --versionQEMU emulator version 8.2.2 (Debian 1:8.2.2+ds-0ubuntu1.13)Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers❯ nasm -vNASM version 2.16.01❯ gcc --versiongcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0Copyright (C) 2023 Free Software Foundation, Inc.This is free software;...
软件系统安全赛初赛2026 PWN方向wp
0x00只有一题,比赛中本地打通了, 被远程卡了 一个多小时。。 0x01 mailsystem一个邮件管理系统, 有user和admin 先逆向, 改完函数名然后自定义了一个userstruct结构体就好看多了 1234567891011121314151617181900000000 struct UserStruct // sizeof=0x41000000000 {00000000 char inbox_content[256];00000100 __int64 draft_size;00000108 __int64 field_108;00000110 char draft_content[256];00000210 __int64 inbox_size;00000218 char gap_218[96];00000278 __int64 user_id;00000280 char gap_280[24];00000298 char username[40];000002C0 ...
SparkCTF2026-final-PWN方向wp
0x00DAMN 也是 ak 十道题目拿下第一(虽然感觉没什么人打) 0x01 encoder非常简单, base64 加密后数据长度会溢出, 然后可以逐步带出 flag 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263#!/usr/bin/env python3from pwn import *import base64context(os='linux', arch='amd64', log_level='debug')filename = "pwn_patched"libcname =...
楚慧杯2026初赛PWN方向wp
0x00高手杯 0x01 House_1123456789101112unsigned __int64 sub_135E(){ char buf[56]; // [rsp+0h] [rbp-40h] BYREF unsigned __int64 v2; // [rsp+38h] [rbp-8h] v2 = __readfsqword(0x28u); puts("Please write your name:"); read(0, buf, 0x30uLL); puts("the name is:"); printf(buf); return __readfsqword(0x28u) ^ v2;} 12345678910_BYTE *sub_12E5(){ _BYTE buf[72]; // [rsp+0h] [rbp-50h] BYREF unsigned __int64 v2; // [rsp+48h] [rbp-8h] v2 = __readfsqword(0x28u); ...
VNCTF2026PWN方向wp
0x00寒假躺了好久,看看题稍微复健一下 0x01 vm-syscall1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859__int64 __fastcall main(int a1, char **a2, char **a3){ void **ptr; // rbx setbuf(stdin, 0LL); setbuf(stdout, 0LL); setbuf(stderr, 0LL); ptr = malloc(0x48uLL); memset(ptr, 0, 0x48uLL); ptr = (void **)ptr; *ptr = mmap(0LL, 0x1000uLL, 3, 34, -1, 0LL); puts("Enter your code:"); read(0, *(void **)ptr, 0x200uLL); mprotect(*(void...
WHUSESC数据结构考纲算法模版
0x00数据结构实验期末考试复习,搓了考纲内的简单算法模版,仅作参考 0x01...
WHUSESC数据结构实验往年题解
0x00WHUSESC 23-24 、 22-23 和 20-21 的数据结构实训期末考核题解源码笔者手写,仅供参考 0x01 23-24一、H 遍历算法设计在森林上定义一种特殊的遍历次序,称为 H 遍历。规则如下:对于有多棵子树的森林,先遍历第一棵子树 T1,再遍历第二棵子树 T2,依次按顺序遍历完所有子树。在每一棵子树内部,比如 T1 的内部,先遍历 T1 的第一棵子树,再访问 T1 的根结点,再遍历 T1 的其余的子树森林。 如图所示,该树的 H 遍历结果是:EBFACHIJKGD。 因为任意的树都可以转换为对应的二叉树,如上图所示的树,可以转换成下图所示的二叉树: 请设计一个算法,能够在以二叉链表表示的树(即孩子兄弟链结构)上输出 H 遍历次序。 具体要求(1) 定义二叉树的结点的数据类型,并使用动态内存分配的方式向二叉树中插入新的结点。 (2) 定义栈元素的数据类型,以满足遍历二叉链表结构的需要。概念上是一个二叉树的结点入栈,同时应该表明该结点是其父结点的左孩子还是右孩子。这样可以方便判断回溯时是从左子树上来的还是从右子树上来的。 (3)...
DASCTF2025-winter-PWN方向wp及复现
0x00简单放下 wp , 复现了一下最后的 vm 0x01 rcms菜单 1234567891011121314151617181920212223242526272829303132333435363738394041int __fastcall main(int argc, const char **argv, const char **envp){ __int64 v3; // rdx __int64 v4; // rcx __int64 v5; // r8 __int64 v6; // r9 int v8; // [rsp+Ch] [rbp-14h] BYREF _QWORD *v9; // [rsp+10h] [rbp-10h] unsigned __int64 v10; // [rsp+18h] [rbp-8h] v10 = __readfsqword(0x28u); init(argc, argv, envp); sandbox(*(__int64 *)&argc, (__int64)argv, v3, v4, v5,...


