오늘도 어김없이 시작하는 피시의 강좌입니다.
만약 내용에서 모르거나 이해가 안가는 부분은 꼭 댓글로 질문해주세요.
어디까지 아시는지 어딜 놓치고 갔는지 저도 누군가에게 들어야 알 수 있으니까요.
자, 오늘은 디버거로 들어가기전에 ATCode 의 기능들에 대해서 약간의 설명과
주의할점, 착각하는점, 실수하는점 등을 조금 짚어보고 가려고 합니다.
조그마한 예제도 준비했으니 너무 겁먹지 말고 천천히 따라와주세요? ^-^
1. 공통 옵션
이 부분은 가장 기본적인 설정이 있습니다.
1-1. 한글 폰트 로드
게임 내에 폰트를 강제로 한글로 변경합니다.
바를 왼쪽에서 오른쪽으로 움직이면 아래와 같이 변합니다.
- 한글 폰트를 로드하지 않습니다.
말 그대로 아무런 동작을 하지 않습니다.
- 문자 출력 함수에 한글폰트를 적용합니다.
보통은 이 부분까지 당겨서 사용합니다.
폰트로드 시도시에만 변경됩니다.
(GlyphOutline, TextOut, ExtTextOut, DrawText 등 텍스트 출력이 끝나면 원래 폰트로 복구시킵니다.)
- 한글 폰트 적용 후 복구하지 않습니다.
두번째 기능에서 원래 폰트로 복구작업만 하지 않습니다.
폰트로드 시도시에만 변경됩니다.
다섯번째 것은 현 사항을 포함합니다.
(솔직히 폰트를 실시간으로 검사하는 게임이 있을지 모르겠지만 만약 있다면야 여기까지는 땡겨야 겠지요.)
- 폰트 로드 시 한글 폰트를 로드해줍니다.
아스키를 유니코드 문자로 혹은 유니코드를 아스키로 변환하는 과정을 거치는 경우
즉, WideCharToMultiByte, MultiByteToWideChar 강제로 한글 코드 셋으로 변환합니다.
변환 시도시에만 변경됩니다.
다섯번째 것은 현 사항을 포함합니다.
CreateFontW 는 원래 로드작업을 기반으로 이행합니다.
(유니코드 출력의 경우 확인을 하고 싶을때 요부분을 여기까지 땡겨보면 폰트의 일부가 변하거나 물음표로 변하거나 문자가 반각으로 바뀌거나 아주 일부 글자가 한글로 보이는 반응을 볼 수 있습니다.)
- 프로그램의 모든 폰트를 한글로 바꿉니다.
세번째와 네번째를 같이 적용하되
네번째의 CreateFontW는 새로 생성하여 적용합니다.
[다소 내용이 누락된게 있을 수 있습니다]
보통 게임이 텍스트 출력전이나 출력준비를 할때 폰트로드 작업을 하고
아스키로 된 스크립을 유니코드로 변환하여 출력하는 경우하 그 반대에도 저런 함수를 거치게 됩니다.
그.러.나 반응이 전혀 듣지 않는 예외가 존재합니다. (이때 반응이란 글이 깨지는 현상을 말합니다.)
* 폰트로드를 게임이 처음 실행되는 맨 초기에만 딱 한번 동작하고 더이상 폰트를 로드하지 않을때
(폰트로드 함수를 지나처야만 변경이 되는데 게임 진행중에는 더이상 로드를 한번도 하지 않는 경우에는 작동하지 않지요)
* 변환작업따위 없이 바로 출력속행인 유니코드문자일때
(스크립이 유니코드인데다가 그걸 제대로된 문자인지 확인하는걸 자기들이 직접 만든 함수로 확인 후 출력하러 속공으로 보낼때는 마찬가지로 함수를 거치지 못하게 됩니다)
* 위 두개 사항이 겹쳐있을때
(필히 실행파일을 직접 손봐야 해결이 됩니다.)
* 변환작업을 다른 방법으로 사용하고 있을때
(자체폰트에서 주로 사용되는 방식이네요. 폰트가 매핑될 위치 선정으로 랜덤 주소를 얻기 위해 사용하거나 일어 전반각을 확인할때 사용합니다. 반각일때는 예외로 보내버리거나 합니다. 예외의 반응으로는 글이 전부 안나오거나 다른 특정 색이나 네모 같은 이상한 한개의 문자로만 모든글이 나와버릴때 입니다.)
1-1-1. 글꼴 및 폰트 크기 고정
말그대로 설정된 폰트를 로드해줍니다.
폰트 로드 바를 두번째 이상에 놓았을 때만 동작합니다.
폰트 크기 고정은 해당 글꼴에서 선택한 크기로 전부 고정시킵니다.
(글자가 너무 크게 나와버리거나 한다면 이부분을 사용해서 작게 고정해주세요.)
주의할 점으로는 폰트 크기 고정의 경우 미리 선언한 크기가 존재하기 때문에
충돌이 일어나 뒤죽박죽 폰트크기가 엉키게 됩니다.
따라서, 크기 설정을 하고나면 바로가기를 만들어 게임 종료 후 바로가기로 새로켜주시거나
게임을 종료하여 새로키신후 코드입력시 최초 1회만 폰트 크기 고정을 해주세요.
(이미 폰트로드 함수 지나간 글을 출력하고 나서 크기 고정 하면 적용이 이상하다는거 기억해두세요. ^-^)
(그러고 보니 01화 강좌 영상에서 마지막 부분에 크기 고정 때문에 게임을 여러번 실행한 이유가 이 때문입니다.)
1-2. 한글을 일본 문자셋으로 변환
먼저 "한글 폰트 로드" 바는 말그대로 일어폰트가 아닌 한글 폰트를 로드시켜주는 것입니다.
일어 폰트에는 한글이 없기 때문에 한글이 들어있는 굴림체라든가 궁서체 등으로 로드 했을뿐입니다.
그래서 제대로된 한글을 출력하기 위해서는 문자셋도 변경해야합니다.
문자셋을 변경하지 않으면 한글이 아닌 일어 반각으로만 나오거나
유니코드의 경우에는 한글셋으로 변경을 하지 않았기 때문에 한글을 볼 수가 없게 됩니다.
따라서, 이 부분은 별로 특별하지 않는한 무조건 체크하게 됩니다.
역시 예외가 있습니다.
노어플로 실행하여 그냥 진행해보았을때 "궭갏긁..."과 같은 깨진 문자로 이미 게임내에서 한글 출력이 되고 있다면
체크 할 필요가 없습니다. 이유는 문자셋을 윈도우 언어로케일에서 디폴트 값인 한글을 받아왔기 때문입니다.
(보통은 어플 실행이기 때문에 무조건 체크하라는 소리입니다.)
1-3. 타이틀 및 메뉴 번역
윈도우 창에 메세지를 띄우는건 보통 한글자씩이 아닌 통째로 올립니다.
따라서 이 부분들만 아랄이 가져와서 번역후 보내게 됩니다.
저는 별로 추천하지도 않고 왠만해서는 사용하지도 않는 기능입니다.
버그도 있구요.
(바로가기로 만들고 실행하면 이 기능이 동작하지 않습니다. 새로 다시 활성화해야 먹히더군요.)
제가 우연히 사용할때는 가끔 메뉴가 일어로 되있을때만 잠시켜서 사용하고 안쓸때는 꺼놓습니다.
1-4. 후킹주소 추가
자신이 찾아낸 대사가 지나가는 장소의 주소를 적습니다.
클릭하면 창이 하나 뜨는데 모듈 선택의 초기값은 [Absolute] 입니다.
이때는 절대 주소로 입력을 해야합니다.
(추후에 절대 주소와 상대 주소의 개념을 설명하겠습니다.)
상대 주소로 입력할 경우에는 위 그림과 같이 외부 dll 이나 실행파일을 선택후
찾은 주소에서의 offset 값을 입력하면 됩니다.
(offset 값을 구하는 방식은 다른 강좌에서도 설명되있지만 저도 따로 추후에 설명하도록 하겠습니다.)
1-5. 옵션값 직접입력
이미 옵션을 문자화한 값을 적어 코드를 적용시킵니다.
혹은 모든 옵션과 후킹주소를 입력하고나서 문자열로 가져가고 싶을때도 여기서 가져올 수 있습니다.
2. 번역 옵션
여러분이 가장 많이 보게 될 부분입니다.
너무 어렵게 생각하지 마시고 천천히 봐주세요.
2-1. 번역인자 추가 및 삭제
자신이 후킹주소로 추가한 지점에서 가리킬 메모리를 레지와 스택이나 주소로 알려줘야합니다.
추가 버튼을 누르면 인자값을 추가할 수 있고
추가된 인자값을 선택하여 삭제 버튼을 누르면 삭제가 됩니다.
2-1-1. 메모리 지정
추가 버튼을 누르면 뜨는 창입니다.
자신이 확인한 레지나 스택값을 찾아서 선택하면 됩니다.
위 그림에서 EAX~ESP 까지는 레지가 직접 가리키는 메모리를 말합니다.
이미지를 예제로 보이면 이런형태로 EAX는 0x1252000 위치를 가리키고 있다고 할때
그 위치로 가보니 바로 텍스트가 있네요. 이런 경우는 포인터 바꿔치기를 사용할 수 없습니다. 포인터가 없으니까요.
EAX 레지가 직접 가리키기 때문에 EAX를 메모리 지정으로 선택하여 추가하고 메모리 덮어쓰기 기능을 사용하게 됩니다.
[ESP]~[ESP+0x??] 는 ESP내에 들어있는 스택 포인터를 가리킵니다.
이미지를 예제로 보이면 이런형태로 ESP는 0x12FE00 위치를 가리키고 있습니다.
그 위치로 가보니 4Byte 길이의 0x1252000 주소 형태로 바이너리가 들어있네요.
오른쪽을 보시면 그 주소에 무엇이 들었는지 간략하게 보여줍니다.
실제 해당 메모리로 가보니 텍스트가 있는걸 두번째 이미지에서 볼 수 있지요?
이런식으로 4Byte 주소로 가리키는 곳에 실제 데이터가 들어있는 형태가 바로 포인터입니다.
이걸 아랄에 메모리 지정으로 추가하여 번역한다면 2가지 방법을 사용할 수 있습니다.
- [ESP] 추가, 포인터 바꿔치기 - 의 경우에는 0x1252000 의 주소를 다른 4Byte 주소(포인터)로 바꿔넣습니다.
그림과 같이 가리킨 포인터가 0x160000 으로 변경되고 그 메모리 안에는 "EroGame" 라는 글이 들어있습니다.
이때 0x1252000 주소에는 원본 글 "Text1234" 가 살아 있습니다.
이런 식으로 스택의 포인터만 바꿔치기해서 보내는 기능입니다.
아랄트랜스가 새로 생성한 메모리 0x160000 과 같은 장소에는 순수 번역한 글만 있기 때문에
0x1252000 주소 앞뒤에 있던 내용이 전혀 없습니다.
따라서 대사만이 아닌 앞뒤에 내용도 같이 참조해서 무언가를 하는 곳일 경우에는
0x160000 의 번역한 대사 앞뒤에 아무것도 없는 0x00 만 있기 때문에 참조에러가 생겨 튕기는 경우가 있습니다.
포인터 바꿔치기의 튕기는 이유는 이 때문입니다.
- [ESP] 추가, 메모리 덮어쓰기 - 의 경우에는 0x1252000 의 메모리내에 번역한것을 직접 덮어쓰게 됩니다.
그림과 같이 포인터가 가리키는 곳은 그대로이나 메모리 내용이 바뀌게 됩니다.
종결문자는 0x00 (null 문자) 가 채워지고 뒤에 남은 "56"은 쓰레기 문자가 된셈이지요.
번역한 글이 넘처 버린다면 이미지에서 볼때 뒤쪽으로 0x00 으로 되있으니까 상관이 없겠지만
만약 뒤쪽에 다른 글이나, 명령어, 포인터 같은게 들어있어서 그 부분을 뭉게버리고 덮어버리면 게임에 무슨일이 벌어질지 모르는겁니다.
메모리 덮어쓰기의 튕기는 이유는 이 때문입니다.
2-1-2. 직접입력
꼭 ESP에만 포인터가 있는것은 아닙니다.
EAX에도 포인터가 올 수도 있습니다.
그럴경우 목록에 없기 때문에 직접입력을 하셔야 합니다.
이미지와 같을 경우 [EAX+0x4] 와 같이 입력해서 인자값을 추가하면 됩니다.
========================================================================================================
왠지 ATCode의 기능과 이론의 반절정도 설명하느라 오늘 강좌 채워버렸네요.
아직 밑에 기능이 더 수두룩 한데.... 다음 화에 올리도록 하겠습니다. ㅠ.ㅡ
본 내용을 전부 필히 알고있어야 필요는 없습니다.
일부 내용은 이해하지 못하셔도 스쳐지나가듯 읽으신 정도면 충분합니다.
저도 위 내용들을 전부 이해하시라고 바라지는 않습니다.
^-^
본 강좌는 무단으로 다른 곳에 기재하는걸 금합니다.
아니, 허락 맞고도 금합니다. 데헷~♥