내가 리버싱 ctf를 하는건지 거참
피탄봄을 구현하기 위해 다음과 같은 과정을 생각하였다.
- 피탄 시 실행되어 잔기를 감소하도록 하는 함수를 찾는다.
- 피탄 유예 시간동안 실행되는 함수를 찾는다.
- 피탄 유예 시간을 저장하는 변수를 찾는다.
- 해당 변수값의 변화를 이용해 피탄 여부 판단 후 봄을 사용하도록 구현한다.
step 1
앞에서 주솟값 0069d4b8(+29d4b8 ) 의 메모리에는 잔기값이 들어간다는 것을 확인하였다. 따라서, 이 값을 수정하는 함수를 먼저 찾아보자.
친절하게도 치트엔진은 "여기 뭔가 쓰려고 오는 놈"들을 찾아주는 기능을 지원한다. 저걸 설정한 후 피탄당하면 다음과 같은 결과를 얻을 수 있다.
step 2
위의 결과에 따라, 00428DED 주소로 가면 아래 사진과 같이 00428DE6부터 살고있는 함수라는 것을 알 수 있다. 또한 바로 윗집에 사는 함수로부터 호출되는 것을 알 수 있다.
윗집 함수의 가장 처음으로 가면, 아래와 같이 더 높은 상사를 찾아갈 수 있다.
차례차례 쭉 올라온 결과 다음과 같은 함수를 찾을 수 있다.
이 함수는 unconditional이면서 피탄시 저 함수들을 호출하는 것을 보면, 게임을 하는 동안 계속해서 실행되는 함수라고 생각할 수 있다.
따라서, 우리는 +28C48 함수를 실행하는 조건은 바로 위에서 보이는, [eax+0x0009d8] 에 저장된 값이 0이 되는 것임을 알 수 있다.
step 3
이제 eax에 저장된 값을 찾으면 된다. 이를 위해, 다시 +28A8B에 breakpoint를 걸고 피탄당하면 다음과 같은 결과를 얻을 수 있다.
기대한대로 피탄 유예시간은 끝난 상태로, 피탄 애니메이션이 출력되기 전에 break가 걸렸다. 이때 eax값은 오른쪽 위의 registers에서 볼 수 있듯 006CA628로 나온다. 따라서, 0x6CA628+0x0009d8 = 0x6CB000 주소에 피탄 타이머가 있을 거라고 기대할 수 있다. 실제로 해당 주소로 가면 다음과 같다.
이 사진에서 볼 수 있듯, 현재 06이라는 값이 저장되어 있다.
실제 피탄을 당했을 때, 타이머가 줄어드는 것을 보면 맞는 것 같다. 이제 이 값을 이용하면 피탄봄을 만들 수 있다....!
step 4
그래서 해당 값이 6보다 작은 경우에 x를 누르도록 하면 될 것 같았으나.. 피탄봄 사용 이후 봄을 난사하는 것을 볼 수 있었다. 그 이유는 아래와 같이 유예 프레임이 '피탄 이후 봄 작동까지의 소요 프레임만큼 감소' 하기 때문에, 피탄봄에 성공하면 이후 6CB000의 값이 감소한다.
따라서 해당 부분을 반영해서, 다음과 같은 코드를 작성해 줄 수 있다.
import time
import keyboard
import pymem
import os
freq = 1/120 # Execution interval in seconds
def read_memory(pm, address):
return pm.read_int(address)
def press_and_hold(key):
keyboard.press(key)
def release_key(key):
keyboard.release(key)
def auto_control():
pm = pymem.Pymem("th6.exe")
frame = 0
remaind = 6
try:
while True:
player_state = read_memory(pm, 0x006CB000)
if player_state <remaind:
keyboard.press("x")
time.sleep(freq*6)
keyboard.release("x")
print("피탄!")
time.sleep(24*freq)
if player_state == 0 :
remaind = 6
else:
remaind = player_state
if frame == 0:
press_and_hold("z")
frame = (frame + 1) % 60
p1 = read_memory(pm, 0x006CAA68)
p2 = read_memory(pm, 0x006CB044)
print( p1 , p2)
if p2 < p1:
keyboard.press("left")
time.sleep(freq/2)
if frame == 0: print("[left]")
keyboard.release("left")
elif p2 > p1:
keyboard.press("right")
time.sleep(freq/2)
if frame == 0:print("[right]")
keyboard.release("right")
except Exception as e:
print(f"Memory read error: {e}")
finally:
release_key("z")
if __name__ == "__main__":
auto_control()
실행 영상은 다음과 같다.
'프로그래밍 > 동방프로젝트 봇 만들기' 카테고리의 다른 글
5. 탄막 위치 가져오기 (2) (0) | 2025.02.20 |
---|---|
4. 탄막 위치 가져오기 (1) (0) | 2025.02.20 |
2. 조작 기능 구현 (0) | 2025.02.16 |
1. 변수 위치 찾기(1) (0) | 2025.01.22 |
동방프로젝트 ai만들기 (0) | 2025.01.21 |