Season 1/기술 보안
[pwn.college] Assembly Crash Course - Level 4
작성자 - LRTK문제
ASMLevel4에 오신 것을 환영합니다.
==================================================
이 레벨에서는 어떤 레벨에서든 raw bytes를 stdin을 통해 이 프로그램에 전송하게 됩니다.
문제를 효율적으로 해결하기 위해, 먼저 실행하여 필요한 것이 무엇인지 확인한 다음 코드를 작성, 어셈블, 그리고 이 프로그램에 파이프하여 바이트를 전송하세요.
예를 들어, asm.S 파일에 어셈블리 코드를 작성한 경우, 다음과 같이 object file로 어셈블할 수 있습니다:
as -o asm.o asm.S
그런 다음 .text 섹션(코드)을 asm.bin 파일로 복사합니다.
objcopy -O binary --only-section=.text asm.o asm.bin
마지막으로 그것을 챌린지에 전송합니다:
cat ./asm.bin | /challenge/run
모든 것을 한 명령어로 실행할 수도 있습니다:
as -o asm.o asm.S && objcopy -O binary --only-section=.text ./asm.o ./asm.bin && cat ./asm.bin | /challenge/run
이 레벨에서는 레지스터와 작업하게 됩니다. 레지스터를 수정하거나 읽을 것을 요청받게 됩니다.
이제 각 run 전에 메모리의 일부 값이 동적으로 설정됩니다. 각 run마다 값이 변합니다. 이는 레지스터를 사용하여 어떠한 형식의 수식 연산이 필요하다는 것을 의미합니다. 레지스터가 미리 설정되어 있는지와 결과를 어디에 둘 것인지 알려드리겠습니다. 대부분의 경우, rax입니다.
x86에서의 division은 일반 수학에서의 것과는 좀 더 특별하다는 것을 기억하세요. 여기서의 수학은 integer math라고 불립니다. 이것은 모든 것이 정수 영역에 있다는 것을 의미합니다. 예를 들어:
10 / 3은 integer math에서 3입니다. 왜냐하면 3.33은 정수로 내림되기 때문입니다.
이 레벨에서 관련된 명령어들은 다음과 같습니다:
mov rax, reg1; div reg2
주의: 이 명령어를 사용하기 위해선, 먼저 나눌 피제수를 rax로 로드해야 합니다. 그런 다음 div reg2를 실행하면, 여기서 reg2는 divisor입니다. 이것은 다음과 같은 결과를 가져옵니다:
rax = rdi / rsi; rdx = remainder
quotient는 rax에, remainder는 rdx에 배치됩니다.
다음을 계산해주세요:
speed = distance / time, 여기서:
distance = rdi
time = rsi
위에서 주어진 조건으로 speed의 값을 rax에 배치해주세요.
코드를 준비하기 위해 다음을 설정하겠습니다:
rdi = 0x8a8
rsi = 0x52
어셈블리를 바이트 단위로 받을 수 있게 해주세요 (최대 0x1000 바이트):
/challenge/run에서 나온 방식대로 어셈블리 코드를 작성하지 않고, nasm으로 제출하도록 하겠음.
문제 풀이
[bits 64]
mov rax, rdi
div rsi
코드 분석
class ASMLevel4(ASMBase):
"""
Integer Division
"""
init_rdi = random.randint(1000, 10000)
init_rsi = random.randint(10, 100)
registers_use = True
dynamic_values = True
@property
def description(self):
return f"""
Recall division in x86 is more special than in normal math. Math in here is
called integer math. This means everything, as it is now, is in the realm
of whole looking numbers. As an example:
10 / 3 = 3 in integer math. Why? Because 3.33 gets rounded down to an integer.
The relevant instructions for this level are:
mov rax, reg1; div reg2
Notice: to use this instruction you need to first load rax with the desired register
you intended to be the divided. Then run div reg2, where reg2 is the divisor. This
results in:
rax = rdi / rsi; rdx = remainder
The quotient is placed in rax, the remainder is placed in rdx.
Please compute the following:
speed = distance / time, where:
distance = rdi
time = rsi
Place the value of speed into rax given the above.
We will now set the following in preparation for your code:
rdi = {hex(self.init_rdi)}
rsi = {hex(self.init_rsi)}
"""
def trace(self):
self.start()
expected = self.init_rdi // self.init_rsi
yield self.rax == expected, f"rax was expected to be {hex(expected)}, but instead was {hex(self.rax)}"
해당 코드들은 밑 레벨의 코드와 비슷하기 때문에 trace 메소드만 설명하도록 하겠음.
정답 검증 로직
def trace(self):
self.start()
expected = self.init_rdi // self.init_rsi
yield self.rax == expected, f"rax was expected to be {hex(expected)}, but instead was {hex(self.rax)}"
self.start
메소드를 호출하여 제출한 어셈블리 바이너리를 실행함.
동적 변수들을 나누기한 결과를 expected
변수에 삽입함.
이후, 제출한 어셈블리 바이너리 실행 후의 rax
레지스터 값과 expected
변수를 비교하여 같으면, (True, rax was expected to be [정답의 곱셈 결과], but instead was [제출한 곱셈 결과])
을 반환하게 됨.
'Season 1 > 기술 보안' 카테고리의 다른 글
C/S 프로그램 취약점 진단 환경 구축 (1) | 2023.10.31 |
---|---|
[pwn.college] Assembly Crash Course - Level 5 (0) | 2023.10.01 |
[pwn.college] Assembly Crash Course - Level 3 (0) | 2023.10.01 |
[pwn.college] Assembly Crash Course - Level 2 (0) | 2023.10.01 |
레드팀 인프라 구축(3) (그레이 공간 생성과 클라우드 설정) (0) | 2023.09.30 |
Contents