CTF-北理工暑期培训

B 站录制的视频

1 Python 快速入门

注释:

1
# hello

或:

1
2
3
"""
hello
"""

用更高精度的 floatdecimal 模块.

python 中没有 ++--

bin() 将十进制转换为二进制数:

1
bin(10)

输出则为:

1
0b1010

hex() 将十进制转换为十六进制数:

1
hex(10)

输出则为:

1
0xa

可连续比较:

1
1 < 2 < 3 # ture

字符串连接:

1
"Hello" + "World"

切片:

1
"This is a string"[0] # =>  "T"

format 来格式化:

1
2
3
"{} can be {}".format("strings", "interpolatred")
"{1} {1} can be {2}".format("strings", "interpolatred") # 重复使用
"{haha} {haha} can be {lala}".format(haha="strings", lala="interpolatred") # 命名

python 中的多行写法:

1
2
myvar = 10 \
+ 10

类型注解:

1
some_var:int = 5

创建列表:

1
list = []

可用 pop()append() 等方法.

删除任意元素:

1
del list[2]

是否包含:

1
1 in list

元组创建:

1
tup = (1, 2, 3)

其不可变.

在函数中使用全局变量, 用 global 关键字:

1
2
3
4
5
x = 5

def set GlobalX(num):
global x
print(x)

终端获取:

1
2
a = input()
b = input("input something...")

文件读写:

1
2
3
4
5
6
7
8
f = open("filepath", "r")
f.read()
f.close()
with open("filepath", 'r') as f:
f.readline()
f.readlines()

f = open("filepath", "r", encoding = 'gbk')

python 中, strings, tuples, numbers 都是不可更改的对象, 而 list, dict 都是可以修改的对象

关于新的内存空间的开辟:

2 古典密码学, 编码介绍

概念:

  • 明文(m, plaintext)
  • 密文(c, ciphertext)
  • 密钥(key)

三种加密算法:

  • Gen (Generate), 用算法来生成一个密钥
  • Enc (Encode), 加密算法
  • Dec (Decode), 解密算法

一个式子的含义:

1
Dec(Enc(m,k), k) = m

k 加密过的明文 m 可以通过 k 解密得到原来的明文.

四种攻击方式:

  • 唯密文攻击, 被攻击方向攻击方传送密文, 攻击方找共同点
  • 已知明文攻击, 被攻击方向攻击方传送明密文对, 攻击方分析
  • 选择明文攻击, 攻击方可以向被攻击方发送明文并得到返回的密文进行分析
  • 选择密文攻击, 攻击方可以向被攻击方发送密文并得到返回的明文进行分析

古典密码学

基于算法的安全性, 算法是未知的, 一旦被已知算法, 就容易被破解.

一般分为两种加密方式:

  • 字母的代换, 一一映射
  • 顺序的置换, 调换字串顺序

凯撒密码 & 移位密码

如:

A 被映射为 “移动4位” 的字符 E, 后面的都依次类推.

用穷举法解决.

仿射加密

每个字母对应一个数字 0 ~ 25, 得到一个 key (a,b):
$$
\displaylines
{
\begin{aligned}
Enc: c = a \cdot m + b\ mod\ 26 \
Dec: m = a^{-1} (c-b)\ mod 26
\end{aligned}
}
$$

单字母替换密码

用词频分析解决.

3 PWN, Linux 入门

PWN 指二进制漏洞挖掘 (Binary exploitation)

payload 就是要发送到目标服务器的数据.

4 Web 基础

url 格式:

域名结构:

也就是从后往前解析.

OSI 体系结构可能有些过时, 大部分用 TCP/IP 的体系结构.

注意 TCP 的三次握手和四次挥手, 这里的次数指的是传送的包的数量.

好玩的状态码网站

一些工具:

  • AntSword, 中国蚁剑
  • BurpSuite
  • Sqlmap
  • hackbar

一些套路:

  • F12 查看 HTML 源码
  • Web 源码泄漏
    • vim 源码泄漏, 利用如 /.index.php.swp 文件, vim -r index.php
  • 查看 http 数据包 BurpSuite 看请求/响应首部
  • 修改 http 请求头
    • Method
    • User-Agent
    • Referer
    • X-Forwarded-For
    • Cookie

5 Pwn 汇编入门

程序编译与链接

过程:

16 位的 CPU 只能确定数据总线是 16 位的.

BP 寄存器是用来定位栈帧的基底.

Pwn 主要要覆写的内容就是 SP, BPIP.

6 Web 爬虫入门

抓取有规律的网页.

重复处理网络工作.

与网站自动交互.

这里用 python 编写爬虫脚本, 可查看官方文档

几个推荐的平台:

  • GeakforGeak

中文网站的编码可能用 gbk 或者 gb1312.

登录时都是通过 cookie 来判断的.

常用 Get 和 Post 两种请求方法.

网页是文档树的结构.

CTF 中常用的 Python 库:

  • Web
    • Requests
    • Socket
  • Blast
    • itertools
    • Multiprocess
  • Crypto
    • gmpy2
    • PyCrypto/PyCryptodome
  • Pwn
    • Pwntools

关于爬虫的合法性

基本每个网站都有 robots.txt 文件, 一般位于网站的根目录下. 如 http://baidu.com/robots.txt

文件内容如:

1
2
3
User-agent: *
Disallow: /private/
Disallow: /admin/

做 Web 题时, 注意 .zip, .swap.bak 文件. 有时也会放在 robots.txt 里面.

7 Pwn 实战

步骤:

收集信息, 如小段 gagets 的地址, glibc 的版本.

查看保护用 checksec, 了解程序逻辑一般用 IDA.

一般存在栈溢出的一般是 gets, getchar 等函数.

可能存在内存地址泄漏的一般有 printf.

辅助信息一般有可链接的 elf 文件或版本号.

很多工具都依赖 python. 一般用 Pwntools 模块, 其包含了大量需要使用的模块, 包括 pwn, pwnlib 等.

安装 pwntools 的开发版:

1
pip install --editable pwntools

checksec 的输出如:

其中:

  • Arch(Architecture, 架构):指定二进制文件编译的目标架构(Architecture),例如x86、x64、ARM等。

  • RELRO(RElocation Read-Only, 可重定位只读性):指定二进制文件中重定位表(Relocation Table)的只读性。RELRO分为三种级别:

    • No RelRO:重定位表无保护,可以被恶意攻击者修改。
    • Partial RelRO:只读保护了重定位表的一部分,但是还存在一部分是可写的。
    • Full RelRO:完全只读保护了重定位表,使得攻击者无法修改其中的地址。
  • Stack(栈):指定二进制文件中的栈保护,包括以下两个方面:

    • Canary:栈中插入了一个随机值作为标记,用于检测缓冲区溢出等攻击。
    • NX:栈不可执行,防止栈上的数据被当做代码执行。
  • NX(Non-eXecutable, 不可执行):指定二进制文件数据段(Data Segment)的可执行性。NX可以防止攻击者执行已经存在于二进制文件中的恶意代码。

  • PIE(Position Independent Executable, 位置独立执行):指定二进制文件是否启用了地址随机化。启用PIE后,二进制文件会在每次运行时随机选择一个内存位置,使得攻击者很难通过静态分析获取二进制文件的内存地址,从而增加攻击的难度。

python pwn 模块的使用如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *
context(os='linux', arch='amd64', bits=64)
My_ShellCode = """
mov rbx, 0x68732f6e69622f
push rbx
push rsp
pop rdi
xor esi, esi
xor edx, edx
push 0x3b
pop rax
syscall
"""
payload1 = asm(My_ShellCode)

payload1 中是生成的一段二进制数据, 可用于发送到服务器.

关于 IDA Pro (Interactive DisAssembler Professional)

  • 最主要的静态反汇编/反编译工具
  • 提供强大的逆向功能

IDA-view 一般是主界面, 其有两种界面, 一种是 graph, 一种是纯文本, 可以用右键切换.

按 F5 可以反编译, 从汇编中提取出 C 源程序逻辑.

Hex view 中可以查看二进制源码.

Imports 是导入表, 其包含一些导入的符号信息.

Exports 是导出符号表, 有一些导出符号信息.

Strings window 上有连续字符串的地址信息.

最左边是一个函数栏, 包含定义的函数信息. (一般用得比较少)

界面如:

在顶部 View -> Open subview -> Segment registers 比较有用, 可以查看段表.

关于 gdb 以及其 pwndbg (pwn debug) 插件

其为动态调试. 利用其汇编级别的调试.

常见指令:

汇编级别的调试指令如 si (step instruction)

在指定地址下断点: b *0x565561c0

其他的 pwn 工具

  • LibcSearcher
  • one_gadget
  • ropper
  • patchif

注意修改 glibc 的地址.

关于 stack overflow

有栈上溢, 也有栈下溢.

一个游戏 SHENZHEN I/O

栈空间中一般放调用相关的内容.

如果要看栈的具体分段, 可以用 gdbvmmap 命令查看.

栈的大致内容:

一个栈帧主要包括的内容有:

  • 返回地址, 参数
  • 寄存器值
  • 局部变量

注意上一个栈帧的 bp 的值.

一般一个栈帧的顶部和底部的数据:

  • 底部, 存放上一个栈帧的 bp 的值
  • 顶部, 存放想要跳转的地址的值 return address

8 Pwn 程序装载细节与栈帧结构

栈顶就是当前栈帧的顶部.

ELF 文件类型:

  • Relocatable File (*.o), 可重定位文件, 用于链接
  • Executable File (*), 可执行文件
  • Shared Object File (*.so), 共享目标文件, 用于动态链接

ELF 文件结构:

Sections (节视图) 存储在磁盘中, Segments (段视图) 存储在内存中.

不同的 Sections 根据它们对权限的不同要求被装载进不同的 Segments 中.

虚拟地址空间方便不连续地分配内存.

函数调用约定

形如 __cdecl, __stdcall, __fastcall.

__cdecl 要求调用这清除栈帧. 即 push 多少个进来, 就 pop 多少个出去. 也就允许了可变参数列表的存在. (注意这里是 调用者 )

可参考的博客1

可参考的博客2

9 Web php入门及序列化与反序列化

PHP 的全称为 Pre Hypertext Processor. 其可以嵌入到 HTML 中.

如:

1
2
3
4
<?php
$str = 'Hello World';
echo $str;
?>

其功能包括:

  • 生成动态页面内容
  • 创建, 打开, 读取, 写入, 关闭服务器上的文件
  • 收集表单数据
  • 发送和接收 cookies
  • 添加, 删除, 修改数据库中的数据
  • 限制用户访问网站上的一些页面
  • 加密数据
    等.

可查看其 官方文档1 , 官方文档2

搭建 php 环境

安装一些 Web 服务器软件, 如 Apache, Nginx, Tomcat, IIS 等.

配置服务器和防火墙.

也可参考 WAMP(Windows Apache MySQL PHP)/LAMP(Linux Apache MySQL PHPj) 等.

基础语法

  • 可放在文档中的任意位置
  • <?php 开始, 以 ?> 结束, 如:
    1
    2
    3
    4
    5
    <?php
    // $str = 'Hello World';
    // echo $str;
    // php codes
    ?>
  • PHP 文件通常包含 HTML 标签和一些 PHP 脚本代码

一个 index.php 的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

<?php
$str = 'Hello World'
echo $str;
?>

</body>


php 的变量以 $ 开头.

有时题目禁掉了 A-z0-9 的变量名, 可以用 _ 下划线作为变量名使用.

变量的作用域

  • local

  • global

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    $x = 3;
    $y = 5;
    function myFunction() {
    global $x, $y; // use the outer variable
    $z = $x + $y;
    echo $z;
    }
    ?>
  • static

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    function testStatic() {
    static $val = 1;
    echo $val;
    $val++
    }

    testStatic();
    testStatic();
    testStatic();
    ?>
  • parameter

echoprint 的区别

  • echo 可以输出一个或多个字符串
  • print 只允许输出一个字符串, 返回值总是 1
1
2
3
4
<?php
echo 'GG', '<br>';
print 'GG', '<br>'
?>

一种输出多行字符串的方式

1
2
3
4
5
6
7
8
9
10
<?php
function getHtml1() {
echo <<<hello
<html>
<head><title>Title</title></head>
<body>Content</body>
</html>
hello
}
?>

两种比较

  • 松散比较, 用 == 进行比较, 只比较值, 不比较类型
  • 严格比较, 用 === 进行比较, 比较值的同时也比较类型

序列化和反序列化

serialize() 将一个对象转换成一个字符串.

unserialize() 将字符串还原为一个对象.

在 PHP 应用中, 序列化和反序列化一般用于做缓存, 如 session, cookie 缓存.

序列化时常用的方法:

就是定义这些方法后, 会在特定的场景中被自动调用.

构造 POP (Property-Oriented Programing) 链

利用原有的代码 (控制代码流程) 拼凑出自己需要的功能.

利用 Autoloading

采用 Autoloading 来自动加载文件列表, 自动加载一些类, 如:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
function __autoload($class_name) {
$name = strtolower($class_name);
$path = "../includes/($name).php";

if (file_exists($path)) {
require_once($path);

} else {
die("the file {$class_name} could not be found");
}
}
?>

可通过此机制上传自己的 php 文件.

在 php 版本 7.2.0 之后, 使用 __autoload() 会 warning, 取而代之的是 sql_autoload_register().

库的安装

PHP 用 Composer 来管理依赖.

其默认从 Packagist 下载依赖库.

漏洞利用思路:

  • 从可能存在漏洞的依赖库文件入手
  • 从应用的代码框架的逻辑上入手
  • 从 PHP 语言本身漏洞入手

构造漏洞的常见方法:

  1. 在依赖库中全局搜索 __wakeup()__destruct()
  2. 查看 composer.json 文件, 其标明了应用需要的库, 可用来寻找 POP 组建
  3. 查找流行库的类, 查看是否存在可以利用的组件
  4. 手动验证, 构建 POP 链, 利用易受攻击的方式部署应用程序和 POP 组件, 通过自动加载类来生成 poc 及测试漏洞.

一个示例

__toString 触发漏洞.

10 Pwn 栈溢出实战基础

X86 架构常见的调用约定:

  • stdcall
  • cdecl
  • fastcall

(前两者把参数压入栈中进行传输, 后者压入寄存器)

cdecl 调用约定的流程 (32 位)

  • 参数全部存储在栈中
  • 参数自右向左入栈
  • 由调用者清理栈区 (参数部分)
  • eax 保存函数返回值

64 位的有一些区别, 前六个参数存储在寄存器中. 从第一个到第六个分别存储在: rdi, rsi, rdx, rcx, r8, r9

这里也要关注传入参数的大小, 4 字节存储在如 edi 中, 而 8 字节才是 rdi 中.

其余的参数仍然存放在栈中, 还是从右向左传. 如:

如:

(这里的栈帧是 32 位的)

局部变量在自己当前的栈帧中, 而传入的参数在其他栈帧 (如上一个栈帧) 中.

leave 指令分为两个步骤:

  1. esp = ebp, 也就是删除栈帧
  2. pop ebp, 获取上一个栈帧的基址

区分 lea (Load Effective Address) 指令: 其作用是将一个有效地址(Effective Address)加载到指定的寄存器中,而不是加载内存中的数据. 如:

1
LEA EBX, DWORD PTR [ESI+20]

这里的ESI寄存器包含数组的基地址,20是第5个元素的偏移量。因此,LEA指令计算出该元素的地址,并将该地址加载到EBX寄存器中。

注意 , 栈帧的开辟操作存在于函数调用时, 每当一个函数被调用时,都会创建一个新的栈帧来存储该函数的局部变量、函数参数和其他执行上下文信息。这个过程被称为栈帧开辟(stack frame setup).

栈溢出

栈溢出 (stack overflow) 属于缓冲出溢出 (buffer overflow) 的一个大类, 还有:

  • Heap Overflow
  • Others

缓冲区溢出的定义: 编写程序时没有考虑或错误设置用户输入长度, 导致用户向缓冲区输入长度超过接收变量长度, 从而覆盖到其他正常数据, 破坏栈帧结构.

造成缓冲区溢出的主要函数有:

  • gets, 读到换行为止, 没有长度限制
  • read
  • scanf

如:

  • Read 读取长度超过 buf 长度:
    1
    2
    3
    4
    void foo() {
    char s[0x10];
    read(STDIN_FILENO, s, 0x30);
    }

示例 python 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import * # 导入名称空间

context(log_level='debug', os='linux', arch='i386', bits=32) # 设置上下文

p = process(["./buffer_overflow"]) # 运行文件

if __name__ == "__main__":
gdb.attach(p, 'b foo') # 第一个参数是要将哪一个程序和 gdb 连接, 第二个参数是 gdb 运行的指令
backdoor = 0x08049172
payload = b"a" * 0x18 + b'b * 4 + p32(backdoor) # p32 函数是转为 32 位的字节串

p.sendline(payload) # 发送构造好的字节数据

p.interactivc()

可以在符号表中找对应的符号然后获取其地址.

Shellcode

Shellcode 指能使程序调用 shell 的一段代码(通常为汇编级别/机器码), 一旦某种 Shellcode 被执行, 就能够拿到目标机器的控制权限, 从而获取 flag.

一般 Shellcode 不会特别长, 且运行 Shellcode 的环境一般不具有运行外部库函数的能力.

如:

  • execve("/bin/sh", 0, 0)
  • 触发中断 int 0x80 / syscall, 此时需要在中断之前设置一些条件, 如要调用 execve, 需要设置一些寄存器值:

示例汇编:

1
2
3
4
5
6
7
8
9
10
11
12
13
;  nasm -f elf32 first.asm
; ld -m elf_i386 -o getShell first.o
;; objdump -d getShell

global _start
_start:
push "/sh"
push "/bin"
mov ebx, esp
xor edx, edx
xor ecx, ecx
mov al, 0xb
int 0x80

查看完整的 syscall 调用表

漏洞特征:

  • 有一个可读可写可执行段, 这个漏洞在 checksec 扫描器中会显示为 RWX segments.
  • 调用某处可控内存空间代码

利用方式:

  • 在可控空间处注入 Shellcode
  • 使程序执行流转向该处

可参考的 shell code

11 Web sql 注入基础

SQL, Structured Query Language, 用于存储数据以及查询, 更新和管理 关系数据库.

关系数据库指数据库中的每一个元素都可以用一列和一行进行定位.

SQL 是解释型语言 (用解释器, 而不是编译器)

SQL 注入指用户插入了额外的 SQL 语句来执行, 实现无账号登录, 篡改数据库等攻击.

SQL 注入的完整视频讲解

MySQL 本身实际上只是一个 SQL 接口, 它的内部还包含了多种数据引擎, 常用的包括 InnoDB, MyISAM.

一些绕过手法, 比如 &, ||, ^ 被禁掉了, 可以尝试 and, or, xor.

一些词被禁掉了, 可以尝试用 ascii() 等编码函数, 传送字母后拼接.

常用 SQL 语句和操作:

注意不同的 sql 版本有不同的关键字.

注入条件:

  • 用户可控输入 (要有对话框让用户输入)
  • 输入内容与数据库交互 (输入的内容)

简单的示例 – 闭合 (即利用双引号, 单引号的闭合构造一直为真的语句, 主要是为了让自己能够操作后端语句), 如:

1
2
3
4
<?php
$id = $_GET['id']
$sql = "select * from data where id = " . $id;
?>

构造如 select * from data where id = 1 or 1 = 1, 就能输出所有数据.

有时常见的注释符, 以及单引号会被 ban 掉, 此时可用的注释符有:

  • %23
  • --+
  • ;%00
  • `

示例:

1
2
3
4
<?php
$id = $_GET['id']
$sql = "SELECT * FROM data WHERE username = '" . $username . "' and password = '" . $password . "' ";
?>

在这个语句中, $username$password 变量两侧都有一对单引号, 此时如果输入 \, 则可以转义一个单引号, 如:

1
select * from data where username = '\' and password = '';

此时第一个闭合为 and password = 这个值, 最后一个单引号多出来了, 不处理则会报错, 此时用 ;%00 来把这个单引号注释掉, 并在前面加上自己的操作:

1
select * from data where username = '\' and password = ' or 1 = 1 ;%00';

此时 or 1 = 1 则可以运行.

联合查询注入 – Order by 探测注入点

利用 union 联合查询, 注意 联合查询 的基本要求:

  1. 查询列数必须一致
  2. 查询语句的查询的各列类型, 顺序最好一致

联合查询的步骤:

  1. 闭合
  2. 判断字段数 (用 Order by)

如:

1
select * from data where id = '1' order by 1;

接着试:

1
select * from data where id = '1' order by 2;

直到报错, 就能知道有多少行数据.

一般情况下, 会限制返回数据的行数 (用了 limit 语句等). 此时需要判断结果输出的位置, 比如原本只输出第一行, 得知之后, 就可以让需要的数据输出在第一行.

information_schema 这个数据库中的 TABLECOLUMNS 表中分别提供了数据库中的表的信息和列的信息.

通过联合查询注入爆库, 爆表, 爆列的方法:

爆库名:

  • union select 1,2,database()

爆表名:

  • union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = database()
  • union select 1,2,group_concat(table_name) from information_schema.columns where table_schema = database()

爆 Column 名:

  • union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'

group_concat 函数将所有数据连接为一条数据, 从而可以显示出来.

一个用 php 进行攻击的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$con = mysql_connect("localhost", "root", "Xiao") or die();
mysql_select_db("security");
$ID = $_GET['id'];
if ($ID >= 9)
die();

$sql = "select * from users where id=$ID";
$sql = strtolower($sql);

echo "sql operations: ".$sql."<br>";
$res = mysql_query($sql);

while ($rows = mysql_fetch_array($res)) {
echo "ID:".$rows['id']."<br>";
echo "username:".$rows['username']."<br>";
echo "passwd:".$rows['passwd']."<br>";
}

mysql_close($con);
?>

使用工具探测 sql 注入漏洞

使用 sqlmap, 可用 pip 下载.

常用操作:

简单的靶场搭建教程

SQL 注入天书

12 Pwn Ret2xx & ROP链构造

介绍可执行文件的保护措施 – NX.

NX, No Execute bit (禁止执行位), 是应用在 CPU 上的安全技术, 其支持了操作系统级别的 DEP (Data Execution Prevention).

在应用了 NX 的系统上 (如果可执行文件开启保护), 会把内存中的区域分类为只供存储指令和只供存储数据两种, NX bit 被标记在内存分页使用的页表索引上, 如果置 1, 则该页内存数据不允许被执行, 即把所有内容作为数据处理.

其杜绝了一部分缓冲区攻击.

同样可以用 checksec 工具来查看保护措施.

ROP 介绍

ROP (Return-Oriented Programming), 允许攻击者在开启了栈不可执行等安全保护技术的情况下, 执行恶意代码.

核心思想是通过栈溢出等方式, 改写栈上的控制信息, 以控制调用栈, 劫持程序控制流并执行一些针对性的命令序列 (gadgets, 指一些以 ret 结尾的小段汇编指令, 他们的执行通过 ret 语句和栈上控制的地址相连, 构成一条 ROP 链, 链的功能是设置寄存器值, 泄露信息, 调用函数等)

Ret2xx, 指构造 ROP 链的几种方法

Ret2Text, 一般条件是, gadget 存在于 Text 中, 或存在于 ELF 文件中, 其同样通过将返回地址改写为能执行某些特定功能的 gadget 地址来构造 ROP 链.

可以用 ropperpwntools (ELF class) 工具辅助, 用于查找 ELF 文件中的 gadgets.

在 64 位中, 由于 rdi 是传入的第一个参数, 因此将 rdi 的值设置为 /bin/sh.

对于某些 ELF 文件不含有 backdoor 函数的情况, 此时需要借助 PLT 表 (前提是这个 ELF 文件引用过 system 函数, 此时 PLT 表中才存在这个条目)

如:

1
2
3
4
5
6
7
backdoor = e.plt['system']
bin_sh = next(e.search(b'/bin/sh'))
prdi = 0x4011eb
payload = b'a' * 0x10 + b'b' + p64(prdi) + p64 =(bin_sh) + p64(backdoor)
sl(payload)

p.interactive()

Ret2syscall, 一般条件是, 存在静态链接的可执行文件, 因此指令非常多, 也提供了许多 gadget.

最核心的 gadget 为 syscall(int 0x80) (没有 system 函数可调用时就利用系统中断)

一般可以用 file 命令查看一个文件是否有静态链接 (statically linked)cnss{Welc0me_to_SA_W0r1d}.

可以利用的辅助工具: ROPgadget.

最常见的为 Ret2libc

PLT 表和 GOT 表介绍

  • GOT, Global Offset Table, 全局偏移表, 包含所有需要动态链接的外部函数的地址 (在第一次执行后)
  • PLT, Procedure Link Table, 过程链接表, 包含调用外部函数的跳转指令 (跳转到 GOT 表中), 以及初始化外部调用指令

Linux 虚拟内存分段映射中, 一般会分出三个相关的段:

  • .plt, 放跳转指令
  • .got.plt
  • .got, 放地址

调用一个函数, 就需要跳转, 因此需要 plt 表中的值, 同时需要函数的地址, 因此也需要 got 表中的值.

若需要中找到一个 system 函数在内存中的地址, 需要知道两个东西:

  • system 函数在 glibc 中的地址
  • glibc 被链接到内存空间中的基址, 一般未知, 需要手段来泄漏.

13 Web XSS 入门

XSS, Cross Site Scripting, 向网页中注入恶意代码, 导致用户浏览器在加载网页, 渲染 HTML 文档时就会执行攻击者的代码.

按照漏洞成因, 一般分类为:

  • 反射型
  • 存储型
  • DOM 型

或按照输出点位置分为:

  • 输出在 HTML 属性中
  • 输出在 CSS 代码中
  • 输出在 JavaScript 代码中

反射型 XSS

原型如:

1
2
3
4
<?
echo 'your input:' . $_GET['input']

?>

攻击者提交如:

1
http://example.com/xss.php?<script>alert(/xss/)</script>

则服务端解析后会通过 echo 语句将攻击者输入的内容完整的输出到 HTTP 响应, 从而导致弹窗.

储存型 XSS

也就是说用户点击页面上的链接而遇害 (链接即 JavaScript 代码, 存储在服务器中)

DOM 型 XSS

其不需要服务器解析, 而通过浏览器解析.

输出在 HTML 属性中

这个和 SQL 注入类似:

输出在 CSS 代码中

输出在 JavaScript 代码中

Payload 和 Bypass

特定标签过滤, 事件过滤

完整的事件属性参考

绕过方法如:

  1. 用 JavaScript 伪协议
  2. HTML5 新属性
  3. 对事件属性进行 Fuzz 测试

铭感关键字过滤

绕过方法如:

  • 字符串拼接
  • 编码
  • svg 标签
  • 提交绕过

DVWA 平台默认账号 admin, 默认密码 password

14 Pwn ELF保护机制与绕过、高级栈溢出技巧

ASLR 介绍

ASLR, Address Space Layout Randomization, 地址空间配置随机化.

将可执行文件, 共享库, 栈, 堆的基址随机化. 用于防范明确地址的内存破坏攻击.

可以用 地址泄漏 来应对.

该保护措施由操作系统配置为开或者不开, 而不是写在 ELF 文件头.

PIE 介绍

PIE, Position-independent executable (地址无关代码/可执行文件), 无论文件被加载进内存空间的什么地址中, 程序都能正常运行. (程序中不会写死地址, 是动态的)

就像共享库文件动态链接到内存中, PIE 使其能正确处理外部引用.

其特点是, 整个 ELF 文件都会被装载进一个 随机偏移 的连续的内存空间里, 只是 基址 变成了未知的, 其他如偏移都是相同的.


CTF-北理工暑期培训
http://example.com/2023/07/02/CTF-北理工暑期培训/
作者
Jie
发布于
2023年7月2日
许可协议