CS:APP第九章学习
开始学 CSAPP的第九章
逐步更新:
2023-1-30:开始写
2023-2-01:完成
梗概虚拟内存是当今操作系统最重要的概念之一,它提供了三个重要的能力:
它将主存视为硬盘的缓存,主存只保留活动区域(局部性原理)
它为每个进程提供一致的地址空间
它保护了进程的内存,防止被随意覆盖
物理和虚拟寻址计算机的内存被组织为一个由 M 个连续的字节大小的单元组成的数组,每个字节都有唯一的物理地址。CPU 访问内存最自然的方式就是使用物理地址,我们称为物理寻址 。早期的 CPU 是使用物理寻址的,而现代的处理器是使用虚拟寻址。
虚拟寻址与物理寻址相比,多了一步将虚拟地址翻译成物理地址的过程,翻译是通过一个内存管理单元(MMU)的专用硬件,通过查表得知的物理地址,这张表由操作系统管理。
地址空间地址空间是一个非负整数地址的有序集合:
如果地址空间中的整数是连续的,那么我们说它是线性地址空间。
为了简化讨论,我们假设地址空间是线性地址空间。
在带虚拟存储器的系统中,CPU从一个有 $N=2^n$ 个地址的地址空间中生成虚拟地址,这个地址空间称为虚拟地址空间。
一个地址空间 ...
Windows基础知识(2)
Windows基础知识(2)——鼠标键盘消息处理
前置芝士焦点一般来说,我们选中一个窗口就叫获取了一个焦点,键盘输入事件只会发送给具有焦点的窗口或者是控件。我们按下一个按键,会将我们的按键格式化成一个消息给内核,内核通过打包这个消息发送给具有焦点的窗体应用程序。
键盘事件我们可以处理的键盘按键大致分为两类:
系统按键:WM_KEYDOWN,WM_KEYUP。
非系统按键:WM_SYSKEYDOWN,WM_SYSKEYUP。
WM_KEYDOWN 事件表示一个键按下,如果一直按住会持续地发送此类消息。
123456789case WM_KEYDOWN: { switch (wParam) { case 'B': { MessageBox(NULL, L"123", L"123", MB_OK); break; } } break;}
WM_KEYUP 就是键盘弹起事件。
...
CS:APP第八章学习
开始学 CSAPP的第八章
逐步更新:
2023-1-25:开始写
2023-1-28:写完
梗概程序计数器假设有一个值序列 $a_1,a_2, … , a_{n-1}$,其中,每个 ak是某个相应指令 Ik的地址,每次从地址 ak到 ak+1的过渡称为 控制转移。而这样的控制转移序列叫做处理器的 控制流。最简单的一种控制流是一个平滑的序列,其中每个指令 $I_k$ 和 $I_{k+1}$ 在内存中的位置都是相邻的。当然也有平滑流的突变,即指令 $I_k$ 和 $I_{k+1}$ 在内存中的位置不相邻,通常是由跳转、调用和返回这种程序指令造成的。这些指令都是一些必要机制,使得程序能够对由程序变量表示的内部程序状态的变化做出反应。
同理,系统也必须能够对系统状态的变化做出反应,这些系统状态不能由内部程序变量捕获,而且也不一定要会程序的执行相关,现代系统通过使控制流突变来对系统状态变化做出反应,一般将这种突变称为异常控制流。
调试器触发断点的一种方法是,将断点处的目标指令替换为一个不规范指令(int 3),并捕获由此引发的异常。
所以,对于我们来说,学习异常处理是非常有必要的。
异 ...
Windows基础知识(1)
来学学 windows 的基础知识,在 C++ 中的实现。
字符类型在 C++ 中,两个标准的字符类型是 char 和 wchar_t 类型,分别是代表 ASCII 字符和 UNICODE 字符。windows 对它进行了二次定义,变成了 CHAR 和 WCHAR 类型。并且为了兼容环境,还出现了 TCHAR,它会跟着项目环境选择 CHAR 还是 WCHAR。
有个函数可以把单字节转为宽字节:MultiByteToWideChar。
1234CHAR* s = (CHAR*)"xia0ji233";WCHAR buffer[50];MultiByteToWideChar(CP_ACP, NULL, s, -1, buffer, 50);printf("%S", buffer);
这里格式化字符串 %S 不同于 %s,%S 是宽字符,如果使用 %s 则会因为 ASCII 字符转 unicode 多了一个 00 字节而被截断。
还有个函数可以转回去。
1234WCHAR* ws = (WCHAR*)L"xia0ji233"; ...
CS:APP第七章学习
开始学 CSAPP的第七章
逐步更新:
2023-1-20:开始写
2023-1-23:写完
梗概这一节讲的就是链接,链接作为编译可执行文件的最后一步,也是比较重要的,书上也罗列了一些链接带来的问题:
理解链接器将帮助你构造大型程序
理解链接器将帮助你避免一些危险的编程错误
理解链接将帮助你理解语言的作用域规则是如何实现的。例如,全局和局部变量之间的区别是什么?当你定义一个具有static属性的变量或者函数时,实际到底意味着什么
理解链接将帮助你理解其他重要的系统概念
编译器驱动程序它给了一个多文件编译的一个示例,也不写了,大概意思就是一个地方调用函数但是不写定义,另一个文件写该函数的定义,然后把两个文件一起编译得到可执行文件。
其实我们所说的广义上的编译器(如 gcc)指的是编译系统给我们提供的编译器驱动程序,它是语言预处理器(cpp),编译器(cc1),汇编器(as),链接器(ld)的集合。
把 main.c 和 sum.c 一起编译的一个命令是:
1gcc -o prog main.c sum.c
把它的步骤拆开就是这样的:
预编译展开头文件和替换宏定义
1cpp ...
游戏安全的学习(3)
游戏安全的学习(3)—— SDK dump。
学这个的终极目标肯定是去搞原嘛,但是虽然⚪的保护比上不足但是比下有余啊。所以还是先从无保护的游戏入手,是之前很火的一个 3d 恐怖解谜游戏 Granny。
Unity引擎Unity 引擎是个很火的支持跨平台的游戏引擎,它主要的实现有 il2cpp 和 mono 两个工具来完成。
因此它生成的游戏中,就会隐含这两个工具其中一个的接口,通过这些接口,我们可以 dump 出所有这些基类的派生类,方法名,属性名,属性类型以及它们的偏移等等。
获取了这些东西之后,我们要对游戏 hook 就非常容易了。
dump mono 平台的符号这里 CE 的源码其实实现了这些功能,对于一些基本的没有保护的游戏,我们就是一键 dump 符号。但是处出于学习的目的还是选择自己写一遍,复刻它 dump 的方法。
dump准备这里选择 dll 注入然后获取模块列表,得到之后直接去寻找关键的函数。对于 Mono 平台来说,关键函数是 mono_thread_attach,而 il2cpp 的关键函数是 il2cpp_thread_attach。
先写一个注入器去注 ...
CS:APP第六章学习
开始学 CSAPP的第六章
逐步更新:
2023-1-15:开始写
2023-1-18:补完第二小节
2023-1-19:写完第六章!
梗概跟平时理解的差不多,层次存储,越靠近 CPU 的存储器读写速度越快,造价越贵,容量越小。
这里还举了一个例子:如果你的程序需要的数据是存储在CPU寄存器中的,那么在指令的执行期间,在 0 个周期内就能访问到它们。如果存储在高速缓存中,需要4~75个周期。如果存储在主存中,需要上百个周期。而如果存储在磁盘上,需要大约几千万个周期!
因此,为了考虑程序的性能,我们按照访问的频率,让数据在存储器中依次排好,以便于 CPU 能更快的访问到它需要的数据。
存储技术随机访问存储器随机访问存储器(Random-Access Memory,RAM)分为两类:静态的和动态的。静态RAM(SRAM)比动态RAM(DRAM)更快,但也贵得多。
SRAM它的每一位存储单元都是双稳态的,特性就是:可以无限期地在两种电压模式下保存,其它任何电压的状态都是不稳定的。
这里给了一个图,描述了这个特性:
只有倒向左边或者倒向右边两种状态是稳定的,其余状态均不稳定,如果出 ...
游戏安全的学习(2)
游戏安全的学习(2)—— 利用Windows API 操作游戏窗口,和扫雷游戏分析。
先定个小目标,实现以下功能:
透视,炸弹不炸,时间暂停,一键扫雷等等
句柄句柄(handle)是Windows操作系统用来标识被应用程序所建立或使用的对象的整数,可以理解为内核有一张句柄表,我们打开获得的句柄得到的是句柄表的偏移值。
特定的,窗口句柄叫 HWND。我们可以通过 VS 的工具选项中的 SPY++
去找到窗口的标题,句柄和类等等信息。
获取窗口句柄使用 API FindWindow 即可,我们需要给定两个参数,第一个参数为 Class Name,第二个参数为 Window name,应该是标题。我们可以给第一个参数传 NULL 一样能成功获取窗口句柄。
设置窗口标题使用 SetWindowText 就可以了,第一个参数为窗口句柄,第二个参数为要修改的标题。
然后我们来搞搞扫雷。
12345678#include<windows.h>#include<iostream>int main() { HWND hwnd=FindWindow( ...
游戏安全的学习(1)
游戏安全的学习(1)—— CE 的基本用法
开始学习游戏安全了,后续跟着队爹搞 O 去。
Cheat Engine简介说到游戏安全就不得不提这个软件了,这个软件本质是一款内存调试器,但是它对内存搜索的便捷特性使得它很容易修改游戏的某些数值,成为入门游戏安全必备的一个软件。
CE练习关卡CE 它内置了很多小游戏帮助我们快速入门 CE 这款软件,基础练习就不说了,我们直接来到游戏修改的这几关。可以在安装目录下找到 gtutorial-i386.exe 这个程序,这就是我们的练习关卡了,有三个经典的小游戏让我们修改。
第一关一个射击游戏,那边有一个靶标,我们需要摧毁目标,提示说了,每射击五次目标会回血并且立刻处于无敌状态,并且是在第五发子弹射出去的瞬间生效,正常过关我们是很难的,那就考虑修改靶标的血量,找到这一块内存。
因为不知道伤害和血量,所以首次搜索使用未知的初始值去搜索,搜索类型为 4 字节。
每射出一发子弹打到目标,就搜一次减少的数值,如果四次打完还没有找到合适的值,那就打出第五发子弹然后去搜 增加的数值,随后再这样循环操作直到看到合适的值。
我们找到了一个初始值为 100 ...
Golang入门学习(19)
Go的第19课——Go对mysql的操作
对于包的理解终于是对包这个东西有点概念了。首先我们直接导包,只会去 GOROOT 当中寻找,GOROOT 就是你安装 go 的一个地方,当然我们如果写的项目太大了肯定是要分很多包的,直接写在 GOROOT 里面又感觉很难受。
那么此时是这样的,我们要新建一个项目,这个项目作为文件夹,然后里面再建包,新建一个 go.mod 文件,内容就是
123module [projectname]go [go version]
比如我的项目名称为 xia0ji233,那么我的 go.mod 就是这样的内容:
123module xia0ji233go 1.19
里面新建的文件夹就会被作为包啦,要引用的时候就是 import "xia0ji233/pkgname"。
环境准备mysql就不说了官网上直接下,主要说说驱动下载,这里建议直接去 github 官网搞下来,这里贴一个 link。
然后像刚刚那样,新建一个项目,把源码目录改名为 mysql 放入项目文件夹即可,只要能引用就可以了。
连接数据库然后再要一个 databas ...