第一次
约 4494 字大约 15 分钟
2024-7-12
2024年7月7日 周日
汇编语言
看了三章的内容,记录新指令和注意的点
标志寄存器 PSW
abc 和 sbb 用于进行更大位数的运算
cmp 相当于减法,不保存值,比较大小
六个条件转移指令,满足条件就 jmp
串传送指令 movsb、movsw + 两个 df 设置指令 cld(正)、std(负)
rep 次数由 cx 寄存器中的值决定
pushf 和 popf 将标志寄存器的值压栈
内中断
8086 cpu 中断向量表存放位置 0000:03FF,最后 256 字节是空的
中断处理程序编写 & iret 指令
在栈中弹出 CS:IP 的值以及弹出寄存器的值
保存用到的寄存器
处理中断
恢复用到的寄存器
用 iret 指令返回
中断特殊情况:ss 和 sp 最好是连续设置
int 指令
- 指令的格式为:int n n为中断类型码
- Bios中断例程
- DOS中断例程
CTF
一直以来都想入CTF的大门,但是今天算真正看 Wiki ,了解了赛制还有方向什么的,最关键的是这个平台上提供了很多学习资源,可以补全自己的技能树
修改博客
之前的博客文件结构有些问题,重新配置了文件路径,并且美化了一下,不过要想真正的做到自己修改还是得学前端,抽空再说吧
2024年7月8日 周一
汇编语言
- 端口
在 PC 系统中,CPU 最多可以定位 64KB 个不同的端口,地址范围为 0~65535
对端口读写不能使用 mov、push、pop 等内存读写指令,只能使用 in 和 out
注意
只能使用 ax 或 al 来存放从端口中读入的数据或要发送到端口中的数据。访问 8 位端口时使用 al,访问 16 位端口时用 ax。
CMOS RAM 芯片
- 包含一个实时钟和128存储单元的 RAM 存储器
- 靠电池供电,所以 RAM 中的信息不丢失
- 内部时钟占用 0~0dh 单元来保存时间信息,其余大部分单元用于保存系统配置信息,供系统启动时 BIOS 程序读取
- CPU 通过该芯片内部 70h(地址端口)、71h(数据端口) 两个端口读写 CMOS RAM
shl 和 shr 指令
如果移动位数大于 1 时,必须将移动位数放在 cl 中
- shl 逻辑左移指令
- shr 逻辑右移指令
修改博客
今天仔细看了下中文排版的规矩,有所启发,于是花费时间把将近四个月前写的东西重新排版了一下,当时对于 markdown 还不熟练。再然后就是修改一些小错误。之前 vitepress 的官方文档我也就看了我需要看的部分,今天也是把能看懂的都看了一遍,安装了别人做好的主题样式,并且使用了一些新的 markdown 拓展语法,跟之前的十分简陋相比,现在已经丰富很多了
2024年7月9日 周二
今天汇编语言终于结束了。今天阅读官方文档添加了友情链接的功能,并且添加了几个链接,我感觉我有点蠢前前后后又搞了一个半小时。然后就是修改文章格式,我现在还在纠结要不要把周记专门分出来一栏,分成一周一周的,从第一周开始一个一个添加 md 文件。
汇编语言
外中断
CPU 通过端口和外部设备进行联系
两种外中断
可屏蔽中断
IF=1,CPU 在执行完当前指令后响应中断,IF=0,则不响应可屏蔽中断
sti:设置 IF=1
cli:设置 IF=0
不可屏蔽中断
[!IMPORTANT] 请注意
不可屏蔽中断是 CPU 必须响应的外中断。
对于 8086CPU,不可屏蔽中断的中断类型码固定为 2。
PC 机键盘处理
输入
扫描码被送入 60h 端口。按键再松开会产生扫描码。断码 = 通码 + 80h。
通码:按键产生
断码:松开产生
引发 9 号中断:中断类型码为 9
执行 9 号中断
在 BIOS 键盘缓冲区中,一个输入用一个字单元存放,高位字节扫描码,低位字节字符码
0040:17 单元存储键盘状态字节
直接定址表
开头讲了一种新的定义段的方式,更加简便
data segment a db 1,2,3,4,5,6,7,8 b dw 0 data ends
空间换时间
使用 BIOS 进行键盘输入和磁盘读写
int 9 和 int 16h 是相互配合的
int 9 中断例程对键盘输入的处理
- I/O 接口
- 60h 端口
- 数据缓冲寄存器
- 内存-键盘缓冲区
int 16h 中断例程读取键盘缓冲区。以下给出 0 号功能:
- 检测键盘缓冲区中是否有数据
- 没有则继续做第 1 步
- 读取缓冲区第 1 个字单元中的键盘输入
- 将读取的扫描码送入 ah,ASCII 码送入 al
- 将已读取的键盘输入从缓冲区删除
字符串的输入
- 字符的输入和删除——栈
- 输入回车后,字符串输入结束
- 在输入的同时需要显示这个字符串
- 程序的处理过程
- 调用 int 16h 读取键盘输入
- 如果是字符,进入字符栈,显示字符栈中的所有字符;继续执行调用
- 如果是退格键,从字符栈中弹出一个显示字符栈中的所有字符;继续执行调用
- 如果是 Enter 键,向字符栈中压入0,返回
应用 int 13h 中断例程对磁盘进行读写
入口参数比较多,我就打算把这块作以了解,以后用到
博客修改
[!TIP] 痛定思痛
最后仔细想了想为了更好的管理以及更好地查阅文档,上面的考虑是完全有必要的,于是我又花了一个半小时新增了几个文件结构,重新写了导航栏和侧边栏,使得条理更加清晰
2024年7月10日 周三
《安全之路:避开路由器陷阱》
谷歌机翻 + 英语原文混着看
概念
这里列出的概念都是我不太熟悉的
- 僵尸网络(Botnet):由大量被黑客控制的被感染计算机组成的分布式网络系统。这些被感染的计算机被称为"僵尸"(Bot)。
- 硬编码凭证(hardcoded credentials):将用户名、密码等敏感信息直接写入程序代码或配置文件中,而不是通过动态方式从安全存储中获取。主要就是硬编码这个词的理解
- UPnP(Universal Plug and Play):是一种网络协议,允许设备在局域网内自动发现和相互连接,无需人工干预。UPnP会主动公开设备信息,本身也可能存在安全漏洞
- RCE(Remote Code Execution):是一种严重的安全漏洞,它允许攻击者在远程系统上执行任意代码。RCE漏洞通常是由于软件开发中的安全编码问题导致的。
- Telnet:基于文本的远程登录协议,它允许用户通过网络连接远程计算机并进行交互式操作。不加密通信。
- NVRAM:非易失性随机访问存储器,指断电后仍能保持数据的一种RAM
- HNAP(Home Network Administration Protocol):用于管理家庭网络设备的协议。它可以让管理员或用户通过Web浏览器或专用应用程序来轻松配置和管理家庭网络设备。过时的专有协议
- SOAP (Simple Object Access Protocol) :一种基于 XML 的消息传输协议,用于在分布式环境中进行信息交换。它主要用于实现基于 Web 服务的应用程序之间的通信。
- XML(Extensible Markup Language):一种标记语言,用于描述数据的结构。它被设计用于传输和存储数据,并且易于被人类和机器读取和理解。
- Lua:一种轻量级、可嵌入的脚本语言。适合嵌入式设备的脚本语言,在自定义网络设备和物联网设备中有着广泛的应用前景。
指令 & 函数
iptables 命令:Linux操作系统中一个强大的网络防火墙和数据包过滤工具。它允许管理员控制进出系统的网络流量,并根据预定义的规则对数据包进行过滤和转发处理。
system 函数:
int main(int argc, char** argv) { setuid(geteuid());//将程序的有效用户ID设置为当前进程的有效用户ID system(argv[1]);//接收参数为字符串指针。如果发生错误,则返回值为 -1,否则返回命令的状态。 return 0; }
snprintf 函数:
int snprintf ( char * str, size_t size, const char * format, ... ); //str:目标字符串,用于存储格式化后的字符串的字符数组的指针。 //size:字符数组的大小。 //format:格式化字符串。 //...:可变参数,可变数量的参数根据 format 中的格式化指令进行格式化 //返回值是输出到 str 缓冲区中的字符数,不包括字符串结尾的空字符 \0
execve 函数: exec系列的系统调用是把当前程序替换成要执行的程序,而fork用来产生一个和当前进程一样的进程(虽然通常执行不同的代码流)。通常运行另一个程序,而同时保留原程序运行的方法是,fork+exec。
int execve(const char *filename, char *const argv[ ], char *const envp[ ]); //filename:文件路径程+序名 //argv[ ]:利用数组指针来传递执行文件,并且需要以空指针(NULL)结束 //envp[ ]:传递给执行文件的新环境变量数组
[!IMPORTANT]注意
这里的第二个参数 argv 中,argv[0] 通常是可执行程序的路径或文件名,从 argv[1] 开始是传递给可执行程序的参数。参数数组最后一个元素必须是 NULL(或 0 ),用于标记参数数组的结尾。
execve("/bin/iptables", { "/bin/iptables", "-A", "INPUT", "-s", ip_addr_to_block, "-j", "DROP", 0 }, 0);
形如这样的调用中没有空格分隔命令在 Linux 也是可以执行的
strncmp 函数:用于比较两个字符串的前 n 个字符是否相等
int strncmp(const char *str1, const char *str2, size_t n) //str1:要进行比较的第一个字符串。 //str2:要进行比较的第二个字符串 //n:要比较的最大字符数
argc 以及 argv:使用 argc 和 argv 是 C 语言中处理命令行参数的标准方式,它为程序提供了一种简单而强大的方式来获取用户输入
sprintf 函数:发送格式化输出到 str 所指向的字符串
int sprintf(char *str, const char *format, ...); sprintf(cmd, "ping %s", ip_addr);//这个直接上实例 //将字符串 ping %s 格式化,将 ip_addr 变量的值替换到格式化字符串中 //最后用字符串 cmd 来存储格式化的字符串 ping %s
os.system 函数:
[!warning]这是 Python 中的函数
类似于上面 C 语言中的 system 函数
eval:一个把字符串当作表达式执行而返回一个结果的函数
漏洞类别
身份验证绕过
身份验证绕过漏洞对攻击者来说很有价值,因为它打开了的攻击面。
CVE-2021-32030:报告了华硕 GT-AC2900 路由器上的身份验证绕过问题
问题
当你要登录管理员面板时,客户端发出 asus_token 给后端服务器,后端服务器收到请求后,会从路由器的 NVRAM 读取的 ifttt_token 进行比较验证管理员身份,但是如果 ifttt_token 为空,asus_token 也为空,就会直接验证成功。
解决
这是由程序员没有考虑边界情况引起的,应该有确保 ifttt_token 函数不为空的函数,先确保 ifttt_token 不为空再与客户端提供的 asus-token 进行比较验证。为了更安全也可以增加 asus_token 是否为空的判断。。
CVE-2020-8864:报告了 D-Link DIR-882、DIR-878 和 DIR-867 路由器上的身份验证绕过漏洞
问题
下面的函数用来比较验证,如果攻击者输入为空,那么 strlen 函数返回 0,这下比较前 0 个字符,这根本不用比 strncmp 函数自动返回 0 身份验证直接就成功了。
strncmp(db_password, attacker_provided_password, strlen(attacker_provided_password));
解决
将 db_password 作为strlen 的参数传递给 strncmp 函数。
CVE-2020-8863:D-Link 多路由器 HNAP PrivateLogin 身份验证算法错误实现身份验证绕过漏洞。
问题
通过 HNAP 进行身份验证时,服务器通常会根据用户的密码生成 PrivateKey。但是,当攻击者在登录请求中提供额外的 PrivateLogin 元素时,会发生一些不同的情况。服务器会使用 Username 元素的值来生成 PrivateKey,而不是用户密码。所以密码随意填写都能过。
命令注入
根本原因
利用命令语法和设计缺陷进行攻击。
使用 shell 理由:省事。
预防
并非所有操作都需要通过 shell 命令执行,因此请避免这样做,除非必要。
避免 system 命令
这一类函数都别用:system、popen、os.system、subprocess.Popen 等。
使用参数列表运行可执行文件
使用这类函数:execve、subprocess.Popen、subprocess.run、subprocess.call等
[!important]注意
fork + exec
Lua
为了防止开发人员制作容易受到命令注入攻击的命令字符串,开发团队可以创建一个类似 execve 的函数,但是:
[!important]注意
用单引号将每个参数括起来:防止命令替换
转义每个参数中的单引号:防止不会关闭参数前面的单引号
在 shell 脚本中避免使用 eval
即使外部调用过程安全,最终执行的脚本代码仍可能被利用,造成系统被攻击或信息泄露等安全问题
shell 脚本
没专门学过,原来用 Linux 都是现学现卖,不过上面那篇文章有点看不懂了,故而选择上菜鸟教程好好看一看 shell 的内容😂😂😂
2024年7月12日 周五
昨天有点小事,就只学了两个小时,由于时间太短就不写了。
《安全之路:避开路由器陷阱》
概念
- ASLR(Address Space Layout Randomization):操作系统安全技术,用于增强系统的抗攻击能力
- PIE(Position Independent Executable):是一种代码编译技术,通常与 ASLR(Address Space Layout Randomization)结合使用,以提高系统的安全性。
- RELRO(Relocation Read-Only):是一种针对 ELF 可执行文件和动态链接库的安全强化技术。它的主要目的是减少程序中可被攻击者利用的攻击面。
- Stack Canary:用于检测和防范栈溢出攻击的安全技术。
- NX(No-eXecute):内存保护技术,用于防止缓冲区溢出攻击。
- ASLR (Address Space Layout Randomization) :一种计算机安全技术,用于在程序加载时随机化进程地址空间布局,以降低利用内存中的漏洞进行攻击的风险。
函数
strcat 函数:
char *strcat(char *dest, const char *src) //dest:指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串。 //src:指向要追加的字符串,该字符串不会覆盖目标字符串。
memcpy 函数:
void *memcpy(void *str1, const void *str2, size_t n) //str1:指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。 //str2:指向要复制的数据源,类型强制转换为 void* 指针。 //n:要被复制的字节数。
memset 函数:
void *memset(void *str, int c, size_t n) //str:指向要填充的内存区域的指针。 //c:要设置的值,通常是一个无符号字符。 //n:要被设置为该值的字节数。
漏洞类别续
缓冲区溢出
原因
用 C 语言编程常见问题,栈溢出覆盖。在路由器中,使用复制内存内容的函数时通常会观察到此错误。
预防
使用有界函数进行复制
[!important]注意
在使用像 strncpy 或 memcpy 这样的函数时,应引入用户独立输入的 length 参数来决定要复制的长度,而且要基于目标缓冲区分配的大小来决定 length 的值。
将缓冲区大小作为函数参数传递
当存在多重函数调用的时候,跟踪和管理缓冲区大小就变得很复杂(特别是当它们被动态分配时)。
[!important]注意
使用 strncpy 函数时,需要特别注意目标缓冲区的大小,并确保在复制操作后手动添加空字符来确保字符串的正确终止,同时避免越界访问。
使用 strncat 函数追加时,确保目标缓冲区有足够的空间来容纳要追加的字符串及其终止符。
避免使用库函数,创建并使用自己常见的库函数
格式字符串错误
printf 函数,现代 C 编译器不是使用
printf("%s", username);
形式,都是会报错的,所以无需担心
shell 脚本
今天早上有课,下午有个小考试,其实今天的东西还没学完,目前就是这些先提交上去