1. 잡소리
음.. 오랜만에 인사드립니다. 오늘은 Sprotect의 정상적인 해제 방법을 알아보도록 합시다.
이 강좌가 8번인 이유는 제가 그냥 비공개 강좌로 쓴게좀 있어서.. 조금 건너뛴 형식이 되었습니다.
이번 강좌는 어느정도는 컴퓨터에 대해 이해 하고 계셔야하며, 적어도 머리는 쓰실줄 알아야지 해제할 수 있습니다.
원래는 SProtect의 강좌를 안쓰려고 했는데 기왕 공개한거 한글로도 써보도록 하죠.
엨읔.. 좀 길게 설명을 곁들여서 쓴 강좌 입니다.
이 강좌는 http://forum.wc3edit.net/deprotection-cheating-f64/completely-deprotect-s-ssprotect-t34029.html 글을 어느정도 참고 하고 쓴 글임을 알립니다. 귀찮은 일을 다하는 그분.. 최고다!!
저도 어디까지나 독학입니다. 글이 매우 주관적임을 알고 가셔야 합니다.
강좌시작!
Sprotect.exe (프로텍트를 걸어주는 프로그램)
사용방법은 맵을 Drag & Drop 하시면 됩니다.
2. 준비물
라딕 - 블로그 어딘가에 있음
HxD - 이것도 어딘가에서 다운 받으시길;
Sprotect가 걸린 맵
MPQ_HASH_FILE_KEY
(hash table) = 7037AFC3
(block table) = A3B383EC
귀찮은걸 해결해주는 매크로 프로그램
계산기
3. 알아둬야할것들
일단 강좌를 시작하기 전에 정말로 알아둬야 할 것들이 있습니다.
바로 HashTable, BlockTable 인데요.
앞으로는 부르기 쉽게 HT, BT라고 부르겠습니다. 아니면 해쉬테이블, 블록테이블이라고 부르거나요
자 그럼 왜 HT와 BT가 왜 중요한가?
워크 맵에 파일을 집어 넣으면 이 파일들은 맵에 바이트 단위로 들어가게 됩니다.
근데 파일이 너무 크면 1mb 한개를 넣는 것 만으로도 맵의 용량이 엄청 커지게 되겠죠.
그래서 압축이 되어서 들어가게 됩니다. 이 과정에서 흔히 생기는 압축을 워크에서는 ZLIB 압축이라고 하는데.. 뭐 상세한것 까지는 필요없을 것 같구요.
어쨋거나 압축을 해서 넣게 되면 원본의 크기와 압축된 크기를 어딘가에 저장해야하고, 바이트를 넣은 위치 라던지 압축을 했다면 어떻게 압축을 했는지, 그리고 해당 파일의 이름을 저장해야하는데
그 역활을 하는게 HT와 BT입니다.
정확하게 어떤정보를 저장하는지 궁금하신분들을 위해 잠깐 짧게 설명 하겠습니다.
보기싫으시다면 바로 강좌로 넘어가셔도 무관합니다.
HashTable(FileNameA, FileNameB, Locale, Platform, BlockIndex)
일단 파일의 HT에는 FileNameA(uint), FileNameB(uint), Locale,(short) Platform(short), BlockIndex(uint) 의 정보를 저장해 둡니다.
파일을 맵에 넣게 되면 파일의 이름을 (listfile)에 표기하거나 war3map.imp (불러오기매니저) 에 저장하긴 하는데 보통 맵을 배포할때는 두개를 다 삭제하고 배포해버리기 때문에 의미가 없습니다.
워크 또한 파일의 이름을 그대로 보관하지 않고 암호화해서 보관한다. 그 보관하는 장소가 HT이며, 암호화한값이 들어가 있는게 FileNameA와 FileNameB 입니다.
Locale과 Platform에 관해서는 따로 설명은 안하겠습니다. 워크의 경우에는 무조건 0 이라는 것만 알아 두시면 됩니다.
자세한건 MPQ Wiki를 참고 하시길!
그리고 마지막으로 BlockIndex는 해당 파일의 세부정보를 가지고 있는 BT의 순서를 말하는 것 입니다.
BlockIndex가 1이라면 BT의 2번째 (시작은 0부터 하기때문에 1일경우 2번째이다.)에 위치 하고 있다는 알고 계시면 됩니다. 물론 BT 열어보면 왼쪽에 따로 표기가 있습니다.
나머지 0xFFFFFFF는 빈 파일이라는 뜻이며, 만약 맵에 이제 새로운 파일을 집어 넣게 되면 빈 파일의 자리에 해당 파일의 정보를 끼워 넣는다. 워크는 파일이 일정갯수가 되면 테이블 크기가 늘어납니다.
BlockTable (FilePos, Compress Size,Uncompress Size,Flags)
HT의 0xE 번째 줄에 있는 war3map.w3i를 보시면 BlockIndex가 1입니다.
BT에 와서 # 1번을 보시면 파일이름이 war3map.w3i라고 되어있죠. 물론 BT가 파일이름을 따로 저장하거나 하지는 않지만 사용자들이 편히 사용 하라고 라딕에서 제공하는 기능입니다.
네 BT에 오면 w3i의 상세한 정보를 알 수 있습니다. 파일의 위치(Position)와 압축된 크기(Cmpr) 파일의크기(Size) 특성(Flags)
짧막하게 설명하자면 파일의 위치가 0xD6D9 인데 이게 헤더의 위치로 부터 0xD6D9라서 헤더의 위치를 더해야합니다 (보통 헤더의 위치 0x200)
그래서 Hex로 보게되면 0xD8D9라는 위치에 해당 파일이 있게 되는 겁니다. 근데 압축이 되어있네요?
압축된 파일은 Sector라는 개념을 알아야지 이해가 가능한데 Sector에 관한 강좌는 비밀글로 되있어서 공개할 생각도 없고; 혼자서 연구해보시길 바랍니다.
특성(Flags)은 위키 참고 하세요.
어쨋거나 중요한 정보는 위치와 압축크기 그리고 압축하기전의 크기가 표기 되어 있습니다. 이걸로 이제 해당 파일을 압축을 풀어 추출하고 하는 것 입니다.
간단한 설명은 끝났습니다. 이것만 알아도 어느정도 이제 준비가 되있다고 보시면 됩니다.
정말로 상세한 내용이 궁금하신분들은 따로 검색해서 찾으시길 바랍니다.
자 이제 진짜로 풀어보도록 하죠!
4. 강좌
위의 내용을 다 알고 있거나 몰라도 할 수 있도록하는 강좌를 쓰려고 노력은 안했습니다. 알아서 쳐알아 먹으세요.
Sprotect의 방지의 핵심은 바로 Index의 인식을 막아 버리는 것과 동시에 BT의 위치를 헤더와 엮어버렸다는 점 입니다.
자 그럼 맵을 열어서 Header를 먼저 찾아 보도록 하죠.
MPQ검색해서 1A를 찾으시면 됩니다.
물론 Sprotect는 200번재겠지만요. 킄킄..
제가 올린 맵의 기준이 아니긴 한데.. 이게 바로 큰 맥입니다.
0x200 = HeaderPos
0x210~213 = HashTablePosition
0x214~217 = BlockTablePosition
0x218~21B = HashTableSize
0x21C~21F = BlockTableSize
네 Header의 위치를 중심으로 바로 아래에 있는 것들이 저러한 정보를 나타내고 있습니다.
위에도 뭐 HeaderSize, MapSize, MPQVersion, SectorSize 라던가 있긴 합니다. 근데 알필요는 없삼!
계속 적을게요. 이번에는 제가 올린맵을 봅시다.
HeaderPos = 0x200
예전강좌에서도 말했지만 읽는 방법이 Little Endian 이라 읽는 순서를 조심해서 봐야한다. (리틀엔디안에 대한 상세한 정보는 따로 검색)
0x210 부터 4자리씩 끊어서 봅시다.
HTPos = 0x28E99
BTPos = 0
HTSize = 0x40
BTSize = 0x14
여기서 주의하셔야할 점이 있습니다.
제가 왜 HeaderPos를 적어놨느냐 하면 HTPos와 BTPos가 Header의 위치로 부터 0x28E99, 0 이기 때문에 HeaderPos값을 더해줘야지 원래의 위치를 알 수가 있습니다.
그래서 실제로는
HTPos = HTPos(0x28E99)+HeaderPos(0x200)
BTPos = BTPos(0)+HeaderPos(0x200) 입니다.
계산기를 써야할때가 왔죠? 프로그래머용으로 바꾸신후에 Hex(16진수)로 하신후 더하시면 됩니다.
HTPos = 0x29099 , BTPos = 0x200 이 정상적인 위치입니다.
근데 막상 해당 위치에 찾아가도 어디까지 인지 모른다면 낭패겠죠. 그래서 사이즈가 존재합니다.
HTSize = 0x40 , BTSize = 0x14
단, 이 Size는 크기가 아니라 갯수를 뜻하는 것이기 때문에 0x10을 곱해주어야 합니다.
그래서 최종적인 HT의 위치는
HT = 0x28E99+HeaderPos(0x200) ~ 0x28E99+HeaderPos(0x200)+(HTSize(0x40)*0x10) 이 되겠습니다.
계산하면 HT = 0x29099 ~ 0x29499
BT의 위치도 알아봅시다.
BT = 0+HeaderPos(0x200) ~ 0+HeaderPos(0x200)+(BTSize(0x14)*0x10)
BT = 0x200 ~ 0x340 입니다. 정말 쉽죠?
그럼 위치도 알았으니까 따로 파일을 하나 만들죠. (이 이후로는 HxD 기준입니다.)
일단 Ctrl+G 를 눌러서 이동창을 키신후에 0x29099 로 이동
그리고 29099부터 29498 까지 복사
아까 적어놓은것처럼 크기가 400이라고 쉽게 알수도 있으니까 29499가 어딘지 모르는 분은 HTSize*10의 크기만큼 복사하시면 됩니다.
그리고 Ctrl + N 하셔서 빈파일을 만드신후 복붙 하신후 파일을 저장합니다.
파일 이름은.. 음 Hashtable로 하져
그리고 BT도 같은 방법으로 만들어 줍니다.200~340
그럼 파일이 두개가 만들어집니다.
혹시나 자기가 틀렸을까봐 조금 망설여지거나 불안하신 분은 파일을 올려 둘테니까 참고하세요
네 이제 준비가 끝났습니다.
제가 준비물에 올린 MPQHelper를 다운받으신 후
hastbale를 클릭 하신후에 MPQHelper.exe에 끌어다 올리시면 됩니다. (Drag & Drop)
그럼 창이 뜰텐데 우리는 지금 암호화를 푸는 복호화작업을 해야하기 때문에 dec라고 치시면 됩니다.
그럼 Key를 입력하라고 하실텐데 해쉬테이블의 Key값은
(hash table) = 7037AFC3
(block table) = A3B383EC
7037AFC3을 입력하시면 됩니다.
이런식으로 말이져
그러면 파일이 하나 생성됩니다. (hashtable.mpqdec)
쨔쟌 완벽하게 복호화가 되었습니다. 짝짝짝
같은 원리로 blocktable파일도 복호화합시다.
이런식으로 복호화가 됩니다.
혹시나 싶으니 올려둘게요.
자 그럼 이게 뭔지부터 알아야하는데 사실 3번과정에서 다 한번씩 설명했습니다.
해쉬테이블에 있는 정보가 뭔지 다시 보시면
HashTable(FileNameA, FileNameB, Locale, Platform, BlockIndex)
입니다.
자리를 끊어서 볼까요?
NameA(uint) = 0x9644F843
NameB(uint) = 0x74E57A4F
Locale(short) = 0x412
Platform(short) = 0x2600
BlockIndex(uint) = 0x4000000E 입니다.
햬당 프로텍트가 걸린 맵을 강제로 열면
맞죠? 괴언어가 알 수 있는 언어로 복호화 됬습니다. WOW~~~
네.. 이작업하려고 개고생했습니다.
제가 위에서 그래도 설명을 적어두긴 했는데 이상한점이 있죠?
Locale과 Platform은 워크에선 0이라고 생각하라고 했고 블럭색인(BlockIndex)는 BT에서의 번호를 나타낸다고 했는데 0x4000000E는 너무 어이가 없는 번호죠?
워크는 BlockIndex의 0x4xxxxxxx 0x8xxxxxxx가 있다면 무시하는데 라딕이라는 프로그램은 앞자리를 무시 못해요.
물론 신라딕은 하고 있긴합니다만, 구버전의 라딕은 하지 못합니다. 그렇기 때문에 수정해줄 필요가 있습니다.
사용하는 파일들의 Locale과 Platform을 전부다 0 으로 바꾸고 블럭색인(BlockIndex)에 있는 40을 0으로 바꾸면? 완벽하게 HT가 원본처럼 바뀝니다.
예시를들어드리자면
이런식으로 고치는 겁니다. Little Endian인거 생각하시고 수정하시길 바랍니다.
근데 테이블 크기가 0x40이면 수정하기는 쉬운데; 테이블크기가 0x8000이라면? 일일이 다 수정할 수는 없습니다.
그럼 이제 쉽게 다 바꿀 수 있는 매크로 프로그램을 써봅시다.
제가 준비물에 올려둔 Hex Edit Macro.exe를 켜주시구요
Open File 하신 후 hashtable.mpqdec을 엽니다.
따로 아무것도 건들지 마시구
Start Offset 에 8을 집어넣고 밑에 Overwrite의 Value값에 00 00 00 00을 집어넣습니다.
Modify 적용 시킵니다.
그 다음엔 Start Offset에 F를 넣습니다. Overwrite의 Value값에 00을 집어 넣구요.
이것도 Modify를 눌러서 적용시킵니다.
그다음 File -> SaveAs 하신후 원하는 이름으로 저장하시면 됩니다. 저는 HTModify라고 해서 저장 하겠습니다.
자 해당 파일을 열면 많이 바꼈죠? Start Offset을 8 로 하고 Value를 00 00 00 00 한 이유가 보일겁니다. 8번째것들을 전부다 00 00 00 00 덮어 쓴거 보이시죠? 그리고 F위치에도 보시면 전부다 00으로 변경됬구요.
이걸로 귀찮은 작업은 끝났습니다. 하지만 문제가 존재합니다.
워크에서 빈파일들을 다시 설정 해줘야한다는 건데.. 원래 Hex하고 비교하면
0xFFFFFFFF 0xFFFFFFFF 0xFFFF 0xFFFF 0xFEFFFFFF 가 빈파일입니다. 근데 지금은
0xFFFFFFFF 0xFFFFFFFF 0x0000 0x0000 0x00FFFFFF 로 되있죠. 이걸 일일이 하면 귀찮으니까 한번에 수정 하도록 합시다.
어떻게 수정할거냐 하면 Hxd를 기준으로 Ctrl + R 그다음
검색 : FF FF FF FF FF FF FF FF 00 00 00 00 FF FF FF 00
바꿀 텍스트 : FF FF FF FF FF FF FF FF FF FF FF FF FE FF FF FF
데이터 형식 : 16 진수
FE 니까 조심하세영
하신 후 모두 바꾸기 하시면
이런식으로 되는데 저장하시면 됩니다.
이것도 올려두긴 하겠습니다. (FE로 수정이 안되있음.. 부덜부덜)
자 이제 HT의 문제점을 다 지웠습니다. 나중에 다시 암호화 해야하니까 잘 꿍쳐 두시구요.
마지막으로 남은 BT의 문제점만 제거하시면 됩니다.
매크로 프로그램으로 blocktable.mpqdec을 열도록 합시다.
Start Offset : 2F , Overwrite Value : 80 으로 해서 적용 하신후 저장하시면 됩니다. (응용 하시면 위치를 0x2F부터도 시작이 가능합니다.
이 작업을 왜 해줬냐하면 Flags에는 여러가지 특성들이 존재하는데 그 특성중 하나가 Protect(상세 명칭은 위키 참조)라는 특성을 가진 Flags가 존재합니다. 해당값이 1이 되면 파일을 추출못하게 하는데 워크랑 신라딕은 상관없는데 구버전 라딕이 추출을 못합니다. 음.. 다시 생각해보니까 추출인지 삭제인지 너무 오래되서 까먹었네요 ㅋ.. 어쨋거나 그러한 기능이 있습니다 ^어^;;
그렇기 때문에 0x81000200(파일존재 && 프로텍트 && 압축상태)을 0x80000200(파일존재 && 압축상태) 으로 바꾸어 줘야합니다.
파일을 여시면 이렇게 되있는데 0번째 줄과 1번째 줄을 00 으로 다 바꾸어 주어야 합니다.
뭐.. 상세한 내용을 말해드리긴 너무 길어져서 적기 애매해지는데 일종의 암호화와 복호화를 걸친 산물이라고 해야할까요.
테이블에 원래는 MPQ 즉, Header의 내용을 포함하지 않습니다. 근데 이 테이블을 보면 Header의 내용을 포함함과 동시에 자기 테이블을 가지고 있죠. 뭐 그런 원리 입니다. 그래서 Header의 크기는 워크상으로 0x20이고 그렇기 때문에 0~0x20까지의 값을 0으로 다 바꿔야 하는 것 입니다.
이런식으로 고쳐주시면 됩니다.
음.. 딱히 올릴 필요는 없을 것 같은데; 일단 올려드립니다;
네 이제 다 저장하시고 마지막 작업을 하면 됩니다. 얼마 안남았어욧..
이제 프로그램 다 꺼주시구요.
BTModify와 HTModify를 다시 암호화 해줍시다.
HTModify를 MPQHelper에 Drag&Drop 합니다.
enc를 치신후 7037AFC3
BTmodify도 MPQHelper에 Drag&Drop 합니다.
enc를 치신후 A3B383EC
그럼 파일이 두개가 생깁니다.
HTModify.mpqenc , BTModify.mpqenc
이제 맵을 Hex로 열어줍니다.
지금부터 할 작업은 다시 HT와 BT의 바뀐 테이블을 붙혀넣고 해당 테이블의 위치를 조정해주는 행동입니다.
커서를 제일 아래로 내려서
이렇게 되있을텐데.. 위치가 너무 복잡해지면 계산하기 귀찮아집니다.
그래서 저는 뭐 자동화 하는 프로그램이 있긴한데 만약 이러한 일이 생긴다면 왠만하면 위치를 맞춰주는 편입니다.
이런식으로 00 을 삽입해서 위치를 맞춰줍시다.
제일아래쪽에 보시면 Offset : 0x295A0이라고 되있죠? 어딘가에 필기해두시거나 계산기에 적어두세요
그다음은 HT와 BT의 암호화된 Hex값을 전부다 집어 넣습니다. 순서는 위치를 잡을 줄 알면 BT HT를 막 섞어도 되지만 아니면 무조건적으로 HT를 먼저 넣으시는 것을 추천드립니다
제일 아래쪽 -> 수정하기 쉽게 자리 맞춰주기 -> Offset Value Check -> HT Paste -> BT Paste 입니다.
자 그럼 다시 MPQ Header를 찾으러 갑시다. MPQ 1A (4D 50 51 1A)를 뜻하는 것입니다.
이제 Header를 정리 해야합니다.
4D 50 51 1A 53 50 72 6F 74 65 63 74 00 00 03 00 를
4D 50 51 1A 20 00 00 00 74 65 63 74 00 00 03 00 로 수정
이건 그냥 뭐 의식같은 겁니다. 신라딕이 워낙 민감해서 이렇게 안하면 읽기모드로 열립니다. 조심하세요.
99 8E 02 00 00 00 00 00 40 00 00 00 14 00 00 00 를
A0 93 02 00 A0 97 02 00 40 00 00 00 14 00 00 00 로 수정
최종적으로 완성되는 Hex Value
자 이제 중요한 부분인데 왜 이렇게 되는지에 대해서 설명하겠습니다.
제일 처음에서도 말했듯이
0x210~213 = HashTablePosition
0x214~217 = BlockTablePosition
0x218~21B = HashTableSize
0x21C~21F = BlockTableSize
라고 했습니다. 근데 저희는 Size를 건들지 않았고 테이블의 위치만 건드렸습니다.
이거 두개만 수정하면 되는데.. 저희가 HT와 BT를 복붙할 때 Offset을 따로 저장하셨을 겁니다. 그 값이 0x295A0 이구요.
그자리에는 분명 HT가 복붙 됬을 겁니다.
0x210~213 = HashTablePosition = 0x295A0 이라는 말이 되는데 Header의 위치로 부터 0x295A0은 아닙니다.
Header의 위치는 0x200 그렇다면 0x295A0-0x200을 해야지 헤더의 위치로 부터 계산한 값 자리에 가면 있다는 말이 됩니다.
그렇기 때문에 0x293A0 입니다
이걸 Hex값으로 넣을려면 A0 93 02 가 되구요.
그럼 BT의 위치는 어떻게 하는가? BT의 위치는 0x295A0에서 HT의 크기(Size)만큼 더해주시면 됩니다.
0x218~21B = HashTableSize라고 말씀 드렸죠? 해당 위치를 보시면 0x40이라고 되있는데 이건 갯수라고 위에서 설명했습니다.
0x40*0x10을 해주시면 0x400이 되고 이게 HT의 크기가 됩니다.
즉, 이렇게 됩니다.
0x210~213 = HashTablePosition - 0x200 = 0x293A0
0x214~217 = HashTablePosition - 0x200 + (HashTableSize*10) = 0x293A0+0x400 = 0x297A0
요약 하면 이렇게 됩니다.
이제 저장하시고 맵을 열어 보세요!
네 수고하셨습니다.
강좌는 이걸로 끝내도록 하겠습니다.
마지막엔 살짝 귀찮아져서;; 대충 쓰긴 했습니다
제가 살짝 긴 강좌는 오랜만이라 영어를 썻다가 한글을 썻다가 왔다갔다 했네요; 조금 이해하기 어려운 부분이 존재할 수도 있습니다.
따로 상세한 질문은 안받습니다.
Sprotect에 대한 강좌가 조금씩 풀리고 있길래 이번 기회에 워크의 구조를 어느정도 소개 했습니다.
음.. 마지막으로 외전 사진하나 찍고 끝내볼까욧!?
한 4~5달전에 만들어둔 GTConvert라는 프로그램 입니다.
사실 저는 이런식으로 풀어서 긴 설명하는게 귀찮아 질뻔 했는데; 후.. 그래도 열심히 하시는 분 계시니까 이런식으라도 소개 할 수 있어서 나름 재미없었네요.
아 SSProtect는 이걸 잘 읽어보시고 응용 하시면 가능합니다. ㄹㅇ임;
그래서 따로 강좌는 없음 ㅎㅎ;; 잠수 수고링
문의는 안받지만 틀린점있으시면 지적 해주시면 감사하겠습니다.
그럼 다들 수고하세요 ^^
'강좌 > 수정법' 카테고리의 다른 글
4. 헥스 심화과정 (0) | 2017.02.27 |
---|---|
3. 헥스 푸는방법 - Spazzlar (27) | 2015.03.09 |
2. 맵 수정 시작 (69) | 2015.01.06 |
1. 맵 수정 시작하기 전 (9) | 2015.01.06 |