Merge branch 'master' of github.com:camera-2018/hdu-cs-wiki

This commit is contained in:
Plumbiu
2023-07-17 22:46:53 +08:00
2 changed files with 36 additions and 4 deletions

View File

@@ -3,6 +3,7 @@
### 栈溢出
#### 栈介绍
栈是一种典型的后进先出 (Last in First Out) 的数据结构,其操作主要有压栈 (push) 与出栈 (pop) 两种操作,如下图所示(维基百科)。两种操作都操作栈顶,当然,它也有栈底。
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/stack.png)
高级语言在运行时都会被转换为汇编程序,在汇编程序运行过程中,充分利用了栈这一数据结构。每个程序在运行时都有虚拟地址空间,其中某一部分就是该程序对应的栈,用于保存函数调用信息和局部变量。此外,常见的操作也是压栈与出栈。需要注意的是,**程序的栈是从进程地址空间的高地址向低地址增长的**。
@@ -17,11 +18,14 @@ int main()
printf("ch: %p, ch2: %p",ch,ch2);
}
```
对于如上程序,运行后可以发现`ch``a`的地址相差不大(`a``ch`的顺序不一定固定为`a`在前`ch`在后)
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/out1.PNG)
可以发现`ch``ch2`刚好差`8`个字节,也就是`ch`的长度。
`ch`只有`8`个字节,那么如果我们向`ch`中写入超过`8`个字节的数据呢?很显然,会从`ch`处发生溢出,写入到`ch2`的空间中,覆盖`ch2`的内容。
```C
#include<stdio.h>
int main()
@@ -32,6 +36,7 @@ int main()
printf("ch: %s, ch2: %s",ch,ch2);
}
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/out2.PNG)
这就是栈溢出的基本原理。
@@ -39,6 +44,7 @@ int main()
#### 栈溢出的基本利用
##### 0x0
对于以上程序,“栈溢出”带来的后果仅仅是修改了局部变量的值,会造成一些程序的逻辑错误:
```C
#include<stdio.h>
int main()
@@ -57,10 +63,15 @@ int main()
return 0;
}
```
如上代码所示如果我们想办法通过向input中输入过长的字符串覆盖掉password的内容我们就可以实现任意password“登录”。
那么能不能有一些更劲爆的手段呢?
> 以下内容涉及x86汇编语言知识
在C语言编译之后通常会产生汇编语言汇编语言的字节码可以直接在物理CPU上运行。而C语言函数调用会被编译为如下形式
```C
#include<stdio.h>
int add(int a,int b)
@@ -75,7 +86,7 @@ int main()
return 0;
}
```
```assembly
```asm
add:
endbr64
push rbp
@@ -117,18 +128,24 @@ mov eax, 0
leave
retn
```
可以看到其中使用`call`指令来调用`add`函数。那么该指令是如何工作的呢?其实`call`指令相当于`push next_loc;jmp loc`,通过将`call`指令下一行汇编的地址压栈的方式,等到函数调用完再取回,从而从`call`指令的下一行继续执行。由于栈地址从高向低生长,新调用的函数的局部变量生成在返回地址的上方(低地址处),因此如果我们在新函数中使用栈溢出来修改这一返回地址,如果将返回地址修改为某个函数的地址,就可以执行任意函数:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/stack2.png)
> 注意该图中使用32位的寄存器EBP、ESP、EIP实际原理一样的并且上方为高地址下方为低地址
在此给出一道题作为例子https://github.com/ctf-wiki/ctf-challenges/raw/master/pwn/stackoverflow/ret2text/bamboofox-ret2text/ret2text
32位的程序我们使用IDA来打开该题目查看反编译代码可以发现有非常明显的栈溢出
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/main.png)
由于第`8``gets`函数并没有检查输入的长度和`s`的长度,我们可以轻易地通过栈溢出来控制`main`函数的返回地址。而在程序中,存在另外一个函数`secure`,在该函数中有一个后门`system("/bin/sh")`,如果我们想办法执行该后门,就可以拿到目标机器的`shell`,从而控制目标计算机。
由于我们需要将返回地址在标准输入中输入待测程序,而返回地址拆分成小端序的字节后经常无法手动输入到待测程序中,所以此处我们使用`pwntools`这一`python`包来方便地进行攻击。
首先查看后门的地址:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/backdoor.png)
接着计算溢出长度这里我们使用gdb来调试程序图中的gdb安装了pwndbg插件该插件在pwn调试时比较好用
@@ -136,6 +153,9 @@ retn
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/gdb.png)
将断点打在`gets`函数前后,可以看到此时`esp`值为`0xffffcd80``ebp`值为`0xffffce08`,在 IDA 中我们又可以看到`s`相对于`esp`的偏移为`+1C`,此时我们即可计算`hex(0xffffcd80+0x1c-0xffffce08)=-0x6C`,即`s`相对于`ebp`的偏移为`0x6C`,由于在`main`函数的开头有`push ebp`的操作,所以将`0x6C`再加`4`,即可到达返回地址处:
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/s.png)
```python
from pwn import *
sh=process("./pwn")
@@ -144,29 +164,41 @@ exp+=p32(0x0804863A) # 4字节的返回地址
sh.sendline(exp)
sh.interactive() # 切换为手动交互模式
```
![](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/shell.png)
##### 0x1
通过上面的学习我们已经可以知道执行任意函数的办法但很多情况下对于攻击者来说程序中并没有可用的后门函数来达到攻击的目的因此我们需要一种手段来让程序执行任意代码任意汇编代码这样就可以最高效地进行攻击。ROPReturn Oriented Programming面向返回编程就是这样的一种技术在栈溢出的基础上通过在程序中寻找以retn结尾的小片段gadgets来改变某些寄存器、栈变量等的值再结合Linux下的系统调用我们就可以执行需要的任意代码。
ROP网上已有非常系统的资料在这里不做过多的叙述可参考ctf-wiki: https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/basic-rop/#ret2shellcode
### 格式化字符串
格式化字符串的利用思路来源于`printf`函数中的`%n`format标签该标签的作用和`%s``%d`等不同,是将已打印的字符串的长度返回到该标签对应的变量中。在正常情况下的使用不会出现什么问题:
```C
printf("abcd%n",&num);
//输出abcd,并且num的值为4
```
但如果在编写代码时忘记format字符串
```
```C
printf(something_want_print);
```
此时若攻击者可以自定义该字符串,就可以使用`%d``%p``%s`等打印栈上数据,或者`%n`来覆写栈上的数据,如果覆写了返回地址,就可以实现任意代码执行。
```C
char ch[20];
scanf("%s",ch);// 输入 %d%n%n%n%n%n
printf(ch);
```
## 漏洞挖掘技术
### 代码审计
代码审计分人工代码审计和自动化代码审计,人工审计由安全研究人员查看代码来发现漏洞,需要安全研究人员很高的研究经验,投入大量的人力。自动化代码审计目前的发展进度迅速,如由 Vidar-Team 毕业学长 LoRexxar 主导的开源项目Kunlun-Mhttps://github.com/LoRexxar/Kunlun-M
以及字节跳动公司开源的appsharkhttps://github.com/bytedance/appshark
### fuzz
fuzz是一种自动化测试手段通过一定的算法生成一定规律的随机的数据输入到程序中如果程序发生崩溃等异常即可知道此处可能有漏洞。比较著名的有[AFL](https://github.com/google/AFL)、[AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)、[libfuzzer](https://llvm.org/docs/LibFuzzer.html)、[honggfuzz](https://github.com/google/honggfuzz)等。

View File

@@ -54,7 +54,7 @@
大伙普遍性的都希望别人能给一条既定的道路,循规蹈矩的走完每一步仿佛就可以获得成功。每一次在计算机的提建议的会议上,我就会很奇怪,相当多的同学要求取消通识选修课,取消大物取消数电这种基础课,都要求要加一些更为流行的技术的课。
杭电有一个相当强的 CTF 战队 Vidar他们有十年的历史,深厚的积淀和超强的竞赛实力,但是近期却面对着无人可招的情况,因为大伙都去卷 JAVA 了。
杭电有一个相当强的计算机信息安全战队 Vidar他们有十年的历史,坐拥深厚的技术积淀和超强的竞赛实力,却面对着无人可招的情况,因为大伙都去卷 JAVA 了。
我认为之所以这样,是因为我们放弃了自己掌握自己发展,自己掌握自己命运的能力,我们放弃了如何去思考,而选择了变成无根的浮萍。如果知识利益最大化,那么我们培育出来的仅仅只是讨好企业的大学生,而大学教育本身,应该让我们寻找改变世界的力量。
@@ -65,7 +65,7 @@
不过问题很快暴露出来,我作为一个个体是渺小且无力的,而计算机科学的世界是宏伟且庞大的,凭借我一个人,我这辈子写完是没戏了。不过没关系,我在冥冥之中仿佛与战国时期翻手为云,覆手为雨的纵横学家有了心灵感应,是时候发动人民群众的力量了!
在新生到来前的那个暑假,我先后联系了杭电技术最强的几个技术团体的同学,一起参与到 WIKI 的完善工作去,尽可能补齐计算机技术的方方面面,甚至我们找到了杭电最受欢迎的老师之一韩健夫老师为我们写了一篇文章。随着 22 届新生的到来Wiki 已经初具雏形了,我们依靠新生的反馈,循序渐进地修改内容,并且鼓励新生可以根据自己的学习心得对 Wiki 进行修正。
在新生到来前的那个暑假,我先后联系了杭电技术最强的几个技术团体的同学,一起参与到 Wiki 的完善工作去,尽可能补齐计算机技术的方方面面,甚至我们找到了杭电最受欢迎的老师之一韩健夫老师为我们写了一篇文章。随着 22 届新生的到来Wiki 已经初具雏形了,我们依靠新生的反馈,循序渐进地修改内容,并且鼓励新生可以根据自己的学习心得对 Wiki 进行修正。
![超大规模的22届](https://pic-hdu-cs-wiki-1307923872.cos.ap-shanghai.myqcloud.com/dcf8ab68-4de4-4af2-898d-bd930f829f9f.jpg)