MED엔진...

예를 들면 몬스터파크2 같은 게임에서 사용된 엔진입니다.

뭐.. 이것도 아직 아랄과 상성이 않좋은 엔진중 하나라고 생각됩니다.(튕기는 이유를 알 수 없음)

MED엔진은 그냥 후킹할 경우에

폰트 출력 문제가 발생하는데,

이것은 포럼 게시글중에 그 해결법이 있으니,

다들 알고 계실꺼라 생각하고(따라서 생럌)

왜 MED엔진은 포인터 바꿔치기 하면 안되는가?에 대한 논의를 해보고자 합니다

먼저 MED엔진은 포인터 돌리기를 하는데.

그 구조는 다음과 같습니다.

1. 게임을 스타트(타이틀 화면에서 시작 버튼을 누르면)하면

   모든 스크립을 각각의 랜덤 포인터 지점에 밖아 넣는다.

2. 밖아 넣은 포인터를 하나씩 일련의 계산과정을 거쳐서 꺼내온다.

(2바이트 이하 문구 제거 과정도 있습니다.)

3. 꺼내온 포인터 출력..

그래서 아랄양은 2의 과정이나, 3의 과정에서 후킹해야 합니다. 1은 어렵다고 생각됩니다.

후킹해야 하는 주소도 전부, 이전의 포럼글에 있으니 참고하시면 됩니다.(이미지 못 올려서 이렇게 대채)

그럼이제, MED엔진의 출력 방식을 살펴보면

0041AE8C   .  8BD0          MOV EDX,EAX
0041AE8E   .  FF85 ECFEFFFF INC DWORD PTR SS:[EBP-114]
0041AE94   .  8B45 FC       MOV EAX,DWORD PTR SS:[EBP-4]
0041AE97   .  E8 00E40000   CALL monpa2.0042929C
0041AE9C   .  8D55 F0       LEA EDX,DWORD PTR SS:[EBP-10]
0041AE9F   .  8D45 FC       LEA EAX,DWORD PTR SS:[EBP-4]


이곳은 대사 출력 구문인데, 이곳을 통해 예를 들어 보자면,

MED엔진은 포인터 돌리기를 할 때, [ESP] 스택 값으로 돌리지 않고, [EBP]스택 값으로 돌립니다.

그래서 위에서 보시다 시피, [EBP-10],[EBP-4]에 대사 주소의 포인터 위치가 들어가게 됩니다.

물론 들어간 포인터 값은 아래의 CALL문을 통해서 출력되는 구조입니다.

그렇다면, 우리는 0041AE94 에서 [ebp-4] 값으로 포인터를 바꾸면 나올거라고 예상해 볼 수 있습니다.(실제로 됩니다.)

그런데 막상 해 보면, 한글자도 안나오는 현상을 경험하실 수 있습니다.

그건 MED엔진을 열어보면, 다음과 같은 출력 방식을 갖추고 있기 때문입니다.

0FB049B4           00 00 2E 00 00 00 02 00 00 00 1E 00 00 00   
0FB049C4  81 75 82 A8 8E 6F 82 BF 82 E1 82 F1 81 41 82 B1 
0FB049D4  82 EA 81 63 81 63 82 CD 82 A2 82 C1 81 76 00 00 

여기서 보시면, 스크립 출력 위에 명령어가 0C 만큼 붙어서 나오는 것을 알 수 있습니다.

그런데 이 명령어를 읽을 때에, 명령어도 각각의 개별 주소로 읽는것이 아니라,

[EAX-4],[EAX-8],[EAX-C] 처럼 고정 포인터의 형태로 읽어 오기 때문에, 포인터 바꿔치기가 제대로 작동하지 않게 됩니다.

포인터 바꿔치기를 하면, 가장의 메모리 주소에 새로 쓰는것이기 대문에, 명령어 단을 못 가져오기 때문이죠.

따라서 자체 ATCODE.DLL을 수정하면 정상 출력되는 것을 확인했습니다.

여기서 앞의 붙은 명령어의 기능은 다음과 같습니다.

00 00 2E 00 00 00 02 00 00 00 1E 00 00 00

먼저 2E는 전체 명령어 + 스크립의 길이 입니다. 여기서는 앞의 00 00, 뒤의 00 00을 전부 포함합니다.

이 명령어는 맨 처음, 박은 포인터를 불러올 때 계산되는 것 같습니다.

두번재의 02는 해당 스크립의 종류를 판별하는 명령어인듯 싶은데, 정확한 기능을 이해하진 못했습니다.

만약 MED엔진을 후킹하실 분이라면, 이 명령어의 기능을 알아봐야 할 듯 싶습니다.

마지막의 1E는 실제 출력되는 스크립의 길이를 나타냅니다. 실제로 이 부분을 수정하면

수정된 만큼만 출력됩니다.

출력시 문제점.

출력하면, 정상 출력되지만 금방 튕 하는것을 경험할 수 있습니다.

그 이유는

MED엔진에는

RaiseException이라는 함수가 들어있습니다.

말 그대로, 예상치 못한 상황에 대한 대처 방안인데

이 엔진은 아주 정직하게 튕 시켜 줍니다.(망할)

현재 생각으로는, 이 부분을 전부 회피하면 될 듯 싶은데

너무 광범위 해서.. 제가 찾은 부분만 일단 올려 봅니다.

004cdb98 << retn으로 수정

0047d4cf << JE를 JMP로 수정

이것 외에 아마도 1~2개 지점을 더 수정해야 할 겁니다.


추가로 수정 ATCODE.DLL로 한다고 가정할 때

FORCEFONT(5),ENCODEKOR,HOOK(0x0041B418,TRANS([ebp-0x1c],PTRCHEAT,TWOBYTE),RETNPOS(SOURCE)),HOOK(0x0041AE68,TRANS([eax],PTRCHEAT,PTRBACKUP,TWOBYTE),RETNPOS(SOURCE)),HOOK(0x00429AE0,TRANS([ebp-0x4],PTRCHEAT,PTRBACKUP),RETNPOS(SOURCE))

이렇게 코드 주소를 넣으면 정상 동작할 겁니다. 물론 위의 두곳은 수정해야 하지만..




마지막으로..

실제 ATCODE.DLL을 수정한다고 한다면

MOV ECX,DWORD PTR SS:[EBP-20]
MOV DWORD PTR DS:[ECX],EAX
PUSH EAX
PUSH ECX
PUSH EDX
PUSH EBX
MOV ECX,DWORD PTR DS:[ESP+54]
XOR EDX,EDX
MOV EDX,DWORD PTR DS:[ECX-C]
SUB EAX,0C
MOV DWORD PTR DS:[EAX],EDX
ADD EAX,4
MOV EDX,DWORD PTR DS:[ECX-8]
MOV DWORD PTR DS:[EAX],EDX
ADD EAX,8
XOR EDX,EDX
XOR ECX,ECX
MOV DL,BYTE PTR DS:[EAX]
CMP EDX,0
JE SHORT ATCODE~1.15E2D6B6
INC EAX
INC ECX
JMP SHORT ATCODE~1.15E2D6AB
MOV EAX,DWORD PTR DS:[ESP+C]
SUB EAX,4
MOV DWORD PTR DS:[EAX],ECX
POP EBX
POP EDX
POP ECX
POP EAX
RETN

이런식으로 수정이 가능합니다.

(물론 이건 발코드여서 플래그 값은 그냥 무시했습니다.)

이상으로..

잉여력 충만해진 분들이라면

가끔 도전해 볼만한 과제일듯..

P.S

암튼.. 저 락만 어떻게 해결하면 되겠는데..

문제는 이게 락인지, 아니면 백로그 출력할 때 문제 생겨서 튕기는건지 그거까진 분석해 보지 않아서..

한편으로는 백로그 정상 출력안되는 것 땜에 튕기는듯도 해서..

뭐.. 그렇다는 겁니다.