# 게임가드 시스템 분석 보고서

**프로젝트**: NeoRylClient (ROW - Reign of Revolution)
**분석 날짜**: 2025-11-29
**분석 대상**: 안티치트 시스템 (GameGuard + HackShield + AntiHack)

---

## 개요

NeoRylClient는 **3중 안티치트 시스템**을 사용하여 게임 클라이언트를 보호합니다:
1. **nProtect GameGuard** (잉카인터넷) - 기본 보호
2. **AhnLab HackShield** (안랩) - 강화 보호
3. **자체 AntiHack** - 보조 디버거 탐지

---

## 1. nProtect GameGuard

### 위치
- 헤더: `GlobalScript/GameGuardLib/NPGameLib.h`
- 라이브러리: `GlobalScript/GameGuardLib/NPGameLib.lib`
- 서버 통신: `GlobalScript/GameGuardLib/ggsrvlib.lib`

### 주요 기능

#### 보안 기능
- **SpeedHack 탐지**: 게임 속도 조작 프로그램 감지
- **GameHack 탐지**: 메모리 해킹, 치트 프로그램 탐지
- **통신 보안**: 게임 서버와의 양방향 인증
- **패킷 암호화**: 네트워크 패킷 암호화/복호화
- **리소스 인증**: 게임 파일 무결성 검증
- **충돌 프로그램 감지**: 게임과 충돌하는 프로그램 탐지

#### 핵심 API

```cpp
// 초기화
DWORD PreInitNPGameMon(LPCSTR szGameName);
DWORD InitNPGameMon();

// 주기적 체크
DWORD CheckNPGameMon();

// 콜백 등록
void SetCallbackToGameMon(NPGMCALLBACK fnCallback);

// 사용자 인증
BOOL SendUserIDToGameMon(LPCSTR szUserID);
BOOL SendCSAuthToGameMon(DWORD dwAuth);
BOOL SendCSAuth2ToGameMon(PGG_AUTH_DATA pAuth);

// 패킷 암호화
DWORD InitPacketProtect(LPCSTR lpszUserKey);
DWORD EncryptPacket(LPVOID lpData, DWORD dwLength);
DWORD DecryptPacket(LPVOID lpData, DWORD dwLength);

// 종료
BOOL CloseNPGameMon();
```

#### CNPGameLib 래퍼 클래스

```cpp
class CNPGameLib {
public:
    explicit CNPGameLib(LPCTSTR lpszGameName);
    ~CNPGameLib();

    DWORD Init();           // 초기화
    void SetHwnd(HWND hWnd); // 윈도우 핸들 설정
    DWORD Check();          // 주기적 검사
    DWORD Send(LPCTSTR lpszUserId); // 사용자 ID 전송
    LPCSTR GetInfo();       // 정보 조회
    LPBYTE GetHackInfo(DWORD *dwSize); // 해킹 정보 조회
};
```

### 콜백 이벤트 처리

**콜백 함수**: `NPGameMonCallback` (RYLClientMain.cpp:2839)

```cpp
BOOL CALLBACK NPGameMonCallback(DWORD dwMsg, DWORD dwArg)
{
    switch (dwMsg)
    {
        case NPGAMEMON_COMM_ERROR:
            // 통신 오류 → 게임 종료
            MessageBox("게임가드 통신 오류");
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_COMM_CLOSE:
            // 통신 종료 → 게임 종료
            MessageBox("게임가드 통신 종료");
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_INIT_ERROR:
            // 초기화 오류 → 게임 종료
            sprintf(msg, "게임가드 초기화 오류 (Code: %x)", dwArg);
            MessageBox(msg);
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_SPEEDHACK:
            // 스피드핵 탐지 → 게임 종료
            MessageBox("스피드핵이 감지되었습니다");
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_GAMEHACK_KILLED:
            // 게임핵 종료됨 → 계속 진행
            MessageBox("불법 프로그램이 종료되었습니다");
            return TRUE;

        case NPGAMEMON_GAMEHACK_DETECT:
            // 게임핵 탐지 → 게임 종료
            MessageBox("게임핵이 감지되었습니다");
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_GAMEHACK_DOUBT:
            // 의심 프로그램 → 게임 종료
            MessageBox("의심스러운 프로그램이 감지되었습니다");
            PostQuitMessage(WM_QUIT);
            return FALSE;

        case NPGAMEMON_CHECK_CSAUTH2:
            // 서버 인증 코드 수신 → 저장
            memcpy(&m_GGAuthCode.m_AuthCode2, (PVOID)dwArg, sizeof(GG_AUTH_DATA));
            return TRUE;
    }
}
```

### 에러 코드

**초기화 오류** (110-300):
- `NPGAMEMON_ERROR_EXIST (110)`: 게임가드 이미 실행 중
- `NPGAMEMON_ERROR_CREATE (111)`: 디렉토리 생성 오류
- `NPGAMEMON_ERROR_NPSCAN (112)`: npscan.des 오류
- `NPGAMEMON_ERROR_INIT (114)`: 초기화 오류
- `NPGAMEMON_ERROR_AUTH_GAMEMON (122)`: GameMon.des 인증 실패
- `NPGAMEMON_ERROR_NFOUND_GG (153)`: GameGuard.des 파일 없음

**업데이트 오류** (310-400):
- `NPGMUP_ERROR_INIT (330)`: 업데이트 초기화 오류
- `NPGMUP_ERROR_DOWNCFG (340)`: 다운로드 오류
- `NPGMUP_ERROR_CONNECT (380)`: 업데이트 서버 연결 실패

**충돌 오류** (500):
- `NPGG_ERROR_COLLISION (500)`: 충돌 프로그램 감지

### 사용 예시

**RYLNetWorkData.cpp:77**:
```cpp
#ifndef NO_GAMEGUARD
    if (0 != szGameGuardString && 0 != strlen(szGameGuardString))
    {
        m_lpNPGameLib = new CNPGameLib(szGameGuardString);
    }
#endif
```

**LoginoutProcess.cpp:588** (게임 로그인 후):
```cpp
CNPGameLib* lpNPGameLib = CRYLNetworkData::Instance()->m_lpNPGameLib;
lpNPGameLib->Send(userID);  // 사용자 ID 전송
```

---

## 2. AhnLab HackShield

### 위치
- 헤더: `GlobalScript/HShield/HShield.h`
- 라이브러리: `GlobalScript/HShield/HShield.lib`
- 업데이트: `GlobalScript/HShield/HSUpChk.h` / `HSUpChk.lib`

### 주요 기능 (GameGuard보다 강력)

#### 보호 기능

**시스템 레벨 보호**:
- 스피드핵 감지 (5단계 민감도)
- 메모리 읽기/쓰기 프로세스 감지
- 커널 디버거 감지 (KdTrace)
- 프로세스 오픈 감시
- 메시지 후킹 감지
- 프로세스 스캔

**애플리케이션 레벨 보호**:
- 자동 마우스 감지
- 자동 매크로 감지
- API 후킹 감지
- DLL 인젝션 감지
- 모듈 변조 감지
- 코드 불일치 감지

**고급 보호**:
- 화면 보호 (스크린샷 차단)
- 로컬 메모리 보호
- 비정상 함수 호출 감지
- DirectX 보호
- 가상머신 감지
- 자동 파괴 (변조 감지시)

#### 핵심 API

```cpp
// 초기화
int _AhnHS_Initialize(
    const char* szFileNameA,        // EhSvc.dll 경로
    PFN_AhnHS_Callback pfn_Callback, // 콜백 함수
    int nGameCode,                   // 게임 코드
    const char* szLicenseKeyA,       // 라이센스 키
    unsigned int unOption,           // 보호 옵션
    unsigned int unSHackSensingRatio // 스피드핵 민감도
);

// 서비스 제어
int _AhnHS_StartService();
int _AhnHS_StopService();
int _AhnHS_PauseService(unsigned int unPauseOption);
int _AhnHS_ResumeService(unsigned int unResumeOption);
int _AhnHS_Uninitialize();

// 서버 통신
int _AhnHS_MakeAckMsg(unsigned char *pbyReqMsg, unsigned char *pbyAckMsg);
int _AhnHS_MakeGuidAckMsg(unsigned char *pbyGuidReqMsg, unsigned char *pbyGuidAckMsg);
int _AhnHS_MakeResponse(unsigned char *pbyRequest, unsigned long ulRequestLength,
                        PAHNHS_TRANS_BUFFER pResponseBuffer);

// 함수 주소 저장 (CRC 검증용)
int _AhnHS_SaveFuncAddress(unsigned int unNumberOfFunc, ...);

// API 후킹 검사
int _AhnHS_CheckAPIHooked(const char* szModuleName, const char* szFunctionName,
                          const char* szSpecificPath);

// DirectX 래퍼
PVOID _AhnHS_Direct3DCreate9(IN UINT SDKVersion);
PVOID _AhnHS_Direct3DCreate8(IN UINT SDKVersion);

// 모니터링 서비스
int _AhnHS_StartMonitor(IN AHNHS_EXT_ERRORINFO HsExtErrorInfo, IN const char* szFileName);
void _AhnHS_SetUserId(IN const char* szUserID);
BOOL _AhnHS_IsModuleSecure(IN const char* szModulePath);

// 로그 전송
void _AhnHS_SendHsLog(IN DWORD dwError, IN const char* szUserID, IN const char* szHShieldPath);

// 상태 확인
int _AhnHS_CheckHackShieldRunningStatus();
```

### 초기화 옵션

```cpp
// 개별 옵션
#define AHNHS_CHKOPT_SPEEDHACK                  0x2      // 스피드핵 감지
#define AHNHS_CHKOPT_READWRITEPROCESSMEMORY     0x4      // 메모리 읽기/쓰기 감지
#define AHNHS_CHKOPT_KDTRACER                   0x8      // 커널 디버거 감지
#define AHNHS_CHKOPT_OPENPROCESS                0x10     // 프로세스 오픈 감시
#define AHNHS_CHKOPT_AUTOMOUSE                  0x20     // 자동 마우스 감지
#define AHNHS_CHKOPT_MESSAGEHOOK                0x40     // 메시지 후킹 감지
#define AHNHS_CHKOPT_PROCESSSCAN                0x80     // 프로세스 스캔
#define AHNHS_CHKOPT_LOADLIBRARY                0x10000  // LoadLibrary 감시
#define AHNHS_CHKOPT_PROTECTSCREEN              0x20000  // 화면 보호
#define AHNHS_CHKOPT_LOCAL_MEMORY_PROTECTION    0x80000  // 로컬 메모리 보호
#define AHNHS_CHKOPT_ABNORMAL_FUNCTION_CALL     0x100000 // 비정상 함수 호출 감지
#define AHNHS_CHKOPT_ANTIFREESERVER             0x200000 // 프리서버 방지
#define AHNHS_CHKOPT_PROTECT_D3DX               0x1000000 // DirectX 보호
#define AHNHS_CHKOPT_DETECT_VIRTUAL_MACHINE     0x8000000 // 가상머신 감지

// 전체 옵션
#define AHNHS_CHKOPT_ALL (모든 옵션 조합)
```

### 스피드핵 민감도

```cpp
#define AHNHS_SPEEDHACK_SENSING_RATIO_HIGHEST   0x1  // 최고 민감도
#define AHNHS_SPEEDHACK_SENSING_RATIO_HIGH      0x2  // 높은 민감도
#define AHNHS_SPEEDHACK_SENSING_RATIO_NORMAL    0x4  // 보통 민감도 (사용 중)
#define AHNHS_SPEEDHACK_SENSING_RATIO_LOW       0x8  // 낮은 민감도
#define AHNHS_SPEEDHACK_SENSING_RATIO_LOWEST    0x10 // 최저 민감도
#define AHNHS_SPEEDHACK_SENSING_RATIO_GAME      0x20 // 게임용 (5초마다 비율 전송)
```

### 에러 코드

**초기화 오류** (0x00000100-0x00000108):
- `HS_ERR_INVALID_LICENSE (0x100)`: 잘못된 라이센스 키
- `HS_ERR_INVALID_FILES (0x101)`: 잘못된 파일 설치
- `HS_ERR_ANOTHER_SERVICE_RUNNING (0x103)`: 다른 서비스 실행 중
- `HS_ERR_ALREADY_INITIALIZED (0x104)`: 이미 초기화됨
- `HS_ERR_DEBUGGER_DETECT (0x105)`: 디버거 감지
- `HS_ERR_EXECUTABLE_FILE_CRACKED (0x106)`: 실행 파일 크랙됨
- `HS_ERR_NEED_ADMIN_RIGHTS (0x107)`: 관리자 권한 필요

**서비스 오류** (0x00000200-0x00000207):
- `HS_ERR_START_ENGINE_FAILED (0x200)`: 엔진 시작 실패
- `HS_ERR_ALREADY_GAME_STARTED (0x206)`: 게임 중복 실행
- `HS_ERR_VIRTUAL_MACHINE_DETECT (0x207)`: 가상머신 감지

**서버-클라이언트 인증 오류** (0x00010000-0x00010030):
- `HS_ERR_ANTICPCNT_DEBUGGER_DETECTED (0x10030)`: 디버거 감지

**확장 인증 오류** (0xE4010000-0xE40100FF):
- `HS_ERR_ANTICPXCNT_DEBUGGER_DETECTED`: 디버거 감지
- `HS_ERR_ANTICPXCNT_BAD_HSHIELD_MODULE`: 핵쉴드 모듈 손상
- `HS_ERR_ANTICPXCNT_BAD_CLIENT_FILE`: 클라이언트 파일 손상

### 콜백 이벤트

**콜백 함수**: `HS_CallbackProc` (RYLNetWorkData.cpp:1149)

```cpp
int __stdcall HS_CallbackProc(long lCode, long lParamSize, void* pParam)
{
    switch(lCode)
    {
        case AHNHS_ENGINE_DETECT_GAME_HACK:
            // 게임 해킹 툴 발견
            sprintf(szMsg, "불법 해킹툴이 발견되어 프로그램을 종료합니다.\n%s", (char*)pParam);
            MessageBox(NULL, szMsg, "Error", MB_OK);
            break;

        case AHNHS_ENGINE_DETECT_WINDOWED_HACK:
            // 창모드 해킹툴 감지
            MessageBox(NULL, "프로그램 창에 대한 해킹툴이 감지되었습니다.", "Error", MB_OK);
            break;

        case AHNHS_ACTAPC_DETECT_SPEEDHACK:
            // 스피드핵 감지
            MessageBox(NULL, "현재 PC에서 SpeedHack으로 의심되는 프로그램이 감지되었습니다.", "Error", MB_OK);
            break;

        case AHNHS_ACTAPC_DETECT_KDTRACE:
        case AHNHS_ACTAPC_DETECT_KDTRACE_CHANGED:
            // 커널 디버거 감지
            sprintf(szMsg, "프로그램 실행에 커널 트레이스가 발생하였습니다. (Code = %x)\n프로그램을 종료합니다.", lCode);
            MessageBox(NULL, szMsg, "Error", MB_OK);
            break;

        case AHNHS_ACTAPC_DETECT_AUTOMACRO:
            // 매크로 프로그램 감지
            sprintf(szMsg, "매크로 프로그램으로 의심되는 프로그램이 감지되었습니다. (Code = %x)\n프로그램을 종료합니다.", lCode);
            MessageBox(NULL, szMsg, "Error", MB_OK);
            break;

        case AHNHS_ACTAPC_DETECT_ABNORMAL_MEMORY_ACCESS:
            // 비정상 메모리 접근
            sprintf(szMsg, "불법 해킹툴의 메모리 접근이 감지되어 프로그램을 종료합니다.\n%s", (char*)pParam);
            MessageBox(NULL, szMsg, "Error", MB_OK);
            break;

        case AHNHS_ACTAPC_DETECT_AUTOMOUSE:
        case AHNHS_ACTAPC_DETECT_DRIVERFAILED:
        case AHNHS_ACTAPC_DETECT_HOOKFUNCTION:
        case AHNHS_ACTAPC_DETECT_MESSAGEHOOK:
        case AHNHS_ACTAPC_DETECT_MODULE_CHANGE:
        case AHNHS_ACTAPC_DETECT_ENGINEFAILED:
        case AHNHS_ACTAPC_DETECT_CODEMISMATCH:
        case AHNHS_ACTAPC_DETECT_PROTECTSCREENFAILED:
            // 기타 해킹 관련 이상
            sprintf(szMsg, "해킹 관련 기능에 이상이 발생하였습니다. (Code = %x)\n프로그램을 종료합니다.", lCode);
            MessageBox(NULL, szMsg, "Error", MB_OK);
            break;
    }
    return 1;
}
```

### 구현 예시

**초기화** (RYLNetWorkData.cpp:1303):
```cpp
BOOL CRYLNetworkData::InitHShield(HWND hWnd)
{
    // 배틀로한 서버가 아니고, ADMIN_L3가 아닌 경우에만 실행
    if (GameRYL::SERVER_BATTLE_LOHAN != m_eServerType &&
        ADMIN_L3 != g_ClientMain.m_wAdminMode)
    {
#ifdef ON_HACKSHIELD
        int nRet = HS_ERR_OK;
        CHAR szFullFilePath[MAX_PATH];
        DWORD dwOption = 0;

        // HackShield DLL 경로 설정
        sprintf(szFullFilePath, "%s\\HShield\\EhSvc.dll", g_ClientMain.m_strClientPath);

        // 모든 보호 옵션 활성화
        dwOption = AHNHS_CHKOPT_ALL;

        // HackShield 초기화
        nRet = _AhnHS_Initialize(
            szFullFilePath,                          // DLL 경로
            HS_CallbackProc,                         // 콜백 함수
            5750,                                    // 게임 코드
            "15E4BF63F549784BECC7FC70",            // 라이센스 키
            dwOption,                                // 보호 옵션
            AHNHS_SPEEDHACK_SENSING_RATIO_NORMAL    // 스피드핵 민감도
        );

        // 초기화 오류 처리
        if (nRet != HS_ERR_OK)
        {
            switch(nRet)
            {
                case HS_ERR_ANOTHER_SERVICE_RUNNING:
                    MessageBox(NULL, "다른 서비스가 실행중입니다.\n프로그램을 종료합니다.", "Error", MB_OK);
                    break;
                case HS_ERR_INVALID_FILES:
                    MessageBox(NULL, "잘못된 파일이 설치되었습니다.\n프로그램을 재설치하시기 바랍니다.", "Error", MB_OK);
                    break;
                case HS_ERR_DEBUGGER_DETECT:
                    MessageBox(NULL, "컴퓨터에서 디버거 프로그램이 감지되었습니다.", "Error", MB_OK);
                    break;
                case HS_ERR_NEED_ADMIN_RIGHTS:
                    MessageBox(NULL, "Admin 권한으로 실행되어야 합니다.", "Error", MB_OK);
                    break;
                case HS_ERR_COMPATIBILITY_MODE_RUNNING:
                    MessageBox(NULL, "호환성 모드로 프로그램이 실행됩니다.\n프로그램을 종료합니다.", "Error", MB_OK);
                    break;
                default:
                    sprintf(szMsg, "해킹방지 기능에 오류가 발생하였습니다.(Error Code = %x)\n프로그램을 종료합니다.", nRet);
                    MessageBox(NULL, szMsg, "Error", MB_OK);
                    break;
            }
            return FALSE;
        }

        // 주기적 체크 타이머 설정 (10초마다)
        SetTimer(hWnd, 255, 10000, NULL);
#endif
    }
    return TRUE;
}
```

**서비스 시작** (RYLNetWorkData.cpp:1395):
```cpp
BOOL CRYLNetworkData::StartHShield(HWND hWnd)
{
    if (GameRYL::SERVER_BATTLE_LOHAN != m_eServerType &&
        ADMIN_L3 != g_ClientMain.m_wAdminMode)
    {
#ifdef ON_HACKSHIELD
        int nRet = HS_ERR_OK;
        CHAR szMsg[MAX_PATH];

        // HackShield 서비스 시작
        nRet = _AhnHS_StartService();

        // 시작 오류 처리
        if (nRet != HS_ERR_OK)
        {
            switch (nRet)
            {
                case HS_ERR_START_ENGINE_FAILED:
                case HS_ERR_DRV_FILE_CREATE_FAILED:
                case HS_ERR_REG_DRV_FILE_FAILED:
                case HS_ERR_START_DRV_FAILED:
                default:
                    wsprintf(szMsg, "해킹 방지 기능에 오류가 발생 하였습니다.(%x)", nRet);
                    break;
            }
            MessageBox(NULL, szMsg, "Error", MB_OK);
            return FALSE;
        }
#endif
    }
    return TRUE;
}
```

**서비스 종료** (RYLNetWorkData.cpp:1427):
```cpp
BOOL CRYLNetworkData::StopHShield()
{
    if (GameRYL::SERVER_BATTLE_LOHAN != m_eServerType &&
        ADMIN_L3 != g_ClientMain.m_wAdminMode)
    {
#ifdef ON_HACKSHIELD
        int nRet = HS_ERR_OK;

        // HackShield 서비스 정지
        nRet = _AhnHS_StopService();

        if (nRet != HS_ERR_OK)
        {
            return FALSE;
        }
#endif
    }
    return TRUE;
}
```

**업데이트 체크** (RYLNetWorkData.cpp:1230):
```cpp
BOOL CRYLNetworkData::UpdateHShield()
{
#ifdef ON_HACKSHIELD
    DWORD dwRet = 0;
    CHAR szFullFilePath[MAX_PATH];

    sprintf(szFullFilePath, "%s\\HShield", strClientPath);

    AHNHS_EXT_ERRORINFOA HsExtError;
    ZeroMemory(&HsExtError, sizeof(AHNHS_EXT_ERRORINFOA));

    // HackShield 업데이트
    dwRet = _AhnHS_HSUpdateEx(
        szFullFilePath,     // HackShield 폴더 경로
        1000 * 600,         // 업데이트 전체 타임아웃 (600초)
        5750,               // 게임 코드
        AHNHSUPDATE_CHKOPT_HOSTFILE | AHNHSUPDATE_CHKOPT_GAMECODE,
        HsExtError,
        1000 * 20           // 서버 연결 타임아웃 (20초)
    );

    if (dwRet != ERROR_SUCCESS)
    {
        // 업데이트 오류 처리
        switch (dwRet)
        {
            case HSERROR_ENVFILE_NOTREAD:
            case HSERROR_ENVFILE_NOTWRITE:
            case HSERROR_NETWORK_CONNECT_FAIL:
            case HSERROR_HSUPDATE_TIMEOUT:
            case HSERROR_MISMATCH_ENVFILE:
            case HSERROR_HOSTFILE_MODIFICATION:
                sprintf(szBuff, "업데이트에 실패하였습니다\nError ID : %s", szTitle);
                MessageBox(NULL, szBuff, "Error", MB_OK);
                return FALSE;
        }
    }
#endif
    return TRUE;
}
```

---

## 3. 자체 AntiHack 시스템

### 위치
- 헤더: `RYLClient/AntiHack.h`
- 사용: `RYLClient/RYLClientMain.cpp:56-58`

### 주요 기능

#### 디버거 탐지
```cpp
class CAntiHack
{
private:
    BOOL m_bAntiHack[MAX_HACKCOUNT];  // 해킹 탐지 플래그
    BOOL m_bWinNT;                     // Windows NT 계열 여부

public:
    CAntiHack()
    {
        // Windows 버전 확인
        OSVERSIONINFOEX osv;
        osv.dwOSVersionInfoSize = sizeof(osv);
        GetVersionEx((LPOSVERSIONINFO)&osv);
        m_bWinNT = (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);

        // IsDebuggerPresent API 로드 (문자열 암호화됨)
        HMODULE hKernel = LoadLibrary(DecryptText("KDPKAG-+&;BA")); // "KERNEL32.DLL"
        BOOL (WINAPI *pIsDebuggerPresent)(void);
        pIsDebuggerPresent = GetProcAddress(hKernel, DecryptText("IrBb^pa`]iFgYfW_d")); // "IsDebuggerPresent"

        // 디버거 존재 확인
        m_bAntiHack[HACK0] = pIsDebuggerPresent();
        FreeLibrary(hKernel);
    }

    void AntiDebug1(void)
    {
#if USE_ANTIHACK == 1
        if (m_bAntiHack[HACK1]) {
            MessageBox(NULL, "Please turn your Debugger off!", "ERROR", MB_OK);
            ExitProcess(0);
        }

        // SoftICE 탐지 (\\.\SICE 장치)
        m_bAntiHack[HACK1] = (CreateFileA("\\[,YOD=>", ...) != INVALID_HANDLE_VALUE); // "\\.\SICE"

        // NuMega Bounds Checker 탐지 (\\.\NTICE 장치)
        m_bAntiHack[HACK2] = (CreateFileA("\\[,YJOC<=", ...) != INVALID_HANDLE_VALUE); // "\\.\NTICE"
#endif
    }

    void AntiDebug2(DWORD dwAddress)
    {
#if USE_ANTIHACK == 1
        if (m_bAntiHack[HACK2] || m_bAntiHack[HACK1]) {
            WinExit(EWX_SHUTDOWN | EWX_FORCE);  // 시스템 강제 종료!
        }
#endif
        pCall = (BOOL (WINAPI *)(HINSTANCE))(XCHG(dwAddress));
    }

protected:
    // 문자열 암호화/복호화 (위치별 덧셈)
    bool Decrypt(unsigned char *lpData, DWORD dwLength)
    {
        for (int i=0; i < (int)dwLength; i++)
            *(lpData + i) += i;
        return true;
    }

    bool Encrypt(unsigned char *lpData, DWORD dwLength)
    {
        for (int i=0; i < (int)dwLength; i++)
            *(lpData + i) -= i;
        return true;
    }

    // 시스템 종료 권한 획득
    BOOL SetPrivilege(unsigned char *name, BOOL bEnable)
    {
        HANDLE hToken;
        TOKEN_PRIVILEGES tpToken;

        OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
        tpToken.PrivilegeCount = 1;

        if (LookupPrivilegeValue(NULL, (LPCSTR)name, &(tpToken.Privileges[0].Luid)))
        {
            tpToken.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
            AdjustTokenPrivileges(hToken, FALSE, &tpToken, sizeof(tpPrev), &tpPrev, &dwRetLen);
        }

        CloseHandle(hToken);
        return bResult;
    }

    // 시스템 종료
    bool WinExit(DWORD dwFlags)
    {
        if (SetPrivilege((unsigned char *)"SeShutdownPrivilege", TRUE))
        {
            ExitWindowsEx(dwFlags, 0);
            SetPrivilege((unsigned char *)"SeShutdownPrivilege", FALSE);
        }
        return true;
    }
};
```

### 사용 방법

```cpp
// 전역 선언
#define USE_ANTIHACK 0  // 현재 비활성화
#include "..\\AntiHack.h"
DECLARE_ANTIHACK();  // g_AntiHack 전역 변수 선언

// 사용 매크로
USE_ANTIHACK1();              // 디버거 체크
USE_ANTIHACK2(Func);          // 함수 주소 암호화
USE_ANTIHACK3(Inst);          // 함수 실행
```

### 특징

**장점**:
- 가벼운 구현 (헤더 파일만)
- 외부 의존성 없음
- 문자열 난독화로 우회 어려움

**단점**:
- 구식 기법 (SoftICE는 2006년 단종)
- `USE_ANTIHACK = 0`으로 비활성화 상태
- 현대적 디버거에 효과 없음
- 시스템 강제 종료는 과도한 조치

---

## 통합 아키텍처

### 실행 순서

```
1. 프로그램 시작
   └─ CClientMain::InitInstance()
      └─ RYLClientMain.cpp

2. HackShield 초기화
   └─ CRYLNetworkData::InitHShield(hWnd)
      ├─ _AhnHS_Initialize(...)
      │  ├─ 게임 코드: 5750
      │  ├─ 라이센스: "15E4BF63F549784BECC7FC70"
      │  ├─ 옵션: AHNHS_CHKOPT_ALL
      │  └─ 콜백: HS_CallbackProc
      └─ SetTimer(hWnd, 255, 10000, NULL)  // 10초마다 체크

3. HackShield 시작
   └─ CRYLNetworkData::StartHShield(hWnd)
      └─ _AhnHS_StartService()

4. GameGuard 초기화
   └─ CRYLNetworkData 생성자
      └─ m_lpNPGameLib = new CNPGameLib(szGameName)
         └─ PreInitNPGameMon(szGameName)

5. 메인 게임 루프
   ├─ 주기적 체크 (Timer 255, 10초마다)
   │  └─ HackShield 상태 확인
   │
   ├─ 게임 실행 중
   │  ├─ GameGuard 콜백 처리 (NPGameMonCallback)
   │  └─ HackShield 콜백 처리 (HS_CallbackProc)
   │
   └─ 서버 인증
      ├─ GameGuard Auth2 코드 수신
      └─ 서버로 인증 코드 전송

6. 프로그램 종료
   ├─ CRYLNetworkData::StopHShield()
   │  └─ _AhnHS_StopService()
   │
   ├─ CRYLNetworkData::UnInstHShield()
   │  └─ _AhnHS_Uninitialize()
   │
   └─ CRYLNetworkData 소멸자
      └─ delete m_lpNPGameLib
         └─ CloseNPGameMon()
```

### 조건부 활성화

```cpp
// 1. 빌드 설정에 따른 활성화
#ifndef NO_GAMEGUARD
    // GameGuard 코드
#endif

#ifdef ON_HACKSHIELD
    // HackShield 코드
#endif

// 2. 런타임 조건 (배틀로한 서버 또는 ADMIN_L3일 경우 비활성화)
if (GameRYL::SERVER_BATTLE_LOHAN != m_eServerType &&
    ADMIN_L3 != g_ClientMain.m_wAdminMode)
{
    // HackShield 활성화
}
```

### 빌드 설정별 동작

| 빌드 설정 | NO_GAMEGUARD | ON_HACKSHIELD | GameGuard | HackShield |
|-----------|--------------|---------------|-----------|------------|
| Debug | 미정의 | 미정의 | ✅ | ❌ |
| Debug_MY | 미정의 | 미정의 | ✅ | ❌ |
| Release | 미정의 | 미정의 | ✅ | ❌ |
| Release_MY | 정의됨 | 정의됨 | ❌ | ✅ |
| Release_NoGD | 정의됨 | 정의됨 | ❌ | ✅ |

**GlobalScript.vcxproj:146**:
```xml
<PreprocessorDefinitions>
    WIN32;NDEBUG;_LIB;_RYL_GAME_CLIENT_;NO_GAMEGUARD;ON_HACKSHIELD
</PreprocessorDefinitions>
```

---

## 보안 전략 분석

### 다층 방어 (Defense in Depth)

```
레이어 1: 자체 AntiHack (현재 비활성화)
         └─ 기본 디버거 탐지

레이어 2: nProtect GameGuard
         ├─ 스피드핵 탐지
         ├─ 게임핵 탐지
         ├─ 패킷 암호화
         └─ 서버 인증

레이어 3: AhnLab HackShield (더 강력)
         ├─ 시스템 레벨 보호
         ├─ 커널 디버거 탐지
         ├─ 메모리 보호
         ├─ DirectX 보호
         └─ 가상머신 감지
```

### 주기적 검증

```cpp
// Timer 255: 10초마다 HackShield 상태 확인
SetTimer(hWnd, 255, 10000, NULL);

// WM_TIMER 메시지 처리
case WM_TIMER:
    if (wParam == 255)
    {
        // HackShield 상태 체크
        _AhnHS_CheckHackShieldRunningStatus();
    }
    break;
```

### 서버 연동 인증

```cpp
// GameGuard 서버 인증 흐름
1. 클라이언트 → 서버: 로그인 요청
2. 서버 → 클라이언트: GG_AUTH_DATA (인증 코드)
3. 클라이언트: NPGameMonCallback에서 인증 코드 저장
4. 클라이언트 → 서버: 인증 코드 포함 패킷 전송
5. 서버: 인증 코드 검증
```

**인증 데이터 구조**:
```cpp
typedef struct _GG_AUTH_DATA
{
    DWORD dwIndex;   // 인덱스
    DWORD dwValue1;  // 값1
    DWORD dwValue2;  // 값2
    DWORD dwValue3;  // 값3
} GG_AUTH_DATA;
```

### 즉시 대응

모든 안티치트 시스템은 부정 행위 감지 시 **즉각 프로그램 종료**:

```cpp
// GameGuard
case NPGAMEMON_SPEEDHACK:
case NPGAMEMON_GAMEHACK_DETECT:
    MessageBox("부정 행위 감지");
    PostQuitMessage(WM_QUIT);  // 즉시 종료
    return FALSE;

// HackShield
case AHNHS_ACTAPC_DETECT_SPEEDHACK:
case AHNHS_ENGINE_DETECT_GAME_HACK:
    MessageBox("해킹 프로그램 감지");
    // 프로그램 종료 (콜백에서는 메시지만 표시)
    break;
```

### 관리자/개발자 예외

```cpp
// ADMIN_L3 또는 배틀로한 서버에서는 안티치트 비활성화
if (GameRYL::SERVER_BATTLE_LOHAN != m_eServerType &&
    ADMIN_L3 != g_ClientMain.m_wAdminMode)
{
    // 안티치트 활성화
}
else
{
    // 안티치트 비활성화 (개발/테스트용)
}
```

**관리자 레벨**:
```cpp
enum AdminLevelMode
{
    ADMIN_NONE = 0,  // 일반 사용자
    SUPPORTER = 1,   // 서포터
    ADMIN_L1 = 2,    // 관리자 레벨 1
    ADMIN_L2 = 3,    // 관리자 레벨 2
    ADMIN_L3 = 4,    // 관리자 레벨 3 (안티치트 우회)
    ADMIN_DEV = 5,   // 개발자
};
```

---

## 취약점 및 한계

### 1. 구식 기술 스택

**문제점**:
- 2011년경 코드로 최신 해킹 기법에 취약
- SoftICE, NuMega 같은 단종된 도구만 탐지
- 현대적 디버거 (x64dbg, IDA Pro, Ghidra) 미대응

**영향**:
- 메모리 스캔, DLL 인젝션 등 기본 해킹 기법에만 효과
- 최신 안티디버깅 우회 기법에 무력

### 2. 하드코딩된 민감 정보

**HackShield 라이센스 키** (RYLNetWorkData.cpp:1326):
```cpp
"15E4BF63F549784BECC7FC70"  // 소스코드에 평문 노출
```

**게임 코드**:
```cpp
5750  // 고정값, 변경 불가
```

**문제점**:
- 리버스 엔지니어링으로 쉽게 추출 가능
- 크랙된 버전에서 동일 라이센스 사용 가능

### 3. 조건부 비활성화

**빌드 매크로**:
```cpp
#ifndef NO_GAMEGUARD
    // GameGuard 코드
#endif
```

**문제점**:
- 컴파일 타임에 완전히 제거 가능
- `Release_NoGD` 빌드는 GameGuard 없음
- 크래커가 쉽게 비활성화 버전 배포 가능

### 4. 단일 실패점 (Single Point of Failure)

**콜백 함수 우회**:
```cpp
// 콜백 함수만 후킹하면 모든 탐지 무력화
BOOL CALLBACK NPGameMonCallback(DWORD dwMsg, DWORD dwArg)
{
    return TRUE;  // 항상 성공 반환
}

int __stdcall HS_CallbackProc(long lCode, long lParamSize, void* pParam)
{
    return 1;  // 항상 정상 반환
}
```

**문제점**:
- 콜백 함수 주소만 찾으면 완전 우회 가능
- 반환값 조작만으로 모든 보호 무효화

### 5. 과도한 권한

**시스템 강제 종료** (AntiHack.h:120):
```cpp
bool WinExit(DWORD dwFlags)
{
    ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0);  // 시스템 강제 종료!
}
```

**문제점**:
- 오탐지 시 사용자 PC 강제 종료
- 사용자 데이터 손실 위험
- 악성코드로 오인될 수 있음

### 6. 업데이트 메커니즘 취약점

**HackShield 업데이트** (RYLNetWorkData.cpp:1256):
```cpp
dwRet = _AhnHS_HSUpdateEx(
    szFullFilePath,     // 로컬 경로
    1000 * 600,         // 10분 타임아웃
    5750,               // 게임 코드
    AHNHSUPDATE_CHKOPT_HOSTFILE | AHNHSUPDATE_CHKOPT_GAMECODE,
    HsExtError,
    1000 * 20           // 20초 연결 타임아웃
);
```

**문제점**:
- MITM 공격으로 업데이트 가로채기 가능
- hosts 파일 검사만으로는 DNS 스푸핑 방지 불충분
- SSL/TLS 미사용 시 업데이트 파일 변조 가능

### 7. 메모리 보호 한계

**문제점**:
- 유저모드 안티치트는 커널모드 해킹 방지 불가
- 하드웨어 디버거 (JTAG) 탐지 불가
- DMA 공격 (PCILeech) 방어 불가

### 8. 가상머신 감지의 양날의 검

**HackShield VM 감지** (AHNHS_CHKOPT_DETECT_VIRTUAL_MACHINE):

**문제점**:
- 합법적 VM 사용자 차단 (개발자, 테스터)
- 클라우드 게이밍 서비스 불가
- VM 감지 우회 기법 다수 존재

---

## 모범 사례 및 개선 방안

### 현대적 안티치트로 전환

**권장 사항**:
1. **Easy Anti-Cheat** (Epic Games)
2. **BattlEye** (Ubisoft)
3. **Vanguard** (Riot Games) - 커널 레벨
4. **XIGNCODE3** (Wellbia) - 국내 대안

**장점**:
- 최신 해킹 기법 대응
- 정기 업데이트 및 패턴 DB
- 글로벌 표준 준수

### 서버 사이드 검증 강화

**클라이언트 검증의 한계**:
```
클라이언트는 항상 신뢰할 수 없음 (Never trust the client)
```

**개선 방안**:
1. **서버 권위 (Server Authority)**
   - 모든 게임 로직을 서버에서 계산
   - 클라이언트는 입력과 렌더링만 담당

2. **행위 분석 (Behavior Analysis)**
   - 비정상적인 플레이 패턴 탐지
   - 머신러닝 기반 이상 감지

3. **통계적 검증**
   - 불가능한 성과 자동 감지
   - 실시간 통계 분석

### 하드웨어 기반 보안

**TPM (Trusted Platform Module)**:
```cpp
// TPM 기반 무결성 검증
HRESULT VerifyGameIntegrity()
{
    // TPM을 사용한 부팅 체인 검증
    // 하드웨어 레벨 변조 탐지
}
```

**Secure Boot**:
- 커널 모드 드라이버 서명 검증
- 부팅 과정 무결성 보장

### 코드 난독화 및 보호

**현재 상태**:
```cpp
// 단순 문자열 암호화만 존재
char *DecryptText(char *lpData)
{
    for(int i=0; i < strlen(lpData); i++)
        *(lpData + i) += i;
}
```

**개선 방안**:
1. **VMProtect / Themida** - 강력한 코드 난독화
2. **Anti-tampering** - 코드 변조 탐지
3. **Control Flow Obfuscation** - 제어 흐름 난독화
4. **String Encryption** - 문자열 암호화 강화

### 보안 정보 관리

**현재 문제**:
```cpp
// 하드코딩된 라이센스 키
"15E4BF63F549784BECC7FC70"
```

**개선 방안**:
```cpp
// 환경 변수 또는 안전한 저장소 사용
HRESULT GetLicenseKey(LPSTR lpszKey, DWORD dwSize)
{
    // Windows Credential Manager 사용
    // 또는 서버에서 동적 발급
}
```

### 다단계 인증

**현재**: 단순 인증 코드 교환

**개선 방안**:
1. **Challenge-Response**
   ```
   Server → Client: Random Challenge
   Client → Server: Hash(Challenge + Secret)
   Server: Verify
   ```

2. **Time-based Token (TOTP)**
   - 시간 기반 일회용 토큰
   - 리플레이 공격 방지

3. **디바이스 지문 (Device Fingerprinting)**
   - 하드웨어 정보 기반 식별
   - 다중 계정 탐지

### 로깅 및 모니터링

**현재 상태**: 기본 콜백 메시지만 표시

**개선 방안**:
```cpp
// 중앙 집중식 로깅
void LogSecurityEvent(SecurityEventType type, const char* details)
{
    // 로컬 로그 + 서버 전송
    // 실시간 분석 및 알림

    SecurityEvent event = {
        .timestamp = GetCurrentTime(),
        .userId = GetCurrentUserId(),
        .eventType = type,
        .details = details,
        .systemInfo = GetSystemFingerprint()
    };

    SendToSecurityServer(event);
    WriteLocalLog(event);
}
```

**모니터링 대시보드**:
- 실시간 해킹 시도 모니터링
- 지역별/시간대별 통계
- 자동 대응 시스템

---

## 결론

### 현재 시스템 평가

**강점**:
1. ✅ 이중 상용 안티치트 (GameGuard + HackShield)
2. ✅ 다층 방어 구조
3. ✅ 서버 연동 인증
4. ✅ 주기적 검증
5. ✅ 관리자 예외 처리

**약점**:
1. ❌ 2011년경 구식 기술
2. ❌ 하드코딩된 민감 정보
3. ❌ 조건부 비활성화 가능
4. ❌ 콜백 함수 단일 실패점
5. ❌ 최신 해킹 기법 미대응
6. ❌ 클라이언트 중심 보안

### 역사적 의의

이 시스템은 **2011년경 한국 MMORPG의 표준적인 안티치트 구현**입니다:
- 당시로서는 매우 강력한 보호 체계
- nProtect GameGuard는 한국 온라인 게임의 사실상 표준
- AhnLab HackShield 추가로 이중 보호

### 현대적 관점

**2025년 기준**:
- 기술적으로 낙후됨
- 최신 해킹 기법에 취약
- 서버 사이드 검증 강화 필요
- 클라우드 기반 안티치트로 전환 권장

### 학습 가치

**보안 아키텍처 학습**:
1. 다층 방어의 중요성
2. 클라이언트 보안의 한계
3. 서버-클라이언트 협력 보안
4. 상용 솔루션 통합 방법

**레거시 시스템 이해**:
- 과거 온라인 게임 보안 기술
- 안티치트 진화 과정
- 보안 요구사항 변화

---

## 참고 자료

### 파일 위치

**GameGuard**:
- `GlobalScript/GameGuardLib/NPGameLib.h` - 주요 헤더
- `GlobalScript/GameGuardLib/NPGameLib.lib` - 라이브러리
- `GlobalScript/GameGuardLib/ggsrv.h` - 서버 통신
- `RYLClient/RYLClient/RYLNetWorkData.cpp:70-79` - 초기화
- `RYLClient/RYLClient/RYLClientMain.cpp:2839-2927` - 콜백

**HackShield**:
- `GlobalScript/HShield/HShield.h` - 주요 헤더
- `GlobalScript/HShield/HShield.lib` - 라이브러리
- `GlobalScript/HShield/HSUpChk.h` - 업데이트
- `RYLClient/RYLClient/RYLNetWorkData.cpp:1303-1444` - 구현
- `RYLClient/RYLClient/RYLNetWorkData.cpp:1149-1227` - 콜백

**AntiHack**:
- `RYLClient/AntiHack.h` - 전체 구현
- `RYLClient/RYLClient/RYLClientMain.cpp:56-58` - 사용

### 빌드 설정

**GlobalScript.vcxproj:146**:
```xml
<PreprocessorDefinitions>
WIN32;NDEBUG;_LIB;_RYL_GAME_CLIENT_;NO_GAMEGUARD;ON_HACKSHIELD
</PreprocessorDefinitions>
```

### 코드 레퍼런스

| 기능 | 파일:라인 |
|------|-----------|
| GameGuard 초기화 | RYLNetWorkData.cpp:77 |
| GameGuard 콜백 | RYLClientMain.cpp:2839 |
| HackShield 초기화 | RYLNetWorkData.cpp:1303 |
| HackShield 시작 | RYLNetWorkData.cpp:1395 |
| HackShield 종료 | RYLNetWorkData.cpp:1427 |
| HackShield 콜백 | RYLNetWorkData.cpp:1149 |
| HackShield 업데이트 | RYLNetWorkData.cpp:1230 |
| AntiHack 클래스 | AntiHack.h:19-128 |

---

**문서 작성일**: 2025-11-29
**분석 도구**: Claude Code (claude.ai/code)
**프로젝트**: NeoRylClient - ROW (Reign of Revolution)
