西电网信院 网安实验班 软件与系统安全
【软件与系统安全笔记】一、引入_框架主义者的博客-CSDN博客
【软件与系统安全笔记】二、软件与系统安全基础_框架主义者的博客-CSDN博客
【软件与系统安全笔记】三、基础技术_框架主义者的博客-CSDN博客
【软件与系统安全笔记】四、内存破坏漏洞_框架主义者的博客-CSDN博客
【软件与系统安全笔记】五、内存破坏防御_框架主义者的博客-CSDN博客
【软件与系统安全笔记】六、恶意代码的机理及其防护_框架主义者的博客-CSDN博客
【软件与系统安全笔记】七、模糊测试_框架主义者的博客-CSDN博客
【软件与系统安全笔记】八、软件自我保护_框架主义者的博客-CSDN博客
简答题(70分)+综合题(30分)
浅灰色不重要:
概述
软件与系统安全基础
“威胁模型”1, 可信计算基(Trusted computing base),
“安全策略与策略执行”2, 通用的安全设计原则, 攻击面
软件逆向基础:
软件漏洞利用与防护
内存破坏漏洞与防御: “四、内存破坏漏洞”4
“缓冲区溢出:栈溢出(stack smashing)”5
整数溢出,
“堆溢出”6
Double free, Type Confusion,
“格式化字符串攻击”8
高级防御与攻击: “五、内存破坏防御”9
恶意代码的机理及其防护 “六、恶意代码的机理及其防护”15
病毒, 蠕虫, 木马, (侧重:差异, 共性, 如何隐藏)
模糊测试技术
软件保护技术 “软件保护技术”20
渗透测试及其他高级技术(线上)“九、Web 安全”24
变量存储位置
栈的工作原理
栈溢出、防护技术、DEP,金丝雀
堆的工作原理
堆溢出
整数溢出
格式化字符串漏洞
SQL注入
数组越界访问漏洞
释放重引用漏洞
绕过DEP “数据执行保护(DEP)”11
return to libc “代码重用攻击: Return to libc”27
返回导向编程 “ROP 面向返回的编程”14
*返回导向编程:*地址空间随机化 “ASLR Linux 的地址空间布局随机化”13
Fuzzing 定义、原理、特点
木马实现原理 “木马的实现原理与攻击步骤”28
病毒
分类"计算机病毒的分类"29
感染目标、过程
隐藏技术 “病毒的隐藏技术”30
花指令
多态 “病毒的多态”31
软件自我保护
mate 模型 “Man-At-The-End 攻击 (MATE)”32
#### 代码重用攻击: Return to libc
危险库函数如 `system()`
攻击者构造合适的参数(在栈上, 返回指令指针的上方)
* 在x64架构上,还需要更多的工作:设置参数传递寄存器的值
函数返回,库函数得到执行
* 例如:`execve(“/bin/sh”)`
甚至可以链接两个库函数调用
![Image](https://img-blog.csdnimg.cn/img_convert/75f31894424157e447f2695768e6f141.png)
==**具体地**==
* 攻击者用一个溢出填充buffer:
* 更改栈上保存的ebp为一个合适地址
* 更改返回指令指针为一个欲执行的库函数的地址
* 写一个占位符值(库函数会认为其是返回地址,如果想利用它调用第二个库函数, 应写入第二个库函数的地址)
* 写一个或多个要传递给此库函数的参数
* 当被攻击的函数返回时, 恢复(更改过的)ebp, 然后pop更改后的返回地址到eip, 从而开始执行库函数代码
* 因为库函数相信它已被调用, 故会将栈顶当前值(占位符)作为它自己栈帧的返回指令指针, 之上是参数
* 最终会在占位符位置的下方创建起一个新的栈帧 (对应于库函数的执行)
* 根据库函数参数类型以及库函数对参数的解释方式, 攻击者可能需要准确地知道参数地址以做溢出写
### 代码注入 vs 代码重用
![Image](https://img-blog.csdnimg.cn/img_convert/69ddf6348dd918ec4b69e39a92c91e4d.png)
**代码重用与代码注入的协同**
在很多攻击中, 代码重用攻击用来作为禁用DEP的第一步
* 目标是允许对栈内存进行执行
* 有一个系统调用可以更改栈的读/写/执行属性
* int mprotect(void *addr, size_t len, int prot);
* 设置对于起始于addr的内存区域的保护
* 调用此系统调用, 允许在栈上的“执行”属性, 然后开始执行被注入的代码
威胁模型(Attack model):对于影响系统安全的所有信息的结构化表示
本质上, 是从安全的视角解读系统与其环境
用于理解攻击者
捕获、组织和分析这些影响系统安全的信息的过程
威胁模型使得 结构化地推理 攻击面 成为可能
确定入口点
从攻击者的视角审视系统
漏洞(vulnerability):可以被对缺陷具有利用能力的攻击者访问并利用的缺陷, 要素:
攻击(attack): 指攻击者尝试利用漏洞,例如 主动、被动、DoS…
危害(compromise):攻击成功则危害发生 ↩︎
安全策略
策略执行
为了安全策略被遵循, 我们要做什么
策略执行的方法:利用某些“机制”(mechanism)
安全策略是一个系统所应具备的 安全属性 的高层次规约
安全策略模型是安全策略的简明(规范化)描述
安全目标是用户希望通过执行安全策略而获得的东西
安全属性与安全目标有时不做严格区分
参照 网络与协议安全 中的 CIA 概念
其他安全目标:
隐私(Privacy)
可以归类到机密性下
非否认性(Non-repudiation), 或可追责性(accountability):防止对消息传送或接收的否认
也叫可计量性
网络与协议安全 中还有 真实性
安全属性的另一种分类方法:
任何安全属性都可以被分解为一个 safety 属性和一个 liveness 属性
注意:实际上有一些安全策略无法用 safety 属性或 liveness 属性表示, 如信息流策略(2-safety 属性[2])——是“非属性”(Non-Property) ↩︎
x86: 基于 Intel 8086/8088 CPU 的一系列向后兼容的 ISA 的总称
IA-32: 32 位版本的 x86 指令集体系结构
三种主要操作模式:
CISC(Complex Instruction Set Computer)体系结构
x64: 又称 x86-64, 是 x86 的扩展, 是与 x86 兼容的 64 位 ISA
字节序:多字节数据在内存中存储或在网络上传输时各字节的存储/传输顺序
小端序(little endian):低位字节存储在内存中低位地址, 效率较高(Intel CPU 使用)
大端序(big endian):低位字节存储在内存中高位地址, 符合思维逻辑。RISC 架构处理器(如 MIPS, PowerPC)采用
分段内存模型
程序内存由一系列独立的地址空间(称为“段”)组成。代码、数据和栈在不同的段中
逻辑地址=段选择器 + 偏移量
保护模式下的内存管理:分段(必须)+ 分页(可选)
程序线性地址空间 ≤4GB, 物理地址空间 ≤64GB
每个段最大 232 字节, IA-32 程序最多使用 16383 个段
↩︎
2022-03-21 第四次课后半部分
mem-vul-part.pdf 内存破坏漏洞
回顾:
漏洞(vulnerability):可以被对缺陷具有利用能力的攻击者访问并利用的缺陷, 要素:
攻击(attack): 指攻击者尝试利用漏洞,例如 主动、被动、DoS…
危害(compromise):攻击成功则危害发生
在 C/C++ 程序中, 用 C 语言字符串编程时, 容易出现的错误
差一错误 是在计数时由于边界条件判断失误导致结果多了一或少了一的错误
gets:无边界的字符串复制
strcpy 和 strcat
“x86 Linux 系统的线性地址空间分层”33
“System V AMD64 ABI 调用惯例”34
缓冲区溢出可被利用于修改:
覆写返回指令指针
代码注入
将 ret 设置为被注入代码的起始地址, 被注入代码可以做任何事情,如下载和安装蠕虫
注入 Shell Code
shellcode: 注入的 payload 代码会执行起来一个 shell
在该 shell 中, 攻击者可以执行任何命令
该 shell 与当前进程具有相同的特权级
通常具有 root 权限的进程会被攻击
如何使用被注入的代码调用“execve”?
将函数“execve”的地址注入栈上
“execve”是一个 libc 中的函数, 动态链接到进程地址空间中
为了使得我们的可执行程序能够调用 libc 中的函数,可执行程序必须能找到被调用函数的地址
略
【NOTES.0x04】简易 Glibc heap exploit 笔记 - arttnba3’s blog
堆溢出: 在堆上开辟的缓冲区中的缓冲区溢出漏洞
溢出发生在堆缓冲区
Heap allocators (又称内存管理器)
Heap allocators 维护了元数据 (前块大小, 本块大小, previous 指针, next 指针)
堆溢出攻击会篡改元数据,并等待内存管理函数把被篡改的元数据写入目标地址
移除一个块
通过溢出 chunk2, 攻击者控制 chunk2 的 bk 和 fd 指针
假设攻击者想将 value 写入内存地址 addr
free()
:
变为
(*addr)=value
第一个写操作实现了攻击者的目标, 实现了任意的内存写操作
因 write-what-where 操作由free()完成, 故需从free()向上寻找潜在溢出
当溢出与代码注入/代码重用结合时,
*(addr)=value
”的addr是预先选择的函数指针、返回指令指针、影响控制流的变量地址等, value是恶意的跳转目标
定义: 程序在堆上释放内存, 然后引用该内存, 就好像该内存位置仍然合法:攻击者可以控制使用已释放的指针进行的数据写入
又称作悬挂指针使用,也是一个 write-what-where 漏洞
大多数有效的 use-after-free 攻击利用另一类型的数据
struct A {
void (*fnptr)(char *arg);
char *buf;
};
struct B {
int B1;
int B2;
char info[32];
};
// 释放A, 开辟B, 实际做了什么?
x = (struct A *)malloc(sizeof(struct A));
free(x);
y = (struct B *)malloc(sizeof(struct B));
// 如何利用此漏洞?
y->B1 = 0xDEADBEEF;
x->fnptr(x->buf);
Use-after-free 是类型混淆的一个实例
如何以较简单的方式禁止use-after-free?
设置所有被释放的堆空间为NULL
这时在使用被释放的堆空间时产生一个 null-pointer dereference
目前, 操作系统对 null-pointer deference 有内建的防护机制
复杂度: 需要设置所有别名指针(aliased pointers)为NULL
略
略
能够导致很灵活的恶意利用
int i; printf (“i = %d with address %08x\n", i, &i);
将格式化字符串的地址指针, i
和 &i
分别通过寄存器 rdi, rsi 和 rdx 传递, 并调用 printf
当程序运行至printf内部, 会在这些寄存器中查找参数;如果参数超过6个,还会在栈上查找参数
格式指示符字母的含义: printf - C++ Reference (cplusplus.com)
%n
”能够将到“%n”位置为止已经由printf打印出的字节数写到一个我们选定的变量中
int i;
printf ("foobar%n\n", (int *) &i);
printf ("i = %d\n", i);
// i 的值最终为6
对于“format-string.c”程序, 如果用户输入“foobar%n”会怎样?
因此, 攻击者可以用任意内容更新任意内存。可否覆写一个函数指针并劫持控制流(且安装某些蠕虫代码)?
int main(int argc, char *argv[]) {
char buf[512];
fgets(buf, sizeof(buf), stdin); // no buffer overflow here
printf("The input is:");
printf(buf); // format string attacks here
return 0
}
攻击者可以
通过提供一个特殊的格式化字符串, 可以规避“%400s
”的限制:
“%497d\x3c\xd3\xff\xbf
”。创建一个497字符长的字符串,加上错误字符串(“ERR Wrong command: ”),超过了outbuf的长度4字节。虽然“user”字符串只允许 400字节,可以通过滥用格式化字符串参数扩展其长度。因为第二个sprintf
不检查长度, 它可以用来突破outbuf的长度界限。此时我们写入了一个返回地址 (0xbfffd33c
), 并可以以之前栈溢出的利用方式进行攻击
即限制攻击者控制格式化字符串的能力
%*
”的格式化字符串printf(arg)
”%n
%s
和 sprintf
能够被用于构造栈内容披露攻击 ↩︎
“x86 Linux 系统的线性地址空间分层”33
“System V AMD64 ABI 调用惯例”34
缓冲区溢出可被利用于修改:
覆写返回指令指针
代码注入
将 ret 设置为被注入代码的起始地址, 被注入代码可以做任何事情,如下载和安装蠕虫
注入 Shell Code
shellcode: 注入的 payload 代码会执行起来一个 shell
在该 shell 中, 攻击者可以执行任何命令
该 shell 与当前进程具有相同的特权级
通常具有 root 权限的进程会被攻击
如何使用被注入的代码调用“execve”?
将函数“execve”的地址注入栈上
“execve”是一个 libc 中的函数, 动态链接到进程地址空间中
为了使得我们的可执行程序能够调用 libc 中的函数,可执行程序必须能找到被调用函数的地址
↩︎
【NOTES.0x04】简易 Glibc heap exploit 笔记 - arttnba3’s blog
堆溢出: 在堆上开辟的缓冲区中的缓冲区溢出漏洞
溢出发生在堆缓冲区
Heap allocators (又称内存管理器)
Heap allocators 维护了元数据 (前块大小, 本块大小, previous 指针, next 指针)
堆溢出攻击会篡改元数据,并等待内存管理函数把被篡改的元数据写入目标地址
移除一个块
通过溢出 chunk2, 攻击者控制 chunk2 的 bk 和 fd 指针
假设攻击者想将 value 写入内存地址 addr
free()
:
变为
(*addr)=value
第一个写操作实现了攻击者的目标, 实现了任意的内存写操作
因 write-what-where 操作由free()完成, 故需从free()向上寻找潜在溢出
当溢出与代码注入/代码重用结合时,
*(addr)=value
”的addr是预先选择的函数指针、返回指令指针、影响控制流的变量地址等, value是恶意的跳转目标
↩︎
定义: 程序在堆上释放内存, 然后引用该内存, 就好像该内存位置仍然合法:攻击者可以控制使用已释放的指针进行的数据写入
又称作悬挂指针使用,也是一个 write-what-where 漏洞
大多数有效的 use-after-free 攻击利用另一类型的数据
struct A {
void (*fnptr)(char *arg);
char *buf;
};
struct B {
int B1;
int B2;
char info[32];
};
// 释放A, 开辟B, 实际做了什么?
x = (struct A *)malloc(sizeof(struct A));
free(x);
y = (struct B *)malloc(sizeof(struct B));
// 如何利用此漏洞?
y->B1 = 0xDEADBEEF;
x->fnptr(x->buf);
Use-after-free 是类型混淆的一个实例
如何以较简单的方式禁止use-after-free?
设置所有被释放的堆空间为NULL
这时在使用被释放的堆空间时产生一个 null-pointer dereference
目前, 操作系统对 null-pointer deference 有内建的防护机制
复杂度: 需要设置所有别名指针(aliased pointers)为NULL
↩︎
能够导致很灵活的恶意利用
int i; printf (“i = %d with address %08x\n", i, &i);
将格式化字符串的地址指针, i
和 &i
分别通过寄存器 rdi, rsi 和 rdx 传递, 并调用 printf
当程序运行至printf内部, 会在这些寄存器中查找参数;如果参数超过6个,还会在栈上查找参数
格式指示符字母的含义: printf - C++ Reference (cplusplus.com)
%n
”能够将到“%n”位置为止已经由printf打印出的字节数写到一个我们选定的变量中
int i;
printf ("foobar%n\n", (int *) &i);
printf ("i = %d\n", i);
// i 的值最终为6
对于“format-string.c”程序, 如果用户输入“foobar%n”会怎样?
因此, 攻击者可以用任意内容更新任意内存。可否覆写一个函数指针并劫持控制流(且安装某些蠕虫代码)?
int main(int argc, char *argv[]) {
char buf[512];
fgets(buf, sizeof(buf), stdin); // no buffer overflow here
printf("The input is:");
printf(buf); // format string attacks here
return 0
}
攻击者可以
通过提供一个特殊的格式化字符串, 可以规避“%400s
”的限制:
“%497d\x3c\xd3\xff\xbf
”。创建一个497字符长的字符串,加上错误字符串(“ERR Wrong command: ”),超过了outbuf的长度4字节。虽然“user”字符串只允许 400字节,可以通过滥用格式化字符串参数扩展其长度。因为第二个sprintf
不检查长度, 它可以用来突破outbuf的长度界限。此时我们写入了一个返回地址 (0xbfffd33c
), 并可以以之前栈溢出的利用方式进行攻击
即限制攻击者控制格式化字符串的能力
%*
”的格式化字符串printf(arg)
”%n
%s
和 sprintf
能够被用于构造栈内容披露攻击 ↩︎
虽然对缓冲区溢出的认知已超过 40 年之久, 但缓冲区溢出仍未被消除。部分原因在于存在大量的利用选项:
防御可以在不同的时机进行
是栈溢出的检测机制, 又称“栈 cookies”,由 gcc 的 StackGuard 实现
原理:将一个 dummy 值(或随机值)写到栈上的返回地址之前,并在函数返回时检查该值。不小心构造的栈溢出(假定是顺序栈粉碎)会覆写该“canary”单元, 该行为将被探测到。
对 canary 单元, 用正确的值覆写
无法抵御 disclosure 攻击是 StackGuard 的最大局限性
disclosure 攻击通过对缓冲区的“overread”实现
著名例子: 对 SSL 的 Heartbleed 攻击
以下程序为什么会对 Stackguard 的 canaries 造成威胁?
char packet[10];
…
// suppose len is adversary controlled
strncpy(buf, packet, len);
send(fd, buf, len);
有时不需要覆写返回地址, 可以溢出:
void foo () {...}
void bar () {...}
int main() {
char buf [16];
void (*f) () = &foo;
gets(buf);
f();
}
假定我们没有机会溢出返回地址
可溢出缓冲区, 使得函数指针被修改为 bar 的地址, 然后函数调用将调用 bar 而非 foo
劫持函数指针的其他方法
有时不需要覆写返回地址, 可以溢出:
安全敏感的局部变量
堆数据
全局数据
· · ·
如何防御?
也是一种运行时检测方法, 可以看作StackGuard的扩展
在一个进程地址空间中关键内存区域之间放置守卫页 (像一些gaps)
效果: 能失效缓冲区溢出攻击, 特别是对全局数据区的溢出攻击
甚至可以在栈帧之间、或者堆缓冲区之间放置守卫页
冯诺依曼体系结构
哈佛架构
Data Execution Prevention (数据执行保护): 是一种运行时缓解技术
DEP又称作Nx-bit (non executable bit), W⊕X
能够阻止代码注入攻击
很多缓冲区溢出攻击涉及将机器码复制到目标缓冲区, 然后将执行转移到这些缓冲区
DEP 被绝大多数操作系统和指令集体系结构支持
对 Nx-bit 的不同叫法
如果CPU硬件支持, DEP可作为操作系统更新, 通过更改对进程虚拟地址空间的内存管理, 提供对现有漏洞程序的保护
DEP将栈和堆置为不可执行, 对多种缓冲区溢出攻击提供了一种高度的保护
但有一些合法程序需要将可执行代码放在栈上:
思路: 重用程序自身的代码
Return-to-libc: 用危险的库函数的地址替换返回地址
危险库函数如 system()
攻击者构造合适的参数(在栈上, 返回指令指针的上方)
函数返回,库函数得到执行
execve(“/bin/sh”)
甚至可以链接两个库函数调用
具体地
攻击者用一个溢出填充buffer:
当被攻击的函数返回时, 恢复(更改过的)ebp, 然后pop更改后的返回地址到eip, 从而开始执行库函数代码
因为库函数相信它已被调用, 故会将栈顶当前值(占位符)作为它自己栈帧的返回指令指针, 之上是参数
最终会在占位符位置的下方创建起一个新的栈帧 (对应于库函数的执行)
根据库函数参数类型以及库函数对参数的解释方式, 攻击者可能需要准确地知道参数地址以做溢出写
代码重用与代码注入的协同
在很多攻击中, 代码重用攻击用来作为禁用DEP的第一步
目标是允许对栈内存进行执行
有一个系统调用可以更改栈的读/写/执行属性
设置对于起始于addr的内存区域的保护
调用此系统调用, 允许在栈上的“执行”属性, 然后开始执行被注入的代码
面向返回的编程
正常机器指令序列
ROP执行
TODO
Turing completeness
一种语言是Turing complete的,如果其具有
这两点在ROP中均能实现
ROP的工作基于对程序控制流的修改
控制流完整性 (Control-flow integrity, CFI)
预先决定被攻击程序的控制流图
向该程序中插入检测, 使得在程序运行时发生非法控制流跳转时,终止程序
ROP利用要求攻击者对代码/数据地址的知识,例如
思路: 引入人为的多样性(随机化)
有很多方法能够实现随机化
实现随机化的时机
地址空间随机化的挑战
地址空间随机化的有效性取决于
ASLR(Address space layout randomization)
对于位置无关的可执行程序(PIE), 随机化该可执行程序的基地址
关注的是内存块的随机化
ASLR 是一种粗粒度的随机化形式
攻破 ASLR 的方法
如果随机地址空间很小, 可以进行一个穷举搜索
ASLR 经常被 memory disclosure (内存泄漏) 攻破
费根检查(fagan inspection)
检查表
危险的 C 库函数
所有输入都是恶意的
最小化攻击面
识别攻击面
好的实践
使用更安全的编程语言
进行代码评审
使用编译器的机制, 如 StackGuard
编写内存安全的代码
输入验证
↩︎
是栈溢出的检测机制, 又称“栈 cookies”,由 gcc 的 StackGuard 实现
原理:将一个 dummy 值(或随机值)写到栈上的返回地址之前,并在函数返回时检查该值。不小心构造的栈溢出(假定是顺序栈粉碎)会覆写该“canary”单元, 该行为将被探测到。
对 canary 单元, 用正确的值覆写
无法抵御 disclosure 攻击是 StackGuard 的最大局限性
disclosure 攻击通过对缓冲区的“overread”实现
著名例子: 对 SSL 的 Heartbleed 攻击
以下程序为什么会对 Stackguard 的 canaries 造成威胁?
char packet[10];
…
// suppose len is adversary controlled
strncpy(buf, packet, len);
send(fd, buf, len);
有时不需要覆写返回地址, 可以溢出:
void foo () {...}
void bar () {...}
int main() {
char buf [16];
void (*f) () = &foo;
gets(buf);
f();
}
假定我们没有机会溢出返回地址
可溢出缓冲区, 使得函数指针被修改为 bar 的地址, 然后函数调用将调用 bar 而非 foo
劫持函数指针的其他方法
有时不需要覆写返回地址, 可以溢出:
安全敏感的局部变量
堆数据
全局数据
· · ·
如何防御?
也是一种运行时检测方法, 可以看作StackGuard的扩展
在一个进程地址空间中关键内存区域之间放置守卫页 (像一些gaps)
效果: 能失效缓冲区溢出攻击, 特别是对全局数据区的溢出攻击
甚至可以在栈帧之间、或者堆缓冲区之间放置守卫页
↩︎
冯诺依曼体系结构
哈佛架构
Data Execution Prevention (数据执行保护): 是一种运行时缓解技术
DEP又称作Nx-bit (non executable bit), W⊕X
能够阻止代码注入攻击
很多缓冲区溢出攻击涉及将机器码复制到目标缓冲区, 然后将执行转移到这些缓冲区
DEP 被绝大多数操作系统和指令集体系结构支持
对 Nx-bit 的不同叫法
如果CPU硬件支持, DEP可作为操作系统更新, 通过更改对进程虚拟地址空间的内存管理, 提供对现有漏洞程序的保护
DEP将栈和堆置为不可执行, 对多种缓冲区溢出攻击提供了一种高度的保护
但有一些合法程序需要将可执行代码放在栈上:
思路: 重用程序自身的代码
Return-to-libc: 用危险的库函数的地址替换返回地址 ↩︎ ↩︎
代码重用与代码注入的协同
在很多攻击中, 代码重用攻击用来作为禁用DEP的第一步
目标是允许对栈内存进行执行
有一个系统调用可以更改栈的读/写/执行属性
设置对于起始于addr的内存区域的保护
调用此系统调用, 允许在栈上的“执行”属性, 然后开始执行被注入的代码
↩︎
ASLR(Address space layout randomization)
对于位置无关的可执行程序(PIE), 随机化该可执行程序的基地址
关注的是内存块的随机化
ASLR 是一种粗粒度的随机化形式
攻破 ASLR 的方法
如果随机地址空间很小, 可以进行一个穷举搜索
ASLR 经常被 memory disclosure (内存泄漏) 攻破
↩︎ ↩︎
面向返回的编程
正常机器指令序列
ROP执行
TODO
Turing completeness
一种语言是Turing complete的,如果其具有
这两点在ROP中均能实现
ROP的工作基于对程序控制流的修改
控制流完整性 (Control-flow integrity, CFI)
预先决定被攻击程序的控制流图
向该程序中插入检测, 使得在程序运行时发生非法控制流跳转时,终止程序
ROP利用要求攻击者对代码/数据地址的知识,例如
思路: 引入人为的多样性(随机化)
有很多方法能够实现随机化
实现随机化的时机
地址空间随机化的挑战
地址空间随机化的有效性取决于
ASLR(Address space layout randomization)
对于位置无关的可执行程序(PIE), 随机化该可执行程序的基地址
关注的是内存块的随机化
ASLR 是一种粗粒度的随机化形式
攻破 ASLR 的方法
如果随机地址空间很小, 可以进行一个穷举搜索
ASLR 经常被 memory disclosure (内存泄漏) 攻破
↩︎ ↩︎
病毒, 蠕虫, 木马, (侧重:差异, 共性, 如何隐藏)
8-木马.pdf
9-病毒.pdf
一个典型的特洛伊木马(程序)通常具有以下四个特点:
此外,木马还具有以下辅助型特点:
木马实现原理
本质上说,木马大多都是网络客户/服务(Client/Server)程序的组合。常由一个攻击者控制的客户端程序和一个运行在被控计算机端的服务端程序组成
当攻击者要利用“木马”进行网络入侵,一般都需完成如下环节:
植入技术
主动植入
本地安装
远程安装
被动植入
自动加载技术
在Windows系统中木马程序的自动加载技术主要有:
隐藏技术
连接技术
监控技术
木马的远程监控功能概括起来有以下几点:
木马的检测
木马的清除与善后
木马的防范
算机病毒一般依附于其他程序或文档,是能够自身复制,并且产生用户不知情或不希望、甚至恶意的操作的非正常程
计算机病毒的特点
以上列举的定义指的是狭义上的病毒。
但是随着黑客技术的发展,病毒、木马、蠕虫往往交叉在一起相互借鉴技术,因此人们经常说的计算机病毒往往是指广义上的病毒,它是一切恶意程序的统称。
计算机病毒的破坏性
计算机病毒引起的异常状况
我们针对狭义上的病毒,按照不同的标准对它进行分类。
按照计算机病毒攻击的对象或系统平台分类
按照计算病毒的攻击目标机类型分类:
按照计算机病毒的链接方式分类
按照计算机病毒的破坏情况分类
按传播媒介来分类
计算机病毒的命名
虽然每个反病毒公司的命名规则都不太一样,但大体都是采用一个统一的命名方法来命名的。一般格式为: <病毒前缀>.<病毒名>.<病毒后缀>
计算机病毒程序模块划分
感染模块
触发模块
破坏模块(表现模块)
主控模块
计算机病毒的生命周期
计算机病毒的传播机制
病毒入侵宿主程序的基本方式有两种: 替代方式和链接方式。
病毒的宿主程序可分为两类: 操作系统和应用程序。
交叉感染
寄生感染
没有入口点的感染
零长度感染
计算机病毒的触发机制
计算机病毒的破坏机制
DOS病毒
Win32 PE病毒
宏病毒
脚本病毒
HTML病毒
蠕虫
隐藏技术主要有:
多态技术中的密钥和解密代码都变化多端,多态技术将对解密代码进行等价指令替换、寄存器替换、插入垃圾指令或者随机调换指令的前后位置(有些指令的前后位置调换之后不影响代码功能)等变化,以产生功能相同但是代码截然不同的解密代码
多态引擎的组成:
它与其他的病毒相比,具有传染的主动性
计算机病毒是一段代码,能把自身加到其它程序包括操作系统上。它不能独立运行,需要由它的宿主程序运行来激活它”。
Eugene H. Spafford对蠕虫的定义:“计算机蠕虫可以独立运行,并能把自身的一个包含所有功能的版本传播到另外的计算机上”
↩︎
算机病毒一般依附于其他程序或文档,是能够自身复制,并且产生用户不知情或不希望、甚至恶意的操作的非正常程
计算机病毒的特点
以上列举的定义指的是狭义上的病毒。
但是随着黑客技术的发展,病毒、木马、蠕虫往往交叉在一起相互借鉴技术,因此人们经常说的计算机病毒往往是指广义上的病毒,它是一切恶意程序的统称。
计算机病毒的破坏性
计算机病毒引起的异常状况
我们针对狭义上的病毒,按照不同的标准对它进行分类。
按照计算机病毒攻击的对象或系统平台分类
按照计算病毒的攻击目标机类型分类:
按照计算机病毒的链接方式分类
按照计算机病毒的破坏情况分类
按传播媒介来分类
计算机病毒的命名
虽然每个反病毒公司的命名规则都不太一样,但大体都是采用一个统一的命名方法来命名的。一般格式为: <病毒前缀>.<病毒名>.<病毒后缀>
计算机病毒程序模块划分
感染模块
触发模块
破坏模块(表现模块)
主控模块
计算机病毒的生命周期
计算机病毒的传播机制
病毒入侵宿主程序的基本方式有两种: 替代方式和链接方式。
病毒的宿主程序可分为两类: 操作系统和应用程序。
交叉感染
寄生感染
没有入口点的感染
零长度感染
计算机病毒的触发机制
计算机病毒的破坏机制
DOS病毒
Win32 PE病毒
宏病毒
脚本病毒
HTML病毒
蠕虫
隐藏技术主要有:
多态技术中的密钥和解密代码都变化多端,多态技术将对解密代码进行等价指令替换、寄存器替换、插入垃圾指令或者随机调换指令的前后位置(有些指令的前后位置调换之后不影响代码功能)等变化,以产生功能相同但是代码截然不同的解密代码
多态引擎的组成:
↩︎
一个典型的特洛伊木马(程序)通常具有以下四个特点:
此外,木马还具有以下辅助型特点:
木马实现原理
本质上说,木马大多都是网络客户/服务(Client/Server)程序的组合。常由一个攻击者控制的客户端程序和一个运行在被控计算机端的服务端程序组成
当攻击者要利用“木马”进行网络入侵,一般都需完成如下环节:
植入技术
主动植入
本地安装
远程安装
被动植入
自动加载技术
在Windows系统中木马程序的自动加载技术主要有:
隐藏技术
连接技术
监控技术
木马的远程监控功能概括起来有以下几点:
木马的检测
木马的清除与善后
木马的防范
↩︎
它与其他的病毒相比,具有传染的主动性
计算机病毒是一段代码,能把自身加到其它程序包括操作系统上。它不能独立运行,需要由它的宿主程序运行来激活它”。
Eugene H. Spafford对蠕虫的定义:“计算机蠕虫可以独立运行,并能把自身的一个包含所有功能的版本传播到另外的计算机上”
↩︎
模糊测试:在很多随机的、不正常的输入上运行程序,找出程序对这些输入进行响应时的错误行为(如崩溃、挂起)
软件保护技术 ↩︎
目标:阻止对软件实施非授权的逆向分析
核心方法: 语义保留的程序变换
借鉴密码学算法的安全模型。目标:可证明安全性
然而,“虚拟黑盒”式的混淆器真的可以实现吗?
研究结论: 不可能
核心因素: 程序执行与Oracle访问有着本质区别
代码混淆的实际能力
较强的构造方法:基于3SAT问题 通过3SAT证明支配集是NPC问题 | 骑士的个人主页 (samjjx.github.io)
方法:
单向函数
利用分析技术弱点
利用神经网络
目标:
意义: 阻止对软件的破解
方法:
内省自检(introspection)
Oblivious Hashing 未察觉的哈希
新场景:对抗app重打包
↩︎
胎记”的实际含义
软件胎记的广义安全价值
构造形式分类
静态构造举例:基于JAVA的栈行为模式
动态构造1:基于执行路
动态构造2:基于程序内的系统调用
不懂呀
目标:在软件中嵌入用于标识其版权归属的秘密信息
软件水印的应用形式
软件水印的形式分类
静态构造举例:基本块重排序
静态构造举例:寄存器占用重分配
传统动态构造1:基于动态生成的图对象
传统动态构造2:基于执行路径上的分支行为
传统动态构造3:基于多线程的同步
传统动态构造的问题1:
一个特别的设计:基于抽象解释的水印
改进动态构造1:利用返回导向编程
改进动态构造2:利用代码混淆
传统动态构造的问题2:
改进动态构造3:利用神经网络
软件水印仍然存在的不足之处
↩︎
10-Web-sec.pdf
10-web-sec-companion-pu.pptx
看PPT吧
脆弱性: 任意编程语言实现的连接到SQL数据库的应用程序都可能存在
看PPT吧
脆弱性:用户输入, 可能包含可执行内容 (JavaScript, VBscript, ActiveX, …)被弹回到一个web页面
↩︎
看PPT吧
脆弱性: 任意编程语言实现的连接到SQL数据库的应用程序都可能存在
↩︎
看PPT吧
脆弱性:用户输入, 可能包含可执行内容 (JavaScript, VBscript, ActiveX, …)被弹回到一个web页面
↩︎
危险库函数如 system()
攻击者构造合适的参数(在栈上, 返回指令指针的上方)
函数返回,库函数得到执行
execve(“/bin/sh”)
甚至可以链接两个库函数调用
具体地
攻击者用一个溢出填充buffer:
当被攻击的函数返回时, 恢复(更改过的)ebp, 然后pop更改后的返回地址到eip, 从而开始执行库函数代码
因为库函数相信它已被调用, 故会将栈顶当前值(占位符)作为它自己栈帧的返回指令指针, 之上是参数
最终会在占位符位置的下方创建起一个新的栈帧 (对应于库函数的执行)
根据库函数参数类型以及库函数对参数的解释方式, 攻击者可能需要准确地知道参数地址以做溢出写
↩︎
木马实现原理
本质上说,木马大多都是网络客户/服务(Client/Server)程序的组合。常由一个攻击者控制的客户端程序和一个运行在被控计算机端的服务端程序组成
当攻击者要利用“木马”进行网络入侵,一般都需完成如下环节:
植入技术
主动植入
本地安装
远程安装
被动植入
自动加载技术
在Windows系统中木马程序的自动加载技术主要有:
隐藏技术
连接技术
监控技术
木马的远程监控功能概括起来有以下几点:
↩︎
我们针对狭义上的病毒,按照不同的标准对它进行分类。
按照计算机病毒攻击的对象或系统平台分类
按照计算病毒的攻击目标机类型分类:
按照计算机病毒的链接方式分类
按照计算机病毒的破坏情况分类
按传播媒介来分类
计算机病毒的命名
虽然每个反病毒公司的命名规则都不太一样,但大体都是采用一个统一的命名方法来命名的。一般格式为: <病毒前缀>.<病毒名>.<病毒后缀>
↩︎
隐藏技术主要有:
多态技术中的密钥和解密代码都变化多端,多态技术将对解密代码进行等价指令替换、寄存器替换、插入垃圾指令或者随机调换指令的前后位置(有些指令的前后位置调换之后不影响代码功能)等变化,以产生功能相同但是代码截然不同的解密代码
多态引擎的组成:
↩︎
攻击者: 位于终端,对终端计算资源有最高控制权限
攻击对象:安装在受控终端上的软件程序
攻击目的: 获悉、篡改软件的内部逻辑
↩︎
↩︎ ↩︎
System V AMD64 ABI 调用惯例 ↩︎ ↩︎
劫持全局偏移量表(GOT)中的函数指针, 被动态链接函数所使用 ↩︎ ↩︎