-
2010. 11. 15. 06:17 Processor Code/Reversing
첨부파일 :
오르지널 Sonic3K PC 버전 입니다.
Win95/98 을 이용할때, 마지막으로 사용 했었습니다.
서론 : 알고있는 고전 게임을 인터넷 검색으로 찾아서 한번 실행해본결과 호환성 문제가 있었고,
게임 플레이가 힘들었습니다.
물론 DOS에서 실행하는 게임의 경우 DOSBOX 를 이용할 수 있지만, 윈도우즈용으로 릴리즈된 게임들은 호환성 문제를 해결하거나,
구버전 운영체제를 설치 하는수 밖에 없습니다.
그것은 매우 비효율 적입니다.
나쁘게 말하면 소프트웨어 크래킹 이 될것이고, 좋은 말로는 리펙 이 될까요?
시작에 앞서 경고 합니다. 저작권이 유효한 게임 분류의 소프트웨어이며, 현재 생산 중지 됬으며,
비상업적 용도의 저작권 규제가 거의 없으며, 저작자(개발사,개발자)의 요청이 있을경우 해당 자료는 삭제 처리 할수 있습니다.
주의사항을 숙지하시고, 가이드를 보시면 좋습니다.
WinNT 시스템에서 게임을 실행해보면, 화면이 매우 빠른것을 알수 있죠.
절때, 사람이 플레이가 불가능 할정도로 빨라집니다.
이는 CPU 의 속도 및 운영체제의 정책이 고속화되면서, 덩달아 빨라지는경우가 있습니다.
PeekMessage 와 GetMessage 의 문제로 해당 문제가 생길 수 있으나,
쓰래드(Thread) 정책(Policy)및 운영체제(OpratingSystem)의 쓰래드 처리 성능/정책에 따른 호환성 문제입니다.
이미 오래전에 해당 소프트웨어를 해킹 하여보았기에 답만 알려드리도록 하겠습니다.
올리디버그1.1(OllyDBG110) 를 이용했으며, PeekMessage 검사, 게임 실행 패턴검사, 쓰레드 검사를 하여 간단히 알아낼 수 있습니다.
Sonic3K.exe 의 소프트웨어 EntryPoint 입니다.
여기서 다음 코드 실행 F8 ( Call 에 들어가지 않습니다. ) 키를 눌러 진행합니다.
게임 루프에 도달할때까지 계속 누르는데, 루프에 들어가기전 창이 뜰것 입니다.
문제는 아래사진과 같은 부분에서 계속 맴돈다는것 인데,
이것을 처리하는 방법은 루프문을 빠져나가는것으로, F2 를 이용한 브레이크 포인트 그리고,
F9 실행 키를 이용하여 실행을 눌러주면, 브레이크 포인트에 멈추어섭니다.
주석(메모)이 필요하다면, ; 키를 눌러 코멘트를 삽입 하세요.
아래 빨간 부분이 브레이크 포인트를 적용한 모습입니다.
계속 F8 을 눌러 진행합니다.
진행하다보면 메세지박스가 뜨며 더이상 F8 을 눌러도 다음 코드를 실행 하지 않습니다.
메세지박스가 뜰때, 프로그램이 멈추도록 하는것이 운영체제의 정책 입니다.
물론 보안등의 이유로 프로그램이 멈추지 않게 하거나, 메세지박스가 뜬후 일정 시간이 지나면,
프로세스가 파괴되도록 설계 하기도 합니다.
다시 본론으로 돌아와서, 메세지박스의 확인 버튼을 누를시 게임이 시작되는군요.
해당 부분에 F2 를 눌러 브레이크 포인트를 걸어주었습니다.
물론 이부분이외의 브레이크 포인트는 해제 해주어도 상관이 없구요.
사실 약간의 인내심을 요구합니다.
올리디버그 Ctrl + F2 단축키로 리셋 시킵니다.
메세지창이 뜨는데 예 를 눌러주세요.
혹은 눈치가 빠르다면, 쓰래드창이 생성됨을 보고 CreateThread 함수를 조사 할수 있습니다.
다른 호환성의 취약한 문제가 없는지 자세히 확인 하겠다면 아래 부분에서 F7 을 눌러 Call 문을 타고 이동.
F7 을 눌러 이동한 모습입니다.
스텍에 Call 명령 다음 주소가 들어가며, 다른 메모리로 이동되었습니다.
여기서도 계속 F8 을 눌러 진행 해봅니다.
좀전에 보았던 해당 메세지를 다시 만났습니다.
이곳을 F2 로 브레이크 포인트를 걸고 Ctrl + F2 를 할수도 있겠지만,
이부분에서 Enter 를 눌러 미리 Call 의 명령어를 살펴볼수 있습니다.
한가지 팁을 드리자면, 쓰레드 부분을 잘 살펴 보십시오.
메인 쓰레드 뿐이군요, 계속 지켜 봅니다.
Ctrl + F2 키를 눌러 리셋후 브레이크 포인트 주소로 다시 왔습니다.
F7 을 눌러 진입 합니다.
진입한 모습.
F8 을 눌러서 진행 합니다.
Win32API 들인 FindWindow, FindWindowEx, CreateMutex 함수들은 다중실행 방지에 이용되기도 합니다.
이부분은 분석을 뛰어넘도록하며, 진행을 계속 합니다.
진행하다보면 메세지 박스 뜨는부분을 찾아내었습니다.
내친김에 메세지 박스 내용을 편집을 해보도록 하죠.
엔터(Enter) 키를 눌러 Call 에 진입 해봅니다.
Call 에 진입한 모습.
윗부분 PUSH 에서 스텍에 메세지 내용을 담고, 아래 Text 에 다시 담아주는 코드 이군요.
[ARG.1] 부분이 함수의 첫번째 파라미터(Parameter) 입니다. ( Parameter = 파래미터 라고 읽습니다. )
void Call(DWORD A){ } 로 볼때, A 부분이 [ARG.1] 부분 입니다. ( <- PC 프로그래머의 이해를 돕기위한 부분 )
PUSH 후 바로 CALL 을 실행 했음으로, 스텍에서 바로 메모리를 바꾸어줍니다.
스텍 목록 최상위에서 마우스 오른쪽 클릭시 메뉴가 나옵니다.
Follow in Dump 클릭을하게되면 옆 핵스(Hex) 뷰에 나타나게 되는데,
여기 Please insert a .... 부분에 포커스를두고, 원하는 문자를 기입 할수 있습니다.
문자를 마치려면 문자열 마지막에 NULL 문자인 0 을 기록 해주면 됩니다.
물론 원본 문자열 보다 길어지면 진짜 문제가 생길수 있음으로 주의 하시기 바랍니다.
빨간 따움표에 에러 메세지창과 사운드가 싫으신가요?
아래 문서와 사진에 포커스된 PUSH 10 을 바꾸어 다른 형태로 변경이 가능합니다.
PUSH 옆에 오는 숫자는 16진수 이며, 이를 모르고 0x40을 64구나 하고 PUSH 64를 넣는다면, 전혀 다른 결과가 나타납니다.
PUSH 40 을 적게되면 흰색 느낌표에 정보박스가 대신 뜨게되죠.
http://msdn.microsoft.com/en-us/library/ms645505(VS.85).aspx
뒤로 돌아가려면 - 키를 눌러주고 앞으로 다시 가고싶다면 + 키를 눌러줍니다.
이전에 브레이크포인트를 걸어두었음으로, 좀전에뜬 확인 버튼을 그냥 눌러주어도 됩니다.
F8 을 눌러 진행 합니다.
진행도중 쓰레드가 생성 되었습니다.
살펴본결과 BGM 관련 라이브러리 로드를 진행 하는 것 으로 보여집니다.
뛰어넘고 계속 진행 합니다. F8
이런 경우가 있습니다. CREATE_SUPPENDED
아래 그림을 보도록 하죠, 분명히 CreateThread 실행 되었는데 정지상태라서 나타나지 않습니다.
쓰레드 시작점을 얻으려면 CreateThread 함수를 보아야 합니다.
아래 그림 보이시냐요? 쓰레드의 메인 시작점이 아닌, 네이티브 시작점으 가르키고 있네요.
저 많은 횡 스크롤에 쓰레드가 시작될 지점을 나타내주면 안되는 것 인가요?
이건 좀 억지 스럽습니다. User time 옆으로 이동시켜보면 System time 이 전부이죠.
아무튼 이후에 오는 Call 들을 모두 조사 합니다.
다행히도 어렵지 않게 찾아내었습니다.
바로 다음 CALL 에서 찾아내었죠.
이런경우 ResumeThread API 가 쓰래드를 재개 해줍니다.
다음으로 진행하여 ResumeThread 를 찾아냅니다.
아, 아니요, 그럴 필요 없이 ThreadFunction 주소를 뽑아와야 겠죠.
CREATE_SUPPENDED 바로 및에 있군요.
Ctrl + G 주소 이동 명령을 실행하여 주소를 기입합니다.
이런,, 코드 분석이 제대로 안되었습니다.
분명이 이부분은 함수 부분이 맞습니다.
Ctrl + A 로 재분석 할수도 있지만, 이경우 제대로 분석이 안되는것임으로 구간에 포커스를 주고 복사후 다시 붙여넣습니다.
복사 & 붙여넣기
제대로된 코드가 보이는군요.
브레이크 포인트를 걸어주고, F9 을 눌러서 진행 합니다.
브레이크 포인트에 도달하면 F8 을 눌러 하나씩 진행 해봅니다.
적당한 루프에 Sleep 문을 첨가하여 처리를 지연 시킬 예정임으로,
적당한 위치를 찾아야 합니다.
적당히 아래 부분에 브레이크 포인트를 걸어두고 다음 분석을 진행 합니다.
모든 부분을 다 살펴보며 코드를 집어넣기 좋은 부분을 찾습니다.
이부분의 CALL 이 많네요.
하지만 그림의 함수로 들어갑니다.
JMP 를 타고 첫번째 CALL 문을 만났습니다.
어이없게도 들어가게되면 RETN ..
바로 나오게 되네요? 아니 그럼 이함수는 필요가 없는것인데 ..
그래도 두고 넘기겠습니다.
아니, 프로그램을 어떻게 정리도 안하고 컴파일 했을까요?
void Function(){return} 이런 형태의 코드가 하나도 아니고 여러곳에서 사용 되었군요?
물론 Function 의 문자는 다른 기능을 하던 함수이지만 설계상의 문제로 지웠을 수 있습니다.
이때는 1996년도, 컴파일러의 기능이 크게 좋지는 않았습니다.
윈도우 95 때였으며, 저는 윈도우 98 로 이게임을 해보았습니다.
데모 컬렉션 시디 에서 말이죠.
한곳도 아니고 여러곳에서 Call 을 하며 효율성으로 따지면 최악 입니다.
What the ....
무슨 코드기 이렇게 빼곡 한것인지, 매우 지저분합니다.
현재 NT 계열에 사용되는 컴파일러는 이런 코드를 만들지 않고 있죠.
디버그시 편리함은 물론이고, Virtual Studio C++ 2008 에서는 어셈블리어 뷰 까지 지원 합니다.
2010 버전에서는 어떤지 모르겠군요.
아래 5개의 Call 에 희망을 걸고 분석해본결과 첫번쨰는 Retn , 두번째는 별코드 없으며, 세네번째도 Retn 입니다.
다섯번째에서 뭔가 처리를 하는가 싶더니 JMP 여러번 뛰고 retn 합니다.
마지막 부분인것 같군요, 여기서 그나마 쓸만한 부분을 찾아 낼수 있었습니다.
해당 CALL 을 들어가서야 자리를 바꿔버릴 코드를 찾아내었고, 해당부분은 루프시 계속 거치는 패턴중 하나라는 것 입니다.
물론 이부분도 어김없이 RETN ?
이건 정말 .... ( What the .... )
매우 답이 없는 코드 입니다.
RETN ? 여기에 JMP 코드를 넣어서 뭘 어쩌고 어떻게, RETN 부분에 Sleep 문을 넣을것인가 !!
좋습니다 어떻게든 크래킹 해놓겠습니다.
이미 저는 오래전에 답을 찾았습니다.
이건 사람이 만들어낼 코드가 아닌것이다.... ( 2010년 2월에 대체 무슨 일이 있었던것 일까요.. )
DB 가 무었이냐구요? DB 는 함수의 주소를 나타내는데 그저 닿기만하면 그리로 보내버립니다.
JMP 처럼 상대 값을 가지기도 합니다.
디버깅 도중 갑작스럽게 불안정 해지는군요.
이래서 개발용 혹은, 해킹용이든, 크래킹용도로 PC 는 2대 이상을 사용 하고 봐야 합니다.
아무튼 아래 그림을 보면 어떤 일이 있었는지 알수 있습니다.
아 물론 그아래에 있는 코드또한 설명을 해야겠죠?
- Trick : EB 06 을 한코드로 볼때, JMP 004114B1 코드가 됩니다. -
우선 Sleep 에 들어가는 파래매터( Parameter ) 가
PUSH DWORD PTR DS:[8547E8]
메모리의 0x8547E8 를 참조합니다. ( Fixed 이주소는 읽고쓰기 가능한 메모리 마지막 주소 4바이트를 지정합니다. )
이부분은 사용되지 않는 부분을 가져써야 하며, EP 를 조작하여,
프로그램 실행시 커멘드라인 "My.exe" ?Param
부분을 가져옵니다.
윈도우즈 XP 와 7 에서 동작이 다른것을 확인하고,
XP 는 16을, 7은 1 을 주어 해결 하였습니다.
위 사진은 아래부분과 연동 됩니다.
파래메터 받아서 숫자로 변환한뒤 값을 저장 하는 부분.
Trick 한부분을 눈치 채셧습니까?
정말 긴 가이드를 끝까지 봐주셔서 감사 합니다.
한가지 문제가 생겼군요.
Sleep 에 넣어주는값을 보관하는 곳,
적당히 찍어서 넣었던것 같은데, 메모리가 거기까지 사용되더군요.
맨끝으로 이동 시켰습니다.
넣는부분 , 사용하는부분 2곳이 있고, 그곳을 수정하면 되겠네요 ^^ ( 가이드에 표시 해두었습니다. ).
Crack 업로드본에는 수정한것을 올려두겠습니다.
아하,, 한가지더, FILE_ID.DIZ 파일을 보니까,
이미 이전에 어떤분이 손을 한번 댄거죠, CD-ROM 패치.
Sonic3 & Knuckles (턜?무3, SEGA)[x/4]
Cracked by Martin Wu, PC Game City BBS
PC games, Photo .......................
>< Line#1:26639229 Line#2:26632684 ><
Ripped : Nothing lost
Cracked: CD-ROM checking........
마치면서..
FILE_ID.diz 파일이 Crackerskit.2.0-ICU 에도 들어있는데, 해당 그륩/사람을 알리는것 이군요.