프로텍트 해석과 기계어
프로텍트를 제거하려면 무엇보다도 기계어를 모르고서는 더 이상 이야기할 수 없습니다. 라고는 해도 딱히 모든 명령을 알고있을 필요는 없습니다. 프로텍트에 사용되는 명령, 알고리즘은 거의 정해져있기 때문입니다.
그런고로, 여기서는 기계어는 어느정도 알고있다는 것으로 하고 그 사용법, 특히 IOCS 콜 등에 대해서 다뤄보려고 합니다. 말하는 걸 잊었는데, 디버거는 필수품입니다.
(1) IOCS 콜에 관하여
우선, 체커에 자주 사용되는 IOCS 콜에 대해서 조금 설명을 해둘까합니다. 디스크 관계의 IOCS 콜은 $40$는 16진수라는 의미번대에 있는데, 자주 사용되는 것은 다음에 소개되는 것 정도입니다.
$40 시크 B_SEEK 헤드를 특정 위치까지 가지고 간다.
$42 리드 다이어그 B_READDI 진단을 위해 읽기 = 특수 데이터를 읽을 수 있다.
$46 리드 데이터 B_READ 보통의 읽기.
$4A 리드 ID B_READID 트랙의 섹터 길이를 반환하도록 되어있으나,
ROM의 버그 때문에 제대로 동작하지 않는다.
스테이터스만 의미가 있다.
다음에는 IOCS 콜을 실행할 때 각 레지스터의 내용에 대해서 설명합니다. 레지스터의 뒤의 괄호 속에는 유효한 사이즈입니다. (자세한 것은, SHARP “프로그래머즈 매뉴얼” 참조)
D0 (바이트8비트) IOCS콜 번호가 들어있다.
D1 (워드16비트) PDAPeripheral Device Address(주변기기 주소) & MODE가 들어있다.
다시말해 사용 드라이브, FM단밀도/MFM배밀도 전환, 리트라이를 하는지 시크를
하는지를 나타낸다. 보통은 $9070나 $9170이 된다 (각각 드라이브 0, 1) .
$9070 : pda = $90 드라이브 0, 드라이브 1이라면 $91
mode = %0111_0000 = $70 bit6 MFM, bit5 리트라이한다, bit4 시크 동작 후 실행
D2 (롱 워드32비트) 디스크상의 목적 섹터 위치와 그 섹터의 길이를 나타낸다.
(예) D2 = $034C0105 의 경우 인간이 알아보기 쉽게 $03_4C_01_05로 표기 가능하다
섹터 길이 $3 = 1024바이트
(2 = 512, 1 = 256 …)
트랙 $4C = 76 트랙
(0 ~ $4C)
사이드 $01 = 사이드1
(0 ~ 1)
섹터 $05 = 제5섹터
(1 ~ 8)
또, 디버거에서는 레코드라는 단위를 사용합니다만, 이것을 레코드로 고쳐쓰면
($4C × 2 + 1) × 8 + 5 – 1 = $4CC
가 됩니다. 레코드라는 것은 선두의 섹터를 0 레코드로 했을 때의 번호입니다.
D3 (롱 워드) 읽기, 또는 쓰기의 길이를 나타낸다.
A1 (롱 워드) 읽기, 또는 쓰기의 어드레스를 나타낸다.
그러면 여기에서 하나의 예를 들어봅시다.
moveq #$42, d0 * iocs콜 실행을 위한 지정: moveq #[iocs 콜 번호], d0
move.w #$9070, d1 * $9070 -> Drive 0
move.l #$034C0105, d2 * 읽을 위치 지정
move.l #$1DF, d3 * 읽어들일 바이트수 $1DF -> 479
lea $80000, a1 * A1 레지스터에 $80000이라는 주소를 넣어주는 명령
trap #$0f * iocs콜을 실행시키는 마지막 명령 trap15
* #$ -> 데이터 $ -> 주소 또는 데이터
위의 프로그램은 어떤 소프트웨어 체커의 일부입니다만, 이제는 대략 무엇을 하는지 알겠지요. 그렇습니다, $80000에 드라이브 0 디스크의 데이터를 리드 다이어그로 읽어들인다는 것입니다.
여기까지의 정리로 우선 체커를 찾으려면 위의 IOCS 콜이 사용되고 있는 부분을 찾으면 됩니다. 다시말해,
$7040, $7042
$7046, $704A
* "moveq #[iocs 콜 번호], d0" 을 기계어로 바꾸면 "$70[iocs 콜 번호]"
여기서 번호가 $40이면 $7040, $42면 $7042 ...
이것을 서치해보면, 체커일듯한 부분을 대부분 발견하게 됩니다.
자, 찾은 뒤에는 체커를 바꿔 써넣을 차례입니다만, 어디를 바꿔 쓰면 좋을까요? 우선, 체커일듯한 부분의 주변을 살펴보면
clr.l d0
rts
moveq #$ff, d0
rts
와 같은 부분을 찾을 수 있을 것입니다. 이것은 무엇을 하는 것인가 하면, 체커로 조사한 결과를 d0 레지스터에 넣는 것입니다. clr.L은 long word(32비트)를 의미. 32비트 값 모두를 0으로 만든다 이라는 명령은 레지스터를 0으로 하는 명령이고 moveqmove quick라는 것은 레지스터에 1바이트의 값을 넣는 명령입니다. 여기에서는 $FF이므로 d0에 -1을 넣는 것입니다.$ff는 16진수 FF를 의미하며, 이는 10진수로 255에 해당하고, 8비트 부호 있는 정수(signed integer)로는 -1로 해석된다
결국, 위와 같은 체커에서는 OK의 경우 d0 = 0, 걸린 경우는 d0 = -1이 된다는 것입니다. 여기서, 바꿔 써 넣을 때는 프로텍트에 걸린 경우에도 d0 = 0을 반환하도록 하면 되므로, $FF를 $00으로 바꿔주면 됩니다.
이렇게, 체커 제거는 걸린 경우도 가능한 OK의 경우와 같은 상태로 만들어 주는 것이 기본입니다. 그러나, 언제나 위와 같이 간단히 풀리지는 않습니다. 암호가 걸려있는 경우도 많으나 기본은 동일합니다.







댓글 남기기