게임 수정자 만드는 방법, 간단하게 만들어보세요

게임 수정자 제작 - 해킹 소개

도구: SoftICE, Kingsoft Ranger 2002, VC 7.0, PE 뷰어, SPY

테스트 플랫폼: Window2000 Professional SP2 < /p>

우선 사용할 도구를 소개하겠습니다.

1. SoftICE(더 말할 필요도 없이 사용하시면 될 것 같습니다)

2 , Kingsoft Ranger 2002 (이것도 사용할 수 있어야 함)

3. VC 7.0 (사용 방법을 꼭 알아야 할 필요는 없지만 최소한 하나의 프로그래밍을 알아야 함) 도구)

4. PE 뷰어(원하는 대로 찾을 수 있습니다. 없어도 상관없습니다. SoftICE를 사용하여 보는 방법을 알려드리겠습니다.)

< p>5. SPY(프로그램 정보를 보기 위한 VC의 도구로, Delphi 및 C Builder의 WinSight32와 같은 다른 도구와 함께 사용할 수 있습니다)

그러면 알아야 할 지식은 다음과 같습니다.

1. 어셈블리 기본 사항

2. 적어도 나를 이해해야 할 몇 가지 API 함수 소개

3. PE 파일 구조의 기본을 알면 설명드리겠습니다

위의 사항을 모두 갖추셨다면 시작하겠습니다.

내가 가르쳐주고 싶은 내용을 소개하겠습니다. 모두가 PC 게임을 해본 적이 있을 것이므로 Diablo, Red Alert 및 Monopoly와 같은 클래식 게임에는 모두 고유한 특수 수정자가 있을 것입니다. 참고로, 저는 클래스에 대한 일반적인 수정 도구를 말하는 것이 아닙니다. .

Red Alert 2에서 Kingsoft Ranger를 사용하여 돈을 수정해 보셨나요? 이 게임은 메모리를 동적으로 할당하고 다시 시작할 때마다 변경되기 때문에 플레이할 때마다 변경해야 한다는 점을 알아야 합니다. 따라서 온라인에 접속하여 특별한 수정자를 다운로드하기로 결정한 적이 있습니까? 생각해 보셨나요? 그럼 왜 하지 그래? 그렇지 않은 것은 무엇입니까? 이 튜토리얼을 읽고 나면 쉽게 알 수 있습니다. D 더 이상 고민하지 않고 원리를 설명하겠습니다.

게임을 자주 수정하는 친구들은 게임 내 '아이템'의 메모리 주소가 동적이든 아니든 상관없이 아이템 사이의 거리가 변하지 않는다는 것을 알고 있을 것입니다. Legend"의 예를 들어, 처음에 Jinshan Ranger를 사용하여 내부 힘 값의 메모리 주소를 찾았고 찾은 결과는 79F695C였으며 항목 "Jinchuang Medicine"의 주소는 328D1DC였습니다. 이제 328D1DC를 에서 뺍니다. 79F695C, got: 4769780, 이 숫자는 내부 힘 값과 황금 약 사이의 오프셋 값입니다. 그럼 아직 끝나지 않았습니다. 이제 게임을 다시 실행하고 내부 force 값의 주소를 검색하여 798695C를 얻습니다. 그런 다음 Jin Chuangyao를 검색하여 두 값의 메모리 주소를 얻습니다. ​변경되었지만 내부 강제 값의 주소에서 Jin Chuang Yao의 주소를 뺀 결과는 무엇입니까? 그렇죠, 여전히 4769780입니다. 즉, 이 두 값의 메모리 주소가 아무리 커져도 이 게임뿐만 아니라 적어도 게임 전반에서는 그 사이의 거리가 변하지 않습니다. 's: D

위에서 말한 내용은 결론으로 ​​이어집니다. 즉, 이 두 주소 중 하나를 얻으면 다른 주소도 얻을 수 있다는 것입니다. 당신은 그들 사이의 오프셋이 얼마나 많은지 알고 있습니다.

우리가 해야 할 첫 번째 단계는 이 주소를 얻는 것입니다. 그러나 메모리의 주소는 동적으로 변경되므로 이를 얻는 것은 쓸모가 없습니다. 절대 바꾸지 마세요! 계속해서 "The New Legend of Chu Liuxiang"을 예로 들겠습니다. 이 게임이 있으면 저와 함께 하세요. 이 단계를 이해하시면 됩니다.

시작!

먼저 게임에 들어가서 내부 값의 주소를 검색하고 다음을 얻습니다: 798695C(왜 업스트림이 다시 시작할 때마다 메모리 주소를 변경하지 않는지 모르겠습니다), Ctrl D를 누릅니다. SoftICE를 열고 BPM 798695C W(이 주소를 쓸 때 중단) 명령을 실행하고, 게임으로 돌아가서 캐릭터 속성 패널을 열고, 게임이 중단되면 SofitICE에 다음 명령이 표시됩니다.

0047EB17 MOV EAX [EDX 000003F4] 명령을 실행하십시오: D EDX 3F4 그러면 내부 강제 값이 표시됩니다.

0047EB1D PUSH EAX

… ……………

… 이는 일반적인 주소 지정 방법입니다. EDX에서 기본 주소에 도달하면 언제든지 EDX 3F4를 사용하여 쉽게 내부 강제 값의 주소를 얻을 수 있습니다. 변경되지 않습니다. EDX의 주소만 변경되면 EDX에서 값을 얻으면 모든 것이 더 쉬워집니다. 그래도 이해가 안 되시면 다시 읽어보세요. 지금 해야 할 일은 이 값을 얻는 방법입니다. 아래에서 방법을 가르쳐 드리겠습니다.

내 방법은 EDX의 값을 주소에 저장하는 코드 조각을 설계하는 것입니다. 그런 다음 이 코드를 실행하세요. 게임의 원래 지침으로 돌아가서 계속 실행하세요. 패치 기술? SMC? 무슨 말을 하든 정상적으로 실행된다면 모든 것이 괜찮을 것입니다. D

실제 작업:

먼저 프로그램에서 빈 공간을 찾아 우리가 설계한 코드를 저장하세요. PE 파일 구조를 아는 사람이라면 일반적으로 EXE 파일의 데이터 세그먼트(.data 세그먼트) 끝에 버퍼 영역이 있다는 것을 알 것입니다. "90대법" "빈 공간 찾기"도 사용할 수 있지만, 그래도 내가 가르쳐 준 방법을 사용하는 것이 좋습니다. 위에서 언급한 것처럼 PE 파일 보기 도구가 없으면 SoftICE를 사용하여 보는 방법을 알려드릴 수 있으며 이 방법은 매우 간단합니다. MAP32 "모듈 이름"이라는 명령만 있으면 됩니다. 내가 하면 당신도 알게 될 것이다.

Ctrl D는 SoftICE를 호출한 다음 MAP32 CrhChs 명령을 실행합니다. 이때 주의해야 할 것은 .data 세그먼트입니다. 데이터 세그먼트 끝을 찾고 있으므로 다음 세그먼트부터 시작하여 다음과 같이 위쪽으로 검색합니다.

.data 004FB000

.rsrc 00507000

.data의 다음 세그먼트는 00507000에서 시작합니다. 이는 00507000에서 1바이트 위쪽이 데이터 세그먼트의 끝임을 의미합니다. 오랫동안 이야기한 후에 우리는 무엇을 합니까? 코드는 어떻게 생겼나요? 수정된 명령어는 어떤 모습인가요? 걱정하지 마세요. 아래를 살펴보세요.

0047EB17을 수정한 후의 코드:

0047EB17 JMP 00506950 //실행할 코드로 점프

0047EB1C NOP // 이 명령어의 원래 길이는 6바이트이고 수정된 길이는 5바이트이므로 빈 명령어를 사용하여 이를 채웁니다.

0047EB1D PUSH EAX

// 코드:

00506950 MOV DWORD PTR EAX, [EDX 00003F4] //파괴된 명령어 복원

00506956 MOV DWORD PTR [00506961], EDX //EDX를 00506961로 저장

0050695C JMP 0047EB1D //원래 명령어로 돌아가 실행

SoftICE의 A 명령어를 이용하여 위의 코드를 작성, OK!

이제 실행 효과를 시도해 보겠습니다. 이제 Jinshan Ranger를 사용하여 내부 강제 주소를 검색해 보겠습니다. 그게 변하지 않는다면 왜 우리는 여전히 그렇게 많은 노력을 기울여야 하는가? 이 주소를 기록하고 게임으로 돌아갑니다. Ctrl D는 SoftICE를 호출하고 D *[00506961] 000003F4 명령을 실행합니다. 데이터 창에 무엇이 표시됩니까? ㅎㅎ 네, 방금 외운 주소를 봤습니다. 안에 있는 값이 바로 내부 힘의 값입니다. 바꿔서 게임을 돌려보세요. ㅋㅋㅋ 내부 힘의 값이 바뀌었군요. D

< p> 현재 우리는 90개의 작업을 완료했지만 너무 기뻐하지 마세요. 다음 10개는 처음 90개보다 훨씬 오래 걸릴 것입니다. 왜냐하면 이 모든 것을 달성하려면 프로그래밍을 사용해야 하기 때문입니다. 지금처럼 매번 하지 말고 한 번만 해보세요!

이제 프로그래밍 단계에 대해 이야기하겠습니다.

먼저 FindWindow 함수를 사용하여 창 핸들을 가져온 다음 GetWindowThreadID 함수를 사용하여 창 핸들에서 프로세스 ID를 가져옵니다. 그런 다음 OpenProcess를 사용하여 프로세스의 ID 읽기 및 쓰기 권한을 얻은 다음 마지막으로 WriteProcessMemory 및 ReadProcessMemory를 사용하여 메모리를 읽고 씁니다. . . .

하하, 수정자가 준비되었습니다: D

다음은 제가 이전에 작성한 수정자 소스 프로그램의 일부입니다. 첫 번째 부분은 지금 코드를 동적으로 작성하는 것이고, 두 번째 부분은 읽고 수정하는 것입니다. 내부 강제 값입니다. 정렬하고 테스트할 시간이 없으므로 오류가 없다고 보장할 수 없습니다. 누락된 항목이 있으면 QQ에 메시지를 남기거나 저에게 메시지를 보내주세요. 다음과 같습니다:

몇 가지 주의 사항:

1. 기계어 코드를 작성할 때는 바이트 단위로 작성하세요.

2. 먼저 게임 내 코드를 수정하세요. (다음 코드는 영향을 주지 않기 때문에 이를 수행하지 않지만 이 문제에 주의해야 합니다.)

#define MY_CODE5 0x00

#define MY_CODE6 0x90

/ /00506950

#define MY2_CODE1 0x8B

#define MY2_CODE2 0x82 //이 부분은 상수 정의입니다. 작성할 기계어 코드

#define MY2_CODE3 0xF4< /p>

#define MY2_CODE4 0x03

#define MY2_CODE5 0x00

#define MY2_CODE6 0x00< /p>

#define MY3_CODE1 0x89

#define MY3_CODE2 0x15

#define MY3_CODE3 0x61

#define MY3_CODE4 0x69

#define MY3_CODE5 0x50

#define MY3_CODE6 0x00

#define MY4_CODE1 0xE9

#define MY4_CODE2 0xBC

#define MY4_CODE3 0x81

#define MY4_CODE4 0xF7

# 정의 MY4_CODE5 0xFF

//--------- ------- ----------------- ---------//

DWORD A1 =MY_CODE1;

DWORD A2 =MY_CODE2;

DWORD A3 =MY_CODE3;

DWORD A4 =MY_CODE4;

DWORD A5 =MY_CODE5 ;

DWORD A6 =MY_CODE6;

DWORD B1 =MY2_CODE1;

< p>DWORD B2 =MY2_CODE2;

DWORD B3 =MY2_CODE3; / /변수 정의 부분입니다.

DWORD B4 =MY2_CODE4;

DWORD B5 =MY2_CODE5;

DWORD B6 =MY2_CODE6;

DWORD C1 =MY3_CODE1;

DWORD C2 =MY3_CODE2;

DWORD C3 =MY3_CODE3 ;

DWORD C4 =MY3_CODE4;

DWORD C5 =MY3_CODE5;

DWORD C6 =MY3_CODE6;

<

p>DWORD D1 =MY4_CODE1;

DWORD D2 =MY4_CODE2;

DWORD D3 =MY4_CODE3;

DWORD D4 =MY4_CODE4;

DWORD D5 =MY4_CODE5;

//-------------------------------------- ------------ ------------------------- -------//

HWND hWnd = :: FindWindow("CRHClass", NULL); //창 핸들 가져오기

if(hWnd ==FALSE)

MessageBox("게임이 실행되고 있지 않습니다!");

else

{

GetWindowThreadProcessId(hWnd, amp; hProcId) ; // 창 핸들에서 프로세스 ID 가져오기

HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS |PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|

PROCESS_VM_WRITE, FALSE, hProcId) //프로세스 열기 읽기 및 권한을 얻습니다.

if(nOK ==NULL)

MessageBox("Error opening process");

else

{

//0047EB17

WriteProcessMemory(nOK, (LPVOID )0x0047EB17,&A1,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x0047EB18, &A2,1,NULL);

WriteProcessMemory(nOK,(LPVOID) )0x0047EB19,&A3,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x0047EB1A,&A4,1 ,NULL);

WriteProcessMemory(nOK,(LPVOID) )0x0047EB1B,&A5,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x0047EB1C,&A6,1,NULL) ;

//00506950

WriteProcessMemory(nOK, (LPVOID)0x00506950, & B1, 1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506951 , & B2, 1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506952, & B3, 1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506953, & B4, 1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506954, amp; B5, 1, NULL);

WriteProcessMemory(n

OK, (LPVOID) 0x00506955, & B6, 1, NULL)

//두 번째 문장

WriteProcessMemory (nOK, (LPVOID) 0x00506956, & C1, 1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506957,&C2,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x00506958,&C3,1, NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506959,&C4,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x0050695A,&C5,1, NULL);

WriteProcessMemory (nOK, (LPVOID)0x0050695B, amp; C6, 1, NULL);

//마지막 문장

WriteProcessMemory(nOK, (LPVOID)0x0050695C,&D1,1,NULL) ;

WriteProcessMemory(nOK,(LPVOID)0x0050695D,&D2,1,NULL);

WriteProcessMemory(nOK, (LPVOID)0x0050695E,&D3,1,NULL);

WriteProcessMemory(nOK,(LPVOID)0x0050695F,&D4,1,NULL);

WriteProcessMemory(nOK, (LPVOID)0x00506960,&D5,1,NULL);

< p>CloseHandle(nOK); //프로세스 핸들 닫기

}

}

}

////// ///////////////////////////////////////////////// ///////////////////////////////////////////////// //////////////////////////////////////////////// ///////////////////////////////////////////// //// //////////

//내부 강제 값을 읽고 수정합니다.

DWORD hProcId;

HWND hWnd =:: FindWindow( "CRHClass", NULL);

if(hWnd ==FALSE)

MessageBox("No");

else

< p> {

GetWindowThreadProcessId(hWnd,&hProcId);

HANDLE nOK =OpenProcess(PROCESS_ALL_ACCESS|PROCESS_TERMINATE|PROCESS_VM_OPERATION|PROCESS_VM_READ|

PROCESS_VM_WRITE,FALSE, hProcId);< /p>

if(nOK ==NULL)

p>

MessageBox("ProcNo!");

else

{

DWORD buf1;

DWORD write;< /p>

BOOL OK=ReadProcessMemory(nOK, (LPCVOID)0x00506961, (LPVOID)amp; buf1, 4, NULL) //EDX에 저장한 기초 읽기

if(OK = =TRUE)

{

write =buf1 0x000003F4; //내부 강제 값의 주소를 가져옵니다.

DWORD Written =0x00; 수정됨< /p>

BOOL B =WriteProcessMemory(nOK,(LPVOID)write,amp;Writeed,1,NULL);

if(B==FALSE)

MessageBox( "WriteNo");

}

}

CloseHandle(nOK);

}

아, 오늘은 여기까지입니다. 저는 별로 재능이 없어서 필연적으로 VC를 사용하는 것을 좋아하지 않는 경우 조언을 부탁드립니다. , QQ에서 저와 소통하실 수 있으며 Delphi, C Builder, Win32Asm 또는 VC에서 위와 동일한 기능을 구현하는 방법을 가르쳐 드릴 수 있습니다.

(이 기사를 재인쇄할 경우 내용과 작성자를 변경하지 마세요!)

저자: CrackYY

이메일: CoolYY@msn.com

p>< p>OICQ: 20651482

2001년에 Yunfeng에게서 IDA 같은 좋은 것들을 배웠어요. 그가 Caesar의 게임 자원을 해결하는 걸 보고 재미있다고 생각해서 스스로 뭔가를 해결하기 시작했어요. 당시에는 몇 가지 게임 리소스를 한 번에 풀었습니다. 물론 그다지 복잡하지는 않았습니다. 주로 대만과 일본에서 나온 것들이었습니다.

나중에 홈페이지에 잠시 올려두었습니다. 관심있는 친구들이 꽤 많았던 기억이 있는데, 아직 얘기할 시간이 없었는데 이제 어떻게 해야할지 얘기해보겠습니다 :)

도구는 당연히 IDA+SoftIce 입니다. 압축해제 프로그램을 직접 작성하려면 익숙한 편집기도 필요합니다. 물론 저는 VC를 사용합니다.

사실 리소스 크래킹은 크게 세 가지 방법이 있습니다. p>1. 하드 크래킹

대상 파일과 디스어셈블리 코드를 관찰하여 리소스 압축이나 암호화된 형식을 분석하고, 파일을 읽고 수정하는 프로그램을 작성하여 인식할 수 있는 형식으로 변환합니다. .

직접 리소스를 디코딩할 때 생각하기 가장 쉬운 방법입니다

Specific 즉, fopen 등 파일 관련 함수 등 일부 특정 기능을 사용한다는 의미입니다. 그리고 createFile을 사용하여 게임의 리소스 솔루션 기능을 파악한 후 필사적으로 어셈블리 코드를 분석합니다.

초기 리소스의 대부분은 이렇게 크랙하는 방식입니다. UEDIT를 사용하여 분석하는 것이 가장 좋습니다. 일부 형식은 너무 간단합니다. 파일 크기만 보면 됩니다.

이때 제가 해결한 방법 중 가장 복잡하다고 느꼈습니다. GIF와 유사하지만 동일하지는 않습니다. 그래서 압축 알고리즘에 대해 자세히 연구하지 않았습니다. 그러나 나중에 인터넷에서 매우 일반적인 압축 알고리즘이라는 기사를 읽었습니다. 압축 해제 도구를 사용하여 압축을 풀 수 있습니다. ◎#PY%... 정말 답답합니다(다행히 게임 압축을 푸는 데 몇 시간밖에 걸리지 않았습니다.

2, Dump

이미지가 로드된 후 메모리에서 직접 내보냅니다.

이 접근 방식도 생각하기 쉽습니다. 가장 큰 어려움은 메모리의 리소스 형식에 있습니다. 3D 게임은 더 쉽습니다. 결국 텍스처 렌더링은 소프트웨어가 아닌 그래픽 카드로 수행됩니다.

어떤 사람들은 OpenGL의 일부 기능을 연결하여 이런 방식으로 월드 오브 워크래프트의 리소스를 잠금 해제했다는 것을 알게 되었습니다.< /p>

레이싱 게임에 대해서는 이와 같은 일부 게임 텍스트(중국어 텍스트)를 해독했습니다. 게임 텍스트를 모두 얻기 위해 게임이 클리어되었다고 구체적으로 말했습니다.

3. 게임의 디코딩 호출 디코딩 함수

두 번째 방법과 비슷하지만, 함수를 적극적으로 호출하면 기본적으로 게임을 클리어할 필요 없이 모든 리소스를 한 번에 잠금 해제할 수 있습니다.

< p>물론 게임 Unpacking 모듈을 호출하라는 메시지가 표시되지 않습니다. 결국 많은 게임이 dll 형식이 아닙니다.

게임 프로세스에 침입하여 적절한 시간을 찾을 수만 있습니다(보통 다른 파일을 로드할 때 인터럽트 및 점프를 먼저 수행한 후) 내부 함수를 호출하여 모든 리소스를 잠금 해제합니다.

이 방법을 사용하여 게임을 해결했는데, 리소스 압축률이 입니다. 해당 게임은 rar 0과 거의 동일합니다. 요구 사항 문서

LZW 압축 알고리즘은 Lemple-Ziv-Welch가 공동으로 개발한 새로운 압축 방법으로, 그 이름은 다음과 같습니다. 그들을. 처음 나타나는 각 문자열을 문자열 테이블에 넣고 숫자를 사용하여 문자열을 나타내는 고급 문자열 테이블 압축을 사용합니다. 개선되었습니다. 놀라운 점은 압축 또는 압축 해제 중에도 이 문자열 테이블이 올바르게 설정될 수 있다는 것입니다. 압축 또는 압축 해제가 완료된 후에는 이 문자열 테이블이 삭제됩니다.

1. 기본 원리

먼저 문자열 테이블을 만들고, 처음 나타나는 문자열을 문자열 테이블에 넣고 숫자로 표현합니다. as 이 문자열은 문자열 테이블에서의 위치와 관련되며 이 숫자는 압축 파일에 저장되며, 이 문자열이 다시 나타나면 이를 나타내는 숫자로 대체될 수 있으며 이 숫자가 파일에 저장됩니다. 압축이 완료된 후 문자열 테이블은 삭제됩니다. 예를 들어, 압축 중에 "print" 문자열이 266으로 표시되면 다시 나타나는 한 266으로 표시되고, 숫자 266을 만나면 "print" 문자열이 문자열 테이블에 저장됩니다. 디코딩하는 동안 문자열 테이블에서 검색할 수 있습니다. 266으로 표시된 문자열 "print"는 압축 해제 중에 압축된 데이터를 기반으로 문자열 테이블을 재생성할 수 있습니다.

2. 구현 방법

A. 문자열 테이블 초기화

정보를 압축할 때 먼저 문자열이 처음 나타날 때마다 기록하는 문자열 테이블을 만듭니다. 문자열 테이블은 최소한 두 개의 문자 배열로 구성됩니다. 하나는 현재 배열이라고 하고 다른 하나는 접두사 배열이라고 합니다. 파일의 각 기본 문자열 길이는 일반적으로 2입니다(그러나 그것이 나타내는 실제 문자열 길이는 최대 2일 수 있음). 수백 또는 수천까지) 기본 문자열은 현재 문자와 그 앞의 문자(접두사라고도 함)로 구성됩니다. 문자열의 첫 번째 문자는 접두사 배열에 저장되고 문자열의 마지막 문자는 현재 배열에 저장됩니다. 따라서 아래 첨자가 결정되는 한 저장되는 기본 문자열은 동일합니다. 결정되므로 데이터 압축 시 기본 문자열 대신 아래 첨자가 사용됩니다. 일반적으로 스트링 테이블의 크기는 4096바이트(즉, 2의 12승)입니다. 이는 최대 4096개의 기본 스트링이 스트링 테이블에 저장될 수 있음을 의미합니다. 초기화 중에 스트링 테이블은 숫자에 따라 초기화됩니다. 파일의 문자 수입니다. 시작 위치의 바이트는 모두 할당된 숫자입니다. 일반적으로 현재 배열의 내용은 요소의 일련 번호(즉, 아래 첨자)입니다. 예를 들어 첫 번째 요소는 0이고 두 번째 요소는 1입니다. , 15번째 요소는 14입니다. 아래 첨자는 문자 수에 요소 2개를 더한 값입니다. 문자 수가 256이면 258번째 바이트로 초기화되며 이 바이트의 값은 257입니다. 숫자 256은 삭제 코드를 나타내고 숫자 257은 파일 끝 코드를 나타냅니다. 다음 바이트는 파일에서 문자열이 처음 나타나는 각각을 저장합니다. 콘서트 프리픽스 배열의 초기화도 필요하며, 각 요소의 값은 임의의 숫자이지만 일반적으로 각 위치는 1로 설정되고 시작 위치의 각 요소는 0XFF로 초기화됩니다. 현재 배열과 동일하고 후속 요소 그런 다음 문자열이 처음 나타나는 각각을 저장해야 합니다. 스트링 테이블의 길이를 늘리면 압축 효율은 더욱 향상될 수 있지만 디코딩 속도는 느려집니다.

B. 압축 방법

압축 방법을 이해하려면 먼저 몇 가지 명사를 이해해야 하는데, 하나는 문자 흐름, 다른 하나는 코드 흐름, 세 번째는 현재 코드, 네 번째는 현재 접두사입니다. 문자 스트림은 소스 파일의 압축되지 않은 파일 데이터입니다. 코드 스트림은 압축 후 파일에 기록된 압축 파일 데이터입니다. 현재 코드는 문자 스트림에서 방금 읽은 문자입니다. 방금 읽은 캐릭터입니다.

파일을 압축할 때 파일의 문자 수에 관계없이 색상 값을 바이트 단위로 코드 스트림에 넣어야 하며 각 바이트는 색상을 나타냅니다. 소스 파일에서 16색, 4색, 2색을 표현하기 위해 1바이트를 사용하면(1바이트에 4비트가 16색을 표현할 수 있기 때문에) 4비트 이상의 낭비가 발생하지만, LZW Free 비트(바이트)를 사용하면 압축 중에 재활용될 수 있습니다.

압축할 때 먼저 문자 스트림의 첫 번째 문자를 현재 접두사로 읽은 다음 두 번째 문자를 현재 코드로 사용하여 첫 번째 기본 문자열을 구성합니다(예: 현재 접두사는 ​​A이고 현재 코드는 B이고 이 문자열은 AB입니다.) 문자열 테이블을 찾아보면 이번에는 확실히 같은 문자열을 찾을 수 없을 것입니다. 그런 다음 이 문자열을 문자열 테이블에 쓰고 현재 접두사를 접두사 배열, 현재 코드를 현재 배열에 쓰고, 현재 접두사를 코드 스트림으로 보내고, 현재 코드를 현재 접두사에 넣은 다음, 다음 문자, 즉 현재 코드를 읽습니다. 기본 문자열이 형성됩니다(현재 코드가 C이면 기본 문자열은 BC입니다). 문자열 테이블을 조회하고, 그러한 문자열이 있으면 현재 접두사의 값을 버리고 위치 코드(예: 아래 첨자)를 사용합니다. 문자열 테이블의 문자열을 현재 접두사로 읽은 다음 다음 문자를 다음 문자로 읽습니다. 현재 코드는 전체 파일이 압축될 때까지 새로운 기본 문자열을 형성합니다. 압축하는 동안 접두사 배열의 값은 코드 스트림의 문자이고, 문자 수보다 큰 코드는 문자열을 나타내야 하고, 문자 수보다 작거나 같은 코드는 문자임을 알 수 있습니다. 그들 자신.

C. 클리어 코드

실제로 파일을 압축할 때 문자열 테이블을 여러 번 초기화해야 하는 경우가 많으며, 처음으로 나타나는 기본 문자열의 개수가 많은 경우가 많습니다. 파일의 길이가 4096을 초과합니다. 압축 과정에서 문자열 길이가 4096을 초과하는 한 현재 접두사와 현재 코드를 코드 스트림에 입력해야 하며 삭제 코드를 코드 스트림에 추가해야 합니다. 테이블을 초기화해야 하며, 위의 방법에 따라 압축을 계속해야 합니다.

D. 종료 코드

모든 압축이 완료되면 파일 종료 코드는 문자 수에 1을 더한 값으로 출력됩니다. 파일의 종료 코드는 257입니다.

E. 바이트 공간 재활용

파일 출력 코드 스트림에 데이터를 데이터 패킷 형태로 저장하는 것 외에도 모든 코드를 단위로 저장하므로 저장 공간이 효과적으로 절약됩니다. . 이는 4비트 컬러(16색) 파일과 같습니다. 바이트로 저장하면 4비트만 사용할 수 있고 나머지 4비트는 낭비됩니다. 비트로 저장하면 각 바이트는 두 개의 색상 코드를 저장할 수 있습니다. 실제로 파일에서는 가변숫자 저장 방식을 사용하고 있는데, 256색 파일에서는 문자열 테이블 접두사 배열의 각 요소의 값이 규칙적인 것을 압축 과정에서 볼 수 있다. -511 해당 요소의 중앙값 범위는 0~510으로 9자리 이진수로 표현할 수 있다. 512~1023번째 요소의 중앙값 범위는 0~1022로 정확하게 표현할 수 있다. 10자리 이진수로 표현됩니다. 1024~2047번째 요소의 중앙값은 0~2046이며, 이는 정확히 11비트 이진수로 표시됩니다. 2048~4095번째 요소의 값 범위는 0입니다. -4094는 12비트 이진수로 정확하게 표현됩니다. 가변자리수를 사용하여 코드를 저장하는 경우 기본 자리수는 파일의 문자수에 1을 더한 값이 됩니다. 코드수가 증가할수록 자릿수도 늘어나서 자릿수가 12가 될 때까지 늘어납니다. 문자열 테이블의 문자 수 문자열 수는 정확히 2의 12제곱, 즉 4096입니다. 기본 방법은 코드 스트림에 문자가 추가될 때마다 문자열 테이블의 문자열 위치(즉, 아래 첨자)가 2의 현재 자릿수의 거듭제곱을 초과하는지 확인하는 것입니다. 초과하면 자릿수가 1 증가합니다. 예를 들어, 4비트 파일의 경우 시작 부분의 코드가 5비트로 저장되며, 첫 번째 바이트의 하위 5비트가 첫 번째 코드, 상위 3비트가 두 번째 코드의 하위 3비트, 두 번째 바이트 코드의 하위 2비트가 두 번째 코드의 상위 2비트에 배치되는 식입니다. 8비트(256색) 파일의 경우 기본 비트 수는 9이며, 코드는 최소 2바이트 이상 들어가야 합니다.

F. 압축 범위

다음은 파일 인코딩의 예입니다. 주의 깊게 살펴보면 이것이 훌륭한 인코딩 방법이며 문자열 테이블이 없는 이유를 알 수 있습니다. 또한 압축이 완료된 후에는 디코딩 중에 코드 흐름 정보를 기반으로 문자열 테이블을 다시 생성할 수 있습니다.

문자열: 1, 2, 1, 1, 1, 1, 2, 3, 4, 1, 2, 3, 4, 5, 9,…

현재 코드: 2, 1, 1, 1, 1, 2, 3, 4, 1, 2, 3, 4, 5, 9,…

현재 접두어: 1, 2, 1, 1, 260, 1 , 258, 3, 4, 1, 258, 262, 4, 5,…

현재 배열: 2, 1, 1, 1, 3, 4, 1, 4, 5, 9,… < /p>

배열 아래 첨자: 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,...

코드 흐름: 1, 2, 1, 260, 258, 3, 4, 262, 4, 5,…

3. 테스트 문서

지침:

선택 시 1~ 3, 다른 데이터를 선택하면 오류가 발생합니다.

4. 문서 사용

프로그램에 들어간 후 프로그램을 압축할지, 압축을 풀지, 종료할지 선택하세요.

압축된 파일:

1) 프롬프트: "파일 이름을 입력하시겠습니까?" 입력: D:\cc\test.txt

2) 프롬프트: "압축됨" 파일 이름?" 입력: test.lzw

3) 표시: "압축 중......" 및 "*"는 파일 압축 진행률을 나타냅니다.

참고: 입력한 파일이 없으면 올바른 파일 위치와 파일 이름을 입력할 때까지 메시지가 반복됩니다. 생성된 test.lzw는 프로그램의 루트 디렉터리에 저장됩니다.

예: 프로그램이 D:\cc\에 있으면 생성된 파일도 D:\cc\에 있습니다.

압축 풀기:

1) 팁: "파일 이름을 입력하시겠습니까?" 입력: test.lzw

2) 프롬프트: "압축된 파일 이름을 입력하시겠습니까?" 입력: test.txt

3) 표시: " 확장......”과 “*”는 파일 압축 해제 진행 상황을 나타냅니다.

참고: 입력한 파일이 없으면 올바른 파일 위치와 파일 이름을 입력할 때까지 메시지가 반복됩니다. 생성된 test.lzw는 프로그램의 루트 디렉터리에 저장됩니다.

ANI(APPlicedon Startins Hour Glass) 파일은 MS-Windows용 애니메이션 커서 파일이며 파일 확장자는 ".ani"입니다. 일반적으로 텍스트 설명 영역, 정보 영역, 시간 제어 영역 및 ACONLIST 블록인 데이터 영역의 네 부분으로 구성됩니다. anih 블록, rate 블록 및 LIST 블록.

다음은 파일 내용(데이터 E)과 ANI 파일 표준 구조 다이어그램(그림)을 예시로 보여줍니다.

1. From (0000-006D)는 Wnd0WS 95 & NT ANI 파일의 텍스트 설명 영역 부분입니다

개발한 ANI 파일에 대한 간단한 텍스트 설명을 제공하고 저작권 정보를 추가하려는 경우 동시에 ANI 파일 재생 소프트웨어에서 인식되는 경우 이것이 유일한 옵션입니다. 이것이 번거롭다고 생각되거나 쓸 내용이 없다면 이 블록의 내용을 모두 제거하고 블록 크기를 0으로 설정하면 됩니다. "블록 식별 코드

'ACONLIST'"와 식별 "블록 크기"의 두 부분(총 12바이트)은 변경, 이동 또는 삭제되어서는 안 됩니다. 그렇지 않으면 결과에 대한 책임은 귀하에게 있습니다.

아마도 텍스트 설명 정보를 체계화하기 위해 ACONLIST 블록에는 여러 하위 블록이 포함되어 있습니다. 이 예에서 사용된 두 블록은 INFOINAM 블록(이 문서에 대한 설명 제공)과 IART 블록(용)입니다. 버전 정보 삽입).

솔직히 말하면 AVI 파일에 사용자 정의 블록을 삽입하는 방법을 사용하여 자신만의 사용자 정의 블록을 추가할 수 있습니다. 그 결과 ANI 재생 소프트웨어는 이를 "정크"로 처리합니다.

0000-0003: 멀티미디어 파일 식별 코드: RIFF

0004-0007 파일 크기(2052h 바이트) - 8바이트

0008-000F: ACONLIST 블록 텍스트 설명 영역의 시작 부분을 나타내는 식별 코드

0010-0013: ACONLIST 블록의 크기(5Ah 바이트)

0014-001B: INFOINAM 블록 식별 code, sign 파일 설명 정보 하위 블록의 시작

001C-001F: INFOINAM 블록의 크기(20h 바이트)

0020-003F: 파일의 내용 설명 정보 하위 블록 "애플리케이션 시작시간 유리"

0040-0043: IART 블록 식별 코드, 저작권 표시 정보의 시작을 표시

0044-0047: IART 블록 크기(26h 바이트)

0048- 006D: 저작권 정보는 "Microsoft Corporation, Copyright 1995" 블록의 내용에 있습니다.

2. (006E-0099)부터?